/* Self-hosted display face — headings, stat numerals, wordmark. Latin subset only:
   Korean/Japanese glyphs fall through per-glyph to the system CJK fonts in the stack
   (see --font-display), which keeps mixed-script headings from going anemic. */
@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/fonts/barlow-condensed-500.woff2') format('woff2');
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/barlow-condensed-600.woff2') format('woff2');
}

@font-face {
    font-family: 'Barlow Condensed';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/barlow-condensed-700.woff2') format('woff2');
}

:root {
    --font-display: 'Barlow Condensed', 'Malgun Gothic', 'Yu Gothic UI', 'Apple SD Gothic Neo', 'Hiragino Sans', sans-serif;
    /* Body face, matching MudBlazor's default. Declared here because MudBlazor's own copy
       arrives with the circuit, and the shell paints before that. */
    --font-body: Roboto, Helvetica, Arial, sans-serif;
}

/* The shell paints before any circuit, and every --mud-* custom property is emitted by
   MudThemeProvider inside one — including the palette MudBlazor's own body rule reads. So the
   shell owns its base, from --mix-* tokens the server emits (docs/design/static-shell.md D5). */
body {
    background: var(--mix-bg);
    color: var(--mix-ink);
    font-family: var(--font-body);
}

/* Big-number treatment for stats (rating, Pumbility, scores). tabular-nums keeps digit
   columns steady while values tick up live. */
.stat-display {
    font-family: var(--font-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: .02em;
}

/* ===== The circuit-drop overlay =====
   App.razor supplies #components-reconnect-modal, so Blazor stops building its own and just
   toggles state classes on ours. Everything here is --mix-*: a dropped circuit is exactly the
   moment MudThemeProvider's --mud-* vars can't be relied on. Every rule is id-scoped because
   MudBlazor ships its own #components-reconnect-modal rules (background, z-index, and a
   `#components-reconnect-modal button` that outranks a bare class). */

#components-reconnect-modal {
    display: none;
    position: fixed;
    inset: 0;
    align-items: center;
    justify-content: center;
    padding: 16px;
    /* !important answers MudBlazor's own !important background; site.css loads after theirs. */
    background: color-mix(in srgb, var(--mix-bg) 82%, transparent) !important;
    backdrop-filter: blur(2px);
}

/* No state class means no circuit trouble; -hide is the reconnected case. Both stay down. */
#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

#components-reconnect-modal .reconnect-card {
    min-width: 240px;
    padding: 22px 28px;
    border-radius: 10px;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 14%, transparent);
    background: var(--mix-surface);
    color: var(--mix-ink);
    box-shadow: 0 14px 44px -16px color-mix(in srgb, var(--mix-bg) 90%, transparent);
    font-family: var(--font-body);
    text-align: center;
}

/* All three states ship; the class Blazor set decides which one has a box. */
#components-reconnect-modal .reconnect-state { display: none; }

#components-reconnect-modal.components-reconnect-show .reconnect-on-show,
#components-reconnect-modal.components-reconnect-failed .reconnect-on-failed,
#components-reconnect-modal.components-reconnect-rejected .reconnect-on-rejected {
    display: block;
}

#components-reconnect-modal .reconnect-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 600;
    letter-spacing: .01em;
}

#components-reconnect-modal .reconnect-spinner {
    display: block;
    width: 28px;
    height: 28px;
    margin: 0 auto 12px;
    border-radius: 50%;
    border: 3px solid color-mix(in srgb, var(--mix-ink) 18%, transparent);
    border-top-color: var(--mix-primary);
    animation: reconnect-spin .9s linear infinite;
}

@keyframes reconnect-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    #components-reconnect-modal .reconnect-spinner { animation-duration: 3s; }
}

#components-reconnect-modal .reconnect-btn {
    margin-top: 16px;
    padding: 8px 18px;
    border-radius: 6px;
    border: 1px solid var(--mix-primary);
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

#components-reconnect-modal .reconnect-btn:hover {
    background: color-mix(in srgb, var(--mix-primary) 85%, var(--mix-ink));
}

/* ===== Shell: app bar, wordmark, top nav, mega-menus, mix pill =====
   The bar and its menus are server-rendered HTML with no circuit behind them, so every value
   MudAppBar/MudMenu used to supply is pinned here. Heights and z-indexes match the MudTheme
   defaults they replace (docs/design/static-shell.md §9): appbar height is Dense
   (64px - 64px/4 = 48px) and ZIndex.AppBar is 1300, which is what keeps the bar stacked
   correctly against Mud's popovers (1200) and dialogs (1400). */

:root {
    --shell-appbar-h: 48px;
}

.shell-appbar {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1300;
    display: flex;
    align-items: center;
    gap: 4px;
    height: var(--shell-appbar-h);
    box-sizing: border-box;
    padding: 0 12px;
    background: var(--mix-nav);
    color: var(--mix-ink);
    box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12);
}

.shell-main {
    padding-top: var(--shell-appbar-h);
}

.shell-spacer {
    flex: 1 1 auto;
}

/* Breakpoint seam at Mud's Md (960px), replacing MudHidden — which needed JS to measure the
   viewport before it could decide what to render. Each side only ever hides: the elements
   themselves own their display value, because the bottom nav (flex) and the More sheet
   (block) don't share one. */
@media (max-width: 959.98px) {
    .shell-desktop-only {
        display: none !important;
    }
}

@media (min-width: 960px) {
    .shell-mobile-only {
        display: none !important;
    }
}

/* ===== Shell menus (the static stand-in for MudMenu + its popover) ===== */

.shell-menu {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.shell-menu-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 1;
    display: none;
    min-width: 200px;
    max-width: calc(100vw - 16px);
    padding: 4px 0;
    border-radius: 4px;
    background: var(--mix-surface);
    box-shadow: 0 5px 5px -3px rgba(0, 0, 0, .2), 0 8px 10px 1px rgba(0, 0, 0, .14), 0 3px 14px 2px rgba(0, 0, 0, .12);
}

/* Menus at the bar's right edge open inward. nav.js shifts any panel that still overflows. */
.shell-menu-panel-end {
    left: auto;
    right: 0;
}

.shell-menu.open .shell-menu-panel {
    display: block;
}

.shell-menu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 16px;
    cursor: pointer;
    font-size: .875rem;
    color: var(--mix-ink);
    text-decoration: none;
    white-space: nowrap;
    list-style: none;
}

.shell-menu-item:hover {
    background: rgba(255, 255, 255, .08);
    text-decoration: none;
}

.shell-menu-item::-webkit-details-marker {
    display: none;
}

.shell-menu-caption {
    padding: 4px 16px;
    font-size: .8rem;
    color: var(--mix-ink-muted);
}

.shell-menu-divider {
    margin: 4px 0;
    border-top: 1px solid rgba(255, 255, 255, .12);
}

/* Native disclosure carries the mix picker's collections and the More sheet's subgroups —
   no circuit, and keyboard support comes free. */
.shell-disclosure > summary {
    display: flex;
}

.shell-disclosure[open] > summary .mud-icon-root {
    transform: rotate(90deg);
}

.shell-disclosure-body .shell-menu-item {
    padding-left: 40px;
}

.shell-avatar-btn,
.shell-icon-btn {
    display: inline-flex;
    align-items: center;
    padding: 4px;
    background: none;
    border: none;
    border-radius: 50%;
    cursor: pointer;
    color: var(--mix-ink);
}

.shell-avatar-btn:hover,
.shell-icon-btn:hover {
    background: rgba(255, 255, 255, .08);
}

.wordmark {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: .08em;
    color: var(--mix-ink);
    text-shadow: 0 0 12px var(--mix-glow);
    text-decoration: none;
    white-space: nowrap;
}

.top-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: 14px;
}

.top-nav-btn {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 6px 10px;
    border-radius: 6px;
    font-family: var(--font-display);
    font-weight: 500;
    font-size: .95rem;
    letter-spacing: .05em;
    color: var(--mix-ink);
    text-decoration: none;
    white-space: nowrap;
}

.top-nav-btn:hover {
    background: rgba(255, 255, 255, .08);
}

/* Tier Lists is top-level when the bar has room for seven items and folds into Play when
   it doesn't. 1280 is MudBlazor's Lg — the ladder the rest of the app speaks — and it puts
   every tablet-landscape width (1024, 1180, 1194) on the folded side while every real
   laptop keeps the full bar. Both copies ship in the HTML; exactly one is ever shown. */
.nav-wide-only {
    display: none;
}

@media (min-width: 1280px) {
    .top-nav .nav-wide-only {
        display: inline-flex;
    }

    .nav-folded-only {
        display: none;
    }
}

.mix-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: transparent;
    border: 1px solid var(--mix-primary);
    border-radius: 16px;
    padding: 3px 12px;
    cursor: pointer;
    font-family: var(--font-display);
    font-weight: 500;
    font-size: .8rem;
    letter-spacing: .08em;
    color: var(--mix-ink);
    white-space: nowrap;
}

.mix-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--mix-primary);
    box-shadow: 0 0 8px var(--mix-glow);
}

/* App-bar chart search — a quiet pill that matches the mix pill, not a form field.
   The outlined border and dropdown caret are stripped; focus brings the theme primary in. */
.appbar-search .mud-input-control {
    margin: 0;
}

.appbar-search .mud-input.mud-input-outlined {
    background: rgba(255, 255, 255, .07);
    border-radius: 16px;
    font-size: .85rem;
}

.appbar-search .mud-input.mud-input-outlined:focus-within {
    background: rgba(255, 255, 255, .11);
    box-shadow: 0 0 0 1px var(--mix-primary);
}

.appbar-search .mud-input.mud-input-outlined input {
    color: var(--mix-ink);
    padding: 5px 14px;
    height: unset;
}

.appbar-search .mud-input.mud-input-outlined input::placeholder {
    color: var(--mix-ink-muted);
    opacity: 1;
}

.appbar-search .mud-input.mud-input-outlined .mud-input-outlined-border {
    border: none;
}

.appbar-search .mud-input-adornment {
    display: none;
}

/* One pulse when something opens the search programmatically (shell.openSearch) —
   settles into the same ring the focused field already wears. */
@media (prefers-reduced-motion: no-preference) {
    .appbar-search.search-flash .mud-input.mud-input-outlined {
        animation: search-flash .9s ease-out;
    }

    @keyframes search-flash {
        0% { box-shadow: 0 0 0 5px var(--mix-primary), 0 0 26px var(--mix-glow); }
        100% { box-shadow: 0 0 0 1px var(--mix-primary); }
    }
}

/* ===== Atmosphere: per-mix page-ground light, derived from each game's attract screen.
   Ground only — cards and surfaces stay flat so contrast is untouched. Trial feature:
   deleting a theme's block (or all three) fully removes it. ===== */

body.theme-phoenix {
    background:
        radial-gradient(1200px 800px at 85% -10%, rgba(255, 107, 53, .10), transparent 60%),
        radial-gradient(1000px 700px at 10% 110%, rgba(63, 169, 245, .08), transparent 60%),
        var(--mix-bg);
    background-attachment: fixed;
    min-height: 100vh;
}

body.theme-xx {
    background:
        radial-gradient(1100px 700px at 80% -10%, rgba(255, 47, 160, .10), transparent 60%),
        radial-gradient(900px 700px at 5% 105%, rgba(53, 200, 255, .08), transparent 60%),
        var(--mix-bg);
    background-attachment: fixed;
    min-height: 100vh;
}

body.theme-phoenix2 {
    background:
        radial-gradient(1200px 700px at 70% -15%, rgba(79, 227, 63, .10), transparent 55%),
        radial-gradient(1000px 800px at 15% 115%, rgba(43, 193, 216, .07), transparent 60%),
        var(--mix-bg);
    background-attachment: fixed;
    min-height: 100vh;
}

/* ===== Mobile: bottom nav + More sheet ===== */

.bottom-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1300;
    display: flex;
    align-items: stretch;
    background: var(--mix-nav);
    border-top: 1px solid rgba(255, 255, 255, .08);
    padding-bottom: env(safe-area-inset-bottom);
}

.bottom-nav .bn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 0 9px;
    background: none;
    border: none;
    cursor: pointer;
    font-family: var(--font-display);
    font-size: .68rem;
    letter-spacing: .04em;
    color: var(--mix-ink-muted);
    text-decoration: none;
}

.bottom-nav .bn.active {
    color: var(--mix-primary);
}

/* The Communities slot only earns space on squarish viewports (fold phones, landscape). */
.bottom-nav .bn-wide {
    display: none;
}

@media (min-aspect-ratio: 1/1) {
    .bottom-nav .bn-wide {
        display: flex;
    }
}

/* Keep page content clear of the fixed bottom nav (Md breakpoint = 960px). */
@media (max-width: 959.98px) {
    .shell-main {
        padding-bottom: 72px;
    }

    /* Pages with a dock need clearance for both bars (the at-rest worst case). */
    html.has-dock .shell-main {
        padding-bottom: 132px;
    }
}

/* ===== Page dock (docs/design/randomizer-overhaul.md) =====
   Page-registered primary actions above the bottom nav. Scrolling down slides the
   nav away (html.nav-away, set by page-dock.js) and the dock takes the bottom edge;
   both bars only coexist at rest. */

:root {
    --bottom-nav-h: calc(53px + env(safe-area-inset-bottom));
}

.bottom-nav {
    transition: transform .25s ease;
}

html.nav-away .bottom-nav {
    transform: translateY(110%);
}

.page-dock {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--bottom-nav-h);
    z-index: 1299;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    background: var(--mix-nav);
    border-top: 1px solid rgba(255, 255, 255, .08);
    transition: bottom .25s ease, padding-bottom .25s ease;
}

html.nav-away .page-dock,
html.focus-mode .page-dock {
    bottom: 0;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
}

@media (prefers-reduced-motion: reduce) {
    .bottom-nav,
    .page-dock {
        transition: none;
    }
}

/* Focus mode: shell chrome gone. The page owes the user an explicit exit affordance.
   Both bars are server-rendered now, so both are hidden here rather than skipped. */
html.focus-mode .shell-appbar,
html.focus-mode .bottom-nav {
    display: none !important;
}

html.focus-mode .shell-main {
    padding-top: 12px;
}

/* The mobile More sheet, replacing MudDrawer's temporary-bottom variant. It hides by
   translating its own height off-screen, so the height must be fixed — "auto" leaves nothing
   to translate and the sheet renders permanently open. */
.more-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1400;
    height: 75vh;
    overflow-y: auto;
    background: var(--mix-nav);
    transform: translateY(100%);
    transition: transform .225s cubic-bezier(0, 0, .2, 1);
    scrollbar-width: none;
}

.more-sheet::-webkit-scrollbar {
    display: none;
}

.more-sheet.open {
    transform: translateY(0);
}

.more-sheet-body {
    padding: 8px 0 16px;
}

.more-sheet-scrim {
    position: fixed;
    inset: 0;
    z-index: 1399;
    background: rgba(0, 0, 0, .5);
    opacity: 0;
    pointer-events: none;
    transition: opacity .225s cubic-bezier(0, 0, .2, 1);
}

html.sheet-open .more-sheet-scrim {
    opacity: 1;
    pointer-events: auto;
}

/* The search sheet drops from the TOP, unlike More. The phone keyboard takes the bottom half
   of the screen the moment the input focuses, so a bottom-anchored field opens underneath the
   thing typing into it. It is only as tall as it needs to be — this asks one question. */
.search-sheet {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    z-index: 1400;
    background: var(--mix-nav);
    border-bottom: 1px solid rgba(255, 255, 255, .10);
    transform: translateY(-100%);
    transition: transform .225s cubic-bezier(0, 0, .2, 1);
}

.search-sheet.open {
    transform: translateY(0);
}

.search-sheet-body {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px 16px 18px;
}

.search-sheet-label {
    font-family: var(--font-display);
    font-size: .6875rem;
    letter-spacing: .08em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

/* The autocomplete's popover is teleported to the provider at the document root, so it is
   never clipped by this box — the sheet only has to frame the input. */
.search-sheet-input {
    display: flex;
    align-items: center;
}

/* A thumb target, not an app-bar accent: taller than the desktop pill, and never under 16px
   — iOS Safari zooms the whole viewport when a smaller input takes focus. */
.search-sheet-input .mud-input.mud-input-outlined {
    width: 100%;
    border-radius: 10px;
}

.search-sheet-input .mud-input.mud-input-outlined input {
    padding: 11px 14px;
    font-size: 1rem;
}

/* The group head is a section label by default. nav.js promotes it to a tappable row when
   the viewport is too narrow for the grid; until then its chevron stays hidden so it never
   advertises an interaction it doesn't have. */
.more-sheet .more-group-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px 2px;
    font-family: var(--font-display);
    font-size: .6875rem;
    letter-spacing: .08em;
    line-height: 1.4;
    text-transform: uppercase;
    opacity: .65;
}

.more-sheet .more-group-head .mud-icon-root {
    font-size: .95rem;
}

.more-sheet .more-group-chevron,
.more-sheet .more-back {
    display: none;
}

/* ---- Drill-down: narrow, tall viewports ----------------------------------------------
   No horizontal room for tiles, so the groups collapse to a root list of section names and
   open one at a time. nav.js adds .drill-mode (layout is narrow) and .drill-inside (a group
   is open); the markup is identical to the grid's. */
.more-sheet .drill-mode .more-group-head {
    padding: 8px 16px;
    font-family: var(--font-body);
    font-size: .875rem;
    letter-spacing: normal;
    text-transform: none;
    opacity: 1;
    cursor: pointer;
}

.more-sheet .drill-mode .more-group-head:hover,
.more-sheet .drill-mode .more-group-head:focus-visible {
    background: rgba(255, 255, 255, .08);
}

.more-sheet .drill-mode .more-group-head .mud-icon-root {
    font-size: 1.25rem;
}

/* Pushed to the far edge so the row reads as "there is more this way". */
.more-sheet .drill-mode .more-group-chevron {
    display: inline-flex;
    margin-left: auto;
    opacity: .5;
}

.more-sheet .drill-mode .more-group-body {
    display: none;
}

.more-sheet .drill-mode .more-group.drill-open .more-group-body {
    display: block;
}

/* The open group's own head is redundant once the back bar names the section. */
.more-sheet .drill-mode .more-group.drill-open .more-group-head {
    display: none;
}

.more-sheet .drill-mode.drill-inside > .shell-menu-item {
    display: none;
}

.more-sheet .drill-mode .more-back {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 10px 16px;
    background: none;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
    color: var(--mix-primary);
    font-family: var(--font-display);
    font-size: .9375rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    cursor: pointer;
}

/* ---- Icon grid: squarish or wide viewports -------------------------------------------
   The aspect half is the same rule the bottom nav's wide-only slot uses (fold phones,
   landscape). The width floor catches portrait tablets, which are taller than 1:1 but have
   room to spare. Above 960 none of this applies — the desktop top nav has taken over. */
@media (min-aspect-ratio: 1/1), (min-width: 700px) {
    .more-sheet .more-group-body {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
        gap: 6px;
        padding: 4px 10px 2px;
    }

    .more-sheet .more-group-body .shell-menu-item {
        flex-direction: column;
        gap: 6px;
        min-height: 82px;
        padding: 12px 6px 10px;
        border-radius: 10px;
        background: var(--mix-surface);
        text-align: center;
        white-space: normal;
    }

    .more-sheet .more-group-body .shell-menu-item .mud-icon-root {
        font-size: 1.4rem;
    }

    /* Two lines, then ellipsis. Tournament names are owner-authored and can be any length,
       so the tile has to survive one without stretching the row it sits in. */
    .more-sheet .more-group-body .shell-menu-item span {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        font-size: .75rem;
        line-height: 1.25;
    }
}

@media (prefers-reduced-motion: reduce) {
    .more-sheet,
    .more-sheet-scrim {
        transition: none;
    }
}

/* ===== Randomizer draw cards (docs/design/randomizer-overhaul.md) =====
   Rides the tier-chart-card base. Held deliberately wears the mix-primary ring, NOT
   the owner-locked pass-green; vetoed dims + strikes in place (state words print in
   chips/tooltips, so hue never travels alone). */

.draw-card-order {
    position: absolute;
    top: 4px;
    right: 4px;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 6px;
    display: grid;
    place-items: center;
    background: var(--mix-accent);
    color: var(--mix-primary-contrast);
    font-size: .72rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .55);
}

/* Held/vetoed border rules live with the tier-card border language further down —
   the base card declares a `border` shorthand at equal specificity, so source order
   is what lets the state colors win (same rule as the pass/To-Do states). */

.draw-card-vetoed .tier-chart-card-jacket {
    filter: grayscale(.85) brightness(.5);
}

.draw-card-vetoed .draw-card-name {
    text-decoration: line-through;
    color: var(--mud-palette-text-secondary);
}

.draw-card-state-chip {
    position: absolute;
    bottom: 4px;
    right: 4px;
    border-radius: 6px;
    padding: 1px 7px;
    font-size: .62rem;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
}

.draw-card-state-held-chip {
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
}

.draw-card-state-vetoed-chip {
    background: var(--mud-palette-error);
    color: var(--mud-palette-error-text);
}

/* Compact keeps a name line (identity survives unfamiliar jackets, rule 2). */
.draw-card .tier-chart-card-name {
    font-size: .72rem;
    line-height: 1.5;
    display: block;
}

/* ===== Randomizer page (draw-first layout) ===== */

.rand-header {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}


.rand-anon-note {
    color: var(--mix-ink-muted);
    margin-bottom: 4px;
}

.rand-chipbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 2px;
    margin: 4px 0;
}

.rand-countline {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 8px;
}

.rand-count-n {
    font-weight: 800;
    color: var(--mix-primary);
    font-variant-numeric: tabular-nums;
}

.rand-count-label {
    font-size: .78rem;
    color: var(--mix-ink-muted);
}

.rand-actionbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

/* Reference strip below the cards: what this draw was configured with. */
.rand-draw-settings {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 2px;
    margin-top: 18px;
    opacity: .8;
}

.rand-draw-settings-label {
    font-family: var(--font-display);
    font-size: .68rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin-right: 8px;
}

.rand-grid {
    display: grid;
    gap: 8px;
}

.rand-grid-compact {
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
}

.rand-grid-comfortable {
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
}

/* A ghost of the card that will land there: same shape, surface, and radius as a
   tier-chart-card, dashed to read as "empty slot". */
.rand-add-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    border: 2px dashed var(--mud-palette-lines-default);
    border-radius: 8px;
    background: var(--mud-palette-surface);
    color: var(--mix-ink-muted);
    min-height: 104px;
    cursor: pointer;
}

.rand-add-tile:hover {
    border-color: var(--mix-primary);
    color: var(--mix-ink);
}

.rand-add-tile-plus {
    font-size: 1.6rem;
    line-height: 1;
}

.rand-add-tile-label {
    font-family: var(--font-display);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .05em;
}

.rand-add-tile:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
}

.rand-add-anchor {
    display: flex;
}

.rand-add-anchor .rand-add-tile {
    flex: 1;
    width: 100%;
}

.rand-add-pop {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 300px;
    max-width: 90vw;
}

/* New match popover (round 12): the panel content inside whichever trigger's popover. */
.rand-new-match-pop {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 300px;
    max-width: 90vw;
    padding: 14px;
}

/* Header + empty-state anchors hug their button; the dock anchor fills the CTA slot. */
.rand-newmatch-anchor {
    display: inline-flex;
}

.dock-cta-anchor {
    flex: 1;
    display: flex;
}

.rand-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 40px 16px;
    text-align: center;
    color: var(--mix-ink-muted);
}

.rand-table .rand-table-order {
    font-weight: 800;
    color: var(--mix-accent);
    font-variant-numeric: tabular-nums;
    width: 34px;
}

.rand-table .rand-table-name {
    font-weight: 600;
}

