/* Theme tokens. Light values here match the site's original (pre-dark-mode) hardcoded colors
   exactly, so light mode is unchanged. Dark values apply in two cases: (1) the visitor is in "auto"
   mode (the default — see ThemeToggleButton.razor/theme.js) and their OS prefers dark (`@media`
   block, guarded by `:not([data-theme="light"])` so an explicit light override still wins), or
   (2) theme.js has stamped `data-theme="dark"` on <html> because the visitor picked "dark" (or
   "time" mode resolved to dark for the current hour) — persisted via the `dfl-theme-mode` cookie
   and re-applied server-side by App.razor on every request, so there's no flash of the wrong theme
   on load (except for "time" mode, which the server can't resolve — see App.razor's ThemeAttr).
   --dfl-on-brand is intentionally IDENTICAL in both themes: it's the text/icon color used on top of
   an already-colored chip/button/hero background (e.g. white text on the brand-blue button), never
   on the page's own background — those chip backgrounds (the standings hero gradient, header
   masthead, solid sport-accent pills) are fixed brand colors left unthemed, so the text sitting on
   them must stay constant too.
   --dfl-tint-mix / --dfl-accent-text-mix exist because per-sport (SportBranding.cs) and per-member
   (MemberBranding.cs) colors are set as INLINE custom properties per element (e.g. --sport-accent,
   --sport-accent-soft, --member-bg/-fg) — a stylesheet rule can never override a custom property an
   element already sets inline on itself, so app.css can't just redeclare --sport-accent-soft for dark
   mode the way it does --dfl-surface etc. Instead, every CONSUMING rule blends the inline color via
   color-mix() against one of these two ratios: --dfl-tint-mix controls how much of an inline "soft"
   pastel background survives after mixing toward the page surface (100% = untouched in light mode;
   a low percentage in dark mode mutes what would otherwise be a bright pastel patch on a dark page),
   and --dfl-accent-text-mix controls how much white gets blended into an inline accent color used as
   plain text (0% = untouched in light mode; darker sport accents are otherwise hard to read as text
   on a dark page — see SportBranding.cs's UEFACL comment for a case this ratio alone couldn't fix).
   Solid, non-soft accent fills (pills/buttons/borders paired with --dfl-on-brand text) are left
   unmixed, same reasoning as the hero gradient —
   EXCEPT --dfl-table-header-bg, used only for the "Overall"/"Money"/section-header table bars that
   sit directly beside the (now near-black) per-sport columns: the fully vivid brand blue read as too
   jarring/saturated next to them, so this one gets its own darker, muted-navy value in dark mode
   instead of either the vivid fixed blue or a full brighten. */
:root {
    --dfl-bg: #f4f6f8;
    --dfl-surface: #ffffff;
    --dfl-surface-alt: #eef4f9;
    --dfl-surface-hover: #f8fafc;
    --dfl-border: #e5e7eb;
    --dfl-border-strong: #cbd5e1;
    --dfl-table-header-bg: #1a5490;
    --dfl-text: #1f2937;
    --dfl-text-muted: #6b7280;
    --dfl-brand: #1a5490;
    --dfl-brand-dark: #0f3d6b;
    --dfl-on-brand: #ffffff;
    --dfl-on-brand-rgb: 255, 255, 255;
    --dfl-success: #15803d;
    --dfl-success-strong: #14532d;
    --dfl-success-bg: #dcfce7;
    --dfl-success-rgb: 21, 128, 61;
    --dfl-danger: #b91c1c;
    --dfl-danger-bg: #fee2e2;
    --dfl-danger-rgb: 220, 38, 38;
    --dfl-warning: #d97706;
    --dfl-warning-text: #92400e;
    --dfl-warning-bg: #fef3c7;
    --dfl-shadow-rgb: 0, 0, 0;
    --dfl-gold-rgb: 255, 215, 0;
    --dfl-silver-rgb: 192, 192, 192;
    --dfl-bronze-rgb: 205, 127, 50;
    /* 4th/5th money places (see LeagueSeedData.cs payouts) — deliberately NOT more "metals" (pewter/
       copper read too close to silver/bronze, and a blue "sapphire" for 5th still read too close to
       bronze/3rd in practice); emerald/ruby break into a different hue family entirely so all five
       rows stay visually distinct at a glance. Sport.razor only — Home.razor's overall standings
       stays gold/silver/bronze (top 3 only). */
    --dfl-emerald-rgb: 46, 139, 87;
    --dfl-ruby-rgb: 244, 114, 137;
    --dfl-info-bg: #dbeafe;
    --dfl-info-border: #bfdbfe;
    --dfl-info-text: #003e7e;
    --dfl-purple-bg: #ede9fe;
    --dfl-purple-text: #4c1d95;
    --dfl-purple-border: #7c3aed;
    --dfl-tint-mix: 100%;
    --dfl-accent-text-mix: 0%;
    /* Scoreboard/TeamDetail win-loss cell tint (rendered by .scoreboard-cell--win/--loss, near the
       bottom of this file, as two stacked background layers using these four custom properties).
       --dfl-scoreboard-win-rgb/--dfl-scoreboard-loss-rgb/--dfl-scoreboard-tint-alpha are the tint
       itself and are NEVER redeclared per theme, unlike --dfl-success-rgb/--dfl-danger-rgb above —
       this tint is meant to read as the same washed-out rgba() in both themes, not the more saturated
       colors (or a much higher alpha) the rest of dark-mode UI switches to; both alternatives were
       tried and read as too vivid/saturated.
       --dfl-scoreboard-brighten-alpha drives a SECOND layer painted behind that tint, only to lift the
       near-black dark-mode page a little before the tint lands on it — 0 here (no effect in light
       mode), overridden to a real value only in the two dark-mode blocks below. It deliberately reuses
       --dfl-success-rgb/--dfl-danger-rgb (the theme's own lighter shade of the SAME hue) rather than
       plain white for that layer's color — a white wash under a translucent color tint was tried first
       and read as a gray/desaturated cast rather than a brighter green/red. */
    --dfl-scoreboard-tint-alpha: 0.16;
    --dfl-scoreboard-win-rgb: 21, 128, 61;
    --dfl-scoreboard-loss-rgb: 220, 38, 38;
    --dfl-scoreboard-brighten-alpha: 0;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --dfl-bg: #0e1116;
        --dfl-surface: #1a1f27;
        --dfl-surface-alt: #1c2a3a;
        --dfl-surface-hover: #232a35;
        --dfl-border: #2d333d;
        --dfl-border-strong: #3d4552;
        --dfl-text: #e5e7eb;
        --dfl-text-muted: #9aa4b2;
        --dfl-brand: #5b9bd5;
        --dfl-brand-dark: #7fb2e8;
        --dfl-success: #4ade80;
        --dfl-success-strong: #86efac;
        --dfl-success-bg: #14532d;
        --dfl-success-rgb: 74, 222, 128;
        --dfl-danger: #f87171;
        --dfl-danger-bg: #450a0a;
        --dfl-danger-rgb: 248, 113, 113;
        --dfl-warning: #fbbf24;
        --dfl-warning-text: #fde68a;
        --dfl-warning-bg: #451a03;
        --dfl-gold-rgb: 191, 149, 0;
        --dfl-silver-rgb: 148, 148, 148;
        --dfl-bronze-rgb: 153, 94, 37;
        --dfl-emerald-rgb: 63, 168, 114;
        --dfl-ruby-rgb: 244, 63, 94;
        --dfl-info-bg: #1e3a5f;
        --dfl-info-border: #2f5a8a;
        --dfl-info-text: #93c5fd;
        --dfl-purple-bg: #3b2a5c;
        --dfl-purple-text: #c4b5fd;
        --dfl-purple-border: #8b5cf6;
        --dfl-table-header-bg: #14304a;
        --dfl-tint-mix: 0%;
        --dfl-accent-text-mix: 30%;
        /* Only defined for dark mode, deliberately absent from :root — every consuming rule below
           falls back to its own original light-mode opacity value via var(..., <original>), so light
           mode's "washed out" inactive-sport look is untouched. In dark mode this same reduced
           dimming applies everywhere uniformly instead of each rule's own (much lower) value, since
           opacity toward a dark page background reads as "too dim to see", not just "de-emphasized"
           the way it does against a light background. */
        --dfl-inactive-opacity: 0.9;
        --dfl-scoreboard-brighten-alpha: 0.15;
    }
}

:root[data-theme="dark"] {
    --dfl-bg: #0e1116;
    --dfl-surface: #1a1f27;
    --dfl-surface-alt: #1c2a3a;
    --dfl-surface-hover: #232a35;
    --dfl-border: #2d333d;
    --dfl-border-strong: #3d4552;
    --dfl-text: #e5e7eb;
    --dfl-text-muted: #9aa4b2;
    --dfl-brand: #5b9bd5;
    --dfl-brand-dark: #7fb2e8;
    --dfl-success: #4ade80;
    --dfl-success-strong: #86efac;
    --dfl-success-bg: #14532d;
    --dfl-success-rgb: 74, 222, 128;
    --dfl-danger: #f87171;
    --dfl-danger-bg: #450a0a;
    --dfl-danger-rgb: 248, 113, 113;
    --dfl-warning: #fbbf24;
    --dfl-warning-text: #fde68a;
    --dfl-warning-bg: #451a03;
    --dfl-gold-rgb: 191, 149, 0;
    --dfl-silver-rgb: 148, 148, 148;
    --dfl-bronze-rgb: 153, 94, 37;
    --dfl-emerald-rgb: 63, 168, 114;
    --dfl-ruby-rgb: 244, 63, 94;
    --dfl-info-bg: #1e3a5f;
    --dfl-info-border: #2f5a8a;
    --dfl-info-text: #93c5fd;
    --dfl-purple-bg: #3b2a5c;
    --dfl-purple-text: #c4b5fd;
    --dfl-purple-border: #8b5cf6;
    --dfl-table-header-bg: #14304a;
    --dfl-tint-mix: 0%;
    --dfl-accent-text-mix: 30%;
    --dfl-inactive-opacity: 0.9;
    --dfl-scoreboard-brighten-alpha: 0.15;
}

