/**
 * FPLyzer — Manual Squad Builder ("Build Your Own" mode)
 * =============================================================================
 * docs/MANUAL_SQUAD_BUILDER_PLAN.md B.3 (pitch/slots/summary), B.4 (search &
 * filter panel), B.5 (XI/bench/formation/captain, drag + tap-swap).
 *
 * Reuses the existing `.squad-pitch` / `.squad-player-card` / `.squad-bench`
 * layout from templates/wildcard_wrapper.html so both modes read as one page
 * (B.0.1) — this file only adds the empty-slot control, the remove
 * affordance, the summary/controls bar and the search panel that sits
 * beside (desktop) or below (phone) the pitch.
 *
 * ── Breakpoints (B.8.4) ─────────────────────────────────────────────────────
 * Two sets are in play here, and mixing them up is what makes a pitch go
 * ragged, so they are named:
 *
 *   • LAYOUT — 1024 / 768 / 480 / 360 px, the house contract already in use in
 *     season-calendar.css and header.css. Everything that is *this component's*
 *     own furniture uses these: the side-panel↔drawer switch, the sticky
 *     summary bar, the touch-target floor.
 *
 *   • PITCH CARDS — 768 / 540 / 400 px, the breakpoints wildcard_wrapper.html's
 *     own `<style>` block already resizes `.squad-player-card` at. An empty
 *     slot sits in the same row as a filled card, so it MUST track the card's
 *     widths at the card's breakpoints. Sizing it on the layout set instead
 *     leaves a 110px slot beside a 72px card at 500px wide, and overflows the
 *     row at 360px. Neither set is new — this file just has one foot in each.
 *
 * RTL: `[dir="rtl"]` overrides are colocated with their LTR rule (the same
 * convention wildcard_wrapper.html already uses for `.wc-ai-stale`), not
 * split into rtl.css, since this is a single new component.
 *
 * Touch: every interactive element is ≥44px on a touch pointer (B.8.4). Where
 * that would make a badge visually oversized (the × and ⇅ on a player card),
 * the *hit area* is grown with a transparent `::after` and the painted glyph
 * stays small — the target is 44px, the decoration is not.
 */

/* ── Fixed-header offset for the sticky bits below, matching header.css's
   own body.has-header padding-top values at the same breakpoints ── */
:root {
    --mb-header-h: 80px;
}
@media (max-width: 768px) { :root { --mb-header-h: 70px; } }
@media (max-width: 480px) { :root { --mb-header-h: 60px; } }
/* header.css's scroll-to-hide script (_header.html) mirrors .site-header's
   own nav-hidden toggle onto body.header-hidden — collapse the offset so the
   sticky strip below docks to the real top instead of hovering over a gap
   where the (now-hidden) header used to be. */
body.header-hidden { --mb-header-h: 0px; }

/* ================================================================
   Layout — side panel beside the pitch on desktop/tablet, single
   column (drawer overlays) on phone. One DOM, one CSS switch (B.4.1).
================================================================ */
.mb-layout {
    display: flex;
    align-items: flex-start;
    gap: 20px;
}
.mb-layout .squad-pitch-widget {
    flex: 1 1 auto;
    min-width: 0;
}
/* RTL (B.8.2): the panel flips to the left of the pitch on its own — a flex
   row lays out along the inline axis, which `dir="rtl"` reverses. It is stated
   rather than left implicit because the header forces `direction: ltr` on
   itself in rtl.css, and the obvious next assumption is that the page body
   does too. It does not. */
@media (max-width: 767px) {
    .mb-layout {
        display: block;
    }
}