.rand-table .rand-table-actions {
    text-align: right;
    white-space: nowrap;
}

.rand-row-vetoed .rand-table-name {
    text-decoration: line-through;
    color: var(--mud-palette-text-secondary);
}

.rand-row-held .rand-table-name {
    color: var(--mix-primary);
}

.rand-drawer {
    display: flex;
    flex-direction: column;
}

.rand-drawer-body {
    flex: 1;
    overflow-y: auto;
    padding: 16px 16px 8px;
}

/* The drawer is viewport-wide (bottom sheet), but its content column isn't — full-bleed
   controls floated the Advanced toggle mid-screen on desktop (round 7). */
.rand-drawer-body > * {
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
}

.rand-drawer-footer > * {
    flex-shrink: 0;
}

.rand-drawer-footer {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
    border-top: 1px solid rgba(255, 255, 255, .08);
}

.rand-footer-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
}

.rand-drawer-count {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-right: auto;
}

.rand-save-name {
    max-width: 200px;
}

/* Dock content shared by randomizer (and future dock pages). */
.page-dock .dock-cta {
    flex: 1;
    height: 44px;
    border-radius: 12px;
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
    font-weight: 800;
    letter-spacing: .04em;
    box-shadow: 0 0 20px var(--mix-glow);
}

.page-dock .dock-side {
    border: 1px solid rgba(255, 255, 255, .08);
    border-radius: 12px;
}

/* Tournament context + draft mode (docs/design/randomizer-overhaul.md C9). */

.rand-context-select {
    max-width: 260px;
}

.rand-create-tournament {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 10px;
    padding: 10px 12px;
    margin: 6px 0;
}

.rand-create-tournament .mud-input-control {
    flex: 1;
    min-width: 200px;
}

.rand-invites {
    display: flex;
    flex-direction: column;
    gap: 6px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    padding: 10px 12px;
    margin: 6px 0;
}

.rand-invite-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.rand-invite-role {
    font-weight: 700;
    font-size: .82rem;
    min-width: 82px;
}

.rand-invite-expiry {
    font-size: .78rem;
    color: var(--mix-ink-muted);
    margin-right: auto;
}

.rand-invite-mint {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    border-top: 1px dashed var(--mud-palette-lines-default);
    padding-top: 8px;
}

.rand-invite-mint .mud-input-control {
    max-width: 150px;
}

/* Match picker (round 9): rides the header, right-aligned — the field carries only
   "which match am I looking at". New match joins it on desktop; the dock CTA covers
   phones. On phone widths it takes its own full line instead of squeezing the title. */
.rand-header-match {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
}

.rand-header-match .rand-match-select {
    min-width: 200px;
    max-width: 300px;
}

@media (max-width: 599.98px) {
    .rand-header-match {
        flex: 1 1 100%;
        margin-left: 0;
    }

    .rand-header-match .rand-match-select {
        max-width: none;
        flex: 1;
    }
}

/* Manage-tournament drawer (round 8): stacked role-layered sections. */
.rand-manage-section {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 26px;
}

.rand-manage-heading {
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--mix-ink-muted);
}

.rand-manage-rename {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.rand-manage-rename .mud-input-control {
    flex: 1;
    min-width: 200px;
}

.rand-manage-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.rand-staff-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.rand-staff-row .rand-invite-role {
    margin-right: auto;
}

/* Draft mode: the staff tablet in player hands — loud mode control, explicit exit. */
.rand-draft-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

/* Two-line preset items: name + summary — legible on touch, no hover needed. */
.rand-preset-item {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
    padding: 2px 0;
}

.rand-preset-name {
    font-weight: 700;
    font-size: .85rem;
}

/* Summaries render only on the open dropdown's list items — the closed select shows
   just the preset name (round 7: the two-line clone skewed the input's layout).
   Scoped to .mud-list-item, not .mud-popover, so it stays hidden even when the whole
   select lives inside another popover, like the New match panel (round 12). */
.rand-preset-summary {
    display: none;
    font-size: .7rem;
    color: var(--mix-ink-muted);
}

.mud-list-item .rand-preset-summary {
    display: block;
}

.rand-preset-select {
    min-width: 220px;
}

.rand-drawer-presets {
    margin-bottom: 14px;
}

.rand-exit-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    padding: 6px 14px;
    background: none;
    cursor: pointer;
    font-size: .82rem;
    font-weight: 700;
    color: var(--mix-ink);
}

.rand-tour-pill {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    padding: 6px 14px;
    font-size: .82rem;
    font-weight: 700;
    background: var(--mix-surface);
}

.rand-draft-armed {
    margin-bottom: 12px;
}

.rand-live {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-display);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .14em;
    color: var(--mud-palette-error);
}

.rand-live-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--mud-palette-error);
    box-shadow: 0 0 8px var(--mud-palette-error);
    animation: rand-live-pulse 1.6s infinite;
}

@keyframes rand-live-pulse {
    50% {
        opacity: .35;
    }
}

@media (prefers-reduced-motion: reduce) {
    .rand-live-dot {
        animation: none;
    }
}

.rand-legend {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .72rem;
    color: var(--mix-ink-muted);
    margin-left: 10px;
}

.rand-legend i {
    width: 10px;
    height: 10px;
    border-radius: 3px;
}

.rand-legend-held {
    background: var(--mix-primary);
}

.rand-legend-vetoed {
    background: var(--mud-palette-error);
}

.page-dock .rand-staff-btn {
    border: 1px solid rgba(255, 255, 255, .08);
    border-radius: 12px;
    color: var(--mud-palette-error);
}

/* ===== Randomizer settings panel ===== */

.rand-settings {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.rand-settings-row {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.rand-settings-label {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .04em;
}

.rand-type-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.rand-count-presets {
    display: flex;
    align-items: center;
    gap: 6px;
}

.rand-count-preset,
.rand-coop-chip,
.rand-seg,
.rand-grade-chip {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 9px;
    background: none;
    cursor: pointer;
    color: var(--mix-ink-muted);
    font-family: var(--font-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.rand-count-preset {
    min-width: 40px;
    padding: 7px 0;
    font-size: .82rem;
}

.rand-count-custom {
    max-width: 76px;
}

.rand-count-preset.on,
.rand-coop-chip.on,
.rand-seg.on,
.rand-grade-chip.on {
    background: var(--mix-primary);
    border-color: var(--mix-primary);
    color: var(--mix-primary-contrast);
}

.rand-coop-chips {
    display: flex;
    gap: 6px;
}

.rand-coop-chip {
    padding: 6px 13px;
    font-size: .8rem;
}

.rand-seg-group {
    display: flex;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 9px;
    overflow: hidden;
}

.rand-seg {
    flex: 1;
    border: none;
    border-radius: 0;
    padding: 8px 0;
    font-size: .78rem;
}

.rand-grade-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

.rand-grade-chip {
    padding: 4px 10px;
    font-size: .72rem;
}

.rand-gated-reason {
    color: var(--mix-ink-muted);
}

.rand-advanced-toggle {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    text-align: left;
    gap: 8px;
    width: 100%;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 10px;
    padding: 10px 12px;
    background: none;
    cursor: pointer;
    color: var(--mix-ink-muted);
    font-size: .8rem;
}

/* Slider heads carry a lone switch/note that belongs on the right; the Co-Op head
   still has its label on the left (round 10 fix — a blanket flex-end dragged it over). */
.rand-type-head > :only-child {
    margin-left: auto;
}

.rand-advanced-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 8px;
}

/* Opt-in advanced sections: a quiet switch row until enabled. */
.rand-adv-section {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    padding: 4px 12px 6px;
}

.rand-adv-section-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.rand-adv-section-content {
    padding: 6px 2px 8px;
}

.rand-section-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.rand-owned-note {
    color: var(--mix-ink-muted);
}

.rand-section-hint {
    color: var(--mix-ink-muted);
    display: block;
}

.rand-weighted-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding-top: 4px;
}

.rand-min-mode {
    max-width: 440px;
}

.folder-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 6px;
}

.rand-plain-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 4px;
}

.rand-coop-bounds {
    display: flex;
    gap: 10px;
}

/* Dynamic weight rows (FolderWeightList). */
.weight-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    align-items: flex-start;
}

.weight-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.weight-row-label {
    min-width: 52px;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: .82rem;
    font-variant-numeric: tabular-nums;
}

.weight-row-weight {
    font-size: .7rem;
    color: var(--mix-ink-muted);
}

.weight-row-field {
    max-width: 90px;
}

/* ===== Armed action selector ===== */

.armed-selector {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.armed-selector-label {
    font-family: var(--font-display);
    font-size: .68rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.armed-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 2px solid var(--mud-palette-lines-default);
    border-radius: 11px;
    padding: 8px 16px;
    background: none;
    cursor: pointer;
    font-family: var(--font-display);
    font-size: .8rem;
    font-weight: 800;
    letter-spacing: .04em;
    color: var(--mix-ink-muted);
}

.armed-btn:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
}

.armed-btn-on {
    background: var(--mix-primary);
    border-color: var(--mix-primary);
    color: var(--mix-primary-contrast);
    box-shadow: 0 0 18px var(--mix-glow);
}

.armed-btn-on-veto {
    background: var(--mud-palette-error);
    border-color: var(--mud-palette-error);
    color: var(--mud-palette-error-text);
}

/* Staff-tablet sizing: readable at arm's length, tappable in a hurry. */
.armed-selector-loud .armed-btn {
    padding: 12px 24px;
    font-size: .95rem;
    border-radius: 13px;
}

/* ===== Level range slider (dual thumb) ===== */

.range-slider {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.range-slider-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

.range-slider-label {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .04em;
}

.range-slider-value {
    margin-left: auto;
    font-family: var(--font-display);
    font-size: .78rem;
    color: var(--mix-primary);
    font-variant-numeric: tabular-nums;
}

.range-slider-track-wrap {
    position: relative;
    height: 28px;
}

.range-slider-track {
    position: absolute;
    top: 12px;
    left: 0;
    right: 0;
    height: 4px;
    border-radius: 2px;
    background: var(--mix-surface-muted);
}

.range-slider-fill {
    position: absolute;
    top: 12px;
    height: 4px;
    border-radius: 2px;
    background: var(--mix-primary);
    box-shadow: 0 0 8px var(--mix-glow);
}

/* Two overlaid native inputs; only the thumbs take pointer events. */
.range-slider-track-wrap input[type=range] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 28px;
    margin: 0;
    -webkit-appearance: none;
    appearance: none;
    background: transparent;
    pointer-events: none;
}

.range-slider-track-wrap input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    pointer-events: auto;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--mix-primary);
    border: 3px solid var(--mix-bg);
    box-shadow: 0 0 0 1.5px var(--mix-primary);
    cursor: pointer;
    margin-top: 4px;
}

.range-slider-track-wrap input[type=range]::-moz-range-thumb {
    pointer-events: auto;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--mix-primary);
    border: 3px solid var(--mix-bg);
    box-shadow: 0 0 0 1.5px var(--mix-primary);
    cursor: pointer;
}

.range-slider-ticks {
    position: relative;
    height: 14px;
    margin: 0 10px;
}

.range-slider-ticks span {
    position: absolute;
    transform: translateX(-50%);
    font-family: var(--font-display);
    font-size: .6rem;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.range-slider-disabled .range-slider-fill {
    background: var(--mix-surface-muted);
    box-shadow: none;
}

.range-slider-disabled .range-slider-value {
    color: var(--mix-ink-muted);
}

.range-slider-disabled input[type=range]::-webkit-slider-thumb {
    background: var(--mix-ink-muted);
    box-shadow: 0 0 0 1.5px var(--mix-ink-muted);
    opacity: .5;
    cursor: default;
}

.range-slider-disabled input[type=range]::-moz-range-thumb {
    background: var(--mix-ink-muted);
    box-shadow: 0 0 0 1.5px var(--mix-ink-muted);
    opacity: .5;
    cursor: default;
}

/* Rarity treatment ramp — glow intensity rises with the band. Hue alone can't order the
   bands monotonically (gold is brighter than sapphire), so treatment does; the percentile
   number always rides alongside, so color is never the only channel. Shadows omit a color
   on purpose: they take currentColor from the band hue. */
.rarity-glow-1 {
    text-shadow: 0 0 6px;
}

.rarity-glow-2 {
    text-shadow: 0 0 4px, 0 0 10px;
}

.rarity-glow-3 {
    text-shadow: 0 0 4px, 0 0 10px, 0 0 18px;
    font-weight: 600;
}

/* Legacy difficulty chips (docs/design/legacy-mixes.md): rendered, not image bubbles.
   Pre-Exceed slots, Half-Doubles, and levelled legacy co-ops announce "different
   scale" by looking deliberately unlike the modern bubble art. Hue rides the
   --slot-* tokens via inline style from ThemeScales.SlotColor. */
.legacy-chip {
    display: inline-flex;
    align-items: center;
    border: 2px solid var(--slot-neutral);
    border-radius: 12px;
    padding: 1px 8px;
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: .06em;
    color: var(--slot-neutral);
    white-space: nowrap;
    line-height: 1.5;
}
/* ===== Tier-list component vocabulary: sections, chart cards + the border language,
   lamp strip, border legend, folder picker. These back Components/* (TierSection,
   TierListChartCard, TierListSkeleton, LampStrip, BorderLegend, FolderPicker), so they
   live here rather than in any page's style block — the components must render
   correctly wherever they're reused. ===== */

.tier-section {
    margin: 12px 0;
}

.tier-section-header {
    display: flex;
    align-items: baseline;
    gap: 8px;
    cursor: pointer;
    border-left: 4px solid var(--tier-section-color, var(--mud-palette-text-secondary));
    padding-left: 8px;
}

.tier-section-name {
    color: var(--tier-section-color, var(--mud-palette-text-secondary));
}

.tier-section-count, .tier-section-stat {
    color: var(--mud-palette-text-secondary);
}

.tier-section-body {
    margin-top: 8px;
}

.tier-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
    gap: 10px;
}

.tier-card-grid-compact {
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
}

.tier-chart-card {
    border: 2px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background: var(--mud-palette-surface);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.tier-chart-card-jacket {
    height: 92px;
    background-size: cover;
    background-position: center;
    position: relative;
}

.tier-chart-card-bubble {
    position: absolute;
    top: 4px;
    left: 4px;
}

.tier-chart-card-body {
    padding: 4px 8px;
    min-width: 0;
    flex-grow: 1;
}

.tier-chart-card-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tier-chart-card-actions {
    display: flex;
    align-items: center;
    padding: 0 4px 4px;
}

.tier-chart-card-compact {
    cursor: pointer;
}

.tier-chart-card-compact-jacket {
    height: 72px;
}

.tier-chart-card-compact-grade {
    position: absolute;
    bottom: 3px;
    right: 3px;
    background: var(--mud-palette-background);
    border-radius: 4px;
    padding: 1px 3px;
}

.tier-chart-card-skeleton {
    border-radius: 8px;
}

.tier-chart-card-lens-dot {
    position: absolute;
    top: 3px;
    right: 3px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .45);
}

.tier-chart-card-tier {
    display: block;
}

.tier-chart-card-meta {
    display: block;
    color: var(--mud-palette-text-secondary);
}

.tier-chart-card-skills {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    padding-bottom: 4px;
}

.tier-chart-card-skill {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 0 5px;
    font-size: .65rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* Category-tinted chips (piucenter variant B): identity hue per skill category via
   the --skillcat-* tokens; the printed name carries the meaning (rule 8). */
.skillcat-speed { --skill-chip: var(--skillcat-speed); }
.skillcat-stamina { --skill-chip: var(--skillcat-stamina); }
.skillcat-twist { --skill-chip: var(--skillcat-twist); }
.skillcat-bracket { --skill-chip: var(--skillcat-bracket); }
.skillcat-tech { --skill-chip: var(--skillcat-tech); }

/* The owner's five badge families (docs/design/nuke-old-skill-categories.md §2): the granular
   piucenter vocabulary's identity colors, feeding the same --skill-chip variable the chip and
   bar rules already read, so a badge chip tints exactly like the rollup chips used to. */
.badgecat-brackets { --skill-chip: var(--badgecat-brackets); }
.badgecat-twists { --skill-chip: var(--badgecat-twists); }
.badgecat-staminaandruns { --skill-chip: var(--badgecat-staminaandruns); }
.badgecat-tech { --skill-chip: var(--badgecat-tech); }
.badgecat-doublestech { --skill-chip: var(--badgecat-doublestech); }

.tier-chart-card-skill[class*="badgecat-"],
.tier-chart-card-skill[class*="skillcat-"] {
    color: color-mix(in srgb, var(--skill-chip) 55%, var(--mix-ink));
    background: color-mix(in srgb, var(--skill-chip) 16%, transparent);
    border-color: color-mix(in srgb, var(--skill-chip) 45%, transparent);
}

.tier-chart-card-skill-more {
    opacity: .75;
}

.tier-table-skills .tier-chart-card-skill {
    margin-right: 3px;
}

/* Folder Stats: personal per-skill pass rates, weakest first (piucenter round 3).
   Rides the same --skill-chip category tint the chips use. */
.tier-folder-skills {
    margin-top: 8px;
}

.tier-folder-skills-title {
    display: block;
    color: var(--mix-ink-muted);
}

/* Bar + % = ability over played charts; the trailing count = completion (played /
   charts carrying the skill). Sorted by their product upstream. */
.tier-folder-skill-row {
    display: grid;
    grid-template-columns: 92px 1fr 38px 44px;
    align-items: center;
    gap: 8px;
    font-size: .75rem;
    padding: 1px 0;
}

.tier-folder-skill-label {
    color: color-mix(in srgb, var(--skill-chip) 60%, var(--mix-ink));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tier-folder-skill-track {
    height: 5px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--skill-chip) 14%, transparent);
    overflow: hidden;
}

.tier-folder-skill-fill {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--skill-chip);
}

.tier-folder-skill-value {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.tier-folder-skill-count {
    text-align: right;
    color: var(--mix-ink-muted);
    font-size: .68rem;
    font-variant-numeric: tabular-nums;
}

.tier-chart-card-scoreline {
    display: block;
}

.lamp-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 8px 0;
}

.lamp-chip {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    padding: 2px 8px;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .75rem;
}

.lamp-chip-meter {
    width: 48px;
    height: 4px;
    background: var(--mud-palette-lines-default);
    border-radius: 2px;
    overflow: hidden;
    display: inline-block;
}

.lamp-chip-fill {
    display: block;
    height: 100%;
    background: var(--mud-palette-primary);
}

.lamp-chip-complete .lamp-chip-fill {
    background: var(--mud-palette-success);
}

.border-legend {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    margin: 8px 0;
}

.border-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.border-legend-swatch {
    width: 20px;
    height: 12px;
    display: inline-block;
    border: 2px solid var(--mud-palette-lines-default);
    border-radius: 3px;
}

/* The card border language (owner-locked): solid success = passed, dashed info = To-Do,
   dashed success = passed in another mix. Declared AFTER the card and swatch bases on
   purpose — those declare `border` shorthands at equal specificity, so source order is
   what guarantees the state classes win everywhere they're worn. */
.tier-chart-card-pass {
    border-color: var(--mud-palette-success);
    border-style: solid;
}

.tier-chart-card-todo {
    border-color: var(--mud-palette-info);
    border-style: dashed;
}

.tier-chart-card-other-mix {
    border-color: var(--mud-palette-success);
    border-style: dashed;
}

/* Randomizer draw states join the same source-order contract: held = mix-primary ring
   (deliberately NOT the pass-green), vetoed = error red — both in every density, on
   top of the dim/strike second channels. */
.draw-card-held {
    border-color: var(--mix-primary);
    border-style: solid;
    box-shadow: 0 0 0 1px var(--mix-primary), 0 0 14px var(--mix-glow);
}

.draw-card-vetoed {
    border-color: var(--mud-palette-error);
    border-style: solid;
}

.folder-picker {
    display: flex;
    align-items: center;
    gap: 2px;
}

.folder-picker-anchor {
    position: relative;
}

.folder-picker-pop {
    padding: 8px;
}

.folder-picker-types {
    margin-bottom: 8px;
}

.folder-picker-levels {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 2px;
    max-height: 260px;
    overflow-y: auto;
}

.folder-picker-level {
    background: none;
    border: none;
    border-radius: 4px;
    padding: 6px 0;
    cursor: pointer;
    font: inherit;
    color: var(--mud-palette-text-primary);
    text-align: center;
}

.folder-picker-level:hover {
    background: rgba(255, 255, 255, .08);
}

.folder-picker-current {
    color: var(--mud-palette-primary);
    font-weight: 600;
}

/* A folder this host has nothing for. Dimmed rather than hidden: the grid is a map of
   the level range, and holes in it are information — they say the change landed
   somewhere else. */
.folder-picker-level-off {
    opacity: .3;
    cursor: default;
}

.folder-picker-level-off:hover {
    background: none;
}

/* ===== Home dashboard (unlisted pre-release, D7): 4-column desktop grid, mobile
   derives a single column from auto-flow order (D3), cells span via size presets
   (D5). The widget frame is owned by WidgetHost so every widget wears identical
   chrome. ===== */

.dash-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 56px 16px;
    text-align: center;
}

.dash-pagebar {
    display: flex;
    gap: 4px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}

.dash-pagetab {
    background: none;
    border: none;
    cursor: pointer;
    padding: 6px 14px;
    border-radius: 8px 8px 0 0;
    font-family: var(--font-display);
    font-weight: 500;
    font-size: .95rem;
    letter-spacing: .05em;
    color: var(--mix-ink-muted);
    border-bottom: 2px solid transparent;
}

.dash-pagetab.active {
    color: var(--mix-ink);
    border-bottom-color: var(--mix-primary);
    text-shadow: 0 0 10px var(--mix-glow);
}

.dash-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 168px;
    grid-auto-flow: row;
    gap: 14px;
}

.dash-cell {
    min-width: 0;
}

.dash-cols-2 { grid-column: span 2; }
.dash-cols-3 { grid-column: span 3; }
.dash-cols-4 { grid-column: span 4; }
.dash-rows-2 { grid-row: span 2; }

.dash-widget {
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .06);
    border-radius: 10px;
    padding: 12px 14px;
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.dash-widget-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    flex: none;
}

.dash-widget-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: .82rem;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.dash-widget-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.dash-widget-message {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--mix-ink-muted);
}

/* Import Scores widget (§4): a credential form has to live in a 1x1 body, so the fields and
   button pack into a tight flex column that scrolls rather than clipping the action off. */
.import-widget-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.import-widget-body .mud-input-control {
    margin-top: 0;
}

/* Saved-credential state: alert + full-width action, packed to the middle. */
.import-saved {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* Spinner / done state: everything centered on both axes. */
.import-progress {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
}

/* Typed one-time credentials: username/password stacked, a tall import button beside them. */
.import-typed {
    display: flex;
    gap: 6px;
    align-items: stretch;
}

.import-typed-fields {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.import-typed-go {
    min-width: 48px;
    height: auto;
}

/* Nav-bar import indicator: a pulsing dot on the avatar while a background import runs. */
.nav-avatar-wrap {
    position: relative;
    display: inline-flex;
}

.nav-import-pulse {
    position: absolute;
    top: -1px;
    right: -1px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--mix-primary);
    border: 1px solid var(--mix-surface);
    animation: nav-import-pulse 1.4s ease-out infinite;
}

@keyframes nav-import-pulse {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mix-primary) 65%, transparent); }
    70% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--mix-primary) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mix-primary) 0%, transparent); }
}

/* Quick Record widget (§4.2): the arcade recorder, purpose-built to fit a 1x1 body. */
.qr-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.qr-hint {
    font-size: .68rem;
    color: var(--mix-ink-muted);
}

/* The selected chart — a display header, not a chip: nothing here navigates. */
.qr-selected {
    display: flex;
    align-items: center;
    gap: 7px;
}

