/* ============================================================
   Court Series Design System – Global Styles
   ============================================================ */

/* ---- Design Tokens ---- */
:root {
    /* Status colors */
    --status-completed-bg:   rgba(34, 197, 94, 0.12);
    --status-completed-fg:   #15803D;
    --status-in-progress-bg: rgba(245, 158, 11, 0.12);
    --status-in-progress-fg: #B45309;
    --status-upcoming-bg:    rgba(59, 130, 246, 0.12);
    --status-upcoming-fg:    #1D4ED8;
    --status-pending-approval-bg: rgba(249, 115, 22, 0.12);
    --status-pending-approval-fg: #C2410C;
    --status-disputed-bg:    rgba(220, 38, 38, 0.08);
    --status-disputed-fg:    #B91C1C;
    --status-disputed-border: rgba(220, 38, 38, 0.35);

    /* Rank badge colors */
    --rank-gold-bg:   rgba(212, 160, 23, 0.12);
    --rank-gold-fg:   #D4A017;
    --rank-silver-bg: rgba(156, 163, 175, 0.15);
    --rank-silver-fg: #6B7280;
    --rank-bronze-bg: rgba(217, 119, 6, 0.12);
    --rank-bronze-fg: #D97706;

    /* League promotion / relegation slot tints (group cards). */
    --promotion-row-bg:      rgba(34, 197, 94, 0.06);
    --promotion-marker-bg:   rgba(34, 197, 94, 0.18);
    --relegation-row-bg:     rgba(220, 38, 38, 0.06);
    --relegation-marker-bg:  rgba(220, 38, 38, 0.18);

    /* Recent form W/L chips */
    --form-win-bg:  #dcfce7;
    --form-win-fg:  #15803D;
    --form-loss-bg: #fee2e2;
    --form-loss-fg: #B91C1C;

    /* Structural borders */
    --border-subtle: rgba(26, 58, 92, 0.08);
    --border-light:  rgba(26, 58, 92, 0.10);

    /* Surface / tint tokens (CourtNavy & AceTeal at various opacities) */
    --navy-tint-2:    rgba(26, 58, 92, 0.02);
    --navy-tint-3:    rgba(26, 58, 92, 0.03);
    --navy-tint-4:    rgba(26, 58, 92, 0.04);
    --navy-tint-6:    rgba(26, 58, 92, 0.06);
    --navy-tint-30:   rgba(26, 58, 92, 0.30);
    --navy-tint-70:   rgba(26, 58, 92, 0.70);
    --teal-tint-4:    rgba(13, 148, 136, 0.04);
    --teal-tint-6:    rgba(13, 148, 136, 0.06);
    --teal-tint-10:   rgba(13, 148, 136, 0.10);
    --teal-tint-20:   rgba(13, 148, 136, 0.20);
    --teal-tint-30:   rgba(13, 148, 136, 0.30);
    --draw-connector: rgba(13, 148, 136, 0.45);
    --warning-glow:   rgba(245, 158, 11, 0.45);

    /* ChalkWhite — the Court Series background/alt surface color. */
    --chalk-white: #F5F5F0;

    /* DeepCourt — the Court Series AppBar/sidebar background. */
    --deep-court: #0F2440;

    /* Shadow tokens */
    --shadow-sm:  0 1px 3px rgba(26, 58, 92, 0.06);
    --shadow-md:  0 6px 20px rgba(26, 58, 92, 0.10);
    --shadow-xs:  0 2px 8px rgba(26, 58, 92, 0.08);

    /* League slot colors (AceTeal) */
    --league-slot-color:    #0D9488;
    --league-slot-bg:       rgba(13, 148, 136, 0.12);
    --league-slot-bg-hover: rgba(13, 148, 136, 0.20);
    --league-slot-claimed-bg: rgba(13, 148, 136, 0.18);
    --league-slot-mine-fg:  #15803D;
    --league-slot-mine-bg:  rgba(34, 197, 94, 0.15);
    --league-slot-mine-border: #22C55E;

    /* Issue #1158: "my reservation" cells render as solid primary fill with a
       MatchGold border so members can spot their own bookings at a glance —
       the prior 12% tint read as just another gray "Booked" cell. Foreground
       flips to ChalkWhite for contrast against the dark navy fill. Border
       stays routed through --mud-palette-tertiary so a tenant theme swap
       carries through. */
    --booked-mine-fg:     var(--chalk-white);
    --booked-mine-border: var(--mud-palette-tertiary);
    --booked-mine-bg:     var(--mud-palette-primary);

    /* Issue #771 follow-up: no-show slot tokens. MatchGold border + caption +
       icon, ChalkWhite underpaint, MutedGray fallback when the session type
       has no configured colour. --noshow-session-color is set inline on each
       cell so the same rule renders against whatever colour the tenant
       configured for the session type. */
    --noshow-color:            #D4A017;
    --noshow-fill-base:        #F5F5F0;
    --noshow-session-fallback: #6B7280;

    /* Scheduling calendar tokens */
    --scheduling-grid-gap:      rgba(26, 58, 92, 0.08);
    --scheduling-header-border: var(--mud-palette-primary);
    --scheduling-time-color:    var(--mud-palette-text-primary);
    --scheduling-time-font:     0.95rem;
    --scheduling-time-weight:   700;
    --scheduling-slot-bg:       #fff;
    --scheduling-slot-hover:    var(--teal-tint-6);
    --scheduling-closed-bg:     #f5f5f5;
    --scheduling-closed-color:  var(--mud-palette-text-disabled);
    --scheduling-month-hover:   var(--teal-tint-6);
    --scheduling-today-bg:      var(--navy-tint-6);
    --scheduling-today-border:  var(--mud-palette-primary);

    /* Court surface type colors */
    --surface-clay:  #C2613A;
    --surface-hard:  #4A7AB5;
    --surface-grass: #3A8F47;

    /* Analytics heatmap ramp (#307) — 5-step pale-chalk → AceTeal → CourtNavy.
       Used by court utilisation, and reused by future analytics heatmaps. */
    --heat-l0:        #F1F2EE;
    --heat-l1:        #C8E5E1;
    --heat-l2:        #6FC1B7;
    --heat-l3:        #1A9F90;
    --heat-l4:        #11625B;
    --heat-fg-light:  var(--mud-palette-primary);
    --heat-fg-dark:   var(--chalk-white);
    --heat-closed-bg: var(--navy-tint-4);
    --heat-closed-stripe: rgba(26, 58, 92, 0.08);

    /* Tenant-overridable primary color token */
    --tc-primary: #1A3A5C;
}

/* ============================================================
   Dark theme token overrides (#910)

   "Deep Court at night" — the Court Series palette carried into dark mode.
   MudBlazor's PaletteDark recolors its own components; this block recolors the
   custom tokens that non-Mud surfaces consume. `html.clubrise-theme-dark` beats
   `:root` (equal specificity, later in the cascade) for every token NOT set
   inline; themeManager.js strips the tenant-derived inline vars in dark mode so
   these win there too. Dark is fixed for all tenants (issue #910).
   ============================================================ */
html.clubrise-theme-dark {
    /* Status colors — brighter fg, translucent bg on dark surfaces */
    --status-completed-bg:   rgba(52, 211, 153, 0.18);
    --status-completed-fg:   #6EE7B7;
    --status-in-progress-bg: rgba(251, 191, 36, 0.18);
    --status-in-progress-fg: #FCD34D;
    --status-upcoming-bg:    rgba(96, 165, 250, 0.18);
    --status-upcoming-fg:    #93C5FD;
    --status-pending-approval-bg: rgba(251, 146, 60, 0.18);
    --status-pending-approval-fg: #FDBA74;
    --status-disputed-bg:    rgba(248, 113, 113, 0.16);
    --status-disputed-fg:    #FCA5A5;
    --status-disputed-border: rgba(248, 113, 113, 0.45);

    /* Rank badges */
    --rank-gold-bg:   rgba(212, 160, 23, 0.20);
    --rank-gold-fg:   #E9C04A;
    --rank-silver-bg: rgba(203, 213, 225, 0.16);
    --rank-silver-fg: #CBD5E1;
    --rank-bronze-bg: rgba(217, 119, 6, 0.20);
    --rank-bronze-fg: #E0A458;

    /* Promotion / relegation */
    --promotion-row-bg:     rgba(52, 211, 153, 0.10);
    --promotion-marker-bg:  rgba(52, 211, 153, 0.26);
    --relegation-row-bg:    rgba(248, 113, 113, 0.10);
    --relegation-marker-bg: rgba(248, 113, 113, 0.26);

    /* Form W/L chips */
    --form-win-bg:  rgba(52, 211, 153, 0.20);
    --form-win-fg:  #6EE7B7;
    --form-loss-bg: rgba(248, 113, 113, 0.20);
    --form-loss-fg: #FCA5A5;

    /* Structural borders — light, low-opacity on dark */
    --border-subtle: rgba(232, 238, 244, 0.10);
    --border-light:  rgba(232, 238, 244, 0.16);

    /* Tints flip from navy to light */
    --navy-tint-2:  rgba(232, 238, 244, 0.03);
    --navy-tint-3:  rgba(232, 238, 244, 0.04);
    --navy-tint-4:  rgba(232, 238, 244, 0.06);
    --navy-tint-6:  rgba(232, 238, 244, 0.09);
    --navy-tint-30: rgba(232, 238, 244, 0.30);
    --navy-tint-70: rgba(232, 238, 244, 0.70);
    --teal-tint-4:  rgba(45, 212, 191, 0.10);
    --teal-tint-6:  rgba(45, 212, 191, 0.14);
    --teal-tint-10: rgba(45, 212, 191, 0.20);
    --teal-tint-20: rgba(45, 212, 191, 0.30);
    --teal-tint-30: rgba(45, 212, 191, 0.40);
    --draw-connector: rgba(45, 212, 191, 0.55);
    --warning-glow: rgba(251, 191, 36, 0.45);

    /* Surfaces */
    --chalk-white: #13283F;   /* alt surface → dark card */
    --deep-court:  #0A1626;   /* appbar/sidebar already dark */

    /* Shadows deepen on dark */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.40);
    --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.50);
    --shadow-xs: 0 2px 8px rgba(0, 0, 0, 0.45);

    /* League slots */
    --league-slot-color:      #2DD4BF;
    --league-slot-bg:         rgba(45, 212, 191, 0.20);
    --league-slot-bg-hover:   rgba(45, 212, 191, 0.30);
    --league-slot-claimed-bg: rgba(45, 212, 191, 0.28);
    --league-slot-mine-fg:    #6EE7B7;
    --league-slot-mine-bg:    rgba(52, 211, 153, 0.22);
    --league-slot-mine-border: #34D399;

    /* No-show tokens */
    --noshow-fill-base:        #13283F;
    --noshow-session-fallback: #7C8696;

    /* Scheduling */
    --scheduling-grid-gap:   rgba(232, 238, 244, 0.10);
    --scheduling-slot-bg:    #13283F;
    --scheduling-closed-bg:  #0E2034;

    /* Heatmap ramp — dark variant (deep navy → teal → bright) */
    --heat-l0: #16243A;
    --heat-l1: #1C4A48;
    --heat-l2: #2A7A72;
    --heat-l3: #3FA99B;
    --heat-l4: #5BD0BE;
    --heat-closed-bg:     rgba(232, 238, 244, 0.06);
    --heat-closed-stripe: rgba(232, 238, 244, 0.08);

    /* Court surface types — keep recognizable, slightly lift for dark */
    --surface-clay:  #C2613A;
    --surface-hard:  #5B91C9;
    --surface-grass: #4BA65A;

    --tc-primary: #5B91C9;
}

/* ---- Auth Splash Screen ---- */
.auth-splash {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: var(--mud-palette-surface);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 9999;
    animation: auth-splash-in 0.6s ease-out;
}

.auth-splash img {
    width: 312px;
    height: auto;
    animation: auth-logo-pulse 2s ease-in-out infinite;
}

@keyframes auth-splash-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes auth-logo-pulse {
    0%, 100% { opacity: 0.4; transform: scale(0.95); }
    50%      { opacity: 1;   transform: scale(1);    }
}

/* ---- Card Hover Lift ---- */
.elevated-element {
    transition: box-shadow 0.25s ease, transform 0.25s ease;
}

.elevated-element:hover {
    box-shadow: var(--mud-elevation-8);
    transform: translateY(-2px);
}

/* ---- Competition Status Colors (chips and badges) ---- */
.status-completed {
    background-color: var(--status-completed-bg) !important;
    color: var(--status-completed-fg) !important;
    border: none !important;
}

.status-in-progress {
    background-color: var(--status-in-progress-bg) !important;
    color: var(--status-in-progress-fg) !important;
    border: none !important;
}

.status-upcoming {
    background-color: var(--status-upcoming-bg) !important;
    color: var(--status-upcoming-fg) !important;
    border: none !important;
}

.status-pending-approval {
    background-color: var(--status-pending-approval-bg) !important;
    color: var(--status-pending-approval-fg) !important;
    border: none !important;
}

/* ============================================================
   Match Card (mc-*) — Premium Scoreboard Component
   ============================================================ */

/* ─── Card Shell ─── */
.mc {
    position: relative;
    display: flex;
    min-width: 240px;
    border-radius: 10px;
    background: var(--mud-palette-surface);
    border: 1px solid var(--border-light);
    cursor: pointer;
    overflow: hidden;
    transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
    box-shadow: var(--shadow-sm);
}

.mc:hover {
    box-shadow: var(--shadow-md);
    border-color: var(--teal-tint-30);
    transform: translateY(-1px);
}

.mc:active {
    transform: translateY(0);
    box-shadow: var(--shadow-xs);
}

.mc.mc--bye {
    cursor: default;
    pointer-events: none;
}
.mc.mc--bye:hover {
    box-shadow: var(--shadow-sm);
    border-color: var(--border-light);
    transform: none;
}

/* ─── Status Strip (left edge) ─── */
.mc__status-strip {
    width: 4px;
    flex-shrink: 0;
    border-radius: 10px 0 0 10px;
    background: var(--border-light);
    transition: background 0.2s ease;
}

.mc-status--final    .mc__status-strip { background: var(--mud-palette-success); }
.mc-status--live     .mc__status-strip { background: var(--mud-palette-warning); }
.mc-status--awaiting .mc__status-strip { background: var(--status-pending-approval-fg); }
.mc-status--pending  .mc__status-strip { background: var(--border-subtle); }

/* ─── Card Body ─── */
/* The schedule sidebar (.mc__schedule) is taller than two team rows once it
   stacks court / day+date / time, so flex stretches the body to match. Centering
   the rows along the body's main axis keeps the team rows vertically aligned
   with the sidebar's tinted panel instead of pinned to the top. */
.mc__body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* ─── Team Row ─── */
.mc__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    gap: 8px;
    min-height: 36px;
    transition: background-color 0.15s ease;
}

.mc__row--winner {
    background: var(--teal-tint-6);
}

.mc__row--pending {
    opacity: 0.55;
}

/* ─── Team Name Area ─── */
.mc__team {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    flex: 1;
}

.mc__seed {
    flex-shrink: 0;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    background: var(--navy-tint-6);
    border-radius: 4px;
    padding: 1px 5px;
    line-height: 1.3;
}

/* Avatar group in front of the team name (ShowPlayerImages opt-in).
   MudAvatarGroup would be the natural choice, but its overlap CSS targets
   .mud-avatar children only — and PlayerImage renders MudImage when an
   image is loaded (needed for JS-interop preview), so the avatar group's
   negative-margin / ring rules never reach it. These two rules give us the
   same effect across both code paths (loaded image and initials fallback). */
.mc__avatars {
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

.mc__avatar {
    border: 1.5px solid var(--mud-palette-surface);
    border-radius: 50%;
}

.mc__avatars > .mc__avatar + .mc__avatar {
    margin-left: -7px;
}

.mc__name {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    line-height: 1.35;
}

.mc__row--winner .mc__name {
    font-weight: 700;
    color: var(--mud-palette-primary-darken);
}

.mc__name--tentative {
    opacity: 0.5;
    font-style: italic;
}

/* ─── Retired Badge ─── */
.mc__ret {
    flex-shrink: 0;
    font-size: 0.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--form-loss-fg);
    background: var(--form-loss-bg);
    border-radius: 3px;
    padding: 1px 5px;
    line-height: 1.4;
}

/* ─── Scores Area ─── */
.mc__scores {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
}

.mc__set {
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
    min-width: 18px;
    text-align: center;
    padding: 2px 3px;
    border-radius: 3px;
    line-height: 1.2;
}

.mc__set--won {
    font-weight: 600;
    color: var(--mud-palette-primary-darken);
}

.mc__total {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    min-width: 20px;
    text-align: center;
    padding: 2px 4px;
    margin-left: 4px;
    border-radius: 4px;
    background: var(--navy-tint-4);
    line-height: 1.2;
}

.mc__total--won {
    font-weight: 800;
    color: var(--mud-palette-primary-darken);
    background: var(--teal-tint-10);
}

/* ─── Row Divider ─── */
.mc__divider {
    height: 1px;
    margin: 0 12px;
    background: var(--border-subtle);
}

/* Divider-embedded round marker. Opt-in (ShowRound) so only the
   competition schedule grid uses it — bracket view and match lists
   keep the plain 1px line. */
.mc__divider--with-round {
    display: flex;
    align-items: center;
    gap: 8px;
    height: auto;
    margin: 2px 12px;
    background: transparent;
}
.mc__divider--with-round::before,
.mc__divider--with-round::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-subtle);
}
.mc__divider-round {
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-primary);
    background: var(--navy-tint-6);
    padding: 1px 6px;
    border-radius: 3px;
    line-height: 1.3;
    white-space: nowrap;
}

/* ─── Live Pulse Dot ─── */
.mc__live-dot {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--mud-palette-warning);
    animation: mc-pulse 1.8s ease-in-out infinite;
}

@keyframes mc-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 var(--warning-glow); }
    50%      { opacity: 0.7; box-shadow: 0 0 0 5px transparent; }
}

/* ─── Awaiting Approval Badge ─── */
.mc-status--awaiting {
    background: var(--status-pending-approval-bg);
}
.mc__awaiting-badge {
    position: absolute;
    top: 5px;
    right: 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--status-pending-approval-fg);
    opacity: 0.8;
    animation: mc-await-pulse 2.4s ease-in-out infinite;
}

@keyframes mc-await-pulse {
    0%, 100% { opacity: 0.8; }
    50%      { opacity: 0.4; }
}

/* #874: each fact (court / day+date / time) gets its own row, the whole
   stack is centered on both axes, and the section uses --navy-tint-4 so it
   reads as a distinct meta panel one step lighter than the match dialog
   hero (--navy-tint-3). No border — the tint already separates it from the
   body, and a top border made no sense on a side-by-side sibling. */
.mc__schedule {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 12px;
    background: var(--navy-tint-4);
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}
.mc__schedule-item {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
}
.mc__schedule-item .mud-icon-root {
    font-size: 0.8125rem;
}

/* ─── Responsive: tighter on small viewports ─── */
@media (max-width: 599.98px) {
    .mc { min-width: 200px; }
    .mc__row { padding: 6px 10px; }
    .mc__name { font-size: 0.75rem; }
    .mc__total { font-size: 0.8125rem; }
    .mc__set { font-size: 0.6875rem; min-width: 16px; }
    .mc__divider { margin: 0 10px; }
}

/* Status border accents for MatchSummaryCard & other match-card consumers */
.completed-match-card   { border-left: 3px solid var(--mud-palette-success); }
.in-progress-match-card      { border-left: 3px solid var(--mud-palette-warning); }
.pending-approval-match-card { border-left: 3px solid var(--mud-palette-info); }
.match-winner-row {
    font-weight: 700;
    color: var(--mud-palette-primary-darken);
    background-color: var(--teal-tint-6);
}

/* ---- Profile Images ---- */
.profile-image {
    border: 2px solid var(--mud-palette-secondary);
    border-radius: 50%;
}

.image-container {
    width: 6rem;
    height: 6rem;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid var(--mud-palette-secondary);
    margin: 0 auto;
    margin-top: 1.5rem;
}

.image-container .profile-image {
    border-radius: unset;
    border: none;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover;
}

.adm-avatar .profile-image {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover;
    border-radius: 50%;
    border: none;
}

.pp-hero-photo .profile-image,
.h2h-player-photo .profile-image {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover;
    border-radius: 50%;
}

/* ---- Rankings – Top 3 Accent ---- */
.rank-gold   { color: var(--rank-gold-fg);   font-weight: 700; }
.rank-silver { color: var(--rank-silver-fg); font-weight: 700; }
.rank-bronze { color: var(--rank-bronze-fg); font-weight: 700; }

/* ---- Court Line Gradient Divider ---- */
.court-divider {
    height: 3px;
    background: linear-gradient(90deg, var(--mud-palette-primary) 0%, var(--mud-palette-secondary) 50%, var(--mud-palette-primary) 100%);
    border-radius: 2px;
    margin: 8px 0;
}

/* ---- Court Edit Dialog ---- */
/* Sticky tab header so tabs stay visible when the tab body scrolls. MudBlazor has no
   out-of-box sticky-tabs switch, so this stays. */
.edit-court-dialog .edit-court-dialog-tabs .mud-tabs-header {
    background-color: var(--mud-palette-background);
    position: sticky;
    top: 0;
    z-index: 1;
}

/* Mobile: all court-admin dialogs go edge-to-edge (MudDialog's FullScreen option is
   all-or-nothing, not responsive — hence the media query). */
@media (max-width: 599px) {
    .edit-court-dialog.mud-dialog,
    .new-court-dialog.mud-dialog,
    .new-closure-dialog.mud-dialog {
        margin: 0 !important;
        max-height: 100dvh !important;
        height: 100dvh !important;
        max-width: 100vw !important;
        width: 100vw !important;
        border-radius: 0 !important;
    }

    .edit-court-dialog .mud-dialog-content,
    .new-court-dialog .mud-dialog-content,
    .new-closure-dialog .mud-dialog-content {
        max-height: none !important;
    }
}

/* Pre-existing: weekly-hours row hover — unchanged from before this redesign */
.edit-court-dialog .weekly-hours-row,
.weekly-hours-row {
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid transparent;
    transition: background-color 0.15s ease;
}

.edit-court-dialog .weekly-hours-row:hover,
.weekly-hours-row:hover {
    background-color: var(--navy-tint-4);
    border-color: var(--border-subtle);
}