/* ================================================================
   B.3.1 — Empty slot control
================================================================ */
.squad-empty-slot {
    width: 110px;
    min-height: 150px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: rgba(255,255,255,0.03);
    border: 2px dashed rgba(255,255,255,0.28);
    border-radius: 10px;
    color: rgba(255,255,255,0.55);
    font-family: 'Montserrat', sans-serif;
    cursor: pointer;
    transition: all 0.15s ease;
    padding: 8px 4px;
    box-sizing: border-box;
}
.squad-empty-slot:hover,
.squad-empty-slot:focus-visible {
    background: rgba(0,255,135,0.06);
    border-color: rgba(0,255,135,0.55);
    color: #00FF87;
    outline: none;
}
.squad-empty-slot:focus-visible { box-shadow: 0 0 0 3px rgba(0,255,135,0.35); }
.squad-empty-slot .mb-slot-plus {
    font-size: 1.6rem;
    line-height: 1;
    font-weight: 400;
}
.squad-empty-slot .mb-slot-label {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.4px;
    text-transform: uppercase;
}
.squad-bench .squad-empty-slot { width: 95px; min-height: 120px; }

/* Empty slots track .squad-player-card at the PITCH CARD breakpoints (see the
   file header) — they share a row with real cards, so they must shrink with
   them or the row goes ragged and, at 360px, overflows the page. */
@media (max-width: 768px) {
    .squad-empty-slot { width: 88px; min-height: 128px; }
    .squad-bench .squad-empty-slot { width: 80px; min-height: 108px; }
}
@media (max-width: 540px) {
    .squad-empty-slot { width: 72px; min-height: 104px; }
    /* The bench turns into a nowrap scroller at this width, so its slots need
       the same flex basis its cards get. */
    .squad-bench .squad-empty-slot { flex: 0 0 68px; width: 68px; min-width: 68px; min-height: 92px; }
}
@media (max-width: 400px) {
    .squad-empty-slot { width: 62px; min-height: 92px; }
    .squad-empty-slot .mb-slot-plus { font-size: 1.3rem; }
    .squad-empty-slot .mb-slot-label { font-size: 0.58rem; }
    .squad-bench .squad-empty-slot { flex: 0 0 60px; width: 60px; min-width: 60px; min-height: 84px; }
}

/* Tap-to-select highlight for the XI/bench swap path (B.5.1) */
.squad-player-card.mb-selected .squad-player-jersey,
.squad-empty-slot.mb-selected {
    box-shadow: 0 0 0 3px #00FF87, 0 0 14px rgba(0,255,135,0.5);
    border-radius: 8px;
}
.squad-player-card.mb-drag-over,
.squad-empty-slot.mb-drag-over {
    box-shadow: 0 0 0 3px #FFD700;
    border-radius: 8px;
}

/* ================================================================
   B.3.4 — Remove affordance on a filled card
================================================================ */
.squad-player-card { position: relative; }
.mb-remove-btn {
    position: absolute;
    top: -6px; right: -6px;
    width: 22px; height: 22px;
    border-radius: 50%;
    background: #E90052;
    color: #fff;
    border: 2px solid rgba(56,0,60,0.9);
    font-size: 0.75rem; font-weight: 800;
    line-height: 1;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    opacity: 0;
    transform: scale(0.8);
    transition: opacity 0.12s, transform 0.12s;
    z-index: 3;
}
[dir="rtl"] .mb-remove-btn { right: auto; left: -6px; }
.squad-player-card:hover .mb-remove-btn,
.squad-player-card:focus-within .mb-remove-btn,
.mb-remove-btn:focus-visible {
    opacity: 1;
    transform: scale(1);
    outline: none;
}
.mb-remove-btn:focus-visible { box-shadow: 0 0 0 3px rgba(255,255,255,0.8); }

/* Touch targets (B.8.4). The painted badge stays small — visibly smaller
   than the 44px it must be tappable across, since at a 62-72px card even a
   26px disc was swallowing the jersey underneath it — while the transparent
   ::after still grows the *hit area* to the full 44×44 regardless of how
   small the badge itself is drawn. Hover doesn't exist on touch, so the ×
   must be permanently visible or the card cannot be removed at all. */
@media (hover: none), (max-width: 767px) {
    .mb-remove-btn {
        opacity: 1;
        transform: none;
        width: 18px; height: 18px;
        top: -5px; right: -5px;
        font-size: 0.62rem;
    }
    [dir="rtl"] .mb-remove-btn { right: auto; left: -5px; }
    .mb-remove-btn::after {
        content: '';
        position: absolute;
        top: 50%; left: 50%;
        width: 44px; height: 44px;
        transform: translate(-50%, -50%);
    }
}
/* Tracks the PITCH CARD breakpoints (see file header), not this component's
   own LAYOUT set — the jersey itself keeps shrinking here, so the badge
   steps down with it rather than staying fixed at the 767px size. */