.qr-mini-art {
    flex: none;
    display: inline-flex;
}

.qr-mini-art img {
    width: 22px;
    height: 22px;
    border-radius: 4px;
}

.qr-selected-name {
    flex: 1;
    min-width: 0;
    font-family: var(--font-display);
    letter-spacing: .03em;
    font-size: .9rem;
    color: var(--mix-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.qr-scorerow {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Score and the plate/result dropdown share the row (owner, 2026-07-13): score cut to
   ~half, plate lifted up beside it as shorthand. On the legacy row the score dominates and
   the letter-grade box stays compact (owner, field test). */
.qr-score-field {
    flex: 1 1 0;
    min-width: 96px;
}

/* Plate lives on the Save row (owner, 2026-07-13): compact on the left, Save pushed right. */
.qr-plate-field {
    flex: 0 1 auto;
    min-width: 104px;
    max-width: 168px;
}

/* The derived grade doubles as the broken toggle — click to flip pass/broken while keeping
   the plate (plated broken). Deliberately subtle: pointer + a hover tint, no label. */
.qr-grade-toggle {
    flex: none;
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    border-radius: 6px;
    padding: 2px;
}

.qr-grade-toggle:hover {
    background: rgba(255, 255, 255, .07);
}

.qr-actionrow {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Second row: plate on the left, Save pushed to the right (margin-left auto) so it never
   clips on narrow widths (the mobile bug). Pinned to the bottom of the body. */
.qr-actionrow-save {
    margin-top: auto;
}

.qr-actionrow-save .qr-save-btn {
    margin-left: auto;
}

/* MudBlazor fields carry generous default margins — reclaim them for the tight footprint. */
.qr-body .mud-input-control {
    margin-top: 0;
}

.qr-saved {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    gap: 12px;
}

.qr-saved-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.qr-saved-title {
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: .13em;
    font-size: .74rem;
    color: var(--mud-palette-success);
}

.qr-saved-song {
    font-family: var(--font-display);
    font-size: 1rem;
    color: var(--mix-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.qr-saved-detail {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .78rem;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.qr-saved-grade {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--mix-ink);
}

/* All-mixes mode: the runtime picker + the mix chip on the recording header. The chip is
   neutral (not the theme accent) so it doesn't imply the active theme is the record mix. */
.qr-mix-field {
    flex: none;
}

/* Legacy grade strip (owner, 2026-07-13): tap a grade image to pick it (passing), tap the
   selected one again to mark broken (its art goes cracked). Replaces the select + checkbox. */
/* The grade strip is the primary/lead row in legacy (score dropped below it); 4 primaries +
   a "more" menu, spread with a little air. */
.qr-graderow {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.qr-graderow-disabled {
    pointer-events: none;
    opacity: .5;
}

/* "More" overflow (B and lower) — either a … affordance or the selected lower grade. */
.qr-grade-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 26px;
    min-width: 26px;
    cursor: pointer;
    border-radius: 5px;
    color: var(--mix-ink-muted);
    font-size: 1.15rem;
    line-height: 1;
    opacity: .75;
}

.qr-grade-more:hover {
    opacity: 1;
    background: rgba(255, 255, 255, .06);
}

.qr-grade-menu-img {
    height: 24px;
    width: auto;
}

.qr-grade-opt {
    height: 30px;
    width: auto;
    cursor: pointer;
    border-radius: 5px;
    padding: 2px 3px;
    opacity: .5;
    transition: opacity .12s, transform .12s, background .12s;
}

.qr-grade-opt:hover {
    opacity: .85;
    background: rgba(255, 255, 255, .06);
}

.qr-grade-opt-sel {
    opacity: 1;
    background: color-mix(in srgb, var(--mix-primary) 22%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mix-primary) 55%, transparent);
    transform: scale(1.08);
}

.qr-mixchip {
    font-family: var(--font-display);
    font-size: .6rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--mix-ink-muted);
    background: var(--mix-surface-muted);
    border: 1px solid rgba(255, 255, 255, .08);
    padding: 1px 6px;
    border-radius: 5px;
    flex: none;
    max-width: 88px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Column stagger (round 3): 4 on desktop, 3 on small desktop/tablet, 2 on landscape
   phones, 1 on portrait phones. Spans clamp to the column count. */
@media (max-width: 1279.98px) {
    .dash-grid { grid-template-columns: repeat(3, 1fr); }

    .dash-cols-4, .dash-cols-3 { grid-column: span 3; }
}

@media (max-width: 959.98px) {
    .dash-grid { grid-template-columns: repeat(2, 1fr); }

    .dash-cols-4, .dash-cols-3, .dash-cols-2 { grid-column: span 2; }
}

@media (max-width: 599.98px) {
    .dash-grid {
        grid-template-columns: 1fr;
        grid-auto-rows: minmax(168px, auto);
    }

    .dash-cols-2, .dash-cols-3, .dash-cols-4 { grid-column: span 1; }

    .dash-rows-2, .dash-rows-3 { grid-row: span 1; }
}

/* Edit mode: toolbar, edit chrome, add-drawer. */

.dash-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}

.dash-toolbar .dash-pagebar {
    margin-bottom: 0;
}

.dash-pagetab-new {
    color: var(--mix-primary);
}

.dash-widget-editing {
    border-style: dashed;
    border-color: color-mix(in srgb, var(--mix-primary) 45%, transparent);
}

.dash-edit-controls {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    flex: none;
}

/* Header refresh action (shuffle etc.): first auto margin wins the free space, so it
   sits far right in browse mode and immediately left of the edit controls in edit. */
.dash-head-action {
    margin-left: auto;
    flex: none;
}

/* Widget-pushed title-bar content (§2.3 header slot) — e.g. Quick Record's selected chart.
   Sits at the right of the title; the mini-art/bubble/✕ line up compactly. */
.dash-head-slot {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    overflow: hidden;
}

.dash-head-slot .qr-mini-art img {
    width: 28px;
    height: 28px;
    border-radius: 4px;
}

/* Header-slot status glyph (e.g. Hot Streak's fallback note) — icon + tooltip only. */
.dash-head-flag {
    display: inline-flex;
    align-items: center;
    cursor: help;
}

.dash-drawer-body {
    padding: 16px;
}

.dash-drawer-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px;
    border-radius: 8px;
    cursor: pointer;
}

.dash-drawer-item:hover {
    background: rgba(255, 255, 255, .06);
}

.dash-drawer-item.disabled {
    opacity: .45;
    pointer-events: none;
}

.dash-chart-fill {
    flex: 1;
    min-height: 0;
}

/* Pumbility widget: stat block + scrollable target list with dismiss. */

.dash-pumbility {
    display: flex;
    gap: 16px;
    flex: 1;
    min-height: 0;
}

.dash-pumbility-left {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: none;
    max-width: 46%;
}

.dash-stat-num {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 2.2rem;
    line-height: 1;
    color: var(--rarity-gold);
    font-variant-numeric: tabular-nums;
}

.dash-stat-delta {
    color: var(--mud-palette-success);
    font-size: .8rem;
    font-weight: 600;
}

.dash-sparkline {
    width: 100%;
    height: 26px;
}

.dash-muted {
    color: var(--mix-ink-muted);
}

.dash-pumbility-targets {
    flex: 1;
    min-width: 0;
    min-height: 0; /* flex-column children refuse to shrink without this — the tall variant could never scroll */
    display: flex;
    flex-direction: column;
    border-left: 1px solid rgba(255, 255, 255, .06);
    padding-left: 14px;
}

.dash-targets {
    flex: 1;
    min-height: 0;
}

.dash-target-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 0;
    font-size: .8rem;
}

.dash-target-name {
    min-width: 0;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--font-display);
    letter-spacing: .04em;
    color: var(--mix-ink-muted);
}

/* Suggested Charts only: a full-width single column shows the name to fill the gap the
   right-aligned score would leave, but a cramped narrow cell hands that width back to
   the score. Scoped to .dash-suggested's container so the always-named Weekly and Daily
   Step rows (which share this class but sit in no such container) keep their names. */
@container dash-suggested (max-width: 209.98px) {
    .dash-target-name { display: none; }
}

.dash-skillchip {
    font-size: .68rem;
    white-space: nowrap;
    flex: none;
}

.dash-target-gain {
    font-family: var(--font-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-success);
    flex: none;
}

/* Weekly widget: board rows + rotation countdown. */

.dash-weekly {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.dash-weekly-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
    flex: none;
}

.dash-countdown {
    font-family: var(--font-display);
    font-size: .7rem;
    letter-spacing: .08em;
    color: var(--mix-accent);
    border: 1px solid color-mix(in srgb, var(--mix-accent) 40%, transparent);
    border-radius: 10px;
    padding: 1px 8px;
    white-space: nowrap;
}

.dash-weekly-expiry {
    font-family: var(--font-display);
    font-size: .68rem;
    letter-spacing: .05em;
    color: var(--mix-ink-muted);
    flex: none;
}

.dash-weekly-place {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: .75rem;
    flex: none;
    font-variant-numeric: tabular-nums;
}

/* Community Highlights feed (docs/design/home-page-widgets.md §7). */
.dash-ch-feed {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    height: 100%;
    /* So win rows can respond to the widget's own width, not just the viewport. */
    container-type: inline-size;
}

.dash-ch-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .25rem;
    text-align: center;
    padding: 1rem;
}

.dash-ch-entry {
    display: flex;
    gap: .6rem;
    padding: .55rem .25rem;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink-muted) 15%, transparent);
}

.dash-ch-avatar {
    flex: none;
    width: 2rem;
    height: 2rem;
}

.dash-ch-body {
    min-width: 0;
    flex: 1;
}

.dash-ch-head {
    display: flex;
    align-items: baseline;
    gap: .5rem;
}

.dash-ch-name {
    font-weight: 600;
    font-size: .85rem;
}

.dash-ch-time {
    margin-left: auto;
    font-size: .7rem;
    white-space: nowrap;
}

.dash-ch-wins {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    margin-top: .15rem;
}

.dash-ch-win {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    font-size: .78rem;
}

.dash-ch-chart {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    min-width: 0;
}

.dash-ch-song {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 12rem;
}

.dash-ch-why {
    color: var(--mix-ink-muted);
    white-space: nowrap;
}

/* Scored win = one line on wide: chart (the song name truncates) + highlight, then a right-aligned
   grade/plate + score. The narrow queries below reflow it into a chart+score line and a subtitle. */
.dash-ch-win-scored {
    flex-wrap: nowrap;
    align-items: center;
    gap: .35rem;
}

.dash-ch-win-scored .dash-ch-chart {
    min-width: 0; /* the song name ellipsises rather than shove the score off the line */
}

.dash-ch-score-right {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    padding-left: .4rem;
}

.dash-ch-score {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    padding-left: .25rem;
}

/* Narrow — a 1-wide widget (container query on the feed) or mobile, where the dashboard is one
   column (media query): hide the song name and drop the highlight onto its own subtitle line. */
@container (max-width: 300px) {
    .dash-ch-song { display: none; }
    .dash-ch-win-scored { flex-wrap: wrap; }
    .dash-ch-win-scored .dash-ch-score-right { order: 2; }
    .dash-ch-win-scored .dash-ch-why { order: 3; flex-basis: 100%; font-size: .72rem; }
}

@media (max-width: 600px) {
    .dash-ch-song { display: none; }
    .dash-ch-win-scored { flex-wrap: wrap; }
    .dash-ch-win-scored .dash-ch-score-right { order: 2; }
    .dash-ch-win-scored .dash-ch-why { order: 3; flex-basis: 100%; font-size: .72rem; }
}

/* Card-strip person divider (avatar + vertical name) — the community analog of the
   Suggested-Charts category divider, reusing that strip's card CSS + arrow pager. */
.dash-strip-person {
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 2px 3px;
    min-width: 0;
}

.dash-strip-pname {
    writing-mode: vertical-rl;
    font-family: var(--font-display);
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .02em;
    max-height: 62px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: var(--mix-ink);
}

.dash-strip-person.you .dash-strip-pname {
    color: var(--mix-primary);
}

/* A title or full-folder clear has no chart art — it reads as a centered text card. */
.dash-card-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    gap: 3px;
}

.dash-card-emoji {
    font-size: 1.35rem;
    line-height: 1;
}

/* The cards/dividers are wrapped in MudTooltip, so its root is the strip's flex child —
   keep it a fixed-size item so the cards don't grow or shrink. */
.dash-card-strip > .mud-tooltip-root {
    flex: none;
    min-width: 0;
    display: inline-flex;
}

/* Drag chrome: handle (desktop pointer only), dragged-cell dim, insertion marker. */

.dash-drag-handle {
    cursor: grab;
    color: var(--mix-ink-muted);
    font-size: .9rem;
    user-select: none;
    touch-action: none;
    flex: none;
}

.dash-dragging {
    opacity: .35;
}

.dash-drop-target {
    outline: 2px dashed var(--mix-primary);
    outline-offset: 2px;
    border-radius: 10px;
}

.dash-json textarea {
    font-family: Consolas, monospace;
    font-size: .78rem;
}

@media (max-width: 959.98px) {
    .dash-drag-handle {
        display: none;
    }
}

/* Field-test round 1: 3-row spans, swap indicator, mini art, clickable rows,
   tall pumbility. */

.dash-rows-3 { grid-row: span 3; }

.dash-swap-target {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
    border-radius: 10px;
}

.dash-mini-art {
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: 5px;
    overflow: hidden;
    display: inline-flex;
}

.dash-mini-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Suggested Charts widget: goal sections inside one scroll + a right-hand score column. */

.dash-suggested {
    height: 100%;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Its own inline size decides whether target rows show the song name. */
    container: dash-suggested / inline-size;
}

.dash-target-caption {
    padding-top: 6px;
    text-transform: uppercase;
    letter-spacing: .08em;
    font-family: var(--font-display);
}

.dash-target-score {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-variant-numeric: tabular-nums;
    font-size: .75rem;
    /* Suggested rows drop the name at 1x2 — the score column right-aligns itself. */
    margin-left: auto;
}

.dash-target-detail {
    font-size: .7rem;
}

/* Card strips (suggested-charts field test): wide widgets read as compact chart cards
   scrolling horizontally, not tabled text. Hover-revealed pager arrows (clicks handled
   by dashboard-grid.js delegation); honest x-axis fades mirror the vertical ones. */

.dash-strips {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.dash-strip-wrap {
    position: relative;
    flex: none;
    min-width: 0;
}

.dash-card-strip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    /* Bottom padding keeps the score line off the widget edge (owner, round 6). */
    padding: 2px 2px 8px;
    mask-image: linear-gradient(to right,
        transparent 0,
        #000 var(--dash-fade-left),
        #000 calc(100% - var(--dash-fade-right)),
        transparent 100%);
}

.dash-card-strip::-webkit-scrollbar {
    display: none;
}

@property --dash-fade-left {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

@property --dash-fade-right {
    syntax: "<length>";
    inherits: false;
    initial-value: 20px;
}

@supports (animation-timeline: scroll()) {
    .dash-card-strip {
        animation: dash-strip-fades linear both;
        animation-timeline: scroll(self x);
    }

    @keyframes dash-strip-fades {
        0% {
            --dash-fade-left: 0px;
            --dash-fade-right: 20px;
        }

        10% {
            --dash-fade-left: 20px;
            --dash-fade-right: 20px;
        }

        90% {
            --dash-fade-left: 20px;
            --dash-fade-right: 20px;
        }

        100% {
            --dash-fade-left: 20px;
            --dash-fade-right: 0px;
        }
    }
}

.dash-strip-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 26px;
    height: 26px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .14);
    background: color-mix(in srgb, var(--mix-surface-muted) 88%, transparent);
    color: var(--mix-ink);
    cursor: pointer;
    display: grid;
    place-items: center;
    font-size: 15px;
    line-height: 1;
    opacity: 0;
    transition: opacity .15s;
}

.dash-widget:hover .dash-strip-arrow,
.dash-strip-arrow:focus-visible {
    opacity: .85;
}

.dash-strip-arrow-left {
    left: 2px;
}

.dash-strip-arrow-right {
    right: 2px;
}

/* Touch scrolls the strip directly — pager arrows are a pointer affordance. */
@media (hover: none) {
    .dash-strip-arrow {
        display: none;
    }
}

.dash-chart-card {
    /* Sized so art + name + score clear a 2x1 cell on desktop (owner, round 6). */
    flex: none;
    width: 76px;
    min-width: 0;
}

@media (max-width: 599.98px) {
    /* Mobile cells auto-grow — the roomier card reads better there. */
    .dash-chart-card {
        width: 86px;
    }
}

.dash-card-art {
    position: relative;
    width: 100%;
    aspect-ratio: 1;
    border-radius: 8px;
    overflow: hidden;
    background: var(--mix-surface-muted);
}

@media (min-width: 600px) {
    /* Desktop strip cells are fixed-height (168px rows): landscape-crop the art so
       name + score + detail all clear the cell (owner, round 7). Mobile cells
       auto-grow, so the square art stays there. */
    .dash-card-art {
        aspect-ratio: auto;
        height: 52px;
    }
}

/* Direct child only — the DifficultyBubble overlay nests its own img inside this box,
   and a blanket rule blew it up to full card size (owner, round 4). */
.dash-card-art > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.dash-card-bubble {
    position: absolute;
    left: 3px;
    bottom: 3px;
}

.dash-card-veto {
    position: absolute;
    top: 2px;
    right: 2px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mix-surface) 78%, transparent);
}