/* Mobile: edge-to-edge dialog since MudBlazor's FullScreen is all-or-nothing,
   not responsive. Same pattern as edit-court / new-closure dialogs above. */
@media (max-width: 599px) {
    .create-weekly-slot-pool-dialog.mud-dialog {
        margin: 0 !important;
        max-height: 100dvh !important;
        height: 100dvh !important;
        max-width: 100vw !important;
        width: 100vw !important;
        border-radius: 0 !important;
    }

    .create-weekly-slot-pool-dialog .mud-dialog-content {
        max-height: none !important;
    }
}

/* Mobile: import-rankings dialog goes edge-to-edge so the multi-section preview
   table is usable on small screens. Same pattern as the dialogs above. */
@media (max-width: 599px) {
    .import-rankings-dialog.mud-dialog {
        margin: 0 !important;
        max-height: 100dvh !important;
        height: 100dvh !important;
        max-width: 100vw !important;
        width: 100vw !important;
        border-radius: 0 !important;
    }

    .import-rankings-dialog .mud-dialog-content {
        max-height: none !important;
    }
}

/* ---- Dashboard Section Headers ---- */
.section-header {
    display: flex;
    align-items: center;
    padding: 12px 0 8px 0;
    border-bottom: 2px solid var(--border-subtle);
    margin-bottom: 12px;
}

/* ---- Utility ---- */
.bold-text            { font-weight: 600; }
.icon-text-row        { display: flex; align-items: center; gap: 4px; }
.text-center          { text-align: center; }
.text-italic          { font-style: italic; }
.description-text     { line-height: 1.75; overflow-wrap: break-word; word-break: break-word; white-space: pre-wrap; max-width: 100%; }
.ce-hero-title        { font-weight: 700; text-align: center; }
.comp-name-bold       { font-weight: 700; line-height: 1.3; }
/* ============================================================
   Match Dialog (md-*) — Detailed Match View
   ============================================================ */

.md-dialog { min-width: 420px; }

/* ─── Title ─── */
.md-title {
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--mud-palette-primary);
}

/* ─── Matchup Hero ─── */
.md-hero {
    display: flex;
    align-items: stretch;
    gap: 0;
    background: var(--navy-tint-3);
    border-radius: 12px;
    border: 1px solid var(--border-subtle);
    padding: 20px 12px;
    margin-bottom: 16px;
}

.md-hero__team {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.md-hero__name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    text-align: center;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    max-width: 100%;
}

.md-hero__center {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0 16px;
}

.md-hero__score {
    font-size: 1.75rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--mud-palette-primary-darken);
}

.md-hero__score--pending {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.md-hero__score--pending-approval {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--status-pending-approval-fg);
    opacity: 0.85;
}

/* ─── Pending Approval Component (inside MatchDialog) ─── */
.md-pending-approval__banner {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 8px;
    background: var(--status-pending-approval-bg);
    border-left: 3px solid var(--status-pending-approval-fg);
}
.md-pending-approval__banner-icon {
    color: var(--status-pending-approval-fg);
    margin-top: 1px;
    flex-shrink: 0;
}
.md-pending-approval__banner-text {
    color: var(--status-pending-approval-fg);
    font-weight: 500;
    line-height: 1.5;
}
.md-pending-approval__details {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 12px 0 4px;
}
.md-pending-approval__detail-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.md-pending-approval__detail-icon {
    color: var(--mud-palette-text-secondary);
    opacity: 0.7;
    flex-shrink: 0;
}
.md-pending-approval__expires {
    color: var(--mud-palette-text-secondary);
}
.md-pending-approval__actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    padding-top: 8px;
}

/* ─── Pending Approvals Page Cards ─── */
.pa-card {
    padding: 16px;
    border-radius: 12px !important;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.pa-card__matchup {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.pa-card__score {
    display: flex;
    align-items: center;
}
.pa-card__score-value {
    font-weight: 700;
    color: var(--status-pending-approval-fg);
    letter-spacing: -0.01em;
}

/* ─── Disputed Submissions Cards ─── */
.ds-card {
    padding: 16px;
    border-radius: 12px !important;
    border-left: 4px solid var(--status-disputed-fg) !important;
    background: linear-gradient(135deg, var(--status-disputed-bg) 0%, transparent 60%);
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.ds-card:hover {
    box-shadow: 0 4px 16px rgba(185, 28, 28, 0.12);
    transform: translateY(-1px);
}
.ds-card__matchup {
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: center;
}
.ds-card__score-label {
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.68rem;
}
.ds-card__score-value {
    font-weight: 700;
    color: var(--status-disputed-fg);
    letter-spacing: -0.01em;
    text-decoration: line-through;
    opacity: 0.75;
}
.ds-card__reason {
    padding: 8px 12px;
    border-radius: 6px;
    background: var(--status-disputed-bg);
    border: 1px solid var(--status-disputed-border);
}
.ds-card__reason-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--status-disputed-fg);
    margin-bottom: 2px;
}
.ds-card__reason-text {
    font-style: italic;
    color: var(--mud-palette-text-primary);
    line-height: 1.45;
}
.status-disputed {
    background-color: var(--status-disputed-bg) !important;
    color: var(--status-disputed-fg) !important;
    border: none !important;
}
.ds-card__intervention-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 6px;
    background: var(--status-disputed-bg);
    color: var(--status-disputed-fg);
    font-size: 0.75rem;
    font-weight: 500;
}

/* ─── Actions Bar ─── */
.md-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border-light);
    margin-bottom: 12px;
}

.md-actions__label {
    font-weight: 700;
    letter-spacing: 0;
    color: var(--mud-palette-primary);
}

/* ─── Match Details Scoreboard ─── */
.md-details {
    display: flex;
    border-radius: 10px;
    border: 1px solid var(--border-light);
    overflow: hidden;
    margin-top: 8px;
}

.md-details__meta {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6px;
    padding: 12px 14px;
    background: var(--navy-tint-4);
    border-right: 1px solid var(--border-light);
    flex-shrink: 0;
}

.md-details__meta-item {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.md-details__meta-icon {
    color: var(--mud-palette-text-secondary) !important;
    font-size: 1rem !important;
}

.md-details__scoreboard {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.md-details__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    gap: 12px;
    transition: background-color 0.15s ease;
}

.md-details__row--winner {
    background: var(--teal-tint-6);
}

.md-details__row--winner .md-details__team-name {
    font-weight: 700;
    color: var(--mud-palette-primary-darken);
}

.md-details__row--winner .md-details__sets {
    font-weight: 800;
    color: var(--mud-palette-primary-darken);
    background: var(--teal-tint-10);
}

.md-details__team-name {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1;
}

.md-details__scores {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
}

.md-details__game {
    font-size: 0.8125rem;
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
    min-width: 20px;
    text-align: center;
    padding: 2px 4px;
}

.md-details__sets {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    min-width: 24px;
    text-align: center;
    padding: 2px 6px;
    margin-left: 6px;
    border-radius: 5px;
    background: var(--navy-tint-4);
}

.md-details__separator {
    height: 1px;
    margin: 0 14px;
    background: var(--border-subtle);
}

/* ─── Form Section (shared by result edit + time/court edit) ─── */
.md-form-section {
    border-top: 1px solid var(--border-light);
    padding-top: 16px;
    margin-top: 16px;
}

.md-form-section__heading {
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--mud-palette-primary) !important;
    margin-bottom: 12px;
}

/* ─── Result Edit: Set Rows ─── */
.md-result-sets {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.md-result-set {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.md-result-set__label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.md-result-set__fields {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 8px;
    align-items: center;
}

.md-result-set__dash {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
    text-align: center;
}

/* xs (≤599.98px) — flip to single horizontal row per set: label | A | – | B.
   Spinner buttons are removed via HideSpinButtons on the component itself,
   so we don't need a `.mud-input-numeric-actions { display: none }` hack. */
@media (max-width: 599.98px) {
    .md-result-set {
        flex-direction: row;
        align-items: center;
        gap: 8px;
    }

    .md-result-set__label {
        flex: 0 0 52px;
        margin: 0;
    }

    .md-result-set__fields {
        flex: 1 1 auto;
        grid-template-columns: 1fr 12px 1fr;
        gap: 6px;
    }
}

/* On wide screens, lay all sets out in a single row with compact numeric
   fields — set scores are typically one digit, so a column-per-set is
   wasted vertical space. Below sm we keep the stacked layout so the
   inputs remain comfortable on phones (#233, #459). */
@media (min-width: 600px) {
    .md-result-sets {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 16px;
    }

    .md-result-set {
        flex: 0 0 auto;
        align-items: center;
    }

    .md-result-set__fields {
        grid-template-columns: 56px auto 56px;
        gap: 6px;
    }
}

/* ─── Retired Section ─── */
.md-retired-section {
    border-top: 1px solid var(--border-light);
    padding-top: 8px;
    margin-top: 12px;
}

/* ─── Sticky Save Bar (mobile keyboard-friendly) ─── */
/* Stays visible at the bottom of the dialog scroll area when the OS
   keyboard pushes content up. The fade prevents an abrupt visual cut
   when content scrolls underneath. */
.md-save-bar--sticky {
    position: sticky;
    bottom: 0;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--mud-palette-surface) 0%, transparent) 0%,
        var(--mud-palette-surface) 32%);
    padding: 12px 0 8px;
    margin-top: 12px;
    z-index: 2;
}

/* ─── Responsive ─── */
@media (max-width: 599.98px) {
    .md-dialog {
        min-width: unset;
        width: 100%;
    }

    .md-dialog .profile-image {
        max-width: 64px;
        max-height: 64px;
    }

    .md-hero {
        padding: 14px 8px;
    }

    .md-hero__score {
        font-size: 1.375rem;
    }

    .md-hero__center {
        padding: 0 10px;
    }

    .md-hero__name {
        font-size: 0.75rem;
    }

    .md-details {
        flex-direction: column;
    }

    .md-details__meta {
        flex-direction: row;
        border-right: none;
        border-bottom: 1px solid var(--border-light);
        padding: 8px 14px;
    }

    .md-details__meta-item {
        font-size: 0.6875rem;
    }
}

/* Legacy compat — kept for other dialogs that may still reference */
.match-dialog-content { min-width: 400px; }

/* ---- KPI Summary Cards ---- */
.kpi-completed   { border-left: 4px solid var(--mud-palette-success); }
.kpi-in-progress { border-left: 4px solid var(--mud-palette-warning); }
.kpi-upcoming    { border-left: 4px solid var(--mud-palette-info); }

.kpi-label-completed   { color: var(--status-completed-fg);   font-weight: 600; letter-spacing: 0.1em; }
.kpi-label-in-progress { color: var(--status-in-progress-fg); font-weight: 600; letter-spacing: 0.1em; }
.kpi-label-upcoming    { color: var(--status-upcoming-fg);    font-weight: 600; letter-spacing: 0.1em; }

/* compact on xs so all 3 KPI tiles sit in one row */
@media (max-width: 599px) {
    .kpi-card    { padding: 10px 8px !important; }
    .kpi-icon-sm { display: none !important; }
}

/* ---- Icon Colors ---- */
.icon-completed   { color: var(--mud-palette-success); }
.icon-in-progress { color: var(--mud-palette-warning); }
.icon-upcoming    { color: var(--mud-palette-info); }
.icon-navy        { color: var(--mud-palette-primary); }

/* ---- Smart Search ---- */
.cs-search {
    background: var(--mud-palette-surface);
    border: 1px solid var(--border-subtle);
    border-radius: 12px;
    padding: 16px 20px 12px;
    margin-bottom: 16px;
    box-shadow: var(--shadow-xs);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.cs-search:focus-within {
    border-color: var(--mud-palette-secondary);
    box-shadow: 0 0 0 3px var(--teal-tint-10), var(--shadow-xs);
}

.cs-search-field .mud-input-outlined .mud-input-outlined-border {
    border-color: transparent !important;
}

.cs-search-field .mud-input-adornment-start .mud-icon-root {
    color: var(--mud-palette-primary);
    transition: color 0.2s ease;
}

.cs-search:focus-within .cs-search-field .mud-input-adornment-start .mud-icon-root {
    color: var(--mud-palette-secondary);
}

.cs-search-hints {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
    padding-left: 4px;
}

.cs-hint-chip {
    background: var(--navy-tint-4) !important;
    color: var(--mud-palette-primary) !important;
    font-size: 0.7rem !important;
    height: 22px !important;
    letter-spacing: 0.03em;
    opacity: 0.7;
    cursor: default !important;
}

/* Category filter popover — width, height, and checkbox row hover
   (MudMenu's default popover has no width cap; long category names
   would otherwise stretch it off-screen, and the checkbox list needs
   a scroll cap for tenants with many categories) */
.cs-category-popover {
    min-width: 280px;
    max-width: 340px;
}

.cs-category-menu {
    display: flex;
    flex-direction: column;
}

.cs-category-list {
    max-height: 260px;
    overflow-y: auto;
    padding-bottom: 4px;
}

.cs-category-item {
    display: flex;
    padding: 2px 6px;
    margin: 0;
    border-radius: 6px;
    transition: background-color 0.12s ease;
}

.cs-category-item:hover {
    background: var(--navy-tint-4);
}

/* Active-filter row — sits between the search row and the hint row */
.cs-active-row {
    padding-top: 10px;
    border-top: 1px dashed var(--border-subtle);
}

.cs-active-label {
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.68rem !important;
    opacity: 0.55;
    font-weight: 500;
}

/* ---- Empty State ---- */
.empty-state-icon { font-size: 4rem; color: var(--mud-palette-primary); }

/* ---- Competition Status Border (Dashboard Paper Row) ---- */
.competition-border-completed   { border-left: 4px solid var(--mud-palette-success); }
.competition-border-in-progress { border-left: 5px solid var(--mud-palette-warning); }
.competition-border-upcoming    { border-left: 4px solid var(--mud-palette-info); }

/* ---- Competition Dashboard Image ---- */
.competition-paper-image { width: 130px; height: 130px; flex-shrink: 0; object-fit: cover; }

/* ---- Competition Dashboard Item Paper ---- */
.cdip-image     { width: 130px; min-width: 130px; height: 100%; object-fit: cover; flex-shrink: 0; }
.cdip-dim       { opacity: 0.72; filter: grayscale(15%); }
.cdip-bg-active { background: var(--status-in-progress-bg); }

/* ---- Urgent Deadline ---- */
.text-urgent { color: var(--status-in-progress-fg) !important; font-weight: 700; }
.icon-urgent { color: var(--status-in-progress-fg) !important; }

/* ---- Match Card ---- */
.match-name-cell   { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.match-scores-wrap { gap: 6px; flex-shrink: 0; }
.match-set-score   { min-width: 14px; text-align: right; color: var(--mud-palette-text-secondary); }

/* ---- Player Card ---- */
.image-container .mud-avatar { width: 100% !important; height: 100% !important; font-size: 1.75rem !important; font-weight: 600; border-radius: 0 !important; }

/* ---- Competition Details View ---- */
.cd-field { display: flex; flex-direction: column; gap: 3px; }
.cd-label { text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.6875rem; font-weight: 500; color: var(--mud-palette-text-secondary); }
.cd-value { font-weight: 500; color: var(--mud-palette-text-primary); font-size: 0.9375rem; }

/* ---- Competition Card (List View) ---- */
.comp-card-avatar     { width: 52px; height: 52px; border: 2px solid var(--mud-palette-secondary); }
.comp-card-avatar-img { width: 52px; height: 52px; object-fit: cover; }

/* Match type / surface type meta badges */
.comp-meta-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.comp-meta-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 12px;
    background: var(--navy-tint-6);
    color: var(--mud-palette-primary);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
}

/* ---- Competition Edit / Details Form ---- */

/* form max-width + centering */
.ce-form-wrap { max-width: 900px; margin: 0 auto; overflow: hidden; }

/* section cards */
.ce-section {
    background: var(--mud-palette-surface);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    padding: 20px 20px 24px;
    margin-bottom: 16px;
    overflow-wrap: break-word;
    word-break: break-word;
}

/* scope divider inside cards to 2px */
.ce-section .court-divider { height: 2px; margin-bottom: 20px; }

/* section header: icon + overline side by side */
.ce-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.section-label { color: var(--mud-palette-primary); font-weight: 700; letter-spacing: 0.10em; }

/* photo upload zone */
.ce-photo-zone {
    width: 160px;
    height: 160px;
    border: 2px dashed var(--mud-palette-secondary);
    border-radius: 12px;
    background: var(--teal-tint-4);
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ce-photo-placeholder-icon {
    font-size: 2.5rem !important;
    color: var(--mud-palette-secondary) !important;
    pointer-events: none;
}

.ce-photo-image {
    position: absolute;
    inset: 0;
    width: 100% !important;
    height: 100% !important;
    object-fit: cover;
}

/* hide broken img when no src is set */
.ce-photo-image:not([src]),
.ce-photo-image[src=""] { display: none; }

/* ---- Tenant edit page ---- */
.te-form-wrap                  { max-width: 900px; }
.te-card-full-height           { height: 100%; }
.te-image-preview              { height: 120px; position: relative; overflow: hidden; border-style: dashed; }
.te-image-preview--sm          { height: 100px; overflow: hidden; border-style: dashed; }
.te-image-fill                 { width: 100%; height: 100%; position: absolute; inset: 0; }
.te-favicon-thumb              { max-width: 48px; max-height: 48px; }
.te-placeholder-icon           { font-size: 2rem; opacity: 0.3; }
.te-color-picker               { min-width: 300px; flex: 1; max-width: 500px; }

/* checkbox styled to match outlined field height */
.ce-toggle-card {
    border: 1px solid var(--border-light);
    border-radius: 8px;
    height: 56px;
    display: flex;
    align-items: center;
    padding: 0 8px 0 4px;
    transition: border-color 0.2s;
    box-sizing: border-box;
}

.ce-toggle-card:hover { border-color: var(--mud-palette-lines-inputs); }

/* save action bar */
.ce-save-bar {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding-top: 20px;
    margin-top: 4px;
    border-top: 1px solid var(--border-light);
}

/* ---- Media Embeds ---- */
.media-embed-container {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
    border-radius: 8px;
}

.media-embed-iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: none;
    border-radius: 8px;
}

.gallery-photo-card {
    border-radius: 8px;
    overflow: hidden;
    transition: transform 0.15s ease;
}

.gallery-photo-card:hover {
    transform: scale(1.02);
}

.cursor-pointer {
    cursor: pointer;
}

/* mobile adjustments */
@media (max-width: 600px) {
    .ce-section   { padding: 14px 14px 18px; }
    .ce-form-wrap { padding-inline: 0 !important; }
    .ce-photo-zone { width: 120px; height: 120px; }
    .ce-photo-placeholder-icon { font-size: 2rem !important; }
    .ce-toggle-card { min-height: 48px; }
}

/* ---- Player Profile Overview ---- */
.pp-hero-photo {
    width: 110px;
    height: 110px;
    border-radius: 50%;
    overflow: hidden;
    border: 3px solid var(--mud-palette-secondary);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pp-hero-avatar {
    width: 110px !important;
    height: 110px !important;
    font-size: 2rem !important;
    font-weight: 700 !important;
}

.pp-stat-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 16px 12px;
    background: var(--navy-tint-3);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    text-align: center;
    gap: 4px;
}

.pp-stat-value { font-weight: 700; color: var(--mud-palette-primary); }
.pp-stat-gold  { font-weight: 700; color: var(--mud-palette-tertiary); }

/* ---- Form W/L Chips ---- */
.form-chip-win  { background: var(--form-win-bg)  !important; color: var(--form-win-fg)  !important; font-weight: 700 !important; }
.form-chip-loss { background: var(--form-loss-bg) !important; color: var(--form-loss-fg) !important; font-weight: 700 !important; }

/* ---- Rankings ---- */
.pp-ranking-row + .pp-ranking-row {
    border-top: 1px solid var(--border-subtle);
}

.pp-rank-badge {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.875rem;
    flex-shrink: 0;
    margin-right: 16px;
    background: var(--navy-tint-6);
    color: var(--mud-palette-primary);
}

.pp-rank-badge.pp-rank-1 { background: var(--rank-gold-bg);   color: var(--rank-gold-fg); }
.pp-rank-badge.pp-rank-2 { background: var(--rank-silver-bg); color: var(--rank-silver-fg); }
.pp-rank-badge.pp-rank-3 { background: var(--rank-bronze-bg); color: var(--rank-bronze-fg); }

/* ---- Match W/L/Pending Chips ---- */
.form-chip-pending { background: var(--status-upcoming-bg) !important; color: var(--status-upcoming-fg) !important; font-weight: 700 !important; }

/* ---- Head-to-Head ---- */
.h2h-comparison-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 16px;
}

.h2h-player-card,
.h2h-summary-card {
    border: 1px solid var(--border-light);
    border-radius: 14px;
    background: var(--mud-palette-surface);
    box-shadow: 0 10px 28px var(--navy-tint-6);
}

.h2h-player-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 18px 14px;
}

.h2h-summary-card {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 18px;
}

.h2h-summary-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}


.h2h-player-avatar {
    width: 100px;
    height: 100px;
    font-size: 1.75rem;
    font-weight: 700;
}
.h2h-player-photo {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    overflow: hidden;
    border: 3px solid var(--mud-palette-secondary);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--teal-tint-4);
}

.h2h-player-name {
    min-height: 2.6em;
    display: flex;
    align-items: center;
    justify-content: center;
}

.h2h-win-pill {
    min-width: 86px;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--navy-tint-4);
    border: 1px solid var(--border-subtle);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.h2h-stat-row  { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 6px; }
.h2h-p1-value  { font-weight: 700; color: var(--mud-palette-primary); font-size: 1rem; min-width: 80px; }
.h2h-p2-value  { font-weight: 700; color: var(--mud-palette-primary); font-size: 1rem; min-width: 80px; text-align: right; }
.h2h-stat-label { flex: 1; text-align: center; text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.6875rem; color: var(--mud-palette-text-secondary); font-weight: 600; }

/* Player name in hero blocks */
.pp-hero-name { font-weight: 700; line-height: 1.2; }

/* "This Year" / "Career" sub-section labels */
.pp-stat-sub-label { color: var(--mud-palette-text-secondary); font-weight: 600; display: block; margin-bottom: 8px; }

/* Rankings list: series name cell */
.pp-ranking-series { flex: 1; min-width: 0; font-weight: 500; }