@media (max-width: 400px) {
    .mb-remove-btn {
        width: 15px; height: 15px;
        top: -4px; right: -4px;
        border-width: 1.5px;
        font-size: 0.56rem;
    }
    [dir="rtl"] .mb-remove-btn { right: auto; left: -4px; }
}

/* ================================================================
   B.5.3/B.3.4/B.5.1 — per-player action menu, opened by clicking a filled
   card. One floating element repositioned per open (matches the AI Builder's
   own .squad-tooltip pattern in wildcard_wrapper.html), so it always sits
   above whichever card was clicked instead of being laid out inline.
================================================================ */
.mb-action-menu {
    position: fixed;
    min-width: 168px;
    background: #17101f;
    border: 1px solid rgba(255,255,255,0.14);
    border-radius: 12px;
    padding: 6px;
    box-sizing: border-box;
    box-shadow: 0 12px 32px rgba(0,0,0,0.55);
    z-index: 1500;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity 0.12s ease, transform 0.12s ease, visibility 0.12s ease;
}
.mb-action-menu.mb-open { opacity: 1; visibility: visible; transform: translateY(0); }
.mb-action-menu-title {
    padding: 6px 10px 7px;
    font-size: 0.72rem; font-weight: 800;
    color: #00FF87;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    margin-bottom: 4px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mb-action-menu-item {
    display: block;
    width: 100%;
    background: transparent;
    border: none;
    border-radius: 8px;
    color: rgba(255,255,255,0.85);
    text-align: left;
    padding: 9px 10px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.8rem; font-weight: 600;
    cursor: pointer;
}
[dir="rtl"] .mb-action-menu-item { text-align: right; }
.mb-action-menu-item:hover,
.mb-action-menu-item:focus-visible { background: rgba(255,255,255,0.08); outline: none; }
.mb-action-menu-item.mb-action-menu-danger { color: #FF6B9D; }
.mb-action-menu-item.mb-action-menu-danger:hover { background: rgba(233,0,82,0.12); }
@media (hover: none), (max-width: 767px) {
    .mb-action-menu-item { min-height: 44px; padding: 11px 12px; }
}

/* ================================================================
   B.3.5 — Summary bar (extends the AI Builder's #wcStatsGrid cards)
================================================================ */
.mb-summary-extra {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    background: rgba(255,255,255,0.035);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 12px;
    padding: 12px 16px;
    margin: -10px 0 20px;
    font-size: 0.82rem;
    max-width: 100%;
    box-sizing: border-box;
}
.mb-count-chip, .mb-pos-chip, .mb-club-chip {
    display: inline-flex; align-items: center;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 20px;
    padding: 4px 11px;
    font-weight: 700;
    color: rgba(255,255,255,0.75);
    white-space: nowrap;
}
.mb-count-chip.mb-complete { border-color: rgba(0,255,135,0.4); color: #00FF87; }
.mb-club-chip.mb-club-full { border-color: rgba(233,0,82,0.5); background: rgba(233,0,82,0.12); color: #FF6B9D; }
.mb-leader-chip {
    display: inline-flex; align-items: center;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 20px;
    padding: 4px 11px;
    font-weight: 700; font-size: inherit;
    color: rgba(255,255,255,0.55);
    white-space: nowrap;
}
.mb-basis-line {
    flex-basis: 100%;
    color: rgba(255,255,255,0.55);
    font-size: 0.78rem;
    line-height: 1.5;
}
.mb-basis-line strong { color: #00FF87; }
.mb-basis-line .mb-basis-warn { color: #FFD700; }
.mb-budget-negative { color: #FF6B9D !important; }
.mb-summary-actions {
    display: flex; align-items: center; gap: 10px;
    margin-left: auto;
    flex-wrap: wrap;
}
[dir="rtl"] .mb-summary-actions { margin-left: 0; margin-right: auto; }
.mb-btn-secondary {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.8);
    border-radius: 20px;
    padding: 7px 14px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.78rem; font-weight: 700;
    cursor: pointer;
    transition: all 0.15s;
}
.mb-btn-secondary:hover:not(:disabled) { background: rgba(255,255,255,0.12); }
.mb-btn-secondary:disabled { opacity: 0.4; cursor: not-allowed; }
.mb-review-reason {
    flex-basis: 100%;
    font-size: 0.76rem;
    color: rgba(255,255,255,0.45);
}

/* ================================================================
   B.4 — Search & filter panel
================================================================ */
.mb-drawer-backdrop {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.55);
    opacity: 0; pointer-events: none;
    transition: opacity 0.2s ease;
    z-index: 1400;
}
.mb-drawer-backdrop.mb-open { opacity: 1; pointer-events: auto; }
/* ⚠️ The backdrop belongs to the DRAWER presentation only, and this override is
   load-bearing. `showPanel()` adds `.mb-open` unconditionally — deliberately, per
   B.4.1's "two presentations chosen in CSS, not by branching the JS" — so without
   this rule, opening the panel on desktop drops a full-page 55%-black scrim over
   a pitch that is still meant to be visible and clickable beside it, and every
   click outside the panel is swallowed by an element with `pointer-events: auto`.
   Found by B.8.6's real-browser pass; jsdom has neither layout nor pointer
   events, so no amount of DOM testing could have caught it. */
@media (min-width: 768px) {
    .mb-drawer-backdrop,
    .mb-drawer-backdrop.mb-open { opacity: 0; pointer-events: none; }
}

.mb-search-panel {
    flex: 0 0 380px;
    max-width: 380px;
    background: rgba(20,10,26,0.92);
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    position: sticky;
    top: calc(var(--mb-header-h) + 12px);
    max-height: calc(100dvh - var(--mb-header-h) - 24px);
}
@media (max-width: 1023px) {
    .mb-search-panel { flex-basis: 300px; max-width: 300px; }
}
@media (max-width: 767px) {
    .mb-search-panel {
        position: fixed;
        left: 0; right: 0; bottom: 0;
        max-width: none;
        width: 100%;
        height: 85dvh;
        max-height: 85dvh;
        border-radius: 18px 18px 0 0;
        transform: translateY(100%);
        transition: transform 0.25s ease;
        z-index: 1401;
        top: auto;
    }
    .mb-search-panel.mb-open { transform: translateY(0); }
}

.mb-search-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 16px; gap: 8px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    flex-shrink: 0;
}
.mb-search-title { font-size: 0.95rem; font-weight: 800; color: #00FF87; margin: 0; }
.mb-search-close {
    width: 30px; height: 30px; border-radius: 50%;
    background: rgba(255,255,255,0.08); border: none; color: #fff;
    font-size: 1rem; cursor: pointer; flex-shrink: 0;
    min-width: 30px;
}
@media (max-width: 767px) { .mb-search-close { width: 44px; height: 44px; min-width: 44px; font-size: 1.2rem; } }

.mb-slot-info {
    padding: 10px 16px 0;
    font-size: 0.78rem;
    color: rgba(255,255,255,0.6);
    flex-shrink: 0;
}
.mb-slot-info strong { color: #B47FFF; }

.mb-search-controls { padding: 10px 16px; flex-shrink: 0; }
.mb-search-input {
    width: 100%;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 10px;
    color: #fff; padding: 9px 12px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.85rem;
    box-sizing: border-box;
    margin-bottom: 8px;
}
.mb-search-input::placeholder { color: rgba(255,255,255,0.35); }
.mb-filter-row {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-bottom: 8px;
}
.mb-filter-select, .mb-filter-input {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff; border-radius: 8px;
    padding: 6px 8px; font-size: 0.74rem;
    font-family: 'Montserrat', sans-serif;
}
/* `color-scheme` tells the browser to paint its OWN chrome around this
   control — the <select> popup, its scrollbar — in dark colors. Without it,
   `background`/`color` above only ever reach the closed control; the popup
   itself is native UI and defaults to the OS light theme, which is the white
   dropdown seen against this dark panel. The explicit `option` rule below is
   the fallback for engines that don't fully theme the popup off `color-scheme`. */
.mb-filter-select { color-scheme: dark; }
.mb-filter-select option {
    background: #1a0e22;
    color: #fff;
}
.mb-filter-input { width: 76px; }
.mb-filter-toggle {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 0.74rem; color: rgba(255,255,255,0.7);
}
/* ⚠️ Any class that sets `display` outranks the UA's `[hidden] { display: none }`,
   so an element JS marks `hidden` keeps rendering. That is how the "In my team"
   toggle (B.4.9 — must not render at all when the user owns nobody) shipped
   visible to every preseason and unclaimed user: the JS set `.hidden = true`
   correctly and this rule quietly cancelled it. jsdom cannot catch this — it
   reports `.hidden === true` and computes no cascade — so it took B.8.6's real
   browser. `.mb-empty-state[hidden]` below already carried this guard; every
   display-setting class in this file now does. */
.mb-filter-toggle[hidden],
.mb-search-panel [hidden],
.mb-sticky-strip[hidden] { display: none !important; }
.mb-sort-row { display: flex; align-items: center; gap: 8px; font-size: 0.74rem; color: rgba(255,255,255,0.5); }
.mb-sort-row select { flex: 1; }
.mb-clear-filters-btn {
    flex-shrink: 0;
    background: transparent;
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.65);
    border-radius: 14px;
    padding: 5px 11px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.7rem; font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.15s;
}
.mb-clear-filters-btn:hover { background: rgba(255,255,255,0.08); color: #fff; }

.mb-search-results {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 4px 10px 10px;
}
.mb-search-empty {
    text-align: center; padding: 30px 12px;
    color: rgba(255,255,255,0.4); font-size: 0.82rem;
}

.mb-player-row {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 6px;
    border-radius: 10px;
    cursor: pointer;
    background: transparent;
    border: 1px solid transparent;
    transition: background 0.12s;
    width: 100%;
    text-align: left;
    font-family: 'Montserrat', sans-serif;
    color: #fff;
}
[dir="rtl"] .mb-player-row { text-align: right; }
.mb-player-row:hover { background: rgba(255,255,255,0.06); }
.mb-player-row:focus-visible {
    background: rgba(255,255,255,0.06);
    outline: none;
    box-shadow: 0 0 0 2px #00FF87;   /* the arrow-key cursor must be visible (B.8.3) */
}
/* B.8.3 — an unpickable row is `aria-disabled`, not `disabled`, so it stays
   focusable and its reason stays readable. Dimming it to 0.42 would make that
   reason the least legible text on the panel, so the row dims and the reason
   does not. */
.mb-player-row[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.mb-player-row[aria-disabled="true"]:hover { background: transparent; }
.mb-player-row[aria-disabled="true"] .mb-row-reason { opacity: 1; }
.mb-row-jersey {
    width: 34px; height: 34px; flex-shrink: 0;
    background-size: contain; background-repeat: no-repeat; background-position: center;
}
.mb-row-info { flex: 1 1 auto; min-width: 0; }
.mb-row-name-line { display: flex; align-items: center; gap: 5px; }
.mb-row-name { font-weight: 700; font-size: 0.82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mb-row-pos-badge {
    font-size: 0.6rem; font-weight: 800; padding: 1px 5px; border-radius: 4px;
    background: rgba(255,255,255,0.12); color: rgba(255,255,255,0.6);
}
.mb-row-meta { font-size: 0.68rem; color: rgba(255,255,255,0.45); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mb-row-reason { font-size: 0.66rem; color: #FF6B9D; margin-top: 1px; }
.mb-row-compare { font-size: 0.66rem; color: #00FF87; margin-top: 1px; }
.mb-owned-chip {
    display: inline-block; font-size: 0.6rem; font-weight: 800;
    color: #00BFFF; background: rgba(0,191,255,0.12);
    border: 1px solid rgba(0,191,255,0.35);
    border-radius: 8px; padding: 0 5px; margin-inline-start: 4px;
}
.mb-row-pips { display: flex; gap: 2px; flex-shrink: 0; }
.mb-pip { width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,0.2); }
.mb-pip.diff-1, .mb-pip.diff-2 { background: #00FF87; }
.mb-pip.diff-3 { background: #FFD700; }
.mb-pip.diff-4, .mb-pip.diff-5 { background: #ff6b6b; }
.mb-row-side {
    display: flex; flex-direction: column; align-items: flex-end; gap: 1px; flex-shrink: 0;
    min-width: 54px;
}
[dir="rtl"] .mb-row-side { align-items: flex-start; }
.mb-row-price { font-weight: 800; font-size: 0.8rem; color: #FFD700; }
.mb-row-pts { font-size: 0.68rem; color: #00FF87; font-weight: 700; }
.mb-row-avail-badge {
    font-size: 0.6rem; font-weight: 800; padding: 1px 5px; border-radius: 6px;
    margin-top: 2px;
}
.mb-row-avail-badge.injured { background: rgba(233,0,82,0.18); color: #FF6B9D; }
.mb-row-avail-badge.doubtful { background: rgba(255,215,0,0.15); color: #FFD700; }

.mb-loadmore { text-align: center; padding: 8px 0 4px; }
.mb-loadmore-btn {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.75);
    border-radius: 16px; padding: 7px 18px;
    font-size: 0.76rem; font-weight: 700; cursor: pointer;
}

/* ── Placeholder state when the panel has no target slot yet (desktop) ── */
.mb-search-placeholder {
    padding: 40px 20px; text-align: center;
    color: rgba(255,255,255,0.4); font-size: 0.85rem; line-height: 1.6;
}

/* ── aria-live status text for squad changes (B.8.3), visually hidden ── */
.mb-visually-hidden {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap;
}

/* ── "Edit this squad" handoff button on the AI Builder pitch (B.5.5) ── */
.mb-edit-squad-btn {
    background: transparent;
    border: 1px solid rgba(0,255,135,0.4);
    color: #00FF87;
    border-radius: 16px;
    padding: 5px 13px;
    font-size: 0.74rem; font-weight: 700;
    font-family: 'Montserrat', sans-serif;
    cursor: pointer;
    white-space: nowrap;
}
.mb-edit-squad-btn:hover { background: rgba(0,255,135,0.1); }

/* ── Empty-state copy under the blank pitch (B.6.5) ── */
.mb-empty-state {
    margin-top: 16px; padding: 16px 18px;
    background: rgba(0,255,135,0.05);
    border: 1px dashed rgba(0,255,135,0.28);
    border-radius: 12px;
    text-align: center;
}
.mb-empty-state[hidden] { display: none; }
.mb-empty-lead {
    margin: 0 0 6px;
    font-size: 0.9rem; font-weight: 700; color: #fff;
}
.mb-empty-rules {
    margin: 0 0 12px;
    font-size: 0.78rem; color: rgba(255,255,255,0.55); line-height: 1.6;
}
.mb-empty-cta {
    background: transparent;
    border: 1px solid rgba(0,255,135,0.45);
    color: #00FF87;
    border-radius: 8px;
    padding: 9px 18px;
    font-size: 0.8rem; font-weight: 700;
    font-family: 'Montserrat', sans-serif;
    cursor: pointer;
    min-height: 44px;
}
.mb-empty-cta:hover:not([disabled]) { background: rgba(0,255,135,0.12); }
.mb-empty-cta[disabled] { opacity: 0.6; cursor: progress; }

.mb-empty-ai-options {
    display: flex; flex-wrap: wrap; justify-content: center;
    gap: 10px 16px;
    margin-bottom: 14px;
}
.mb-empty-ai-label {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 4px;
    font-size: 0.68rem; font-weight: 700;
    color: rgba(255,255,255,0.45);
    text-transform: uppercase; letter-spacing: 0.5px;
}
.mb-empty-ai-select {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.16);
    color: #fff;
    border-radius: 8px;
    padding: 7px 10px;
    font-size: 0.78rem; font-weight: 600;
    font-family: 'Montserrat', sans-serif;
    text-transform: none; letter-spacing: normal;
    min-height: 36px;
    cursor: pointer;
}
.mb-empty-ai-select:focus { outline: 2px solid rgba(0,255,135,0.5); outline-offset: 1px; }
/* Same fix as .mb-filter-select: without color-scheme, the popup list and its
   scrollbar are native OS chrome and render light against this dark panel. */
.mb-empty-ai-select { color-scheme: dark; }
.mb-empty-ai-select option {
    background: #1a0e22;
    color: #fff;
}

/* ── Toast (B.8.2/B.8.4) — a class rather than an inline cssText so it can be
   media-queried and sits above the drawer, not under it ── */
.mb-toast {
    position: fixed;
    left: 50%; bottom: 24px;
    transform: translateX(-50%);
    background: rgba(20,10,26,0.96);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    padding: 10px 18px;
    border-radius: 24px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.82rem;
    line-height: 1.45;
    text-align: center;
    box-shadow: 0 6px 20px rgba(0,0,0,0.4);
    max-width: min(92vw, 460px);
    box-sizing: border-box;
    z-index: 2000;   /* above the drawer (1401) — a refused move must be readable */
}
@media (max-width: 767px) {
    /* Clear of the drawer's top edge (85dvh) so a toast raised by an action
       inside the drawer is not hidden behind it. */
    .mb-toast { bottom: calc(15dvh + 12px); }
}

/* ── B.8.4 — the drawer is a real modal: the page behind it must not scroll.
   JS sets `top` to the frozen offset and restores it on close, so dismissing
   the drawer puts the user back on the slot they came from rather than at the
   top of the page. ── */
body.mb-scroll-locked {
    position: fixed;
    left: 0; right: 0;
    width: 100%;
    overflow: hidden;
}

/* ================================================================
   B.8.4 — the layout contract, by width

   Tablet (768-1023): side panel AND pitch, both visible. At this width a
   110px card row (5 x 110 + gaps = 590px) does not fit beside a 300px panel,
   so manual mode borrows the <=768 card sizes early. Scoped under .mb-layout,
   which only exists in manual mode — the AI Builder pitch is untouched
   (B.10.6 regression rule).
================================================================ */
@media (min-width: 768px) and (max-width: 1023px) {
    .mb-layout .squad-player-card   { width: 88px; }
    .mb-layout .squad-player-jersey { width: 74px; height: 74px; }
    .mb-layout .squad-player-name   { font-size: 0.70rem; max-width: 88px; }
    .mb-layout .squad-gw-box        { max-width: 88px; font-size: 0.62rem; column-gap: 3px; }
    .mb-layout .squad-position      { gap: 8px; }
    .mb-layout .squad-empty-slot    { width: 88px; min-height: 128px; }
    .mb-layout .squad-bench .squad-player-card   { width: 80px; }
    .mb-layout .squad-bench .squad-player-jersey { width: 64px; height: 64px; }
    .mb-layout .squad-bench .squad-player-name   { font-size: 0.64rem; max-width: 80px; }
    .mb-layout .squad-bench .squad-empty-slot    { width: 80px; min-height: 108px; }
}

/* ⚠️ Phone: a SLIM strip sticks, not the whole summary bar.
   B.8.4 asks for the summary "sticky to the viewport so budget-left survives
   scrolling". Making `.mb-summary-extra` itself sticky satisfies that
   literally and breaks it in practice: at 360px that bar wraps to a count
   chip + 4 position chips + up to 8 club chips + 5 action buttons + a reason
   line + the basis line — 250-350px of a 740px viewport. It covered the top
   third of the pitch and intercepted taps on the slots underneath, which
   B.8.6's real-browser pass caught while trying to fill slot 5.
   So the two facts the user actually re-reads after every pick get their own
   one-line strip, and the rest of the bar scrolls away like normal content.
   Styled full-width and flush with .site-header (not a rounded floating
   card) so it reads as a docked continuation of the header while it scrolls
   over the pitch, rather than a chip that fell in the middle of the squad. */
.mb-sticky-strip { display: none; }

@media (max-width: 767px) {
    .mb-sticky-strip {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 10px;
        position: sticky;
        top: var(--mb-header-h);
        z-index: 900;
        /* Full-bleed and styled off .site-header (header.css) — a docked
           extension of the header, not a card that has landed on the pitch.
           Bleeds past whatever horizontal padding the ancestor applies. That
           is 20px on the builder pages (.page-content, all widths), but
           .lp-shell on the landing page drops to 14px/12px below 768/480 — a
           hard-coded 20px there bled 8px *past* the viewport on each side, and
           the browser answered by shrink-to-fitting the whole page to 87%.
           Ancestors that use anything other than 20px set --mb-bleed to their
           own padding next to the rule that changes it. */
        width: calc(100% + var(--mb-bleed, 20px) * 2);
        margin: 0 calc(var(--mb-bleed, 20px) * -1) 10px;
        background: rgba(56, 0, 60, 0.95);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
        border: none;
        border-bottom: 1px solid rgba(0, 255, 135, 0.2);
        border-radius: 0;
        padding: 10px 20px;
        font-size: 0.8rem;
        font-weight: 700;
        box-sizing: border-box;
        box-shadow: 0 4px 14px rgba(0,0,0,0.35);
    }
    .mb-sticky-count { color: rgba(255,255,255,0.75); }
    .mb-sticky-count.mb-complete { color: #00FF87; }
    .mb-sticky-left { color: #00BFFF; }
    .mb-sticky-left.mb-budget-negative { color: #FF6B9D; }
    .mb-summary-extra { margin: -4px 0 14px; }
}

/* Landscape phones are too short even for the strip. */
@media (max-height: 500px) and (orientation: landscape) {
    .mb-sticky-strip { position: static; }
}

/* Every interactive control clears 44px on a touch pointer (B.8.4).
   ⚠️ `.wc-ai-review-btn` is styled in wildcard_wrapper.html (it is P.7's class,
   and after B.6.3 deleted P.7's card the manual summary bar is its only
   remaining consumer), so it is easy to miss when listing "this component's"
   controls — B.8.6's measured pass found it at 37px. */
@media (hover: none), (max-width: 767px) {
    .mb-search-input,
    .mb-filter-select,
    .mb-filter-input,
    .mb-filter-toggle,
    .mb-btn-secondary,
    .wc-ai-review-btn,
    .mb-loadmore-btn,
    .mb-clear-filters-btn { min-height: 44px; }
    .mb-filter-input { width: 88px; }
    .mb-player-row { min-height: 48px; padding: 9px 6px; }
    .mb-sort-row select { min-height: 44px; }
    /* ⚠️ B.8.5 — the filters must not crowd out the list they filter.
       `#mbFilterClub` is a `<select multiple size="4">`, which renders as a
       ~190px listbox on a 360px screen and left only three player rows visible
       in the drawer — on a panel the user opens fifteen times. Capped and
       scrolled internally; the control is unchanged, it just stops dominating
       the sheet. Found by looking at B.8.6's phone screenshot, not by a check. */
    #mbFilterClub { max-height: 88px; }
}

@media (max-width: 480px) {
    .mb-summary-extra { padding: 10px 12px; font-size: 0.76rem; }
    .mb-summary-actions { flex-basis: 100%; margin-left: 0; }
    [dir="rtl"] .mb-summary-actions { margin-right: 0; }
    .mb-empty-state { padding: 14px 12px; }
}

@media (max-width: 360px) {
    /* Nothing may push the page wider than the viewport here (B.8.4). The
       empty-slot widths that make this hold are on the pitch-card
       breakpoints above (62px at <=400), not restated. */
    .mb-summary-extra { gap: 8px 10px; }
    .mb-search-panel { height: 88dvh; max-height: 88dvh; }
}

/* Landscape phone is short, not just wide (B.8.4): a sticky bar plus an 85dvh
   drawer would leave nothing to read. Give the pitch the height back and let
   it scroll instead of being crushed. */
@media (max-height: 500px) and (orientation: landscape) {
    .mb-summary-extra { position: static; }
    .mb-search-panel { height: 100dvh; max-height: 100dvh; border-radius: 0; }
}
