h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ===== Lineup pitch (MatchDetail) =====
   Narrow: vertical pitch, home top half / away bottom half.
   Wide  : horizontal pitch, home left half / away right half.
   The away half is mirrored on the cross-axis so its GK ends up at the far edge. */
.lineup-pitch {
    background: repeating-linear-gradient(180deg, #2f7a36 0 8%, #2a6e30 8% 16%);
    border-radius: 8px;
    padding: 12px;
    color: #fff;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column; /* narrow default */
    gap: 0;
}

@media (min-width: 900px) {
    .lineup-pitch {
        flex-direction: row;
        background: repeating-linear-gradient(90deg, #2f7a36 0 8%, #2a6e30 8% 16%);
        min-height: 520px;
    }
}

/* Center line */
.lineup-pitch::before {
    content: "";
    position: absolute;
    background: rgba(255,255,255,0.45);
    pointer-events: none;
    left: 4%;
    right: 4%;
    top: 50%;
    height: 2px;
    transform: translateY(-1px);
}

@media (min-width: 900px) {
    .lineup-pitch::before {
        left: 50%;
        right: auto;
        top: 4%;
        bottom: 4%;
        height: auto;
        width: 2px;
        transform: translateX(-1px);
    }
}

/* Center circle */
.lineup-pitch::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 72px;
    height: 72px;
    border: 2px solid rgba(255,255,255,0.45);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.lineup-half {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;        /* narrow: formation rows stack vertically */
    justify-content: space-around;
    min-height: 240px;
    padding: 8px 0;
    position: relative;
}

.lineup-half.away { flex-direction: column-reverse; }

@media (min-width: 900px) {
    .lineup-half {
        flex-direction: row;       /* wide: formation rows stack horizontally */
        min-height: 0;
        padding: 0 8px;
    }
    .lineup-half.away { flex-direction: row-reverse; }
}

.lineup-row {
    display: flex;
    flex-direction: row;           /* narrow: players in a row */
    justify-content: space-around;
    align-items: flex-start;
    flex-wrap: wrap;
    flex: 1;
    gap: 8px;
    padding: 4px 8px;
}

@media (min-width: 900px) {
    .lineup-row {
        flex-direction: column;    /* wide: players in a column */
        justify-content: space-around;
        align-items: center;
        flex-wrap: nowrap;
        padding: 8px 4px;
    }
}

.lineup-team-label {
    font-weight: 600;
    font-size: 0.85rem;
    letter-spacing: 0.5px;
    color: rgba(255,255,255,0.92);
    padding: 4px 12px;
    text-align: center;
}

.lineup-player {
    width: 96px;
    min-height: 92px;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.lineup-player .lineup-name {
    display: block;
    max-width: 92px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 600;
    line-height: 1.2;
}

.lineup-player .mud-typography {
    color: #fff !important;
    line-height: 1.15;
}

.lineup-player .mud-typography-caption.lineup-stat {
    color: rgba(255,255,255,0.78) !important;
    font-size: 0.72rem;
}

.lineup-player a.mud-typography {
    color: #fff !important;
    text-decoration: none;
}
.lineup-player a.mud-typography:hover { text-decoration: underline; }

.lineup-photo-wrap {
    position: relative;
    display: inline-block;
}

/* Round chip overlays — points top-right (prominent), minutes top-left (subtle) */
.lineup-points-badge,
.lineup-minutes-badge {
    position: absolute;
    background: #1a1a1a;
    color: #fff;
    font-weight: 600;
    border-radius: 10px;
    line-height: 1.3;
    white-space: nowrap;
    box-shadow: 0 1px 2px rgba(0,0,0,0.35);
}

.lineup-points-badge {
    top: -4px;
    right: -10px;
    font-size: 0.68rem;
    padding: 1px 6px;
    border: 1px solid rgba(255,255,255,0.55);
}

.lineup-minutes-badge {
    top: -4px;
    left: -6px;
    font-size: 0.6rem;
    padding: 0 5px;
    background: rgba(0,0,0,0.55);
    color: rgba(255,255,255,0.85);
    font-weight: 500;
    border: none;
    box-shadow: none;
}

/* Event icons stacked on the bottom-left of the photo */
.lineup-events-overlay {
    position: absolute;
    bottom: -4px;
    left: -6px;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 2px;
}

.lineup-event-icon {
    width: 12px;
    height: 12px;
    border-radius: 2px;
    display: inline-block;
    box-shadow: 0 1px 2px rgba(0,0,0,0.45);
}
.lineup-event-icon.yellow { background: #f5c518; }
.lineup-event-icon.red    { background: #d13b3b; }
.lineup-event-icon.goal   {
    background: #fff;
    border-radius: 50%;
    border: 1px solid #1a1a1a;
    width: 13px;
    height: 13px;
}
.lineup-event-icon.sub-off {
    width: 0; height: 0;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
    border-top: 8px solid #d13b3b;
    background: none;
    border-radius: 0;
    box-shadow: none;
    filter: drop-shadow(0 1px 1px rgba(0,0,0,0.45));
}

/* ===== Single-team pitch (TeamSelection view & editor) =====
   Drops the center line / center circle that the two-team match pitch draws,
   and lets a single half fill the container. */
.lineup-pitch-single::before,
.lineup-pitch-single::after { content: none; }

.lineup-pitch-single { flex-direction: column; min-height: 0; }

.lineup-pitch-single .lineup-half {
    flex-direction: column;
    min-height: 360px;
}

@media (min-width: 900px) {
    .lineup-pitch-single { flex-direction: column; min-height: 0; }
    .lineup-pitch-single .lineup-half {
        flex-direction: column;
        min-height: 420px;
        padding: 8px 0;
    }
    .lineup-pitch-single .lineup-row { flex-direction: row; padding: 4px 8px; }
}

/* Captain / coach markers on a player photo */
.lineup-captain-badge,
.lineup-coach-badge {
    position: absolute;
    bottom: -4px;
    right: -6px;
    background: #1a1a1a;
    color: #fff;
    font-weight: 700;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.65rem;
    border: 1px solid rgba(255,255,255,0.65);
    box-shadow: 0 1px 2px rgba(0,0,0,0.45);
    line-height: 1;
}

.lineup-captain-badge { background: #f5c518; color: #1a1a1a; }
.lineup-coach-badge   { background: #5a3a8a; }

/* Coach row inside a lineup half. Two flavours:
   - Two-team match pitch: coach sits at the team's defensive end (far edge,
     past the GK) via order:-1 so it stays clear of the center line.
   - Single-team selection pitch (editor / public view): coach stays at the
     natural bottom-of-pitch position (after FW), reading like a touchline. */
.lineup-coach-row {
    flex: 0 0 auto;
    justify-content: center;
    padding: 4px 0;
    background: rgba(0,0,0,0.14);
}
.lineup-coach-row .lineup-player { width: 110px; }

.lineup-pitch:not(.lineup-pitch-single) .lineup-coach-row {
    order: -1;
}

.lineup-pitch-single .lineup-coach-row {
    border-top: 1px dashed rgba(255,255,255,0.35);
    margin-top: 4px;
    padding-top: 6px;
}

/* Empty / clickable slot (selection editor) */
.lineup-slot-empty {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: 2px dashed rgba(255,255,255,0.65);
    background: rgba(255,255,255,0.08);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: rgba(255,255,255,0.85);
    font-weight: 600;
    font-size: 0.78rem;
}

.lineup-slot-clickable { cursor: pointer; }
.lineup-slot-clickable:hover .lineup-slot-empty,
.lineup-slot-clickable:hover .lineup-photo-wrap {
    filter: brightness(1.15);
    transition: filter 120ms;
}

/* Bench (squad players not in lineup) */
.lineup-bench {
    margin-top: 12px;
    transition: background-color 120ms, outline 120ms;
}
.lineup-bench .lineup-bench-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}
.lineup-bench-chip {
    display: inline-flex;
    cursor: grab;
}
.lineup-bench-chip:active { cursor: grabbing; }

/* Drag-and-drop visual feedback */
.lineup-slot-droppable { cursor: grab; }
.lineup-slot-droppable:active { cursor: grabbing; }

/* While a drag is in progress, every droppable slot pulses to show it's a target. */
.lineup-slot-droppable.lineup-drop-active .lineup-photo-wrap::before {
    content: "";
    position: absolute;
    inset: -6px;
    border: 2px dashed rgba(255,255,255,0.55);
    border-radius: 50%;
    pointer-events: none;
    animation: lineup-drop-pulse 1.2s ease-in-out infinite;
}
@keyframes lineup-drop-pulse {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 1; }
}

/* Bench is highlighted as a "remove" target while a starter is being dragged. */
.lineup-bench-drop-active {
    outline: 2px dashed var(--mud-palette-error, #f44336);
    outline-offset: -4px;
    background-color: rgba(244, 67, 54, 0.06);
}

/* Slots that don't match the dragged player's position get a muted "no" outline
   so the user immediately sees where dropping will succeed vs fail. */
.lineup-slot-droppable.lineup-drop-invalid .lineup-photo-wrap::before {
    content: "";
    position: absolute;
    inset: -6px;
    border: 2px dashed rgba(244, 67, 54, 0.55);
    border-radius: 50%;
    pointer-events: none;
}
.lineup-slot-droppable.lineup-drop-invalid {
    opacity: 0.55;
    cursor: not-allowed;
}

/* Bench column variant — sits to the right of the pitch as a transparent
   container so the bench just floats next to the pitch. Min-height matches
   the pitch so drag-targets line up. */
.lineup-bench-side {
    background-color: transparent;
    padding: 8px;
    min-height: 360px;
}
/* Inside the right-side bench, lay players out as a wrapping grid of circular
   chips that match the pitch styling. */
.lineup-bench-side .lineup-bench-row {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 8px;
}
/* Bench player chip when shown on the right column — same circular slot
   appearance as on the pitch. The dragged-from-bench source still inherits
   the cursor and pulse animation classes. */
.lineup-bench-side .lineup-bench-player {
    width: 70px;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    cursor: grab;
}
.lineup-bench-side .lineup-bench-player:active { cursor: grabbing; }
.lineup-bench-side .lineup-bench-player .lineup-name {
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The pitch sets `.lineup-player .mud-typography { color: #fff }` so names
   are legible against the green grass. The bench paper is transparent
   (white background), so the same rule renders invisible text. Re-color
   the bench typography to a normal foreground colour. */
.lineup-bench-side .lineup-player .mud-typography {
    color: rgba(0, 0, 0, 0.87) !important;
}

/* Tournament-points overlay on a player chip in the editor. */
.lineup-points-badge {
    position: absolute;
    top: -6px;
    left: -6px;
    background: rgba(34, 139, 230, 0.95);
    color: #fff;
    font-weight: 700;
    border-radius: 10px;
    padding: 0 6px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    font-size: 0.65rem;
    border: 1px solid rgba(255,255,255,0.65);
    box-shadow: 0 1px 2px rgba(0,0,0,0.45);
    line-height: 1;
}

/* Player photo with a position-coloured ring. Used in the Players & Bids
   table as the first column, replacing the old solid-color "abbrev box".
   Falls back to the position abbreviation when there's no PhotoUrl, so the
   colour cue still works for unsync'd players. */
.player-photo-pos {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--mud-palette-action-disabled-background, #e0e0e0);
    color: var(--mud-palette-text-primary);
    font-weight: 700;
    font-size: 0.8rem;
    line-height: 1;
    text-decoration: none;
    box-sizing: border-box;
}
.player-photo-pos img { width: 100%; height: 100%; object-fit: cover; }
.player-photo-pos.position-goalkeeper { border-color: var(--mud-palette-warning, #ffc107); }
.player-photo-pos.position-defender   { border-color: var(--mud-palette-info, #2196f3); }
.player-photo-pos.position-midfielder { border-color: var(--mud-palette-success, #4caf50); }
.player-photo-pos.position-attacker   { border-color: var(--mud-palette-error, #f44336); }
.player-photo-pos.position-coach      { border-color: var(--mud-palette-dark, #424242); }

/* Wrapper for player-photo + team-logo overlay. The overlay sits at the
   bottom-right of the photo as a small clickable team badge — hover shows
   the team name (via title), click navigates to the team page. */
.player-photo-wrap {
    position: relative;
    width: 36px;
    height: 36px;
    display: inline-block;
}
.player-team-overlay {
    position: absolute;
    bottom: -3px;
    right: -3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-divider);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0,0,0,0.25);
    text-decoration: none;
}
.player-team-overlay img {
    width: 16px;
    height: 16px;
    object-fit: contain;
}

/* Inline points caption shown next to the player name on phones (the
   dedicated points column is `pc-hide-narrow` so phones lose it). On
   desktop the dedicated column is the source of truth and the inline
   variant is hidden to avoid duplication. */
.player-points-inline {
    color: var(--mud-palette-text-secondary);
    font-size: 0.85em;
    margin-left: 8px;
    white-space: nowrap;
    display: none;
}
@media (max-width: 599px) {
    .player-points-inline { display: inline; }
}

/* Inline bid input — replaces the bid button (and the dialog popup it
   used to open) when a row enters bid mode. Tight numeric input that
   slots into the action cell; size matches a Size.Small button so the
   row height doesn't jump as the cell content swaps. */
.inline-bid-stack {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}
.inline-bid-input {
    width: 160px;
    height: 32px;
    padding: 4px 8px;
    border: 1px solid var(--mud-palette-primary, #594ae2);
    border-radius: 4px;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary);
    font-size: 0.875rem;
    line-height: 1.2;
    box-sizing: border-box;
    /* Native number-input spinners eat horizontal space; the user can
       still type numbers, the +/- arrows aren't worth the width on a
       narrow row. */
    -moz-appearance: textfield;
}
.inline-bid-input::-webkit-outer-spin-button,
.inline-bid-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.inline-bid-input:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(89, 74, 226, 0.25);
}

/* Mobile: the bid button is hidden because the whole row is the tap
   target (OnRowClick triggers inline-bid mode). The button stays on
   desktop so users with mice get a visible affordance. */
@media (max-width: 599px) {
    .bid-action-btn { display: none !important; }
    .inline-bid-input { width: 100%; min-width: 80px; }
    .inline-bid-stack { width: 100%; }
}

/* Subtle highlight for the rows the current user owns on the All Agents tab.
   Replaces the per-row "Yours" chip — easier to scan, less visual noise. */
.mud-table-row.row-mine {
    background-color: rgba(94, 53, 177, 0.07);
}
.mud-table-row.row-mine:hover {
    background-color: rgba(94, 53, 177, 0.12) !important;
}
.mud-table-row.row-mine td:first-child {
    border-left: 3px solid var(--mud-palette-primary, #5e35b1);
}

/* Country / club mini-badge under the player photo. */
.lineup-team-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    background: rgba(255,255,255,0.92);
    border-radius: 50%;
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(0,0,0,0.25);
    box-shadow: 0 1px 2px rgba(0,0,0,0.45);
    overflow: hidden;
}
.lineup-team-badge img {
    width: 16px;
    height: 16px;
    object-fit: contain;
}

/* ===== Players & Bids: sticky tabs / filter / pager =====
   Pinned chrome on the catalog page so the tab labels and the filter
   toggle stay visible while the player list scrolls, and the pager
   stays one tap away at the bottom. Filter bar is collapsed by default
   (`pc-filter-toggle`); the active-filter count chip in the toggle
   tells users whether results are filtered without expanding the bar.
   `.mud-tabs` ships with `overflow: hidden` which clips any sticky
   descendant — override to visible inside .players-table-page so the
   tab toolbar / filter toggle / pager can pin themselves. */
@media (max-width: 599px) {
    .mud-tabs,
    .mud-tabs-panels,
    .mud-tab-panel {
        overflow: visible !important;
    }
    .mud-tabs > .mud-tabs-tabbar {
        position: sticky;
        top: 56px; /* below the fixed AppBar */
        z-index: 4;
        background: var(--mud-palette-surface);
    }
    /* Sentinel below the visible-rows window. Empty when the user has
       scrolled to the end (no spinner shown); otherwise renders a small
       spinner + "X / Y" hint while the next batch is being prepared. */
    .pc-load-sentinel {
        height: 48px;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        color: var(--mud-palette-text-secondary);
        font-size: 0.85rem;
    }

    .pc-filter-toggle {
        position: sticky;
        top: 104px; /* AppBar 56 + tabs toolbar ~48 */
        z-index: 3;
        background: var(--mud-palette-surface);
        padding: 0;
        /* The first row's own top divider provides separation;
           an additional border here just stacks on top. */
    }
    /* Trim the MudButton inside the toggle so it doesn't add 8-12px of
       its own dead space — the toggle row is just a tappable strip. */
    .pc-filter-toggle .mud-button-root {
        padding: 4px 8px !important;
        min-height: 32px;
    }
}

/* ===== Edge-to-edge tables on phones =====
   Five nested layers (`pa-md-4 px-1`, MudContainer, MudTabs `pa-4`,
   `mud-tabs-panels`, MudTabPanel content + the row's own padding) each
   add 4px or more of horizontal padding, so the actual row content sits
   24-32px in from the viewport edge — pure waste on a 375px screen.
   Zero out every outer layer so only the TR's own 4px padding remains. */
@media (max-width: 599px) {
    /* MainLayout's outer page wrapper — the `py-3` adds 12px above the
       page content; on phones we want the tabs/filter row to butt up
       against the AppBar instead of floating below a gap. */
    .mud-main-content > .pa-md-4 {
        padding-left: 0 !important;
        padding-right: 0 !important;
        padding-top: 0 !important;
    }
    /* MudContainer adds 16px top padding by default — kill it so the
       tabs sit flush against the AppBar. */
    .mud-container {
        padding-left: 0 !important;
        padding-right: 0 !important;
        padding-top: 0 !important;
    }
    /* AppBar drop-shadow renders as a faint gray strip below the bar
       on phones, reads like a spacing gap. Remove on mobile. */
    .mud-appbar {
        box-shadow: none !important;
    }
    /* MudTabs and its inner panel wrappers. The `pa-4` class on the
       page's tab container adds 16px on all sides — override every
       direction so the tabs sit flush against the AppBar above. */
    .mud-tabs.pa-4,
    .mud-tabs .mud-tab-content,
    .mud-tabs .mud-tabs-toolbar,
    .mud-tabs .mud-tabs-panels,
    .mud-tabs .mud-tab-panel {
        padding: 0 !important;
    }
    /* Wide tables don't need rounded corners cutting their content. */
    .mud-paper > .mud-table-container,
    .mud-paper > .mud-table {
        border-radius: 0;
    }
}

/* ===== No horizontal table scroll on phones =====
   MudBlazor's `.mud-table-container` ships with `overflow-x: auto` so wide
   tables get an internal horizontal scrollbar. On phones we want columns
   to share the viewport instead — we'd rather hide low-priority columns
   (`pc-hide-narrow`) and let the rest reflow. `table-layout:fixed` makes
   columns share width equally so a long cell doesn't push others out of
   view. Avoid forcing word-break globally — it shatters action-button
   text into one-character-per-line. Cells that should ellipsis-truncate
   apply `match-team-name` (or similar) explicitly. */
@media (max-width: 599px) {
    .mud-table-container {
        overflow-x: visible;
    }
    .mud-table-container > table {
        table-layout: fixed;
        width: 100%;
    }
}

/* ===== Players & Bids: card-grid rows on phones =====
   The All Agents / Free Agents catalog has 11 / 4 columns. On phones, even
   after `pc-hide-narrow` collapses to 5 / 4 cells, MudBlazor's stacked
   layout produces an awkward column of orphan values per row. We instead
   keep the table markup (`Breakpoint=None`) and re-flow each `<tr>` into a
   2-row card via CSS grid:

       [Pos]  Player name           [Bid]
              Team logo + name      Status

   `display: contents` on the rendered <tr> would lose the row context, so we
   preserve `<tr>` as the grid container and place visible cells via
   `:nth-child` (cells with `pc-hide-narrow` are already `display: none`). */
@media (max-width: 599px) {
    .players-table thead { display: none !important; }
    .players-table .mud-table-container,
    .players-table table {
        display: block !important;
        width: 100% !important;
    }
    .players-table tbody {
        display: block !important;
        width: 100% !important;
    }
    .players-table tbody tr {
        display: grid !important;
        grid-template-columns: 44px minmax(0, 1fr) auto;
        grid-template-areas:
            "pos name action"
            "pos name status";
        column-gap: 8px;
        row-gap: 2px;
        padding: 6px 4px;
        border-bottom: 1px solid var(--mud-palette-divider);
        align-items: center;
        width: 100%;
        box-sizing: border-box;
        min-height: 56px;
    }
    .players-table tbody tr td {
        display: flex !important;
        align-items: center;
        padding: 0 !important;
        border: none !important;
        min-width: 0;
    }
    /* Re-hide secondary columns: my display:flex above shadows pc-hide-narrow. */
    .players-table tbody tr td.pc-hide-narrow {
        display: none !important;
    }
    /* All Agents columns after dropping the Team column:
       Photo(1) Name(2) Pts(3h) Owner(4h) Price(5h) Deadline(6h) Status(7) YourBid(8h) Action(9) */
    .players-table tbody tr td:nth-child(1) { grid-area: pos; justify-content: center; }
    .players-table tbody tr td:nth-child(2) { grid-area: name; min-width: 0; flex-wrap: wrap; gap: 4px; }
    .players-table tbody tr td:nth-child(7) { grid-area: status; justify-content: flex-end; }
    .players-table tbody tr td:nth-child(9) { grid-area: action; justify-content: flex-end; }
    /* Free Agents (3 cols: Pos / Name / Action) and MySquad roster
       (3 cols: Photo / Name+points / Price-paid) share a single-row
       grid since neither carries a status row below the action area. */
    .players-table-free tbody tr,
    .players-table-squad tbody tr {
        grid-template-areas: "pos name action";
    }
    .players-table-squad tbody tr td:nth-child(3) { grid-area: action; justify-content: flex-end; }
    /* Owned-by-me rows already wear a `row-mine` purple tint and surface
       a HISTORY link in the action cell — the redundant "Assigned" chip
       was the only thing pushing them to a 2-row layout (taller than
       Available rows). Hide it on mobile and collapse the grid back to
       a single row so heights match. */
    .players-table tbody tr.row-mine {
        grid-template-areas: "pos name action";
    }
    .players-table tbody tr.row-mine td:nth-child(7) {
        display: none !important;
    }

    /* Bid-mode replaces everything except the photo cell with the input.
       Only Photo (col 1) and Action (col 9 — holds the input) remain
       visible; Name / Points / Status / etc. are hidden so the input
       takes the entire remaining row width. Row height stays the same. */
    .players-table tbody tr.bid-mode {
        grid-template-columns: 44px minmax(0, 1fr);
        grid-template-areas: "pos action";
    }
    .players-table tbody tr.bid-mode td:nth-child(2),
    .players-table tbody tr.bid-mode td:nth-child(7) {
        display: none !important;
    }
    .players-table tbody tr.bid-mode td:nth-child(9) {
        grid-area: action;
        justify-content: stretch;
    }
    .players-table tbody tr.bid-mode .inline-bid-stack {
        width: 100%;
        gap: 4px;
    }
    .players-table tbody tr.bid-mode .inline-bid-input {
        flex: 1;
    }
    /* Free Agents (3 cells: 1=photo, 2=name, 3=action). */
    .players-table-free tbody tr.bid-mode td:nth-child(2) {
        display: none !important;
    }
    .players-table-free tbody tr.bid-mode td:nth-child(3) {
        grid-area: action;
        justify-content: stretch;
    }
    .players-table-free tbody tr td:nth-child(2) { grid-area: name; min-width: 0; }
    .players-table-free tbody tr td:nth-child(3) { grid-area: action; justify-content: flex-end; }
    /* Long player / team names need ellipsis since the flex cell won't size. */
    .players-table tbody tr td .mud-link,
    .players-table tbody tr td span {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    /* Pager remains a separate row below the grid. */
    .players-table tfoot { display: block; }
    .players-table tfoot tr { display: block; padding: 4px; }
}

/* ===== MySquad position-group header =====
   Tight one-line header that introduces each position group on the squad
   roster. Replaces the heavy `Typo.h6` chip+count line — same info, but
   ~16px tall instead of ~32px, with no top margin to crowd the previous
   group's last row. */
.squad-position-header {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 4px 2px;
    font-size: 0.85rem;
    line-height: 1;
}
.squad-position-count {
    color: var(--mud-palette-text-secondary);
    font-size: 0.8rem;
}

/* ===== Competition stats inside the user-icon dropdown =====
   The CompetitionInfoBar used to live as a permanent strip below the
   AppBar (3 outlined chips). Since the user-icon menu already has
   Profile / Logout, we tuck the stats above those items so the chrome
   is gone on every page but the values are still one tap away. */
.user-menu-stat-row {
    display: grid;
    grid-template-columns: 24px 1fr auto;
    align-items: center;
    gap: 8px;
    padding: 6px 16px;
    min-width: 200px;
    color: var(--mud-palette-text-primary);
    font-size: 0.875rem;
    line-height: 1.3;
    pointer-events: none; /* Stat rows aren't actionable */
}
.user-menu-stat-label {
    color: var(--mud-palette-text-secondary);
}
.user-menu-stat-value {
    font-weight: 600;
    text-align: right;
    white-space: nowrap;
}

/* ===== Notification badge inside MudAppBar =====
   MudBadge default offset is top:-8/right:-8 which clips above the AppBar
   (badge sits at y:-4 in a 56px-tall bar starting at y:0). Pull it inward
   so the count stays visible on phones. */
.mud-appbar .mud-badge.mud-badge-top.right {
    top: 4px;
    right: 4px;
}

/* ===== Responsive column hiding =====
   Wide MudTables (8+ columns) overflow horizontally on phones. Apply
   pc-hide-narrow to MudTh + MudTd of lower-priority columns so the
   essentials stay readable without scrolling under 600px.
   Used by: PlayerCatalog (All Agents tab), Admin/Players. */
@media (max-width: 599px) {
    .pc-hide-narrow {
        display: none !important;
    }
}

/* ===== Responsive table wrapper =====
   For MudTables that have meaningful column headers (e.g. point rules
   per position, score-per-round) and where MudBlazor's default
   responsive stacking strips the headers and produces orphan values.
   Pair with `Breakpoint="Breakpoint.None"` on the MudTable: the table
   keeps its desktop layout and overflows horizontally inside this
   wrapper, so the user swipes within the table instead of seeing
   stacked context-less values. */
.responsive-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    width: 100%;
}

/* ===== Team-name truncation in match tables =====
   Long team names (e.g. "Bosnia & Herzegovina") need ellipsis inside narrow
   table cells so they don't push the table wider than the viewport. */
.match-team-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    display: inline-block;
    max-width: 100%;
}

/* ===== Match-row reflow on phones =====
   The CompetitionMatches / PlayerDetail breakdown rows lay out as
   `MudStack Row="true"` with fixed-min-width inner divs that sum to
   >320px and break a 311px container at 375px viewport. Allow the
   stack to wrap onto multiple lines under 600px while keeping the
   single-line desktop layout intact. */
@media (max-width: 599px) {
    .match-row-wrap {
        flex-wrap: wrap;
    }
}