/* Empty-state icon (rankings / smaller contexts) */
.pp-empty-state-icon { font-size: 3rem; }

/* ---- Shared Layout Utilities ---- */
.empty-state-dim { opacity: 0.6; }
.min-w-0         { min-width: 0; }

/* Toggle / match-type button bar (shared across tabs) */
.toggle-row { gap: 8px; flex-wrap: wrap; }

/* Icon + label inline pair */
.meta-item { gap: 4px; }

/* ---- Player Profile Layout ---- */
.pp-hero-block   { gap: 20px; }            /* hero: photo beside content */
.pp-hero-content { min-width: 0; }         /* prevents flex text overflow  */
.pp-meta-row     { gap: 10px; flex-wrap: wrap; } /* hometown · dob · style row */
.pp-form-row     { gap: 6px;  flex-wrap: wrap; } /* W/L chip row              */
.pp-ranking-pts  { flex-shrink: 0; }       /* ranking points column        */

/* ---- Head-to-Head Layout ---- */
.h2h-player-col { gap: 8px; }             /* player column (flex-column)  */
.h2h-center-col { gap: 12px; min-height: 130px; }
.h2h-wins-row   { display: flex; justify-content: center; align-items: stretch; gap: 14px; flex-wrap: wrap; }
.h2h-wins-divider { color: var(--mud-palette-text-secondary); align-self: center; font-weight: 700; }

/* ---- Match Card Score Column ---- */
.match-score-cell { min-width: 18px; text-align: right; }

/* ---- Retired Match Indicators ---- */
.match-retired-badge {
    background-color: var(--form-loss-bg) !important;
    color: var(--form-loss-fg) !important;
    font-weight: 600;
    font-size: 0.65rem;
    height: 20px !important;
    min-height: 20px !important;
    padding: 0 6px;
    margin-left: 4px;
}

.match-retired-section {
    border-top: 1px solid var(--border-light);
    padding-top: 12px;
    margin-top: 12px;
}

/* ---- Match Dialog ---- */
/* Score header row: icon + MudText + spacer + action buttons */
.match-dialog-actions { gap: 8px; align-items: center; }
/* Narrow score number column inside MatchDetails */
.match-score-col { width: 10px; }
/* Sub-form section separator inside MatchDialog (result edit / time edit) */
.match-form-section { border-top: 1px solid var(--border-light); padding-top: 16px; margin-top: 16px; }

/* ---- Inline label + field row (used in dialogs) ---- */
.field-row { gap: 12px; align-items: center; }

/* ---- Complete Competition Dialog ---- */
.round-points-input { width: 100px; }

.cc-dialog { min-width: 480px; }

.cc-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.cc-title-icon { color: var(--tc-primary); }
.cc-title-text { color: var(--tc-primary); font-weight: 600; }

.cc-step-dots {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}

.cc-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #CBD5E1;
    transition: background 0.2s ease;
}

.cc-dot-active {
    background: var(--ace-teal, var(--mud-palette-secondary));
}

.cc-winner-card {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px 20px;
    border-radius: 10px;
    background: linear-gradient(135deg, rgba(212, 160, 23, 0.08), rgba(212, 160, 23, 0.16));
    border: 1px solid var(--rank-gold-fg);
}

.cc-winner-trophy { color: var(--mud-palette-tertiary); }
.cc-winner-label { color: var(--mud-palette-text-secondary); letter-spacing: 0.08em; }
.cc-winner-name { color: var(--tc-primary); font-weight: 700; }

.cc-preview-table {
    border-radius: 8px;
    overflow: hidden;
}

.cc-preview-table th {
    background: var(--tc-primary) !important;
    color: #fff !important;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.cc-rank-up { color: var(--status-completed-fg); }
.cc-rank-down { color: var(--status-disputed-fg); }
.cc-rank-same { color: var(--mud-palette-text-disabled); }

.cc-penalty-input { width: 120px; }

/* Sign-aware delta pill: positive (green) for awarded points, negative (red) */
/* for walkover deductions, neutral (grey) for unchanged. The signed icon + signed */
/* number + signed color gives three independent cues, so the meaning survives */
/* color-blindness and small renderings. */
.cc-delta-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 10px 2px 6px;
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.8125rem;
    line-height: 1.4;
    letter-spacing: 0.01em;
}

.cc-delta-pill-icon {
    font-size: 1rem !important;
    width: 1rem !important;
    height: 1rem !important;
}

.cc-delta-pill-value { font-variant-numeric: tabular-nums; }

.cc-delta-pill-positive {
    background: #15803D;
    color: #ffffff;
}

.cc-delta-pill-negative {
    background: #DC2626;
    color: #ffffff;
}

.cc-delta-pill-neutral {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    border: 1px solid var(--border-light);
}

/* Winner row/card accent: thin gold left border ties the projected #1 back to */
/* the gold winner card above. Subtle warm tint reinforces the link without */
/* overwhelming the table's striped rhythm. */
.cc-preview-row-winner > td:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-tertiary, #D4A017);
}

.cc-preview-row-winner > td {
    background: var(--rank-gold-bg) !important;
}

.cc-preview-card-winner {
    border-left: 3px solid var(--mud-palette-tertiary, #D4A017) !important;
    background: var(--rank-gold-bg);
}

.cc-walkover-alert .mud-chip { font-weight: 600; }

.cc-loading-preview {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 48px 0;
}

.cc-completed-banner {
    border-radius: 10px;
}

.cc-banner-trophy { color: var(--mud-palette-tertiary); font-size: 1.8rem; }
.cc-banner-title { color: var(--status-completed-fg); font-weight: 600; }

/* Mobile (xs <600px): MudBlazor primitives don't expose viewport-based row/column toggling, */
/* so these media-query rules adapt the dialog's inline layouts to narrow screens. */
@media (max-width: 600px) {
    .cc-dialog { min-width: unset; }

    /* Field rows: stack label-on-top with full-width input so long labels don't crowd the input */
    .cc-dialog .field-row { flex-direction: column; align-items: stretch; gap: 4px; }
    .cc-dialog .field-row .round-points-input { width: 100%; }

    /* Walkover penalty: switch and numeric stack vertically; numeric grows to full width */
    .cc-dialog .cc-penalty-row .cc-penalty-input { width: 100%; }

    /* Winner card: column layout so long doubles team names don't crowd the trophy */
    .cc-dialog .cc-winner-card { flex-direction: column; align-items: center; text-align: center; gap: 8px; }

    /* Stack dialog actions full-width with primary on top (column-reverse because primary is last in DOM) */
    .cc-dialog ~ .mud-dialog-actions,
    .mud-dialog .cc-dialog + .mud-dialog-actions,
    .mud-dialog:has(.cc-dialog) .mud-dialog-actions {
        flex-direction: column-reverse;
        align-items: stretch;
        gap: 8px;
    }
    .mud-dialog:has(.cc-dialog) .mud-dialog-actions .mud-button-root { width: 100%; margin: 0; }
}

/* ---- Completed Competition Summary ---- */
.ccs-wrap {
    max-width: 900px;
    margin: 0 auto;
}

.ccs-champion {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 24px 16px 16px;
    text-align: center;
}

.ccs-trophy-icon {
    font-size: 3rem !important;
    color: var(--rank-gold-fg);
    margin-bottom: 4px;
}

.ccs-champion-label {
    letter-spacing: 0.15em;
    color: var(--rank-gold-fg);
    font-weight: 700;
}

.ccs-champion-players {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.ccs-champion-name-link {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--mud-palette-text-primary) !important;
    cursor: pointer;
}

.ccs-champion-name-link:hover {
    text-decoration: underline;
}

.ccs-points-chip {
    margin-top: 4px;
}

.ccs-podium {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: 32px;
    padding: 16px;
}

.ccs-podium-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    min-width: 100px;
    max-width: 180px;
}

.ccs-podium-first {
    order: 2;
    padding-top: 0;
}

.ccs-podium-second {
    order: 1;
    padding-top: 32px;
}

.ccs-podium-third {
    order: 3;
    padding-top: 32px;
}

.ccs-third-players {
    display: flex;
    gap: 8px;
    justify-content: center;
}

.ccs-third-player {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.ccs-podium-avatar {
    width: 48px;
    height: 48px;
    font-weight: 700;
    font-size: 1.1rem;
    margin-bottom: 8px;
}

.ccs-avatar-gold {
    background-color: var(--rank-gold-fg) !important;
    color: white !important;
}

.ccs-avatar-silver {
    background-color: var(--rank-silver-fg) !important;
    color: white !important;
}

.ccs-avatar-bronze {
    background-color: var(--rank-bronze-fg) !important;
    color: white !important;
}

.ccs-podium-photos {
    display: flex;
    gap: 6px;
    justify-content: center;
    margin-bottom: 6px;
}

.ccs-podium-name {
    word-break: break-word;
    line-height: 1.3;
    cursor: pointer;
    color: var(--mud-palette-text-primary) !important;
}

.ccs-podium-name:hover {
    text-decoration: underline;
}

.ccs-podium-points {
    color: var(--mud-palette-success);
    font-weight: 600;
    margin-top: 2px;
}

.ccs-final-section {
    margin-top: 8px;
}

.ccs-final-matchup {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    flex-wrap: wrap;
}

.ccs-final-team {
    flex: 1;
    text-align: center;
    min-width: 120px;
    padding: 8px;
}

.ccs-final-winner {
    font-weight: 700;
}

.ccs-final-score {
    padding: 4px 16px;
}

.ccs-stats-section {
    margin-top: 16px;
}

.ccs-rankings-link {
    display: flex;
    justify-content: center;
    margin-top: 16px;
}

@media (max-width: 600px) {
    .ccs-podium {
        gap: 12px;
    }

    .ccs-podium-slot {
        min-width: 70px;
    }

    .ccs-podium-second {
        padding-top: 24px;
    }

    .ccs-podium-third {
        padding-top: 24px;
    }

    .ccs-podium-avatar {
        width: 40px;
        height: 40px;
        font-size: 0.95rem;
    }

    .ccs-third-players {
        gap: 10px;
    }

    .ccs-final-matchup {
        flex-direction: column;
        gap: 8px;
    }
}

/* ---- Mobile Table Scroll & Sticky Columns ---- */
.ce-table-scroll-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: 4px;
}

.ce-striped-table {
    border: 1px solid var(--border-light);
    border-radius: 10px;
    overflow: hidden;
    background: var(--mud-palette-surface);
}

.ce-striped-table .mud-table-toolbar {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-light);
    background: var(--navy-tint-2);
}

.ce-striped-table .mud-table-head .mud-table-cell {
    background: var(--navy-tint-4);
    color: var(--mud-palette-text-primary);
    font-weight: 700;
    border-bottom: 1px solid var(--border-light);
}

.ce-striped-table .mud-table-cell {
    border-bottom: 1px solid var(--border-subtle);
}

.ce-striped-table .mud-table-body .mud-table-row:nth-of-type(odd) .mud-table-cell {
    background: var(--navy-tint-4);
}

.ce-striped-table .mud-table-body .mud-table-row:nth-of-type(even) .mud-table-cell {
    background: var(--mud-palette-surface);
}

.ce-striped-table .mud-table-body .mud-table-row:last-child .mud-table-cell {
    border-bottom: none;
}

.ce-striped-table .mud-table-footer,
.ce-striped-table .mud-table-pagination {
    border-top: 1px solid var(--border-light);
    background: var(--navy-tint-2);
}

/* Scroll hint shadow on right edge */
.ce-league-scroll-wrap {
    position: relative;
}

.ce-league-scroll-wrap::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 24px;
    background: linear-gradient(to left, var(--mud-palette-surface), transparent);
    pointer-events: none;
    opacity: 1;
    transition: opacity 0.2s;
    z-index: 2;
}

/* Sticky first column (Name / Player) */
.ce-sticky-col {
    position: sticky;
    left: 0;
    background: inherit;
    z-index: 1;
}

th.ce-sticky-col { background: var(--mud-palette-surface); }
.ce-striped-table .mud-table-head th.ce-sticky-col {
    background: var(--navy-tint-4);
}

.ce-striped-table .mud-table-body td.ce-sticky-col {
    background: inherit;
    box-shadow: 1px 0 0 var(--border-subtle);
}

/* League table column widths */
.ce-league-th-pos { width: 40px; text-align: center; }
.ce-league-th-player { min-width: 120px; }
.ce-league-th-stat { width: 50px; text-align: center; white-space: nowrap; }

/* Compact table cells on mobile */
@media (max-width: 599px) {
    .ce-league-table .mud-table-cell,
    .ce-league-table .mud-table-head .mud-table-cell {
        padding: 8px 6px;
        font-size: 0.8125rem;
    }

    .ce-group-table .mud-table-cell,
    .ce-group-table .mud-table-head .mud-table-cell {
        padding: 8px 10px;
        font-size: 0.875rem;
    }
}

/* ---- Draw Action Bar ---- */
.draw-actions-row { gap: 12px; align-items: center; flex-wrap: wrap; }
.draw-group-size  { width: 100px; }
.draw-size-select { width: 110px; }
.draw-actions-row-knockout { align-items: stretch; }
.draw-knockout-setup {
    display: flex;
    flex-direction: column;
    gap: 14px;
    width: 100%;
    padding: 16px;
    border: 1px solid var(--border-light);
    border-radius: 10px;
    background: var(--mud-palette-surface);
}
.draw-knockout-copy { max-width: 52rem; }
.draw-knockout-help,
.draw-knockout-note { color: var(--mud-palette-text-secondary); }
/* ---- Knockout Draw Bracket ---- */
/* Scroll wrapper keeps the horizontal scrollbar OUTSIDE the bracket's
   flex layout so it cannot steal height from the round columns.       */
.draw-bracket-scroll {
    overflow-x: auto;
    border: 1px solid var(--border-light);
    border-radius: 10px;
    background: var(--navy-tint-2);
}

.draw-bracket {
    display: flex;
    flex-direction: row;
    padding: 20px;
    align-items: stretch;   /* all rounds share the same height */
    width: max-content;     /* prevent bracket from shrinking to viewport */
}

/* Each round column — 16px padding each side creates the 32px inter-round
   gap that connector pseudo-elements occupy */
.draw-round {
    display: flex;
    flex-direction: column;
    min-width: 240px;
    padding: 0 16px;
}
.draw-round:first-child { padding-left: 0; }
.draw-round:last-child  { padding-right: 0; }

.draw-round-header {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: var(--mud-palette-primary);
    text-align: center;
    padding: 6px 12px;
    background: var(--navy-tint-6);
    border-radius: 8px;
    margin-bottom: 12px;
}

.draw-round-matches {
    display: flex;
    flex-direction: column;
    flex: 1;
}

/* Pair of two matches — the structural bracket unit.
   flex:1 distributes height equally so item centers land at
   exactly 25% and 75% of the pair — matching the vertical connector. */
.draw-match-pair {
    display: flex;
    flex-direction: column;
    flex: 1;
    position: relative;
}

/* Individual match slot — flex:1 gives both slots equal height */
.draw-match-item {
    flex: 1;
    min-height: 80px;
    display: flex;
    align-items: center;
    padding: 4px 0;
    position: relative;
}
.draw-match-item .mc,
.draw-mobile-match-item .mc,
.sched-match-cell .mc { width: 100%; }

/* ── Incoming horizontal connector (gap-center → left edge of card) ── */
.draw-match-item::before {
    content: '';
    position: absolute;
    right: 100%;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 2px;
    background: var(--draw-connector);
    pointer-events: none;
}

/* ── Outgoing connector — default: simple horizontal (single-item pairs) ── */
.draw-match-item::after {
    content: '';
    position: absolute;
    left: 100%;
    top: 50%;
    transform: translateY(-50%);
    width: 17px;
    height: 2px;
    background: var(--draw-connector);
    pointer-events: none;
}

/* ── Outgoing bracket connector for two-item pairs ──
   Uses borders so the horizontal→vertical corner is gap-free.
   First item draws the top-right ┐ half, second draws bottom-right ┘ half.
   The two halves overlap by 1px at the pair midpoint for continuity. */
.draw-match-pair .draw-match-item:first-child:not(:last-child)::after {
    top: 50%;
    bottom: -1px;
    height: auto;
    transform: none;
    background: none;
    border-top: 2px solid var(--draw-connector);
    border-right: 2px solid var(--draw-connector);
}
.draw-match-pair .draw-match-item:last-child:not(:first-child)::after {
    top: -1px;
    bottom: 50%;
    height: auto;
    transform: none;
    background: none;
    border-bottom: 2px solid var(--draw-connector);
    border-right: 2px solid var(--draw-connector);
}

/* Vertical connector no longer needed — bracket shape is drawn by items */
.draw-match-pair::before { display: none; }

/* First round has no incoming connectors */
.draw-round:first-child .draw-match-item::before { display: none; }

/* Last round (final) has no outgoing connectors */
.draw-round:last-child .draw-match-pair .draw-match-item::after { display: none; }

/* ── Third place match (inside finals column, below centered finals) ── */
.draw-round--has-third-place {
    position: relative;
    padding-bottom: 140px;          /* reserve space so it doesn't overflow */
}
.draw-third-place {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0 16px;
}
.draw-round--has-third-place:last-child .draw-third-place {
    padding-right: 0;
}
.draw-third-place-match {
    width: 100%;
}
.draw-third-place-match .mc {
    width: 100%;
}

/* ── Feeder stages (Qualifying / Repechage) ──
   These columns feed into the main draw but are NOT part of the binary
   connector tree, so we suppress both the incoming and outgoing
   pseudo-element connectors on their match items.
   Similarly, the first Main-stage column must not draw connectors
   reaching back toward the Repechage column. */
.draw-round--feeder .draw-match-item::before,
.draw-round--feeder .draw-match-item::after { display: none; }

.draw-round--main-start .draw-match-item::before { display: none; }

/* Feeder column header: teal tint to signal the qualification phase,
   distinct from the navy-tint-6 used for main-draw headers.
   --teal-tint-10 echoes AceTeal (the secondary color) and reads as
   the qualification context without overwhelming the bracket. */
.draw-round--feeder .draw-round-header {
    background: var(--teal-tint-10);
    color: var(--mud-palette-secondary);
}

/* A hairline left border on the first Main column signals the phase
   boundary between qualification and the main draw. Uses the existing
   teal-tint-30 token to stay cohesive with the rest of the palette. */
.draw-round--main-start {
    border-left: 2px solid var(--teal-tint-30);
    margin-left: 8px;
    padding-left: 24px;
}

/* ── Manual knockout draw bracket ── */
.draw-bracket--manual {
    min-height: 400px;
}

.draw-bracket--manual .draw-round {
    min-width: 280px;
}

/* ---- Manual Round Robin Draw ---- */

.rr-group-card {
    background: var(--mud-palette-surface);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    overflow: hidden;
}

.rr-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background: var(--navy-tint-4);
    border-bottom: 1px solid var(--border-light);
}

.rr-group-slots {
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-height: 60px;
}

.rr-player-slot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 10px;
    border: 1px dashed var(--border-light);
    border-radius: 8px;
    min-height: 44px;
    transition: border-color 0.15s, background 0.15s;
}

.rr-player-slot--filled {
    border-style: solid;
    background: var(--teal-tint-4);
    border-color: var(--teal-tint-20);
}

.rr-player-info {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}

.rr-player-info .mud-typography {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rr-points-chip {
    flex-shrink: 0;
}

.rr-slot-autocomplete {
    flex: 1;
}

.rr-empty-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 20px 12px;
}

/* ---- Knockout Draw Generation ---- */

.ko-generate-layout {
    display: flex;
    gap: 24px;
    align-items: flex-start;
}

.ko-generate-config {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ko-draw-size-field {
    width: 140px;
}

.ko-generate-actions {
    display: flex;
    gap: 10px;
    flex: 1;
    align-items: flex-start;
    padding-top: 4px;
}

.ko-actions-separator {
    border-top: 1px solid var(--border-light);
}

@media (max-width: 599px) {
    .ko-generate-layout {
        flex-direction: column;
        gap: 14px;
    }

    .ko-draw-size-field {
        width: 100%;
    }

    .ko-generate-actions {
        flex-direction: column;
        width: 100%;
        padding-top: 0;
    }
}

/* ---- Round Robin Group Cards (generated draw) ---- */

.rr-group-progress {
    border-radius: 0;
}

.rr-standing-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--navy-tint-6);
}

.rr-standing-row:last-child {
    border-bottom: none;
}

.rr-standing-relegation {
    background: var(--relegation-row-bg);
}

.rr-standing-relegation .rr-standing-pos {
    background: var(--relegation-marker-bg);
    color: var(--mud-palette-error);
}

.rr-standing-promotion {
    background: var(--promotion-row-bg);
}

.rr-standing-promotion .rr-standing-pos {
    background: var(--promotion-marker-bg);
    color: var(--mud-palette-success);
}

.rr-standing-pos {
    flex: 0 0 24px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--border-subtle);
    color: var(--court-navy);
    font-weight: 600;
    font-size: 0.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.rr-standing-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.875rem;
}

.rr-standing-stats {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
}

.rr-stat-chip {
    font-size: 0.7rem !important;
    height: 22px !important;
    padding: 0 6px !important;
}

/* ── Group standings table ──────────────────────────────────────────
   Editorial-sports leaderboard feel: condensed header in tracked-out
   uppercase, tabular numerics, subtle row dividers. The signed-in
   player's row gets a teal left rail + bold weight; their group card
   gets a teal border + gold corner tick so it reads as "yours" without
   overwhelming the rest of the table.
*/
.rr-standings-table {
    padding: 4px 4px 6px;
    display: flex;
    flex-direction: column;
}

.rr-standings-head,
.rr-standings-row {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) repeat(5, 32px);
    align-items: center;
    gap: 4px;
    padding: 7px 8px;
    border-left: 3px solid transparent;
}

.rr-standings-head:has(.rr-col-points),
.rr-standings-row:has(.rr-col-points) {
    grid-template-columns: 28px minmax(0, 1fr) repeat(6, 32px);
}

.rr-standings-head {
    font-size: 0.7rem;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    border-bottom: 1px solid var(--border-light);
    letter-spacing: 0.08em;
    font-weight: 600;
}

.rr-standings-row {
    border-bottom: 1px solid var(--navy-tint-6);
    font-size: 0.875rem;
    transition: background-color 120ms ease;
}

.rr-standings-row:last-child {
    border-bottom: none;
}

.rr-standings-row.rr-standing-promotion {
    background: var(--promotion-row-bg);
    border-left-color: var(--mud-palette-success);
}