.dash-card-name {
    margin-top: 3px;
    font-family: var(--font-display);
    font-size: .72rem;
    line-height: 1.25;
    letter-spacing: .03em;
    color: var(--mix-ink-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-card-score {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .72rem;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

.dash-card-detail {
    font-size: .65rem;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Category context inside a merged strip: a slim vertical label opens each group
   (owner, round 7 — "which flavor of Score Push is this?"). */
.dash-strip-divider {
    flex: none;
    writing-mode: vertical-rl;
    font-family: var(--font-display);
    font-size: .62rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 2px 1px;
    border-left: 1px solid rgba(255, 255, 255, .10);
}

.dash-clickable {
    cursor: pointer;
}

.dash-clickable:hover {
    background: rgba(255, 255, 255, .05);
    border-radius: 6px;
}

.dash-pumbility-tall {
    flex-direction: column;
    gap: 8px;
}

.dash-pumbility-tall .dash-pumbility-left {
    max-width: none;
    flex: none;
}

.dash-pumbility-tall .dash-pumbility-targets {
    border-left: none;
    padding-left: 0;
    border-top: 1px solid rgba(255, 255, 255, .06);
    padding-top: 8px;
}

/* Round 2: target rows get air (the tall/mobile variant was crushing lines). */

.dash-target-row {
    min-height: 34px;
    padding: 3px 0;
}

.dash-pumbility-tall .dash-target-row {
    padding: 5px 0;
}

.dash-mini-art {
    width: 26px;
    height: 26px;
}

@media (max-width: 599.98px) {
    /* Mobile cells auto-grow — let the page scroll instead of clipping rows. */
    .dash-targets {
        overflow-y: visible;
        mask-image: none;
        animation: none;
    }
}

.dash-endzone {
    box-shadow: inset 0 -3px 0 0 var(--mix-primary);
    border-radius: 10px;
}

.dash-pools {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    font-variant-numeric: tabular-nums;
}

/* Account Stats widget: glowy Pumbility + competitive level, then the closest matches. */
.dash-acct {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
    min-height: 0;
}

.dash-acct-stats {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: none;
}

.dash-acct-eyebrow {
    font-size: .6rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    font-weight: 700;
    color: var(--mud-palette-text-disabled);
}

.dash-acct-cl-eyebrow {
    margin-top: 6px;
}

.dash-acct-hero {
    display: flex;
    align-items: center;
    gap: 16px;
}

.dash-acct-total {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    flex: none;
}

/* S/D Pumbility pools stacked to the right of the big total (owner, field-test). */
.dash-acct-pools {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    font-size: .82rem;
    font-variant-numeric: tabular-nums;
}

.dash-acct-poolrow {
    display: flex;
    gap: 6px;
    align-items: baseline;
    white-space: nowrap;
}

.dash-acct-poolrow > span:first-child {
    font-weight: 600;
}

.dash-acct-poolnum {
    font-weight: 700;
}

.dash-acct-active {
    box-shadow: 0 2px 0 var(--mix-primary);
}

.dash-acct-matches {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    border-top: 1px solid rgba(255, 255, 255, .06);
    padding-top: 8px;
}

.dash-acct-mhead {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 6px;
}

.dash-acct-mlabel {
    font-size: .6rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    font-weight: 700;
    color: var(--mud-palette-text-disabled);
}

.dash-acct-you {
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

.dash-acct-you b {
    color: var(--daily-you);
    font-weight: 700;
}

.dash-acct-mlist {
    display: flex;
    flex-direction: column;
    gap: 5px;
    overflow-y: auto;
    min-height: 0;
}

.dash-acct-who {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
}

.dash-acct-av {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    object-fit: cover;
    flex: none;
}

.dash-acct-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.dash-acct-trail {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    white-space: nowrap;
}

.dash-acct-lvl {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.dash-acct-empty {
    font-size: .72rem;
    font-style: italic;
    color: var(--mud-palette-text-disabled);
    padding: 8px 4px;
    text-align: center;
}

.dash-acct-mixpill {
    font-size: .58rem;
    font-weight: 800;
    letter-spacing: .03em;
    padding: 1px 7px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mix-primary) 16%, transparent);
    color: var(--mix-primary);
    border: 1px solid color-mix(in srgb, var(--mix-primary) 40%, transparent);
}

/* Daily Step widget (docs/design/daily-step.md): the shared daily chart as a leaderboard card. */

/* Row-highlight tokens, global so the leaderboard dialog can glow too: you (blue), community (green). */
:root {
    --daily-you: #4bb8ff;
    --daily-community: #43dc86;
}

.dash-daily {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 0;
}

.dash-daily-limbo {
    align-self: flex-start;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: .78rem;
    padding: 3px 8px;
    border-radius: 6px;
    border: 1px solid var(--mix-primary);
    color: var(--mix-primary);
}

.dash-daily-chart {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding-bottom: 2px;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.dash-daily-board {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-height: 0;
}

/* The taller sizes scroll the whole board; dash-scroll supplies the quiet themed scrollbar. */
.dash-daily-board.dash-scroll {
    overflow-y: auto;
    flex: 1 1 auto;
}

.dash-lb-row {
    display: grid;
    grid-template-columns: 28px 1fr auto;
    align-items: center;
    gap: 8px;
    padding: 5px 7px;
    border-radius: 7px;
    background: color-mix(in srgb, var(--mix-surface-muted) 55%, transparent);
    font-size: .82rem;
}

.dash-lb-place {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.dash-lb-who {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-lb-score {
    display: flex;
    align-items: center;
    gap: 6px;
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
}

.dash-lb-pts {
    font-weight: 600;
}

.dash-lb-you {
    background: color-mix(in srgb, var(--daily-you) 15%, transparent);
    box-shadow: inset 0 0 0 1px var(--daily-you), 0 0 12px -4px var(--daily-you);
}

.dash-lb-community {
    background: color-mix(in srgb, var(--daily-community) 13%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--daily-community) 60%, transparent);
}

.dash-lb-divider {
    font-size: .62rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--mix-ink) 55%, transparent);
    padding: 4px 2px 1px;
}

/* Your row always sits below the scrolling board — the board takes the flex space and scrolls
   internally, so this stays anchored at the widget's bottom. */
.dash-lb-pinned {
    flex: none;
    padding-top: 4px;
    margin-top: 2px;
    border-top: 1px solid rgba(255, 255, 255, .1);
}

.dash-daily-controls {
    display: flex;
    justify-content: flex-end;
    gap: 2px;
}

/* 1x1 split: a short top-three (name + grade, score on hover) on the left, your standing on the right. */
.dash-daily-split {
    flex: 1;
    display: flex;
    gap: 8px;
    min-height: 0;
    align-items: stretch;
}

.dash-daily-top3 {
    flex: 1.15;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 3px;
}

.dash-top3-row {
    display: grid;
    grid-template-columns: 16px 1fr auto;
    align-items: center;
    gap: 6px;
    padding: 4px 6px;
    border-radius: 6px;
    background: color-mix(in srgb, var(--mix-surface-muted) 50%, transparent);
    font-size: .78rem;
}

.dash-top3-place {
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.dash-top3-name {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 600;
}

.dash-top3-grade {
    font-weight: 800;
    font-size: .72rem;
}

/* A place with no entrant yet — the rank still shows, the rest dashes out. */
.dash-top3-empty {
    opacity: .45;
}

.dash-daily-mine {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px;
    border-radius: 9px;
    text-align: center;
}

.dash-daily-mine-empty {
    background: color-mix(in srgb, var(--mix-surface-muted) 45%, transparent);
}

.dash-mine-label {
    font-size: .6rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    font-weight: 800;
    opacity: .85;
}

.dash-mine-rank {
    font-size: 1.6rem;
    font-weight: 800;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
}

.dash-mine-line {
    font-size: .74rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.weekly-lb-verified {
    font-size: 0.9rem;
    opacity: 0.75;
}

.weekly-lb-photo {
    /* An icon-button squeezed to text scale so the proof link sits inline with the name. */
    padding: 0 2px;
}

.weekly-lb-photo .mud-icon-root {
    font-size: 0.95rem;
}

.weekly-lb-legend {
    color: color-mix(in srgb, var(--mix-ink) 55%, transparent);
}

/* Weekly leaderboard dialog (round 3, option 1). */

.weekly-lb-title {
    display: flex;
    align-items: center;
    gap: 10px;
}

.weekly-lb-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 6px;
    border-radius: 6px;
}

.weekly-lb-row + .weekly-lb-row {
    border-top: 1px solid rgba(255, 255, 255, .05);
}

.weekly-lb-me {
    background: color-mix(in srgb, var(--daily-you) 15%, transparent);
    box-shadow: inset 0 0 0 1.5px var(--daily-you);
}

.weekly-lb-community {
    background: color-mix(in srgb, var(--daily-community) 13%, transparent);
    box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--daily-community) 60%, transparent);
}

.weekly-lb-place {
    font-family: var(--font-display);
    font-weight: 700;
    min-width: 36px;
    font-variant-numeric: tabular-nums;
}

.weekly-lb-user {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ===== Quiet scrolling (round 4): widget inner scrollers show NO scrollbar at rest —
   the edge fades are the "there's more" affordance. Desktop reveals a thin themed
   thumb on hover (hover = intent); touch keeps native auto-hiding overlays. Where
   scroll-driven animations exist, the fades are honest: top fade only once scrolled,
   bottom fade gone at the end. Elsewhere the static bottom fade remains. ===== */

@property --dash-fade-top {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

@property --dash-fade-bottom {
    syntax: "<length>";
    inherits: false;
    initial-value: 24px;
}

.dash-scroll,
.dash-drawer .mud-drawer-content {
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}

.dash-scroll:hover,
.dash-drawer .mud-drawer-content:hover {
    scrollbar-color: color-mix(in srgb, var(--mix-ink-muted) 35%, transparent) transparent;
}

.dash-scroll::-webkit-scrollbar,
.dash-drawer .mud-drawer-content::-webkit-scrollbar {
    width: 6px;
}

.dash-scroll::-webkit-scrollbar-track,
.dash-drawer .mud-drawer-content::-webkit-scrollbar-track {
    background: transparent;
}

.dash-scroll::-webkit-scrollbar-thumb,
.dash-drawer .mud-drawer-content::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: 3px;
}

.dash-scroll:hover::-webkit-scrollbar-thumb,
.dash-drawer .mud-drawer-content:hover::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--mix-ink-muted) 35%, transparent);
}

.dash-scroll {
    overflow-y: auto;
    mask-image: linear-gradient(to bottom,
        transparent 0,
        #000 var(--dash-fade-top),
        #000 calc(100% - var(--dash-fade-bottom)),
        transparent 100%);
}

@supports (animation-timeline: scroll()) {
    .dash-scroll {
        animation: dash-scroll-fades linear both;
        animation-timeline: scroll(self);
    }

    @keyframes dash-scroll-fades {
        0% {
            --dash-fade-top: 0px;
            --dash-fade-bottom: 24px;
        }

        10% {
            --dash-fade-top: 24px;
            --dash-fade-bottom: 24px;
        }

        90% {
            --dash-fade-top: 24px;
            --dash-fade-bottom: 24px;
        }

        100% {
            --dash-fade-top: 24px;
            --dash-fade-bottom: 0px;
        }
    }
}

/* Themed ApexCharts tooltips (round 5): Apex's own dark theme half-applies — pin the
   popover to our tokens instead. Keyed on the shared wrapper class so every graph on
   the site can adopt it (ApexChartTheming.WrapperClass). */

.themed-apex .apexcharts-tooltip {
    background: rgba(8, 12, 18, .94) !important;
    border: 1px solid rgba(255, 255, 255, .16) !important;
    color: #ffffff !important;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .5) !important;
}

.themed-apex .apexcharts-tooltip-title {
    background: rgba(255, 255, 255, .06) !important;
    border-bottom: 1px solid rgba(255, 255, 255, .1) !important;
    color: #ffffff !important;
    font-family: var(--font-display) !important;
}

/* All the tooltip text runs white — the token ink was too dim to read over the chart (owner). */
.themed-apex .apexcharts-tooltip-text,
.themed-apex .apexcharts-tooltip-text-y-label,
.themed-apex .apexcharts-tooltip-text-y-value,
.themed-apex .apexcharts-tooltip-text-label,
.themed-apex .apexcharts-tooltip-text-value,
.themed-apex .apexcharts-tooltip-y-group,
.themed-apex .apexcharts-tooltip-series-group {
    color: #ffffff !important;
}

/* ===== Chart details page (docs/design/chart-details-overhaul.md, mock R2) =====
   Answer -> evidence -> record -> onward. Static-SSR-ready: everything here styles from
   tokens; the sections that need a circuit are components (the Stage-3 islands). */

.chart-empty {
    max-width: 560px;
    margin: 32px auto;
    display: grid;
    gap: 10px;
}

.chart-empty-sub {
    color: var(--mix-ink-muted);
}

.chart-hero {
    display: grid;
    grid-template-columns: 300px 1fr;
    gap: 28px;
    align-items: start;
    padding: 18px 0 8px;
}

/* The jacket column: art, then your score in the nook beneath it. */
.chart-hero-jacket-col {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 300px;
    flex: none;
}

/* The chart you are on stays in its song's lineup, ringed rather than removed — taking it
   out made the row read as "the other ones" and hid where you sit in the ladder. */
.chart-hero-sibling-current {
    display: inline-flex;
    padding: 3px;
    border-radius: 10px;
    border: 1px solid var(--mix-primary);
    box-shadow: 0 0 10px color-mix(in srgb, var(--mix-primary) 45%, transparent);
}

.chart-section-credit {
    margin-top: 14px;
    font-size: .74rem;
    color: var(--mix-ink-muted);
}

.chart-jacket {
    position: relative;
    width: 300px;
    border-radius: 14px;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, .10);
    background: var(--mix-surface);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
}

/* Scoped to the jacket wrapper, never `.chart-jacket .mud-image`: the difficulty bubble is
   a MudImage in this box too, and telling it to fill the frame made it 300px wide. */
.chart-jacket-art,
.chart-jacket-art .mud-image {
    width: 100%;
    height: auto;
    display: block;
}

.chart-jacket-video {
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 0;
    display: block;
}

/* The jacket is the button, same as the shelf's cards — two ways to start a video on one
   page is one too many. The bubble stays outside it: it labels the art, it does not play. */
.chart-jacket-playable {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    position: relative;
}

/* Centred circle, revealed on hover — .chart-card-play's treatment at the hero's scale.
   pointer-events: none so the button underneath owns every pixel of the art. */
.chart-jacket-play {
    position: absolute;
    left: 50%;
    top: 50%;
    translate: -50% -50%;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 62px;
    height: 62px;
    padding-left: 4px;
    border-radius: 99px;
    pointer-events: none;
    background: rgba(0, 0, 0, .8);
    border: 1px solid rgba(255, 255, 255, .2);
    color: #fff;
    opacity: .85;
    transform: scale(.94);
    transition: opacity .12s, transform .12s, background .12s, border-color .12s;
}

.chart-jacket-play::before {
    content: "";
    border-style: solid;
    border-width: 10px 0 10px 16px;
    border-color: transparent transparent transparent currentColor;
}

.chart-jacket-playable:hover .chart-jacket-play,
.chart-jacket-playable:focus-visible .chart-jacket-play {
    opacity: 1;
    transform: scale(1);
}

.chart-jacket-playable:hover .chart-jacket-play {
    background: rgba(0, 0, 0, .93);
    border-color: var(--mix-primary);
}

.chart-jacket-close {
    position: absolute;
    right: 12px;
    top: 12px;
    z-index: 4;
    cursor: pointer;
    font-weight: 600;
    font-size: .68rem;
    color: #fff;
    background: rgba(0, 0, 0, .8);
    border: 1px solid rgba(255, 255, 255, .2);
    border-radius: 99px;
    width: 24px;
    height: 24px;
    line-height: 1;
}

.chart-jacket-close:hover {
    border-color: var(--mix-primary);
}

.chart-jacket-bubble {
    position: absolute;
    right: 10px;
    top: 10px;
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .6));
}

.chart-hero-title {
    font-family: var(--font-display);
    font-size: 2.3rem;
    font-weight: 800;
    line-height: 1.05;
    margin: 0;
    text-wrap: balance;
}

.chart-hero-sub {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
    color: var(--mix-ink-muted);
    font-size: .9rem;
}

.chart-hero-siblings {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.chart-hero-facts {
    display: flex;
    gap: 26px;
    flex-wrap: wrap;
    margin-top: 16px;
}

.chart-fact-value {
    display: block;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.chart-fact-label {
    display: block;
    font-size: .68rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin-top: 1px;
}

.chart-verdict {
    margin-top: 16px;
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .10);
    border-left: 3px solid var(--mix-accent);
    border-radius: 12px;
    padding: 14px 17px;
}

.chart-verdict-head {
    font-size: 1.12rem;
    font-weight: 700;
    line-height: 1.35;
    text-wrap: balance;
}

.chart-verdict-sub {
    color: var(--mix-ink-muted);
    font-size: .86rem;
    margin-top: 5px;
    max-width: 62ch;
}

.chart-verdict-chips {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 11px;
}

.chart-verdict-chip {
    border: 1px solid;
    border-radius: 99px;
    font-size: .74rem;
    font-weight: 700;
    padding: 3px 11px;
    white-space: nowrap;
}

.chart-verdict-chip-muted {
    color: var(--mix-ink-muted);
    border-color: rgba(255, 255, 255, .22);
}

.chart-hero-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 16px;
}

.chart-overline {
    display: block;
    font-size: .68rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    font-weight: 600;
}

.chart-section {
    margin: 26px 0;
}

.chart-section-head {
    display: flex;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

.chart-section-sub {
    color: var(--mix-ink-muted);
}

/* Your best + record inputs (the record island at Stage 3). */
/* One card in the hero's nook, not two panels down the page: your score is the first thing
   you look for, and recording is a mode of it rather than a separate destination. */
.chart-record {
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .10);
    border-radius: 12px;
    padding: 14px 16px;
}

.chart-record-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.chart-record-edit {
    flex: none;
    color: var(--mix-ink-muted);
}

.chart-record-edit:hover {
    color: var(--mix-primary);
}

.chart-record-inputs {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 10px;
}

.chart-record-score {
    margin-top: 8px;
}

.chart-record-age, .chart-record-note {
    display: block;
    color: var(--mix-ink-muted);
    margin-top: 4px;
}

.chart-record-empty {
    color: var(--mix-ink-muted);
    margin-top: 8px;
}

.chart-record-journey {
    margin-top: 12px;
    border-top: 1px dashed rgba(255, 255, 255, .14);
    padding-top: 9px;
}

.chart-record-journey-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 0;
}

.chart-record-journey-date {
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.chart-record-journey-score {
    font-variant-numeric: tabular-nums;
}

.chart-record-row {
    display: grid;
    grid-template-columns: minmax(120px, 1fr) minmax(120px, 1fr);
    gap: 10px 12px;
    align-items: center;
    margin-top: 8px;
}

/* Evidence graph cards - sentence first, curve second. */
.chart-evidence {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
}

.chart-evidence-card {
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .10);
    border-radius: 12px;
    padding: 13px 15px;
}

.chart-evidence-caption {
    font-size: .92rem;
    font-weight: 600;
    line-height: 1.4;
    margin: 4px 0 8px;
    max-width: 48ch;
}

.chart-evidence-empty {
    grid-column: 1 / -1;
    color: var(--mix-ink-muted);
}

.chart-skill-foot {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
    font-size: .78rem;
    color: var(--mix-ink-muted);
}

/* History band. */
.chart-timeline {
    display: flex;
    overflow-x: auto;
    padding-bottom: 4px;
}

.chart-timeline-node {
    flex: 1;
    min-width: 150px;
    position: relative;
    padding: 14px 18px 4px 0;
}

.chart-timeline-node::before {
    content: "";
    position: absolute;
    top: 21px;
    left: 0;
    right: 0;
    height: 2px;
    background: rgba(255, 255, 255, .18);
}

.chart-timeline-node::after {
    content: "";
    position: absolute;
    top: 16px;
    left: 0;
    width: 12px;
    height: 12px;
    border-radius: 99px;
    background: var(--mix-bg);
    border: 3px solid var(--mix-primary);
}

.chart-timeline-dim::after {
    border-color: var(--mix-ink-muted);
}

.chart-timeline-mix {
    margin-top: 22px;
    font-weight: 800;
    font-size: .92rem;
}

.chart-timeline-level {
    margin-top: 4px;
    font-size: .82rem;
    color: var(--mix-ink-muted);
}

.chart-timeline-delta {
    margin-left: 6px;
    color: var(--diff-hard);
    font-weight: 800;
}

/* Leaderboard - the widgets' glow vocabulary at page scale. */
.chart-lb-table {
    width: 100%;
    border-collapse: collapse;
    font-size: .88rem;
}

.chart-lb-table th {
    text-align: left;
    font-size: .66rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    font-weight: 600;
    padding: 4px 10px 7px;
}

.chart-lb-table td {
    padding: 6px 10px;
    border-top: 1px solid rgba(255, 255, 255, .07);
}

.chart-lb-place {
    color: var(--mix-ink-muted);
    width: 34px;
    font-variant-numeric: tabular-nums;
}

.chart-lb-level {
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.chart-lb-score-col {
    text-align: right;
}

.chart-lb-me td {
    background: color-mix(in srgb, var(--daily-you) 15%, transparent);
    box-shadow: inset 0 1.5px 0 var(--daily-you), inset 0 -1.5px 0 var(--daily-you);
}

.chart-lb-community td {
    background: color-mix(in srgb, var(--daily-community) 13%, transparent);
}

.chart-lb-gap td {
    text-align: center;
    color: var(--mix-ink-muted);
    font-size: .74rem;
    padding: 2px;
    border-top: none;
}

.chart-lb-foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.chart-lb-legend {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .74rem;
    color: var(--mix-ink-muted);
}

.chart-lb-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 3px;
}

.chart-lb-dot-community {
    background: var(--daily-community);
}

.chart-lb-dot-me {
    background: var(--daily-you);
    margin-left: 10px;
}

.chart-lb-empty, .chart-shelf-empty {
    color: var(--mix-ink-muted);
}

/* Similar-charts shelf - the internal link mesh. Three across, then two, then one; no
   density modes, because the card is sized around 16:9 art and that shape is the point. */
.chart-shelf {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
}

/* The static card grid is the crawlable mesh; the interactive shelf renders the same cards
   plus its controls and marks its root data-island-ready the moment it connects, which
   hides the static copy. Both render real <a href> cards, so nothing reflows on handoff. */
.chart-shelf-wrap:has([data-island-ready]) .chart-shelf-static {
    display: none;
}

.chart-shelf-controls {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    align-items: center;
    margin-bottom: 12px;
}

.chart-shelf-sort {
    display: flex;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 4px;
    overflow: hidden;
}

.chart-shelf-sort button {
    font-size: .75rem;
    color: var(--mix-ink-muted);
    background: transparent;
    border: 0;
    padding: 7px 12px;
    cursor: pointer;
    transition: color .12s, background .12s;
}

.chart-shelf-sort button + button {
    border-left: 1px solid rgba(255, 255, 255, .12);
}

.chart-shelf-sort button[aria-pressed="true"] {
    color: var(--mix-ink);
    background: var(--mix-surface-muted);
}

.chart-shelf-sort button:disabled {
    opacity: .4;
    cursor: not-allowed;
}

.chart-shelf-personal {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .75rem;
    color: var(--mix-ink-muted);
    cursor: pointer;
}

.chart-shelf-personal input {
    accent-color: var(--mix-primary);
    cursor: pointer;
}

.chart-shelf-personal:has(input:disabled) {
    opacity: .4;
    cursor: not-allowed;
}

.chart-shelf-addfilter {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .75rem;
    color: var(--mix-ink-muted);
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 4px;
    padding: 6px 10px;
    cursor: pointer;
    transition: color .12s, border-color .12s;
}

.chart-shelf-addfilter:hover:not(:disabled),
.chart-shelf-addfilter[aria-expanded="true"] {
    color: var(--mix-ink);
    border-color: var(--mix-primary);
}

.chart-shelf-addfilter:disabled {
    opacity: .4;
    cursor: not-allowed;
}

/* How many filters are on, when the panel that would show you is shut. */
.chart-shelf-fcount {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    font-size: .65rem;
    font-weight: 700;
    color: var(--mix-primary-contrast);
    background: var(--mix-primary);
}

.chart-shelf-filterpanel {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-bottom: 14px;
    padding: 14px;
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 6px;
}

.chart-shelf-ftoggles {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.chart-shelf-ftoggles label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .75rem;
    color: var(--mix-ink-muted);
    cursor: pointer;
}

.chart-shelf-ftoggles input {
    accent-color: var(--mix-primary);
    cursor: pointer;
}

.chart-shelf-ftoggles label:has(input:checked) {
    color: var(--mix-ink);
}

.chart-shelf-funavailable {
    opacity: .4;
    cursor: not-allowed;
}

/* Below the line because it is not one of the four: it asks the opposite question rather
   than narrowing this one. */
.chart-shelf-fopposite {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .75rem;
    color: var(--mix-ink-muted);
    cursor: pointer;
    padding-top: 12px;
    border-top: 1px solid rgba(255, 255, 255, .08);
}

.chart-shelf-fopposite input {
    accent-color: var(--mix-primary);
    cursor: pointer;
}

.chart-shelf-fopposite:has(input:checked) {
    color: var(--mix-ink);
}

.chart-shelf-fopposite:has(input:disabled) {
    opacity: .4;
    cursor: not-allowed;
}

.chart-shelf-fapply {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* The count owns the row; the buttons sit at the end of it. */
.chart-shelf-fcompare {
    flex: 1 1 auto;
    font-size: .74rem;
    color: var(--mix-ink-muted);
}

.chart-shelf-fclear,
.chart-shelf-fgo {
    font-size: .75rem;
    border-radius: 4px;
    padding: 6px 14px;
    cursor: pointer;
    transition: opacity .12s;
}

.chart-shelf-fclear {
    color: var(--mix-ink-muted);
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .12);
}

.chart-shelf-fgo {
    color: var(--mix-primary-contrast);
    background: var(--mix-primary);
    border: 1px solid var(--mix-primary);
    font-weight: 600;
}

.chart-shelf-fclear:disabled,
.chart-shelf-fgo:disabled {
    opacity: .4;
    cursor: not-allowed;
}

/* Filters that ran, as against filters being chosen — read-only, because the panel
   above is where they change and two edit points would fight. */
.chart-shelf-fchipclear {
    font-size: .72rem;
    color: var(--mix-ink-muted);
    background: transparent;
    border: 0;
    padding: 4px 6px;
    cursor: pointer;
    text-decoration: underline;
}

.chart-shelf-fchipclear:hover {
    color: var(--mix-primary);
}

.chart-shelf-hint,
.chart-shelf-reach {
    font-size: .74rem;
    color: var(--mix-ink-muted);
}

.chart-shelf-reach {
    margin-top: 10px;
}

.chart-shelf-filters {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.chart-shelf-fchip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .72rem;
    color: var(--mix-ink-muted);
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 4px;
    padding: 4px 4px 4px 8px;
}

.chart-shelf-fchip span {
    color: var(--mix-ink);
    font-weight: 600;
}


.chart-shelf-nearmiss {
    margin-top: 18px;
}

.chart-shelf-nearmiss > summary {
    cursor: pointer;
    color: var(--mix-ink-muted);
    font-size: .8rem;
    padding: 6px 0;
}

.chart-shelf-nearmiss > .chart-shelf {
    margin-top: 10px;
}

.chart-card {
    position: relative;
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .10);
    border-radius: 4px;
    transition: border-color .12s, background .12s;
}

.chart-card:hover {
    border-color: var(--mix-primary);
    background: var(--mix-surface-muted);
}

/* 16:9 from the start, so the video drops into the art's exact box: the card never
   changes height and the grid never jumps. The jacket is the play target; the link out
   is the icon by the name, so the two never fight over a pixel. */
.chart-card-art {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    margin: 10px 10px 0;
    width: calc(100% - 20px);
    border-radius: 2px;
    background: rgba(0, 0, 0, .35);
    padding: 0;
    border: 0;
}

button.chart-card-art {
    cursor: pointer;
}

/* Scoped to the jacket wrapper, never `.chart-card-art img`: the bubble is an <img> in
   that box too, and telling it to fill the box makes it the size of the card. */
.chart-card-jacket,
.chart-card-jacket > * {
    display: block;
    width: 100%;
    height: 100%;
}

.chart-card-jacket img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 2px;
}

.chart-card-art-playing {
    overflow: hidden;
    border: 1px solid var(--mix-primary);
}

.chart-card-video {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}

.chart-card-bubble {
    position: absolute;
    right: -6px;
    bottom: -8px;
    z-index: 3;
    filter: drop-shadow(0 2px 7px rgba(0, 0, 0, .6));
}

.chart-card-body {
    display: block;
    min-width: 0;
    padding: 12px 12px 12px;
}

.chart-card-title {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 9px;
}