html, body {
    margin: 0;
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
    background: var(--dfl-bg, #f4f6f8);
    color: var(--dfl-text, #1f2937);
    overflow-x: clip;
    max-width: 100%;
}

/* Baseline for plain, unclassed <a> tags (e.g. the Commissioner index's link table, inline prose
   links) — without this they fall back to the browser's default link-blue/visited-purple, which
   never adapts to the theme tokens above. Scoped to `:not([class])` deliberately, NOT just left as
   a bare `a, a:visited` — a *classed* button-styled anchor (e.g. .draft-link-btn, which sets white
   text via --dfl-on-brand) would otherwise still lose that fight once visited: `a:visited` carries
   an extra type-selector (a) on top of its pseudo-class, giving it higher specificity than a single
   class selector like `.draft-link-btn`, so it beat the button's own color rule for any link the
   browser considered visited (e.g. Commissioner dashboard "Manage"/"Scoring Math" links after you'd
   clicked them once) — text silently went from white to --dfl-brand's blue, in both themes. Any
   *classed* anchor now falls outside this rule entirely and keeps its own styling regardless of
   visited state. */
a:not([class]),
a:visited:not([class]) {
    color: var(--dfl-brand, #1a5490);
}

/* Theme toggle button (Components/Shared/ThemeToggleButton.razor, mounted twice by
   HeaderNavPanel.razor). Lives here rather than HeaderNavPanel.razor.css because it's rendered by a
   separate child component — reaching into it from a CSS-isolated parent stylesheet would need
   ::deep on every rule for no benefit, since nothing else here is component-private. Sits on the
   colored header bar, so it uses --dfl-on-brand like the rest of the header's icons/text. */
.dfl-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.85rem;
    height: 1.85rem;
    padding: 0;
    border: none;
    border-radius: 999px;
    background: rgba(var(--dfl-on-brand-rgb, 255, 255, 255), 0.12);
    color: var(--dfl-on-brand, #fff);
    cursor: pointer;
    flex-shrink: 0;
}

.dfl-theme-toggle:hover {
    background: rgba(var(--dfl-on-brand-rgb, 255, 255, 255), 0.22);
}

/* Only one icon shows at a time, directly naming the CURRENT mode (not the resolved light/dark
   appearance, and not what clicking will do next) — "A" for auto, sun for light, moon for dark,
   hourglass for time. Keyed off data-theme-mode, which theme.js always sets to one of these four
   explicit values (default "auto"), so this doesn't need the @media-query cascade the color tokens
   use — there's no ambiguity to resolve here. */
.dfl-theme-toggle__icon--auto,
.dfl-theme-toggle__icon--sun,
.dfl-theme-toggle__icon--moon,
.dfl-theme-toggle__icon--time {
    display: none;
}

:root[data-theme-mode="auto"] .dfl-theme-toggle__icon--auto,
:root[data-theme-mode="light"] .dfl-theme-toggle__icon--sun,
:root[data-theme-mode="dark"] .dfl-theme-toggle__icon--moon,
:root[data-theme-mode="time"] .dfl-theme-toggle__icon--time {
    display: block;
}

.dfl-theme-toggle-wrap {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

/* Descriptor text next to the toggle, naming the current mode in words (icon-only isn't always
   obvious). Hidden on the desktop header — no room, and the icon alone carries the meaning there —
   shown only in the hamburger dropdown via the same 1900px breakpoint MainLayout.razor.css/
   HeaderNavPanel.razor.css duplicate; keep this in sync with those if that breakpoint ever moves. */
.dfl-theme-toggle-label {
    display: none;
}

.dfl-theme-toggle-label span {
    display: none;
}

@media (max-width: 1900px) {
    .dfl-theme-toggle-label {
        display: inline-block;
        font-size: 0.8rem;
        opacity: 0.85;
    }
}

:root[data-theme-mode="auto"] .dfl-theme-toggle-label--auto,
:root[data-theme-mode="light"] .dfl-theme-toggle-label--sun,
:root[data-theme-mode="dark"] .dfl-theme-toggle-label--moon,
:root[data-theme-mode="time"] .dfl-theme-toggle-label--time {
    display: inline;
}

h1, h2, h3 {
    color: var(--dfl-brand, #1a5490);
}

.dfl-card {
    background: var(--dfl-surface, #fff);
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.08);
    padding: 0.5rem;
    margin-bottom: 0.5rem;
}

.dfl-banner {
    background: var(--dfl-surface-alt, #e8f4f8);
    border-left: 4px solid var(--dfl-brand, #1a5490);
    padding: 0.425rem 0.5rem;
    border-radius: 4px;
    margin-bottom: 0.5rem;
}

.dfl-banner.warn {
    background: var(--dfl-warning-bg, #fff8e1);
    border-left-color: var(--dfl-warning, #f59e0b);
}

.dfl-install-banner {
    display: none;
    position: fixed;
    left: 0.75rem;
    right: 0.75rem;
    bottom: 0.75rem;
    z-index: 1000;
    align-items: center;
    gap: 0.75rem;
    background: var(--dfl-surface, #fff);
    border-radius: 10px;
    box-shadow: 0 4px 16px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.2);
    padding: 0.375rem 0.5rem;
    max-width: 420px;
    margin: 0 auto;
}

.dfl-install-banner.is-visible {
    display: flex;
}

.dfl-install-banner__icon {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    flex-shrink: 0;
}

.dfl-install-banner__copy {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    font-size: 0.85rem;
}

.dfl-install-banner__copy strong {
    color: var(--dfl-brand, #1a5490);
}

/* Fixed brand-blue fill in both themes — see .dfl-standings-hero's comment for why (this is the
   same "primary action" brand color used for buttons/badges/header-bars throughout the app, always
   paired with the theme-constant --dfl-on-brand text). */
.dfl-install-banner__install {
    background: #1a5490;
    color: var(--dfl-on-brand, #fff);
    border: none;
    border-radius: 6px;
    padding: 0.5rem 0.85rem;
    font-weight: 600;
    cursor: pointer;
    flex-shrink: 0;
}

.dfl-install-banner__dismiss {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 0.9rem;
    padding: 0.25rem;
    flex-shrink: 0;
    color: var(--dfl-text-muted, #888);
}

.dfl-table-wrap {
    overflow-x: auto;
}

table.dfl-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

table.dfl-table th,
table.dfl-table td {
    padding: 0.275rem 0.325rem;
    border-bottom: 1px solid var(--dfl-border, #e5e7eb);
    text-align: left;
    white-space: nowrap;
}

table.dfl-table th {
    background: var(--dfl-surface-alt, #eef4f9);
    color: var(--dfl-brand-dark, #0f3d6b);
    font-weight: 600;
}

table.dfl-table tr:hover td {
    background: var(--dfl-surface-hover, #f9fbfd);
}

/* Shared delta coloring (MyTeams.razor, DraftBoardCore.razor history columns, etc.) — pair these
   ONLY with a sizing class that does NOT itself set `color` (e.g. a dedicated `__delta` class), never
   with an existing `__proj`/value class that sets color. Same-specificity CSS rules resolve by source
   order, not which class "sounds more specific" — a `color` rule defined later in this file (most
   component-specific rules are, since these three are declared near the top) wins over these
   regardless of which element also has score-positive/-negative/-inactive. */
.score-positive { color: var(--dfl-success, #15803d); }
.score-negative { color: var(--dfl-danger, #b91c1c); }
.score-inactive { color: var(--dfl-text-muted, #6b7280); }

/* Standings heat-map shading for streak / last-10 columns */
.heat-pos-strong { background-color: rgba(var(--dfl-success-rgb, 22, 163, 74), 0.22); }
.heat-pos-med    { background-color: rgba(var(--dfl-success-rgb, 22, 163, 74), 0.13); }
.heat-pos-weak   { background-color: rgba(var(--dfl-success-rgb, 22, 163, 74), 0.07); }
.heat-neg-strong { background-color: rgba(var(--dfl-danger-rgb, 220, 38, 38), 0.22); }
.heat-neg-med    { background-color: rgba(var(--dfl-danger-rgb, 220, 38, 38), 0.13); }
.heat-neg-weak   { background-color: rgba(var(--dfl-danger-rgb, 220, 38, 38), 0.07); }

.sync-ok { color: var(--dfl-success, #15803d); font-size: 0.75rem; }
.sync-fail { color: var(--dfl-danger, #b91c1c); font-size: 0.75rem; }

.dfl-sport-nav {
    display: flex;
    gap: 0.35rem;
    padding: 0.65rem 1.5rem;
    background: var(--dfl-surface, #fff);
    border-bottom: 1px solid var(--dfl-border, #e5e7eb);
    overflow-x: auto;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    -webkit-overflow-scrolling: touch;
}

.dfl-sport-nav a {
    text-decoration: none;
    color: var(--dfl-brand-dark, #0f3d6b);
    font-size: 0.85rem;
    font-weight: 600;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    border: 1px solid var(--dfl-border, #d1d9e0);
    white-space: nowrap;
}

.dfl-sport-nav a:hover {
    background: var(--dfl-surface-alt, #eef4f9);
}

.dfl-sport-nav a.active {
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
    border-color: var(--sport-accent, var(--dfl-brand, #1a5490));
    color: var(--sport-tab-text, var(--dfl-surface, #fff));
}

.dfl-sport-nav a:not(.inactive):not(.active) {
    /* Unlike other --sport-accent-soft consumers in this file, this pill is deliberately NOT muted
       toward --dfl-surface in dark mode (--dfl-tint-mix overridden back to 100% here) — it's a small
       chip, same reasoning as the fixed-color header/hero chips in the top-of-file comment, so the
       pastel stays visible and matches light mode exactly (e.g. MLB stays light red). Text color is
       likewise pinned to the light-mode --dfl-brand-dark value instead of the token, which flips to a
       light blue in dark mode and would be unreadable on a light pastel chip. */
    --dfl-tint-mix: 100%;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    border-color: transparent;
    color: #0f3d6b;
}

.dfl-sport-nav a.inactive {
    opacity: var(--dfl-inactive-opacity, 0.45);
}

/* Wraps DflTicker + NewsTicker (see MainLayout.razor) so the pair sticks and scrolls as one unit
   below the header, instead of each .dfl-ticker fighting over the same sticky offset. */
.dfl-ticker-stack {
    position: sticky;
    /* Sits flush against the bottom of the sticky site header — this is dfl-header's actual height
       (MainLayout.razor.css: 3rem logo + 2 x 0.375rem padding), NOT the 4.75rem offset
       draft-clock-card/dfl-chat--sidebar use (which leaves a 1rem cushion). Keep equal to
       dfl-header's height. -1px kills a sub-pixel hairline at the seam. */
    top: calc(3.75rem - 1px);
    z-index: 1050;
}

@media (max-width: 1900px) {
    .dfl-ticker-stack {
        /* dfl-header's mobile-shrink height: 2.5rem logo + 2 x 0.325rem padding = 3.15rem */
        top: calc(3.15rem - 1px);
    }
}

.dfl-ticker {
    overflow: hidden;
    background: linear-gradient(90deg, var(--dfl-surface-alt, #e8f0f8), var(--dfl-surface-alt, #f2f7fb));
    color: var(--dfl-brand-dark, #0f3d6b);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--dfl-border, #e5e7eb);
    cursor: grab;
    touch-action: pan-y; /* let vertical page scroll pass through; ticker.js owns horizontal drag */
    -webkit-user-select: none;
    user-select: none;
}

/* Set by ticker.js while a drag is in progress (see js/ticker.js) */
.dfl-ticker--dragging {
    cursor: grabbing;
}

/* Movement is entirely JS-driven (see js/ticker.js) so it can be paused/dragged/resumed —
   plain CSS animation can't be interrupted by a pointer gesture and smoothly resumed later. */
.dfl-ticker__track {
    display: flex;
    width: max-content;
    will-change: transform;
}

.dfl-ticker__text {
    display: inline-flex;
    align-items: center;
    padding: 0.45rem 2rem;
    white-space: nowrap;
}

.dfl-ticker__game {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

/* NewsTicker.razor's per-headline equivalent of .dfl-ticker__game above. */
.dfl-ticker__headline {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.dfl-ticker__headline a {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

.dfl-ticker__headline a:hover {
    text-decoration: underline;
}

/* Shown once per sport (see DflTicker.razor's IsFirstOfSport), not once per game — a visually
   distinct "sport change" marker rather than a label repeated on every entry. */
.dfl-ticker__sport-marker {
    color: #b45309;
    font-weight: 900;
    font-size: 0.8rem;
    letter-spacing: 0.14em;
    margin: 0 0.6rem;
}

.dfl-ticker__sep {
    opacity: 0.55;
}

.dfl-ticker__status {
    font-size: 0.62rem;
    opacity: 0.8;
    margin-left: 0.1rem;
}

.dfl-ticker__status.is-live {
    color: var(--dfl-success, #15803d);
    opacity: 1;
}

.dfl-ticker__divider {
    opacity: 0.35;
    margin: 0 1rem;
}

.dfl-ticker .team-logo {
    width: 1.1rem;
    height: 1.1rem;
    vertical-align: middle;
}

.member-badge-link {
    display: inline-flex;
    color: inherit;
    text-decoration: none;
}

.member-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.member-badge__avatar,
.member-badge__photo {
    width: var(--member-badge-size, 36px);
    height: var(--member-badge-size, 36px);
    border-radius: 999px;
    flex-shrink: 0;
    box-sizing: border-box;
    border: 2.5px solid var(--member-chart-color, var(--member-bg, var(--dfl-border, #e5e7eb)));
}

.member-badge__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--member-bg, var(--dfl-border, #e5e7eb));
    color: var(--member-fg, var(--dfl-text, #1f2937));
    font-size: calc(var(--member-badge-size, 36px) * 0.34);
    font-weight: 800;
    letter-spacing: 0.02em;
}

.member-badge__photo {
    display: block;
    object-fit: contain;
    object-position: center;
    background: var(--dfl-surface, #fff);
    image-rendering: auto;
}

.member-badge__name {
    font-weight: 600;
}

.team-logo-link {
    display: inline-flex;
    line-height: 0;
}

.team-logo {
    width: 1.75rem;
    height: 1.75rem;
    object-fit: contain;
    flex-shrink: 0;
}

/* A handful of team crests across MLB/NFL/NHL/NCAAF/NCAAB/UEFACL (see each catalog's own
   GetLocalDarkLogoUrl — MlbTeamCatalog, ProTeamLogoCatalog, CollegeTeamLogoCatalog,
   UefaclTeamLogoCatalog) are entirely (or almost entirely) navy/black on a transparent PNG and nearly
   disappear against the dark theme's near-black page background. For those teams only, TeamLogo.razor
   renders BOTH the normal logo (tagged --light-variant) and ESPN's own official dark-mode crest (tagged
   --dark-variant, downloaded from their 500-dark CDN endpoint — see MlbTeamCatalog.GetLocalDarkLogoUrl
   for why that's the source, not a hand-recolor) as sibling <img> elements, and this pair of rules
   toggles which one is
   visible — mirrors the --dfl-bg dark-mode pattern at the top of this file: auto/OS-dark vs. explicit
   data-theme="dark". Every other team only ever renders the plain .team-logo (no variant class), so
   it's unaffected and still always visible. SportLogo.razor reuses these same two class names (on its
   .sport-logo elements) for the same problem on UEFACL's sport-wide crest — see
   SportLogoCatalog.GetLocalDarkLogoUrl. ScoreboardSportPanel.razor reuses them a third time (on its
   .scoreboard-broadcast-logo elements) for the same problem on broadcast-network logos — see
   BroadcastLogoCatalog. Base rule
   below is qualified with the img type (not just .team-logo--dark-variant) so its specificity beats
   .sport-logo's own `display: block` — .sport-logo sets display itself (unlike .team-logo, which
   doesn't), and without the type qualifier the two rules tie on specificity and .sport-logo (later in
   this file) would win the cascade, showing the dark variant even outside dark mode. */
img.team-logo--dark-variant {
    display: none;
}

/* Summary.razor's .summary-matrix__sport-head .sport-logo rule (below, in this same file) also sets
   its own `display: block` and outranks the plain img.team-logo--dark-variant rule above on
   specificity (two classes beats one class + type) — this targeted rule keeps the default-off state
   winning there too. Still below the dark-mode "on" overrides' specificity, so the toggle itself is
   unaffected. */
img.sport-logo.team-logo--dark-variant {
    display: none;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .team-logo--light-variant {
        display: none;
    }

    :root:not([data-theme="light"]) .team-logo--dark-variant {
        display: inline-block;
    }
}

:root[data-theme="dark"] .team-logo--light-variant {
    display: none;
}

:root[data-theme="dark"] .team-logo--dark-variant {
    display: inline-block;
}

.team-name-cell {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

.sport-banner {
    border-left-color: var(--sport-accent, var(--dfl-brand, #1a5490));
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #e8f4f8)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.sport-banner__brand {
    display: flex;
    align-items: center;
    gap: 0.85rem;
}

.sport-banner__text {
    min-width: 0;
}

.sport-panel__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
}

.sport-panel__title h1 {
    margin: 0;
    font-size: 1.1rem;
}

.sport-panel h1,
.sport-panel h2 {
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand, #1a5490)));
}

.sport-panel h2 {
    margin: 0 0 0.35rem;
    font-size: 1.1rem;
}

.dfl-card.sport-panel {
    padding: 0.3rem 0.375rem;
    margin-bottom: 0.325rem;
}

.dfl-banner.sport-banner--page {
    padding: 0.3rem 0.425rem;
    margin-bottom: 0.325rem;
}

/* Sport.razor's Scores/Standings pill toggle + its per-view sub-toggle (Current/Projected or
   Overall/League-Conference/Division). Same visual language as .draft-sport-pill's active-state
   ring, just larger since these are primary page navigation rather than a compact filter row.
   --sub is a touch smaller/lighter than the primary row so the two-level hierarchy reads clearly. */
.sport-view-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0 0 0.65rem;
}

.sport-view-pills--sub {
    margin-top: -0.25rem;
}

.sport-view-pill {
    display: inline-block;
    padding: 0.3rem 0.9rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.85rem;
    font-weight: 700;
    border: 1px solid transparent;
    cursor: pointer;
}

.sport-view-pills--sub .sport-view-pill {
    padding: 0.2rem 0.7rem;
    font-size: 0.78rem;
}

.sport-view-pill.active {
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
    color: var(--dfl-on-brand, #fff);
    border-color: var(--sport-accent, var(--dfl-brand-dark, #0f3d6b));
}

.sport-panel__footnote {
    margin: 0.45rem 0 0;
}

.sport-panel .dfl-sheet-note {
    margin: 0 0 0.4rem;
}

.sport-panel table.dfl-table th,
.sport-panel table.dfl-table td {
    padding: 0.14rem 0.225rem;
    line-height: 1.2;
    vertical-align: middle;
    text-align: right;
}

.sport-panel table.dfl-table .col-text {
    text-align: left;
}

/* flex (not inline vertical-align) so the logo/name/badges genuinely center as a group against
   taller neighboring cells (e.g. the Owner column's avatar) — inline vertical-align only aligns
   elements relative to each other on the line, not the line as a whole within a taller cell. Same
   technique already used successfully for .scoreboard-owner-cell/.scoreboard-opponent-cell. */
.sport-panel table.dfl-table td.team-name-cell {
    display: flex;
    align-items: center;
    line-height: normal;
    text-align: left;
}

.sport-panel table.dfl-table td.team-name-cell .team-logo {
    margin-right: 0.35rem;
}

.sport-panel table.dfl-table td.pick-list {
    line-height: normal;
    text-align: center;
}

.sport-panel table.dfl-table td:has(.member-badge) {
    line-height: normal;
    text-align: left;
}

/* Caps the unfrozen name column's growth on wide desktop viewports — table-layout:auto (this
   table's default; nothing overrides it) hands ALL of a table's leftover width to whichever
   column has no explicit width, which is this one (freeze-col-2 right before it also now has its
   own width+min-width fix, further down this file, so it can't absorb any of the leftover either).
   width+max-width alone wasn't enough to stop the browser from still inflating this column — same
   class of quirk as the freeze-col-1 comment describes ("table auto-layout treats a bare `width`
   as only a *preferred* size"), confirmed here too. min-width matching width is what actually
   holds it, mirroring freeze-col-1's exact proven recipe (width+min-width+box-sizing:border-box)
   instead of width+max-width. overflow/ellipsis (nowrap already comes from table.dfl-table's base
   rule) truncates gracefully if a name is longer than this.
   Sport.razor's Member Scores tables share the same 4rem as Home.razor's Overall Standings/Score
   Trends tables below (shrunk from 6rem once the league's longest member display name went from
   "Charlie H." to "Charlie" — comfortably fits well under 4rem), and the narrower column matters
   most on mobile, where every column competes for the same limited viewport width before
   .dfl-table-wrap's overflow-x:auto kicks in. */
.sport-panel table.dfl-member-scores-table td.col-text {
    width: 4rem;
    min-width: 4rem;
    max-width: 4rem;
    overflow: hidden;
    text-overflow: ellipsis;
    box-sizing: border-box;
}

.dfl-standings-table--sheet td.col-text,
.dfl-trend-table td.col-text {
    width: 4rem;
    min-width: 4rem;
    max-width: 4rem;
    overflow: hidden;
    text-overflow: ellipsis;
    box-sizing: border-box;
}

.sport-panel table.dfl-table td:has(.member-pick-logos) {
    line-height: normal;
    text-align: center;
}

.sport-panel .member-badge {
    gap: 0.35rem;
    vertical-align: middle;
}

.sport-panel .member-pick-logos {
    display: inline-flex;
    gap: 0.2rem;
    vertical-align: middle;
    align-items: center;
}

.sport-panel table.dfl-table .team-logo,
.sport-panel table.dfl-table .member-badge__photo,
.sport-panel table.dfl-table .member-badge__avatar {
    vertical-align: middle;
}

.sport-panel .scoring-detail-table td.tier-breakdown-cell {
    vertical-align: top;
    text-align: left;
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
}

/* Same display:flex-on-<td> fix as .dfl-team-standings-table above — this table's Tier Breakdown
   column routinely wraps to multiple lines, making the row tall, and without this override the
   Team cell (flex, so no longer a real table-cell) stopped centering against that taller row. */
.sport-panel table.dfl-table.scoring-detail-table td.team-name-cell {
    display: table-cell;
    vertical-align: middle;
}

.scoring-detail-table .team-name-inner {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.sport-panel .tier-breakdown-list {
    padding-left: 0.95rem;
    line-height: 1.25;
}

.sport-panel .tier-breakdown-list li + li {
    margin-top: 0.1rem;
}

table.dfl-table tr.sport-head th,
.sport-panel table.dfl-table thead th {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

/* Deep muted navy in dark mode (--dfl-table-header-bg) rather than the vivid fixed brand blue used
   for buttons/badges elsewhere — see that token's comment above for why. */
.dfl-standings-table .section-overall,
.dfl-standings-table .section-money {
    text-align: center;
    background: var(--dfl-table-header-bg, #1a5490);
    color: var(--dfl-on-brand, #fff);
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.dfl-standings-table .section-sport {
    text-align: center;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.dfl-standings-table .section-sport.is-inactive {
    opacity: var(--dfl-inactive-opacity, 0.55);
}

.section-sport__head {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
}

.dfl-sport-leader-card__sport {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
}

.dfl-standings-table tr.subhead th {
    font-size: 0.78rem;
    background: var(--dfl-surface-hover, #f8fafc);
    text-align: right;
}

.dfl-standings-table tr.subhead th:first-child {
    text-align: right;
}

.dfl-standings-table tr.subhead th.col-text {
    text-align: left;
}

.dfl-standings-table .score-cell strong {
    color: var(--dfl-brand-dark, #0f3d6b);
}

table.dfl-table.dfl-standings-table td {
    text-align: right;
}

table.dfl-table.dfl-standings-table tbody td.col-text {
    text-align: left;
}

/* Frozen leading columns for the site's scrollable data tables, so a row stays identifiable
   while scrolling right through stat columns on a narrow screen. `.freeze-col-1`/`.freeze-col-2`
   freeze a 2-column identity pair (e.g. Rk+Member, #+Team); `.freeze-col-solo` freezes a single
   leading column (e.g. just a Team or Member column). freeze-col-1 gets a fixed border-box width
   PLUS a matching min-width — table auto-layout treats a bare `width` as only a *preferred* size
   and will shrink the column toward its min-content width once the table overflows its container
   (exactly the narrow-screen/overflow-x:auto case this feature targets), which silently produces
   a real gap between freeze-col-1's shrunk right edge and freeze-col-2's `left` offset (still
   computed from the wider assumed width) — min-width is what actually holds the column at that
   width. Two width groups by known max content width: 2rem for 1-2 digit rank/AP-poll numbers
   (Home.razor Overall Standings + Projection Trends, Sport.razor Member Scores,
   SportTeamStandingsTable.razor — all centered, see the freeze-col-1 text-align rules below),
   3rem for MyTeams.razor's "#", an overall draft pick number up to DraftConstants.TotalPicks=210,
   genuinely needing the extra digit.
   In Home.razor's two tables (Overall Standings + Projection Trends) and Sport.razor's Member
   Scores table, freeze-col-2 holds ONLY the member avatar (`MemberBadge ShowName="false"`) —
   the member's name is a separate, deliberately unfrozen `.col-text` column right after it
   (`MemberBadge ShowAvatar="false"`) so the name scrolls away while the avatar stays pinned for
   row identification. Same split in SportTeamStandingsTable.razor and MyTeams.razor (one table
   per sport), but for the Team column instead of Member: freeze-col-2 holds only `<TeamLogo>`,
   and the team name/badges (formerly combined with the logo in one `.team-name-cell` /
   `.my-teams-team-name` cell) live in their own unfrozen `.col-text` column right after it.
   Don't recombine any of these back into one freeze-col-2 cell without re-checking that request.
   Home.razor's merged colspan=5 "Overall" header cell is split into a blank frozen colspan=2
   segment (Rk+Avatar) + a blank unfrozen colspan=1 segment (Member name column) + a labeled
   colspan=3 segment, so the banner still reads as one continuous bar while only Rk+Avatar
   freeze; same trick for its tfoot "Total" label (colspan=2, exactly the frozen zone's width,
   followed by an empty td for the unfrozen name column).
   position:sticky on table cells doesn't composite cleanly against the collapsed-border layer
   (Chrome/Firefox both show a hairline see-through gap between sticky cells) — switch every
   frozen table to the separate border model so the sticky columns paint with solid edges. */
.dfl-standings-table--sheet,
.dfl-trend-table,
.dfl-member-scores-table,
.dfl-team-standings-table,
.dfl-my-teams-table,
.dfl-sidebet-balances-table,
.scoring-detail-table,
.dfl-login-history-table,
.draft-report-card-table {
    border-collapse: separate;
    border-spacing: 0;
}

.draft-report-card-table .freeze-col-solo {
    min-width: 9rem;
}

/* Side-Bets balances table: every cell bold; the numeric columns (everything but Member) right-aligned. */
.dfl-sidebet-balances-table th,
.dfl-sidebet-balances-table td {
    font-weight: 700;
}

.dfl-sidebet-balances-table th:not(.freeze-col-solo),
.dfl-sidebet-balances-table td:not(.freeze-col-solo) {
    text-align: right;
}

/* Best steal / Worst bust cells: team logo left of the name + pick detail, bold and sport-accent
   coloured (--sport-accent set inline per row). */
.draft-report-card__pick {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

.dfl-standings-table--sheet .freeze-col-1,
.dfl-standings-table--sheet .freeze-col-2,
.dfl-trend-table .freeze-col-1,
.dfl-trend-table .freeze-col-2,
.dfl-member-scores-table .freeze-col-1,
.dfl-member-scores-table .freeze-col-2,
.dfl-team-standings-table .freeze-col-1,
.dfl-team-standings-table .freeze-col-2,
.dfl-my-teams-table .freeze-col-1,
.dfl-my-teams-table .freeze-col-2,
.freeze-col-solo,
.section-overall--frozen,
.standings-total-label--frozen {
    position: sticky;
    z-index: 1;
}

th.freeze-col-1,
th.freeze-col-2,
th.freeze-col-solo,
.section-overall--frozen {
    z-index: 2;
}

.dfl-standings-table--sheet .freeze-col-1,
.dfl-member-scores-table .freeze-col-1,
.dfl-team-standings-table .freeze-col-1,
.dfl-trend-table .freeze-col-1,
.dfl-my-teams-table .freeze-col-1,
.freeze-col-solo,
.section-overall--frozen,
.standings-total-label--frozen {
    left: 0;
}

.dfl-standings-table--sheet .freeze-col-1,
.dfl-member-scores-table .freeze-col-1,
.dfl-team-standings-table .freeze-col-1,
.dfl-trend-table .freeze-col-1 {
    width: 2rem;
    min-width: 2rem;
    box-sizing: border-box;
}

.dfl-standings-table--sheet .freeze-col-2,
.dfl-member-scores-table .freeze-col-2,
.dfl-team-standings-table .freeze-col-2,
.dfl-trend-table .freeze-col-2 {
    left: 2rem;
}

/* These three tables' freeze-col-2 (the avatar-only cell right before the name column) gets its own
   explicit width — same width+min-width+box-sizing recipe as freeze-col-1 above, not just a bare
   width, for the same reason: table-layout:auto's extra-space-distribution step doesn't reliably
   respect a bare width/max-width as a real cap (confirmed by this column visibly getting an equal
   share of the table's leftover desktop width alongside every other flexible column before this was
   added). Left off .dfl-team-standings-table deliberately — that table's freeze-col-2 holds a Team
   logo, not a member avatar, and hasn't shown this problem. */
.dfl-standings-table--sheet .freeze-col-2,
.dfl-member-scores-table .freeze-col-2,
.dfl-trend-table .freeze-col-2 {
    width: 2.75rem;
    min-width: 2.75rem;
    box-sizing: border-box;
}

.dfl-my-teams-table .freeze-col-1 {
    width: 3rem;
    min-width: 3rem;
    box-sizing: border-box;
}

.dfl-my-teams-table .freeze-col-2 {
    left: 3rem;
}

/* Rk/AP column always centered (not the table's default right/left alignment) — these selectors
   need to out-specificity .dfl-standings-table tr.subhead th:first-child (hence the matching
   tr.subhead prefix below, tied specificity resolved by this block coming later in the file),
   table.dfl-table.dfl-standings-table td, and .sport-panel table.dfl-table th/td (all of which
   would otherwise right-align it) by matching or exceeding their class+element count. */
.dfl-standings-table--sheet tr.subhead th.freeze-col-1,
table.dfl-table.dfl-standings-table td.freeze-col-1,
.dfl-trend-table th.freeze-col-1,
.dfl-trend-table td.freeze-col-1,
.sport-panel table.dfl-table th.freeze-col-1,
.sport-panel table.dfl-table td.freeze-col-1 {
    text-align: center;
}

/* Sport.razor's Member Scores tables (Current Score / Vegas Proj) header alignment. Rk is already
   centered via the shared freeze-col-1 rule above. Member (avatar header is blank/frozen-col-2,
   separate from the "Member" text header right after it — kept as two real cells rather than a
   colspan="2" merge, since a merged header cell can't be marked sticky without covering the Teams
   column while scrolling; a merged header also isn't sticky the way freeze-col-2 is, so the space
   above the frozen avatar visibly scrolled away independently of the body — confirmed broken,
   don't redo the merge) stays left via the base .col-text rule, no override needed. nth-child
   counts DOM <th> elements: with the header split back into two cells, both tables share the same
   [1]Rk [2]blank-avatar [3]Member [4]Teams [5..]stat-columns shape. Teams centers (its body cells
   are centered separately below, via td.pick-list); everything right of Teams right-justifies its
   header to match those columns' already-right-aligned body cells (.sport-panel table.dfl-table td's
   base). The .sport-panel prefix is required to out-specificity .sport-panel table.dfl-table .col-text
   (3 classes) for the Teams th, which carries col-text. */
.sport-panel table.dfl-member-scores-table thead th:nth-child(4) {
    text-align: center;
}

.sport-panel table.dfl-member-scores-table thead th:nth-child(n+5) {
    text-align: right;
}

.dfl-standings-table--sheet .freeze-col-1,
.dfl-standings-table--sheet .freeze-col-2,
.dfl-member-scores-table .freeze-col-1,
.dfl-member-scores-table .freeze-col-2,
.dfl-team-standings-table .freeze-col-1,
.dfl-team-standings-table .freeze-col-2,
.dfl-my-teams-table .freeze-col-1,
.dfl-my-teams-table .freeze-col-2,
.freeze-col-solo {
    background-color: var(--dfl-surface, #fff);
}

/* Derived from the exact same --dfl-X-rgb + opacity the plain `.standings-row-X td` rule below
   uses (color-mix'd onto --dfl-surface since these cells need an OPAQUE fill to hide scrolled-away
   columns underneath, unlike the translucent rgba() the rest of the row can use directly) — a single
   source of truth so these two columns can never drift out of sync with the rest of the row again.
   They previously used separate hand-picked --dfl-X-bg hex constants that were supposed to
   approximate this same blend but went stale for emerald/ruby, producing a visibly different tint
   in the frozen columns vs. the rest of the row. */
.standings-row-gold .freeze-col-1,
.standings-row-gold .freeze-col-2 {
    background-color: color-mix(in srgb, rgb(var(--dfl-gold-rgb, 255, 215, 0)) 20%, var(--dfl-surface, #fff));
}

.standings-row-silver .freeze-col-1,
.standings-row-silver .freeze-col-2 {
    background-color: color-mix(in srgb, rgb(var(--dfl-silver-rgb, 192, 192, 192)) 24%, var(--dfl-surface, #fff));
}

.standings-row-bronze .freeze-col-1,
.standings-row-bronze .freeze-col-2 {
    background-color: color-mix(in srgb, rgb(var(--dfl-bronze-rgb, 205, 127, 50)) 20%, var(--dfl-surface, #fff));
}

.standings-row-emerald .freeze-col-1,
.standings-row-emerald .freeze-col-2 {
    background-color: color-mix(in srgb, rgb(var(--dfl-emerald-rgb, 46, 139, 87)) 20%, var(--dfl-surface, #fff));
}

.standings-row-ruby .freeze-col-1,
.standings-row-ruby .freeze-col-2 {
    background-color: color-mix(in srgb, rgb(var(--dfl-ruby-rgb, 244, 114, 137)) 20%, var(--dfl-surface, #fff));
}

/* Override .sport-panel table.dfl-table td.team-name-cell's display:flex (same fix as
   table.dfl-draft-pool-table's td.team-name-cell below) — a <td> with display:flex stops being a
   table-cell, so it drops out of vertical-align:middle with its Rk/Logo/Owner row-siblings and the
   whole row looks shifted. Flex moves to this inner wrapper div instead; see the
   scoreboard-team-flex comment for the original diagnosis of this exact symptom. Selector must
   match that rule's specificity (.sport-panel + table.dfl-table + td.team-name-cell) or the
   override silently loses the cascade. */
.sport-panel table.dfl-table.dfl-team-standings-table td.team-name-cell {
    display: table-cell;
    vertical-align: middle;
}

.dfl-team-standings-table .team-name-inner {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

/* Fixed brand-blue gradient in both themes (same reasoning as .dfl-header's masthead gradient in
   MainLayout.razor.css) — tokenizing the stops to --dfl-brand/--dfl-brand-dark made this wash out to
   a pale, low-contrast blue in dark mode, since those tokens brighten for their more common role as
   readable text/accent color on a dark page. Only the on-top text color is themed (and it's a no-op:
   --dfl-on-brand is constant white). */
.dfl-standings-hero,
.dfl-standings-hero__group {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.25rem;
    margin-bottom: 1rem;
    padding: 1.25rem 1.5rem;
    border-radius: 12px;
    background: linear-gradient(135deg, #0f3d6b 0%, #1a5490 45%, #2563eb 100%);
    color: var(--dfl-on-brand, #fff);
    box-shadow: 0 8px 24px rgba(15, 61, 107, 0.25);
}

/* Home's hero (Home.razor) nests the blue bar in .dfl-standings-hero__group and adds the
   .dfl-sport-leaders strip as a second child of .dfl-standings-hero--home. Below 1440px this outer
   wrapper collapses (display:contents) so the bar and the strip render as independent siblings —
   byte-identical to the layout before this nesting existed. color:inherit stops the strip
   inheriting the bar's white text through the collapsed wrapper. The override that pulls the strip
   *into* the bar is the @media (min-width: 1440px) block further down. */
.dfl-standings-hero--home {
    display: contents;
    color: inherit;
}

/* Home only — tighter top/bottom so the sport-card row isn't floating on a thick blue margin.
   Applies to the >=1440px bar (--home) and the <1440px bar (__group). Sits before the 720px block
   so the phone padding still wins there. MyTeams' bare .dfl-standings-hero keeps the base padding. */
.dfl-standings-hero--home,
.dfl-standings-hero__group {
    padding-top: 0.625rem;
    padding-bottom: 0.625rem;
}

.dfl-standings-hero__text {
    display: flex;
    align-items: center;
    gap: 1.25rem;
}

.dfl-standings-hero__logo {
    display: block;
    flex-shrink: 0;
    height: 8rem;
    width: auto;
    object-fit: contain;
}

/* 1900px matches the header nav's hamburger breakpoint (MainLayout.razor.css /
   HeaderNavPanel.razor.css) — hide the hero logo once the site is in mobile-nav mode
   so the hero doesn't dominate the viewport on narrow screens. */
@media (max-width: 1900px) {
    .dfl-standings-hero__logo {
        display: none;
    }
}

.dfl-standings-hero__copy {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.dfl-standings-hero__eyebrow {
    display: inline-block;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.85;
}

.dfl-standings-hero__title {
    margin: 0.2rem 0 0;
    font-size: 1.85rem;
    color: var(--dfl-on-brand, #fff);
}

.dfl-standings-hero__phase {
    margin: 0.35rem 0 0;
    opacity: 0.9;
    font-size: 0.9rem;
}

.dfl-podium {
    display: flex;
    align-items: flex-end;
    gap: 0.6rem;
}

.dfl-podium__slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    min-width: 5.25rem;
}

/* The pedestal is now the tiered colored riser that contains the info inside the color */
.dfl-podium__pedestal {
    width: 100%;
    border-radius: 10px 10px 4px 4px;
    backdrop-filter: blur(4px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start; /* data lives near the top of the colored riser */
    padding: 0.4rem 0.3rem 0.3rem;
    gap: 0.12rem;
    text-align: center;
    box-sizing: border-box;
}

/* Tiered heights: 1st tallest/highest (gold), 2nd medium (silver), 3rd shortest/lowest (bronze).
   Content sits inside the colored areas (at the top). Gold and silver have extra riser height below the labels
   so they visibly rise higher than bronze (bronze is kept snug to fit its content without shrinking further). */
.dfl-podium__slot--1 .dfl-podium__pedestal {
    min-height: 10rem;
    background: rgba(var(--dfl-gold-rgb, 255, 215, 0), 0.52);
    box-shadow: inset 0 0 0 1px rgba(var(--dfl-gold-rgb, 255, 215, 0), 0.55);
}

.dfl-podium__slot--2 .dfl-podium__pedestal {
    min-height: 9rem;
    background: rgba(var(--dfl-silver-rgb, 192, 192, 192), 0.50);
    box-shadow: inset 0 0 0 1px rgba(var(--dfl-silver-rgb, 192, 192, 192), 0.55);
}

.dfl-podium__slot--3 .dfl-podium__pedestal {
    min-height: 8rem;
    background: rgba(var(--dfl-bronze-rgb, 205, 127, 50), 0.50);
    box-shadow: inset 0 0 0 1px rgba(var(--dfl-bronze-rgb, 205, 127, 50), 0.55);
}

.dfl-podium__medal {
    font-size: 1.05rem;
    font-weight: 900;
    line-height: 1;
    margin-bottom: 0.1rem;
}

.dfl-podium__name {
    font-size: 0.68rem;
    font-weight: 700;
    text-align: center;
    max-width: 5.1rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.05;
}

.dfl-podium__score {
    font-size: 1.0rem;
    font-weight: 800;
    line-height: 1;
}

.dfl-podium__delta {
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1;
}

/* True-phone breakpoint (matches .summary-hero__title's own 720px cutoff). The desktop podium's
   tiered risers (up to 10rem tall) are the whole space problem, not the layout — so below 720px
   this keeps the same stacked "text row, podium wrapped below" shape and 3-up row/DOM order as
   desktop, and just collapses every riser to one small flat height instead of restructuring into
   stacked rows (a stacked-rows-within-the-podium attempt read worse than the plain tall version —
   flattening each riser in place is the safer, smaller change). Rank tint backgrounds
   (.dfl-podium__slot--1/2/3 .dfl-podium__pedestal) are untouched so color still signals place
   without height doing it. Only .dfl-standings-hero's own vertical padding/gap is trimmed beyond
   that — text and podium chip sizes stay exactly as flattened above; the container's padding is
   the actual source of extra banner height, not the content inside it. */
@media (max-width: 720px) {
    .dfl-standings-hero,
    .dfl-standings-hero__group {
        padding: 0.65rem 0.9rem;
        gap: 0.4rem;
    }

    .dfl-standings-hero__title {
        font-size: 1.3rem;
    }

    .dfl-podium {
        gap: 0.35rem;
    }

    .dfl-podium__slot {
        min-width: 0;
        flex: 1 1 0;
    }

    .dfl-podium__pedestal {
        padding: 0.5rem 0.3rem 0.55rem;
        gap: 0.05rem;
        border-radius: 8px;
    }

    /* The tiered min-height (10rem/9rem/8rem) is set on these higher-specificity
       .dfl-podium__slot--N .dfl-podium__pedestal selectors (2 classes), not on the bare
       .dfl-podium__pedestal rule above (1 class) — a min-height: 0 on the bare rule loses the
       cascade to these regardless of source order, so it must be overridden here directly. */
    .dfl-podium__slot--1 .dfl-podium__pedestal,
    .dfl-podium__slot--2 .dfl-podium__pedestal,
    .dfl-podium__slot--3 .dfl-podium__pedestal {
        min-height: 0;
    }

    .dfl-podium__medal {
        font-size: 0.72rem;
        margin-bottom: 0;
    }

    .dfl-podium__pedestal .member-badge__avatar,
    .dfl-podium__pedestal .member-badge__photo {
        width: 24px !important;
        height: 24px !important;
        font-size: 0.55rem !important;
    }

    .dfl-podium__name {
        font-size: 0.58rem;
        max-width: 100%;
    }

    .dfl-podium__score {
        font-size: 0.78rem;
    }

    .dfl-podium__delta {
        font-size: 0.56rem;
    }
}

/* Home hero, 1440px and up. --home stops being display:contents and becomes the blue bar itself;
   .dfl-standings-hero__group collapses, so the logo/text and the podium become direct flex items
   alongside the .dfl-sport-leaders row. Order is text | cards | podium. The cards keep the base
   .dfl-sport-leaders flex row (only order/grow/margin/text-color differ from the standalone strip)
   and are pinned to a non-shrinking 6rem here. Below 1440px this block is inert and the strip
   renders below the bar. */
@media (min-width: 1440px) {
    .dfl-standings-hero--home {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: 1.5rem;
        color: var(--dfl-on-brand, #fff);
    }

    .dfl-standings-hero--home > .dfl-standings-hero__group {
        display: contents;
    }

    .dfl-standings-hero--home > .dfl-sport-leaders {
        order: 1;
        flex: 1 1 auto;
        min-width: 0;
        margin: 0;
        /* undo the bar's white text so the MemberBadge name (which only sets font-weight) reads on
           the light cards; card elements with their own color are unaffected */
        color: var(--dfl-text, #16202e);
    }

    /* fixed 6rem, no shrink (the base card is 6rem but shrinkable) */
    .dfl-standings-hero--home > .dfl-sport-leaders .dfl-sport-leader-card {
        flex: 0 0 6rem;
    }

    .dfl-standings-hero--home .dfl-podium {
        order: 2;
    }
}

.dfl-standings-card__header {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin-bottom: 0.75rem;
}

.dfl-standings-card__header h2 {
    margin: 0;
}

.dfl-sheet-tag {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background: var(--dfl-surface-alt, #e8f4f8);
    color: var(--dfl-brand-dark, #0f3d6b);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.dfl-sheet-tag--live {
    background: var(--dfl-warning-bg, #fef3c7);
    color: var(--dfl-warning-text, #92400e);
    animation: dfl-live-pulse 2s ease-in-out infinite;
}

/* Pulse without the amber "Live" color swap - for tags that are live-refreshed data
   but keep their own color scheme (e.g. Home.razor's "Current Score" pill). */
.dfl-sheet-tag--pulse {
    animation: dfl-live-pulse 2s ease-in-out infinite;
}

@keyframes dfl-live-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.65; }
}

.dfl-standings-card--proj {
    border-top: 4px solid var(--dfl-brand, #1a5490);
}

.dfl-standings-table--sheet .rank-cell {
    font-weight: 800;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.dfl-standings-table--sheet th,
.dfl-standings-table--sheet td {
    padding: 0.28rem 0.45rem;
    line-height: 1.2;
    vertical-align: middle;
}

/* Make data rows in overall standings match the compact sizing and row height 
   used on individual sport pages (e.g. MLB standings inside .sport-panel + dfl-table-compact).
   This keeps text the same size (0.82rem from compact) and tight row height. */
.dfl-standings-table--sheet tbody td {
    padding: 0.28rem 0.45rem;
    line-height: 1.2;
    vertical-align: middle;
    font-size: 0.82rem;
}

.dfl-standings-table--sheet td:has(.member-badge) {
    line-height: normal;
}

.dfl-standings-table td.sport-col,
.dfl-standings-table th.sport-col {
    background: color-mix(in srgb, var(--sc-bg, transparent) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.dfl-standings-table tr.subhead th.sport-col {
    background: color-mix(in srgb, var(--sc-bg, var(--dfl-surface-hover, #f8fafc)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sc-fg, var(--dfl-brand-dark, #0f3d6b)));
}

.standings-row-gold td {
    background: rgba(var(--dfl-gold-rgb, 255, 215, 0), 0.2);
}

.standings-row-gold td.sport-col {
    background: linear-gradient(rgba(var(--dfl-gold-rgb, 255, 215, 0), 0.3), rgba(var(--dfl-gold-rgb, 255, 215, 0), 0.3)), color-mix(in srgb, var(--sc-bg, white) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.standings-row-silver td {
    background: rgba(var(--dfl-silver-rgb, 192, 192, 192), 0.24);
}

.standings-row-silver td.sport-col {
    background: linear-gradient(rgba(var(--dfl-silver-rgb, 192, 192, 192), 0.35), rgba(var(--dfl-silver-rgb, 192, 192, 192), 0.35)), color-mix(in srgb, var(--sc-bg, white) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.standings-row-bronze td {
    background: rgba(var(--dfl-bronze-rgb, 205, 127, 50), 0.2);
}

.standings-row-bronze td.sport-col {
    background: linear-gradient(rgba(var(--dfl-bronze-rgb, 205, 127, 50), 0.3), rgba(var(--dfl-bronze-rgb, 205, 127, 50), 0.3)), color-mix(in srgb, var(--sc-bg, white) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.standings-row-emerald td {
    background: rgba(var(--dfl-emerald-rgb, 46, 139, 87), 0.2);
}

.standings-row-emerald td.sport-col {
    background: linear-gradient(rgba(var(--dfl-emerald-rgb, 46, 139, 87), 0.3), rgba(var(--dfl-emerald-rgb, 46, 139, 87), 0.3)), color-mix(in srgb, var(--sc-bg, white) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.standings-row-ruby td {
    background: rgba(var(--dfl-ruby-rgb, 244, 114, 137), 0.2);
}

.standings-row-ruby td.sport-col {
    background: linear-gradient(rgba(var(--dfl-ruby-rgb, 244, 114, 137), 0.3), rgba(var(--dfl-ruby-rgb, 244, 114, 137), 0.3)), color-mix(in srgb, var(--sc-bg, white) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.standings-total-row td {
    border-top: 2px solid var(--dfl-border-strong, #cbd5e1);
    background: var(--dfl-surface-hover, #f8fafc);
    font-size: 0.8rem;
}

.standings-total-label {
    font-weight: 700;
    text-align: left;
}

.sport-score-hot {
    font-weight: 700;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.money-cell {
    font-weight: 700;
    color: var(--dfl-success-strong, #14532d);
}

.payout-balance--ok td {
    color: var(--dfl-success-strong, #14532d);
}

.payout-balance--warn td {
    color: var(--dfl-danger, #b91c1c);
}

.dfl-standings-footnote {
    margin-top: 0.75rem;
}

.dfl-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: 0.75rem 1rem;
    margin-bottom: 1rem;
}

.dfl-form-grid--single {
    grid-template-columns: minmax(12rem, 20rem);
}

.dfl-profile-avatar-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

.dfl-profile-nav {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.dfl-profile-nav a {
    color: var(--dfl-brand, #1a5490);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.9rem;
}

.dfl-profile-nav a.active {
    color: var(--dfl-brand-dark, #0f3d6b);
    text-decoration: underline;
}

.dfl-form-grid label {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.dfl-input {
    padding: 0.4rem 0.55rem;
    border: 1px solid var(--dfl-border, #d1d9e0);
    border-radius: 4px;
    font-size: 0.9rem;
}

.dfl-input--narrow {
    max-width: 5.5rem;
}

.dfl-checkbox-label {
    flex-direction: row !important;
    align-items: center;
    gap: 0.45rem !important;
}

.dfl-file-input {
    font-size: 0.78rem;
    max-width: 10rem;
}

.member-inactive-row td {
    opacity: 0.55;
}

.commissioner-member-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

/* The "View As" impersonation control is a real <form> (needs an HTTP POST to swap the auth
   cookie) — let its button sit in the flex row like the sibling <button>s instead of forcing a
   line break. */
.commissioner-impersonate-form {
    display: contents;
}

/* A single centred, non-wrapping row. Cards want 6rem (flex-basis, below) and never grow past it;
   they shrink together only once 7 x 6rem + gaps won't fit. Not a grid — minmax(0, 6rem) tracks
   size to content, not to 6rem, so the cards looked too narrow. Below 720px the mobile block makes
   this a horizontal-scroll strip; at/above 1440px the in-hero block pins the cards to a fixed 6rem.
   6rem is the max card width everywhere. */
.dfl-sport-leaders {
    display: flex;
    flex-wrap: nowrap;
    justify-content: center;
    gap: 0.65rem;
    margin-bottom: 1rem;
}

.dfl-sport-leader-card {
    flex: 0 1 6rem;
    min-width: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.375rem 0.5rem;
    border-radius: 10px;
    background: var(--dfl-surface, #fff);
    border: 2px solid var(--sport-accent-soft, var(--dfl-border, #e5e7eb));
    box-shadow: 0 2px 8px rgba(15, 61, 107, 0.06);
    text-align: center;
    min-height: 6.5rem;
}

.dfl-sport-leader-card.is-active {
    border-color: var(--sport-accent, var(--dfl-brand, #1a5490));
    background: linear-gradient(180deg, color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff)), var(--dfl-surface, #fff) 55%);
}

.dfl-sport-leader-card.is-inactive {
    opacity: var(--dfl-inactive-opacity, 0.65);
}

/* Clip a long member name to the card width instead of letting it wrap and make the card taller. */
.dfl-sport-leader-card .member-badge__name {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dfl-sport-leader-card__label {
    display: inline-block;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

.dfl-sport-leader-card__score {
    font-size: 1.15rem;
    font-weight: 800;
    color: var(--dfl-brand-dark, #0f3d6b);
    line-height: 1;
}

.dfl-sport-leader-card__caption {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--dfl-text-muted, #6b7280);
}

.dfl-sport-leader-card__pending {
    font-size: 0.78rem;
    font-weight: 600;
    margin-top: 0.35rem;
}

/* Mobile: below 720px the 7 cards can't stay at 6rem, so drop to overflow-x:auto (a phone too
   narrow to fit all 7 scrolls, same pattern as .dfl-sport-nav) and shrink each card's own width
   and internals (min-width, padding, avatar/logo/font sizes). The flex-column stacking (sport
   block, MemberBadge, score, caption) is kept so a card only grows taller, never wider. */
@media (max-width: 720px) {
    .dfl-sport-leaders {
        display: flex;
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        /* not center — base's justify-content:center would hide the leftmost card behind the
           scrollport edge on a phone too narrow to fit all 7 */
        justify-content: flex-start;
        gap: 0.3rem;
        margin-bottom: 0.75rem;
    }

    .dfl-sport-leader-card {
        flex: 1 1 0;
        min-width: 2.9rem;
        min-height: 0;
        padding: 0.3rem 0.1rem;
        gap: 0.15rem;
        border-radius: 8px;
        border-width: 1.5px;
    }

    .dfl-sport-leader-card__sport {
        gap: 0.1rem;
    }

    .dfl-sport-leader-card__sport .sport-logo {
        width: 20px;
        height: 20px;
    }

    .dfl-sport-leader-card__label {
        font-size: 0.5rem;
        padding: 0.05rem 0.25rem;
    }

    .dfl-sport-leader-card .member-badge {
        gap: 0.2rem;
    }

    .dfl-sport-leader-card .member-badge__avatar,
    .dfl-sport-leader-card .member-badge__photo {
        width: 16px !important;
        height: 16px !important;
        font-size: 0.4rem !important;
    }

    .dfl-sport-leader-card .member-badge__name {
        font-size: 0.52rem;
        max-width: 3.4rem;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .dfl-sport-leader-card__score {
        font-size: 0.78rem;
    }

    .dfl-sport-leader-card__caption {
        font-size: 0.5rem;
    }

    .dfl-sport-leader-card__pending {
        font-size: 0.56rem;
        margin-top: 0.1rem;
    }
}

a.sport-link--pill {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
    color: var(--dfl-on-brand, #fff) !important;
    text-decoration: none;
    font-weight: 700;
}

a.sport-link--pill:hover {
    filter: brightness(1.08);
    text-decoration: none;
}

a.sport-link {
    color: var(--dfl-brand, #1a5490);
    text-decoration: none;
}

a.sport-link:hover {
    text-decoration: underline;
}

.dfl-table-compact th,
.dfl-table-compact td {
    font-size: 0.82rem;
}

.dfl-pick-sheet-wrap {
    max-height: 70vh;
}

table.dfl-pick-sheet th.member-col,
table.dfl-pick-sheet td.pick-cell {
    text-align: center;
    min-width: 2.25rem;
    padding-left: 0.35rem;
    padding-right: 0.35rem;
}

table.dfl-pick-sheet th.member-col {
    background: color-mix(in srgb, var(--member-bg, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--member-fg, var(--dfl-brand-dark, #0f3d6b)));
    font-weight: 800;
    font-size: 0.72rem;
}

table.dfl-pick-sheet th.member-col .member-badge {
    justify-content: center;
    margin: 0 auto;
}

table.dfl-pick-sheet td.pick-cell.picked {
    background: color-mix(in srgb, var(--member-bg, var(--dfl-success-bg, #dcfce7)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--member-fg, var(--dfl-success, #15803d)));
    font-weight: 800;
}

table.dfl-pick-sheet .sticky-col {
    position: sticky;
    left: 0;
    background: var(--dfl-surface, #fff);
    z-index: 1;
    box-shadow: 2px 0 4px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.04);
}

table.dfl-pick-sheet thead .sticky-col {
    background: var(--dfl-surface-alt, #eef4f9);
}

.pick-list {
    white-space: normal;
    max-width: 8rem;
}

.member-pick-logos {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: nowrap;
}

.member-pick-logos .team-logo {
    width: 1.75rem;
    height: 1.75rem;
}

.sport-pill {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
    color: var(--dfl-on-brand, #fff);
    font-weight: 700;
    font-size: 0.82rem;
}

.seed-input {
    width: 4rem;
    padding: 0.2rem 0.35rem;
}

.winner-select {
    min-width: 12rem;
    max-width: 100%;
}

.tier-breakdown-list {
    margin: 0;
    padding-left: 1.1rem;
    font-size: 0.78rem;
}

.tier-breakdown-cell {
    min-width: 16rem;
}

.scoring-detail-table td {
    vertical-align: top;
}

.scoring-math-formulas {
    margin-bottom: 0.75rem;
    font-size: 0.85rem;
    color: var(--dfl-text, #374151);
}

.scoring-math-formulas p {
    margin: 0.25rem 0;
}

.scoring-math-table th {
    font-size: 0.72rem;
    white-space: nowrap;
}

.scoring-math-note-row td {
    font-size: 0.75rem;
    padding-top: 0;
    border-top: none;
}

.scoring-math-example {
    margin: 0.75rem 0 0;
    font-size: 0.85rem;
    color: var(--dfl-text, #374151);
}

.odds-source-details {
    margin: 0.5rem 0 0;
    padding-left: 1.25rem;
    font-size: 0.85rem;
    color: var(--dfl-text-muted, #4b5563);
}

.member-score-breakdown-table .member-totals-cell {
    font-size: 0.85rem;
    vertical-align: top;
    min-width: 7rem;
}

.member-score-breakdown-table .member-totals-cell div {
    margin-bottom: 0.2rem;
}

.league-scoring-table th.section-sport {
    font-size: 0.75rem;
    text-align: center;
}

.league-scoring-table th.section-overall {
    text-align: center;
}

.league-scoring-table td {
    text-align: right;
    font-size: 0.85rem;
}

.league-scoring-table td:first-child {
    text-align: left;
}

.dfl-sheet-note {
    margin-top: 0;
    color: var(--dfl-text-muted, #6b7280);
    font-size: 0.85rem;
}

.rules-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1rem;
}

.rules-grid .dfl-card h3 {
    margin-top: 0;
}

#blazor-error-ui {
    background: var(--dfl-danger, #b32121);
    bottom: 0;
    box-shadow: 0 -1px 4px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    color: var(--dfl-on-brand, #fff);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 1rem;
    top: 0.5rem;
}

.dfl-playoff-nav {
    display: flex;
    gap: 0.35rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.playoff-nav-item {
    text-decoration: none;
    color: var(--dfl-brand-dark, #0f3d6b);
    font-size: 0.85rem;
    font-weight: 600;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    border: 1px solid var(--dfl-border, #d1d9e0);
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

.playoff-nav-item.active {
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
    border-color: var(--sport-accent, var(--dfl-brand, #1a5490));
    color: var(--dfl-on-brand, #fff);
}

.playoff-nav-item.inactive {
    opacity: var(--dfl-inactive-opacity, 0.45);
}

.playoff-panel h1 {
    margin-top: 0;
}

/* Scroll boundary for .bracket-tree — on narrow viewports the tree grows wider than the
   viewport (see the 900px media query below) instead of squeezing every column down to an
   illegible width; this wrapper is what turns that overflow into a swipeable scroll region
   instead of clipping it or spilling into the rest of the page. No-op on desktop, where the
   tree still fits at width:100% and never overflows this wrapper. */
.bracket-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* The tree is content-sized (fit-content), not viewport-sized: each round column grows to fit
   its longest team name (see .bracket-col--left/--right below), and the tree grows to the sum of
   those columns. margin-inline:auto centers it while it fits; once the columns total more than the
   available width, .bracket-scroll's overflow-x:auto turns the excess into a horizontal scroll
   (justify-content:flex-start, not center, so that overflow stays reachable from the left edge). */
.bracket-tree {
    --bracket-line: #94a3b8;
    --bracket-game-base: 3.25rem;
    display: flex;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    overflow: visible;
    width: fit-content;
    max-width: 100%;
    margin-inline: auto;
    padding: 1rem 0.25rem 1.25rem;
    min-height: 18rem;
}

.bracket-tree__wing {
    display: flex;
    align-items: stretch;
    flex: 0 0 auto;
}

.bracket-tree__wing--single {
    margin: 0 auto;
}

.bracket-col {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-width: 0;
    max-width: 11rem;
    padding: 0 0.85rem;
}

/* Round columns size to content, not to an equal share of the viewport: flex:0 0 auto keeps each
   at its natural width (widest team name in the column + logo/seed/gutter), with a floor so the
   normal-length columns still line up cleanly and only a genuinely long name pushes its column
   wider. No max-width — a long name grows the column (and the tree) rather than being ellipsed.
   .bracket-col--center keeps its own flex:0 0 auto + min/max-width rule below. */
.bracket-col--left,
.bracket-col--right {
    flex: 0 0 auto;
    min-width: 9.5rem;
    max-width: none;
}

.bracket-col__label {
    flex-shrink: 0;
    margin-bottom: 0.65rem;
    font-size: 0.65rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--dfl-text-muted, #6b7280);
    text-align: center;
    min-height: 1.5rem;
}

.bracket-col__games {
    position: relative;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
    min-height: calc(var(--bracket-game-base) * max(var(--match-count, 2), 2) * 1.45);
    gap: 0.35rem;
}

.bracket-col__games--center {
    justify-content: center;
    min-height: 100%;
}

.bracket-game {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 auto;
    min-height: var(--bracket-game-base);
    padding: 0.35rem 0;
}

.bracket-tree--nfl {
    --bracket-game-base: 4rem;
    min-height: 22rem;
}

.bracket-tree--nfl .bracket-col__games {
    min-height: calc(var(--bracket-game-base) * var(--match-count, 3) * 2.15);
    gap: 0.85rem;
    padding: 0.25rem 0;
}

.bracket-tree--nfl .bracket-game {
    min-height: calc(var(--bracket-game-base) + 0.5rem);
    padding: 0.55rem 0;
}

/* Reseed columns (currently only NFL's Wild Card round) have no fixed next-round slot to
   draw a connector to — see RoundTransition.Reseed in PlayoffBracketLayout.cs. Lay their
   games out evenly across the column instead of relying on bracket-pair bunching. */
.bracket-col--reseed .bracket-col__games {
    justify-content: space-between;
}

.bracket-tree--nba,
.bracket-tree--nhl,
.bracket-tree--ncaab,
.bracket-tree--uefacl {
    --bracket-game-base: 4.25rem;
    min-height: 28rem;
}

.bracket-tree--nba .bracket-col__games,
.bracket-tree--nhl .bracket-col__games,
.bracket-tree--ncaab .bracket-col__games,
.bracket-tree--uefacl .bracket-col__games {
    min-height: calc(var(--bracket-game-base) * var(--match-count, 4) * 2.35);
    gap: 1rem;
    padding: 0.35rem 0;
}

.bracket-tree--nba .bracket-game,
.bracket-tree--nhl .bracket-game,
.bracket-tree--ncaab .bracket-game,
.bracket-tree--uefacl .bracket-game {
    min-height: calc(var(--bracket-game-base) + 0.65rem);
    padding: 0.6rem 0;
    flex-shrink: 0;
}

.bracket-tree--nba .bracket-pair,
.bracket-tree--nhl .bracket-pair,
.bracket-tree--ncaab .bracket-pair,
.bracket-tree--uefacl .bracket-pair {
    flex: 1 1 auto;
    min-height: calc(var(--bracket-game-base) * 2 + 1.25rem);
    gap: 0.75rem;
}

.bracket-game--final {
    flex: 1;
    min-height: 6rem;
}

.bracket-pair {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    min-height: 0;
}

/* Connector lines — Merge columns (left wing): game → pair spine → next round.
   Two adjacent games in this round converge into one slot in the next column; see
   RoundTransition.Merge in PlayoffBracketLayout.cs. All three pieces below share ONE x-axis
   convention so they actually meet instead of leaving a gap: each piece starts exactly where
   the previous one ends.
     game stub:     [0, 0.55rem]        starts at the game's own right edge, goes right
     vertical spine: at 0.55rem         catches both game stubs' outer tips
     continuation:  [0.55rem, 1.65rem]  picks up at the spine and keeps going right
   (An earlier version anchored the game stub and spine at `right:0`/`right:0.55rem` — both
   measured as offsets INTO the card from its own edge — which put the spine at x=-0.55rem
   while the continuation started at x=0, leaving a 0.55rem gap between the vertical spine and
   the line that's supposed to continue from it. Anchoring with `left:100%`/`right:-Nrem`
   instead puts every piece in gutter-space, all sharing the same zero point.) */
.bracket-col--merge.bracket-col--left:not(:last-child) .bracket-game::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 100%;
    width: 0.55rem;
    border-top: 2px solid var(--bracket-line);
    transform: translateY(-50%);
    pointer-events: none;
}

.bracket-col--merge.bracket-col--left:not(:last-child) .bracket-pair:has(.bracket-game:nth-child(2))::before {
    content: "";
    position: absolute;
    top: 25%;
    bottom: 25%;
    right: -0.55rem;
    width: 2px;
    background: var(--bracket-line);
    pointer-events: none;
}

.bracket-col--merge.bracket-col--left:not(:last-child) .bracket-pair::after {
    content: "";
    position: absolute;
    top: 50%;
    right: -1.65rem;
    width: 1.1rem;
    border-top: 2px solid var(--bracket-line);
    transform: translateY(-50%);
    pointer-events: none;
}

/* Connector lines — Merge columns (right wing), mirrored (gutter is to the left, not right) */
.bracket-col--merge.bracket-col--right:not(:first-child) .bracket-game::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 100%;
    width: 0.55rem;
    border-top: 2px solid var(--bracket-line);
    transform: translateY(-50%);
    pointer-events: none;
}

.bracket-col--merge.bracket-col--right:not(:first-child) .bracket-pair:has(.bracket-game:nth-child(2))::before {
    content: "";
    position: absolute;
    top: 25%;
    bottom: 25%;
    left: -0.55rem;
    width: 2px;
    background: var(--bracket-line);
    pointer-events: none;
}

.bracket-col--merge.bracket-col--right:not(:first-child) .bracket-pair::after {
    content: "";
    position: absolute;
    top: 50%;
    left: -1.65rem;
    width: 1.1rem;
    border-top: 2px solid var(--bracket-line);
    transform: translateY(-50%);
    pointer-events: none;
}

/* Connector lines — Direct columns: this round has the same game count as the next round,
   so each game advances 1:1 into a fixed slot (e.g. a wild-card winner joining a bye seed)
   at the same row position — no spine needed, just one straight line across the gap. See
   RoundTransition.Direct in PlayoffBracketLayout.cs. Same gutter-space convention as the Merge
   columns above (starts at the game's own edge via `left:100%`/`right:100%`, not inside the
   card) and the same total reach (1.65rem) so both connector styles read as one system. */
.bracket-col--direct.bracket-col--left:not(:last-child) .bracket-game::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 100%;
    width: 1.65rem;
    border-top: 2px solid var(--bracket-line);
    transform: translateY(-50%);
    pointer-events: none;
}

.bracket-col--direct.bracket-col--right:not(:first-child) .bracket-game::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 100%;
    width: 1.65rem;
    border-top: 2px solid var(--bracket-line);
    transform: translateY(-50%);
    pointer-events: none;
}

/* Reseed columns intentionally draw no connector at all — see RoundTransition.Reseed. */

.bracket-col--center {
    flex: 0 0 auto;
    min-width: 9.5rem;
    max-width: 11.5rem;
    padding: 0 1rem;
    z-index: 1;
}

.playoff-panel {
    overflow: visible;
}

.bracket-col--center .bracket-col__label {
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.72rem;
}

.bracket-col--center .bracket-game--final::before,
.bracket-col--center .bracket-game--final::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 1.25rem;
    border-top: 2px solid var(--bracket-line);
    pointer-events: none;
}

.bracket-tree--dual .bracket-col--center .bracket-game--final::before {
    left: -1.25rem;
}

.bracket-tree--dual .bracket-col--center .bracket-game--final::after {
    right: -1.25rem;
}

.bracket-tree--single .bracket-col--center .bracket-game--final::before {
    left: -1.25rem;
}

.bracket-match {
    width: 100%;
    display: grid;
    gap: 0.2rem;
    background: var(--dfl-surface, #fff);
    border: 1px solid var(--dfl-border, #d1d9e0);
    border-radius: 8px;
    padding: 0.3rem;
    box-shadow: 0 1px 3px rgba(15, 61, 107, 0.06);
}

.bracket-match--final {
    border-color: var(--sport-accent, var(--dfl-brand, #1a5490));
    box-shadow: 0 2px 8px rgba(15, 61, 107, 0.12);
    background: linear-gradient(180deg, color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff)), var(--dfl-surface, #fff) 70%);
}

.bracket-team {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--dfl-surface-hover, #f9fbfd);
    border: 1px solid var(--dfl-border, #e5e7eb);
    border-radius: 6px;
    padding: 0.35rem 0.45rem;
    min-height: 2.1rem;
}

.bracket-team .team-logo {
    width: 1.35rem;
    height: 1.35rem;
}

.bracket-team.is-winner {
    border-color: var(--dfl-success, #15803d);
    background: var(--dfl-success-bg, #f0fdf4);
    box-shadow: inset 0 0 0 1px rgba(var(--dfl-success-rgb, 21, 128, 61), 0.15);
}

.bracket-team.is-tbd {
    color: var(--dfl-text-muted, #9ca3af);
    font-style: italic;
    background: var(--dfl-surface-hover, #fafafa);
}

.bracket-team__seed {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.4rem;
    height: 1.4rem;
    border-radius: 4px;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.68rem;
    font-weight: 800;
    flex-shrink: 0;
}

/* No min-width:0 — this column's min-content (the nowrap team name) is what pushes .bracket-team,
   .bracket-match and finally .bracket-col--left/--right wide enough to show the full name. */
.bracket-team__info {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
}

/* Names are never truncated — nowrap only, so the name's intrinsic width propagates up and grows
   the round column (see .bracket-col--left/--right). */
.bracket-team__name {
    font-size: 0.76rem;
    font-weight: 600;
    white-space: nowrap;
}

.bracket-team__owner {
    font-size: 0.62rem;
    font-weight: 500;
    color: var(--dfl-text-muted, #6b7280);
    white-space: nowrap;
}

/* The content-sized column model (flex:0 0 auto + fit-content tree + .bracket-scroll overflow) now
   applies at every width — see .bracket-col--left/--right and .bracket-tree above. On phones just
   tighten the per-column floor and gutter so a narrow name column isn't wastefully wide, and drop
   max-width:100% on the tree so it can grow past the viewport into the scroll region unimpeded. */
@media (max-width: 900px) {
    .bracket-col--left,
    .bracket-col--right {
        min-width: 8.5rem;
        padding: 0 0.75rem;
    }

    .bracket-tree {
        max-width: none;
    }
}

.draft-clock-card {
    position: sticky;
    top: 4.75rem; /* stick below the persistent site header (dfl-header) so it remains visible when scrolling the draft board */
    z-index: 30;
    padding: 0.5rem 0.85rem;
    margin-bottom: 0.75rem;
}

@media (max-width: 899px) {
    .draft-clock-card {
        top: 3.75rem; /* shorter mobile header */
    }
}

.draft-clock-card__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.25rem;
}

.draft-clock-card__who {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.45rem 0.65rem;
    flex: 1 1 16rem;
    min-width: 0;
}

.draft-clock-card__label {
    font-size: 0.82rem;
    font-weight: 800;
    color: var(--dfl-brand, #1a5490);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.draft-clock-card__member {
    font-weight: 700;
    font-size: 0.9rem;
}

.draft-clock-card__status {
    flex: 1 1 12rem;
    min-width: 0;
    font-size: 0.82rem;
}

.draft-your-turn {
    color: var(--dfl-success, #15803d);
    font-weight: 700;
}

.draft-clock-card--yours {
    border: 2px solid var(--dfl-success, #15803d);
    box-shadow: 0 0 0 3px rgba(var(--dfl-success-rgb, 21, 128, 61), 0.15);
}

.draft-live-tag {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: var(--dfl-warning-bg, #fef3c7);
    color: var(--dfl-warning-text, #92400e);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.dfl-draft-room {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.dfl-draft-card__header {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-bottom: 0.35rem;
}

.dfl-draft-card__header h2 {
    margin: 0;
}

.draft-clock-card__pick {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.draft-last-pick {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    margin-top: 0.4rem;
    padding: 0.45rem 0.5rem;
    border-top: 1px solid var(--dfl-border, #e5e7eb);
    border-left: 3px solid var(--sport-accent, var(--dfl-border-strong, #cbd5e1));
    border-radius: 0 4px 4px 0;
    background: linear-gradient(90deg, color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface, #fff)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff)) 0%, var(--dfl-surface, #fff) 65%);
    font-size: 0.78rem;
}

.draft-last-pick .team-logo {
    width: 1.35rem;
    height: 1.35rem;
    flex-shrink: 0;
}

.draft-last-pick__label,
.draft-last-pick__member {
    color: var(--dfl-text-muted, #4b5563);
}

.draft-last-pick__pick,
.draft-last-pick__sport,
.draft-last-pick__team,
.draft-last-pick__proj {
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

.dfl-draft-chart-picks-row {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 1rem;
    align-items: start;
    margin-bottom: 1rem;
}

/* Draft History — the Recent Picks table has 2 more columns than the live-draft list, needs more room. */
.dfl-draft-chart-picks-row--history {
    grid-template-columns: 3fr 2fr;
}

.dfl-draft-teams-wrap {
    overflow-x: auto;
}

/* min-width:0 overrides the grid item's automatic (content-based) minimum width — without it, the
   nested chart's `min-width: 40rem` (.draft-roster-chart below) bubbles up through this card and
   inflates the `.dfl-draft-chart-picks-row` grid track instead of staying contained, which defeats
   `.dfl-draft-chart-scroll`'s overflow-x:auto and widens the whole page on mobile instead of just
   scrolling the chart. */
.dfl-draft-roster-chart-card {
    margin-bottom: 0;
    min-width: 0;
}

.dfl-draft-chart-scroll {
    overflow-x: auto;
}

.dfl-draft-recent-card {
    display: flex;
    flex-direction: column;
}

.draft-roster-chart {
    display: grid;
    grid-template-columns: 2.75rem minmax(0, 1fr) minmax(5.5rem, 7rem);
    gap: 0.75rem 1rem;
    align-items: stretch;
    margin-top: 1.1rem;
    padding-top: 0.65rem;
    min-width: 40rem;
}

.draft-roster-chart__y-axis {
    position: relative;
    height: 15rem;
    /* Must match .draft-roster-chart__grid's bottom inset and .draft-roster-chart__bars'
       margin-bottom — all three define the same 0-baseline distance from the bottom edge.
       Sized to fit the member name overflowing below the 0-line, plus (in dual/ShowCurrent
       mode) the Draft/Curr sublabels row that now also overflows below rather than sitting
       inside the fixed-height bar. */
    margin-bottom: 2.75rem;
}

.draft-roster-chart__y-tick {
    position: absolute;
    right: 0;
    transform: translateY(50%);
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--dfl-text-muted, #6b7280);
    line-height: 1;
}

.draft-roster-chart__plot {
    position: relative;
    min-width: 0;
}

.draft-roster-chart__grid {
    position: absolute;
    inset: 0 0 2.75rem;
    pointer-events: none;
}

.draft-roster-chart__grid-line {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px solid var(--dfl-border, #e5e7eb);
}

.draft-roster-chart__bars {
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 0.35rem;
    height: 15rem;
    margin-bottom: 2.75rem;
    padding: 0 0.25rem;
    border-left: 1px solid var(--dfl-text-muted, #9ca3af);
    border-bottom: 1px solid var(--dfl-text-muted, #9ca3af);
}

.draft-roster-chart__column {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 0;
}

.draft-roster-chart__bar-area {
    position: relative;
    flex: none;
    width: 100%;
    height: 15rem;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
}

.draft-roster-chart__total {
    position: absolute;
    top: -1.1rem;
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.62rem;
    font-weight: 800;
    color: var(--dfl-brand-dark, #0f3d6b);
    white-space: nowrap;
}

.draft-roster-chart__stack {
    width: 72%;
    max-width: 3.25rem;
    min-width: 1.35rem;
    display: flex;
    flex-direction: column-reverse;
    justify-content: flex-start;
    border-radius: 3px 3px 0 0;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(15, 61, 107, 0.08);
}

.draft-roster-chart__segment {
    width: 100%;
    min-height: 1px;
    box-sizing: border-box;
}

.draft-roster-chart__member {
    margin-top: 0.35rem;
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--dfl-brand-dark, #0f3d6b);
    text-align: center;
    line-height: 1.15;
    word-break: break-word;
    max-width: 100%;
}

.draft-roster-chart__legend {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding-top: 0.15rem;
}

.draft-roster-chart__legend-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.draft-roster-chart__legend-swatch {
    width: 0.85rem;
    height: 0.85rem;
    border-radius: 2px;
    flex-shrink: 0;
    box-shadow: inset 0 0 0 1px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.12);
}

.draft-roster-chart__legend-label {
    font-size: 0.74rem;
    font-weight: 700;
    line-height: 1.1;
}

/* Draft History page — two bars (Draft/Curr) per member instead of one. Gap here is
   intentionally tighter than .draft-roster-chart__bars' inter-member gap (0.35rem) so the
   Draft/Curr pair reads as one person's grouped bars, not two more columns. */
.draft-roster-chart__bar-pair {
    display: flex;
    gap: 0.15rem;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.draft-roster-chart--dual .draft-roster-chart__bar-area {
    width: auto;
    flex: 1;
    min-width: 0;
}

/* Sublabels live below .bar-pair (a sibling, not nested inside the fixed-height bar-area) so
   "Draft"/"Curr" overflow below the chart's 0-line the same way .draft-roster-chart__member
   does, instead of being packed against the zero line inside the bar's own box. Gap matches
   .bar-pair so each label centers under its own bar. */
.draft-roster-chart__bar-sublabels {
    display: flex;
    gap: 0.15rem;
    justify-content: center;
    width: 100%;
    margin-top: 0.2rem;
}

.draft-roster-chart__bar-sublabel {
    flex: 1;
    text-align: center;
    font-size: 0.55rem;
    font-weight: 700;
    color: var(--dfl-text-muted, #6b7280);
    white-space: nowrap;
}

@media (max-width: 900px) {
    .draft-roster-chart {
        grid-template-columns: 2.25rem minmax(0, 1fr);
    }

    .draft-roster-chart__legend {
        grid-column: 1 / -1;
        flex-flow: row wrap;
        gap: 0.5rem 0.85rem;
    }
}

table.dfl-draft-teams-sheet {
    table-layout: fixed;
    width: 100%;
    min-width: 40rem;
}

table.dfl-draft-teams-sheet th.draft-sport-section {
    text-align: center;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.82rem;
    font-weight: 800;
    border-bottom: 2px solid var(--sport-accent, var(--dfl-border-strong, #cbd5e1));
}

/* Draft History Teams table — Team/Draft/Curr/+/- sub-header row under each sport's spanned header.
   Column widths themselves are set via <colgroup> in the markup (Team via .draft-teams-col-team below,
   2rem each numeric col) — 7 sports * (4.5rem + 3 * 2rem) + 6.5rem sticky Member col ≈ 80rem — wide,
   but this table already scrolls horizontally (.dfl-draft-teams-wrap), same as the Draft Board further
   down. Team names here always render via TeamName's ForceAbbreviated (see DraftBoardCore.razor),
   so this column stays narrow at every viewport width — no responsive jump needed. */
table.dfl-draft-teams-sheet--history {
    min-width: 80rem;
}

/* Team <col> width in the history table — always narrow since TeamName.razor's ForceAbbreviated
   keeps this column showing only the short abbreviation regardless of viewport width. */
.draft-teams-col-team {
    width: 4.5rem;
}

/* Draft Results by Sport table's Team column — wider than .draft-teams-col-team above since every
   entry here also carries a "#NN" pick-number prefix AND the drafting member's avatar ahead of the
   logo + abbreviated name, neither of which the Teams table's stacked slots have; at the narrower
   4.5rem width only 1 of the 3 abbreviation letters stayed visible. Also always narrow — see
   .draft-teams-col-team's comment above. */
.draft-teams-col-team-picks {
    width: 8rem;
}

th.draft-sport-subhead {
    text-align: center;
    font-size: 0.65rem;
    font-weight: 700;
    border-bottom: 2px solid var(--sport-accent, var(--dfl-border-strong, #cbd5e1));
}

/* Higher-specificity redeclare of background/color/padding, matching the
   `table.dfl-draft-teams-sheet th.draft-sport-section` pattern above — needed because the generic
   `table.dfl-draft-teams-sheet th, td { padding; }` rule further down this file (and `table.dfl-table
   th { background; color; }` near the top) both have higher specificity than a bare `.draft-sport-subhead`
   class selector and would otherwise silently win, leaving this row a flat default blue instead of
   each column's sport accent. Also shrinks the generic cell padding so the narrow numeric
   sub-columns below have room to fit "+123"/"-123" on one line. */
table.dfl-draft-teams-sheet th.draft-sport-subhead {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    padding: 0.15rem 0.2rem;
}

/* Column widths themselves come from the <colgroup>/<col> elements in the markup, not from these
   th's — table-layout:fixed is only required to size columns from the FIRST row, and row 1 here is
   the colspan="4" sport-name row (no per-column width to give it), so relying on row 2's widths is
   unreliable across browsers. <col> width is unambiguous regardless of what's in either header row
   (this is why the Draft Board below, which has only one non-spanning header row, never needed this
   — its th widths alone were always enough). */
th.draft-sport-subhead--team {
    text-align: left;
}

/* Shifts "Team" right to start above the name text, not the logo — same
   logo-width + gap offset as .draft-roster-pick's logo (1.25rem) + gap (0.35rem). Needs the
   `table.dfl-draft-teams-sheet` prefix to beat th.draft-sport-subhead's own padding shorthand above,
   same specificity fight already documented on that rule. */
table.dfl-draft-teams-sheet th.draft-sport-subhead--team {
    padding-left: calc(0.2rem + 1.25rem + 0.35rem);
}

table.dfl-draft-teams-sheet .sticky-col,
table.dfl-draft-board .sticky-col {
    position: sticky;
    left: 0;
    background: var(--dfl-surface, #fff);
    z-index: 2;
    box-shadow: 2px 0 4px rgba(15, 61, 107, 0.06);
}

table.dfl-draft-teams-sheet thead .sticky-col,
table.dfl-draft-board thead .sticky-col {
    background: var(--dfl-surface-alt, #eef4f9);
    z-index: 3;
}

table.dfl-draft-teams-sheet .sticky-col {
    width: 6.5rem;
}

/* Centre the "Member" header over its column (the member cells below stay left-aligned).
   Teams roster table only — not the "Draft Results by Sport" picks sheet, whose sticky header is "#". */
table.dfl-draft-teams-sheet:not(.dfl-draft-sport-picks-sheet) thead th.sticky-col {
    text-align: center;
}

td.draft-teams-member-cell {
    vertical-align: middle;
    padding: 0.35rem 0.4rem;
    background: var(--dfl-surface-alt, #eef4f9);
    color: var(--dfl-brand-dark, #0f3d6b);
}

.draft-teams-member {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    min-width: 5.5rem;
}

.draft-teams-member .member-badge {
    --member-badge-size: 32px;
}

.draft-teams-member__name {
    font-size: 0.8rem;
    font-weight: 800;
    line-height: 1.2;
    text-align: center;
    white-space: normal;
    word-break: break-word;
    color: var(--dfl-brand-dark, #0f3d6b);
}

table.dfl-draft-teams-sheet th,
table.dfl-draft-teams-sheet td {
    padding: 0.35rem 0.4rem;
    white-space: normal;
}

/* More defined horizontal separators between member rows */
table.dfl-draft-teams-sheet tbody tr:not(:last-child) td {
    border-bottom: 2px solid var(--dfl-text-muted, #64748b);
}

/* Draft Results by Sport table's rows are pick positions, not members — the Teams table's thicker
   member-row separator above reads as an unwanted line between every pick here, so switch it off.
   Needs the extra .dfl-draft-sport-picks-sheet class to outrank the rule above (0,3,4 vs 0,2,4). */
table.dfl-draft-teams-sheet.dfl-draft-sport-picks-sheet tbody tr:not(:last-child) td {
    border-bottom: none;
}

.draft-roster-sport {
    min-width: 0;
    font-size: 0.76rem;
    vertical-align: top;
    padding: 0.15rem 0.45rem;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-hover, #f9fbfd)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text, #1f2937)));
}

/* Draft History Teams table — column widths are actually driven by the sub-header row under
   table-layout:fixed (see th.draft-sport-subhead above); this just needs to win the specificity
   fight against the generic `table.dfl-draft-teams-sheet th, td { padding: 0.35rem 0.4rem; }` rule
   elsewhere in this file so the narrow Draft/Curr/+/- columns keep the tight padding needed to fit
   "+123"/"-123" on one line — a bare `.draft-roster-sport--value` class selector would lose that
   fight regardless of source order (lower specificity), same trap as th.draft-sport-subhead above. */
table.dfl-draft-teams-sheet td.draft-roster-sport--value {
    padding: 0.1rem 0.35rem 0.1rem 0.05rem;
    text-align: right;
}

/* Matches --value's top/bottom padding above (keeping wider 0.45rem horizontal for the logo+name
   content) — without this, the Team column's padding (from the base .draft-roster-sport rule) would
   sit lower than Draft/Curr/+/- per slot, since each sport's 4 columns are separate <td>s each
   independently stacking one .draft-roster-pick div per slot, not a single shared row — a per-td
   padding mismatch throws off every slot's alignment identically. */
table.dfl-draft-teams-sheet td.draft-roster-sport--team {
    padding: 0.1rem 0.45rem;
}

/* Right-aligned (was center) — a flex row's justify-content:center only matches the MIDPOINT of
   each number across rows, so "5" and "123" share a center but not a ones-place digit position,
   which is what actually reads as "lined up" for a numeric column. flex-end anchors the ones-place
   digit to the same edge every row regardless of value width. */
.draft-roster-sport--value .draft-roster-pick {
    justify-content: flex-end;
}

.draft-roster-pick {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
    min-height: 1.4rem;
    line-height: 1.1;
    padding: 0.05rem 0;
    border-bottom: 1px solid color-mix(in srgb, var(--sport-accent, var(--dfl-border-strong, #cbd5e1)) 18%, transparent);
}

.draft-roster-pick:last-child {
    border-bottom: none;
}

.draft-roster-pick.empty {
    min-height: 1.4rem;
}

.draft-roster-pick .team-logo {
    width: 1.25rem;
    height: 1.25rem;
    flex-shrink: 0;
}

/* Single-line, truncated with an ellipsis rather than wrapping — keeps every slot's row at a fixed,
   minimal height so rows stay as tight as possible (deliberately NOT the Draft Board's 2-line
   .draft-cell__name clamp further down this page — tried here once already and reverted). */
.draft-roster-slot__name {
    flex: 1;
    min-width: 0;
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text, #1f2937)));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.draft-roster-slot__proj {
    flex-shrink: 0;
    font-size: 0.72rem;
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    opacity: 0.9;
}

/* Draft History Teams table +/- column — sizing-only twin of .draft-roster-slot__proj (no `color`)
   so .score-positive/-negative/-inactive (defined earlier in this file) aren't overridden by a
   later same-specificity `color` rule. */
.draft-roster-slot__delta {
    flex-shrink: 0;
    font-size: 0.72rem;
    font-weight: 700;
}

.dfl-draft-board-wrap {
    overflow-x: auto;
}

table.dfl-draft-board thead .sticky-col,
table.dfl-draft-board .sticky-col.draft-board-round,
.draft-board-round {
    text-align: center;
    width: 1.5rem;
    min-width: 1.5rem;
    max-width: 1.5rem;
    padding: 0.25rem 0.15rem;
    font-size: 0.72rem;
    line-height: 1.1;
}

.draft-board-round__dir {
    display: block;
    font-size: 0.58rem;
    color: var(--dfl-text-muted, #6b7280);
    line-height: 1;
}

tr.draft-board-round--current .sticky-col {
    background: var(--dfl-warning-bg, #fef3c7);
}

/* Draft Results by Sport table (DraftHistory.razor only) — reuses the Teams table's sport-header/
   sub-header/roster-pick styling (table.dfl-draft-teams-sheet, --history modifier) since it's the
   same "sport columns x Team/Draft/Curr/+/-" shape, just rows-are-pick-position instead of
   rows-are-member. Needs its own modifier class to narrow the sticky column from the Teams table's
   6.5rem (sized for a member name) down to fit a bare 1-30 row index — must combine with
   `table.dfl-draft-teams-sheet` to beat that rule's own specificity (0,2,1), which a bare class alone
   (0,1,0) would silently lose. */
table.dfl-draft-teams-sheet.dfl-draft-sport-picks-sheet .sticky-col {
    width: 2.25rem;
    text-align: center;
}

/* Fixed width + right-align so "#7" and "#123" both leave the avatar/logo/name that follow starting
   at the same x position — tabular-nums keeps digit widths consistent within that fixed box too.
   1.9rem fits the widest case, "#210" (DraftConstants.MemberCount * Rounds). display:inline-block is
   required for width to take effect at all on a span, which is inline by default. */
.draft-pick-number {
    flex-shrink: 0;
    display: inline-block;
    width: 1.9rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-size: 0.68rem;
    font-weight: 800;
    color: var(--dfl-text-muted, #6b7280);
}

.draft-cell__pick {
    display: block;
    font-size: 0.7rem;
    font-weight: 800;
    text-align: center;
    color: var(--dfl-text-muted, #6b7280);
    line-height: 1.15;
}

.draft-cell__proj {
    display: block;
    font-size: 0.58rem;
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    line-height: 1;
    opacity: 0.9;
    flex-shrink: 0;
    text-align: right;
}

/* Draft History Draft Board only (scoped to .draft-cell__team--history, set alongside
   ShowHistoryColumns — never touches the live/non-history Draft page, which reuses the same
   .draft-cell__proj class for its single always-shown proj value). Curr is the prominent one here
   since the live/current number is the more relevant one to read at a glance post-draft; Draft
   (the .draft-cell__proj span with no --curr modifier) is the muted one. .draft-cell__delta is a
   sizing-only twin of .draft-cell__proj (no `color`) so .score-positive/-negative/-inactive
   (defined earlier in this file) aren't overridden by a later same-specificity `color` rule. */
.draft-cell__team--history .draft-cell__proj:not(.draft-cell__proj--curr) {
    opacity: 0.65;
}

.draft-cell__team--history .draft-cell__proj--curr {
    opacity: 1;
}

.draft-cell__delta {
    display: block;
    font-size: 0.58rem;
    font-weight: 700;
    line-height: 1;
    flex-shrink: 0;
    text-align: right;
}

td.draft-cell.draft-cell--next {
    box-shadow: inset 0 0 0 2px var(--dfl-warning, #d97706);
    background: var(--dfl-warning-bg, #fffbeb);
}

/* Wraps the header + list together so one scrollbar covers both (matching
   .draft-recent-table-wrap below) — the sticky header then scrolls in lockstep with the
   rows under it instead of the list having its own separate, narrower-by-a-scrollbar-width
   scroll area that throws off column alignment under the header. */
.draft-recent-list-wrap {
    max-height: 34vh;
    overflow-y: auto;
    flex: 1;
}

.draft-recent-list__header {
    position: sticky;
    top: 0;
    z-index: 1;
    display: grid;
    grid-template-columns: 2.5rem 1.4rem minmax(0, 1fr) auto;
    gap: 0.2rem 0.45rem;
    padding: 0.35rem 0.4rem;
    background: var(--dfl-surface-alt, #eef4f9);
    font-size: 0.68rem;
    font-weight: 700;
    white-space: nowrap;
}

.draft-recent-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.draft-recent-item {
    display: grid;
    grid-template-columns: 2.5rem 1.4rem minmax(0, 1fr) auto;
    gap: 0.2rem 0.45rem;
    align-items: start;
    padding: 0.5rem 0.4rem;
    border-bottom: 1px solid var(--dfl-border, #e5e7eb);
    font-size: 0.8rem;
    border-left: 3px solid var(--sport-accent, var(--dfl-border-strong, #cbd5e1));
    background: linear-gradient(90deg, color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface, #fff)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff)) 0%, var(--dfl-surface, #fff) 60%);
}

.draft-recent-item .team-logo {
    width: 1.4rem;
    height: 1.4rem;
    margin-top: 0.1rem;
}

.draft-recent-item__pick {
    font-weight: 900;
    font-size: 0.76rem;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    line-height: 1.15;
    align-self: center;
}

.draft-recent-item__body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    line-height: 1.2;
}

.draft-recent-item__player {
    font-weight: 700;
    white-space: normal;
    word-break: break-word;
}

.draft-recent-item__team {
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.76rem;
    font-weight: 700;
    white-space: normal;
    word-break: break-word;
}

.draft-recent-item__proj {
    font-weight: 700;
    font-size: 0.76rem;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    padding-left: 0.15rem;
    align-self: center;
}

/* Draft History Recent Picks — headered table (Pick/Team/Draft/Curr/+/-) replacing the plain <ol>. */
.draft-recent-table-wrap {
    max-height: 34vh;
    overflow-y: auto;
    flex: 1;
}

table.draft-recent-table {
    width: 100%;
    font-size: 0.78rem;
}

table.draft-recent-table th {
    position: sticky;
    top: 0;
    background: var(--dfl-surface-alt, #eef4f9);
    font-size: 0.68rem;
    font-weight: 700;
    white-space: nowrap;
    z-index: 1;
}

/* Background lives on the row (not each td) so it's one continuous gradient across Pick+Team,
   matching the single-gradient <li> row in the pre/live-draft list — putting it on every td
   instead restarts the gradient per cell, which reads as duplicated/tiled backgrounds. The
   accent stripe stays on the first cell only, since a border on <tr> isn't reliably rendered. */
table.draft-recent-table tr {
    background: linear-gradient(90deg, color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface, #fff)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff)) 0%, var(--dfl-surface, #fff) 60%);
}

table.draft-recent-table td {
    padding: 0.35rem 0.4rem;
}

table.draft-recent-table td:first-child {
    border-left: 3px solid var(--sport-accent, var(--dfl-border-strong, #cbd5e1));
}

.draft-recent-table__pick {
    font-weight: 900;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    white-space: nowrap;
}

/* Draft/Curr/+/- numeric cells — bold like the pre-draft .draft-recent-item__proj; --accent
   supplies the sport-color text for Draft/Curr, but +/- keeps its .score-positive/-negative
   color (applied via DeltaClass in the razor) instead of --accent. Right-aligned (not the
   `col-center` class also on these <td>s, which never fires here — that rule is scoped to
   table.dfl-draft-pool-table, a class this table doesn't carry) so digits line up by place value
   instead of by left edge, which otherwise makes different-length numbers look randomly offset
   down the column. */
.draft-recent-table__num {
    font-weight: 700;
    text-align: right;
}

.draft-recent-table__num--accent {
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

.draft-recent-table__team {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

/* This table has no colgroup/fixed layout — Team is the one flexible column among four narrow
   numeric ones (Pick/Draft/Curr/+/-), so it naturally claims most of the row. Player/team text
   already wraps (.draft-recent-item__player/__team are white-space:normal), so capping max-width
   below the TeamName.razor abbreviation breakpoint just tightens the column instead of truncating
   anything. */
@media (max-width: 1900px) {
    table.draft-recent-table td.draft-recent-table__team {
        max-width: 50%;
    }
}

.draft-recent-table__team .team-logo {
    width: 1.3rem;
    height: 1.3rem;
    flex-shrink: 0;
}

.dfl-draft-pool-card .dfl-table-wrap {
    overflow-y: auto;
    max-height: 60vh;
}

/* Draft-pool table styling below is scoped to table.dfl-draft-pool-table + tr.draft-pool-row —
   any new table reusing this look needs BOTH classes or it renders unstyled. */
table.dfl-draft-pool-table th {
    white-space: nowrap;
    font-size: 0.72rem;
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--dfl-surface-alt, #eef4f9);
}

table.dfl-draft-pool-table th.col-center,
table.dfl-draft-pool-table td.col-center,
table.dfl-draft-pool-table th.hist-score-col,
table.dfl-draft-pool-table td.hist-score-col {
    text-align: center;
}

table.dfl-draft-pool-table tr.draft-pool-row td {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-hover, #f9fbfd)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-weight: 600;
}

table.dfl-draft-pool-table th.col-team {
    white-space: nowrap;
}

/* Post-draft-only "Pick" column (round-position label + drafting member) — see
   _room.IsComplete gate in DraftBoardCore.razor. */
table.dfl-draft-pool-table .draft-pool-pick-cell {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    line-height: 1.2;
    white-space: nowrap;
}

table.dfl-draft-pool-table .draft-pool-pick-cell__label {
    font-weight: 900;
}

table.dfl-draft-pool-table .draft-pool-pick-cell__by {
    font-weight: 600;
    color: var(--dfl-text, #374151);
}

/* Override global display:flex on .team-name-cell — puts flex layout
   inside a block child div so the td behaves as a normal table-cell.
   The inner div naturally sizes to its content; strong gets flex:1 so
   the name fills all available space and truncates with ellipsis. */
table.dfl-draft-pool-table td.team-name-cell {
    display: table-cell;
    vertical-align: middle;
}

table.dfl-draft-pool-table .team-name-inner {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    overflow: hidden;
    white-space: nowrap;
}

table.dfl-draft-pool-table .team-name-inner strong {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

table.dfl-draft-pool-table .draft-sport-badge {
    flex-shrink: 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    padding: 0.1em 0.4em;
    border-radius: 3px;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #e8f0f8)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    border: 1px solid color-mix(in srgb, var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)) 25%, transparent);
    white-space: nowrap;
}

table.dfl-draft-pool-table th.col-team .team-header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
}

table.dfl-draft-pool-table th .draft-sport-badge--header {
    background: transparent;
    color: var(--dfl-text-muted, #5a7080);
    border-color: var(--dfl-border-strong, #b0c4d4);
}

table.dfl-draft-pool-table td.draft-division-cell {
    font-size: 0.72rem;
    white-space: nowrap;
}

table.dfl-draft-pool-table td.draft-division-cell img.conf-logo {
    display: block;
    margin: 0 auto;
    object-fit: contain;
}

table.dfl-draft-pool-table tr.draft-pool-row:hover td {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-hover, #f9fbfd)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    filter: brightness(0.96);
}

table.dfl-draft-pool-table tr.draft-pool-row--drafted td {
    opacity: 0.38;
}

table.dfl-draft-pool-table tr.draft-pool-row--drafted:hover td {
    filter: none;
}

table.dfl-draft-board tr:hover td.draft-cell.filled {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-hover, #f9fbfd)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text, #1f2937)));
}

table.dfl-draft-teams-sheet tr:hover td.draft-roster-sport {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-hover, #f9fbfd)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text, #1f2937)));
}

@media (max-width: 1100px) {
    .dfl-draft-chart-picks-row {
        grid-template-columns: 1fr;
    }

    .draft-recent-list {
        max-height: 16rem;
    }
}

/* min-width is the floor this table won't shrink below on narrow/mobile viewports — width:100% lets
   it fill wider containers past that floor. Raised from 40rem so member/pick columns stay legible
   on phones instead of being squeezed to viewport width; .dfl-draft-board-wrap's overflow-x:auto
   handles the resulting horizontal scroll. */
table.dfl-draft-board {
    table-layout: fixed;
    width: 100%;
    min-width: 100rem;
}

table.dfl-draft-board th,
table.dfl-draft-board td {
    padding: 0.35rem 0.4rem;
    white-space: normal;
}

table.dfl-draft-board th.member-col {
    text-align: center;
    min-width: 6.5rem;
    background: var(--dfl-surface-alt, #eef4f9);
    color: var(--dfl-brand-dark, #0f3d6b);
    vertical-align: bottom;
    padding: 0.4rem 0.35rem;
}

table.dfl-draft-board th.member-col .member-badge {
    flex-direction: column;
    gap: 0.25rem;
    justify-content: center;
    margin: 0 auto;
}

table.dfl-draft-board th.member-col .member-badge {
    --member-badge-size: 34px;
}

table.dfl-draft-board th.member-col .member-badge__name {
    display: block;
    font-size: 0.76rem;
    font-weight: 800;
    line-height: 1.15;
    text-align: center;
    white-space: normal;
    word-break: break-word;
    max-width: 100%;
    color: var(--dfl-brand-dark, #0f3d6b);
}

table.dfl-draft-board th.member-col.on-clock,
table.dfl-draft-board td.draft-cell.on-clock {
    box-shadow: inset 0 0 0 2px var(--dfl-success, #15803d);
}

table.dfl-draft-board td.draft-cell {
    min-width: 5.5rem;
    vertical-align: middle;
    text-align: left;
    font-size: 0.76rem;
    padding: 0.25rem 0.3rem;
    overflow: visible;
}

table.dfl-draft-board td.draft-cell.filled {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-hover, #f9fbfd)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text, #1f2937)));
}

.draft-cell__team {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
    text-align: center;
}

.draft-cell__team--compact {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
}

/* text-align: right (was left) restores the base .draft-cell__proj/.draft-cell__delta intent
   (see those rules above) that this higher-specificity override was accidentally cancelling.
   min-width gives each number a fixed-width box to right-align within — without it, a span sized
   to its own content has no slack for text-align to do anything, and packed flex siblings of
   varying content width (Draft/Curr/+/- can each be 1-5 characters) drift out of column
   regardless of text-align. */
.draft-cell__team--compact .draft-cell__proj,
.draft-cell__team--compact .draft-cell__delta {
    font-size: inherit;
    gap: 0.25rem;
    text-align: right;
    min-width: 2.4em;
}

.draft-cell__logo-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.08rem;
    flex-shrink: 0;
    width: 1.35rem;
}

.draft-cell__team--compact .team-logo {
    width: 1.25rem;
    height: 1.25rem;
    margin-top: 0;
    flex-shrink: 0;
}

.draft-cell__name {
    flex: 1;
    min-width: 0;
    font-weight: 700;
    line-height: 1.15;
    text-align: left;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    word-break: break-word;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text, #1f2937)));
}

.draft-cell__sport {
    font-size: 0.62rem;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-text-muted, #6b7280)));
    font-weight: 700;
}

table.dfl-draft-board.stoch-roster-board td.draft-cell {
    min-width: 7rem;
}

.stoch-total-row td {
    border-top: 2px solid var(--dfl-border-strong, #cbd5e1);
    background: var(--dfl-surface-hover, #f8fafc);
}

.stoch-cell__stats {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    margin-top: 0.2rem;
    font-size: 0.68rem;
    line-height: 1.2;
}

.stoch-cell__stat {
    display: block;
}

.draft-sport-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.65rem 0 0.85rem;
}

.draft-sport-pill {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.72rem;
    font-weight: 700;
    border: 1px solid transparent;
    cursor: pointer;
}

.draft-sport-pill.active {
    border-color: var(--sport-accent, var(--dfl-brand-dark, #0f3d6b));
    box-shadow: 0 0 0 1px var(--sport-accent, var(--dfl-brand-dark, #0f3d6b));
}

/* Fixed brand-blue fill in both themes — see .dfl-standings-hero's comment for why. */
.draft-pick-btn,
.draft-link-btn {
    display: inline-block;
    border: none;
    border-radius: 6px;
    background: #1a5490;
    color: var(--dfl-on-brand, #fff);
    font-size: 0.82rem;
    font-weight: 700;
    padding: 0.45rem 0.85rem;
    cursor: pointer;
    text-decoration: none;
}

.draft-pick-btn:hover,
.draft-link-btn:hover {
    filter: brightness(1.08);
}

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

.draft-pick-btn.warn {
    background: var(--dfl-danger, #9a3412);
}

.commissioner-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

td .commissioner-actions {
    margin-top: 0;
}

.draft-pick-btn.small {
    padding: 0.3rem 0.55rem;
    font-size: 0.75rem;
}

/* Unselected prompt-kind tabs on CommissionerBriefing.razor's prompt settings card — dimmed relative
   to .draft-pick-btn's default fixed brand-blue fill; .active restores full opacity for the selected tab. */
.draft-pick-btn.dfl-prompt-tab {
    opacity: 0.55;
}

.draft-pick-btn.dfl-prompt-tab.active {
    opacity: 1;
    box-shadow: 0 0 0 2px var(--dfl-on-brand, #fff) inset;
}

.dfl-prompt-textarea {
    width: 100%;
    box-sizing: border-box;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.85rem;
    line-height: 1.4;
    padding: 0.6rem;
    border-radius: 6px;
    border: 1px solid var(--dfl-border, #ccc);
    background: var(--dfl-surface, #fff);
    color: var(--dfl-text, #111);
    resize: vertical;
    margin-top: 0.5rem;
}

.bonus-rank-list {
    list-style: none;
    padding: 0;
    margin: 1rem 0;
}

.bonus-rank-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0;
    border-bottom: 1px solid var(--dfl-border, #e8edf2);
}

.bonus-rank-num {
    font-weight: 700;
    color: var(--dfl-brand, #1a5490);
    min-width: 1.5rem;
}

.bonus-rank-team {
    flex: 1;
}

.bonus-rank-worth {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--dfl-text-muted, #6b7280);
    white-space: nowrap;
}

.bonus-rank-item .team-logo,
.bonus-rank-item .team-logo-link { width: 22px; height: 22px; flex: 0 0 auto; }

/* ── Bonus Pick'em standings matrix ── */
.bonus-standings-card { --sport-accent: #1a5490; }

.bonus-matrix { min-width: 100%; }
.bonus-matrix th,
.bonus-matrix td { text-align: center; }
.bonus-matrix .freeze-col-1 { text-align: left; }

.bonus-matrix__team {
    min-width: 2.4rem;
    vertical-align: bottom;
}
.bonus-matrix__team .team-logo,
.bonus-matrix__team .team-logo-link { width: 20px; height: 20px; }
.bonus-matrix__wins {
    display: block;
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--dfl-text-muted, #6b7280);
}

.bonus-matrix__member {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}
.bonus-matrix__trophy { font-size: 0.85rem; }

.bonus-matrix__cell { position: relative; font-variant-numeric: tabular-nums; }
.bonus-matrix__val { color: var(--dfl-text-muted, #6b7280); font-size: 0.78rem; }
.bonus-matrix__pts {
    display: block;
    font-weight: 800;
    font-size: 0.82rem;
    color: var(--dfl-text, #1f2937);
}
.bonus-matrix__total { font-variant-numeric: tabular-nums; }

.bonus-matrix__redacted {
    text-align: center;
    font-size: 0.75rem;
    font-style: italic;
    color: var(--dfl-text-muted, #6b7280);
    background: color-mix(in srgb, var(--dfl-text-muted, #6b7280) 6%, transparent);
}

.bonus-matrix__me td { background: color-mix(in srgb, var(--sport-accent) 8%, transparent); }
.bonus-matrix__winner td {
    background: color-mix(in srgb, var(--dfl-success, #059669) 14%, transparent);
}
.bonus-matrix__winner .bonus-matrix__cell {
    background: color-mix(in srgb, var(--dfl-success, #059669) 10%, transparent) !important;
}

.bonus-commish-rank {
    list-style: decimal inside;
    margin: 0;
    padding: 0;
    columns: 2;
    font-size: 0.78rem;
}
.bonus-commish-rank li { white-space: nowrap; }
.bonus-commish-rank .draft-pick-btn.small { padding: 0 0.3rem; }

/* Series game count next to a team on the playoff bracket. */
.bracket-team__series {
    margin-left: auto;
    flex: 0 0 auto;
    min-width: 1.3rem;
    text-align: center;
    font-weight: 800;
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
    color: var(--dfl-text, #1f2937);
    background: color-mix(in srgb, currentColor 10%, transparent);
    border-radius: 4px;
    padding: 0 0.25rem;
}
.bracket-team.is-winner .bracket-team__series { color: var(--dfl-success-strong, #065f46); }

/* ── Summary sheet (points model) ── */

.summary-sheet {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* Fixed gradient in both themes — see .dfl-standings-hero's comment above for why. */
.summary-hero {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.25rem;
    padding: 1.35rem 1.5rem;
    border-radius: 12px;
    background: linear-gradient(135deg, #0f3d6b 0%, #1a5490 42%, #0d9488 100%);
    color: var(--dfl-on-brand, #fff);
    box-shadow: 0 8px 28px rgba(15, 61, 107, 0.28);
}

.summary-hero__eyebrow {
    display: inline-block;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.88;
}

.summary-hero__title {
    margin: 0.2rem 0 0;
    font-size: 1.75rem;
    color: var(--dfl-on-brand, #fff);
    line-height: 1.15;
}

.summary-hero__season {
    margin: 0.35rem 0 0;
    font-size: 0.9rem;
    opacity: 0.9;
}

.summary-hero__stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.55rem;
}

.summary-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 4.75rem;
    padding: 0.55rem 0.7rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.14);
    backdrop-filter: blur(4px);
}

.summary-stat__value {
    font-size: 1.05rem;
    font-weight: 800;
    line-height: 1.1;
}

.summary-stat__label {
    margin-top: 0.15rem;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    opacity: 0.85;
}

.summary-bottom {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

.summary-card__header {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin-bottom: 0.65rem;
}

.summary-card__header h2 {
    margin: 0;
    font-size: 1.1rem;
}

.summary-card__lead {
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
    color: var(--dfl-text-muted, #4b5563);
}

.summary-card--matrix {
    border-top: 4px solid var(--dfl-brand, #1a5490);
}

.summary-card--payouts {
    border-top: 4px solid var(--dfl-success-strong, #14532d);
}

.summary-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-height: none;
    width: 100%;
}

.summary-matrix {
    width: max-content;
    min-width: 100%;
    font-size: 0.85rem;
    /* separate (not .dfl-table's collapse) so the sticky first column below paints solid edges —
       same collapsed-border/sticky rendering gap the freeze-col-1 tables fix, see the comment near
       .dfl-standings-table--sheet. The Expand-popup path already forces this on the table. */
    border-collapse: separate;
    border-spacing: 0;
}

.summary-matrix__corner {
    min-width: 9.5rem;
    background: var(--dfl-surface, #fff);
    border-right: 2px solid var(--dfl-border, #e5e7eb);
}

.summary-matrix__logo-row th {
    padding: 0.65rem 0.35rem 0.25rem;
    vertical-align: bottom;
}

.summary-matrix__sport-head {
    text-align: center;
    vertical-align: middle;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    border-bottom: 3px solid var(--sport-accent, var(--dfl-brand, #1a5490));
    min-width: 7.25rem;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

.summary-matrix__sport-head .sport-logo {
    display: block;
    margin: 0 auto;
    object-fit: contain;
    max-height: 44px;
    width: auto;
}

/* Every first-column cell — tier labels, the Points/Count sub-rows, and the .summary-section-row
   bars — sits flush-left at the table's default cell gutter (table.dfl-table th padding). Hierarchy
   is conveyed by the bars, weight and font-size, not by staggered indentation. */
.summary-matrix__label {
    text-align: left;
    font-weight: 700;
    color: var(--dfl-brand-dark, #0f3d6b);
    background: var(--dfl-surface-hover, #f8fafc);
    border-right: 2px solid var(--dfl-border, #e5e7eb);
    white-space: nowrap;
}

.summary-matrix__label.summary-matrix__sub {
    font-weight: 600;
    color: var(--dfl-text-muted, #4b5563);
    font-size: 0.74rem;
}

.summary-matrix__value,
.summary-matrix__tier-name,
.summary-matrix__money,
.summary-matrix__pts {
    text-align: center;
    background: color-mix(in srgb, var(--sport-accent-soft, transparent) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
}

table.dfl-table.summary-matrix th.summary-matrix__sport-head,
table.dfl-table.summary-matrix td.summary-matrix__value,
table.dfl-table.summary-matrix td.summary-matrix__tier-name,
table.dfl-table.summary-matrix td.summary-matrix__money,
table.dfl-table.summary-matrix td.summary-matrix__pts {
    text-align: center;
}

/* text-align:left overrides the generic centered th; width:1% + nowrap shrinks column 1 to exactly
   its longest label ("Max Points (3 Teams)") instead of letting it absorb the table's
   min-width:100% stretch on wide screens (the slack goes to the sport columns instead). */
table.dfl-table.summary-matrix th.summary-matrix__label,
table.dfl-table.summary-matrix th.summary-matrix__corner {
    text-align: left;
    width: 1%;
}

/* Freeze the row-label column so the sport columns scroll beneath it — the matrix is wider than
   the viewport on anything but a wide desktop. The corner / label cells carry opaque bg fills
   (surface / surface-hover), so scrolled-away columns don't show through. */
table.dfl-table.summary-matrix th.summary-matrix__corner,
table.dfl-table.summary-matrix th.summary-matrix__label {
    position: sticky;
    left: 0;
}

/* Keep the section-bar name pinned while the sport columns scroll under it. The bar itself is a
   single colspan cell already as wide as the whole table, so position:sticky on the CELL has zero
   room to shift and just scrolls away — the sticky has to go on an inner span that IS narrower
   than its containing block (the cell). The cell's opaque table-header-bg fill spans the full
   width and always sits behind the pinned span. Left padding moves onto the span so it can pin
   flush to the scrollport edge. 0.325rem matches table.dfl-table th's default left padding so the
   bar text lines up exactly with the tier labels below it. */
table.dfl-table.summary-matrix .summary-section-row th {
    padding-left: 0;
}

table.dfl-table.summary-matrix .summary-section-row th > span {
    position: sticky;
    left: 0;
    display: inline-block;
    padding-left: 0.325rem;
}

/* The thead corner sits above the plain sticky sport-head cells sliding under it on horizontal
   scroll — tied z-index lets a later-in-DOM sport column paint over it (the trap the freeze-col-1
   header cells avoid, see the .dfl-expand-modal__body comment). Body labels stay below the
   sticky-top header row in the Expand popup. Prefix carries enough specificity to beat that
   popup's `thead tr:last-child th { z-index: 2 }`. */
table.dfl-table.summary-matrix thead th.summary-matrix__corner {
    z-index: 3;
}

table.dfl-table.summary-matrix tbody th.summary-matrix__label {
    z-index: 1;
}

.summary-matrix__tier-name {
    font-weight: 600;
    font-size: 0.74rem;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    line-height: 1.25;
}

.summary-matrix__pts {
    font-weight: 800;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
}

.summary-matrix__money {
    font-weight: 700;
    color: var(--dfl-success-strong, #14532d);
}

/* Deep muted navy in dark mode — see --dfl-table-header-bg's comment above for why. */
/* Section headers read as headers: bold, uppercase, and at least as large as the labels beneath
   them (.summary-matrix is 0.85rem), sitting a step to the LEFT of those indented labels. */
.summary-section-row th {
    text-align: left;
    background: var(--dfl-table-header-bg, #1a5490);
    color: var(--dfl-on-brand, #fff);
    font-size: 0.85rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 0.45rem 0.75rem;
}

.summary-tier-block--6 td,
.summary-tier-block--6 th.summary-matrix__label {
    border-top: 2px solid var(--dfl-border, #e5e7eb);
}

.summary-tier-block--last td,
.summary-tier-block--last th {
    border-bottom: 1px solid #e8edf2;
}

.summary-matrix__max {
    font-weight: 800;
    font-size: 0.9rem;
}

.dfl-modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(15, 61, 107, 0.55);
    backdrop-filter: blur(3px);
}

.dfl-modal {
    width: min(28rem, 100%);
    padding: 1.25rem 1.35rem;
    border-radius: 12px;
    background: var(--dfl-surface, #fff);
    box-shadow: 0 16px 48px rgba(15, 61, 107, 0.28);
}

.dfl-modal__title {
    margin: 0 0 0.65rem;
    font-size: 1.15rem;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.dfl-modal__body {
    margin: 0 0 1rem;
    color: var(--dfl-text-muted, #4b5563);
    line-height: 1.45;
}

.dfl-modal__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.55rem;
    flex-wrap: wrap;
}

.dfl-briefing-modal {
    width: min(42rem, 100%);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}

.dfl-briefing-modal__body {
    overflow-y: auto;
    margin: 0 0 1rem;
    color: var(--dfl-text, #1f2937);
    line-height: 1.5;
}

.dfl-briefing-modal__body table {
    width: 100%;
    border-collapse: collapse;
    margin: 0.75rem 0;
    font-size: 0.9rem;
}

.dfl-briefing-modal__body th,
.dfl-briefing-modal__body td {
    border: 1px solid var(--dfl-border-strong, #d1d5db);
    padding: 0.35rem 0.6rem;
    text-align: left;
}

.dfl-briefing-modal__body th {
    background: var(--dfl-surface-hover, #f3f4f6);
}

.summary-rank-table__rank {
    font-weight: 800;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.summary-rank-table__pro {
    background: var(--dfl-info-bg, #e8f0fa);
    color: var(--dfl-info-text, #003e7e);
}

.summary-rank-table__college {
    background: var(--dfl-success-bg, #d8ede4);
    color: var(--dfl-success-strong, #1b4332);
}

.summary-rank-table tbody tr:nth-child(even) td {
    background: var(--dfl-surface-hover, #fafbfc);
}

.summary-rank-table tbody tr:nth-child(even) td.summary-rank-table__rank {
    background: var(--dfl-surface-hover, #f3f6f9);
}

.summary-footnote {
    margin: 0.65rem 0 0;
    font-size: 0.75rem;
    color: var(--dfl-text-muted, #6b7280);
}

.summary-payout-grid {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.summary-payout-block h3 {
    margin: 0 0 0.45rem;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.summary-payout-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.summary-payout-list li {
    list-style: none;
}

.summary-payout-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.65rem;
    border-radius: 8px;
    background: var(--dfl-surface-hover, #f8fafc);
    border: 1px solid #eef2f6;
    font-size: 0.82rem;
}

.summary-payout-row + .summary-payout-row {
    margin-top: 0.35rem;
}

.summary-payout-row span {
    color: var(--dfl-text-muted, #4b5563);
}

.summary-payout-row strong {
    min-width: 4.5rem;
    text-align: right;
    color: var(--dfl-success-strong, #14532d);
    font-weight: 800;
    font-size: 0.95rem;
}

.summary-payout-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 0.45rem;
    padding: 0.5rem 0.65rem;
    border-radius: 8px;
    background: var(--dfl-success-bg, #ecfdf5);
    font-size: 0.82rem;
    font-weight: 700;
}

.summary-payout-total strong {
    color: var(--dfl-success-strong, #14532d);
    font-size: 0.95rem;
}

.summary-payout-block--accent {
    padding: 0.65rem 0.75rem;
    border-radius: 8px;
    background: linear-gradient(135deg, var(--dfl-warning-bg, #fffbeb), var(--dfl-warning-bg, #fef3c7));
    border: 1px solid var(--dfl-warning, #fde68a);
}

.sport-logo {
    display: block;
    object-fit: contain;
    max-width: 100%;
    height: auto;
}

@media (max-width: 900px) {
    .summary-bottom {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 720px) {
    .summary-hero__title {
        font-size: 1.35rem;
    }

    .summary-matrix {
        font-size: 0.8rem;
    }

    .summary-matrix__sport-head {
        min-width: 5.75rem;
    }
}

.dfl-chat {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1200;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.65rem;
}

/* Fixed gradient in both themes — see .dfl-standings-hero's comment above for why. */
.dfl-chat__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.55rem 0.9rem;
    border: none;
    border-radius: 999px;
    background: linear-gradient(135deg, #0f3d6b, #1a5490);
    color: var(--dfl-on-brand, #fff);
    font-weight: 800;
    font-size: 0.85rem;
    letter-spacing: 0.04em;
    cursor: pointer;
    box-shadow: 0 8px 24px rgba(15, 61, 107, 0.35);
}

.dfl-chat__toggle:hover {
    filter: brightness(1.06);
}

.dfl-chat__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background: var(--dfl-danger, #dc2626);
    color: var(--dfl-on-brand, #fff);
    font-size: 0.68rem;
    font-weight: 800;
}

.dfl-chat__online-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    height: 1.25rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.16);
    color: rgba(255, 255, 255, 0.85);
    font-size: 0.68rem;
    font-weight: 600;
}

.dfl-chat__online-badge::before {
    content: "";
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 999px;
    background: var(--dfl-success, #22c55e);
    flex-shrink: 0;
}

.dfl-chat__unread-indicators {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.45rem;
    max-width: min(22rem, calc(100vw - 2rem));
}

.dfl-chat__unread-sender {
    position: relative;
    flex: 0 0 auto;
}

.dfl-chat__unread-sender-badge {
    position: absolute;
    top: -0.3rem;
    right: -0.3rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.05rem;
    height: 1.05rem;
    padding: 0 0.2rem;
    border-radius: 999px;
    background: var(--dfl-danger, #dc2626);
    color: var(--dfl-on-brand, #fff);
    font-size: 0.62rem;
    font-weight: 800;
    border: 2px solid var(--dfl-surface, #fff);
    box-shadow: 0 2px 6px rgba(15, 61, 107, 0.25);
}

.dfl-chat__panel {
    width: min(22rem, calc(100vw - 2rem));
    height: min(28rem, calc(100vh - 6rem));
    display: flex;
    flex-direction: column;
    border-radius: 14px;
    overflow: hidden;
    background: var(--dfl-surface, #fff);
    border: 1px solid #d7e0ea;
    box-shadow: 0 16px 40px rgba(15, 61, 107, 0.28);
}

/* Kept in the DOM while chat is minimized — see LeagueChatPanel.razor's comment on why (a live
   video call's <video> elements can't survive Blazor unmounting/remounting their container).
   MUST stay after .dfl-chat__panel above — equal (0,1,0) specificity, so source order decides
   which `display` wins; this one needs to. (.dfl-chat--sidebar .dfl-chat__panel further below
   never sets `display` at all, so it can't re-clobber this regardless of its own position.) */
.dfl-chat__panel--hidden {
    display: none;
}

/* Fixed gradient in both themes — see .dfl-standings-hero's comment above for why. */
.dfl-chat__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 0.85rem;
    background: linear-gradient(135deg, #0f3d6b, #1a5490);
    color: var(--dfl-on-brand, #fff);
}

.dfl-chat__online {
    display: block;
    font-size: 0.72rem;
    opacity: 0.85;
}

.dfl-chat__header-actions {
    display: flex;
    gap: 0.35rem;
}

.dfl-chat__icon-btn {
    border: none;
    background: rgba(255, 255, 255, 0.14);
    color: var(--dfl-on-brand, #fff);
    border-radius: 6px;
    padding: 0.2rem 0.45rem;
    font-size: 0.72rem;
    cursor: pointer;
}

.dfl-chat__icon-btn:hover {
    background: rgba(255, 255, 255, 0.24);
}

.dfl-chat__presence {
    display: flex;
    gap: 0.45rem;
    padding: 0.55rem 0.75rem;
    overflow-x: auto;
    border-bottom: 1px solid #e8edf3;
    background: var(--dfl-surface-hover, #f8fafc);
}

.dfl-chat__presence-user {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    padding: 0.15rem 0.45rem 0.15rem 0.15rem;
    border-radius: 999px;
    background: var(--dfl-surface, #fff);
    border: 1px solid var(--dfl-border, #e2e8f0);
    font-size: 0.72rem;
}

.dfl-chat__presence-name {
    max-width: 5.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Idle = ChatOnlineUser.LastActiveUtc older than ChatPresenceService.IdleThreshold (15 min of no
   mouse/keyboard/touch/scroll activity on the site) — washed out rather than removed, since the
   member is still connected and will see new messages, just not necessarily watching right now. */
.dfl-chat__presence-user--idle {
    opacity: 0.5;
    filter: grayscale(0.6);
}

.dfl-chat__messages {
    flex: 1;
    overflow-y: auto;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    background: var(--dfl-bg, #f4f6f8);
}

.dfl-chat__empty {
    margin: auto 0;
    text-align: center;
    color: var(--dfl-text-muted, #64748b);
    font-size: 0.85rem;
}

.dfl-chat__message {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
}

.dfl-chat__message--mine {
    justify-content: flex-end;
}

.dfl-chat__message--mine .dfl-chat__bubble {
    background: var(--dfl-info-bg, #dbeafe);
    border-color: var(--dfl-info-border, #bfdbfe);
}

.dfl-chat__bubble {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    max-width: 80%;
    padding: 0.45rem 0.6rem;
    border-radius: 10px;
    background: var(--dfl-surface, #fff);
    border: 1px solid var(--dfl-border, #e2e8f0);
}

.dfl-chat__author {
    font-size: 0.68rem;
    font-weight: 800;
    color: var(--dfl-brand-dark, #0f3d6b);
}

.dfl-chat__text {
    font-size: 0.86rem;
    line-height: 1.35;
    white-space: pre-wrap;
    word-break: break-word;
}

.dfl-chat__time {
    font-size: 0.62rem;
    color: var(--dfl-text-muted, #64748b);
}

.dfl-chat__bubble-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
    margin-top: 0.1rem;
}

.dfl-chat__reactions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.2rem;
    margin-top: 0.25rem;
}

.dfl-chat__reaction {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: var(--dfl-surface-alt, #f0f4f8);
    border: 1px solid var(--dfl-border, #e2e8f0);
    font-size: 0.8rem;
    cursor: pointer;
    line-height: 1.4;
}

.dfl-chat__reaction:hover {
    background: var(--dfl-border, #e2e8f0);
}

.dfl-chat__reaction--mine {
    background: var(--dfl-info-bg, #dbeafe);
    border-color: var(--dfl-info-border, #93c5fd);
}

.dfl-chat__reaction--mine:hover {
    background: var(--dfl-info-border, #bfdbfe);
}

.dfl-chat__reaction-count {
    font-size: 0.72rem;
    font-weight: 700;
    color: #475569;
}

.dfl-chat__reaction-wrap {
    position: relative;
    display: inline-flex;
}

.dfl-chat__reaction-tooltip {
    display: none;
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.4rem 0.55rem;
    background: #1e293b;
    color: var(--dfl-on-brand, #fff);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.25);
    z-index: 100;
    min-width: max-content;
    pointer-events: none;
}

.dfl-chat__reaction-wrap:hover .dfl-chat__reaction-tooltip {
    display: flex;
}

.dfl-chat__reaction-tooltip-user {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    white-space: nowrap;
}

.dfl-chat__reaction-tooltip-name {
    font-size: 0.72rem;
    font-weight: 500;
}

.dfl-chat__reaction-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 999px;
    background: none;
    border: 1px dashed var(--dfl-border-strong, #cbd5e1);
    font-size: 0.85rem;
    color: var(--dfl-text-muted, #64748b);
    cursor: pointer;
    line-height: 1;
}

.dfl-chat__reaction-add:hover {
    background: var(--dfl-surface-alt, #f0f4f8);
    border-style: solid;
}

.dfl-chat__picker {
    display: flex;
    flex-wrap: wrap;
    gap: 0.1rem;
    margin-top: 0.25rem;
    padding: 0.3rem;
    max-width: 220px;
    max-height: 148px;
    overflow-y: auto;
    background: var(--dfl-surface, #fff);
    border: 1px solid var(--dfl-border, #e2e8f0);
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.08);
}

.dfl-chat__picker-emoji {
    font-size: 1.15rem;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.15rem 0.2rem;
    border-radius: 6px;
    line-height: 1;
}

.dfl-chat__picker-emoji:hover {
    background: var(--dfl-surface-alt, #f0f4f8);
}

.dfl-chat__error {
    padding: 0.35rem 0.75rem;
    font-size: 0.75rem;
    color: var(--dfl-danger, #b91c1c);
    background: var(--dfl-danger-bg, #fef2f2);
}

.dfl-chat__composer {
    display: flex;
    gap: 0.45rem;
    padding: 0.65rem 0.75rem;
    border-top: 1px solid var(--dfl-border, #e2e8f0);
    background: var(--dfl-surface, #fff);
}

.scoreboard-panel__header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.65rem;
}

.scoreboard-day-toggle {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
}

.scoreboard-day-toggle button {
    border: 1px solid var(--dfl-border-strong, #cbd5e1);
    border-radius: 8px;
    background: var(--dfl-surface, #fff);
    color: var(--dfl-text, #1f2937);
    padding: 0.3rem 0.6rem;
    font-size: 0.8rem;
    cursor: pointer;
}

.scoreboard-day-toggle button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.scoreboard-day-toggle__label {
    min-width: 6rem;
    text-align: center;
    font-size: 0.85rem;
    font-weight: 600;
}

.scoreboard-day-toggle__picker {
    border: 1px solid var(--dfl-border-strong, #cbd5e1);
    border-radius: 8px;
    background: var(--dfl-surface, #fff);
    color: var(--dfl-text, #1f2937);
    padding: 0.25rem 0.5rem;
    font-size: 0.8rem;
}

.scoreboard-sport-grid {
    display: flex;
    flex-direction: column;
}
/* The @media (min-width: 1901px) block below MUST re-declare flex-direction: row — CSS doesn't reset
   a property just because a later rule stops mentioning it, so this column direction stays active
   even past that breakpoint unless something there explicitly overrides it back to row. Confirmed
   live 2026-08-25 as the actual cause of every sport stacking one-per-row on wide desktop screens even
   after the grid-to-flex conversion below: a column-direction flex container with no fixed height
   never wraps into new columns regardless of flex-wrap, since nothing ever overflows its one column's
   height. This was silently masked before that conversion, when the wide breakpoint used
   display:grid instead — grid ignores flex-direction entirely, so the missing override never mattered
   until flex replaced it. */

.scoreboard-panel .dfl-card.sport-panel {
    margin-bottom: 0.325rem;
    /* Overrides .dfl-card.sport-panel's own 0.375rem horizontal padding so each sport card's content
       aligns flush with .scoreboard-panel__header's controls above it instead of sitting inset an
       extra 0.375rem past them (double-padding: this card's own padding stacked on the outer
       .scoreboard-panel .dfl-card's 0.5rem) — that stacked inset was the "indentation" reported live
       2026-08-25, and removing it also reclaims that width for the table. */
    padding-left: 0;
    padding-right: 0;
}

/* Per-sport trim: frame each sport's scoreboard TABLE in that sport's own header color (same
   --sport-accent color-mix .sport-panel h1/h2 use) so side-by-side sport cards in the /scoreboard
   grid read as separate units. Border is on the <table>, not the card, so on a narrow screen where
   the table overflows into .dfl-table-wrap's horizontal scroll the right edge tracks the real end
   of the table instead of being clipped at the viewport. Grid only — Sport.razor's single pill
   doesn't need it. */
.scoreboard-sport-grid .dfl-card.sport-panel .scoreboard-table {
    border: 1px solid color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand, #1a5490)));
}

/* table.dfl-table's border-collapse:collapse means the last body row's cell border-bottom (1px solid
   --dfl-border, from table.dfl-table td) and the frame border above (also 1px solid) meet on the same
   edge — a same-width/same-style tie, which the collapse rules always give to the CELL, so the frame's
   bottom side never painted while the other three showed fine. Drop the final row's cell border so
   only the frame draws that edge. */
.scoreboard-sport-grid .dfl-card.sport-panel .scoreboard-table tbody tr:last-child td {
    border-bottom: none;
}

/* Nudge the sport logo + title in off the framed table's left edge so they sit cleanly above the
   box instead of jammed against its border — about the same inset as the Rk column's cell padding. */
.scoreboard-sport-grid .sport-panel__title {
    padding-left: 0.25rem;
}

/* Matches HeaderNavPanel.razor.css's hamburger breakpoint — above it there's room to lay sport
   cards out side by side instead of stacking every sport full-width. Flex-wrap, not a fixed
   grid-template-columns(3) — a rigid 3-column grid forces every card into the same track width, and a
   card with naturally wider content (NCAAF/NCAAB's full college team names run much longer than pro
   abbreviations) just overflowed its column instead of the row reflowing around it. flex-wrap lets
   each card size to its own table's intrinsic width and wrap to the next row on its own once it
   doesn't fit the remaining space, so a wide card bumps down next to whatever's shortest rather than
   breaking the row it's forced into.
   flex: 0 0 auto (not flex-basis:420px + grow/shrink, tried first and confirmed live to overcorrect):
   a flex item's automatic min-width defaults to its CONTENT's min-content size, not its flex-basis,
   unless the item itself sets overflow other than visible — this card doesn't (only its descendant
   .dfl-table-wrap does, and that overflow:auto doesn't propagate up to relax ITS ancestor's min-width).
   So flex-shrink:1 against a 420px basis couldn't actually shrink any card below its own table's true
   min-content width, meaning wrap decisions were driven by that intrinsic width all along — which for
   ordinary short-name sports was apparently already wider than the leftover row space in some viewport
   widths, wrapping pairs that should have fit. flex-shrink:0 removes the shrink calculation entirely:
   each card is simply exactly as wide as it naturally wants to be, full stop, and wraps only when that
   width genuinely doesn't fit what's left of the row. max-width:100% is the safety net for the
   pathological case (one card's natural width exceeding the whole grid's width, e.g. an extreme NCAAB
   slate) — it caps the card at the container's width and lets .dfl-table-wrap's own overflow-x:auto
   absorb the rest as an internal scrollbar, so a single huge card still can't push the PAGE itself into
   horizontal scroll. */
@media (min-width: 1901px) {
    .scoreboard-sport-grid {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 0.65rem;
        align-items: start;
    }

    .scoreboard-panel .dfl-card.sport-panel {
        margin-bottom: 0;
        flex: 0 0 auto;
        max-width: 100%;
    }
}

/* Same hamburger breakpoint as HeaderNavPanel.razor.css, mirrored (max-width here vs min-width
   above) — below it, drop team names entirely and keep just the logos to conserve width; this is a
   dedicated class (not a blanket "span" selector) so it doesn't also hide MemberBadge's own initials
   span when a member has no avatar photo. Deliberately NOT Components/Shared/TeamName.razor's
   full<->abbreviated swap used everywhere else — the scoreboard table is dense enough that even the
   abbreviation crowds it, so this hides text altogether rather than shortening it.
   Scopes to the TABLE view only, by class: the calendar view's names carry .scoreboard-calendar__team
   (see the section below) and stay visible at every width on purpose — they're already abbreviated
   (TeamAbbreviationCatalog), and a bar with two logos and no text would be unreadable, since unlike a
   table row it has no Rk/Score/Status columns for context. */
@media (max-width: 1900px) {
    .scoreboard-team-name {
        display: none;
    }
}

/* ===== Scoreboard calendar (TV-guide) view — ScoreboardCalendarPanel.razor =====
   One row per broadcast network, one column per hour, each game an absolutely positioned bar inside
   its network's track. The bars' left/width/top are computed in C# as PIXELS (see that file's
   HourWidthPx/BarHeightPx/LaneGapPx constants) and written as inline styles; everything positional
   here must therefore agree with those constants exactly — --cal-hour-w with HourWidthPx, --cal-bar-h
   with BarHeightPx, --cal-lane-gap with LaneGapPx — or the bars drift off the hour columns they're
   supposed to sit on. --cal-track-w is set inline per day (hours x HourWidthPx), since the number of
   hours differs day to day.
   Deliberately a horizontally scrolling fixed-width grid rather than a percentage/responsive one, for
   the same reason as the .bracket-* columns: an hour must be the same width everywhere on the page or
   a bar's length stops meaning "how long the game runs".
   Every fixed-width box in this block therefore carries box-sizing:border-box — this stylesheet has no
   global border-box reset, so a bare `flex: 0 0 <w>` on a padded/bordered element ADDS its padding and
   border to that width. That's what shipped first: .scoreboard-calendar__axis-hour's 0.35rem side
   padding + 1px border made each hour LABEL ~162px while the bars and the track's hour gridlines stayed
   on HourWidthPx's exact (then 150px) column, so the labels crept ~12px right per hour — by the 6th
   column ~72px, a hair under the half-hour mark, which put a 7:30 game's bar directly under the "7 PM"
   heading (reported live 2026-09-04). Keep border-box on anything here that pairs a fixed track/column
   width with padding or a border. */
.scoreboard-calendar {
    /* Must equal ScoreboardCalendarPanel.razor's HourWidthPx — 150px -> 75px -> 60px there and here on
       2026-09-04 to fit more of a day on screen; see that constant's comment. */
    --cal-hour-w: 60px;
    --cal-label-w: 88px;
    --cal-bar-h: 46px;
    --cal-lane-gap: 4px;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.scoreboard-calendar__day-head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
}

.scoreboard-calendar__day-label {
    font-weight: 700;
    font-size: 0.9rem;
}

.scoreboard-calendar__day-count {
    font-size: 0.75rem;
    color: var(--dfl-text-muted, #6b7280);
}

/* The scroll ancestor for the sticky network-label column below — the grid inside it is as wide as
   the day's hour span, so the page itself never scrolls sideways (same containment approach as
   .dfl-table-wrap around the table view). */
.scoreboard-calendar__scroll {
    overflow-x: auto;
    border: 1px solid var(--dfl-border-strong, #cbd5e1);
    border-radius: 8px;
    background: var(--dfl-surface, #fff);
}

.scoreboard-calendar__grid {
    width: calc(var(--cal-label-w) + var(--cal-track-w));
    min-width: 100%;
}

.scoreboard-calendar__row {
    display: flex;
    align-items: stretch;
    border-bottom: 1px solid var(--dfl-border, #e5e7eb);
}

.scoreboard-calendar__row:last-child {
    border-bottom: none;
}

.scoreboard-calendar__label {
    position: sticky;
    left: 0;
    z-index: 2;
    flex: 0 0 var(--cal-label-w);
    width: var(--cal-label-w);
    /* Same border-box reason as the axis columns above (see this section's header): without it this
       column measured 97px against the 88px .scoreboard-calendar__grid budgets for it, so every day's
       grid was 9px narrower than its own content. Every row uses this one class, so the label column
       and the tracks beside it stayed aligned either way — this is about the grid's total width. */
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem;
    background: var(--dfl-surface, #fff);
    border-right: 1px solid var(--dfl-border-strong, #cbd5e1);
}

.scoreboard-calendar__label--corner {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--dfl-text-muted, #6b7280);
}

.scoreboard-calendar__network-logo {
    max-width: calc(var(--cal-label-w) - 0.75rem);
    max-height: 26px;
    object-fit: contain;
}

.scoreboard-calendar__network-name {
    font-size: 0.68rem;
    font-weight: 600;
    text-align: center;
    line-height: 1.1;
    overflow-wrap: anywhere;
}

.scoreboard-calendar__axis {
    display: flex;
    flex: 0 0 var(--cal-track-w);
    width: var(--cal-track-w);
}

.scoreboard-calendar__axis-hour {
    flex: 0 0 var(--cal-hour-w);
    width: var(--cal-hour-w);
    box-sizing: border-box;
    padding: 0.2rem 0.35rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--dfl-text-muted, #6b7280);
    border-left: 1px solid var(--dfl-border, #e5e7eb);
}

.scoreboard-calendar__axis-hour:first-child {
    border-left: none;
}

/* Two stacked repeating gradients: an hour rule at every column boundary, plus a faint half-hour
   band so a bar's start/end can be read against the grid without counting pixels. Painted with
   color-mix against --dfl-text (not a fixed gray) so both themes get the same subtle contrast. */
.scoreboard-calendar__track {
    position: relative;
    flex: 0 0 var(--cal-track-w);
    width: var(--cal-track-w);
    background-image:
        repeating-linear-gradient(to right, var(--dfl-border, #e5e7eb) 0 1px, transparent 1px var(--cal-hour-w)),
        repeating-linear-gradient(to right, color-mix(in srgb, var(--dfl-text, #1f2937) 4%, transparent) 0 calc(var(--cal-hour-w) / 2), transparent calc(var(--cal-hour-w) / 2) var(--cal-hour-w));
}

.scoreboard-calendar__now {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--dfl-danger, #b91c1c);
    opacity: 0.7;
    z-index: 1;
}

.scoreboard-calendar__bar {
    position: absolute;
    height: var(--cal-bar-h);
    box-sizing: border-box;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.1rem;
    padding: 0.15rem 0.35rem;
    border-radius: 6px;
    z-index: 1;
    /* Sport accent as a wash over the card surface, plus a solid accent spine on the left edge — same
       inline --sport-accent (SportBranding.cs) the table view's per-sport frame uses, so a mixed-sport
       "All" calendar still reads sport-by-sport at a glance. */
    background: color-mix(in srgb, var(--sport-accent, var(--dfl-brand, #1a5490)) 14%, var(--dfl-surface, #fff));
    border: 1px solid color-mix(in srgb, var(--dfl-surface, #fff) 55%, var(--sport-accent, var(--dfl-brand, #1a5490)));
    border-left: 4px solid color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand, #1a5490)));
}

.scoreboard-calendar__bar.is-final {
    opacity: 0.82;
}

.scoreboard-calendar__matchup {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}

.scoreboard-calendar__side {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    min-width: 0;
}

.scoreboard-calendar__side--win {
    font-weight: 800;
}

.scoreboard-calendar__side--loss {
    opacity: 0.6;
    font-weight: 500;
}

.scoreboard-calendar__at {
    color: var(--dfl-text-muted, #6b7280);
    font-weight: 400;
}

.scoreboard-calendar__meta {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.65rem;
    color: var(--dfl-text-muted, #6b7280);
    white-space: nowrap;
}

.scoreboard-calendar__sport {
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand, #1a5490)));
}

.scoreboard-calendar__status.is-live {
    color: var(--dfl-danger, #b91c1c);
    font-weight: 700;
}

/* Games whose kickoff time ESPN hasn't published yet can't be placed on the axis at all, so they sit
   under the grid as chips instead of being dropped (see the panel's TBD block). */
.scoreboard-calendar__tbd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    font-size: 0.72rem;
}

.scoreboard-calendar__tbd-label {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--dfl-text-muted, #6b7280);
}

.scoreboard-calendar__tbd-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.15rem 0.4rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--dfl-surface, #fff) 55%, var(--sport-accent, var(--dfl-brand, #1a5490)));
    background: color-mix(in srgb, var(--sport-accent, var(--dfl-brand, #1a5490)) 10%, var(--dfl-surface, #fff));
    font-weight: 600;
}

.scoreboard-calendar__tbd-net {
    color: var(--dfl-text-muted, #6b7280);
    font-weight: 400;
}

/* TeamLogo renders at 28px everywhere else; a bar is only 46px tall and carries two of them plus an
   owner avatar, so they're scaled down here rather than in the component. */
.scoreboard-calendar .team-logo {
    width: 16px;
    height: 16px;
}

/* Sits beside the day toggle in .scoreboard-panel__header — reuses .sport-view-pill's styling so the
   Table/Calendar switch reads as the same control family as the sport-filter pills above it. */
.scoreboard-view-toggle {
    display: flex;
    gap: 0.35rem;
}

/* Keeps the "My Teams Only" / "Owned Teams Only" checkboxes together as one cluster — without this
   wrapper the header's justify-content:space-between would fling them to opposite ends of the row. */
.scoreboard-filter-checks {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 1rem;
}

/* ESPN's own AP Top 25 number (ScoreboardRow.OpponentApRank / TeamDetailGameRow.OpponentApRank) shown
   ahead of a ranked opponent's name — muted rather than accent-colored so it doesn't compete with the
   win/loss tint .scoreboard-cell--win/--loss already puts on this same cell's text. Deliberately a
   SIBLING of .scoreboard-team-name in the markup, not nested inside it — a rank number is exactly the
   kind of compact, high-value context a cramped mobile view benefits from most, so it stays visible
   through the max-width:1900px breakpoint above that hides the full name, rather than disappearing
   together with it. */
.scoreboard-ap-rank {
    color: var(--dfl-text-muted, #6b7280);
    font-weight: 400;
    margin-right: 0.25em;
}

/* Fixed-width wrapper (ScoreboardSportPanel.razor, TeamDetail.razor's Schedule table, and
   HeadToHead.razor's H2H schedule all use it) around the conditional .scoreboard-ap-rank badge
   above — same "reserve the slot" technique as
   .scoreboard-opponent-avatar-slot, for the same reason: without it, an unranked opponent's row loses
   this flex child entirely and everything after it (avatar/logo/name) shifts left, misaligning against
   a ranked opponent's row right above/below it. 1.75rem comfortably fits "#25", the widest a real AP
   rank ever gets. */
.scoreboard-ap-rank-slot {
    display: inline-flex;
    width: 1.75rem;
    flex-shrink: 0;
}

/* Fixed-width wrapper around the leading vs/@ location marker — TeamDetail.razor's Schedule table
   is the only remaining user (ScoreboardSportPanel dropped it 2026-09-02 for the trailing 🏠 glyph
   below). Same "reserve the slot" technique as .scoreboard-ap-rank-slot just above: "vs" and "@"
   render at different widths in a proportional font, so without this everything after the marker
   started at a different x-offset depending on home/away. 1.25rem comfortably fits "vs", the wider
   of the two markers. */
.scoreboard-location-marker {
    display: inline-flex;
    width: 1.25rem;
    flex-shrink: 0;
}

/* 🏠 trailing the home team's name in ScoreboardSportPanel.razor (and mirrored in HeadToHead's
   .h2h__venue). Only one of the two team cells per row carries it, so the away cell is marginally
   narrower — the deliberate, minimal cost of an inline marker over the old dedicated vs/@ column. */
.scoreboard-venue {
    font-size: 0.8rem;
    line-height: 1;
    opacity: 0.8;
    flex-shrink: 0;
}

table.scoreboard-table td {
    padding: 0.15rem 0.25rem;
    vertical-align: middle;
    line-height: normal;
}

.scoreboard-owner-cell,
.scoreboard-opponent-cell {
    text-align: left;
}

/* Flex lives on this inner wrapper, NOT the <td> itself — a <td> with display:flex stops being a
   table-cell (the browser wraps it in an anonymous one), so vertical-align:middle from
   table.scoreboard-table td above no longer centers it like its Rk/Score/Status row-siblings. That
   mismatch is what caused rows to look like they were shifting up/down and columns misaligning. */
.scoreboard-team-flex {
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

/* Wraps everything in the opponent cell (rank/avatar/logo/name, plus the trailing 🏠 when the
   opponent is the home side) so .scoreboard-cell--win/--loss below has one box to paint. The old
   leading vs/@ marker used to sit OUTSIDE this span to stay neutral; the 🏠 that replaced it is a
   property of the opponent team, so it's inside and tints with the name — matching the owner cell,
   whose 🏠 is likewise under that cell's td-level tint. Backgrounds only paint an element's own border box, so
   a plain inner span would color just its snug content — leaving the row's actual td padding
   (table.scoreboard-table td's 0.15rem 0.25rem, above) uncolored and breaking up consecutive rows'
   tints into disconnected blocks. The negative margin + matching extra padding on top/right/bottom
   below is the standard "background bleed" trick: it enlarges this element's own border box by
   exactly the td's own padding on those three sides while the negative margin cancels the resulting
   size increase for layout purposes, so content position is unchanged but the tint now reaches the
   cell's real edges — flush against the row above/below and the cell's right border, same as when
   the tint lived on the <td> itself. padding-left (no matching negative margin — this one's meant to
   visibly grow the box, not just bleed to an existing edge) reproduces the owner cell's own
   inset-before-the-avatar look: .scoreboard-owner-cell's td-level tint already has that colored
   0.25rem before its MemberBadge for free (it's the td's own left padding), so the opponent side needs
   an explicit copy of that same 0.25rem here to match. These four values must always match
   table.scoreboard-table td's own padding exactly (both were halved together 2026-08-26) — change one,
   change all. */
.scoreboard-opponent-tint {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex: 1;
    margin: -0.15rem -0.25rem -0.15rem 0;
    padding: 0.15rem 0.25rem 0.15rem 0.25rem;
}

/* Reserves a MemberBadge's own footprint (28px — box-sizing:border-box on .member-badge__avatar/
   __photo means the border is included in that width, not added on top) even when there's no owner
   and no MemberBadge renders at all. Without this, an unowned team's row loses that flex child
   entirely and its TeamLogo/name shift left, misaligning against every owned row above/below it.
   Shared by ScoreboardSportPanel.razor's opponent cell, TeamDetail.razor's Schedule table opponent
   cell, AND (since GetScoreboardAsync's includeUnowned param started letting an unowned pool team's
   own row through) ScoreboardSportPanel.razor's owner cell too — all three wrap their conditional
   MemberBadge in a span with this class. */
.scoreboard-opponent-avatar-slot {
    display: inline-flex;
    width: 28px;
    height: 28px;
    flex-shrink: 0;
}

/* white-space:nowrap is the load-bearing bit here — every table using these classes sits in a
   .sport-panel card, whose `table.dfl-table th/td { text-align: right }` (~line 790) outranks this
   rule's text-align. Real per-column alignment is set by the higher-specificity rules just below
   (Score centred, TV left, in the scoreboard grid + H2H schedule; TeamDetail keeps the inherited
   right). The `text-align: center` here is kept only as the fallback for any future use outside a
   .sport-panel. */
.scoreboard-score-cell,
.scoreboard-status-cell,
.scoreboard-broadcast-cell {
    text-align: center;
    white-space: nowrap;
}

/* Score column: header + cells centred. The plain .scoreboard-score-cell rule above is outgunned by
   `.sport-panel table.dfl-table th/td { text-align: right }` (~line 790), which both these tables
   inherit from their .sport-panel card wrapper — hence the extra table-class specificity here. The
   cell body is a .score-pair grid (below) that additionally pins the separator dash dead-centre.
   Scoped to the scoreboard grid + the H2H schedule; TeamDetail's Schedule table is left as-is. */
table.dfl-table.scoreboard-table th.scoreboard-score-cell,
table.dfl-table.scoreboard-table td.scoreboard-score-cell,
table.dfl-table.h2h__sched-table th.scoreboard-score-cell,
table.dfl-table.h2h__sched-table td.scoreboard-score-cell {
    text-align: center;
}

/* TV column left-aligned in the same two tables — logos / network names line up at a consistent
   left edge instead of floating mid-cell. */
table.dfl-table.scoreboard-table th.scoreboard-broadcast-cell,
table.dfl-table.scoreboard-table td.scoreboard-broadcast-cell,
table.dfl-table.h2h__sched-table th.scoreboard-broadcast-cell,
table.dfl-table.h2h__sched-table td.scoreboard-broadcast-cell {
    text-align: left;
}

/* Score like "108 – 102": a 3-track inline grid whose equal flexible side tracks force the middle
   (dash) track to the exact horizontal centre of the cell — it stays put whether either side is
   one digit or three, which plain text-align:center does not do. Side scores align toward the dash.
   Rendered by ScorePair.razor. */
.score-pair {
    display: inline-grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: baseline;
}

.score-pair__a {
    text-align: right;
}

.score-pair__b {
    text-align: left;
}

.score-pair__sep {
    padding: 0 0.35rem;
}

.scoreboard-broadcast-logo {
    height: 20px;
    width: auto;
    /* CBS is the widest of the network marks at ~3:1 — needs ~61px at this height. A tighter max-width
       clamped its rendered width below that, which (since height stayed a fixed 20px rather than
       shrinking to match) squeezed it thinner than every other logo in this column. 68px comfortably
       covers CBS with a little headroom for any future wide addition. */
    max-width: 68px;
    object-fit: contain;
    vertical-align: middle;
}

.scoreboard-broadcast-name {
    font-size: 0.75rem;
    color: var(--dfl-text-muted, #64748b);
}

/* Win/loss tint. On Scoreboard.razor (a multi-team grid), applied to the Team cell's <td> directly
   but, on the Opponent cell, to the inner .scoreboard-opponent-tint wrapper instead (see that
   class's own comment) so the leading vs/@ location marker stays unpainted — never Rk, Score, or
   Status; see OwnerCellClass/OpponentCellClass — so each side of the matchup gets its own green or
   red independent of the other, not one color for the whole row. On TeamDetail.razor's single-team
   Recent Schedule (see ScoreCellClass), there's no separate opponent row to color, so it's applied
   to the Score cell instead. Both usages only tint once the game is Final — an in-progress lead can
   still flip, so it stays neutral until then.
   Two stacked `background` layers: a linear-gradient wrapping the tint's rgba() on top (a bare color
   is only legal in the LAST background layer, hence the gradient wrapper) plus a plain rgba() brighten
   wash behind it — see the --dfl-scoreboard-* custom properties' own comment above (:root) for why
   each is shaped the way it is. */
.scoreboard-cell--win {
    background:
        linear-gradient(rgba(var(--dfl-scoreboard-win-rgb, 21, 128, 61), var(--dfl-scoreboard-tint-alpha, 0.16)), rgba(var(--dfl-scoreboard-win-rgb, 21, 128, 61), var(--dfl-scoreboard-tint-alpha, 0.16))),
        rgba(var(--dfl-success-rgb, 21, 128, 61), var(--dfl-scoreboard-brighten-alpha, 0));
}

/* Same green as .dfl-ticker__status.is-live above, applied to the Status cell's in-play text (e.g.
   "Top 3rd", "1st Qu") so a live game reads the same color language on the Scoreboard page and the
   ticker, instead of plain body text. */
.scoreboard-status-cell.is-live {
    color: var(--dfl-success, #15803d);
    font-weight: 600;
}

.scoreboard-cell--loss {
    background:
        linear-gradient(rgba(var(--dfl-scoreboard-loss-rgb, 220, 38, 38), var(--dfl-scoreboard-tint-alpha, 0.16)), rgba(var(--dfl-scoreboard-loss-rgb, 220, 38, 38), var(--dfl-scoreboard-tint-alpha, 0.16))),
        rgba(var(--dfl-danger-rgb, 220, 38, 38), var(--dfl-scoreboard-brighten-alpha, 0));
}

.dfl-chat__input {
    flex: 1;
    min-width: 0;
    border: 1px solid var(--dfl-border-strong, #cbd5e1);
    border-radius: 8px;
    padding: 0.45rem 0.6rem;
    font: inherit;
}

.dfl-chat__send {
    flex-shrink: 0;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

.dfl-chat__emoji-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px dashed var(--dfl-border-strong, #cbd5e1);
    border-radius: 8px;
    padding: 0.3rem 0.35rem;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.dfl-chat__emoji-btn:hover,
.dfl-chat__emoji-btn--active {
    background: var(--dfl-surface-alt, #f0f4f8);
    border-color: var(--dfl-border-strong, #94a3b8);
    border-style: solid;
}

.dfl-chat__composer-picker {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 1px;
    padding: 0.35rem 0.5rem;
    border-top: 1px solid var(--dfl-border, #e2e8f0);
    background: var(--dfl-surface-hover, #f8fafc);
    max-height: 8rem;
    overflow-y: auto;
}

.dfl-chat__icon-btn--active {
    background: rgba(255, 255, 255, 0.32);
}

.dfl-chat__video-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.1rem;
    height: 1.1rem;
    padding: 0 0.25rem;
    margin-left: 0.15rem;
    border-radius: 999px;
    background: #16a34a;
    color: #fff;
    font-size: 0.62rem;
    font-weight: 800;
}

/* Piggybacks on .dfl-chat__online-badge's pill shape but drops its green "online" dot —
   the 🎥 already signals what the pill means, a second dot would just be visual noise. */
.dfl-chat__online-badge--video::before {
    content: none;
}

/* Video call — square tiles rendered by video-call.js directly into .dfl-video-grid's DOM
   (Blazor never re-renders its children, see that file's header comment for why). Single
   column up to 3 tiles ("two squares vertically stacked" for a 2-3 person call), stepping up
   to 2/3 columns as more of the league's up-to-10 seats fill so tiles shrink instead of the
   grid just growing taller than the sidebar. */
.dfl-video-call {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.65rem 0.75rem;
    border-bottom: 1px solid #e8edf3;
    background: var(--dfl-surface-hover, #f8fafc);
}

/* Panel stays in the DOM (unlike the rest of this file's @if-gated sections) so the
   .dfl-video-grid @ref below is always valid — see LeagueChatPanel.razor's comment. */
.dfl-video-call--hidden {
    display: none;
}

.dfl-video-call__prompt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0;
    font-size: 0.8rem;
    color: var(--dfl-text-muted, #64748b);
    text-align: center;
}

.dfl-video-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.4rem;
    max-height: 45vh;
    overflow-y: auto;
}

/* MUST stay after .dfl-video-grid above — equal (0,1,0) specificity, source order decides,
   this needs to win (same trap as .dfl-chat__panel--hidden above; got it wrong here the first
   time too — currently harmless since the grid is empty pre-join, but real once tiles exist). */
.dfl-video-grid--hidden {
    display: none;
}

.dfl-video-grid--cols-2 {
    grid-template-columns: repeat(2, 1fr);
}

.dfl-video-grid--cols-3 {
    grid-template-columns: repeat(3, 1fr);
}

.dfl-video-tile {
    position: relative;
    aspect-ratio: 1 / 1;
    min-width: 0;
    border-radius: 10px;
    overflow: hidden;
    background: #111;
}

.dfl-video-tile video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.dfl-video-tile__name {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 0.2rem 0.4rem;
    font-size: 0.62rem;
    color: #fff;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.65));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dfl-video-call__controls {
    display: flex;
    justify-content: center;
    gap: 0.4rem;
}

/* Draft page sidebar mode. z-index raised above every fixed Euchre control (fab-row 1200,
   bid-panel 1250 in euchre.css) so an open chat panel always wins that overlap — previously 1099,
   which put it BELOW those controls despite .dfl-chat's own base 1200, because this same-specificity
   rule sits later in the cascade and was clobbering it. Still safely under .dfl-modal-backdrop's
   2000, and doesn't affect the Draft page's sticky .dfl-header (z-index 1100) since the sidebar's
   own `top: 4.75rem` already clears the header spatially. */
.dfl-chat--sidebar {
    right: 0;
    bottom: 0;
    top: 4.75rem;
    width: 272px;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    z-index: 1300;
}

.dfl-chat--sidebar .dfl-chat__panel {
    width: 100%;
    height: 100%;
    max-height: none;
    border-radius: 0;
    border: none;
    border-left: 2px solid rgba(15, 61, 107, 0.15);
    box-shadow: -4px 0 20px rgba(15, 61, 107, 0.18);
}

.dfl-chat--sidebar .dfl-chat__toggle {
    display: none;
}

.dfl-shell:has(.dfl-chat--sidebar) .dfl-body {
    padding-right: 272px;
}
/* ── Draft Advisor (commissioner-only) ─────────────────────────── */
.col-advisor {
    min-width: 3.5rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.dar-positive { color: var(--dfl-success, #15803d); font-weight: 600; }
.dar-zero     { color: var(--dfl-text-muted, #64748b); }

.draft-advisor-scarcity {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0 0.5rem;
    font-size: 0.78rem;
}

.scarcity-label {
    color: var(--dfl-text-muted, #64748b);
    font-size: 0.75rem;
    white-space: nowrap;
}

.scarcity-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.45rem;
    border-radius: 6px;
    border: 1px solid var(--sport-accent);
    background: color-mix(in srgb, var(--sport-accent-soft) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    font-size: 0.75rem;
}

.scarcity-chip__name {
    font-weight: 700;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent));
}

.scarcity-chip__great { color: var(--dfl-success, #15803d); font-weight: 600; }
.scarcity-chip__good  { color: var(--dfl-text-muted, #64748b); }
.scarcity--urgent     { color: var(--dfl-danger, #b91c1c); font-weight: 700; }

.scarcity-chip__needed         { color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent)); font-weight: 700; }
.scarcity-chip__needed--done   { color: var(--dfl-text-muted, #64748b); font-weight: 400; }

/* ── My Teams page ──────────────────────────────────────────────────── */

.my-teams-hero-identity {
    display: flex;
    align-items: center;
    gap: 0.85rem;
}

/* Season achievement chips under the hero title (AchievementService). */
.my-teams-achievements {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.5rem;
}

.my-teams-achievement {
    font-size: 0.72rem;
    font-weight: 600;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: var(--dfl-surface-alt, #eef4f9);
    border: 1px solid var(--dfl-border, #e5e7eb);
    /* Explicit — the chip sits inside .dfl-standings-hero, whose white text would otherwise be
       inherited onto this light surface and vanish in light mode. --dfl-text pairs with
       --dfl-surface-alt in both themes. */
    color: var(--dfl-text, #1a202c);
    white-space: nowrap;
}

.my-teams-hero-stats {
    display: flex;
    gap: 0.65rem;
    flex-wrap: wrap;
    align-items: stretch;
}

.my-teams-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 5.5rem;
    background: rgba(255, 255, 255, 0.13);
    border-radius: 10px;
    padding: 0.5rem 0.75rem;
    text-align: center;
    gap: 0.1rem;
}

.my-teams-stat__label {
    font-size: 0.58rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.75);
    line-height: 1;
}

.my-teams-stat__value {
    font-size: 1.3rem;
    font-weight: 800;
    color: var(--dfl-on-brand, #fff);
    line-height: 1.1;
}

.my-teams-stat__value--pos { color: #86efac; }
.my-teams-stat__value--neg { color: #fca5a5; }

.my-teams-stat__sub {
    font-size: 0.62rem;
    color: rgba(255, 255, 255, 0.65);
    line-height: 1;
}

.my-teams-overview-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
}

.my-teams-overview-left {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.my-teams-viewer-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--dfl-brand-dark, #0f3d6b);
}

/* Custom member listbox — native <option> can't show an avatar. Shared shape with the
   HeadToHead (/vs) member pickers below and /activity's "filter by member" dropdown. */
.my-teams-viewer-picker,
.h2h-member-picker,
.activity-member-picker {
    position: relative;
}

.my-teams-viewer-picker__toggle,
.h2h-member-picker__toggle,
.activity-member-picker__toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    font-weight: 400;
    color: var(--dfl-text, #1a202c);
    background: var(--dfl-surface, #fff);
}

/* MyTeams' and /activity's pickers sit inline in a flex row, so they need a width floor; H2H's fills its grid cell. */
.my-teams-viewer-picker__toggle,
.activity-member-picker__toggle {
    min-width: 11rem;
}

.h2h-member-picker,
.h2h-member-picker__toggle {
    width: 100%;
}

.my-teams-viewer-picker__caret,
.h2h-member-picker__caret,
.activity-member-picker__caret {
    margin-left: auto;
    padding-left: 0.5rem;
    color: var(--dfl-text-muted, #6b7280);
    font-size: 0.7rem;
}

.my-teams-viewer-picker__menu,
.h2h-member-picker__menu,
.activity-member-picker__menu {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    min-width: 100%;
    z-index: 40;
    max-height: 18rem;
    overflow-y: auto;
    padding: 0.25rem;
    background: var(--dfl-surface, #fff);
    border: 1px solid var(--dfl-border, #d1d9e0);
    border-radius: 4px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
}

.my-teams-viewer-picker__option,
.h2h-member-picker__option,
.activity-member-picker__option {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 0.3rem 0.5rem;
    border: none;
    border-radius: 3px;
    background: none;
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    white-space: nowrap;
}

.my-teams-viewer-picker__option:hover,
.h2h-member-picker__option:hover,
.activity-member-picker__option:hover {
    background: var(--dfl-surface-alt, #eef4f9);
}

.my-teams-viewer-picker__option.is-selected,
.h2h-member-picker__option.is-selected,
.activity-member-picker__option.is-selected {
    background: var(--dfl-surface-alt, #eef4f9);
}

.my-teams-viewer-backdrop,
.h2h-member-backdrop,
.activity-member-backdrop {
    position: fixed;
    inset: 0;
    z-index: 35;
    background: transparent;
}

.dfl-btn-link {
    color: var(--dfl-brand, #1a5490);
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid var(--dfl-border, #d1d9e0);
    padding: 0.3rem 0.65rem;
    border-radius: 6px;
    background: var(--dfl-surface-hover, #f8fafc);
}

.dfl-btn-link:hover {
    background: var(--dfl-surface-alt, #eef4f9);
    text-decoration: none;
}


.my-teams-sport-card--inactive {
    opacity: var(--dfl-inactive-opacity, 0.75);
}

.my-teams-sport-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.65rem;
    margin-bottom: 0.75rem;
}

.my-teams-sport-title {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

.my-teams-not-started {
    font-size: 0.82rem;
}

.my-teams-finalized-badge {
    display: inline-block;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: var(--dfl-success-bg, #dcfce7);
    color: var(--dfl-success, #15803d);
    font-size: 0.62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-left: 0.5rem;
    vertical-align: middle;
}

.my-teams-sport-ranks {
    display: flex;
    gap: 0.45rem;
}

.my-teams-rank-chip {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 4.25rem;
    padding: 0.3rem 0.5rem;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    border-radius: 8px;
    text-align: center;
    gap: 0.1rem;
}

.my-teams-rank-chip__label {
    font-size: 0.58rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    opacity: 0.7;
    line-height: 1;
}

.my-teams-rank-chip__value {
    font-size: 1rem;
    font-weight: 800;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    line-height: 1;
}

.my-teams-score-bar {
    display: flex;
    margin-bottom: 0.85rem;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    border-radius: 8px;
    overflow: hidden;
    flex-wrap: wrap;
}

.my-teams-score-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0.5rem 0.4rem;
    text-align: center;
    border-right: 1px solid rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.07);
    min-width: 4.5rem;
    gap: 0.15rem;
}

.my-teams-score-item:last-child {
    border-right: none;
}

.my-teams-score-item--total {
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
}

.my-teams-score-item--pos {
    background: var(--dfl-success-bg, #dcfce7);
}

.my-teams-score-item--neg {
    background: var(--dfl-danger-bg, #fee2e2);
}

.my-teams-score-label {
    font-size: 0.57rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    opacity: 0.75;
    line-height: 1;
}

.my-teams-score-val {
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1;
    color: var(--dfl-text, #1a202c);
}

.my-teams-score-item--total .my-teams-score-label,
.my-teams-score-item--total .my-teams-score-val {
    color: var(--dfl-on-brand, #fff);
    opacity: 1;
}

.my-teams-score-item--pos .my-teams-score-val { color: var(--dfl-success, #15803d); font-weight: 700; }
.my-teams-score-item--neg .my-teams-score-val { color: var(--dfl-danger, #b91c1c); font-weight: 700; }

.my-teams-team-name {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

.my-teams-div-badge {
    display: inline-block;
    padding: 0.05rem 0.35rem;
    border-radius: 4px;
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b)));
    font-size: 0.58rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border: 1px solid var(--sport-accent, var(--dfl-brand, #1a5490));
}
.team-badge {
    display: inline-block;
    padding: 0.05rem 0.3rem;
    border-radius: 4px;
    font-size: 0.55rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    white-space: nowrap;
    vertical-align: middle;
    margin-left: 0.25rem;
}
.team-badge--div     { background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff)); color: color-mix(in srgb, white var(--dfl-accent-text-mix, 0%), var(--sport-accent, var(--dfl-brand-dark, #0f3d6b))); border: 1px solid var(--sport-accent, var(--dfl-brand, #1a5490)); }
.team-badge--champ   { background: var(--dfl-warning-bg, #fef3c7); color: var(--dfl-warning-text, #92400e); border: 1px solid var(--dfl-warning, #d97706); }
.team-badge--deep    { background: var(--dfl-success-bg, #d1fae5); color: var(--dfl-success-strong, #065f46); border: 1px solid var(--dfl-success, #059669); }
.team-badge--playoff { background: var(--dfl-purple-bg, #ede9fe); color: var(--dfl-purple-text, #4c1d95); border: 1px solid var(--dfl-purple-border, #7c3aed); }
.team-badge--entry   { background: var(--dfl-surface-hover, #f3f4f6); color: var(--dfl-text, #374151); border: 1px solid var(--dfl-text-muted, #9ca3af); }
.scarcity--low        { color: var(--dfl-warning, #d97706); font-weight: 600; }

/* ── UEFACL League Phase Draw (Sport.razor "Draws" pill) ───────────────────
   One card per club, its 8 league-phase opponents grouped by seeding pot, each with a house/plane
   venue glyph. Colour-coded pot badges (--1..--4) reused for the club's own pot in the card head
   and per pot-row. Theme-aware via the same dfl vars the rest of the file uses. */
.uefacl-draw-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr));
    gap: 0.75rem;
    margin-top: 0.75rem;
}
.uefacl-draw-card {
    border: 1px solid var(--dfl-border, #e2e8f0);
    border-radius: 10px;
    background: var(--dfl-surface, #fff);
    padding: 0.6rem 0.7rem 0.7rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.uefacl-draw-card__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding-bottom: 0.45rem;
    border-bottom: 1px solid var(--dfl-border, #e2e8f0);
}
.uefacl-draw-card__head .team-logo { width: 26px; height: 26px; }
.uefacl-draw-card__head .member-badge,
.uefacl-draw-card__head .member-badge-link { flex: 0 0 auto; }

/* Reserved space so the team logo stays aligned when a club is unowned. */
.uefacl-draw-owner-blank { flex: 0 0 auto; display: inline-block; }
.uefacl-draw-owner-blank--head { width: 26px; height: 26px; }
.uefacl-draw-owner-blank--opp { width: 18px; height: 18px; }
.uefacl-draw-card__name {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
    font-size: 0.9rem;
}
.uefacl-draw-card__opps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.uefacl-draw-potrow {
    display: grid;
    grid-template-columns: 3.2rem 1fr;
    align-items: start;
    gap: 0.4rem;
}
.uefacl-draw-potrow__opps {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.uefacl-draw-opp {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.8rem;
    white-space: nowrap;
    min-width: 0;
}
.uefacl-draw-opp .team-logo-link,
.uefacl-draw-opp .team-logo { width: 18px; height: 18px; flex: 0 0 auto; }
.uefacl-draw-opp .member-badge,
.uefacl-draw-opp .member-badge-link { flex: 0 0 auto; }
.uefacl-draw-opp .member-badge__photo,
.uefacl-draw-opp .member-badge__avatar { font-size: 0.5rem; }
/* Name flexes and ellipsises so the trailing venue glyph + kickoff time stay on the row. */
.uefacl-draw-opp .team-name { overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto; min-width: 0; }
.uefacl-draw-venue {
    margin-left: 0.15rem;
    font-size: 0.85rem;
    line-height: 1;
    opacity: 0.85;
    flex: 0 0 auto;
}
/* Scheduled kickoff, shown right after the venue glyph (see UefaclDrawService.KickoffUtc). */
.uefacl-draw-opp__time {
    flex: 0 0 auto;
    font-size: 0.7rem;
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}
.uefacl-pot-badge {
    display: inline-block;
    padding: 0.05rem 0.3rem;
    border-radius: 4px;
    font-size: 0.55rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
    border: 1px solid transparent;
}
.uefacl-pot-badge--1 { background: var(--dfl-warning-bg, #fef3c7); color: var(--dfl-warning-text, #92400e); border-color: var(--dfl-warning, #d97706); }
.uefacl-pot-badge--2 { background: var(--dfl-info-bg, #dbeafe); color: var(--dfl-info-text, #003e7e); border-color: #2563eb; }
.uefacl-pot-badge--3 { background: var(--dfl-danger-bg, #fee2e2); color: var(--dfl-danger, #b91c1c); border-color: var(--dfl-danger, #b91c1c); }
.uefacl-pot-badge--4 { background: var(--dfl-surface-hover, #f3f4f6); color: var(--dfl-text, #374151); border-color: var(--dfl-text-muted, #9ca3af); }
.uefacl-pot-badge--x { background: var(--dfl-surface-hover, #f3f4f6); color: var(--dfl-text-muted, #6b7280); border-color: var(--dfl-border, #d1d5db); }

/* Mobile / phone-landscape: team names are already abbreviated (3-4 chars) well above this width
   (the 1900px full<->abbr swap in TeamName.razor.css), so a club card needs far less width than
   the 15rem desktop floor. Drop the grid and just let content-width cards wrap — as many per row
   as naturally fit, no fixed column count. Keep the venue glyph tight against the abbreviation
   instead of letting margin-left:auto fling it to the card edge. Opponents stay stacked. */
@media (max-width: 950px) {
    .uefacl-draw-grid {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
    }
    .uefacl-draw-card {
        flex: 0 0 auto;
        padding: 0.5rem 0.5rem 0.55rem;
    }
    .uefacl-draw-potrow {
        grid-template-columns: 2.6rem 1fr;
        gap: 0.3rem;
    }
    .uefacl-draw-opp {
        min-width: 0;
        gap: 0.2rem;
        font-size: 0.72rem;
        justify-content: flex-start;
    }
    .uefacl-draw-opp .team-name {
        min-width: 0;
    }
    .uefacl-draw-opp .uefacl-draw-venue {
        margin-left: 0.15rem;
    }
}

/* ── Projection History Chart ──────────────────────────────────────────── */

.proj-chart-card {
    padding: 1.25rem 1.5rem 1rem;
}

.proj-chart-card__header {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.85rem;
    flex-wrap: wrap;
}

.proj-chart-card__title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--dfl-text, #1a202c);
    margin: 0;
    flex: 1;
}

.proj-chart-card__select {
    min-width: 130px;
}

/* ── Expandable Section (ExpandableSection.razor) ──────────────────────────
   Generic "Expand" affordance reused under any table or chart site-wide (Home/Sport/TeamDetail/
   Summary/etc.) — a tiny bottom-right link/icon under the content, popping a full-screen modal on
   click. Reuses .dfl-modal-backdrop/.dfl-modal (see that pair's comment near .dfl-briefing-modal)
   but overrides .dfl-modal's small centered-dialog width via source-order cascade, same trick
   .dfl-briefing-modal uses. Two content shapes, each with its own rules further down: charts opt
   into FitToScreen (.dfl-expand-modal--fit — sizes to fill the viewport with no scrollbar, see that
   rule's comment); tables get a scrollable body with frozen headers/columns (.dfl-expand-modal__body
   .dfl-table-wrap onward — see those rules' comments, including the z-index tiering bug that one
   was built to fix). */
.dfl-expand-footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.6rem;
}

.dfl-expand-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: none;
    border: none;
    padding: 0;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--dfl-brand, #1a5490);
    cursor: pointer;
    white-space: nowrap;
}

.dfl-expand-btn:hover {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.dfl-expand-btn__icon {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.4;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.dfl-expand-modal-backdrop {
    padding: 0.5rem;
}

.dfl-expand-modal {
    width: min(98vw, 1800px);
    height: 94vh;
    max-height: 94vh;
    display: flex;
    flex-direction: column;
    padding: 0.75rem 1rem 1rem;
}

/* Chart-only variant (ExpandableSection's FitToScreen param). Uses the SAME width as the default
   .dfl-expand-modal above (min(98vw,1800px)) plus the full 94vh height — no special width math
   needed, because the chart itself is what adapts: .proj-chart/.proj-chart__svg below are forced
   to width:100%;height:100% of this fully-sized box instead of the normal height:auto (which
   preserves the SVG's 1000:700 viewBox aspect ratio and would letterbox inside a differently-
   shaped box, leaving empty space rather than truly filling the screen). preserveAspectRatio="none"
   on the <svg> element itself (ProjectionHistoryChart.razor/TeamProjectionHistoryChart.razor) is
   what makes that non-uniform stretch actually take effect instead of the SVG's default
   letterbox-to-preserve-aspect behavior. Trade-off: on an extreme viewport aspect (a tall portrait
   phone, or an ultra-wide desktop window) the chart is visibly stretched off its natural 10:7
   proportions — an intentional trade favoring "fills the screen, no scrollbar, no dead space" over
   perfectly undistorted lines. Tables don't opt into any of this — a wide table keeps the normal
   min(98vw,1800px) width and scrolls horizontally instead of stretching. */
.dfl-expand-modal--fit .dfl-expand-modal__body .proj-chart {
    width: 100%;
    height: 100%;
}

.dfl-expand-modal--fit .dfl-expand-modal__body .proj-chart__svg {
    width: 100%;
    height: 100%;
}

.dfl-expand-modal__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
    flex-shrink: 0;
}

.dfl-expand-modal__title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--dfl-text, #1a202c);
    margin: 0;
}

.dfl-expand-modal__close {
    background: none;
    border: none;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    color: var(--dfl-text-muted, #6b7280);
    padding: 0.25rem 0.5rem;
    flex-shrink: 0;
}

/* Plain block, NOT flex, for both content paths — this body itself never scrolls or centers
   anything; each path's own nested element (.dfl-table-wrap or .proj-chart, both given an
   explicit height:100% below) is what actually fills/scrolls it. An earlier version made this
   element a `display:flex; overflow:auto` scroll container for the table path; that broke the
   freeze-col-1/2 sticky-LEFT columns because browsers have a long-standing bug where content
   overflowing the *leading* side of a centered/end-aligned flex container isn't reliably
   scrollable/stable for sticky math (the "flexbox leading overflow" issue). A later version kept
   flex here just for the chart path's centering; that's gone too now that charts stretch to fill
   (see .dfl-expand-modal--fit above) rather than being centered at their natural size. */
.dfl-expand-modal__body {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: block;
}

/* The actual scroll container for the table path (see .dfl-expand-modal__body's comment above) —
   a plain block div, not a flex item, so both freeze-col-1/2 (sticky-left) and the frozen header
   row (sticky-top, below) resolve against the same straightforward scrollport, exactly like the
   non-modal card view already does for freeze-col-1/2 (that one just never needed a bounded
   height, since its vertical scroll is the whole page, not a nested box). */
.dfl-expand-modal__body .dfl-table-wrap {
    width: 100%;
    height: 100%;
    overflow: auto;
}

/* Frozen table headers inside the Expand popup's scrollable body (the table path — FitToScreen
   charts never reach this). border-collapse:separate matches the fix the freeze-col-1/2
   sticky-COLUMN tables already use for a collapsed-border/sticky rendering gap (see that comment
   above near .dfl-standings-table--sheet) — extended here to every table since sticky ROWS hit the
   same class of issue under border-collapse:collapse (this app's default for tables without freeze
   columns). thead tr:last-child targets the row that actually carries column labels —
   single-header-row tables have only one row (it IS the last), while the two-row tables
   (Home.razor's Overall Standings, Summary.razor's scoring matrix) have a decorative sport-logo
   banner row above it; that banner row is left to scroll away normally rather than also pinning
   it, which reads fine since it carries no data.
   z-index tiering matters here and was the actual bug in an earlier version: giving every th in
   this row the SAME z-index erased the freeze-col-1/2 header cells' priority over their plain
   (top-sticky-only) siblings — with tied z-index, later-in-DOM columns win ties and paint over the
   earlier frozen ones as they scroll underneath, which is exactly the "frozen columns getting
   overlapped" symptom this was built to avoid. Plain header cells get z-index:2 (above the
   freeze-col-1/2 BODY cells' z-index:1, so the header row always wins on vertical scroll); the
   freeze-col-1/2 header cells — sticky on BOTH top and left, since the base freeze-col rule above
   already gives them `left` — get z-index:3 specifically so they stay above plain header cells
   sliding underneath them during horizontal scroll too. */
.dfl-expand-modal__body table.dfl-table {
    border-collapse: separate;
    border-spacing: 0;
}

.dfl-expand-modal__body thead tr:last-child th {
    position: sticky;
    top: 0;
    z-index: 2;
}

.dfl-expand-modal__body thead tr:last-child th.freeze-col-1,
.dfl-expand-modal__body thead tr:last-child th.freeze-col-2,
.dfl-expand-modal__body thead tr:last-child th.freeze-col-solo {
    z-index: 3;
}

.proj-chart {
    position: relative;
    border-radius: 6px;
    overflow: visible;
}

.proj-chart__svg {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 6px;
}

.proj-chart__empty {
    padding: 1.5rem 0;
    text-align: center;
}

/* Last-point avatar pins */
.proj-chart__pin {
    position: absolute;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 5;
    border-radius: 50%;
    line-height: 0;
}

.proj-chart__pin--dimmed {
    opacity: 0.15;
}

/* Compare-mode legend (ProjectionHistoryChart) */
.proj-chart__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.6rem;
}

.proj-chart__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--dfl-border, #e5e7eb);
    background: var(--dfl-surface, #fff);
    color: var(--dfl-text, #1a202c);
    cursor: pointer;
}

.proj-chart__legend-item--on {
    border-color: var(--dfl-brand, #1a5490);
    background: var(--dfl-surface-alt, #eef4f9);
    font-weight: 600;
}

.proj-chart__legend-item--dim {
    opacity: 0.45;
}

.proj-chart__legend-dot {
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    flex-shrink: 0;
}

.proj-chart__legend-clear {
    font-size: 0.75rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--dfl-border, #e5e7eb);
    background: none;
    color: var(--dfl-text-muted, #6b7280);
    cursor: pointer;
}

/* Tooltip */
.proj-chart__tooltip {
    position: absolute;
    top: 12px;
    pointer-events: none;
    z-index: 20;
    background: var(--dfl-surface, #fff);
    border: 1px solid rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.1);
    color: var(--dfl-text, #1a202c);
    border-radius: 8px;
    padding: 0.55rem 0.8rem;
    min-width: 175px;
    box-shadow: 0 4px 16px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.12);
}

.proj-chart__tooltip-date {
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--dfl-text-muted, #6b7280);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    margin-bottom: 0.45rem;
}

.proj-chart__tooltip-row {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.15rem 0;
    font-size: 0.82rem;
}

.proj-chart__tooltip-name {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--dfl-text, #1f2937);
}

.proj-chart__tooltip-score {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--dfl-text, #1a202c);
    flex-shrink: 0;
}

/* Commissioner projection history table */
.proj-history-controls {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.proj-history-label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--dfl-text, #374151);
}

.proj-history-chart-wrap {
    margin-bottom: 0.5rem;
}

.proj-history-table th {
    font-size: 0.75rem;
    white-space: nowrap;
    padding: 0.3rem 0.5rem;
}

/* Member color palette picker */
.member-palette-list {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.member-palette-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.6rem 0;
    border-bottom: 1px solid rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.06);
}

.member-palette-row:last-child {
    border-bottom: none;
}

.member-palette-row__identity {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 170px;
}

.member-palette-row__name {
    font-weight: 500;
    font-size: 0.9rem;
    color: var(--dfl-text, #1a202c);
}

.member-palette-row__swatches {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    flex: 1;
}

.palette-swatch {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2.5px solid transparent;
    cursor: pointer;
    outline: none;
    transition: transform 0.1s, box-shadow 0.1s;
    box-shadow: 0 1px 3px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.18);
}

.palette-swatch:hover {
    transform: scale(1.2);
    box-shadow: 0 2px 6px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.28);
}

.palette-swatch--active {
    border-color: var(--dfl-text, #1a202c);
    transform: scale(1.15);
    box-shadow: 0 0 0 3px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.12);
}

.proj-history-date {
    font-size: 0.8rem;
    white-space: nowrap;
    color: var(--dfl-text-muted, #6b7280);
}

/* CommissionerEuchreHistory.razor — games list' per-seat badge row, and the hand-transcript
   readable log (one line per bid/discard/card play, trick-won lines picked out from the rest). */
.euchre-history-seats {
    display: flex;
    gap: 0.35rem;
    flex-wrap: wrap;
}

.euchre-history-transcript {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.euchre-history-transcript li {
    padding: 0.35rem 0.6rem;
    border-radius: 6px;
    background: var(--dfl-surface-alt, #eef4f9);
}

.euchre-history-transcript__trick-won {
    font-weight: 700;
    background: var(--dfl-surface-hover, #f3f4f6);
}

/* ── Qualifying Path (QualifyingPathTable.razor, UEFACL only) ─────────────
   One card per pool club still alive in qualifying, replacing the old table's one-row-per-round
   layout. All colors route through existing theme tokens (--dfl-*, inline --sport-accent/-soft), so
   no separate dark-mode block is needed here — see app.css's top-of-file token comment for why that
   holds for every rule below. */
.dfl-qualpath-grid {
    display: grid;
    /* 26rem (not the original 15.5rem) is the narrowest a card can go and still fit a round row's
       label + legs + status pill on one line without wrapping — see .dfl-qualpath-round's
       flex-wrap: nowrap comment below for the other half of that guarantee. */
    grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr));
    gap: 0.85rem;
}

.dfl-qualpath-card {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    border-radius: 12px;
    background: var(--dfl-surface, #fff);
    border: 1px solid var(--dfl-border, #e5e7eb);
    box-shadow: 0 1px 4px rgba(var(--dfl-shadow-rgb, 0, 0, 0), 0.06);
}

.dfl-qualpath-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.dfl-qualpath-card__team {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 700;
    min-width: 0;
}

.dfl-qualpath-card__team .team-logo {
    width: 24px;
    height: 24px;
}

.dfl-qualpath-card__unowned {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--dfl-text-muted, #6b7280);
}

/* Eliminated clubs stay in the grid (see QualifyingPathTable.razor's header comment) but read as
   visually "done" — dimmed card, danger-tinted border, and a small OUT tag next to the team name. */
.dfl-qualpath-card.is-eliminated {
    border-color: var(--dfl-danger, #b91c1c);
    opacity: 0.72;
}

.dfl-qualpath-out {
    display: inline-block;
    padding: 0.03rem 0.3rem;
    border-radius: 4px;
    background: var(--dfl-danger-bg, #fee2e2);
    color: var(--dfl-danger, #b91c1c);
    border: 1px solid var(--dfl-danger, #b91c1c);
    font-size: 0.55rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    flex-shrink: 0;
}

/* Owner chip: MemberBadge's default layout is a horizontal avatar+name row (see .member-badge in
   this file), which reads too wide for a card header — stack the (shrunk) name under the avatar
   instead, same "small caption under a bigger visual" pattern .dfl-sport-leader-card already uses. */
.dfl-qualpath-card__header .member-badge {
    flex-direction: column;
    gap: 0.15rem;
    flex-shrink: 0;
}

.dfl-qualpath-card__header .member-badge__name {
    font-size: 0.6rem;
    font-weight: 700;
    text-align: center;
    max-width: 4.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Step tracker: one dot+label per round the team has played, oldest first, connected by a line that
   fills in as rounds are won. Every step but the last is always "is-won" (a team only gets a next
   -round entry by winning the previous one — see QualifyingPathTable.razor's header comment), so
   only the last step's color/pulse actually varies at runtime. */
.dfl-qualpath-steps {
    display: flex;
    align-items: flex-start;
}

.dfl-qualpath-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
}

.dfl-qualpath-step__dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: var(--dfl-border-strong, #cbd5e1);
    border: 2px solid var(--dfl-surface, #fff);
    box-shadow: 0 0 0 1px var(--dfl-border-strong, #cbd5e1);
}

.dfl-qualpath-step__label {
    font-size: 0.58rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--dfl-text-muted, #6b7280);
    white-space: nowrap;
}

.dfl-qualpath-step.is-won .dfl-qualpath-step__dot {
    background: var(--dfl-success, #15803d);
    box-shadow: 0 0 0 1px var(--dfl-success, #15803d);
}

.dfl-qualpath-step.is-eliminated .dfl-qualpath-step__dot {
    background: var(--dfl-danger, #b91c1c);
    box-shadow: 0 0 0 1px var(--dfl-danger, #b91c1c);
}

.dfl-qualpath-step.is-current .dfl-qualpath-step__dot,
.dfl-qualpath-step.is-upcoming .dfl-qualpath-step__dot {
    background: var(--sport-accent, var(--dfl-brand, #1a5490));
    box-shadow: 0 0 0 1px var(--sport-accent, var(--dfl-brand, #1a5490));
}

.dfl-qualpath-step.is-current .dfl-qualpath-step__dot {
    animation: dfl-qualpath-pulse 1.6s ease-in-out infinite;
}

.dfl-qualpath-step.is-current .dfl-qualpath-step__label,
.dfl-qualpath-step.is-won .dfl-qualpath-step__label {
    color: var(--dfl-text, #1f2937);
}

@keyframes dfl-qualpath-pulse {
    0%, 100% { box-shadow: 0 0 0 1px var(--sport-accent, var(--dfl-brand, #1a5490)); }
    50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--sport-accent, var(--dfl-brand, #1a5490)) 35%, transparent); }
}

.dfl-qualpath-connector {
    flex: 1 1 auto;
    height: 2px;
    margin: 0.28rem -0.1rem 0;
    background: var(--dfl-border-strong, #cbd5e1);
    min-width: 0.5rem;
}

.dfl-qualpath-connector.is-won {
    background: var(--dfl-success, #15803d);
}

/* One row per round the team has played (not just the current one — see this file's header comment
   on why "past round games are no longer shown" was the whole point of this section existing). Past
   rounds render plain/compact; only the group's last round (.is-current) gets the accent-tinted
   background that used to be the ONLY round shown here, so the eye still lands on "what's happening
   now" first even though the full history is present. */
.dfl-qualpath-rounds {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.dfl-qualpath-round {
    display: flex;
    /* nowrap, not wrap — label/legs/status below are all flex-shrink: 0 (never compress), so
       .dfl-qualpath-vs (flex-shrink allowed, name already ellipsis-truncates) is the only piece that
       gives, keeping every round on one line. Needs the grid's 26rem card minimum (see
       .dfl-qualpath-grid) to have room for that to look right rather than truncating too aggressively. */
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.3rem 0.6rem;
    padding: 0.35rem 0.6rem;
    border-radius: 8px;
    background: var(--dfl-surface-hover, #f8fafc);
}

.dfl-qualpath-round.is-current {
    background: color-mix(in srgb, var(--sport-accent-soft, var(--dfl-surface-alt, #eef4f9)) var(--dfl-tint-mix, 100%), var(--dfl-surface, #fff));
    padding: 0.5rem 0.65rem;
}

.dfl-qualpath-round__label {
    font-size: 0.58rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--dfl-text-muted, #6b7280);
    flex: 0 0 auto;
    min-width: 3.2rem;
}

.dfl-qualpath-vs {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
    font-size: 0.78rem;
    font-weight: 600;
    flex: 1 1 auto;
}

.dfl-qualpath-round.is-current .dfl-qualpath-vs {
    font-size: 0.82rem;
}

.dfl-qualpath-vs .team-logo {
    width: 18px;
    height: 18px;
}

.dfl-qualpath-round.is-current .dfl-qualpath-vs .team-logo {
    width: 20px;
    height: 20px;
}

.dfl-qualpath-vs__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dfl-qualpath-legs {
    display: flex;
    flex-shrink: 0;
    gap: 0.5rem;
    font-size: 0.74rem;
    font-variant-numeric: tabular-nums;
    color: var(--dfl-text-muted, #6b7280);
    white-space: nowrap;
}

.dfl-qualpath-status {
    display: inline-block;
    flex-shrink: 0;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.62rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
}

.dfl-qualpath-status--advanced { background: var(--dfl-success-bg, #dcfce7); color: var(--dfl-success-strong, #14532d); border: 1px solid var(--dfl-success, #15803d); }
.dfl-qualpath-status--eliminated { background: var(--dfl-danger-bg, #fee2e2); color: var(--dfl-danger, #b91c1c); border: 1px solid var(--dfl-danger, #b91c1c); }
.dfl-qualpath-status--live { background: var(--dfl-info-bg, #dbeafe); color: var(--dfl-info-text, #003e7e); border: 1px solid var(--dfl-info-border, #bfdbfe); }
.dfl-qualpath-status--upcoming { background: var(--dfl-surface-hover, #f3f4f6); color: var(--dfl-text-muted, #6b7280); border: 1px solid var(--dfl-border-strong, #cbd5e1); }

@media (max-width: 480px) {
    .dfl-qualpath-grid {
        grid-template-columns: 1fr;
    }
}