.rr-standings-row.rr-standing-relegation {
    background: var(--relegation-row-bg);
    border-left-color: var(--mud-palette-error);
}

.rr-standings-row.rr-standing-mine {
    background: var(--ace-teal-tint, rgba(13, 148, 136, 0.08));
    border-left-color: var(--mud-palette-secondary);
}

.rr-standings-row.rr-standing-mine .rr-col-name,
.rr-standings-row.rr-standing-mine .rr-col-pos,
.rr-standings-row.rr-standing-mine .rr-col-num {
    font-weight: 700;
}

.rr-col-pos {
    text-align: center;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.rr-col-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 6px;
}

.rr-col-name .team-name-short {
    display: none;
}

@media (max-width: 599.98px) {
    .rr-col-name .team-name-full {
        display: none;
    }

    .rr-col-name .team-name-short {
        display: inline;
    }

    /* On phones the standings grid was giving 32 px to every numeric column
       and 8 px of horizontal row padding, which squeezed the name column to
       ~90 px on the 6-numeric-column variant (#1110). Tightening the fixed
       tracks lets the 1fr name column absorb the freed space without any
       horizontal scroll. */
    .rr-standings-head,
    .rr-standings-row {
        grid-template-columns: 22px minmax(0, 1fr) repeat(5, 26px);
        gap: 2px;
        padding-left: 6px;
        padding-right: 6px;
    }

    .rr-standings-head:has(.rr-col-points),
    .rr-standings-row:has(.rr-col-points) {
        grid-template-columns: 22px minmax(0, 1fr) repeat(6, 26px);
    }

    .rr-standings-head {
        font-size: 0.65rem;
    }

    .rr-standings-row {
        font-size: 0.8125rem;
    }
}

.rr-col-num {
    text-align: center;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

.rr-col-wins {
    color: var(--mud-palette-success);
    font-weight: 600;
}

.rr-col-losses {
    color: var(--mud-palette-error);
    font-weight: 600;
}

.rr-col-points {
    color: var(--mud-palette-primary);
    font-weight: 700;
}

.rr-group-card-mine {
    border-color: var(--mud-palette-secondary);
    position: relative;
}

.rr-group-card-mine::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 22px 22px 0;
    border-color: transparent var(--mud-palette-tertiary) transparent transparent;
    pointer-events: none;
}

.rr-group-footer {
    padding: 8px 12px;
    border-top: 1px solid var(--border-light);
    background: var(--navy-tint-2);
}

/* ---- Overall Standings (phased league sub-tab) ----
   The standings render via MudTable (with HorizontalScrollbar="true"
   handling overflow on narrow screens). These rules only style the
   small visual primitives MudTable doesn't cover: numeric column
   alignment/coloring, the rank-position podium badge, team-name
   wrapping, the "joined at phase N" pill, and the "my team" row tint.
*/
.ovs-num {
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.ovs-num-wins   { color: var(--mud-palette-success); font-weight: 600; }
.ovs-num-losses { color: var(--mud-palette-error);   font-weight: 600; }
.ovs-num-points { color: var(--mud-palette-primary); font-weight: 700; }

.ovs-rank-badge {
    display: inline-block;
    min-width: 22px;
    padding: 1px 4px;
    border-radius: 4px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.ovs-rank-badge.ovs-rank-gold {
    background: var(--rank-gold-bg);
    color: var(--rank-gold-fg);
}

.ovs-rank-badge.ovs-rank-silver {
    background: var(--rank-silver-bg);
    color: var(--rank-silver-fg);
}

.ovs-rank-badge.ovs-rank-bronze {
    background: var(--rank-bronze-bg);
    color: var(--rank-bronze-fg);
}

/* Long team names wrap to a second line (readability beats single-
   line uniformity); the team column already has a 140px min-width
   set inline on its MudTh. */
.ovs-team-name {
    min-width: 0;
    overflow-wrap: anywhere;
    line-height: 1.25;
}

.ovs-joined-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 6px;
    background: var(--navy-tint-6);
    color: var(--mud-palette-text-secondary);
    font-size: 0.65rem;
    font-weight: 600;
    border-radius: 999px;
    letter-spacing: 0.04em;
    flex-shrink: 0;
}

/* "My team" row tint — applied via RowClassFunc on the MudTable. */
.ovs-row-mine td {
    background: var(--ace-teal-tint, rgba(13, 148, 136, 0.08));
    font-weight: 600;
}

/* Inset shadow plays the role of a 3px left border without
   shifting the cell content, keeping column alignment intact. */
.ovs-row-mine td:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-secondary);
}

/* ---- Manual Knockout Draw ---- */

.mkd-slot-card {
    width: 100%;
    border: 1px solid var(--border-light);
    border-radius: 8px;
    background: var(--mud-palette-surface);
    padding: 8px 10px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.mkd-slot-card--empty {
    opacity: 0.5;
    background: var(--navy-tint-3);
}

.mkd-slot-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 0;
}

.mkd-empty-row {
    padding: 10px 8px;
    display: flex;
    align-items: center;
}

/* ---- Competition Teams Tab ---- */

/* Rank badge — reuses rank-gold/silver/bronze design tokens */
.ct-rank-badge {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.8125rem;
    background: var(--navy-tint-6);
    color: var(--mud-palette-primary);
    flex-shrink: 0;
}
.ct-rank-badge.ct-rank-1 { background: var(--rank-gold-bg);   color: var(--rank-gold-fg); }
.ct-rank-badge.ct-rank-2 { background: var(--rank-silver-bg); color: var(--rank-silver-fg); }
.ct-rank-badge.ct-rank-3 { background: var(--rank-bronze-bg); color: var(--rank-bronze-fg); }

/* Column width constraints (applied to <th> so columns are consistent) */
.ct-th-rank    { width: 60px;  }
.ct-th-pts     { width: 90px;  }
.ct-th-actions { width: 60px;  }

/* Player name cell layout */
.ct-player-cell { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ct-player-cell > .mud-image,
.ct-player-cell > .mud-avatar { flex-shrink: 0; }
.ct-player-name {
    font-weight: 500;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Points value */
.ct-points-cell { font-weight: 700; color: var(--mud-palette-primary); }

/* Player count badge in section header */
.ct-player-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    border-radius: 11px;
    background: var(--mud-palette-primary);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    padding: 0 5px;
    margin-left: 6px;
}

/* Empty state container (teams list + player picker dialogs) */
.ct-empty-state {
    padding: 40px 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

@media (max-width: 599px) {
    .ct-empty-state-cta { width: 100%; }
}

/* ---- Player Picker Dialogs (TeamsDialog / DoublePartnersDialog) ---- */

/* Minimum width for name columns in player selection tables */
.td-min-name { min-width: 140px; }

/* Selected player row highlight */
.player-row-selected { background: var(--border-light) !important; }
.player-row-selected .mud-table-cell { color: var(--mud-palette-primary) !important; font-weight: 600 !important; }

/* ================================================================
   CompetitionDashboardItemPaper (desktop) – layout helpers
   ================================================================ */

/* Content column that sits next to the image */
.cdip-content   { padding: 12px; display: flex; flex-direction: column; flex-grow: 1; gap: 8px; min-width: 0; }
/* Name + status badge row */
.cdip-title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
/* MatchType / SurfaceType / Category chips */
.cdip-chips     { display: flex; gap: 6px; flex-wrap: wrap; }
/* Club / date / prize / deadline row */
.cdip-meta      { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 20px; }
/* Single metadata item: icon + text */
.cdip-meta-item { display: flex; align-items: center; gap: 4px; }
/* Sign-in / unsign action row */
.cdip-actions   { display: flex; gap: 8px; }

/* ================================================================
   CompetitionDashboardItemCard (mobile) – layout helpers
   ================================================================ */
.cdic-chips   { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.cdic-actions { display: flex; gap: 8px; }

/* ================================================================
   Administration – Shared
   ================================================================ */

/* Photo overlay wrapper: contains PlayerImage + camera button */
.adm-photo-wrap {
    position: relative;
    width: fit-content;
    margin: 0 auto 20px;
}

/* Absolutely-positioned camera button in bottom-right of photo */
.adm-photo-btn {
    position: absolute !important;
    bottom: 2px;
    right: 2px;
}

/* Circular avatar used in ClubCard and SeriesItem */
.adm-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    border: 2px solid var(--border-light);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--navy-tint-6);
    color: var(--mud-palette-primary);
    font-size: 1.125rem;
    font-weight: 700;
    flex-shrink: 0;
}

/* ================================================================
   Administration – ClubCard
   ================================================================ */
.adm-club-card {
    border-radius: 12px !important;
    border: 1px solid var(--border-light) !important;
    transition: box-shadow 0.18s ease, transform 0.18s ease;
}

.adm-club-card:hover {
    box-shadow: 0 4px 18px rgba(26, 58, 92, 0.14) !important;
    transform: translateY(-2px);
}

/* ================================================================
   Administration – SeriesItem
   ================================================================ */
.series-item-card {
    border: 1px solid var(--border-light) !important;
    border-radius: 12px !important;
    transition: box-shadow 0.18s ease;
    margin-bottom: 12px;
}

.series-item-card:hover {
    box-shadow: 0 4px 16px rgba(26, 58, 92, 0.12) !important;
}

.series-meta-row {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--text-muted);
    font-size: 0.8125rem;
    margin-top: 2px;
}

/* ================================================================
   My Matches – Card Layout
   ================================================================ */
.mm-card {
    padding: 16px;
    border-radius: 12px !important;
    border: 1px solid var(--border-light) !important;
}

.mm-competition-name {
    color: var(--mud-palette-text-secondary);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1.4;
}
.mm-competition-link {
    color: var(--mud-palette-text-secondary) !important;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1.4;
    text-decoration: none !important;
    cursor: pointer;
    transition: color 0.15s ease;
}
.mm-competition-link:hover {
    color: var(--mud-palette-primary) !important;
    text-decoration: underline !important;
}

.mm-matchup {
    text-align: center;
}

.mm-team-name {
    font-weight: 600;
    line-height: 1.45;
    overflow-wrap: anywhere;
    word-break: break-word;
    max-width: 100%;
}

.mm-vs {
    color: var(--mud-palette-text-secondary);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.mm-result-inline {
    font-weight: 700;
    color: var(--mud-palette-primary);
    letter-spacing: 0.02em;
    text-align: center;
}

.mm-meta-icon {
    color: var(--mud-palette-text-secondary);
    opacity: 0.7;
}

.mm-meta-text {
    color: var(--mud-palette-text-secondary);
    line-height: 1.25;
}

.mm-search {
    max-width: 260px;
}

/* ---- My Matches – Dashboard Inline Section ---- */
.mm-inline-section {
    border: 1px solid var(--border-light);
    border-radius: 10px;
    padding: 12px 16px;
}

.mm-inline-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 4px;
    margin: 0 -4px;
    border-top: 1px solid var(--border-light);
    border-radius: 6px;
    flex-wrap: wrap;
    transition: background-color 0.15s ease;
}
.mm-inline-row:hover {
    background-color: var(--teal-tint-4);
}
.mm-inline-competition-link {
    color: var(--mud-palette-text-secondary) !important;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-decoration: none !important;
    flex-shrink: 0;
    transition: color 0.15s ease;
}
.mm-inline-competition-link:hover {
    color: var(--mud-palette-primary) !important;
    text-decoration: underline !important;
}

.mm-inline-date {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
}