.chart-card-title h3 {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    margin: 0;
    font-weight: 600;
    font-size: .88rem;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The card's only <a>. Small, but a real link — the crawler follows this. */
.chart-card-golink {
    flex: none;
    display: inline-flex;
    align-items: center;
    color: var(--mix-primary);
    opacity: .65;
    transition: opacity .12s;
}

.chart-card-golink:hover,
.chart-card-golink:focus-visible {
    opacity: 1;
}

.chart-card-golink .mud-icon-root {
    font-size: .95rem;
}

.chart-card-pct {
    font-weight: 700;
    font-size: .8rem;
    color: var(--mix-primary);
    font-variant-numeric: tabular-nums;
}

.chart-card-meta {
    display: block;
    margin-top: 4px;
    font-size: .69rem;
    line-height: 1.5;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.chart-card-meta em {
    font-style: normal;
    color: var(--mix-ink);
}

.chart-card-meta i {
    font-style: normal;
    opacity: .45;
    padding: 0 4px;
}

.chart-card-wl {
    display: block;
    margin: 10px 0 5px;
    font-weight: 600;
    font-size: .56rem;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.chart-card-why {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.chart-card-why b {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-weight: 500;
    font-size: .69rem;
    padding: 4px 6px;
    border-radius: 2px;
    color: var(--mix-ink);
    background: color-mix(in srgb, var(--mix-primary) 11%, transparent);
    border: 1px solid color-mix(in srgb, var(--mix-primary) 40%, transparent);
}

.chart-card-why b var {
    font-weight: 600;
    font-size: .62rem;
    font-style: normal;
    color: var(--mix-primary);
    font-variant-numeric: tabular-nums;
}

/* Intensity is a different KIND of reason and must not read as a skill. */
.chart-card-why-intensity {
    background: color-mix(in srgb, var(--mix-secondary) 11%, transparent) !important;
    border-color: color-mix(in srgb, var(--mix-secondary) 40%, transparent) !important;
}

.chart-card-why-intensity var {
    color: var(--mix-secondary) !important;
}

/* Mirrors the art's box so the button centres on the art without knowing its height.
   Transparent to the mouse, so the link underneath keeps the whole card as its target
/* Decoration: the whole jacket is the button, so this only says so. */
.chart-card-play {
    position: absolute;
    left: 50%;
    top: 50%;
    translate: -50% -50%;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 50px;
    height: 50px;
    padding-left: 3px;
    border-radius: 99px;
    pointer-events: none;
    background: rgba(0, 0, 0, .8);
    border: 1px solid rgba(255, 255, 255, .2);
    color: #fff;
    opacity: 0;
    transform: scale(.88);
    transition: opacity .13s, transform .13s, background .13s, border-color .13s;
}

.chart-card-play::before {
    content: "";
    border-style: solid;
    border-width: 8px 0 8px 13px;
    border-color: transparent transparent transparent currentColor;
}

.chart-card-art-playable:hover .chart-card-play,
.chart-card-art-playable:focus-visible .chart-card-play {
    opacity: 1;
    transform: scale(1);
}

.chart-card-art-playable:hover .chart-card-play {
    background: rgba(0, 0, 0, .93);
    border-color: var(--mix-primary);
}

.chart-card-close {
    position: absolute;
    right: 15px;
    top: 15px;
    z-index: 4;
    cursor: pointer;
    font-weight: 600;
    font-size: .68rem;
    color: #fff;
    background: rgba(0, 0, 0, .8);
    border: 1px solid rgba(255, 255, 255, .2);
    border-radius: 2px;
    padding: 4px 6px;
}

.chart-card-close:hover {
    border-color: var(--mix-primary);
}

.chart-admin {
    margin: 26px 0 12px;
}

@media (max-width: 900px) {
    .chart-hero {
        grid-template-columns: 1fr;
    }

    .chart-jacket {
        width: min(300px, 100%);
    }

    .chart-hero-title {
        font-size: 1.7rem;
    }

    .chart-record, .chart-evidence {
        grid-template-columns: 1fr;
    }

    .chart-shelf {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 600px) {
    .chart-shelf {
        grid-template-columns: 1fr;
    }
}

/* ============================================================================
   Weekly Charts — the challenges hub (docs/design/weekly-charts-overhaul.md).
   A static-SSR page: --mix-* / semantic tokens only, no --mud-* (static-shell.md
   D5). The one island is the dialog host; these classes are pure layout + the
   two semantic ramps.
   ============================================================================ */

.challenge-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 14px;
    margin: 14px 0 12px;
}

.challenge-head h1 {
    margin: 0;
}

.challenge-yourweek {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    font-size: 12.5px;
}

.challenge-chip {
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 12px;
    padding: 2px 10px;
    color: var(--mix-ink);
    white-space: nowrap;
}

.challenge-chip b {
    color: var(--mix-accent);
    font-weight: 600;
}

.challenge-controls {
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* Native-details pickers (week, communities): no circuit, the shell's mix-picker precedent. */
.challenge-picker {
    position: relative;
}

.challenge-picker > summary {
    list-style: none;
    cursor: pointer;
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 6px;
    padding: 3px 10px;
    font-size: 12.5px;
    color: var(--mix-ink);
    user-select: none;
    white-space: nowrap;
}

.challenge-picker > summary::-webkit-details-marker {
    display: none;
}

.challenge-picker > summary::after {
    content: " \25BE";
    color: var(--mix-ink-muted);
}

.challenge-picker[open] > summary {
    border-color: var(--mix-primary);
}

.challenge-picker-menu {
    position: absolute;
    right: 0;
    z-index: 20;
    margin-top: 5px;
    min-width: 220px;
    max-height: 280px;
    overflow: auto;
    background: var(--mix-surface-muted);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 8px;
    padding: 6px;
    box-shadow: 0 8px 22px rgba(0, 0, 0, .5);
}

.challenge-picker-menu a,
.challenge-picker-menu label {
    display: block;
    padding: 5px 9px;
    border-radius: 5px;
    color: var(--mix-ink);
    text-decoration: none;
    font-size: 13px;
    cursor: pointer;
}

.challenge-picker-menu a:hover,
.challenge-picker-menu label:hover {
    background: rgba(255, 255, 255, .06);
}

.challenge-picker-menu a.on {
    color: var(--mix-accent);
}

.challenge-picker-apply {
    margin: 6px 4px 2px;
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
    border: 0;
    border-radius: 5px;
    padding: 3px 12px;
    font-weight: 600;
    cursor: pointer;
}

.challenge-section {
    margin: 18px 0;
}

.challenge-sect-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 8px;
    flex-wrap: wrap;
}

.challenge-sect-head h2 {
    margin: 0;
}

.challenge-sect-head .sub {
    color: var(--mix-ink-muted);
    font-size: 12.5px;
}

.challenge-sect-head .right {
    margin-left: auto;
    display: flex;
    gap: 6px;
    align-items: center;
}

/* ---- shared row bits ------------------------------------------------------ */
.challenge-lb-place {
    min-width: 1.7em;
    text-align: right;
    font-weight: 700;
}

.challenge-flag {
    font-size: 10.5px;
    opacity: .8;
    margin-right: 4px;
}

.challenge-empty {
    border: 1px dashed rgba(255, 255, 255, .12);
    border-radius: 10px;
    padding: 16px;
    text-align: center;
    color: var(--mix-ink-muted);
}

.challenge-empty a {
    color: var(--mix-accent);
}

.challenge-muted {
    color: var(--mix-ink-muted);
}

/* ---- daily step strip ----------------------------------------------------- */
.challenge-limbo-chip {
    background: var(--mix-secondary);
    color: var(--mix-bg);
    font-weight: 700;
    border-radius: 4px;
    padding: 0 7px;
    font-size: 11.5px;
    text-transform: uppercase;
    white-space: nowrap;
}

/* ---- buttons -------------------------------------------------------------- */
.challenge-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
    font-weight: 600;
    border: 0;
    border-radius: 6px;
    padding: 3px 11px;
    cursor: pointer;
    font-size: 12.5px;
    text-decoration: none;
    white-space: nowrap;
}

.challenge-btn.ghost {
    background: transparent;
    color: var(--mix-primary);
    border: 1px solid var(--mix-primary);
}

.challenge-iconbtn {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .12);
    color: var(--mix-ink-muted);
    border-radius: 4px;
    padding: 0 6px;
    cursor: pointer;
    font-size: 11.5px;
    line-height: 1.6;
}

.challenge-iconbtn:hover {
    color: var(--mix-ink);
    border-color: var(--mix-primary);
}

/* ---- weekly grid ---------------------------------------------------------- */
.challenge-gridbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

.challenge-gridbar h2 {
    margin: 0;
}

.challenge-filter-note {
    color: var(--mix-ink-muted);
    font-size: 12px;
}

.challenge-filter-note a {
    color: var(--mix-accent);
    text-decoration: none;
}

/* Density switcher, right-aligned (Tier Lists treatment). */
.challenge-den-group {
    margin-left: auto;
    display: flex;
    gap: 2px;
}

.challenge-den-btn {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .12);
    color: var(--mix-ink-muted);
    border-radius: 5px;
    width: 28px;
    height: 26px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.challenge-den-btn.on {
    color: var(--mix-primary);
    border-color: var(--mix-primary);
}

/* ── The week's grid, round-12 anatomy (§12): unsquished cards, top-3 + you, both ranking
   worlds shipped. Density keys on the grid's own data-density. ── */
.challenge-grid {
    display: grid;
    gap: 14px;
    /* Cap the comfortable grid at 6 columns: a wide monitor otherwise fits a 7th, and the
       weekly board's chart count divides cleanly by 6, so the 7th just orphans the last row.
       Each track is at least 280px but never narrower than a sixth of the row, so at most six
       ever fill the width — fewer when the row can't hold six at 280px. */
    grid-template-columns: repeat(auto-fill, minmax(max(280px, (100% - 5 * 14px) / 6), 1fr));
}

.challenge-grid.suggested-only .challenge-card[data-suggested="false"] {
    display: none;
}

/* The filter note follows the grid's state — both texts ship, :has() picks one. */
.challenge-main:has(.challenge-grid.suggested-only) .challenge-filter-note .when-all,
.challenge-main:not(:has(.challenge-grid.suggested-only)) .challenge-filter-note .when-filtered {
    display: none;
}

.challenge-card {
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .06);
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    position: relative;
}

.challenge-card[data-suggested="true"] {
    border-color: color-mix(in srgb, var(--mix-accent) 55%, transparent);
    box-shadow: 0 0 14px -8px var(--mix-accent);
}

.challenge-card-jacket {
    position: relative;
    aspect-ratio: 16 / 7.5;
    background-size: cover;
    background-position: center;
    display: block;
}

.challenge-card-bubble {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 2;
}

.challenge-card-body {
    padding: 8px 10px 6px;
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.challenge-card-name {
    display: block;
    font-size: 1.02rem;
    font-weight: 700;
    color: var(--mix-ink);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.challenge-card-line {
    display: grid;
    grid-template-columns: 26px 20px minmax(0, 1fr) auto;
    gap: 7px;
    align-items: center;
    font-size: 12.2px;
    white-space: nowrap;
    color: var(--mix-ink);
    padding: 2px 4px;
    border-radius: 6px;
}

.challenge-card-line .who {
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    color: var(--mix-ink-muted);
    font-weight: 600;
}

.challenge-card-line .score {
    justify-self: end;
}

.challenge-card-line.mine {
    background: color-mix(in srgb, var(--mix-primary) 15%, transparent);
    box-shadow: inset 0 0 0 1px var(--mix-primary), 0 0 12px -4px var(--mix-primary);
}

.challenge-card-line.mine .who {
    color: var(--mix-ink);
}

.challenge-card-line.unplayed {
    display: flex;
    color: color-mix(in srgb, var(--mix-ink-muted) 55%, transparent);
}

.challenge-card-foot {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 8px 7px;
    border-top: 1px solid rgba(255, 255, 255, .05);
    color: var(--mix-ink-muted);
    font-size: 11.5px;
    margin-top: auto;
}

.challenge-card-foot .spacer,
.challenge-gridbar .spacer,
.challenge-railhead .spacer,
.challenge-railfoot .spacer {
    flex: 1;
}

/* ── The two ranking worlds (M20). Default shows the overall head; .relevant-on swaps to the
   renumbered in-range head. Rows/counters carry .co (overall) and .cr (in-range) pairs. ── */
.challenge-card-line.w-r:not(.w-o) {
    display: none;
}

.relevant-on .challenge-card-line {
    display: none;
}

.relevant-on .challenge-card-line.w-r {
    display: grid;
}

.relevant-on .challenge-card-line.unplayed.w-r {
    display: flex;
}

.challenge-card .cr {
    display: none;
}

.relevant-on .challenge-card .co {
    display: none;
}

.relevant-on .challenge-card .cr {
    display: inline;
}

.relevant-on .challenge-card-line[data-inrange="false"]:not(.mine) {
    display: none;
}

/* Compact keeps one action: the count chip opens the board (tier-list corner-chip). */
.challenge-count-chip {
    display: none;
    position: absolute;
    right: 5px;
    bottom: 5px;
    z-index: 2;
    background: color-mix(in srgb, var(--mix-bg) 85%, transparent);
    color: var(--mix-ink);
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 10.5px;
    line-height: 1.6;
    cursor: pointer;
}

.challenge-count-chip:hover {
    border-color: var(--mix-primary);
    color: var(--mix-primary);
}

.challenge-grid[data-density="Compact"] {
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
    gap: 10px;
}

.challenge-grid[data-density="Compact"] .challenge-card-body,
.challenge-grid[data-density="Compact"] .challenge-card-foot {
    display: none;
}

.challenge-grid[data-density="Compact"] .challenge-card-jacket {
    aspect-ratio: 1 / 1;
}

.challenge-grid[data-density="Compact"] .challenge-count-chip {
    display: block;
}

/* Table renders jacket and bubble side by side (M19) — the tier-table pattern, never overlaid. */
.challenge-grid[data-density="Table"] {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.challenge-grid[data-density="Table"] .challenge-card {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
}

.challenge-grid[data-density="Table"] .challenge-card-jacket {
    width: 76px;
    aspect-ratio: 16 / 9;
    border-radius: 6px;
    flex: none;
}

.challenge-grid[data-density="Table"] .challenge-card-bubble {
    position: static;
    order: 1;
}

.challenge-grid[data-density="Table"] .challenge-card-body {
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 0;
    order: 2;
}

.challenge-grid[data-density="Table"] .challenge-card-name {
    width: 170px;
    flex: none;
    font-size: .92rem;
}

.challenge-grid[data-density="Table"] .challenge-card-line {
    flex: 1;
    background: none;
    box-shadow: none;
}

/* Table is top-1 + you: every visible-world row after the first hides unless it's yours. */
.challenge-grid[data-density="Table"]:not(.relevant-on)
.challenge-card-line.w-o:not(.mine) ~ .challenge-card-line.w-o:not(.mine) {
    display: none;
}

.challenge-grid[data-density="Table"].relevant-on
.challenge-card-line.w-r:not(.mine) ~ .challenge-card-line.w-r:not(.mine) {
    display: none;
}

.challenge-grid[data-density="Table"] .challenge-card-foot {
    border: 0;
    margin: 0;
    padding: 0;
    order: 3;
}

.challenge-poollink {
    color: var(--mix-ink-muted);
    font-size: 12.5px;
    margin-top: 8px;
}

/* ── The rail layout (§12.1, M14/M22): boards left in widget chrome, the grid right.
   The collapse ladder: ≥1080 rail-left · 640–1080 rail 2-up above the grid · <640 single
   column in fold order Daily → This Week → Monthly. ── */
.challenge-layout {
    display: grid;
    grid-template-columns: 330px minmax(0, 1fr);
    gap: 18px;
    align-items: start;
    margin-top: 12px;
}

.challenge-rail {
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
}

.challenge-main {
    min-width: 0;
}

@media (max-width: 1079.98px) {
    .challenge-layout {
        grid-template-columns: 1fr;
    }

    .challenge-rail {
        display: grid;
        grid-template-columns: 1fr 1fr;
        align-items: start;
    }
}

@media (max-width: 639.98px) {
    .challenge-layout {
        display: flex;
        flex-direction: column;
    }

    .challenge-rail {
        display: contents;
    }

    .challenge-railcard#daily {
        order: 0;
    }

    .challenge-main {
        order: 1;
    }

    .challenge-railcard#monthly {
        order: 2;
    }
}

/* ── Rail cards: the homepage dash-widget chrome. ── */
.challenge-railcard {
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .06);
    border-radius: 10px;
    padding: 12px 14px;
    min-width: 0;
}

.challenge-railcard.limbo {
    border-left: 3px solid var(--mix-secondary);
}

.challenge-railhead {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

.challenge-kicker {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.challenge-railchart {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 10px;
}

.challenge-rail-jacket {
    width: 44px;
    height: 44px;
    border-radius: 6px;
    background-size: cover;
    background-position: center;
    flex: none;
    display: block;
}

.challenge-railchart-id {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.challenge-railchart-id .name {
    font-weight: 700;
    font-size: .98rem;
    color: var(--mix-ink);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.challenge-railchart-id .sub {
    font-size: .72rem;
    color: var(--mix-ink-muted);
}

.challenge-railsub {
    font-size: .72rem;
    color: var(--mix-ink-muted);
    margin: -4px 0 8px;
}

.challenge-railfoot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    font-size: .74rem;
    color: var(--mix-ink-muted);
}

.challenge-ghostbtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .76rem;
    color: var(--mix-ink-muted);
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 6px;
    padding: 4px 10px;
    cursor: pointer;
    transition: color .12s, border-color .12s;
}

.challenge-ghostbtn:hover {
    color: var(--mix-accent);
    border-color: var(--mix-accent);
}

/* ── Rail leaderboard rows: place · avatar · name · (CL) · value. ── */
.challenge-lb {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.challenge-lb-row {
    display: grid;
    grid-template-columns: 24px 20px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 8px;
    padding: 4px 7px;
    border-radius: 7px;
    font-size: .83rem;
}

.challenge-lb-row.mine {
    background: color-mix(in srgb, var(--mix-primary) 15%, transparent);
    box-shadow: inset 0 0 0 1px var(--mix-primary), 0 0 12px -4px var(--mix-primary);
}

.challenge-lb-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--mix-ink);
}

.challenge-lb-total {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--mix-accent);
}

.challenge-lb-divider {
    font-size: .62rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin: 6px 2px 2px;
}

.challenge-avatar {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

.challenge-cl {
    font-size: .68rem;
    color: var(--mix-ink-muted);
    background: var(--mix-surface-muted);
    border-radius: 4px;
    padding: 1px 5px;
    font-variant-numeric: tabular-nums;
}

.challenge-mboard[hidden] {
    display: none;
}

/* ── The Phoenix 2 folder-title track (docs/design/pumbility-title-track.md): the glowy bar
   toward your next PUMBILITY title + one folder-aware caption, replacing the Phoenix 1 folder
   bars. --mix-* so it wears the mix accent, not a fixed green. ── */
.ptt {
    display: grid;
    gap: 10px;
    margin: 0 0 14px;
}

/* No card behind the bar — it sits directly on the page (owner call). */
.ptt-band {
    padding: 2px 2px 4px;
    display: grid;
    gap: 9px;
}

.ptt-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
}

/* The bar's top-left slot: the "from …" whisper, or the "serves" notifier on wider screens. */
.ptt-lead {
    display: flex;
    align-items: flex-end;
    min-width: 0;
    min-height: 1em;
}

.ptt-from {
    font-family: var(--font-display);
    font-size: 13px;
    letter-spacing: .02em;
    color: var(--mix-ink-muted);
    min-height: 1em;
}

/* The compact "serves" notifier riding the top-left of the bar (wide screens only — see the
   breakpoint by .ptt-serves). Mirrors the banner's accent tint at chip scale. */
.ptt-serves-top {
    display: none;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    padding: 3px 9px;
    border-radius: 8px;
    font-family: var(--font-display);
    font-size: 12px;
    letter-spacing: .02em;
    white-space: nowrap;
    color: var(--mix-ink);
    border: 1px solid color-mix(in srgb, var(--mix-accent) 38%, transparent);
    background: color-mix(in srgb, var(--mix-accent) 12%, transparent);
}

.ptt-target {
    text-align: right;
    line-height: 1.02;
}

.ptt-k {
    display: block;
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: 9.5px;
    color: var(--mix-primary);
    font-weight: 600;
    margin-bottom: 1px;
}

.ptt-t {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 20px;
    letter-spacing: .02em;
    color: var(--mix-ink);
}

/* The glowy bar. overflow:visible so the ring's shadow reads; the fill and dot both carry the
   mix glow. */
.ptt-bar {
    position: relative;
    height: 18px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--mix-bg) 55%, #000);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    overflow: visible;
}

.ptt-fill {
    position: absolute;
    inset: 1px auto 1px 1px;
    border-radius: 9px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--mix-primary) 68%, #000), var(--mix-primary));
    box-shadow: 0 0 16px -3px var(--mix-primary);
}

.ptt-you {
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--mix-bg);
    border: 2.5px solid var(--mix-primary);
    box-shadow: 0 0 0 3px var(--mix-bg), 0 0 13px -1px var(--mix-primary);
}

/* The one caption where the Phoenix 1 percentage used to be. */
.ptt-cap {
    text-align: center;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 14.5px;
    letter-spacing: .02em;
    color: var(--mix-primary);
}

/* Grade-up is a bigger ask than volume, so it reads neutral rather than the encouraging accent. */
.ptt-cap-grade {
    color: var(--mix-ink);
}

/* The folder sits above your current title — you can push past it here. This is the phone
   placement (a banner under the bar); above ~480 it moves up to the top-left .ptt-serves-top chip. */
.ptt-serves {
    display: flex;
    align-items: center;
    gap: 9px;
    border-radius: 10px;
    padding: 8px 13px;
    font-size: 13px;
    border: 1px solid color-mix(in srgb, var(--mix-accent) 40%, transparent);
    background: color-mix(in srgb, var(--mix-accent) 12%, transparent);
    color: var(--mix-ink);
}

@media (min-width: 481px) {
    .ptt-serves-top { display: inline-flex; }
    .ptt-serves { display: none; }
}

.ptt-serves-ic {
    color: var(--mix-accent);
    flex: none;
    font-size: 13px;
}

/* The collapsed state: the folder is beneath your top 50, so the bar's gone — the serves whisper
   is all that remains. */
.ptt-behind {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 14px;
    font-family: var(--font-display);
    font-size: 14px;
    letter-spacing: .02em;
    color: var(--mix-ink-muted);
    background: color-mix(in srgb, var(--mix-surface) 55%, transparent);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 10%, transparent);
    border-radius: 10px;
}

.ptt-behind-ic {
    flex: none;
    font-size: 15px;
}

/* ── The tier-list segment row (M18): joined buttons, filled primary when active. ── */
.challenge-seg {
    display: inline-flex;
    margin-bottom: 10px;
}

.challenge-seg-btn {
    font-size: .74rem;
    font-weight: 600;
    border: 1px solid color-mix(in srgb, var(--mix-primary) 55%, transparent);
    background: transparent;
    color: var(--mix-primary);
    padding: 3px 12px;
    cursor: pointer;
    margin-left: -1px;
    transition: background .12s, color .12s;
}

.challenge-seg-btn:first-child {
    border-radius: 6px 0 0 6px;
    margin-left: 0;
}

.challenge-seg-btn:last-child {
    border-radius: 0 6px 6px 0;
}

.challenge-seg-btn:hover {
    background: color-mix(in srgb, var(--mix-primary) 14%, transparent);
}

.challenge-seg-btn.on {
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
}

/* ── The relevant-players switch (M20) — deliberately quiet. ── */
.challenge-switch {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: .72rem;
    color: var(--mix-ink-muted);
    cursor: pointer;
    user-select: none;
    opacity: .85;
}

.challenge-switch:hover {
    opacity: 1;
}

.challenge-switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.challenge-switch i {
    width: 30px;
    height: 16px;
    border-radius: 999px;
    background: var(--mix-surface-muted);
    border: 1px solid rgba(255, 255, 255, .14);
    position: relative;
    transition: background .12s;
    flex: none;
}

.challenge-switch i::after {
    content: "";
    position: absolute;
    top: 1px;
    left: 1px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--mix-ink-muted);
    transition: left .12s, background .12s;
}

.challenge-switch input:checked + i {
    background: color-mix(in srgb, var(--mix-primary) 45%, var(--mix-surface-muted));
}

.challenge-switch input:checked + i::after {
    left: 15px;
    background: var(--mix-primary);
}

.challenge-switch input:focus-visible + i {
    outline: 2px solid var(--mix-primary);
    outline-offset: 1px;
}

/* ── Field-test round 1 ── */

/* The show-all/show-suggested toggles are actions, not text. */
.challenge-filter-note a {
    cursor: pointer;
}