.mm-inline-teams {
    font-weight: 600;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mm-inline-vs {
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
    margin: 0 4px;
}

.mm-inline-club {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
}

.mm-inline-court {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
}

@media (max-width: 599px) {
    .mm-inline-teams {
        flex-basis: 100%;
        order: -1;
    }
}

/* ================================================================
   Rank List Page — #793 grid layout with stat columns
   ================================================================ */

/* The default .ce-form-wrap is capped at 900px (suited to edit forms),
   but the rank-list table needs room for ~10 columns. Widen the wrap
   only on this page via the rl-page class added in RankList.razor. */
.ce-form-wrap.rl-page {
    max-width: 1240px;
    overflow: visible;
}

/* The grid container uses display:grid on each row so rows align as a
   table without an outer <table> element. Each row's columns map to the
   reference rang-lista layout: rank • player • points • tournaments •
   titles • finals • 3rd places • matches • W/L • win rate. */
.rl-grid {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.rl-row {
    display: grid;
    grid-template-columns:
        56px            /* rank */
        minmax(220px, 2.4fr) /* player */
        90px            /* points */
        70px            /* tournaments */
        70px            /* titles */
        70px            /* finals */
        80px            /* 3rd places */
        70px            /* matches */
        90px            /* W/L */
        110px;          /* win rate */
    align-items: center;
    column-gap: 8px;
    padding: 10px 12px;
    border-radius: 8px;
    transition: background 0.15s ease;
}

.rl-row + .rl-row {
    border-top: 1px solid var(--border-subtle);
}

.rl-row:hover {
    background: var(--navy-tint-3);
}

/* Editing row override — collapse the stat cells, span the row. */
.rl-row-editing {
    background: var(--teal-tint-4) !important;
    border-radius: 8px;
}
.rl-row-edit {
    grid-column: 2 / -1;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

/* Header row — column labels above the leaderboard. */
.rl-row-header {
    padding-top: 6px;
    padding-bottom: 6px;
    border: none !important;
    background: transparent !important;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    cursor: default;
}
.rl-row-header:hover { background: transparent !important; }
.rl-row-header .text-right { text-align: right; }
.rl-row-header .text-center { text-align: center; }

/* Top-3 tinted backgrounds (existing tokens) — applied to the row. */
.rl-row.rl-rank-1 { background: var(--rank-gold-bg); }
.rl-row.rl-rank-2 { background: var(--rank-silver-bg); }
.rl-row.rl-rank-3 { background: var(--rank-bronze-bg); }

/* Rank badge — circular, matches pp-rank-badge sizing */
.rl-rank-badge {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.875rem;
    background: var(--navy-tint-6);
    color: var(--mud-palette-primary);
}

.rl-rank-badge.rl-rank-1 { background: var(--rank-gold-bg);   color: var(--rank-gold-fg); }
.rl-rank-badge.rl-rank-2 { background: var(--rank-silver-bg); color: var(--rank-silver-fg); }
.rl-rank-badge.rl-rank-3 { background: var(--rank-bronze-bg); color: var(--rank-bronze-fg); }

/* Player cell — avatar + name + change-arrow stacked beneath the name. */
.rl-player-cell {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

/* Clicking the player cell navigates to /playerProfile/{id}. The cell stops
   propagation on click so admins editing the row don't drop into edit mode
   from a profile click. */
.rl-player-cell-link {
    cursor: pointer;
    border-radius: 6px;
    padding: 2px 4px;
    margin: -2px -4px;
    transition: background 0.15s ease;
}
.rl-player-cell-link:hover .rl-player-name {
    text-decoration: underline;
    color: var(--mud-palette-primary);
}
.rl-player-cell-link:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}
.rl-player-name-stack {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.rl-player-name {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Stat cells — generic numeric / icon container. */
.rl-cell {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}
.rl-stat-cell { font-size: 0.875rem; }
.rl-stat-empty {
    color: var(--mud-palette-text-secondary);
    opacity: 0.5;
}

/* Points: bigger, bolder — anchors the row. */
.rl-points-cell .rl-points-value {
    font-weight: 700;
    font-size: 1rem;
}

/* Trophy chips — gold/silver/bronze counts for titles/finals/3rd places. */
.rl-trophy {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 999px;
    line-height: 1;
}
.rl-trophy-gold {
    background: var(--rank-gold-bg);
    color: var(--rank-gold-fg);
}
.rl-trophy-silver {
    background: var(--rank-silver-bg);
    color: var(--rank-silver-fg);
}
.rl-trophy-bronze {
    background: var(--rank-bronze-bg);
    color: var(--rank-bronze-fg);
}
.rl-trophy .mud-icon-root { font-size: 0.95rem !important; }

/* W/L fraction with color cues. */
.rl-winloss {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    font-weight: 600;
}
.rl-wins   { color: var(--status-completed-fg); }
.rl-losses { color: var(--status-disputed-fg); }
.rl-winloss-sep {
    color: var(--mud-palette-text-secondary);
    opacity: 0.6;
}

/* Win-rate donut + percentage label. */
.rl-winrate-cell { justify-content: center; }
.rl-winrate {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
}
.rl-winrate-label {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

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

/* ── Rank change indicators ── */
.rl-rank-change, .pp-rank-change {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: 0.75rem;
    font-weight: 600;
}
.rl-rank-up, .pp-rank-up     { color: var(--mud-palette-secondary); }
.rl-rank-down, .pp-rank-down { color: var(--status-disputed-fg); }

/* Skeleton variant uses the same grid template so widths stay aligned. */
.rl-grid-skeleton .rl-row { pointer-events: none; }

/* ── Card layout ─────────────────────────────────────────────────────
   Below the laptop breakpoint the table layout is too dense to read,
   so we render each ranking as a MudCard instead. The grid above and
   the cards block both render the full data set; CSS toggles between
   them based on viewport width.
   The card grid itself is a <MudGrid> (#919); this wrapper only owns the
   table↔cards toggle, which MudBlazor cannot express (hide above a
   breakpoint, show below). */
.rl-cards {
    display: none;
}

.rl-card {
    overflow: hidden;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.rl-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(26, 58, 92, 0.14);
}

/* Top-3 cards inherit the same gold/silver/bronze surface treatment
   the top-3 table rows use. The accent bar on the left edge mirrors
   the visual rhythm of the rang-lista reference. */
.rl-card.rl-rank-1 {
    background: var(--rank-gold-bg);
    border-left: 4px solid var(--rank-gold-fg);
}
.rl-card.rl-rank-2 {
    background: var(--rank-silver-bg);
    border-left: 4px solid var(--rank-silver-fg);
}
.rl-card.rl-rank-3 {
    background: var(--rank-bronze-bg);
    border-left: 4px solid var(--rank-bronze-fg);
}

/* Header row of the card: rank badge • avatar+name • win-rate donut. */
.rl-card-head {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 12px;
    padding: 14px 16px 10px;
}
.rl-card-identity {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}
.rl-card-name-stack {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.rl-card-name-stack .rl-player-name { font-size: 1rem; }
.rl-card-winrate { display: flex; align-items: center; }

/* Points are the headline metric — large, tabular, with a quiet label. */
.rl-card-points {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 10px;
}
.rl-card-points-value {
    font-size: 1.875rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-primary);
}
.rl-card-points-label {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Trophy chip strip — only rendered when the player has any. */
.rl-card-trophies {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 12px;
}

/* Three-up stat strip beneath the card body. Each stat is label-above,
   value-below for compact density. */
.rl-card-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    padding-top: 12px;
    border-top: 1px solid var(--border-subtle);
}
.rl-card-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    align-items: flex-start;
}
.rl-card-stat-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}
.rl-card-stat-value {
    font-size: 1rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

/* Toggle: cards on small screens, table on large. The breakpoint sits
   below the typical laptop width; above it the table fits without
   horizontal scroll once .ce-form-wrap is widened by .rl-page. */
@media (max-width: 1199px) {
    .rl-grid { display: none; }
    .rl-cards { display: block; }
}

/* Narrow: single-column cards, smaller rank badge inside the card.
   The single-column drop is handled by the MudItem xs="12" breakpoint. */
@media (max-width: 599px) {
    .rl-card-head { padding: 12px; }
    .rl-card-points-value { font-size: 1.5rem; }
    .rl-card-stats { grid-template-columns: repeat(3, 1fr); gap: 6px; }
    .rl-rank-badge { width: 36px; height: 36px; font-size: 0.75rem; }
    .rl-winrate { width: 48px; height: 48px; }
}

/* ================================================================
   Administration – Player Duplicates
   ================================================================ */
.player-duplicate-card {
    padding-bottom: 20px;
}

.player-duplicate-header {
    gap: 12px;
    margin-bottom: 14px;
}

.player-duplicate-reasons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
}

.player-duplicate-panel {
    height: 100%;
    border: 1px solid var(--border-light);
    border-radius: 10px;
    padding: 16px;
    background: var(--navy-tint-3);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.player-duplicate-meta {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 76px;
}

/* ---- Main Tab Header (icon-only on mobile) ---- */
.ce-main-tabs-header {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.ce-main-tabs-header::-webkit-scrollbar { display: none; }

/* Nested tabs (Draw / Schedule sub-tabs) — lighter treatment */
.ce-nested-tabs-header {
    border-bottom: 2px solid var(--border-light);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.ce-nested-tabs-header::-webkit-scrollbar { display: none; }

.ce-nested-tabs-panels {
    padding: 16px 0 0;
}

/* ---- Shared Mobile Competition Layout ---- */
.competition-tabs-panels {
    padding: 24px;
}

.schedule-toolbar,
.matches-toolbar {
    display: flex;
    align-items: center;
    gap: 16px;
    width: 100%;
    margin-bottom: 16px;
}

.schedule-toolbar {
    justify-content: flex-end;
}

.schedule-toolbar__date {
    width: min(240px, 100%);
}

.schedule-setup-copy {
    color: var(--mud-palette-text-secondary);
    max-width: 42rem;
}

.matches-toolbar__search {
    width: min(320px, 100%);
}

/* ---- Schedule Table (sched-*) ---- */
.sched-table-wrap {
    overflow: hidden;
    border: 1px solid var(--border-light);
}

.sched-table-wrap .mud-table-container {
    max-height: 70vh;
}

.sched-time-col {
    width: 80px;
    min-width: 80px;
    background: var(--navy-tint-3) !important;
    text-align: center !important;
    vertical-align: middle !important;
    position: sticky;
    left: 0;
    z-index: 2;
}

.sched-court-col {
    min-width: 260px;
    text-align: center !important;
}

.sched-match-cell {
    min-width: 260px;
    vertical-align: middle !important;
    padding: 6px 8px !important;
}

.sched-empty-slot {
    height: 72px;
    border-radius: 8px;
    border: 2px dashed var(--border-light);
    background: var(--navy-tint-2);
}

/* Legacy — kept for any remaining references */
.schedule-grid-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px;
    position: relative;
}

.schedule-grid {
    display: flex;
    gap: 16px;
    min-width: max-content;
}

.schedule-grid > :first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--mud-palette-surface);
}

.schedule-grid > div > :first-child {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--mud-palette-surface);
}


.draw-mobile-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.draw-mobile-round {
    border: 1px solid var(--border-light);
    border-radius: 12px;
    background: var(--mud-palette-surface);
    padding: 14px;
}

.draw-mobile-round-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 14px;
    flex-wrap: nowrap;
}

.draw-mobile-round-nav .mud-icon-button {
    flex-shrink: 0;
}

.draw-mobile-round-header-wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.draw-mobile-round-header {
    margin-bottom: 0;
    flex: 1;
    text-align: center;
}

.draw-mobile-round-counter {
    color: var(--mud-palette-text-secondary);
    font-weight: 600;
    letter-spacing: 0.06em;
}

.draw-mobile-round-matches {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.draw-mobile-match-item {
    width: 100%;
}

@media (max-width: 959px) {
    .competition-tabs-panels {
        padding: 16px;
    }

    /* Phased-league draw subtabs render inside an outer competition-tabs-panels
       container that already supplies mobile padding. Without this override the
       inner panel doubles up, squeezing the standings table so player names get
       clipped (#903). */
    .competition-tabs-panels.phased-draw-subtabs {
        padding: 0;
    }

    /* PhaseDrawTab's outer MudStack carries `pa-2` for desktop breathing room,
       but at sm + xs that 8px of padding on every side just shrinks the
       standings cards further (#903). Strip it at sm too — GroupCardsGrid is
       single-column below lg (1280px) so removing the gutter doesn't break
       any inter-column spacing here. Desktop keeps the 8px. */
    .phase-tab-row.pa-2 {
        padding: 0 !important;
    }

    .draw-actions-row,
    .schedule-toolbar,
    .matches-toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .draw-actions-row > *,
    .schedule-toolbar > *,
    .matches-toolbar > * {
        width: 100%;
    }

    .draw-group-size,
    .draw-size-select,
    .schedule-toolbar__date,
    .matches-toolbar__search {
        width: 100%;
        max-width: none;
    }

    .schedule-setup-card {
        padding: 16px 16px 20px;
    }

    .ce-save-bar {
        justify-content: stretch;
    }

    .ce-save-bar .mud-button-root {
        width: 100%;
    }

    .match-dialog-content {
        min-width: min(400px, calc(100vw - 32px));
    }

    .md-dialog {
        min-width: min(420px, calc(100vw - 32px));
    }
}

@media (max-width: 599px) {
    .competition-tabs-panels {
        padding: 0;
    }

    /* MudGrid's default gutter uses negative margins on .mud-grid plus
       padding-left/top on .mud-grid-item — fine when there's >1 column, but
       at xs every MudItem inside the phased subtabs (xs="12") drops to a
       single column. The padding-left then just insets each card by 16px
       on the left, and the negative margin extends the grid past its
       container. Both squeeze the standings table so player names clip
       (#903). Drop the negatives and the horizontal item padding here;
       keep padding-top so cards still have vertical breathing room.
       Scope: xs only — at sm (600-959px) the metadata and knockout-config
       grids switch to 2-column (sm="6") and still need the gutter. */
    .phased-draw-subtabs .mud-grid {
        width: 100%;
        margin-left: 0;
        margin-top: 0;
    }

    .phased-draw-subtabs .mud-grid > .mud-grid-item {
        padding-left: 0;
    }

    /* Edge-to-edge sections on xs (scoped to competition-edit tabs): drop the card outline
       so content uses the full viewport width. A top divider preserves separation between
       stacked sections and from the tab strip. Other pages using .ce-section keep their card. */
    .competition-tabs-panels .ce-section {
        padding: 12px;
        border: 0;
        border-top: 1px solid var(--border-light);
        border-radius: 0;
        margin-bottom: 0;
    }

    .draw-bracket {
        padding: 12px;
    }

    /* Force fixed column widths so the player name cell can shrink and ellipsis-truncate
       inside a tight viewport. MudTable's default auto layout would otherwise expand to fit
       the longest name and push other columns off-screen. */
    .ct-players-table .mud-table-root {
        table-layout: fixed;
        width: 100%;
    }

    .ct-players-table .ct-th-rank    { width: 44px; }
    .ct-players-table .ct-th-pts     { width: 56px; }
    .ct-players-table .ct-th-actions { width: 44px; }

    .ct-players-table .mud-table-cell {
        padding-left: 6px;
        padding-right: 6px;
    }
}

/* ---- Group Stage Matches Dialog ----
   The gradient banner lives on .mud-dialog-title (not on the inner .gsm-header
   div) so that MudBlazor's floating close button — which is a sibling of
   .mud-dialog-title positioned absolutely against .mud-dialog at top:8px
   right:8px — visually sits over the gradient rather than over the dialog's
   surface color in the rounded-corner gap above the title. The .gsm-header div
   stays as the flex layout for icon + text only. */
.gsm-dialog .mud-dialog-title {
    padding: 16px 24px;
    background: linear-gradient(135deg, var(--tc-primary) 0%, color-mix(in srgb, var(--tc-primary), black 20%) 100%);
    border-bottom: 3px solid var(--mud-palette-secondary);
}

.gsm-header {
    display: flex;
    align-items: center;
    gap: 12px;
}

.gsm-header__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 8px;
    background: var(--teal-tint-20);
    color: var(--mud-palette-secondary);
}

.gsm-header__title {
    color: var(--chalk-white) !important;
    font-weight: 600 !important;
    letter-spacing: 0.01em;
}

.gsm-header__group-name {
    color: var(--mud-palette-secondary) !important;
    font-weight: 500 !important;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* MudBlazor's floating close button (CloseButton="true") sits absolutely at
   the top-right of the dialog. The default action-default-hover background
   (a light surface tint MudBlazor applies on hover/focus/active) breaks the
   gradient gsm-header — force the button transparent so the gradient shows
   through, and tint the active/hover state to a subtle chalk-white wash
   that reads on the dark background instead. */
.gsm-dialog .mud-button-close {
    color: var(--chalk-white) !important;
    background-color: transparent !important;
}

.gsm-dialog .mud-button-close:hover,
.gsm-dialog .mud-button-close:focus,
.gsm-dialog .mud-button-close:focus-within,
.gsm-dialog .mud-button-close:active {
    background-color: color-mix(in srgb, var(--chalk-white), transparent 90%) !important;
}

.gsm-dialog-body {
    padding: 0 !important;
}

.gsm-content {
    padding: 20px 24px;
}

@media (max-width: 599px) {
    .gsm-content {
        padding: 12px;
    }

    .gsm-dialog .mud-dialog-title {
        padding: 12px 16px;
    }

    /* Edge-to-edge dialog since MudBlazor's FullScreen is all-or-nothing,
       not responsive. Same pattern as edit-court / import-rankings dialogs. */
    .gsm-dialog.mud-dialog {
        margin: 0 !important;
        max-height: 100dvh !important;
        height: 100dvh !important;
        max-width: 100vw !important;
        width: 100vw !important;
        border-radius: 0 !important;
    }

    .gsm-dialog .mud-dialog-content {
        max-height: none !important;
    }
}
/* ---- Dialog Responsive Content ---- */
.ce-dialog-content {
    overflow-x: auto;
}

@media (max-width: 599px) {
    .ce-dialog-content {
        padding: 12px !important;
    }

    /* Ensure match dialog doesn't overflow on phones */
    .match-dialog-content {
        min-width: unset;
        width: 100%;
    }

    /* Scale player images in match dialog */
    .match-dialog-content .profile-image {
        max-width: 70px;
        max-height: 70px;
    }

    /* New match dialog responsive (duplicated from md-* inline @media for cascade safety) */
    .md-dialog {
        min-width: unset;
        width: 100%;
    }

    /* Matches table compact on mobile */
    .ce-matches-table .mud-table-cell,
    .ce-matches-table .mud-table-head .mud-table-cell {
        padding: 8px 6px;
        font-size: 0.8125rem;
        white-space: nowrap;
    }
}

/* Tab panel transition */
.competition-tabs-panels,
.ce-nested-tabs-panels {
    animation: ce-fade-in 0.15s ease-out;
}

@keyframes ce-fade-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---- Shared Page Headers / Dialogs ---- */
.responsive-page-header {
    gap: 12px;
}

@media (max-width: 959px) {
    .responsive-page-header {
        flex-wrap: wrap;
        align-items: flex-start !important;
    }

    .responsive-page-header .mud-button-root {
        width: 100%;
    }

    .mud-dialog-width-sm,
    .mud-dialog-width-md,
    .mud-dialog-width-lg,
    .mud-dialog-width-xl {
        max-width: calc(100vw - 24px) !important;
    }
}

/* ---- Scheduling Admin List Cards ----
   Wrap-and-indent layout for SessionTypesManagement and SeasonsManagement
   list rows. Mirrors the .ur-row idiom from UserRolesOverview /
   MembersOverview. Desktop: avatar + info + trailing chips/actions sit
   on a single flex row. Mobile (<=599px): the trailing block wraps to a
   new line, indented 56px (40px avatar + 16px gap) so it lines up under
   the content column; the first action icon absorbs whitespace so
   chips read left-to-right and tap targets pin to the right edge. */
.scheduling-admin-card {
    display: flex;
    align-items: center;
    gap: 16px;
}

.scheduling-admin-card .sac-info {
    flex: 1;
    min-width: 0;
}

@media (max-width: 599px) {
    .scheduling-admin-card {
        flex-wrap: wrap;
    }

    .scheduling-admin-card .sac-trailing {
        width: 100%;
        margin-left: 56px;
    }

    .scheduling-admin-card .sac-trailing .mud-icon-button {
        margin-left: auto;
    }

    .scheduling-admin-card .sac-trailing .mud-icon-button + .mud-icon-button {
        margin-left: 0;
    }
}



/* Issue #458: Compact chip-style tab strip on mobile.
   Replaces the previous icon-only collapse so short labels stay readable while
   reducing vertical footprint (~40px vs. ~48–56px default). Targets default
   mud-* classes so every MudTabs site picks it up without per-page wrappers.
   Uses CourtNavy at low intensity for the active fill (matches the design
   system) instead of the default underline slider.

   #883: MudBlazor 9 writes the `MinimumTabWidth` parameter into each tab as an
   inline style (default `160px`). Inline styles beat regular CSS, so any CSS
   override would only show as struck-through in DevTools while the inline
   declaration itself stuck around. Instead each call site passes
   `MinimumTabWidth="var(--mud-tab-min-width)"`, and the variable is flipped to
   0 on mobile below — the inline style still resolves, but to 0, so the
   constraint is truly gone. */
:root {
    --mud-tab-min-width: 160px;
}

@media (max-width: 599px) {
    :root {
        --mud-tab-min-width: 0;
    }

    .mud-tabs-toolbar {
        min-height: 0;
        border-bottom: none;
    }

    .mud-tab-slider {
        display: none !important;
    }

    .mud-tab {
        min-height: 40px;
        padding: 4px 12px;
        margin: 4px 2px;
        border-radius: 999px;
        border: 1px solid var(--border-light);
        background-color: transparent;
        color: var(--mud-palette-text-secondary);
        text-transform: none;
        font-size: 0.8125rem;
        font-weight: 500;
        letter-spacing: 0;
        gap: 6px;
        flex-shrink: 0;
        opacity: 1;
    }

    /* #883: hide MudTabs icons on mobile globally so the chip strip stays
       compact even when a tab declares Icon="...". MudBlazor still renders the
       icon element but we collapse it to zero so the label can use the full
       chip width. */
    .mud-tab .mud-icon-root {
        display: none !important;
    }

    .mud-tab.mud-tab-active {
        background-color: var(--navy-tint-6);
        border-color: var(--border-light);
        color: var(--mud-palette-primary);
        font-weight: 600;
    }

    .mud-tab.mud-tab-icon-text {
        justify-content: center;
    }

    .mud-tab.mud-tab-icon-text > :not(.mud-icon-root) {
        display: inline !important;
    }

    .mud-tab:focus-visible {
        outline: 2px solid var(--mud-palette-primary);
        outline-offset: 2px;
    }
}


@media (min-width: 960px) {
    .h2h-comparison-shell {
        grid-template-columns: minmax(180px, 1fr) minmax(300px, 1.2fr) minmax(180px, 1fr);
        align-items: stretch;
    }

    .h2h-summary-card {
        grid-column: auto;
    }
}

@media (max-width: 599px) {
    .h2h-comparison-shell {
        grid-template-columns: 1fr 1fr;
        gap: 12px;
    }

    .h2h-summary-card {
        padding: 14px;
    }

    .h2h-player-card {
        padding: 14px 10px;
    }

    
.h2h-player-avatar {
    width: 100px;
    height: 100px;
    font-size: 1.75rem;
    font-weight: 700;
}
.h2h-player-photo {
        width: 76px;
        height: 76px;
    }

    .h2h-wins-row {
        width: 100%;
        justify-content: space-between;
        gap: 10px;
    }

    .h2h-win-pill {
        min-width: 64px;
        padding: 8px 10px;
    }

    .h2h-stat-row {
        gap: 10px;
    }

    .h2h-p1-value,
    .h2h-p2-value {
        min-width: 64px;
        font-size: 0.875rem;
    }

    .h2h-stat-label {
        font-size: 0.625rem;
    }
}

.matches-toolbar__title {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}


/* ── Notification Menu (bell dropdown) ── */

.nm-root {
    position: relative;
    display: inline-flex;
}

.nm-bell-wrap {
    position: relative;
    display: inline-flex;
}

.nm-badge {
    position: absolute;
    top: 4px;
    right: 4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--mud-palette-secondary);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    pointer-events: none;
    box-shadow: 0 0 0 2px var(--deep-court);
}

.nm-bell-wrap--has-unread .nm-badge {
    animation: nm-pulse 2s ease-in-out infinite;
}

@keyframes nm-pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.15); }
}

.nm-popover {
    width: 380px;
    max-width: calc(100vw - 32px);
    border-radius: 14px !important;
    border: 1px solid var(--border-light) !important;
    box-shadow: 0 20px 48px rgba(26, 58, 92, 0.12), 0 4px 12px var(--navy-tint-6) !important;
    overflow: hidden !important;
}

.nm-panel {
    display: flex;
    flex-direction: column;
    background: var(--mud-palette-surface);
}

.nm-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px 12px;
    border-bottom: 1px solid var(--border-subtle);
}

.nm-header__title-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nm-header__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    border-radius: 11px;
    background: var(--teal-tint-10);
    color: var(--mud-palette-secondary);
    font-size: 12px;
    font-weight: 700;
}

.nm-body {
    overflow-y: auto;
    max-height: 360px;
}

.nm-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
}

.nm-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    padding: 14px 20px;
    border: none;
    border-left: 3px solid transparent;
    background: transparent;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s ease;
    font-family: inherit;
}

.nm-item:hover {
    background: var(--navy-tint-3);
}

.nm-item--unread {
    border-left-color: var(--mud-palette-secondary);
    background: var(--teal-tint-4);
}

.nm-item--unread:hover {
    background: var(--teal-tint-6);
}

.nm-item + .nm-item {
    border-top: 1px solid var(--border-subtle);
}

.nm-item__icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    background: var(--navy-tint-6);
    margin-top: 1px;
}

.nm-item--unread .nm-item__icon {
    background: var(--teal-tint-10);
}

.nm-item__content {
    flex: 1;
    min-width: 0;
}

.nm-item__title {
    font-size: 13px;
    font-weight: 600;
    color: var(--tc-primary);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nm-item__message {
    font-size: 12.5px;
    color: var(--mud-palette-text-secondary);
    line-height: 1.4;
    margin-top: 2px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.nm-item__time {
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    margin-top: 4px;
    font-weight: 500;
}

.nm-item__dot {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--mud-palette-secondary);
    margin-top: 6px;
}

.nm-overlay {
    z-index: calc(var(--mud-zindex-popover) - 1) !important;
    background: transparent !important;
}

.nm-footer {
    border-top: 1px solid var(--border-subtle);
    padding: 4px 8px;
}

.nm-footer__btn {
    text-transform: none !important;
    font-weight: 600 !important;
    font-size: 13px !important;
    letter-spacing: 0 !important;
}

/* ── Notifications Page ── */

.notifications-page {
    max-width: 920px;
    margin: 0 auto;
}

.notifications-page__loading,
.notification-settings-shell__loading {
    display: flex;
    justify-content: center;
    padding: 32px 0;
}

.notifications-page__filters {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
}

.notifications-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.notifications-page__time-group {
    font-size: 12px;
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 20px 0 8px;
}

.notifications-page__time-group:first-child {
    padding-top: 0;
}

.notification-item {
    border: 1px solid var(--border-light);
    border-radius: 14px !important;
    background: var(--mud-palette-surface);
    box-shadow: 0 10px 24px rgba(26, 58, 92, 0.05);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.notification-item--unread {
    border-left: 4px solid var(--mud-palette-secondary);
    background: var(--teal-tint-4);
}

.notification-item__button {
    width: 100%;
    padding: 16px 20px;
    border: none;
    background: transparent;
    text-align: left;
    display: flex;
    align-items: flex-start;
    gap: 14px;
    cursor: pointer;
    font-family: inherit;
}

.notification-item__button:hover {
    background: var(--navy-tint-2);
    border-radius: 14px;
}

.notification-item__icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: var(--navy-tint-6);
}

.notification-item--unread .notification-item__icon {
    background: var(--teal-tint-10);
}

.notification-item__body {
    flex: 1;
    min-width: 0;
}

.notification-item__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.notification-item__meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}

.notifications-page__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 60px 20px;
    text-align: center;
}

.notifications-page__empty-icon {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--teal-tint-6);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 16px;
}

/* ── Notification Settings ── */

.notification-settings-shell {
    max-width: 720px;
    margin: 0 auto;
}

.notification-settings-card {
    border: 1px solid var(--border-light);
    border-radius: 14px !important;
    background: var(--mud-palette-surface);
}

.notification-settings-option {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px 0;
    border-top: 1px solid var(--border-subtle);
}

.notification-settings-option:first-of-type {
    margin-top: 8px;
}

.notification-settings-option__icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    background: var(--navy-tint-6);
    color: var(--tc-primary);
}

.notification-settings-option__text {
    flex: 1;
    min-width: 0;
}

.notification-settings-option__coming-soon {
    font-size: 11px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

@media (max-width: 599px) {
    .nm-popover {
        width: calc(100vw - 16px);
    }

    .notification-item__button {
        padding: 14px;
    }

    .notification-item__top {
        flex-direction: column;
    }
}

/* ── User Roles page ─────────────────────────────── */
.ur-table {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ur-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 20px;
    background: var(--mud-palette-surface);
    border-radius: 8px;
    border: 1px solid var(--border-subtle);
    transition: box-shadow 0.2s, border-color 0.2s, opacity 0.2s;
}

.ur-row:hover {
    border-color: var(--teal-tint-30);
    box-shadow: 0 2px 8px var(--navy-tint-6);
}

.ur-row--saving {
    opacity: 0.6;
    pointer-events: none;
}

.ur-avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--tc-primary);
    color: var(--chalk-white);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    flex-shrink: 0;
}

.ur-info {
    flex: 1;
    min-width: 0;
}

.ur-info .mud-typography {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ur-roles {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}

.ur-row-skeleton {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--border-light);
}

/* Role chip color overrides */
.ur-chip--admin.ur-chip--active { background: var(--tc-primary) !important; color: var(--chalk-white) !important; }
.ur-chip--admin:not(.ur-chip--active) { border-color: var(--tc-primary) !important; color: var(--tc-primary) !important; }

@media (max-width: 599px) {
    .ur-row {
        flex-wrap: wrap;
    }

    .ur-roles {
        width: 100%;
        margin-left: 56px;
    }
}

/* ================================================================
   Members Overview (#301)
   ================================================================ */

.mb-table { display: flex; flex-direction: column; }
.mb-row--revoked { opacity: 0.7; }
.mb-avatar--revoked { background: var(--mud-palette-action-disabled) !important; }

@media (max-width: 599px) {
    .mb-table .ur-row { flex-wrap: wrap; gap: 8px; }
}

/* ================================================================
   Sidebar Navigation – Sections & Active State (#193)
   ================================================================ */

.mud-drawer .mud-nav-link.active {
    background-color: color-mix(in srgb, var(--mud-palette-secondary) 15%, transparent) !important;
    box-shadow: inset 3px 0 0 var(--mud-palette-secondary) !important;
    color: #FFFFFF !important;
    font-weight: 600 !important;
}

.mud-drawer .mud-nav-link.active .mud-nav-link-icon {
    color: var(--mud-palette-secondary) !important;
}

.nav-section-label {
    color: var(--mud-palette-drawer-icon);
    padding: 16px 16px 4px;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
}

.nav-section-divider {
    border-color: color-mix(in srgb, var(--mud-palette-drawer-icon) 15%, transparent);
    margin: 4px 12px;
}

/* ── Tenant Picker ── */
.tp-tenant-card            { transition: box-shadow 0.2s, transform 0.15s; }
.tp-tenant-card:hover      { box-shadow: 0 4px 12px rgba(0,0,0,0.12); transform: translateY(-2px); }
.tp-tenant-logo            { height: 96px; width: auto; max-width: 100%; object-fit: contain; }
.tp-tenant-avatar          { height: 96px !important; width: 96px !important; font-size: 2.5rem !important; }

/* Welcome-hero logo variants. MudImage's Src can't be theme-conditional without
   piping theme state into TenantPicker, and dark mode is class-based (not
   prefers-color-scheme, per #1111), so swap by the root .clubrise-theme-dark
   class: color logo on light, light-variant logo on dark. */
.tp-welcome-logo--dark { display: none; }
html.clubrise-theme-dark .tp-welcome-logo--light { display: none; }
html.clubrise-theme-dark .tp-welcome-logo--dark  { display: block; }

/* ============================================================
   Scheduling Calendar Grid
   ============================================================ */

.scheduling-calendar {
    /* inline-grid sizes the container to its track sum, so the gap-color
       background paints across the full grid width when columns force the
       grid to overflow its scroll parent (mobile All-courts mode, or any
       desktop layout with enough courts to overflow). 'min-width: 100%'
       makes it stretch to the parent's width when there's slack so 1fr
       columns still distribute evenly on wide viewports. */
    display: inline-grid;
    gap: 1px;
    background-color: var(--scheduling-grid-gap);
    min-width: 100%;
    box-sizing: border-box;
}

/* Hour-based court calendar. --scheduling-px-per-min drives both the
   grid-row pitch and the inline reservation heights in CalendarSlotCell,
   so changing the scale keeps cell heights aligned with the rows.
   Competition-schedule grids deliberately do NOT carry this class. */
.scheduling-calendar-hourly {
    --scheduling-px-per-min: 0.85;
    --scheduling-hour-row-height: calc(60 * var(--scheduling-px-per-min) * 1px);
    grid-template-rows: auto;
    grid-auto-rows: var(--scheduling-hour-row-height);
}

.scheduling-calendar-mobile.scheduling-calendar-hourly {
    --scheduling-px-per-min: 0.5;
}

/* Keeps empty cells from exceeding their grid track when px-per-min is
   compressed. Scoped so competition cells keep their unscaled 48 px floor. */
.scheduling-calendar-hourly .scheduling-slot {
    min-height: calc(48 * var(--scheduling-px-per-min) * 1px);
}

.scheduling-calendar-header {
    background-color: var(--mud-palette-surface);
    padding: 6px 4px;
    font-weight: 600;
    text-align: center;
    border-bottom: 2px solid var(--scheduling-header-border);
    /* Allow the court-name cell to wrap so narrow columns stay readable. */
    overflow-wrap: anywhere;
    line-height: 1.2;
}

.scheduling-time-label {
    background-color: var(--mud-palette-surface);
    padding: 8px 12px;
    font-size: var(--scheduling-time-font);
    font-weight: var(--scheduling-time-weight);
    color: var(--scheduling-time-color);
    text-align: right;
    /* Keep the time column visible while the grid scrolls horizontally over
       the court columns (#924). Background is already opaque so cells below
       can't bleed through. */
    position: sticky;
    left: 0;
    z-index: 2;
}


/* Corner cell at the intersection of the time column and the court-header row.
   Sticky-left so it stays anchored above the time labels during horizontal
   scroll; higher z-index than the time labels so it occludes any court header
   that scrolls under it. */
.scheduling-calendar-corner {
    position: sticky;
    left: 0;
    z-index: 3;
}

/* The inner MudText renders <p class="mud-typography mud-typography-body2">
   which carries its own font-weight and would otherwise override the
   parent's bold time-label weight. Inherit so the wrapper's weight wins. */
.scheduling-time-label .mud-typography {
    font-weight: inherit;
}

.scheduling-court-name {
    font-weight: 600;
    /* Court names may be long ("Centre Court 1"); wrap onto multiple lines so
       columns can stay narrow on mobile All-courts mode without forcing a
       max-content column width. */
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.15;
}

.scheduling-surface-icon {
    vertical-align: middle;
}

.scheduling-surface-clay  { color: var(--surface-clay); }
.scheduling-surface-hard  { color: var(--surface-hard); }
.scheduling-surface-grass { color: var(--surface-grass); }

.scheduling-slot {
    background-color: var(--scheduling-slot-bg);
    padding: 4px 8px;
    /* border-box makes the inline `height` set by AnchorStyle include padding
       and border, so cells of all variants render at the exact same visual
       height for the same HeightMinutes. Without this, scheduling-slot-booked
       (no border, 8px padding) would be ~82px tall while scheduling-slot-league
       (2px dashed border + 2px margin + 8px padding) would be ~90px — making
       the bleed-gap appear/disappear depending on the variant pair. */
    box-sizing: border-box;
    min-height: 48px;
    cursor: pointer;
    transition: background-color 0.15s;
    /* Wrap long session names / competition names so they respect the
       column's 72px minimum instead of forcing the column wider. */
    overflow-wrap: anywhere;
    min-width: 0;
    /* Anchor point for absolutely-positioned overlays such as
       .scheduling-slot-unpaid-badge. AnchorStyle already sets this when
       HeightMinutes/OffsetMinutes is set, but not every reservation cell
       carries an anchor (e.g. cells rendered at their natural row height),
       so make the relative-positioning explicit on the base rule. */
    position: relative;
}

.scheduling-slot:hover {
    background-color: var(--scheduling-slot-hover);
}

/* Payments MVP follow-up (#1171): top-right corner badge that marks a
   reservation as Unpaid. Only rendered on cell variants whose viewer is
   either the booker themselves or a manager — non-manager viewers of
   other people's cells never see it, mirroring the existing
   CanSeeReservationDetails gate. pointer-events:none lets clicks pass
   through to the cell's own click handler so opening the details dialog
   still works from any pixel. */
.scheduling-slot-unpaid-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 18px !important;
    height: 18px !important;
    padding: 2px;
    background-color: var(--mud-palette-warning);
    color: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
    z-index: 3;
    pointer-events: none;
}

.scheduling-slot-booked {
    cursor: default;
    color: #fff;
    font-size: 0.8rem;
    border-radius: 8px;
    /* No margin — the inline `height` from AnchorStyle (HeightMinutes - 1px)
       already provides a hairline gap below every anchored cell, and avoiding
       margin keeps the gap CONSISTENT across all cell variants (booked, league,
       closure). With margin, the gap would compound for booked-after-booked
       cells but collapse to none between booked-and-empty cells, which is the
       "sometimes there's a gap, sometimes there isn't" bug. */
    overflow: hidden;
}

.scheduling-slot-booked:hover {
    filter: brightness(1.05);
}

.scheduling-slot-pending {
    opacity: 0.7;
    border: 2px dashed rgba(255, 255, 255, 0.6);
    background-image: repeating-linear-gradient(
        -45deg, transparent, transparent 4px, rgba(255,255,255,0.1) 4px, rgba(255,255,255,0.1) 8px
    );
}

.scheduling-recurring-indicator {
    opacity: 0.9;
}

.scheduling-slot-league {
    border: 2px dashed var(--league-slot-color);
    /* Opaque underpaint + tint overlay so the translucent teal doesn't expose
       the grid container's --scheduling-grid-gap navy through the cell. Without
       the opaque underpaint the translucent fill blends with the navy underlayer
       and reads as gray. */
    background-color: var(--scheduling-slot-bg);
    background-image: linear-gradient(var(--league-slot-bg), var(--league-slot-bg));
    cursor: pointer;
    box-sizing: border-box;
    border-radius: 8px;
}

.scheduling-slot-league:hover {
    background-image: linear-gradient(var(--league-slot-bg-hover), var(--league-slot-bg-hover));
}

.scheduling-slot-league-mine {
    border: 2px solid var(--league-slot-mine-border);
    background-color: var(--scheduling-slot-bg);
    background-image: linear-gradient(var(--league-slot-mine-bg), var(--league-slot-mine-bg));
    cursor: pointer;
    box-sizing: border-box;
    border-radius: 8px;
}

/* Issue #1158: "my regular reservation" variant — solid primary fill with a
   MatchGold border so the member's own bookings pop against the surrounding
   gray "Booked" cells. Distinct from --league-slot-mine-* (green fill) so a
   regular booking still reads differently than a claimed league slot. */
.scheduling-slot-booked-mine {
    border: 2px solid var(--booked-mine-border);
    background-color: var(--booked-mine-bg);
    cursor: pointer;
    box-sizing: border-box;
    border-radius: 8px;
}

.scheduling-slot-booked-mine:hover {
    background-color: var(--booked-mine-bg);
    filter: brightness(0.92);
}

.scheduling-slot-league-claimed {
    border: 2px solid var(--league-slot-color);
    background-color: var(--scheduling-slot-bg);
    background-image: linear-gradient(var(--league-slot-claimed-bg), var(--league-slot-claimed-bg));
    cursor: pointer;
    box-sizing: border-box;
    border-radius: 8px;
}

/* Issue #771 follow-up: no-show visual treatment for the day calendar.
   "Vacant cell" — solid MatchGold border, session-type colour heavily
   faded over the slot background so the cell reads as "the booking
   happened, but the seat stayed empty." Distinct from Pending (dashed
   border + stripes, in-flux) and Closed (stripes, no colour). */
.scheduling-slot-noshow {
    border: 2px solid var(--noshow-color);
    background-color: var(--scheduling-slot-bg);
    background-image: linear-gradient(
        color-mix(in srgb, var(--noshow-session-color, var(--noshow-session-fallback)) 18%, var(--noshow-fill-base)),
        color-mix(in srgb, var(--noshow-session-color, var(--noshow-session-fallback)) 18%, var(--noshow-fill-base))
    );
    color: var(--noshow-color);
    cursor: pointer;
    box-sizing: border-box;
    border-radius: 8px;
    text-align: center;
    overflow: hidden;
}

.scheduling-slot-noshow .scheduling-slot-noshow-label {
    font-weight: 700;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--noshow-color);
}

.scheduling-slot-noshow .scheduling-slot-noshow-session {
    font-size: 0.7rem;
    font-weight: 500;
    color: color-mix(in srgb, var(--noshow-session-color, var(--noshow-session-fallback)) 70%, var(--noshow-session-fallback));
    opacity: 0.9;
}

.scheduling-slot-closed {
    background-color: var(--scheduling-closed-bg);
    background-image: repeating-linear-gradient(
        45deg, transparent, transparent 5px, rgba(0,0,0,0.03) 5px, rgba(0,0,0,0.03) 10px
    );
    cursor: not-allowed;
    color: var(--scheduling-closed-color);
    font-size: 0.75rem;
    border-radius: 8px;
    overflow: hidden;
}

.scheduling-slot-past {
    cursor: default;
}

.scheduling-slot-past:hover {
    background-color: var(--scheduling-slot-bg);
}

.scheduling-slot-past-retroactive {
    cursor: pointer;
}

.scheduling-slot-past-retroactive:hover {
    background-color: color-mix(in srgb, var(--mud-palette-warning) 18%, transparent);
    outline: 1px dashed var(--mud-palette-warning);
    outline-offset: -2px;
}

.scheduling-slot-past-retroactive:hover .scheduling-slot-add-icon {
    opacity: 1;
}

.scheduling-slot-add-icon {
    opacity: 0;
    transition: opacity 0.15s;
}

.scheduling-slot:hover .scheduling-slot-add-icon {
    opacity: 1;
}

/* Placeholder for cells fully covered by a multi-hour reservation anchored
   earlier in the same court column. Reserves the grid slot so CSS auto-flow
   keeps the rest of the row aligned to its court column. The anchor's
   z-elevated block paints over this placeholder visually and captures
   pointer events in the same area. */
.scheduling-slot-covered {
    background-color: transparent;
    pointer-events: none;
}

/* ============================================================
   Mobile All-courts compaction (issue #1024)

   Applied only when the mobile calendar is in "All courts" mode. Tightens
   padding/typography so even clubs with 7+ courts fit in a phone viewport
   without horizontal scrolling. Desktop and single-court mobile mode are
   not affected because this modifier is added by CalendarTimeGridMobile
   only in the ShowAllCourtsOnMobile branch.
   ============================================================ */

.scheduling-calendar-mobile-all .scheduling-calendar-header {
    padding: 3px 1px;
}

.scheduling-calendar-mobile-all .scheduling-court-name {
    font-size: 0.65rem;
    line-height: 1.05;
}

.scheduling-calendar-mobile-all .scheduling-surface-icon {
    font-size: 14px;
}

.scheduling-calendar-mobile-all .scheduling-time-label {
    padding: 3px 3px;
}

/* MudText caption renders an <p> with its own size, so the override
   needs to target the inner typography element. */
.scheduling-calendar-mobile-all .scheduling-time-label .mud-typography {
    font-size: 0.65rem;
    line-height: 1.1;
}

.scheduling-calendar-mobile-all .scheduling-slot {
    padding: 2px 3px;
}

.scheduling-calendar-mobile-all .scheduling-slot .mud-typography-caption {
    font-size: 0.5rem;
    line-height: 1.1;
}

.scheduling-calendar-mobile-all .scheduling-slot-closed,
.scheduling-calendar-mobile-all .scheduling-slot-booked {
    font-size: 0.5rem;
}

/* Recurring-occurrence badge inside a booked cell. The default sizes match
   the old inline overrides (12 px icon / 10 px text) so desktop rendering
   stays unchanged; the mobile-all rule above already shrinks the caption to
   match session-type and booker name. The icon needs its own mobile rule
   because MudIcon's size class would otherwise win. */
.scheduling-slot-meta-icon {
    font-size: 12px;
}

.scheduling-slot-meta-text {
    font-size: 10px;
}

.scheduling-calendar-mobile-all .scheduling-slot-meta-icon {
    font-size: 0.65rem;
}

@media (max-width: 599.98px) {
    .cdn-paper {
        margin-bottom: 4px !important;
    }
}

.scheduling-slot-has-booker .scheduling-slot-session-type {
    display: none;
}

/* Issue #1134 / #1158: on small viewports drop the labels from the
   league-mine and no-show variants so the icon alone communicates the
   cell state. The booked-mine label used to be in this list, but in
   #1158 it moved under explicit user control (MyReservationDisplayMode)
   so the media query no longer touches it. */
@media (max-width: 599.98px) {
    .scheduling-slot-league-mine .scheduling-slot-mine-label,
    .scheduling-slot-noshow .scheduling-slot-noshow-label,
    .scheduling-slot-noshow .scheduling-slot-noshow-session {
        display: none;
    }

    .scheduling-slot .mud-icon-root {
        font-size: 1rem;
    }
}

.scheduling-calendar-day-strip {
    padding: 4px 12px 5px;
    background-color: var(--mud-palette-surface);
    border-bottom: 1px solid var(--scheduling-header-border);
    text-align: center;
    line-height: 1.15;
}

.scheduling-calendar-day-name {
    font-weight: 700;
    color: var(--mud-palette-primary);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 0.7rem;
}

.scheduling-calendar-day-separator {
    display: inline-block;
    width: 4px;
    height: 4px;
    margin: 0 0.55rem;
    border-radius: 50%;
    background-color: var(--mud-palette-secondary);
    vertical-align: middle;
    opacity: 0.55;
}

.scheduling-calendar-day-date {
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    font-size: 0.7rem;
    letter-spacing: 0.01em;
}

.scheduling-calendar-header-bottom {
    border-top: 2px solid var(--scheduling-header-border);
    border-bottom: none;
}

.scheduling-calendar-corner-bottom {
    position: sticky;
    left: 0;
    z-index: 3;
}

/* Reserves space for the fixed MudAppBar so smooth-scroll lands the day-
   strip below the navbar instead of underneath it. */
.court-calendar-scroll-anchor {
    scroll-margin-top: 72px;
}

/* Month calendar grid */
.scheduling-month-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}

.scheduling-month-header {
    padding: 8px 4px;
    text-align: center;
}

.scheduling-month-cell {
    min-height: 80px;
    padding: 6px 8px;
    border: 1px solid var(--border-light);
    border-radius: 6px;
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.scheduling-month-cell:hover {
    background-color: var(--scheduling-month-hover);
}

.scheduling-month-cell--other {
    opacity: 0.4;
}

.scheduling-month-cell--today {
    background-color: var(--scheduling-today-bg);
    border-color: var(--scheduling-today-border);
}

.scheduling-month-cell-number {
    margin-bottom: 4px;
}

.scheduling-month-cell-badge {
    margin-top: 4px;
}

/* ── Admin Audit Log ── */
.audit-entry-bordered {
    border-bottom: 1px solid var(--border-subtle);
}

/* ── Closure conflict highlight ── */
.conflict-highlight {
    border: 1px solid var(--mud-palette-error);
    border-radius: 4px;
    padding: 2px;
}

/* ── Competition Schedule cells (MatchScheduleCell) ──
   schedule-cell + match-card: Competition Schedule calendar grid cells.
   MudBlazor has no calendar-cell primitive with the three states we need
   (scheduled match / club-event backdrop / disabled). Colors come from the
   "Court Series" palette (ChalkWhite, CourtNavy, CLUB_EVENT purple). */
/* ── Competition schedule: proportional duration blocks ─────────────────────
   The competition grid (wrapped in .competition-schedule-grid) reuses the
   reservation calendar's hourly-row machinery, but at a taller scale so the
   content-rich match card fits inside a 1-hour block. Each match cell is sized
   to its duration and offset to its start minute by MatchScheduleCell's
   AnchorStyle; matches longer than an hour bleed into later rows. Scoped to the
   competition wrapper so the Scheduling-module court calendar (0.85 px/min) is
   unaffected. */
.competition-schedule-grid .scheduling-calendar-hourly {
    --scheduling-px-per-min: 1.7;
}
/* border-box so the AnchorStyle height includes the cell's 6px padding, keeping
   match blocks aligned to the hour-row pitch (matches the reservation slot). */
.competition-schedule-grid .schedule-cell {
    box-sizing: border-box;
}
/* Fill the duration block so a match's box spans its full length instead of
   shrinking to its content — a 1-hour match now occupies exactly one hour. */
.competition-schedule-grid .schedule-cell-card,
.competition-schedule-grid .schedule-cell-card .mc {
    height: 100%;
}

/* ── Competition schedule: mobile "All courts" horizontal density ───────────
   With every court shown at once the columns are minmax(0, 1fr), so 5 courts on
   a phone leave each match cell barely wider than its scoreboard. The shared
   cell/card gutters (.schedule-cell 6px, .mc__row 8px, .mc__divider 8px) are
   sized for desktop width and waste most of a narrow column on horizontal
   padding. Trim the HORIZONTAL padding only — vertical padding is left intact so
   the duration-block height math (border-box + MatchScheduleCell.AnchorStyle)
   stays aligned to the hour-row pitch. Scoped to BOTH .competition-schedule-grid
   and the all-courts mobile layout, so the Scheduling-module calendar, the
   desktop competition grid, and the single-court mobile timeline are all
   untouched. MudBlazor has no utility for context-scoped padding overrides on a
   shared grid, hence hand-written CSS. */
.competition-schedule-grid .scheduling-calendar-mobile-all .schedule-cell {
    padding-left: 1px;
    padding-right: 1px;
}
.competition-schedule-grid .scheduling-calendar-mobile-all .schedule-cell-card .mc__row {
    padding-left: 2px;
    padding-right: 2px;
}
.competition-schedule-grid .scheduling-calendar-mobile-all .schedule-cell-card .mc__divider {
    margin-left: 2px;
    margin-right: 2px;
}
.competition-schedule-grid .scheduling-calendar-mobile-all .schedule-cell-card .mc__seed {
    padding-left: 1px;
    padding-right: 1px;
}

/* ── Competition schedule: single-court mobile timeline width (#1322) ─────────
   The shared .scheduling-calendar is display:inline-grid + min-width:100% so the
   multi-court "All courts" grid can grow past its scroll parent on purpose. In the
   SINGLE-court mobile timeline (grid-template-columns: auto 1fr, no -all class) that
   same shrink-to-content sizing lets the lone 1fr match column grow to the
   max-content of a long "possible teams" candidate list — a nowrap .mc__name on an
   undecided knockout match — blowing the card out past the viewport (observed
   ~556px) and forcing horizontal scroll. Pinning this layout to block-level grid
   makes its width definite (= the viewport), so the 1fr column is bounded and the
   candidate list truncates with its existing ellipsis instead of overflowing.
   Scoped with :not(.scheduling-calendar-mobile-all) so the All-courts grid keeps
   its intentional horizontal scroll untouched. MudBlazor has no utility for a
   context-scoped display override on a shared grid, hence hand-written CSS. */
.competition-schedule-grid .scheduling-calendar-mobile:not(.scheduling-calendar-mobile-all) {
    display: grid;
}

.schedule-cell { min-height: 96px; padding: 6px; border: 1px solid transparent; position: relative; transition: background-color 180ms ease, box-shadow 180ms ease; }
.schedule-cell.with-match { border-color: transparent; }
/* Disabled cells stay greyed-out but remain pointer-reactive — mobile tap-to-place
   needs to commit a move or surface a "can't drop here" warning when the user
   taps an empty slot, which is impossible with `pointer-events: none`. */
.schedule-cell.disabled { background: var(--mud-palette-surface); opacity: 0.4; }
.schedule-cell.past { opacity: 0.65; }

/* Mobile move-mode / long-press companion: suppresses the inner MatchCard's own
   click so taps route to the cell wrapper. The parent grid then commits the move
   (or shows the invalid-target snackbar). Without this the wrapper's click and
   MatchCard's dialog-open handler both fire and the user lands in the dialog
   while the calendar behind it is in move mode (#454). */
.schedule-cell.suppress-card-clicks .schedule-cell-card,
.schedule-cell.suppress-card-clicks .mc { pointer-events: none; }

/* Availability hint — predictive tint shown on cells in the dragged/hovered match's
   unavailable window. Applies to occupied cells too (swap targets) and to empty cells.
   Reads as "warning" not "blocked": the drop is still allowed (organisers may override
   player preferences). The wash sits on the outer cell, behind the MatchCard, so it
   composes with the spotlight rings/dim already on the card. Uses color-mix on the
   theme's error palette so the warning inherits the active theme (same pattern as
   the secondary-tint hover at line ~4056). */
.schedule-cell.availability-bad {
    background: color-mix(in srgb, var(--mud-palette-error) 18%, transparent);
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--mud-palette-error) 55%, transparent);
    /* .disabled sets opacity:0.4 which would make the wash invisible on empty cells —
       force full opacity here so the warning is legible regardless of cell state. */
    opacity: 1;
}
.schedule-cell.availability-bad.club-event {
    /* Combine cleanly with the club-event navy backdrop instead of replacing it. */
    background:
        linear-gradient(
            color-mix(in srgb, var(--mud-palette-error) 18%, transparent),
            color-mix(in srgb, var(--mud-palette-error) 18%, transparent)
        ),
        var(--navy-tint-4);
}
.schedule-cell.availability-bad.with-match {
    /* Occupied cells also need the warning to read through the card's own background.
       Slightly stronger wash since the card sits on top and would otherwise dilute it. */
    background: color-mix(in srgb, var(--mud-palette-error) 22%, transparent);
}

/* Mobile tap-to-place target — gold wash on cells that are a valid destination
   for the currently-selected match. MudBlazor has no primitive that paints a
   tinted "drop target" indicator on an arbitrary container; this composes with
   the existing .schedule-cell variants the same way .availability-bad does. */
.schedule-cell.mobile-move-target {
    background: color-mix(in srgb, var(--mud-palette-tertiary) 14%, transparent);
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--mud-palette-tertiary) 55%, transparent);
    /* .disabled forces opacity to 0.4 — undo so the wash stays legible on
       empty cells that would otherwise be grayed out. */
    opacity: 1;
}

/* schedule-cell-card: wraps MatchCard inside a calendar cell. The round
   marker now lives inside MatchCard's divider (opt-in ShowRound), so the
   wrapper only carries the optional conflict badge as a corner overlay. */