/* Grade art and the score numeral center on one line and never wrap mid-row. */
.challenge-card-line .score,
.challenge-lb-score {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    white-space: nowrap;
    justify-self: end;
}

.challenge-card-line .score .mud-typography,
.challenge-lb-score .mud-typography {
    vertical-align: baseline !important;
}

/* Card mini-boards rank with a literal #N — one quiet color, no rarity ramp (the colored
   1s read as meaning; the ramp stays on the big boards where percentile is real). */
.challenge-card-line .challenge-lb-place {
    color: var(--mix-ink-muted);
    font-size: 11px;
    text-align: right;
}

.challenge-card-line.mine .challenge-lb-place {
    color: var(--mix-ink);
}

/* Shared-community rows glow green (the homepage widgets' treatment), you glow blue. */
.challenge-lb-row.community,
.challenge-card-line.community {
    background: color-mix(in srgb, var(--rarity-emerald) 13%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rarity-emerald) 60%, transparent);
}

.challenge-monthly tr.community td {
    background: color-mix(in srgb, var(--rarity-emerald) 10%, transparent);
}

/* UserLabel inside board rows: flag + name on one truncating line. */
.challenge-lb-name,
.challenge-card-line .who {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    overflow: hidden;
}

/* Record dialog: score, live grade, and plate share a row; stacked again on narrow phones. */
.challenge-record-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

.challenge-iconbtn.rec:hover {
    color: var(--mix-primary);
    border-color: var(--mix-primary);
}

.challenge-iconbtn.tro:hover {
    color: var(--mix-accent);
    border-color: var(--mix-accent);
}

/* ── The monthly dialog's counted-score stickers (M21): the official-leaderboards compact
   pattern, board-sized — jacket, bubble, grade/score strip, points badge. No song names. ── */
.challenge-mrow-who {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.challenge-stik-row {
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
}

.challenge-stik-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
    background: var(--mix-surface-muted);
    border-radius: 8px;
    padding: 10px;
    margin-top: 6px;
}

.challenge-stik {
    position: relative;
    display: block;
    width: 96px;
    aspect-ratio: 1 / 1;
    border-radius: 7px;
    overflow: hidden;
}

.challenge-stik-row .challenge-stik {
    width: 44px;
    aspect-ratio: 1 / 1;
}

.challenge-stik-row .challenge-stik .challenge-stik-line {
    display: none;
}

.challenge-stik-j {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
}

.challenge-stik-bubble {
    position: absolute;
    top: 4px;
    left: 4px;
    z-index: 2;
}

.challenge-stik-line {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    gap: 4px;
    background: color-mix(in srgb, var(--mix-bg) 85%, transparent);
    padding: 2px 5px;
    font-size: .64rem;
    z-index: 2;
}

.challenge-stik-line b {
    margin-left: auto;
    color: var(--mix-accent);
    font-variant-numeric: tabular-nums;
}

.challenge-poollink a {
    color: var(--mix-accent);
}

/* ---- monthly board -------------------------------------------------------- */
.challenge-monthly {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    min-width: 620px;
}

.challenge-monthly th {
    text-align: left;
    text-transform: uppercase;
    letter-spacing: .05em;
    font-size: 12px;
    color: var(--mix-ink-muted);
    padding: 6px 10px;
    border-bottom: 1px solid rgba(255, 255, 255, .12);
    background: var(--mix-surface);
}

.challenge-monthly td {
    padding: 5px 10px;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
    vertical-align: middle;
}

.challenge-monthly tr:last-child td {
    border-bottom: 0;
}

.challenge-monthly tr.mine td {
    background: color-mix(in srgb, var(--daily-you) 10%, transparent);
}

.challenge-mono-place {
    font-weight: 700;
    font-size: 15px;
}

.challenge-total {
    font-weight: 700;
    font-size: 15px;
    color: var(--mix-accent);
}

.challenge-expand > summary {
    cursor: pointer;
    color: var(--mix-primary);
    list-style: none;
}

.challenge-expand > summary::-webkit-details-marker {
    display: none;
}

.challenge-expand > summary::after {
    content: " \25B8";
}

.challenge-expand[open] > summary::after {
    content: " \25BE";
}

.challenge-expand-body {
    display: flex;
    gap: 7px;
    flex-wrap: wrap;
    padding: 7px 2px 2px;
}

/* ---- daily history -------------------------------------------------------- */
.challenge-history {
    display: flex;
    flex-direction: column;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 9px;
    overflow: hidden;
}

.challenge-hist-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 5px 12px;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
    font-size: 13px;
    background: var(--mix-surface);
}

.challenge-hist-row:nth-child(even) {
    background: var(--mix-surface-muted);
}

.challenge-hist-row:last-child {
    border-bottom: 0;
}

.challenge-hist-date {
    color: var(--mix-ink-muted);
    min-width: 58px;
}

.challenge-hist-chart {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 1;
    min-width: 0;
}

.challenge-hist-chart a {
    color: var(--mix-ink);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.challenge-limbo-tag {
    background: var(--mix-secondary);
    color: var(--mix-bg);
    font-size: 9.5px;
    font-weight: 700;
    border-radius: 3px;
    padding: 0 5px;
    text-transform: uppercase;
}

.challenge-hist-place {
    min-width: 74px;
    text-align: right;
}

.challenge-hist-score {
    min-width: 118px;
    display: flex;
    justify-content: flex-end;
}

/* ---- legend --------------------------------------------------------------- */
.challenge-legend {
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    background: var(--mix-surface);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 9px;
    padding: 12px 15px;
}

.challenge-legend h3 {
    margin: 0 0 6px;
    font-size: 1rem;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    letter-spacing: .06em;
}

.challenge-ladder {
    display: grid;
    grid-template-columns: auto auto;
    gap: 1px 14px;
    font-size: 13px;
    align-items: center;
}

.challenge-rules {
    max-width: 42ch;
    color: var(--mix-ink-muted);
    font-size: 12.5px;
    margin: 0;
    padding-left: 18px;
}

.challenge-rules li {
    margin-bottom: 4px;
}

/* ---- mobile dock (jump links + reset countdown) --------------------------- */
.challenge-dock {
    display: flex;
    gap: 14px;
    align-items: center;
    font-size: 13px;
}

.challenge-dock a {
    color: var(--mix-ink);
    text-decoration: none;
    text-transform: uppercase;
}

.challenge-dock .reset {
    margin-left: auto;
    color: var(--mix-ink-muted);
    font-size: 12px;
}

/* /UploadPhoenixScores - the manual-import expander's numbered steps. */
.import-manual-steps {
    margin: 0;
    padding-left: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* ============================================================
   The 404 page - "your path was a MISS" (Pages/NotFound.razor).
   The title-screen image is the hero; the judgment slams over
   its lower edge like the in-game MISS flash. Judgment red is
   semantic (a judgment, not the mix accent); the credit counter
   mirrors the arcade credit line in the source frame.
   ============================================================ */
.nf-eyebrow {
    text-align: center;
    font-size: .68rem;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin: 28px 0 14px;
}

.nf-stage {
    position: relative;
    max-width: 860px;
    margin: 0 auto;
}

.nf-frame {
    display: block;
    width: 100%;
    border-radius: 10px;
    box-shadow: 0 30px 80px -20px rgba(196, 15, 61, .45);
}

.nf-judgment {
    position: relative;
    /* Only the MISS's top ~20% rides over the frame — any deeper covers the title text. */
    margin-top: clamp(-26px, -3vw, -12px);
    text-align: center;
    pointer-events: none;
}

.nf-miss {
    display: block;
    font-family: Impact, "Arial Black", sans-serif;
    font-style: italic;
    font-size: clamp(4.2rem, 15vw, 8.5rem);
    line-height: .92;
    letter-spacing: .04em;
    transform: skewX(-8deg) rotate(-2deg);
    background: linear-gradient(180deg, #ff8f9f 4%, #ff2f4e 42%, #a30822 96%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    filter: drop-shadow(0 0 22px rgba(255, 47, 78, .55)) drop-shadow(0 6px 0 rgba(20, 2, 8, .9));
}

@media (prefers-reduced-motion: no-preference) {
    .nf-miss {
        animation: nf-slam .34s cubic-bezier(.2, 1.6, .35, 1) .18s both;
    }

    @keyframes nf-slam {
        0% { opacity: 0; transform: skewX(-8deg) rotate(-2deg) scale(1.9); }
        70% { opacity: 1; transform: skewX(-8deg) rotate(-2deg) scale(.96); }
        100% { opacity: 1; transform: skewX(-8deg) rotate(-2deg) scale(1); }
    }
}

.nf-explain {
    max-width: 46ch;
    margin: 18px auto 0;
    text-align: center;
    color: var(--mix-ink-muted);
    font-size: .95rem;
    line-height: 1.55;
    text-wrap: balance;
}

.nf-actions {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 26px;
}

.nf-credit {
    margin: clamp(36px, 7vh, 64px) 0 24px;
    text-align: center;
    font-family: Consolas, "Courier New", monospace;
    font-size: .8rem;
    letter-spacing: .3em;
    color: #ffd94d;
    text-shadow: 0 0 12px rgba(255, 217, 77, .35);
}

/* ===== Charts SRP (docs/design/charts-srp.md) ================================
   The page stack: header (title + scope) → query chips → answer line → results.
   Tokens only — the two ramps and --mix-* carry every color. */
.srp-head {
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.srp-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    min-height: 34px;
}

/* An applied-filter token is dismissed occasionally rather than hunted for, so it sits a
   little under the drawer chips' 40px — but its ✕ is still a real target, not a 16px icon. */
.srp-chip {
    min-height: 36px;
    font-size: .8rem;
}

    .srp-chip .mud-chip-close-button {
        width: 28px;
        height: 28px;
        margin-left: 2px;
    }

        .srp-chip .mud-chip-close-button .mud-icon-root {
            font-size: 1.1rem;
        }

.srp-chip-sort {
    border-color: var(--mix-accent) !important;
}

/* The count and the controls. Six targets plus the count are wider than a phone, so the
   row wraps — the controls stay one block, right-aligned, and drop to their own line
   rather than pushing the page sideways. */
.srp-answer {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 4px 0 12px;
}

.srp-answer-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: auto;
}

.srp-count {
    font-variant-numeric: tabular-nums;
}

.srp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
    gap: 12px;
}

.srp-pager {
    display: flex;
    justify-content: center;
    margin: 18px 0 8px;
}

.srp-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 48px 0;
    color: var(--mix-ink-muted);
}

/* min-width:0 is load-bearing, not tidying. A grid item's automatic minimum size is its
   MIN-CONTENT width, and the card's title is `nowrap` — so one long song name ("Extreme
   Music School 2nd period feat. Nanahira", 482px) floored the whole column at its width,
   stretched every other card to match, and scrolled the page sideways. Letting the card
   shrink is also what lets the title's ellipsis do its job. */
.srp-card {
    position: relative;
    display: flex;
    min-width: 0;
    gap: 12px;
    background: var(--mix-surface);
    border: 1px solid var(--mix-surface-muted);
    border-radius: 10px;
    padding: 12px;
    transition: border-color .15s, box-shadow .15s;
}

.srp-card:hover,
.srp-card:focus-within {
    border-color: var(--mix-primary);
    box-shadow: 0 0 14px var(--mix-glow);
}

.srp-card-link {
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: 10px;
}

.srp-card-art {
    flex: 0 0 auto;
}

.srp-card-main {
    flex: 1;
    min-width: 0;
}

.srp-card-title {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.srp-card-song {
    font-weight: 600;
    font-size: 1.05rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.srp-card-songtype {
    font-size: .7rem;
    color: var(--mix-ink-muted);
    white-space: nowrap;
}

.srp-card-artist {
    font-size: .75rem;
    color: var(--mix-ink-muted);
}

.srp-card-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 6px;
    align-items: center;
}

.srp-card-tier {
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .03em;
    border: 1px solid;
    border-radius: 5px;
    padding: 1px 7px;
    white-space: nowrap;
}

.srp-card-facts {
    margin-top: 7px;
    font-size: .72rem;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
    display: flex;
    flex-wrap: wrap;
    gap: 3px 10px;
}

.srp-card-fact-lead {
    color: var(--mix-ink);
    font-weight: 600;
}

.srp-card-my {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 3px;
    min-width: 70px;
    text-align: right;
}

.srp-card-unplayed {
    font-size: .7rem;
    color: var(--mix-ink-muted);
    border: 1px dashed var(--mix-surface-muted);
    border-radius: 4px;
    padding: 2px 7px;
}

.srp-card-plate {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .05em;
}

.srp-card-score {
    font-size: .75rem;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.srp-card-actions {
    position: absolute;
    right: 8px;
    bottom: 6px;
    z-index: 2;
    display: flex;
    gap: 2px;
}

.srp-drawer {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.srp-drawer-head {
    display: flex;
    align-items: center;
}

.srp-drawer-range {
    display: flex;
    gap: 10px;
}

/* The bottom way out, separated from the last facet so it doesn't read as one more
   filter. */
.srp-drawer-foot {
    border-top: 1px solid var(--mix-surface-muted);
    padding-top: 12px;
}

@media (max-width: 600px) {
    /* minmax(0, …), not a bare 1fr: `1fr` is minmax(auto, 1fr) and that `auto` floors the
       track at the widest card's min-content, which is how the one-column phone layout
       ended up wider than the phone. */
    .srp-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .srp-head {
        gap: 12px;
    }
}

/* The bottom nav outranks the drawer, so the drawer's close button has to clear it —
   only where the nav exists (the same Md seam the shell uses). */
@media (max-width: 959.98px) {
    .srp-drawer-foot {
        padding-bottom: calc(var(--bottom-nav-h) + 12px);
    }
}

/* SRP card state borders — the tier lists' owner-locked language */
.srp-card-pass {
    border-color: var(--mud-palette-success);
}

.srp-card-todo {
    border-style: dashed;
    border-color: var(--mud-palette-info);
}

.srp-head-mix {
    color: var(--mix-ink-muted);
    font-size: .9rem;
    letter-spacing: .04em;
    text-transform: uppercase;
}

/* SRP drawer: badge cloud + switch rows */
.srp-drawer-sub {
    font-size: .65rem;
    color: var(--mix-ink-muted);
    text-transform: none;
    letter-spacing: 0;
}

.srp-badge-cloud {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Skill tags borrow the tier list's chip, which is sized to sit quietly on a card. Here
   each one is something you tap, so the SRP's copy takes the same 40px target as the
   other filter chips while keeping the category tint. */
.srp-badge-opt {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0 12px;
    font-size: .8rem;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    cursor: pointer;
    opacity: .75;
}

.srp-badge-opt:hover,
.srp-badge-opt:focus-visible {
    opacity: 1;
}

.srp-badge-opt-sel {
    opacity: 1;
    outline: 1px solid var(--mix-primary);
}

.srp-card-stepartist {
    color: var(--mix-ink-muted);
}

/* SRP export dialog */
.srp-export {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.srp-export-count {
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.srp-export-columns {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

.srp-export-hint {
    color: var(--mix-ink-muted);
}

.srp-export-file {
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
    border-top: 1px solid var(--mix-surface-muted);
    padding-top: 8px;
}

/* The shared table shell: the tier lists' table density and the chart SRP's both render
   it, so it lives here rather than in either page. The wrap is what side-scrolls — a
   ten-column table on a phone must move inside its own box, never take the page with it. */
.tier-table-wrap {
    overflow-x: auto;
    max-width: 100%;
}

.tier-table {
    width: 100%;
    border-collapse: collapse;
}

.tier-table th {
    text-align: left;
    color: var(--mud-palette-text-secondary);
    font-size: .75rem;
    padding: 4px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.tier-table td {
    padding: 4px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* SRP densities: sticker sheet + table. The sheet itself is the tier lists'
   .tier-card-grid.tier-card-grid-compact — the tiles take their width from that grid. */
.srp-table .srp-th-sortable {
    cursor: pointer;
    white-space: nowrap;
}

.srp-table .srp-th-sorted {
    color: var(--mix-ink);
    border-bottom: 2px solid var(--mix-accent);
}

.srp-table-link {
    color: var(--mix-ink);
    font-weight: 600;
}

.srp-table-link:hover {
    color: var(--mix-primary);
}

.srp-table-muted {
    color: var(--mix-ink-muted);
}

.srp-table-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* SRP drawer facets: chip sets, range-slider headers, debut-mix eras */
.srp-facet {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.srp-facet-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: .75rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.srp-facet-value {
    text-transform: none;
    letter-spacing: 0;
    color: var(--mix-ink);
    font-variant-numeric: tabular-nums;
}

.srp-chipset {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.srp-chipset-sub {
    padding-left: 10px;
    border-left: 2px solid var(--mix-surface-muted);
}

/* A filter chip is the drawer's primary control, and a thumb is about 9mm wide: these
   sit at the 40px target rather than the 22px the type alone would give them. The
   drawer is 420px, so a row still fits two or three of the longest names. */
.srp-facet-chip {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    font-size: .85rem;
    border: 1px solid var(--mix-surface-muted);
    border-radius: 999px;
    padding: 0 14px;
    color: var(--mix-ink-muted);
    cursor: pointer;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition: border-color .12s, color .12s, background-color .12s;
}

.srp-facet-chip:hover,
.srp-facet-chip:focus-visible {
    color: var(--mix-ink);
    border-color: var(--mix-primary);
}

/* A plate chip wears its own plate colour, so the row reads as the plate ladder it is rather
   than five identical pills. --plate-chip is set inline from ThemeScales.PlateColor. */
.srp-facet-chip[style*="--plate-chip"] {
    color: color-mix(in srgb, var(--plate-chip) 62%, var(--mix-ink));
    border-color: color-mix(in srgb, var(--plate-chip) 50%, transparent);
}

    .srp-facet-chip[style*="--plate-chip"].srp-facet-chip-on {
        color: var(--mix-primary-contrast);
        background: var(--plate-chip);
        border-color: var(--plate-chip);
    }

.srp-facet-chip-on {
    color: var(--mix-primary-contrast);
    background: var(--mix-primary);
    border-color: var(--mix-primary);
    font-weight: 600;
}

.srp-era {
    margin-top: 6px;
}

.srp-era-name {
    font-size: .68rem;
    color: var(--mix-ink-muted);
    margin-bottom: 3px;
}

/* ── The leaderboard skin ─────────────────────────────────────────────────────
   The Official Leaderboards rankings board is the golden standard for every
   ranked collection on the site, so its vocabulary lives here rather than in
   the section's own <style> block: the Communities boards wear the same look.
   Names keep their olb- prefix — the Official pages and the E2E suite pin them. */

/* Rankings and chart boards render as compact card rows, never tables — a phone
   reads rank, player, and rating with zero side-scrolling (UX rule: tabular
   collections lean compact). */
.olb-rank-card, .olb-board-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    flex-wrap: wrap;
}

.olb-rank-rankbox { min-width: 52px; display: inline-flex; align-items: center; gap: 4px; }

/* Mud chips ship 4px of margin — inside a row that is already budgeting every
   pixel, that reads as a misalignment rather than as spacing. */
.olb-rank-card .mud-chip { margin: 0; }

.olb-board-place { min-width: 40px; font-weight: 700; }

.olb-rank-tail {
    margin-left: auto; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: flex-end; gap: 8px;
}

.olb-rank-expand { padding: 4px 0 10px; }

/* The column variant of the same row. A board carrying several figures per player
   reads as a pile when every figure is flush right, so the figures spread into
   their own columns instead: the owning page supplies the template in
   --olb-grid-cols (and --olb-grid-cols-narrow for the width where its optional
   columns drop out), and the identity column stays pinned left. */
.olb-grid-row, .olb-grid-head {
    display: grid;
    grid-template-columns: var(--olb-grid-cols);
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
}

.olb-grid-row .mud-chip { margin: 0; }

/* Column names, in the table-head voice the sortable boards already use. The header
   is the row template with labels in it, so it drops the same columns at the same
   widths; a label that outruns its column clips rather than reflowing the row. */
.olb-grid-head {
    color: var(--mix-ink-muted);
    font-size: 11.5px;
    letter-spacing: .4px;
    text-transform: uppercase;
    line-height: 1.25;
}

.olb-grid-head span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Figures are read down a column, so they align on their right edge. */
.olb-grid-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 2px;
}

/* Competitive level and PUMBILITY are two ordinary grid columns, never stacked (owner
   call) — the wrapper is display:contents so its two children sit in the template's cells
   directly, at every width. */
.olb-stack { display: contents; }

/* A label that has a short form: the long one until the row runs out of width. */
.olb-short-form { display: none; }

/* Board tags run long (LIKEASLAM01#8073). Lists print the human half — the digits
   identify an account, they don't name anyone — and truncate what's still too long;
   the full tag stays in the row's tooltip and on the player's own page. */
/* The flag is atomic and the name is what gives: a UserLabel truncated as one box
   spends the width on the flag and prints a bare "…", so the label lays out as a
   flex row whose last child — the name — is the only part allowed to shrink.
   min-width:0 is what permits that shrink; without it the text keeps its full
   width and the ellipsis swallows the whole name. */
.olb-player-name {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    vertical-align: middle;
    min-width: 0;
    max-width: 22ch;
    overflow: hidden;
}

.olb-player-name > :not(:last-child) { flex: 0 0 auto; }

.olb-player-name > :last-child {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
}

/* Every UserLabel, everywhere: flag then name, laid out so a bounded caller truncates
   the NAME. max-width keeps the label inside its container instead of overflowing as one
   atomic box — an overflowing atomic box is replaced wholesale by the container's
   ellipsis, which is how a flagged player used to render as a bare "…". */
.user-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    vertical-align: middle;
    min-width: 0;
    max-width: 100%;
}

.user-label > :not(:last-child) { flex: 0 0 auto; }

.user-label > :last-child {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
}

/* Inline-block, not block: this rule reaches every UserLabel on the site, and the
   label sits inline in most of them. It only truncates where a caller has bounded
   the width. */
.user-label-name {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* A "50× <grade art>" column head: the multiplier and the letter picture read as one
   token, so they never wrap apart. */
.olb-tier-head {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    white-space: nowrap;
}

.olb-delta-up { color: var(--mix-primary); font-weight: 700; }

.olb-delta-down { color: var(--mix-accent); font-weight: 700; }

.olb-delta-flat { color: var(--mix-ink-muted); }

/* The leaderboard skin for the collections that need real table semantics
   (sortable columns): same flat surface, hairlines, and row rhythm as the
   rankings cards — the site's one leaderboard look. */
.olb-board-table.mud-table { background: transparent; }

.olb-board-table .mud-table-cell {
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    padding: 4px 8px;
}

.olb-board-table .mud-table-head .mud-table-cell {
    color: var(--mix-ink-muted);
    font-size: 11.5px;
    letter-spacing: .4px;
    text-transform: uppercase;
}

.olb-board-table .mud-table-body .mud-table-row:hover .mud-table-cell {
    background: color-mix(in srgb, var(--mix-ink) 5%, transparent);
}

/* Row glow: the dashboard vocabulary — you blue, your opt-in crews green. */
.olb-row-me {
    background: color-mix(in srgb, var(--daily-you) 15%, transparent);
    box-shadow: inset 0 0 0 1.5px var(--daily-you);
    border-radius: 6px;
}

.olb-row-community {
    background: color-mix(in srgb, var(--daily-community) 13%, transparent);
    box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--daily-community) 60%, transparent);
    border-radius: 6px;
}

/* A board sheds width one column at a time: at 760 the sortable-table variant pins its
   row identifier while the rest side-scrolls and song titles step aside; the community
   grid then drops its play count at 600 and its playstyle chip at 500 (see those blocks
   below); at 500 the compact card rows tighten padding and long labels fall back to their
   short forms. Figures never stack — every value keeps its own column. */
@media (max-width: 760px) {
    .olb-hide-mobile { display: none !important; }

    .olb-song-text { display: none; }

    .olb-player-name { max-width: 16ch; }

    .olb-sticky-first td:first-child, .olb-sticky-first th:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        background: var(--mix-surface);
        max-width: 200px;
        overflow: hidden;
    }

    .olb-sticky-first td:first-child .mud-typography {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .olb-pager-tight .mud-table-pagination { padding-inline: 2px; }

    .olb-pager-tight .mud-table-pagination-caption { font-size: 11px; margin: 0 4px; }
}

/* The community grid sheds whole columns, never stacking its figures: at 600 the play
   count drops, at 500 the playstyle chip drops (no initials fallback — owner call). The
   header, built from the same template, loses the same columns at the same widths. */
@media (max-width: 600px) {
    .olb-grid-row, .olb-grid-head {
        grid-template-columns: var(--olb-grid-cols-600, var(--olb-grid-cols));
        gap: 6px;
        padding: 3px 4px;
    }

    /* Columns size to their content now, so the header sets smaller to not out-widen a figure. */
    .olb-grid-head { font-size: 10px; letter-spacing: .2px; }

    .olb-hide-narrow { display: none !important; }
}

@media (max-width: 500px) {
    .olb-grid-row, .olb-grid-head {
        grid-template-columns: var(--olb-grid-cols-500, var(--olb-grid-cols-600, var(--olb-grid-cols)));
    }

    .olb-hide-phone { display: none !important; }

    .olb-long-form { display: none; }

    .olb-short-form { display: inline; }

    .olb-rank-card, .olb-board-row { gap: 5px; padding: 3px 4px; }

    .olb-rank-rankbox { min-width: 42px; }

    .olb-rank-card .mud-chip {
        height: 20px;
        padding: 0 7px;
        font-size: 10.5px;
    }

    .olb-rank-card .mud-icon-button { padding: 2px; }

    .olb-first-tail, .olb-hero-listtail, .olb-rank-tail {
        flex-direction: column;
        align-items: flex-end;
        gap: 0;
    }
}

/* ============================================================================
   Life Calculator (/LifeCalculator) — docs/design/life-calculator-redesign.md
   The lifebar is the page's hero instrument: the visible bar (0-1000, the
   rainbow) and the overflow above it, drawn to true proportion.
   ============================================================================ */

.lc-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 18px 24px;
    flex-wrap: wrap;
    padding-bottom: 16px;
}

.lc-sub {
    margin: 7px 0 0;
    max-width: 56ch;
    color: var(--mix-ink-muted);
    font-size: .95rem;
    line-height: 1.5;
}

.lc-eyebrow {
    display: block;
    font-size: .68rem;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    font-weight: 600;
}

.lc-provenance {
    background: none;
    border: 1px solid color-mix(in srgb, var(--mix-accent) 45%, transparent);
    color: var(--mix-accent);
    border-radius: 2px;
    padding: 4px 9px;
    font: 600 .66rem/1.3 var(--font-body);
    letter-spacing: .09em;
    text-transform: uppercase;
    cursor: pointer;
    white-space: nowrap;
}

.lc-provenance-body {
    margin: 10px 0 0;
    padding: 10px 13px;
    border-left: 2px solid var(--mix-accent);
    background: var(--mix-surface);
    font-size: .85rem;
    line-height: 1.55;
    color: var(--mix-ink-muted);
    max-width: 74ch;
}

/* ---------- the bench ---------- */
.lc-bench {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    border-radius: 3px;
    padding: 18px 20px 20px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 232px;
    gap: 22px 26px;
}

.lc-bench-main {
    min-width: 0;
}

.lc-bench-head {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px 18px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.lc-level {
    display: flex;
    align-items: center;
    gap: 12px;
}

.lc-level-value {
    font-family: var(--font-display);
    font-size: 1.9rem;
    line-height: 1;
    font-weight: 700;
    min-width: 2.1ch;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.lc-level input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    width: clamp(120px, 20vw, 210px);
    height: 3px;
    border-radius: 2px;
    background: color-mix(in srgb, var(--mix-ink) 18%, transparent);
    cursor: pointer;
}

.lc-level input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: var(--mix-primary);
    border: none;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--mix-primary) 22%, transparent);
    cursor: pointer;
}

.lc-level input[type="range"]::-moz-range-thumb {
    width: 15px;
    height: 15px;
    border: none;
    border-radius: 50%;
    background: var(--mix-primary);
}

/* ---------- the readout ---------- */
.lc-readout {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

.lc-life {
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 6vw, 3.3rem);
    font-weight: 700;
    line-height: .95;
    font-variant-numeric: tabular-nums;
}

.lc-life-max {
    font-size: .95rem;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.lc-state {
    margin-left: auto;
    font-family: var(--font-display);
    font-size: .95rem;
    letter-spacing: .11em;
    text-transform: uppercase;
    padding: 2px 9px;
    border-radius: 2px;
}

.lc-state[data-state="overflow-full"] {
    color: var(--life-overflow);
    background: color-mix(in srgb, var(--life-overflow) 15%, transparent);
}

.lc-state[data-state="into-overflow"] {
    color: var(--life-r7);
    background: color-mix(in srgb, var(--life-r7) 15%, transparent);
}

.lc-state[data-state="ok"] {
    color: var(--mix-ink-muted);
    background: color-mix(in srgb, var(--mix-ink) 8%, transparent);
}

.lc-state[data-state="danger"] {
    color: var(--life-danger);
    background: color-mix(in srgb, var(--life-danger) 16%, transparent);
}

.lc-state[data-state="dead"] {
    color: var(--mix-bg);
    background: var(--life-danger);
}

/* ---------- the bar ---------- */
.lc-zones {
    display: flex;
    gap: 2px;
    margin-bottom: 5px;
}

.lc-zone-cap {
    font-size: .62rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-top: 1px solid color-mix(in srgb, var(--mix-ink) 16%, transparent);
    padding-top: 3px;
}

.lc-zone-cap b {
    color: var(--mix-ink);
    font-variant-numeric: tabular-nums;
}

.lc-zone-cap-overflow {
    border-top-color: color-mix(in srgb, var(--life-overflow) 42%, transparent);
    text-align: right;
}

.lc-track {
    position: relative;
    display: flex;
    gap: 2px;
    height: 52px;
    background: var(--mix-bg);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    padding: 3px;
    border-radius: 2px;
}

.lc-zone {
    position: relative;
    overflow: hidden;
    min-width: 2px;
}

.lc-zone::before {
    content: "";
    position: absolute;
    inset: 0;
    opacity: .1;
}

.lc-zone-visible::before {
    background: var(--life-rainbow);
}

.lc-zone-overflow::before {
    background: var(--life-overflow);
}

/* A multi-note press sweeps rather than snapping. The durations ride custom
   properties the page sets inline, so a x50 press can take longer than a x1 —
   pure CSS, which is what keeps it free on a server circuit. The two zones run in
   SEQUENCE, not together: gaining, the visible bar fills before the overflow starts;
   draining, the overflow empties first. Life crosses the zones in that order. */
.lc-fill {
    position: absolute;
    inset: 0;
}

.lc-fill-visible {
    background: var(--life-rainbow);
    transition: clip-path var(--lc-vis-sweep, .13s) linear var(--lc-vis-delay, 0s);
}

.lc-fill-overflow {
    background:
        repeating-linear-gradient(115deg, transparent 0 5px, color-mix(in srgb, var(--mix-bg) 55%, transparent) 5px 8px),
        linear-gradient(90deg, color-mix(in srgb, var(--life-overflow) 62%, transparent), var(--life-overflow));
    transition: clip-path var(--lc-overflow-sweep, .13s) linear var(--lc-overflow-delay, 0s);
}

.lc-glow {
    position: absolute;
    inset: -1px;
    pointer-events: none;
    border-radius: 2px;
    opacity: 0;
    transition: opacity .35s ease;
    box-shadow: inset 0 0 22px 2px color-mix(in srgb, var(--life-r7) 55%, transparent);
}

.lc-track[data-rainbow="true"] .lc-glow {
    opacity: 1;
}

.lc-track[data-danger="true"] {
    border-color: var(--life-danger);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--life-danger) 45%, transparent);
}

.lc-tick {
    position: absolute;
    top: -3px;
    bottom: -3px;
    width: 1px;
    background: color-mix(in srgb, var(--mix-ink) 55%, transparent);
    pointer-events: none;
}

.lc-tick-danger {
    background: var(--life-danger);
}

.lc-tick span {
    position: absolute;
    top: calc(100% + 3px);
    left: 0;
    transform: translateX(-50%);
    font-size: .6rem;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    white-space: nowrap;
}

.lc-tick-danger span {
    color: var(--life-danger);
}

.lc-scale {
    height: 15px;
}

/* ---------- judgment keys ---------- */
.lc-keys {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 6px;
    margin-top: 22px;
}

.lc-key {
    --lc-k: var(--mix-ink);
    position: relative;
    background: var(--mix-surface-muted);
    border: 1px solid color-mix(in srgb, var(--lc-k) 38%, transparent);
    border-bottom-width: 3px;
    border-bottom-color: var(--lc-k);
    border-radius: 3px;
    padding: 9px 6px 7px;
    cursor: pointer;
    color: var(--mix-ink);
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    transition: transform .07s ease, background .12s ease;
}

.lc-key:hover {
    background: color-mix(in srgb, var(--lc-k) 16%, var(--mix-surface-muted));
}

.lc-key:active {
    transform: translateY(2px);
    border-bottom-width: 1px;
    margin-bottom: 2px;
    background: color-mix(in srgb, var(--lc-k) 30%, var(--mix-surface-muted));
}

.lc-key-delta {
    font-family: var(--font-body);
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--lc-k);
    font-variant-numeric: tabular-nums;
}

.lc-key-hint {
    position: absolute;
    top: 3px;
    right: 5px;
    font-family: var(--font-body);
    font-size: .58rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--mix-ink-muted);
}

.lc-key-step {
    color: var(--lc-k);
    margin-left: 3px;
}

.lc-key-perfect {
    --lc-k: var(--judg-perfect);
}

.lc-key-great {
    --lc-k: var(--judg-great);
}

.lc-key-good {
    --lc-k: var(--judg-good);
}

.lc-key-bad {
    --lc-k: var(--judg-bad);
}

.lc-key-miss {
    --lc-k: var(--judg-miss);
}

/* ---------- step toggle + run buttons ---------- */
.lc-runs {
    display: flex;
    align-items: center;
    gap: 7px 10px;
    flex-wrap: wrap;
    margin-top: 11px;
}

.lc-runs-label {
    font-size: .63rem;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    font-weight: 600;
}

.lc-runs-gap {
    flex: 1 1 12px;
}

.lc-seg {
    display: inline-flex;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 18%, transparent);
    border-radius: 3px;
    overflow: hidden;
}