.schedule-cell-card {
    position: relative;
    width: 100%;
    border-radius: 6px;
    transition:
        opacity 180ms ease,
        box-shadow 180ms ease,
        transform 180ms ease,
        filter 180ms ease;
}
.schedule-cell-card .mc { width: 100%; min-width: 0; }

/* Hover spotlight — when an organizer hovers a match card on the schedule
   grid, every match that shares a participant gets a teal ring; the rest
   fade back. The hovered match itself wears a navy ring + small lift so the
   "source" reads as distinct from the "siblings". MudBlazor has no primitive
   for this kind of cross-cell relational highlight, hence custom CSS. */
.schedule-cell-card.is-hovered {
    opacity: 1;
    box-shadow:
        0 0 0 2px var(--mud-palette-primary),
        var(--shadow-md);
    transform: translateY(-1px);
    z-index: 2;
}
.schedule-cell-card.is-related {
    opacity: 1;
    box-shadow:
        0 0 0 2px var(--mud-palette-secondary),
        0 4px 12px color-mix(in srgb, var(--mud-palette-secondary) 18%, transparent);
    z-index: 1;
}
.schedule-cell-card.is-dimmed {
    opacity: 0.4;
    filter: saturate(0.7);
}

.schedule-cell-conflict {
    position: absolute;
    top: 4px;
    right: 6px;
    z-index: 2;
    color: var(--mud-palette-warning);
    display: inline-flex;
    line-height: 1;
    pointer-events: none;
}
.schedule-cell-conflict .mud-icon-root { font-size: 0.875rem; }

.club-event-backdrop {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 84px;
    height: 100%;
    color: var(--mud-palette-primary);
    opacity: 0.35;
}

/* Tighter scoreboard typography inside grid cells — cells are narrow. */
.schedule-cell-card .mc__row { padding: 5px 8px; min-height: 28px; }
.schedule-cell-card .mc__divider { margin: 0 8px; }
.schedule-cell-card .mc__name { font-size: 0.75rem; }
.schedule-cell-card .mc__seed { font-size: 0.625rem; padding: 0 4px; }
.schedule-cell-card .mc__total { font-size: 0.75rem; min-width: 18px; }
.schedule-cell-card .mc__set { font-size: 0.6875rem; min-width: 14px; }
/* Bracket + schedule-grid contexts suppress MatchCard's bottom schedule
   strip — the bracket tree position and the grid axes already convey the
   court/time. */
.schedule-cell-card .mc__schedule,
.draw-match-item .mc__schedule,
.draw-mobile-match-item .mc__schedule,
.draw-third-place-match .mc__schedule { display: none; }

.unscheduled-drop-zone { min-height: 48px; display: flex; flex-wrap: wrap; gap: 8px; padding: 8px; }
.unscheduled-drop-zone.mud-drop-zone-over { background: var(--teal-tint-20); outline: 2px dashed var(--mud-palette-secondary); }

/* dnd-*: drag-and-drop feedback for match scheduling grid.
   MudDropContainer applies these via CanDropClass/NoDropClass/DraggingClass.
   Colors source from the "Court Series" palette (AceTeal, CourtNavy). */
.dnd-valid-drop { background: var(--teal-tint-20) !important; outline: 1px dashed var(--mud-palette-secondary); }
.dnd-valid-drop.mud-drop-zone-over { background: var(--teal-tint-30) !important; outline: 2px dashed var(--mud-palette-secondary); }
.dnd-invalid-drop { cursor: not-allowed; }
.dnd-dragging { opacity: 0.6; transform: scale(0.98); transition: transform 80ms ease; }

.schedule-grid-drop-zone { height: 100%; min-height: 84px; }
.unscheduled-chip { display: inline-block; margin: 2px; }

/* ---- MatchCard inline start action ---- */
.mc { position: relative; }
.mc__start-action { position: absolute !important; top: 6px; right: 6px; z-index: 2; box-shadow: var(--shadow-sm); }

/* ---- Competition Completion Bar (persistent across tabs) ---- */
.competition-complete-bar-row { gap: 16px; }
.competition-complete-bar-text { flex: 1 1 320px; min-width: 0; }

/* MudBlazor primitives don't expose viewport-conditional layouts or breakpoint */
/* margin utilities, so xs polish (full-width button, tightened spacing, smaller */
/* bottom margin, calmer title weight) lives in this scoped media query. */
@media (max-width: 600px) {
    .competition-complete-bar { margin-bottom: 0.5rem !important; }
    .competition-complete-bar .mud-alert-message { padding-top: 4px; padding-bottom: 4px; }
    .competition-complete-bar-row { gap: 8px; align-items: stretch; }
    .competition-complete-bar .comp-name-bold { font-size: 1rem; line-height: 1.4; }
    .competition-complete-bar-button { width: 100%; min-height: 44px; }
}

/* ---- Competition Print Results (cpr-*) ---- */
.cpr-root { max-width: 1000px; margin: 0 auto; padding: 16px; }
.cpr-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
.cpr-sheet { background: #fff; border: 1px solid var(--border-light); border-radius: 12px; padding: 32px 40px; box-shadow: var(--shadow-sm); }

.cpr-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; padding-bottom: 16px; border-bottom: 2px solid var(--mud-palette-primary); margin-bottom: 20px; }
.cpr-header-left { display: flex; flex-direction: column; gap: 4px; }
.cpr-kicker { color: var(--mud-palette-primary); letter-spacing: 0.08em; }
.cpr-title { margin: 0; color: #0F2440; line-height: 1.2; }
.cpr-subtitle { color: #4B5563; }
.cpr-series { color: #6B7280; }
.cpr-header-right { display: grid; grid-template-columns: repeat(2, auto); gap: 6px 18px; justify-content: end; }
.cpr-header-stat { display: flex; flex-direction: column; align-items: flex-end; }
.cpr-stat-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; color: #6B7280; }
.cpr-stat-value { font-size: 0.95rem; font-weight: 600; color: #1A3A5C; }
.cpr-stat-big { font-size: 1.5rem; font-weight: 700; color: #1A3A5C; }

.cpr-stats-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 24px; }
.cpr-stat-tile { background: var(--navy-tint-3); border: 1px solid var(--border-subtle); border-radius: 8px; padding: 12px 16px; display: flex; flex-direction: column; gap: 4px; }

.cpr-section { margin-top: 24px; page-break-inside: avoid; }
.cpr-section-title { font-size: 1.05rem; font-weight: 700; color: #1A3A5C; margin: 0 0 12px; padding-bottom: 6px; border-bottom: 1px solid var(--border-light); text-transform: uppercase; letter-spacing: 0.04em; }

.cpr-podium { display: grid; grid-template-columns: 1fr 1.2fr 1fr; gap: 12px; align-items: end; margin-bottom: 16px; }
.cpr-podium-slot { background: var(--navy-tint-3); border: 1px solid var(--border-subtle); border-radius: 8px; padding: 12px; display: flex; flex-direction: column; gap: 6px; align-items: center; text-align: center; }
.cpr-podium-first { background: rgba(212, 160, 23, 0.1); border-color: rgba(212, 160, 23, 0.4); padding-top: 20px; padding-bottom: 20px; }
.cpr-rank-badge { width: 34px; height: 34px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 700; color: #fff; }
.cpr-rank-gold { background: #D4A017; }
.cpr-rank-silver { background: #9CA3AF; }
.cpr-rank-bronze { background: #D97706; }
.cpr-podium-team { font-weight: 600; color: #0F2440; }
.cpr-podium-label { font-size: 0.75rem; text-transform: uppercase; color: #6B7280; letter-spacing: 0.06em; }
.cpr-podium-points { font-size: 0.8rem; color: #15803D; font-weight: 600; }

.cpr-final { margin-top: 12px; padding: 12px 16px; background: var(--navy-tint-2); border: 1px solid var(--border-subtle); border-radius: 8px; }
.cpr-final-label { font-size: 0.7rem; text-transform: uppercase; color: #6B7280; letter-spacing: 0.08em; margin-bottom: 6px; }
.cpr-final-row { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: center; }
.cpr-final-team { color: #1A3A5C; }
.cpr-final-score { font-weight: 700; color: #0F2440; min-width: 100px; text-align: center; }
.cpr-final-winner { font-weight: 700; }

.cpr-group { margin-bottom: 16px; page-break-inside: avoid; }
.cpr-group-name { font-weight: 600; color: #1A3A5C; margin-bottom: 6px; }
.cpr-round { margin-bottom: 14px; page-break-inside: avoid; }
.cpr-round-name { font-weight: 600; color: #1A3A5C; margin-bottom: 6px; letter-spacing: 0.05em; }

.cpr-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.cpr-table thead th { text-align: left; padding: 6px 10px; background: var(--navy-tint-4); color: #374151; font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 1px solid var(--border-subtle); }
.cpr-table tbody td { padding: 6px 10px; border-bottom: 1px solid var(--border-subtle); color: #1F2937; }
.cpr-table tbody tr:last-child td { border-bottom: none; }
.cpr-col-rank { width: 36px; text-align: center; font-weight: 600; color: #6B7280; }
.cpr-col-num { width: 70px; text-align: center; }
.cpr-col-team { text-align: left; }
.cpr-col-strong { font-weight: 700; color: #0F2440; }

.cpr-footer { margin-top: 28px; padding-top: 10px; border-top: 1px solid var(--border-subtle); color: #6B7280; font-size: 0.8rem; text-align: right; }

/* Print overrides: hide page chrome, collapse toolbar, fit to paper */
@media print {
    @page { margin: 14mm; }
    body, html { background: #fff !important; }
    .mud-appbar, .mud-drawer, .mud-toolbar, .mud-snackbar-container, .mud-popover { display: none !important; }
    .mud-main-content, .mud-layout { padding: 0 !important; margin: 0 !important; }
    .mud-container { padding: 0 !important; max-width: 100% !important; }
    .cpr-no-print { display: none !important; }
    .cpr-root { max-width: 100%; padding: 0; }
    .cpr-sheet { border: none; padding: 0; box-shadow: none; border-radius: 0; }
    .cpr-section, .cpr-group, .cpr-round, .cpr-podium-slot { page-break-inside: avoid; }
    .cpr-podium-first { background: rgba(212, 160, 23, 0.1) !important; print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

/* ---- Court Print Schedule (cps-*) ---- */
/* The print sheet lives inside CourtCalendarView and is rendered off-screen
   (left: -10000px, visibility hidden) so the user doesn't see it on screen; it
   is revealed only in print media (see @media print below). Orientation and
   paper size are left to the browser's print dialog (#1231), so the sheet
   flows to the page width the user picks and is not scaled to fit one page. */
.cps-print-only {
    position: absolute;
    left: -10000px;
    top: 0;
    width: 1062px;
    visibility: hidden;
    pointer-events: none;
}
.cps-sheet { background: #fff; border: 1px solid var(--border-light); border-radius: 12px; padding: 28px 32px; box-shadow: var(--shadow-sm); }

.cps-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; padding-bottom: 14px; border-bottom: 2px solid var(--mud-palette-primary); margin-bottom: 18px; }
.cps-header-left { display: flex; flex-direction: column; gap: 4px; }
/* Date and club name share a row, aligned on their text baseline. */
.cps-title-row { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.cps-kicker { color: var(--mud-palette-primary); letter-spacing: 0.08em; }
.cps-title { margin: 0; color: #0F2440; line-height: 1.2; }
.cps-subtitle { color: #4B5563; }
.cps-header-right { display: grid; grid-template-columns: repeat(2, auto); gap: 6px 18px; justify-content: end; }
.cps-header-stat { display: flex; flex-direction: column; align-items: flex-end; }
.cps-stat-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; color: #6B7280; }
.cps-stat-value { font-size: 0.95rem; font-weight: 600; color: #1A3A5C; }

/* Emphasized grid (#1231): bold dark court/column dividers (2px) plus a strong
   outer frame and header rule, with lighter — but clearly visible — horizontal
   time-row lines (1px). Because the table uses border-collapse, the wider 2px
   vertical borders win over the 1px horizontals at every intersection, so the
   court columns read as bold lines down the page while the hour rows stay
   lighter. The same scheme reads well on screen and on paper, replacing the
   faint --border-subtle lines that were hard to follow when printed. */
.cps-grid { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 0.85rem; border: 2px solid #1E293B; }
.cps-grid thead th { background: var(--navy-tint-4); color: #374151; font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; padding: 8px 6px; border: 1px solid #64748B; border-left: 2px solid #334155; border-right: 2px solid #334155; border-bottom: 2px solid #1E293B; text-align: center; }
.cps-time-col { width: 64px; }
.cps-court-col { word-break: break-word; }
.cps-time-cell { width: 64px; padding: 6px 6px; border: 1px solid #64748B; border-left: 2px solid #334155; border-right: 2px solid #334155; background: var(--navy-tint-4); font-weight: 600; color: #1A3A5C; text-align: center; vertical-align: top; }

.cps-cell { padding: 6px 8px; border: 1px solid #64748B; border-left: 2px solid #334155; border-right: 2px solid #334155; vertical-align: top; height: 56px; }
/* Inner wrapper exists so print can clip overflowing content to a fixed
   height (table cells ignore max-height/overflow themselves). On screen it is
   a transparent block. */
.cps-cell-body { display: block; }
.cps-cell-time { font-weight: 700; color: #0F2440; font-size: 0.78rem; }
.cps-cell-session { font-size: 0.78rem; color: #1F2937; margin-top: 2px; }
.cps-cell-booker { font-size: 0.78rem; color: #4B5563; margin-top: 2px; }
.cps-cell-notes { font-size: 0.72rem; color: #6B7280; margin-top: 2px; font-style: italic; word-break: break-word; }

.cps-reservation { background: rgba(13, 148, 136, 0.08); }
.cps-league-slot { background: rgba(212, 160, 23, 0.10); }
.cps-closure { background: rgba(220, 38, 38, 0.08); }
.cps-unavailable { background: repeating-linear-gradient(45deg, #F3F4F6, #F3F4F6 6px, #FFFFFF 6px, #FFFFFF 12px); }
.cps-available { background: #FFFFFF; }

.cps-footer { margin-top: 24px; padding-top: 10px; border-top: 1px solid var(--border-subtle); color: #6B7280; font-size: 0.8rem; text-align: right; }

@media print {
    /* No `size` declaration: orientation and paper size are deferred to the
       browser's print dialog (#1231). Forcing `size: ... landscape` greys out
       the dialog's orientation control in Chromium, which is exactly what we
       want to avoid here. */
    @page { margin: 8mm; }
    body, html { background: #fff !important; }
    .mud-appbar, .mud-drawer, .mud-toolbar, .mud-snackbar-container, .mud-popover { display: none !important; }
    .mud-main-content, .mud-layout { padding: 0 !important; margin: 0 !important; }
    .mud-container { padding: 0 !important; max-width: 100% !important; }

    /* App chrome that isn't part of the schedule must never print (#1310) —
       e.g. the admin impersonation banner. */
    .impersonation-banner { display: none !important; }

    /* Hide the interactive calendar; reveal the print sheet that was sitting
       off-screen. */
    .cps-screen-only { display: none !important; }
    .cps-print-only {
        position: static;
        left: auto;
        top: auto;
        width: auto;
        visibility: visible;
        pointer-events: auto;
    }

    /* One day = one page (#1310). The fit is achieved by keeping the sheet
       compact — a small header (below) and tight rows (below) — rather than by
       clipping content to a computed height. A vh-based row-height cap was
       tried but `vh` does not map to the printed page box reliably in Chromium,
       so it clipped notes mid-line; it was removed. */
    .cps-sheet {
        border: none;
        padding: 0;
        box-shadow: none;
        border-radius: 0;
    }
    /* Compact header in print: the on-screen sizes (h4 title + overline kicker)
       are too tall for paper and, combined with the browser's own print header,
       push rows onto a second page. Shrink the type, drop the redundant kicker,
       and tighten the spacing so the grid gets the vertical room. */
    .cps-header { padding-bottom: 6px; margin-bottom: 8px; gap: 16px; }
    .cps-kicker { display: none; }
    .cps-title { font-size: 1.35rem; line-height: 1.1; }
    .cps-subtitle { font-size: 0.8rem; }
    .cps-stat-label { font-size: 0.6rem; }
    .cps-stat-value { font-size: 0.8rem; }
    .cps-footer { margin-top: 8px; padding-top: 6px; font-size: 0.7rem; }

    /* No grid-level page-break-avoid: it used to bump the whole table past the
       header onto a blank second page. With the one-page fit the table no longer
       paginates anyway. */
    .cps-grid { font-size: 0.78rem; }
    .cps-grid thead th { font-size: 0.7rem; padding: 4px 4px; }
    /* Tight rows: small padding and line-height keep each booking compact so
       the whole day fits one page with room to spare. */
    .cps-cell { padding: 2px 4px; height: auto; }
    .cps-time-cell { padding: 2px 6px; }
    .cps-cell-time, .cps-cell-session, .cps-cell-booker, .cps-cell-notes { line-height: 1.2; }
    .cps-cell-session, .cps-cell-booker, .cps-cell-notes { margin-top: 1px; }
    /* No content-height cap: rows take their natural (compact) height and notes
       render in full. The one-page fit now relies on the tight rows + compact
       header above, not on clipping. */
    .cps-cell-time, .cps-cell-session, .cps-cell-booker { font-size: 0.72rem; }
    .cps-cell-notes { font-size: 0.66rem; }
    .cps-grid tr { page-break-inside: avoid; }

    /* B&W-friendly fills: replace the screen pastel tints with gray patterns
       and distinct borders so cells stay visually separable on monochrome
       printers. The text labels (time, session type, booker, "Closed") still
       carry the meaning; the patterns are visual reinforcement that survives
       single-channel output. */
    .cps-reservation {
        background: #F3F4F6;
        border-top: 2px solid #1F2937;
    }
    .cps-league-slot {
        background:
            radial-gradient(#9CA3AF 1px, transparent 1.5px) 0 0 / 7px 7px,
            #FAFAFA;
        border-top: 2px dashed #1F2937;
    }
    .cps-closure {
        background: repeating-linear-gradient(135deg,
            #D1D5DB,
            #D1D5DB 4px,
            #FFFFFF 4px,
            #FFFFFF 10px);
        border: 1px dashed #1F2937;
    }
    .cps-unavailable {
        background: repeating-linear-gradient(45deg,
            #E5E7EB,
            #E5E7EB 5px,
            #FFFFFF 5px,
            #FFFFFF 10px);
    }
    .cps-time-cell {
        background: #E5E7EB;
    }
    .cps-grid thead th {
        background: #D1D5DB;
    }

    .cps-reservation, .cps-league-slot, .cps-closure, .cps-unavailable, .cps-time-cell, .cps-grid thead th {
        print-color-adjust: exact;
        -webkit-print-color-adjust: exact;
    }
}

/* App-bar tenant logo. Lives in global CSS (not MainLayout.razor.css)
   because the class is applied to <img> rendered by MudImage, which
   sits in a different component scope and would not match Blazor's
   scoped-CSS attribute selector. */
.app-bar-logo {
    height: 60px;
    object-fit: contain;
}

/* Clickable wrapper around the tenant logo. The hover feedback is intentionally
   subtle — Court Series is a refined aesthetic, so a soft scale + brightness
   lift signals interactivity without being playful. The :active state pulls
   back slightly for a tactile press feel. */
.app-bar-logo-link {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1),
                filter 0.18s cubic-bezier(0.4, 0, 0.2, 1);
    transform-origin: left center;
    will-change: transform;
}

.app-bar-logo-link:hover {
    transform: scale(1.025);
    filter: brightness(1.08);
}

.app-bar-logo-link:active {
    transform: scale(0.985);
}

.app-bar-logo-link:focus-visible {
    outline: 2px solid var(--mud-palette-secondary);
    outline-offset: 4px;
    border-radius: 4px;
}

/* Language picker menu — refined two-column row: native name on the left,
   small letter-spaced ISO code chip on the right. The chip uses a tabular
   monospace stack so EN / SR align perfectly across rows. */
.lang-menu-item {
    min-width: 200px;
}

.lang-menu-item__label {
    flex: 1 1 auto;
}

.lang-menu-item__label--active {
    font-weight: 600;
    color: var(--mud-palette-secondary);
}

.lang-menu-item__code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    padding: 2px 8px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 12%, transparent);
    color: var(--mud-palette-text-secondary);
}

/* On narrow viewports (mobile browsers and MAUI native host),
   shrink the tenant logo so the right-side app-bar actions
   (ThemeToggle, LanguagePicker, NotificationMenu, user menu)
   stay reachable. Using max-height + max-width with height/width
   auto preserves the intrinsic aspect ratio for any tenant-uploaded
   logo — wide wordmarks are width-bounded, square/tall logos are
   height-bounded, and small icons are not upscaled.
   MudBlazor has no responsive prop for this, hence the media query. */
@media (max-width: 599px) {
    .app-bar-logo {
        height: auto;
        width: auto;
        max-height: 40px;
        max-width: 28vw;
    }

    /* Trim the default toolbar gutters and icon-button padding so the dark-mode
       ThemeToggle (#910) fits alongside the existing actions without wrapping
       or pushing the user menu off-screen. 8px padding keeps a ~40px touch
       target on the icon buttons. */
    .mud-appbar .mud-toolbar {
        padding-left: 8px;
        padding-right: 8px;
    }

    .mud-appbar .mud-icon-button {
        padding: 8px;
    }
}

/* Consolation eligibility row — highlights the row belonging to
   the current logged-in player. MudBlazor doesn't expose a per-row
   "this is the current user" tint primitive; this uses the AceTeal
   accent token from the Court Series palette. */
.consolation-row-current-player {
    background-color: var(--teal-tint-10);
}

/* App footer — stays at the bottom of MudMainContent, separated from page
   content by a thin divider. Margin-top auto allows the body to push the
   footer down on short pages without breaking when content overflows.
   MudBlazor doesn't ship a layout footer slot, so this is a global rule
   on a small <footer> wrapper rather than a MudBlazor utility. */
.app-footer {
    margin-top: auto;
}

.app-footer .mud-container {
    padding-block: 0.75rem;
}

@media print {
    .app-footer {
        display: none !important;
    }
}

/* ============================================================
   Analytics — Court utilisation heatmap (#307)
   ============================================================
   Lives in app.css rather than the component's .razor.css because
   this project does not load Blazor's scoped-CSS bundle from
   index.html — only app.css. Class names are prefixed cr-heat- so
   they remain collision-free. */

/* 5-step utilisation ramp */
.cr-heat-bg--l0 { background-color: var(--heat-l0); color: var(--mud-palette-text-secondary); }
.cr-heat-bg--l1 { background-color: var(--heat-l1); color: var(--heat-fg-light); }
.cr-heat-bg--l2 { background-color: var(--heat-l2); color: var(--heat-fg-light); }
.cr-heat-bg--l3 { background-color: var(--heat-l3); color: var(--heat-fg-dark); }
.cr-heat-bg--l4 { background-color: var(--heat-l4); color: var(--heat-fg-dark); }
.cr-heat-bg--closed {
    background-color: var(--heat-closed-bg);
    background-image: repeating-linear-gradient(
        135deg,
        var(--heat-closed-stripe) 0,
        var(--heat-closed-stripe) 3px,
        transparent 3px,
        transparent 7px
    );
    color: transparent;
}

/* KPI strip */
.cr-heat-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
}
@media (max-width: 768px) {
    .cr-heat-stats { grid-template-columns: repeat(2, 1fr); }
}
.cr-heat-stat {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.cr-heat-stat__label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}
.cr-heat-stat__value {
    font-size: 26px;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--mud-palette-primary);
    font-variant-numeric: tabular-nums;
}
.cr-heat-stat__value sup {
    font-size: 14px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    margin-left: 2px;
}
.cr-heat-stat__hint {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}
.cr-heat-stat--gold .cr-heat-stat__value { color: var(--mud-palette-tertiary); }
.cr-heat-stat--teal .cr-heat-stat__value { color: var(--mud-palette-secondary); }
.cr-heat-stat--navy .cr-heat-stat__value { color: var(--mud-palette-primary); }

/* Filter row */
.cr-heat-filter-label {
    font-weight: 700 !important;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    min-width: 64px;
}

/* Hero card header */
.cr-heat-court-tag {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    background: var(--teal-tint-10);
    color: var(--mud-palette-secondary);
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
}
.cr-heat-legend {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.cr-heat-legend__ramp {
    display: inline-flex;
    border-radius: 4px;
    overflow: hidden;
    box-shadow: 0 0 0 1px var(--border-light);
}
.cr-heat-legend__step {
    width: 18px;
    height: 12px;
}

/* Hero grid: hours x days */
.cr-heat-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 0 -4px;
    padding: 0 4px 4px;
}
.cr-heat-grid {
    display: grid;
    gap: 3px;
    min-width: max-content;
}
.cr-heat-corner { background: transparent; }
.cr-heat-hour {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding-bottom: 4px;
    font-size: 11px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}
.cr-heat-day {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--mud-palette-surface, #fff);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--mud-palette-primary);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.cr-heat-cell {
    /* Reset only what a <button> needs reset — using `all: unset` would also
       wipe out the background-color set by .cr-heat-bg--lN classes that paint
       the cell, which is the whole point of the heatmap. */
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    padding: 0;
    font-family: inherit;
    color: inherit;
    box-sizing: border-box;
    height: 44px;
    border-radius: 5px;
    border: 1px solid var(--border-subtle);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: transform 100ms ease, box-shadow 100ms ease;
}
.cr-heat-cell:hover:not(:disabled):not(.cr-heat-cell--closed) {
    transform: scale(1.08);
    box-shadow: 0 0 0 2px var(--mud-palette-primary), var(--shadow-md);
    z-index: 2;
}
.cr-heat-cell:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 1px;
    z-index: 2;
}
.cr-heat-cell--closed { cursor: not-allowed; }
.cr-heat-cell--peak {
    box-shadow: 0 0 0 2px var(--mud-palette-tertiary), 0 0 0 4px var(--mud-palette-surface, #fff);
    z-index: 1;
}
.cr-heat-cell__num { pointer-events: none; }

@media (max-width: 768px) {
    /* Mobile: hide numeric labels — cells too small for legible numbers.
       Hover/tap reveals the percentage via the cell's aria-label and the
       browser's accessibility tooltip. */
    .cr-heat-cell { height: 36px; font-size: 0; }
    .cr-heat-cell__num { font-size: 0; }
}

/* Callouts under hero */
.cr-heat-callouts {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-top: 14px;
}
@media (max-width: 640px) {
    .cr-heat-callouts { grid-template-columns: 1fr; }
}

/* Per-court small multiples — the grid is now a <MudGrid> (#919); the
   buttons keep their own styling below. */
.cr-heat-mini {
    /* Same rationale as .cr-heat-cell — selective reset, no `all: unset`. */
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    font-family: inherit;
    color: inherit;
    text-align: left;
    box-sizing: border-box;
    display: block;
    width: 100%;
    border: 1px solid var(--border-light);
    border-radius: 10px;
    padding: 12px;
    cursor: pointer;
    transition: all 120ms ease;
    background: var(--mud-palette-surface, #fff);
}
.cr-heat-mini:hover {
    border-color: var(--mud-palette-primary);
    box-shadow: var(--shadow-sm);
}
.cr-heat-mini--active {
    border-color: var(--mud-palette-secondary);
    box-shadow: 0 0 0 1px var(--mud-palette-secondary);
}
.cr-heat-mini__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.cr-heat-mini__name {
    font-size: 12px;
    font-weight: 600;
    color: var(--mud-palette-primary);
}
.cr-heat-mini__pct {
    font-size: 12px;
    font-weight: 700;
    color: var(--mud-palette-secondary);
    font-variant-numeric: tabular-nums;
}
.cr-heat-mini__grid {
    display: grid;
    gap: 1px;
    grid-auto-rows: 1fr;
}
.cr-heat-mini__cell {
    aspect-ratio: 1;
    border-radius: 1px;
    min-height: 6px;
}

/* Mobile report-selector chip strip (#307) — horizontal scrollable
   row that takes the place of the desktop sidebar on small screens. */
.cr-reports-chip-strip {
    flex-wrap: nowrap;
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px;
    align-items: center;
    /* `safe center` falls back to flex-start when the strip overflows so the
       leftmost chips stay reachable; modern browsers honour this. */
    justify-content: safe center;
    scrollbar-width: thin;
}
.cr-reports-chip-strip::-webkit-scrollbar {
    height: 4px;
}
.cr-reports-chip-strip::-webkit-scrollbar-thumb {
    background: var(--navy-tint-30);
    border-radius: 2px;
}
.cr-reports-chip-strip > * {
    flex: 0 0 auto;
}
/* Chip labels were getting clipped on small viewports because the chip used
   the dense default (~30px tall). Bump touch-target size and keep the label
   on a single line so the report name stays readable. */
.cr-reports-chip-strip .mud-chip {
    min-height: 36px;
    font-size: 0.875rem;
}
.cr-reports-chip-strip .mud-chip .mud-chip-content {
    white-space: nowrap;
}

/* Analytics — Member activity report (#307 PR 2) */
.cr-mac-count {
    font-size: 16px;
    font-weight: 700;
    color: var(--mud-palette-secondary);
}
.cr-mac-secondary { color: var(--mud-palette-text-secondary); }
.cr-mac-warn { color: var(--mud-palette-tertiary); font-weight: 600; }

/* Analytics — No-show report (#307 PR 3) */
.cr-noshow-username {
    font-size: 18px !important;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cr-noshow-count {
    font-size: 16px;
    font-weight: 700;
    color: var(--mud-palette-tertiary);
}
.cr-noshow-rate {
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}
.cr-noshow-rate--mid  { color: var(--mud-palette-warning); }
.cr-noshow-rate--high { color: var(--mud-palette-error); font-weight: 700; }

.cr-noshow-bar {
    position: relative;
    width: 100%;
    min-width: 80px;
    height: 6px;
    background: var(--navy-tint-4);
    border-radius: 3px;
    overflow: hidden;
}
.cr-noshow-bar__fill {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, var(--mud-palette-warning), var(--mud-palette-error));
    border-radius: 3px;
    transition: width 600ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Analytics — Member tier distribution (#307 PR 4) */
.cr-mtd-stack {
    display: flex;
    width: 100%;
    height: 18px;
    border-radius: 9px;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px var(--border-light);
}
.cr-mtd-stack__seg {
    height: 100%;
    transition: filter 140ms ease;
}
.cr-mtd-stack__seg:hover { filter: brightness(0.92); }

.cr-mtd-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.cr-mtd-row {
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid var(--border-subtle);
    background: var(--mud-palette-surface, #fff);
}
.cr-mtd-row__head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}
.cr-mtd-row__dot {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex: 0 0 auto;
}
.cr-mtd-row__name {
    flex: 1 1 auto;
    font-size: 14px;
    font-weight: 600;
    color: var(--mud-palette-primary);
}
.cr-mtd-row__count {
    font-size: 18px;
    font-weight: 700;
    color: var(--mud-palette-primary);
    font-variant-numeric: tabular-nums;
}
.cr-mtd-row__bar {
    height: 6px;
    border-radius: 3px;
    background: var(--navy-tint-4);
    overflow: hidden;
    margin-bottom: 4px;
}
.cr-mtd-row__bar-fill {
    display: block;
    height: 100%;
    border-radius: 3px;
    transition: width 600ms cubic-bezier(0.4, 0, 0.2, 1);
}
.cr-mtd-row__meta {
    font-size: 12px;
    font-weight: 700;
    color: var(--mud-palette-secondary);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* ---- CalendarDateNavigator ---- */
/* Date-only picker — fixed 160px on all viewports so the field is wide enough
   to read comfortably and stays consistent across desktop and mobile. */
.cdn-datepicker {
    width: 160px;
    flex-shrink: 0;
}

/* RightAdornment slot. The outer MudPaper uses flex-wrap so when there isn't
   horizontal room the adornment drops to its own row underneath the navigator
   buttons; this rule keeps it left-aligned and gives it a small top gap when
   it wraps so the switch label doesn't visually collide with the buttons. */
.cdn-paper .cdn-adornment {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
    flex-grow: 1;
}

@media (max-width: 599px) {
    /* Tighten the gap between the buttons row and the wrapped adornment so the
       paper doesn't add extra vertical bulk on phones. */
    .cdn-paper {
        row-gap: 4px;
    }
}

/* ---- CompetitionSchedule (.competition-schedule-section) ---- */
/* The schedule-tab section is a special case of .ce-section: it lives inside
   .ce-nested-tabs-panels (the inner Group/Knockout tabs), not inside the outer
   competition-tabs-panels. The mobile edge-to-edge override at line ~3246 only
   targets ce-sections inside competition-tabs-panels, so we replicate the
   border/padding flatten here for the nested case. */
@media (max-width: 599px) {
    .ce-nested-tabs-panels .competition-schedule-section.ce-section {
        padding: 4px 0 0;
        border: 0;
        border-radius: 0;
        margin-bottom: 0;
    }
}

/* Issue #679: MudBlazor 9.1.0's snackbar pauses its auto-dismiss timer on
   pointerenter/touchstart and only resumes on pointerleave/touchend
   (see InteractionStartHandler/InteractionEndHandler in MudSnackbarElement).
   On touch devices the browser keeps a phantom pointer at the last tap
   location after a tap; when a snackbar appears over that location
   (typical after submitting a match result with the Save button at the
   bottom of the dialog and snackbars positioned at bottom-center), the
   synthetic pointerenter fires on the new snackbar but no pointerleave
   ever follows, so the timer stays paused and the snackbar covers the
   action button indefinitely. MudBlazor exposes no config to disable
   this hover-pause, so we suppress it via CSS on touch-only devices —
   the close button is opted back in so users can still dismiss manually. */
@media (hover: none) {
    .mud-snackbar {
        pointer-events: none;
    }
    .mud-snackbar .mud-snackbar-close-button,
    .mud-snackbar .mud-snackbar-action-button {
        pointer-events: auto;
    }
}

/* Issue #944: the recurring-reservation "Ends" choice uses MudToggleGroup with
   three options ("On date", "After # occurrences", "At season end"). On phone
   widths the three horizontal pills overflow the dialog. MudToggleGroup has no
   responsive flex-direction option, so we stack vertically and stretch to full
   width below 600px. */
@media (max-width: 600px) {
    .recurrence-end-toggle.mud-toggle-group {
        display: flex;
        flex-direction: column;
        width: 100%;
    }
    .recurrence-end-toggle .mud-toggle-item {
        width: 100%;
    }
}

.mud-dialog:has(.cr-nested-dialog-picker .mud-overlay-dialog) {
    transform: none !important;
    -webkit-transform: none !important;
}

/* ── Competition print sheets (ccp-*) — draws & schedule (#961) ──────────────
   Organiser-only print of the group-stage draw, knockout draw, consolation
   draw, and the selected-date schedule. Each is rendered on its own dedicated
   print route (CompetitionPrintDraw / CompetitionPrintSchedule), mirroring
   CompetitionPrintResults — so it prints in normal document flow (multi-page
   brackets paginate, page breaks work) with no off-screen overlay. The MudBlazor
   chrome is hidden in print by the shared cpr- @media print block. */
.ccp-print-page { max-width: 1000px; margin: 0 auto; padding: 16px; }
.ccp-print-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
.ccp-sheet { background: #fff; border: 1px solid var(--border-light); border-radius: 12px; padding: 28px 32px; box-shadow: var(--shadow-sm); color: #1F2937; }

/* Court Series CourtNavy / AceTeal pinned as literals (not var(--mud-palette-*))
   so the sheet keeps its colours after competitionPrint.js hoists it to a direct
   child of <body>, regardless of where the theme variables are scoped. */
.ccp-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; padding-bottom: 14px; border-bottom: 2px solid #1A3A5C; margin-bottom: 18px; }
.ccp-header-left { display: flex; flex-direction: column; gap: 4px; }
.ccp-kicker { color: #0D9488; letter-spacing: 0.08em; }
.ccp-title { margin: 0; color: #0F2440; line-height: 1.2; }
.ccp-subtitle { color: #374151; }
.ccp-series { color: #6B7280; }
.ccp-header-right { display: grid; grid-template-columns: repeat(2, auto); gap: 6px 18px; justify-content: end; }
.ccp-header-stat { display: flex; flex-direction: column; align-items: flex-end; }
.ccp-stat-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; color: #6B7280; }
.ccp-stat-value { font-size: 0.95rem; font-weight: 600; color: #1A3A5C; }

.ccp-group, .ccp-round { margin-bottom: 18px; }
.ccp-round-name { font-weight: 700; color: #0F2440; font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.04em; margin: 14px 0 6px; }
.ccp-fixtures-label { font-weight: 600; color: #4B5563; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; margin: 10px 0 4px; }

.ccp-table, .ccp-grid { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.ccp-grid { table-layout: fixed; border: 2px solid #1E293B; }
.ccp-table { border: 1px solid #CBD5E1; }
.ccp-table thead th, .ccp-grid thead th { background: var(--navy-tint-4); color: #374151; font-weight: 600; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; padding: 7px 8px; text-align: left; }
.ccp-table thead th { border: 1px solid #CBD5E1; }
.ccp-grid thead th { border: 1px solid #64748B; border-left: 2px solid #334155; border-right: 2px solid #334155; border-bottom: 2px solid #1E293B; text-align: center; }
.ccp-table td { border: 1px solid #E2E8F0; padding: 5px 8px; }

.ccp-col-seed { width: 36px; text-align: center; color: #6B7280; }
.ccp-col-num { width: 96px; text-align: center; white-space: nowrap; }
.ccp-col-team { text-align: left; word-break: break-word; }
.ccp-col-strong { font-weight: 700; color: #0F2440; }

.ccp-time-col, .ccp-time-cell { width: 64px; text-align: center; white-space: nowrap; }
.ccp-time-cell { padding: 6px; border: 1px solid #64748B; border-left: 2px solid #334155; border-right: 2px solid #334155; background: var(--navy-tint-4); font-weight: 600; color: #1A3A5C; vertical-align: top; }
.ccp-court-col { word-break: break-word; }
.ccp-grid { --ccp-row-h: 96px; }
.ccp-cell { padding: 0; border: 1px solid #64748B; border-left: 2px solid #334155; border-right: 2px solid #334155; vertical-align: top; height: var(--ccp-row-h); position: relative; }
/* Proportional match block: absolutely placed inside its hourly cell, offset down
   by the start-minute and sized by the match duration (see MatchBlockStyle), so a
   17:30 match straddles the 17:00 and 18:00 rows exactly like the on-screen grid.
   z-index lifts it over the empty cell below that it overflows into. */
.ccp-match-block { position: absolute; left: 3px; right: 3px; box-sizing: border-box; padding: 3px 5px; background: #EAF4F2; border: 1px solid rgba(13, 148, 136, 0.55); border-radius: 4px; overflow: hidden; z-index: 2; display: flex; flex-direction: column; justify-content: center; }
.ccp-cell-team { font-size: 0.66rem; color: #1F2937; text-align: center; line-height: 1.2; }
.ccp-cell-meta { display: flex; justify-content: center; align-items: baseline; gap: 5px; margin-bottom: 1px; }
.ccp-cell-time { font-size: 0.56rem; font-weight: 700; color: #0F2440; }
.ccp-cell-round { font-size: 0.54rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #1A3A5C; }
.ccp-cell-vs { font-size: 0.58rem; color: #6B7280; text-align: center; margin: 1px 0; }
.ccp-empty { background: #FFFFFF; }

.ccp-footer { margin-top: 24px; padding-top: 10px; border-top: 1px solid var(--border-subtle); color: #6B7280; font-size: 0.78rem; text-align: right; }

/* ── Visual knockout / consolation bracket print ────────────────────────────
   Mirrors the on-screen .draw-* connector tree but with static, B&W-friendly
   slots. The whole bracket is shrunk by a fit scale computed in
   CompetitionPrintBracketSheet (inline transform on .ccp-bracket); the
   .ccp-bracket-fit wrapper is sized to the *scaled* dimensions so page-break
   logic and the print page see the real footprint. */
.ccp-bracket-page { margin-bottom: 16px; }
.ccp-bracket-page-label { font-weight: 700; color: #0F2440; font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.04em; margin: 4px 0 10px; }
.ccp-bracket-fit { overflow: hidden; }
.ccp-bracket { display: flex; flex-direction: row; align-items: stretch; }
.ccp-bracket-round { display: flex; flex-direction: column; width: 176px; padding: 0 12px; }
.ccp-bracket-round:first-child { padding-left: 0; }
.ccp-bracket-round:last-child { padding-right: 0; }
.ccp-bracket-round-header { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #1A3A5C; text-align: center; padding: 4px 8px; background: var(--navy-tint-6); border-radius: 6px; margin-bottom: 8px; }
.ccp-bracket-matches { display: flex; flex-direction: column; flex: 1; }
.ccp-bracket-pair { display: flex; flex-direction: column; flex: 1; position: relative; }
.ccp-bracket-match { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 3px 0; position: relative; }
.ccp-bracket-slot { display: flex; align-items: center; gap: 5px; padding: 2px 6px; border: 1px solid #CBD5E1; background: #fff; min-height: 18px; font-size: 0.72rem; color: #1F2937; }
.ccp-bracket-slot + .ccp-bracket-slot { border-top: none; }
.ccp-bracket-slot--winner { font-weight: 700; color: #0F2440; background: rgba(13, 148, 136, 0.08); }
.ccp-bracket-pos { flex: 0 0 auto; min-width: 14px; text-align: right; color: #94A3B8; font-size: 0.62rem; font-weight: 600; }
.ccp-bracket-name { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ccp-bracket-name--tbd { color: #CBD5E1; }
.ccp-bracket-score { flex: 0 0 auto; display: flex; gap: 3px; }
.ccp-bracket-set { font-size: 0.66rem; color: #475569; min-width: 8px; text-align: center; }
.ccp-bracket-third { margin-top: 8px; }
.ccp-bracket-third-header { background: var(--navy-tint-4); color: #475569; }

/* Connectors (mirror the .draw-match-item ┐/┘ corner geometry) */
.ccp-bracket-match::before { content: ''; position: absolute; right: 100%; top: 50%; transform: translateY(-50%); width: 12px; height: 1.5px; background: #CBD5E1; }
.ccp-bracket-match::after { content: ''; position: absolute; left: 100%; top: 50%; transform: translateY(-50%); width: 12px; height: 1.5px; background: #CBD5E1; }
.ccp-bracket-pair .ccp-bracket-match:first-child:not(:last-child)::after { top: 50%; bottom: -1px; height: auto; transform: none; background: none; border-top: 1.5px solid #CBD5E1; border-right: 1.5px solid #CBD5E1; }
.ccp-bracket-pair .ccp-bracket-match:last-child:not(:first-child)::after { top: -1px; bottom: 50%; height: auto; transform: none; background: none; border-bottom: 1.5px solid #CBD5E1; border-right: 1.5px solid #CBD5E1; }
.ccp-bracket-round:first-child .ccp-bracket-match::before { display: none; }
.ccp-bracket-round:last-child .ccp-bracket-pair .ccp-bracket-match::after { display: none; }
.ccp-bracket--feeder .ccp-bracket-match::before,
.ccp-bracket--feeder .ccp-bracket-match::after { display: none; }
.ccp-bracket-third .ccp-bracket-match::before,
.ccp-bracket-third .ccp-bracket-match::after { display: none; }

@media print {
    /* The print routes are dedicated full pages, so they print in normal flow.
       The MudBlazor app chrome (appbar/drawer/etc.) is already hidden globally by
       the cpr- @media print block; here we just drop the page's own toolbar and
       the sheet's screen-only framing, and control pagination. */
    .ccp-no-print { display: none !important; }
    .ccp-print-page { max-width: 100%; margin: 0; padding: 0; }
    .ccp-sheet { border: none; box-shadow: none; border-radius: 0; padding: 0; }

    .ccp-table, .ccp-grid, .ccp-round, .ccp-group { page-break-inside: avoid; }
    .ccp-table tr, .ccp-grid tr { page-break-inside: avoid; }
    /* Force the teal match tint to render on B&W/economy printers too. */
    .ccp-match { print-color-adjust: exact; -webkit-print-color-adjust: exact; }

    /* Feeder (qualifying/repechage) and main bracket each get their own page. */
    .ccp-bracket-page--break { page-break-after: always; break-after: page; }
    .ccp-bracket-page { page-break-inside: avoid; break-inside: avoid; }
    .ccp-bracket-round-header,
    .ccp-bracket-slot--winner { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}