.lc-seg button {
    background: none;
    border: none;
    color: var(--mix-ink-muted);
    font: 600 .74rem/1.3 var(--font-body);
    padding: 5px 12px;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
}

.lc-seg button + button {
    border-left: 1px solid color-mix(in srgb, var(--mix-ink) 18%, transparent);
}

.lc-seg button[aria-pressed="true"] {
    background: var(--mix-primary);
    color: var(--mix-primary-contrast);
}

.lc-ghost {
    background: none;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 20%, transparent);
    color: var(--mix-ink-muted);
    border-radius: 2px;
    padding: 4px 10px;
    font: 600 .72rem/1.3 var(--font-body);
    cursor: pointer;
}

.lc-ghost:hover {
    color: var(--mix-ink);
    border-color: color-mix(in srgb, var(--mix-ink) 42%, transparent);
}

/* Phoenix 2's electric overflow effect: the note lights up when the state it
   describes is actually on screen. */
.lc-note {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 14px 0 0;
    font-size: .8rem;
    line-height: 1.45;
    color: var(--mix-ink-muted);
    max-width: 62ch;
    transition: color .25s ease;
}

.lc-bolt {
    flex: none;
    font-size: .95rem;
    opacity: .35;
    transition: opacity .25s ease, filter .25s ease;
}

.lc-note[data-live="true"] {
    color: var(--mix-ink);
}

.lc-note[data-live="true"] .lc-bolt {
    opacity: 1;
    filter: drop-shadow(0 0 6px var(--mix-accent));
}

/* ---------- telemetry rail ---------- */
.lc-tele {
    display: flex;
    flex-direction: column;
    gap: 13px;
    border-left: 1px solid color-mix(in srgb, var(--mix-ink) 10%, transparent);
    padding-left: 20px;
}

.lc-tele-label {
    display: block;
    font-size: .63rem;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    font-weight: 600;
}

.lc-tele-value {
    display: block;
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.lc-tele-miss {
    color: var(--judg-miss);
}

.lc-tele-note {
    display: block;
    font-size: .76rem;
    color: var(--mix-ink-muted);
    margin-top: 1px;
}

.lc-mult-meter {
    position: relative;
    height: 5px;
    margin-top: 6px;
    background: color-mix(in srgb, var(--mix-ink) 12%, transparent);
    border-radius: 3px;
    overflow: hidden;
}

.lc-mult-fill {
    position: absolute;
    inset: 0 auto 0 0;
    background: linear-gradient(90deg, color-mix(in srgb, var(--judg-perfect) 45%, transparent), var(--judg-perfect));
    transition: width var(--lc-sweep, .13s) linear;
}

/* ---------- sections ---------- */
.lc-section {
    margin-top: 34px;
}

.lc-section-head {
    display: flex;
    align-items: baseline;
    gap: 8px 14px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}

.lc-section-sub {
    margin: 0 0 14px;
    color: var(--mix-ink-muted);
    font-size: .9rem;
    line-height: 1.5;
    max-width: 70ch;
}

/* ---------- survival budget ---------- */
.lc-budget {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
}

.lc-bud {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    border-top: 2px solid var(--lc-bud-c, var(--mix-primary));
    border-radius: 3px;
    padding: 12px 13px 13px;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.lc-bud-miss {
    --lc-bud-c: var(--judg-miss);
}

.lc-bud-bad {
    --lc-bud-c: var(--judg-bad);
}

.lc-bud-value {
    font-family: var(--font-display);
    font-size: clamp(2rem, 4vw, 2.7rem);
    font-weight: 700;
    line-height: .95;
    font-variant-numeric: tabular-nums;
    display: flex;
    align-items: baseline;
    gap: 7px;
}

.lc-bud-unit {
    font-family: var(--font-body);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    line-height: 1.2;
}

.lc-bud-what {
    font-size: .86rem;
    line-height: 1.4;
    color: var(--mix-ink);
}

.lc-bud-bar {
    position: relative;
    height: 6px;
    background: var(--mix-bg);
    border-radius: 2px;
    overflow: hidden;
    margin-top: auto;
}

.lc-bud-bar i {
    position: absolute;
    inset: 0 auto 0 0;
    background: var(--life-rainbow);
}

.lc-bud-settle {
    font-size: .72rem;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
}

.lc-budget-note {
    margin: 11px 0 0;
    font-size: .82rem;
    color: var(--mix-ink-muted);
}

/* ---------- level ladder ---------- */
.lc-ladder {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    border-radius: 3px;
    padding: 14px 16px 16px;
}

.lc-ladder-head,
.lc-ladder-row {
    display: grid;
    grid-template-columns: 3ch minmax(0, 1fr) 7ch;
    gap: 12px;
}

.lc-ladder-head {
    font-size: .62rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    padding-bottom: 7px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
}

.lc-ladder-head span:last-child {
    text-align: right;
}

.lc-ladder-row {
    align-items: center;
    padding: 2px 0;
    background: none;
    border: none;
    width: 100%;
    color: inherit;
    font: inherit;
    cursor: pointer;
    text-align: left;
}

.lc-ladder-row:hover {
    background: color-mix(in srgb, var(--mix-ink) 5%, transparent);
}

.lc-ladder-row[data-current="true"] {
    background: color-mix(in srgb, var(--mix-primary) 13%, transparent);
    box-shadow: inset 2px 0 0 var(--mix-primary);
}

.lc-ladder-level {
    font-family: var(--font-display);
    font-size: .95rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: right;
    color: var(--mix-ink-muted);
}

.lc-ladder-row[data-current="true"] .lc-ladder-level {
    color: var(--mix-ink);
}

.lc-ladder-bar {
    display: flex;
    height: 9px;
    gap: 1px;
}

.lc-ladder-visible {
    background: var(--life-rainbow);
    opacity: .95;
}

.lc-ladder-overflow {
    background:
        repeating-linear-gradient(115deg, transparent 0 4px, color-mix(in srgb, var(--mix-surface) 70%, transparent) 4px 6px),
        color-mix(in srgb, var(--life-overflow) 78%, transparent);
}

.lc-ladder-max {
    font-size: .76rem;
    font-variant-numeric: tabular-nums;
    color: var(--mix-ink-muted);
    text-align: right;
}

.lc-ladder-row[data-current="true"] .lc-ladder-max {
    color: var(--mix-ink);
}

.lc-ladder-key {
    display: flex;
    gap: 18px;
    flex-wrap: wrap;
    margin-top: 12px;
    font-size: .76rem;
    color: var(--mix-ink-muted);
}

.lc-ladder-key i {
    display: inline-block;
    width: 22px;
    height: 8px;
    vertical-align: -1px;
    margin-right: 7px;
}

.lc-ladder-key i.lc-k-visible {
    background: var(--life-rainbow);
}

.lc-ladder-key i.lc-k-overflow {
    background:
        repeating-linear-gradient(115deg, transparent 0 4px, color-mix(in srgb, var(--mix-surface) 70%, transparent) 4px 6px),
        color-mix(in srgb, var(--life-overflow) 78%, transparent);
}

/* ---------- rules of thumb ---------- */
.lc-rules {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}

.lc-rule {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    border-radius: 3px;
    padding: 14px 15px 15px;
}

.lc-rule-value {
    font-family: var(--font-display);
    font-size: 2.1rem;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--lc-rule-c, var(--mix-ink));
}

.lc-rule h3 {
    font-size: 1.08rem;
    letter-spacing: .02em;
    margin: 8px 0 5px;
}

.lc-rule p {
    margin: 0;
    font-size: .87rem;
    line-height: 1.5;
    color: var(--mix-ink-muted);
}

.lc-rule-miss {
    --lc-rule-c: var(--judg-miss);
}

.lc-rule-bad {
    --lc-rule-c: var(--judg-bad);
}

.lc-rule-perfect {
    --lc-rule-c: var(--judg-perfect);
}

.lc-rule-good {
    --lc-rule-c: var(--judg-good);
}

/* ---------- mechanics ---------- */
.lc-mech {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}

.lc-mech-col {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    border-radius: 3px;
    padding: 14px 15px 15px;
}

.lc-mech-col h3 {
    font-size: 1.05rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    margin: 0 0 9px;
}

.lc-mech-gain {
    color: var(--judg-perfect);
}

.lc-mech-loss {
    color: var(--judg-miss);
}

.lc-mech-mult {
    color: var(--mix-accent);
}

.lc-mech-col ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.lc-mech-col li {
    font-size: .87rem;
    line-height: 1.5;
    color: var(--mix-ink-muted);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 10px;
    align-items: baseline;
}

.lc-mech-col li b {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 700;
    color: var(--mix-ink);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.lc-formula {
    margin: 11px 0 0;
    padding-top: 10px;
    border-top: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace;
    font-size: .74rem;
    line-height: 1.5;
    color: var(--mix-ink-muted);
    word-break: break-word;
}

/* ---------- footer ---------- */
.lc-foot {
    margin-top: 36px;
    padding-top: 18px;
    border-top: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 20px 30px;
    align-items: start;
}

.lc-quote {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.5rem;
    line-height: 1.15;
    color: var(--mix-ink);
}

.lc-quote cite {
    display: block;
    margin-top: 5px;
    font-family: var(--font-body);
    font-size: .78rem;
    font-style: normal;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

/* ===== /Titles =====
   Titles are ladders, so the page draws one rail per ladder rather than one row per title
   (docs/design/titles-overhaul.md). Tokens only: this page carries no colour-literal
   allowance and is not to acquire one. */

/* The shell leaves the page flush against the nav, and this one opens on a panel edge or a
   section rule rather than on a heading, so it owes itself the breathing room. */
.title-standing,
.title-anon,
.title-skeleton {
    margin-top: 16px;
}

.title-standing {
    display: grid;
    grid-template-columns: minmax(230px, 1fr) minmax(250px, 1fr);
    gap: 14px 30px;
    align-items: center;
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 10%, transparent);
    border-radius: 4px;
    padding: 14px 16px;
    margin-bottom: 20px;
}

.title-eyebrow {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin: 0 0 6px;
}

.title-worn {
    font-family: var(--font-display);
    font-size: clamp(26px, 6vw, 44px);
    font-weight: 700;
    line-height: 1;
    margin: 0;
    color: var(--mix-ink);
    text-wrap: balance;
}

.title-worn-note {
    color: var(--mix-ink-muted);
    font-size: 13.5px;
    margin: 8px 0 0;
}

.title-tally {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 5px;
}

.title-tally-num {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 30px;
    line-height: 1;
    color: var(--mix-ink);
    font-variant-numeric: tabular-nums;
}

.title-tally-of {
    font-size: 13px;
    color: var(--mix-ink-muted);
}

.title-meter {
    height: 10px;
    border-radius: 2px;
    background: color-mix(in srgb, var(--mix-ink) 9%, transparent);
    overflow: hidden;
}

.title-meter i {
    display: block;
    height: 100%;
    background: var(--mix-primary);
    box-shadow: 0 0 8px var(--mix-glow);
}

.title-meter-legend {
    font-size: 12px;
    color: var(--mix-ink-muted);
    margin-top: 6px;
}

.title-anon {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-primary) 40%, transparent);
    border-radius: 4px;
    padding: 12px 16px;
    margin-bottom: 18px;
}

.title-anon p {
    margin: 0;
    flex: 1 1 260px;
    font-size: 14px;
    color: var(--mix-ink);
}

/* Filter furniture sits above the list and never sticks (UX rule 6). */
.title-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    padding: 9px 0;
    border-top: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    margin-bottom: 18px;
}

.title-search {
    flex: 1 1 190px;
    min-width: 150px;
    margin: 0;
}

.title-chips {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.title-chip {
    font: inherit;
    font-size: 13px;
    background: transparent;
    color: var(--mix-ink-muted);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 20%, transparent);
    border-radius: 999px;
    padding: 2px 12px;
    cursor: pointer;
    transition: color .15s, border-color .15s, background .15s;
}

.title-chip:hover {
    color: var(--mix-ink);
    border-color: color-mix(in srgb, var(--mix-ink) 40%, transparent);
}

.title-chip.on {
    background: color-mix(in srgb, var(--mix-primary) 20%, transparent);
    border-color: var(--mix-primary);
    color: var(--mix-ink);
    font-weight: 600;
}

.title-chip .n {
    opacity: .65;
    margin-left: 5px;
    font-variant-numeric: tabular-nums;
}

.title-section {
    margin: 0 0 26px;
}

.title-section-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding-bottom: 5px;
    margin-bottom: 10px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 14%, transparent);
}

.title-section-head h2 {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--mix-ink);
    margin: 0;
}

.title-section-count {
    font-size: 12.5px;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
    margin-left: auto;
    white-space: nowrap;
}

.title-rails {
    display: flex;
    flex-direction: column;
}

/* Boss breakers are one short rail per mix, so they tile instead of stacking. */
/* Boss breakers are one short rail per mix. The mix name sits ABOVE its buttons rather than
   beside them: side by side, a long mix name and a 150px button fought over a 190px cell and
   the name lost, truncating to nothing. Stacked, every cell also gets the same button width
   for free — the labels are chart data rather than UI strings, so they are the same two
   near-identical widths in every language, which is what made them look misaligned. */
.title-rails.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 4px 18px;
    align-items: start;
}

.title-rail {
    display: grid;
    grid-template-columns: 168px 1fr auto;
    align-items: center;
    gap: 4px 14px;
    padding: 7px 6px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
}

.title-rails.grid .title-rail {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 6px 6px 10px;
}

.title-rails.grid .title-rail-track {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
}

/* Identical width per cell, so a column of them reads as a column. */
.title-rails.grid .title-pip.wide {
    width: 100%;
    min-width: 0;
    justify-content: center;
}

.title-rail:last-child {
    border-bottom: 0;
}

.title-rail:hover {
    background: color-mix(in srgb, var(--mix-ink) 4%, transparent);
}

.title-rail-name {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 600;
    letter-spacing: .04em;
    line-height: 1.1;
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
}

.title-rail-name > span:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Stacked, the mix name owns the full cell width and no longer needs to truncate. */
.title-rails.grid .title-rail-name > span:first-child {
    overflow: visible;
    white-space: normal;
}

.title-rails.grid .title-rail-name {
    font-size: 14px;
    letter-spacing: .1em;
    color: var(--mix-ink-muted);
}

.title-rail-track {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}

.title-rail-tail {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 700;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.title-rail-tail b {
    color: var(--mix-ink);
}

.title-rails.grid .title-rail-tail {
    display: none;
}

.title-pip {
    position: relative;
    width: 32px;
    height: 30px;
    flex: 0 0 auto;
    border-radius: 3px;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 20%, transparent);
    background: transparent;
    color: var(--mix-ink-muted);
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    overflow: hidden;
    transition: transform .12s ease, border-color .15s, box-shadow .15s;
}

.title-pip:hover {
    transform: translateY(-2px);
    border-color: var(--mix-ink);
    z-index: 2;
}

.title-pip:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
    z-index: 2;
}

.title-pip > span {
    position: relative;
    z-index: 1;
}

.title-pip.wide {
    width: auto;
    min-width: 62px;
    padding: 0 9px;
    font-size: 13px;
    letter-spacing: .06em;
}

.title-pip.earned {
    border-color: color-mix(in srgb, var(--mix-primary) 62%, transparent);
    background: color-mix(in srgb, var(--mix-primary) 17%, transparent);
    color: var(--mix-ink);
}

.title-pip.pg {
    border-color: var(--plate-pg);
    box-shadow: 0 0 8px color-mix(in srgb, var(--plate-pg) 45%, transparent);
}

.title-pip.active {
    border-color: var(--mix-accent);
    color: var(--mix-ink);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--mix-accent) 30%, transparent);
}

/* The fill is this rung's own climb from the rung below it. */
.title-pip.active::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--fill, 0%);
    background: color-mix(in srgb, var(--mix-accent) 30%, transparent);
    z-index: 0;
}

.title-pip.locked {
    border-color: color-mix(in srgb, var(--mix-ink) 15%, transparent);
    color: color-mix(in srgb, var(--mix-ink) 34%, transparent);
}

.title-pip.official {
    border-style: dashed;
}

/* One-offs: titles with no ladder behind them. Name colour is how many players hold it,
   and the glow ramp orders the bands where hue cannot. */
.title-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.title-badge {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 11px 4px 8px;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 18%, transparent);
    border-radius: 3px;
    background: color-mix(in srgb, var(--mix-ink) 4%, transparent);
    font: inherit;
    color: var(--mix-ink);
    cursor: pointer;
    transition: transform .12s, border-color .15s;
}

.title-badge:hover {
    transform: translateY(-1px);
    border-color: color-mix(in srgb, var(--mix-ink) 45%, transparent);
}

.title-badge:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
}

.title-badge.official {
    border-style: dashed;
}

.title-badge-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: 0 0 auto;
    background: var(--band);
}

.title-badge-name {
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: .03em;
    color: var(--band);
}

.title-badge.owned {
    border-color: color-mix(in srgb, var(--mix-primary) 55%, transparent);
    background: color-mix(in srgb, var(--mix-primary) 12%, transparent);
}

.title-badge.unowned {
    opacity: .42;
}

.title-badge.unowned .title-badge-name {
    color: var(--mix-ink-muted);
}

.title-empty {
    color: var(--mix-ink-muted);
    padding: 12px 0;
}

/* Loading looks like the layout it becomes (UX rule 9), not a lone spinner. */
.title-skeleton {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 12px;
}

.title-skeleton-rail {
    height: 44px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--mix-ink) 7%, transparent);
    animation: title-skeleton-pulse 1.4s ease-in-out infinite;
}

@keyframes title-skeleton-pulse {
    0%, 100% {
        opacity: 1;
    }

    50% {
        opacity: .55;
    }
}

/* ---- the detail drawer ---- */
.title-drawer {
    display: flex;
    flex-direction: column;
    height: 100%;
    color: var(--mix-ink);
}

.title-drawer-head {
    position: relative;
    padding: 14px 16px 10px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 14%, transparent);
    flex: 0 0 auto;
}

.title-drawer-eyebrow {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.lc-foot-src {
    font-size: .84rem;
    line-height: 1.55;
    color: var(--mix-ink-muted);
}

.lc-foot-src a {
    color: var(--mix-primary);
}

/* ---------- narrow widths ---------- */
@media (max-width: 959.98px) {
    .lc-bench {
        grid-template-columns: minmax(0, 1fr);
    }

    .lc-tele {
        border-left: none;
        border-top: 1px solid color-mix(in srgb, var(--mix-ink) 10%, transparent);
        padding-left: 0;
        padding-top: 15px;
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
        gap: 14px 18px;
    }

    .lc-budget {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .lc-rules {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .lc-mech {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 639.98px) {
    .lc-track {
        height: 40px;
    }

    .lc-bench {
        padding: 14px 13px 16px;
    }

    .lc-rules {
        grid-template-columns: minmax(0, 1fr);
    }

    .lc-foot {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 479.98px) {
    .lc-keys {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .lc-budget {
        grid-template-columns: minmax(0, 1fr);
    }
}

.title-drawer-head h3 {
    font-family: var(--font-display);
    font-size: 27px;
    font-weight: 700;
    line-height: 1.05;
    margin: 2px 0 4px;
    padding-right: 40px;
}

.title-drawer-close {
    position: absolute;
    top: 8px;
    right: 10px;
}

.title-drawer-body {
    padding: 12px 16px 24px;
    overflow-y: auto;
    flex: 1 1 auto;
}

.title-req {
    font-size: 14px;
    background: color-mix(in srgb, var(--mix-ink) 6%, transparent);
    border-left: 2px solid var(--mix-primary);
    padding: 7px 10px;
    margin: 0 0 14px;
}

.title-note {
    font-size: 12.5px;
    color: var(--mix-ink-muted);
    border: 1px dashed color-mix(in srgb, var(--mix-ink) 26%, transparent);
    border-radius: 3px;
    padding: 7px 9px;
    margin: 0 0 14px;
}

.title-label {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin: 16px 0 6px;
}

.title-bar {
    height: 9px;
    border-radius: 2px;
    background: color-mix(in srgb, var(--mix-ink) 10%, transparent);
    overflow: hidden;
}

.title-bar i {
    display: block;
    height: 100%;
    background: var(--mix-accent);
}

.title-bar.done i {
    background: var(--rarity-emerald);
}

.title-figures {
    display: flex;
    justify-content: space-between;
    font-size: 12.5px;
    color: var(--mix-ink-muted);
    margin-top: 4px;
    font-variant-numeric: tabular-nums;
}

.title-figures b {
    color: var(--mix-ink);
}

.title-hint {
    font-size: 12.5px;
    color: var(--mix-ink-muted);
    margin: 6px 0 0;
}

.title-hint b {
    color: var(--mix-ink);
}

.title-suggest {
    display: flex;
    align-items: center;
    gap: 10px;
    background: color-mix(in srgb, var(--mix-primary) 10%, transparent);
    border-left: 2px solid var(--mix-primary);
    padding: 8px 10px;
}

.title-suggest-folder {
    font-family: var(--font-display);
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    color: var(--mix-primary);
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
}

.title-suggest-ask {
    font-size: 13px;
    line-height: 1.35;
}

.title-rarity {
    display: flex;
    align-items: baseline;
    gap: 9px;
}

.title-rarity-pct {
    font-family: var(--font-display);
    font-size: 31px;
    font-weight: 700;
    line-height: 1;
    color: var(--band);
}

.title-holders {
    display: flex;
    flex-direction: column;
}

@media (max-width: 860px) {
    .title-standing {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 700px) {
    .title-standing {
        gap: 10px;
        padding: 11px 12px;
        margin-bottom: 14px;
    }

    .title-worn {
        font-size: clamp(24px, 8vw, 34px);
    }

    .title-controls {
        padding: 7px 0;
        margin-bottom: 12px;
        gap: 6px 8px;
    }

    .title-search {
        flex: 1 1 100%;
    }

    .title-chip {
        padding: 2px 9px;
        font-size: 12.5px;
    }

    .title-section {
        margin-bottom: 20px;
    }

    /* The rail wraps onto its own row; it never side-scrolls. */
    .title-rail {
        grid-template-columns: 1fr auto;
        gap: 3px 10px;
        padding: 9px 4px;
    }

    .title-rail-name {
        grid-column: 1;
    }

    .title-rail-tail {
        grid-column: 2;
    }

    .title-rail-track {
        grid-column: 1 / -1;
        margin-top: 2px;
    }
}

/* Filtered out, not removed: a ladder with holes punched through it stops reading as a
   ladder, so a non-matching rung fades in place. */
.title-pip.dim {
    opacity: .16;
    pointer-events: none;
}

.title-badge.dim {
    opacity: .16;
    pointer-events: none;
}

/* ── Folder levels (docs/design/folder-level-progression.md): a folder is two numbers, and
   these are the two ways it renders. The chip carries the grade in its metal with the glow
   stepping by completion tier; the spectrum lays the whole folder out best-first so length
   reads as completion and hue reads as quality. All colour arrives as tokens — the grade
   metals via --grade-*, everything unplayed via --unplayed-grade. ── */
.fl-chip {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    min-width: 58px;
    padding: 6px 7px 5px;
    border-radius: 9px;
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
}

.fl-chip-grade {
    font-size: 23px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: .01em;
}

.fl-chip-pct,
.fl-chip-count {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .07em;
    color: var(--mix-ink-muted);
}

.fl-chip-count {
    font-size: 15px;
    color: var(--unplayed-grade);
}

/* A lamped folder is ringed in its own grade metal — the trophy state, and the one rung
   content growth can take back. */
.fl-lamped {
    border-color: currentColor;
    box-shadow: 0 0 0 1px currentColor, 0 0 16px -4px currentColor;
}

.fl-spectrum {
    width: 100%;
}

.fl-track {
    position: relative;
    height: 18px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--mix-bg) 55%, #000);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
}

.fl-slim .fl-track {
    height: 11px;
    border-radius: 7px;
}

.fl-chunky .fl-track {
    height: 22px;
    border-radius: 11px;
}

.fl-fill {
    position: absolute;
    inset: 1px;
    border-radius: 9px;
}

.fl-slim .fl-fill {
    border-radius: 6px;
}

.fl-chunky .fl-fill {
    border-radius: 10px;
}

/* Ticks are cut out of the bar rather than drawn over it, so they read at every fill colour. */
.fl-tick {
    position: absolute;
    top: -4px;
    bottom: -4px;
    width: 2px;
    border-radius: 1px;
    background: var(--mix-bg);
}


/* The tier list's folder standing: one line and the bar, sitting under the title track. */
.fl-header {
    display: grid;
    gap: 8px;
    margin: 0 0 16px;
    padding: 2px 2px 4px;
}

.fl-header-line {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: .02em;
    line-height: 1.1;
}

.fl-header-dot {
    color: var(--mix-ink-muted);
    font-weight: 400;
    margin: 0 4px;
}

/* Folder Levels widget: a 1x1 gives one folder the whole cell, everything wider stacks rows. */
.dash-fl-hero {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    text-align: center;
}

.dash-fl-hero-grade {
    font-family: var(--font-display);
    font-size: 40px;
    font-weight: 700;
    line-height: 1;
}

.dash-fl-hero-pct {
    font-family: var(--font-display);
    font-size: 13px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.dash-fl-hero-bar {
    width: 100%;
}

.dash-fl-hero-left {
    font-family: var(--font-display);
    font-size: 11px;
    color: var(--mix-ink-muted);
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
}

.dash-fl-rows {
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
    justify-content: center;
}

.dash-fl-row-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 5px;
}

.dash-fl-row-name {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.dash-fl-row-count {
    font-family: var(--font-display);
    font-size: 12px;
    color: var(--mix-ink-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-fl-row-grade {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 16px;
}

.dash-fl-row-pct {
    font-family: var(--font-display);
    font-size: 11px;
    letter-spacing: .05em;
    color: var(--mix-ink-muted);
    margin-left: 6px;
    font-variant-numeric: tabular-nums;
}

/* Vertical spectrum: the community profile stacks folders as columns, so the long axis
   flips and the fill grows from the base. Ticks become horizontal rules. */
.fl-vertical .fl-track {
    height: 100%;
    border-radius: 5px 5px 0 0;
}

.fl-vertical .fl-fill {
    border-radius: 4px 4px 0 0;
}

.fl-vertical .fl-tick {
    top: auto;
    bottom: 0;
    left: -4px;
    right: -4px;
    width: auto;
    height: 2px;
}


/* A lamped folder glows, in its own grade metal — a folder lamped at AA burns copper and one
   lamped at SSS+ burns ice-blue, so the glow says how well it was lamped and not only that it
   was. The hue arrives as currentColor from the component. There is deliberately no
   end-of-track marker: the track own end already IS 100%, so a flag there drew a finish line
   on top of the finish line. */
.fl-track-lamped {
    border-color: currentColor;
    box-shadow: 0 0 12px -2px currentColor;
}

/* Folder Levels config: the running count sits above the grid so a full widget explains
   itself before a tap does nothing. */
.fl-cfg-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-family: var(--font-display);
    font-size: 13px;
    letter-spacing: .04em;
    color: var(--mix-ink-muted);
    margin-bottom: 6px;
}

.fl-cfg-picks {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 10px;
}

/* The Select Folders popover anchor — same shape as the tier list's folder picker. */
.fl-cfg-anchor {
    position: relative;
    display: inline-block;
}

/* A folder grid at its host's cap: unpicked cells go quiet so the grid reads as full,
   while the picked ones stay live because removing is how you make room. */
.folder-picker-level:disabled {
    opacity: .35;
    cursor: not-allowed;
}

/* The 1x1 hero leads with the difficulty ball — nothing else in that cell names the folder. */
.dash-fl-hero > .mud-tooltip-root,
.dash-fl-hero > .difficulty-bubble {
    flex: none;
}

/* ===== Mix Changes — the mix diff =====
   The board wears the rankings-board skin (compact rows, hairline separators, no card per
   row) because that is the site's standard for any dense board. The one encoding this page
   adds is direction: warm means the game calls it harder, cool means easier, taken off the
   existing difficulty ramp so it is never the tier lists' red/green. Every direction colour
   is paired with an arrow and the printed delta. */
.mc {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.mc-head {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.mc-title {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1;
    letter-spacing: .01em;
}

.mc-sub {
    color: var(--mix-ink-muted);
    max-width: 52ch;
    margin-top: 5px;
}

.mc-mixpair {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.mc-mixsel {
    min-width: 168px;
    max-width: 220px;
}

.mc-tween {
    color: var(--mix-ink-muted);
}

.mc-lookup {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.mc-hint {
    font-size: .82rem;
    color: var(--mix-ink-muted);
}

.mc-notice {
    margin: 0;
}

/* ---- the answer card ---- */
.mc-answer {
    display: flex;
    gap: 13px;
    align-items: flex-start;
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 10%, transparent);
    border-left: 3px solid var(--mix-primary);
    border-radius: 5px;
    padding: 13px 15px;
}

.mc-answer-up {
    border-left-color: var(--diff-hard);
}

.mc-answer-down {
    border-left-color: var(--diff-overrated);
}

.mc-answer-new {
    border-left-color: var(--mix-accent);
}

.mc-answer-gone {
    border-left-color: var(--diff-overrated);
}

.mc-answer-same {
    border-left-color: color-mix(in srgb, var(--mix-ink) 20%, transparent);
}

.mc-answer-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.mc-answer-id {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.mc-answer-song {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.28rem;
    line-height: 1.12;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mc-answer-artist {
    font-size: .79rem;
    color: var(--mix-ink-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mc-verdict {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.06rem;
    line-height: 1.3;
    margin: 0;
}

.mc-moves {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.mc-move {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 13%, transparent);
    border-radius: 5px;
    padding: 4px 8px;
}

.mc-move-pinned {
    border-color: var(--mix-primary);
    box-shadow: 0 0 0 1px var(--mix-glow);
}

/* The earlier mix's bubble, stated as past tense. */
.mc-was {
    filter: grayscale(.5) brightness(.82);
    display: inline-flex;
}

.mc-arrow {
    color: var(--mix-ink-muted);
    font-size: .85rem;
}

.mc-delta {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: .86rem;
    font-variant-numeric: tabular-nums;
    min-width: 30px;
    text-align: right;
}

.mc-up {
    color: var(--diff-hard);
}

.mc-down {
    color: var(--diff-overrated);
}

.mc-quiet {
    font-size: .8rem;
    color: var(--mix-ink-muted);
}

.mc-restepped {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* What did NOT move is part of the answer, so it is always shown rather than hidden
   behind a toggle. */
.mc-unchanged {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.mc-unchanged-label {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
}

.mc-unchanged-list {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    align-items: center;
}

/* Note counts line up as a column across rows, so they get tabular figures. */
.mc-notes {
    font-variant-numeric: tabular-nums;
    font-size: .85rem;
    color: var(--mix-ink-muted);
    white-space: nowrap;
}

.mc-linkish {
    background: none;
    border: 0;
    padding: 0;
    color: var(--mix-secondary);
    cursor: pointer;
    font: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.mc-linkish:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
}

/* ---- tabs ---- */
.mc-tabs {
    display: flex;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 10%, transparent);
    overflow-x: auto;
}

.mc-tab {
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    padding: 9px 14px 8px;
    color: var(--mix-ink-muted);
    white-space: nowrap;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 1.02rem;
    letter-spacing: .02em;
    display: flex;
    align-items: baseline;
    gap: 7px;
}

.mc-tab-n {
    font-variant-numeric: tabular-nums;
    font-size: .86rem;
    opacity: .75;
}

.mc-tab[aria-selected="true"] {
    color: var(--mix-ink);
    border-bottom-color: var(--mix-primary);
}

.mc-tab:hover {
    color: var(--mix-ink);
}

.mc-tab:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: -2px;
}

/* ---- the folder picker and what narrows inside it ---- */
.mc-filters {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
    margin: 14px 0;
}

.mc-filters .folder-picker { margin-right: 4px; }

/* The chart-selector suggestion's mix suffix — present only where several mixes feed it. */
.chart-selector-mix { color: var(--mix-ink-muted); font-size: .82em; }

.mc-chip {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 13%, transparent);
    color: var(--mix-ink-muted);
    border-radius: 99px;
    padding: 3px 12px;
    cursor: pointer;
    font-size: .83rem;
}

.mc-chip:hover {
    color: var(--mix-ink);
}

.mc-chip:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 2px;
}

.mc-chip[aria-pressed="true"] {
    background: color-mix(in srgb, var(--mix-primary) 15%, var(--mix-surface));
    border-color: color-mix(in srgb, var(--mix-primary) 55%, transparent);
    color: var(--mix-ink);
}

.mc-filter-sep {
    width: 1px;
    height: 18px;
    background: color-mix(in srgb, var(--mix-ink) 13%, transparent);
}

.mc-groupby {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: .8rem;
    color: var(--mix-ink-muted);
}

.mc-seg {
    display: inline-flex;
    border: 1px solid color-mix(in srgb, var(--mix-ink) 13%, transparent);
    border-radius: 5px;
    overflow: hidden;
}

.mc-seg button {
    background: var(--mix-surface);
    border: 0;
    color: var(--mix-ink-muted);
    cursor: pointer;
    padding: 3px 10px;
    font-size: .81rem;
}

.mc-seg button[aria-pressed="true"] {
    background: color-mix(in srgb, var(--mix-primary) 18%, var(--mix-surface));
    color: var(--mix-ink);
}

.mc-seg button:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: -2px;
}

/* ---- the folder in view, and its rows ---- */
.mc-fgroup {
    display: flex;
    flex-direction: column;
}

/* Names the folder the picker selected. Not a control — the picker is. */
.mc-fhead {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 8px 5px;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 22%, transparent);
    position: sticky;
    top: -1px;
    background: var(--mix-surface);
    z-index: 2;
}

.mc-ftitle {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.14rem;
    letter-spacing: .01em;
}

.mc-fcount {
    font-size: .79rem;
    color: var(--mix-ink-muted);
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

.mc-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 4px 6px;
    width: 100%;
    border: 0;
    border-bottom: 1px solid color-mix(in srgb, var(--mix-ink) 12%, transparent);
    background: var(--mix-surface);
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.mc-row:hover {
    box-shadow: inset 2px 0 0 var(--mix-primary);
}

.mc-row:hover .mc-name {
    color: var(--mix-primary);
}

.mc-row:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: -2px;
}

.mc-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .92rem;
}

.mc-tail {
    margin-left: auto;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 7px;
}

/* ---- sticker sheet ---- */
.mc-sheet {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 14px;
}

.mc-stickers {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}

.mc-sticker {
    background: var(--mix-surface);
    border: 1px solid color-mix(in srgb, var(--mix-ink) 9%, transparent);
    border-radius: 5px;
    padding: 9px;
    display: flex;
    flex-direction: column;
    gap: 7px;
    text-align: left;
    color: inherit;
    min-width: 0;
}

/* Jacket art is a ~16:9 banner. A fixed height sizes the width from the aspect and
   overflows a fluid card, so the box owns the geometry and the image is bounded to it. */
.mc-sticker-art {
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 3px;
    overflow: hidden;
    background: var(--mix-surface-muted);
    display: flex;
    align-items: center;
    justify-content: center;
}

.mc-sticker-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* The one thing on a sticker worth clicking. */
.mc-ball {
    background: none;
    border: 0;
    padding: 0;
    line-height: 0;
    cursor: pointer;
    border-radius: 3px;
}

.mc-ball:hover {
    filter: brightness(1.25);
}

.mc-ball:focus-visible {
    outline: 2px solid var(--mix-primary);
    outline-offset: 1px;
}

/* Dimming the card is what says "gone" — desaturating the bubbles instead would cost the
   red-Single / green-Double read for no extra meaning. */
.mc-sticker-gone {
    opacity: .72;
}

.mc-sticker-gone:hover {
    opacity: 1;
}

.mc-sticker-name {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.02rem;
    line-height: 1.13;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.mc-sticker-artist {
    font-size: .72rem;
    color: var(--mix-ink-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mc-sticker-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
}

.mc-loose {
    display: flex;
    flex-direction: column;
}

.mc-loose-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: .72rem;
    letter-spacing: .15em;
    text-transform: uppercase;
    color: var(--mix-ink-muted);
    margin: 8px 0 6px;
}

.mc-empty {
    padding: 26px 14px;
    text-align: center;
    color: var(--mix-ink-muted);
    font-size: .9rem;
    border: 1px dashed color-mix(in srgb, var(--mix-ink) 14%, transparent);
    border-radius: 5px;
}

@media (min-width: 820px) {
    .mc-head {
        flex-direction: row;
        align-items: flex-end;
        justify-content: space-between;
        gap: 24px;
    }
}

/* Narrow: the grouping control takes its own line instead of squeezing in beside a wrapped
   direction chip. */
@media (max-width: 600px) {
    .mc-groupby {
        margin-left: 0;
        width: 100%;
        justify-content: flex-start;
    }
}
