/* ============================================
   LineupIQ Stacks modal (team sports)
   Stack Exposure / Team Stacks / Game Stacks; box sized to content by JS
   ============================================ */

/* Overlay content box (the .slate-modal overlay itself centers it) —
   sized for this content rather than the slate picker's 1200px/70vh */
.stacks-modal-content {
    /* Width is set by LineupIQStacks.fitModalWidth() on open: one steady
       width for all three tabs = the widest tab's natural table width
       (+ the settings column on Stack Exposure), capped at 92vw. These are
       the pre-measure fallbacks. */
    width: 92%;
    max-width: 92vw;
    height: auto;
    max-height: 86vh;
}

/* Reset button: explicit colors — Bootstrap's btn-outline-secondary is
   near-invisible against our light-mode footer */
#stacksResetBtn {
    color: var(--liq-text-secondary);
    border-color: var(--liq-border-color);
    background: var(--liq-bg-primary);
}

    #stacksResetBtn:hover {
        color: var(--liq-text-primary);
        border-color: var(--liq-accent-green);
    }

    .stacks-modal-content .slate-modal-header {
        padding: 1rem 1.25rem;
    }

        .stacks-modal-content .slate-modal-header h2 {
            font-size: 1.15rem;
            margin: 0;
        }

/* Tab bar */
.stacks-tabbar {
    display: flex;
    gap: 0.25rem;
    padding: 0.5rem 1.25rem 0;
    border-bottom: 1px solid var(--liq-border-color);
    flex-shrink: 0;
}

.stacks-tab {
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 0.45rem 0.9rem;
    font-size: 0.85rem;
    color: var(--liq-text-secondary);
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}

    .stacks-tab:hover {
        color: var(--liq-text-primary);
    }

    .stacks-tab.active {
        color: var(--liq-accent-green);
        border-bottom-color: var(--liq-accent-green);
    }

/* Body: the only scroll region */
.stacks-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* No top padding on the SCROLLER: sticky headers park at top: 0 of the
       scrollport, so the breathing room lives on the pane instead */
    padding: 0 1.25rem 1rem;
    position: relative;   /* anchors off-screen measuring of hidden panes */
}

.stacks-pane {
    display: none;
    padding-top: 1rem;
}

    .stacks-pane.active {
        display: block;
    }

    /* fitModalWidth(): render a hidden pane invisibly to read its natural width */
    .stacks-pane.stacks-measuring {
        display: block;
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        visibility: hidden;
        pointer-events: none;
    }

    /* ...and while measuring, every table reports its NATURAL width even
       if it normally stretches (Team Stacks) */
    .stacks-modal.stacks-measure .stacks-table-wrap {
        display: inline-block !important;
        width: auto !important;
    }

    .stacks-modal.stacks-measure .stacks-table {
        width: auto !important;
    }

/* Stack Exposure: table + settings column side by side (settings wrap
   under the table only if the box is narrower than both; mobile puts
   them on top, see the media block) */
.stacks-exposure-layout {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1rem;
}

.stacks-exposure-main {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 100%;
}

    /* The notes under the table must not widen the column (their long
       text would push the settings panel onto the next line): contribute
       0 to intrinsic width, then stretch to the table's width */
    .stacks-exposure-main > .form-text {
        width: 0;
        min-width: 100%;
    }

.stacks-settings-row.stacks-settings-panel {
    flex: 1 1 300px;
    min-width: 280px;
    flex-direction: column;
    gap: 0.9rem;
    margin-bottom: 0;
    overflow: hidden;   /* nothing may bleed past the card */
}

    /* Everything inside the column must be able to shrink and wrap */
    .stacks-settings-panel .stacks-setting {
        min-width: 0;
        max-width: 100%;
    }

    .stacks-settings-panel .stacks-bb-row {
        flex-wrap: wrap;
        row-gap: 0.4rem;
    }

    .stacks-settings-panel .stacks-bb-count {
        flex: 0 0 auto;
    }

    .stacks-settings-panel .stacks-bb-pct span {
        white-space: nowrap;
    }

    .stacks-settings-panel .form-text {
        overflow-wrap: anywhere;
    }

/* Footer */
.stacks-footer {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1.25rem;
    border-top: 1px solid var(--liq-border-color);
    background: var(--liq-bg-tertiary);
    flex-shrink: 0;
}

    .stacks-footer-note {
        margin-left: auto;
    }

/* Global stack settings row (gap / orders / bring-back) */
.stacks-settings-row {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 1.5rem;
    padding: 0.5rem 0.75rem 0.75rem;
    margin-bottom: 0.75rem;
    background: var(--liq-bg-tertiary);
    border: 1px solid var(--liq-border-color);
    border-radius: 8px;
}

.stacks-setting {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 150px;
}

    .stacks-setting > label {
        font-size: 0.72rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--liq-text-secondary);
    }

    .stacks-setting .form-text {
        font-size: 0.7rem;
        margin: 0;
    }

/* Bring-back: toggle + count + share */
.stacks-bb-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

    .stacks-bb-row .stacks-bb-count {
        width: 88px;
    }

    .stacks-bb-pct {
        display: inline-flex;
        align-items: center;
        gap: 0.2rem;
    }

        .stacks-bb-pct input {
            width: 64px;
            text-align: center;
        }

        .stacks-bb-pct span {
            font-size: 0.8rem;
            color: var(--liq-text-secondary);
        }

.stacks-posted {
    color: var(--liq-accent-green);
    font-size: 0.72rem;
}

/* Pool exposure column: actual share of the generated pool */
.stacks-pool-col .stacks-pool-n {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.7;
}

.stacks-pool-cell {
    text-align: center;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--liq-text-secondary);
}

    .stacks-pool-cell.stacks-pool-ok {
        color: var(--liq-accent-green);
    }

    .stacks-pool-cell.stacks-pool-warn {
        color: var(--liq-accent-yellow, #f59e0b);
    }

    .stacks-pool-cell.stacks-pool-bad {
        color: var(--liq-accent-red, #ef4444);
    }

/* Entry column: the same shares over lineups actually entered into contests.
   Only rendered once contests are assigned, so it sits to the right of Pool
   and carries a left rule to read as a separate pane. */
.stacks-entry-col,
.stacks-entry-cell {
    border-left: 1px solid var(--liq-border, rgba(255,255,255,0.12));
}

.stacks-entry-col .stacks-pool-n {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.7;
}

/* Batting-order chips 1..9 */
.stacks-order-chips {
    display: flex;
    gap: 0.2rem;
}

.stacks-chip.stacks-chip-wide {
    width: 40px;
}

.stacks-chip {
    width: 26px;
    height: 26px;
    padding: 0;
    border: 1px solid var(--liq-border-color);
    border-radius: 5px;
    background: var(--liq-bg-primary);
    color: var(--liq-text-muted, var(--liq-text-secondary));
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.12s ease;
}

    .stacks-chip.active {
        background: rgba(var(--liq-accent-rgb), 0.15);
        border-color: var(--liq-accent-green);
        color: var(--liq-accent-green);
    }

/* Tables (the body scrolls; the table just needs its border/radius).
   overflow: clip (not hidden) keeps the rounded clip WITHOUT making the
   wrap a scroll container - that's what lets the sticky header row stick
   to the top of the scrolling body instead of to a box that never scrolls. */
.stacks-table-wrap {
    border: 1px solid var(--liq-border-color);
    border-radius: 8px;
    overflow: hidden;
    overflow: clip;
}

.stacks-table {
    font-size: 0.85rem;
    color: var(--liq-text-primary);
    --bs-table-bg: transparent;
    --bs-table-color: var(--liq-text-primary);
    --bs-table-border-color: var(--liq-border-color);
}

    .stacks-table thead th {
        position: sticky;
        top: 0;
        z-index: 1;
        background: var(--liq-bg-tertiary);
        font-size: 0.72rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--liq-text-secondary);
        white-space: nowrap;
    }

    .stacks-table td {
        vertical-align: middle;
    }

    /* Sortable headers: click cycles desc -> asc -> original */
    .stacks-table th[data-sort] {
        cursor: pointer;
        user-select: none;
        padding-right: 1.1rem;
        /* no position here: the th is position: sticky (frozen header),
           which already anchors the ::after sort arrow; a relative here
           would outrank the sticky rule and un-freeze the row */
    }

        .stacks-table th[data-sort]:hover {
            color: var(--liq-text-primary);
        }

        .stacks-table th[data-sort]::after {
            content: '';
            position: absolute;
            right: 0.35rem;
            top: 50%;
            transform: translateY(-50%);
            border: 4px solid transparent;
            opacity: 0;
        }

        .stacks-table th[data-sort].sorted-desc::after {
            border-top-color: var(--liq-accent-green);
            border-bottom: 0;
            opacity: 1;
        }

        .stacks-table th[data-sort].sorted-asc::after {
            border-bottom-color: var(--liq-accent-green);
            border-top: 0;
            opacity: 1;
        }

        .stacks-table th[data-sort].sorted {
            color: var(--liq-accent-green);
        }

    .stacks-table .w-check {
        width: 40px;
    }

    .stacks-table .w-num {
        width: 96px;
    }

    /* Stack type: left-aligned, fixed comfortable width so the numeric
       columns sit close instead of the label spanning the whole table */
    .stacks-table th:nth-child(2),
    .stacks-table td.stacks-label {
        text-align: left;
        width: 140px;
    }

    /* Per-shape stack-mate chips (NFL) */
    .stacks-table .w-mates {
        width: 150px;
    }

    .stacks-row-mates {
        gap: 0.15rem;
    }

    /* NFL Stack Exposure: per-shape run-back (⇄) + mini (2 / 3) chips */
    .stacks-table .w-extras {
        width: 216px;
    }

    .stacks-row-extras {
        gap: 0.2rem;
    }

        .stacks-row-extras .stacks-chip-x {
            width: 26px;
        }

        .stacks-row-extras .stacks-chip-x .bi {
            font-size: 0.7rem;
        }

        /* "-" row has no run-back: keep the column aligned with a blank slot */
        .stacks-row-extras .stacks-chip-blank {
            display: inline-block;
            visibility: hidden;
        }

    /* NFL Team Stacks: per-team shapes + stack-mates */
    .stacks-table .w-shapes {
        width: 196px;
    }

    .stacks-row-shapes .stacks-chip.stacks-chip-sm {
        width: 30px;
    }

        /* Shape unticked on Stack Exposure: not available to any team */
        .stacks-row-shapes .stacks-chip.is-goff {
            opacity: 0.3;
            text-decoration: line-through;
            cursor: not-allowed;
        }

    /* Inherited-vs-override: active chips always read the same (solid);
       an override is marked by a small dot before the row, not by dimming
       the chips (dim read as "inactive") */
    .stacks-row-mates,
    .stacks-row-orders,
    .stacks-row-shapes,
    .stacks-row-teammates,
    .stacks-row-extras {
        position: relative;
        padding-left: 0.55rem;
    }

        .stacks-row-mates::before,
        .stacks-row-orders::before,
        .stacks-row-shapes::before,
        .stacks-row-teammates::before,
        .stacks-row-extras::before {
            content: '';
            position: absolute;
            left: 0;
            top: 50%;
            width: 5px;
            height: 5px;
            margin-top: -2.5px;
            border-radius: 50%;
            background: var(--liq-accent-green);
            opacity: 0;
        }

        .stacks-row-mates:not(.is-default)::before,
        .stacks-row-orders:not(.is-default)::before,
        .stacks-row-shapes:not(.is-default)::before,
        .stacks-row-teammates:not(.is-default)::before,
        .stacks-row-extras:not(.is-default)::before {
            opacity: 1;
        }

    .stacks-chip.stacks-chip-sm {
        width: 34px;
        height: 22px;
        font-size: 0.68rem;
    }

/* Tables don't need the full box width — let each size to its columns
   and sit left, so a 5-column NFL table isn't stretched across empty
   space while the 9-column MLB Team Stacks table uses what it needs */
.stacks-body .stacks-table-wrap {
    display: inline-block;
    max-width: 100%;
}

    /* Only when the box had to be capped at 92vw (fitModalWidth sets the
       class) do wraps scroll sideways - that costs the sticky header, so
       it's opt-in */
    .stacks-modal.stacks-capped .stacks-body .stacks-table-wrap {
        overflow-x: auto;
    }

.stacks-body .stacks-table {
    width: auto;
}

/* Team Stacks: per-team batting-order chips (MLB) */
.stacks-table .w-orders {
    width: 232px;
}

    .stacks-row-orders {
        gap: 0.12rem;
    }

        .stacks-row-orders .stacks-chip.stacks-chip-sm {
            width: 22px;
        }

/* Team Stacks: compact numeric inputs + a Gap select so ten columns fit.
   The table stretches to the box (MLB fills it anyway; on NFL the QB-name
   column takes the slack instead of leaving the right half empty). */
.stacks-body #stacksTabTeams .stacks-table-wrap {
    display: block;
}

.stacks-body .stacks-teams-table {
    width: 100%;
}

.stacks-teams-table th:nth-child(2),
.stacks-teams-table td.stacks-label {
    width: 96px;   /* logo + abbr; the generic 140px label width is for shape names */
}

.stacks-teams-table th:nth-child(3) {
    width: 56px;   /* Opp */
}

.stacks-teams-table .w-orders {
    width: 222px;
}

.stacks-teams-table input[type="number"] {
    width: 64px;
}

.stacks-teams-table .w-num {
    width: 80px;
}

.stacks-teams-table .w-gap {
    width: 104px;
}

    .stacks-teams-table .stacks-team-gap {
        width: 96px;   /* "global (Any)" + the arrow */
        padding: 2px 22px 2px 6px;
        font-size: 0.78rem;
    }

        /* Lineup posted but this spot isn't in it: hollow, dashed */
        .stacks-row-orders .stacks-chip.is-unposted {
            border-style: dashed;
            opacity: 0.55;
        }

/* Game Stacks: status line above the table */
.stacks-games-status {
    font-size: 0.8rem;
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.6rem;
    border-radius: 6px;
    border: 1px solid var(--liq-border-color);
    background: var(--liq-bg-tertiary);
    color: var(--liq-text-secondary);
}

    .stacks-games-status.is-on {
        border-color: rgba(var(--liq-accent-rgb), 0.45);
    }

    .stacks-games-status.is-on strong {
        color: var(--liq-accent-green);
    }

    .stacks-games-status.is-off strong {
        color: var(--liq-accent-yellow, #f59e0b);
    }

.stacks-games-table .w-gsmax {
    width: 132px;
}

    .stacks-table input[type="number"] {
        width: 80px;
        text-align: center;
    }

    .stacks-table tr.stacks-row-off .stacks-label {
        opacity: 0.45;
        text-decoration: line-through;
    }

.stacks-label {
    font-weight: 600;
    letter-spacing: 0.02em;
}

.stacks-team-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

    .stacks-team-cell .stacks-team-logo {
        width: 18px;
        height: 18px;
        display: block;
    }

    .stacks-team-cell .team-logo-missing {
        display: none;
    }

    .stacks-team-cell.stacks-team-off {
        opacity: 0.45;
        text-decoration: line-through;
    }

/* Game Stacks tab: AWAY @ HOME cell */
.stacks-game-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    white-space: nowrap;
}

    .stacks-game-cell .stacks-game-at {
        font-size: 0.7rem;
        font-weight: 400;
        color: var(--liq-text-secondary);
    }

.stacks-games-table th:first-child,
.stacks-games-table td.stacks-label {
    width: 190px;
    text-align: left;
}

/* Time column (2nd) — narrower than the generic 2nd-column label width */
.stacks-games-table th:nth-child(2),
.stacks-games-table td.stacks-label + td {
    width: 84px;
    text-align: left;
    white-space: nowrap;
}

/* ============================================
   Stacks modal — mobile (<= 768px)
   Full-screen box (matches the slate picker), scrollable tab strip,
   settings above the table, tables scroll sideways inside their wrap,
   footer wraps to two rows.
   ============================================ */
@media (max-width: 768px) {
    .stacks-modal-content {
        width: 100% !important;   /* fitModalWidth() clears its inline width here too */
        max-width: 100%;
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        border-radius: 0;
    }

        .stacks-modal-content .slate-modal-header {
            padding: 0.75rem 1rem;
        }

    .stacks-tabbar {
        padding: 0.35rem 0.75rem 0;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

        .stacks-tabbar::-webkit-scrollbar {
            display: none;
        }

    .stacks-tab {
        flex: 0 0 auto;
        white-space: nowrap;
        padding: 0.45rem 0.7rem;
    }

    /* Footer: let the note wrap fully (it was clipping) and keep some
       breathing room above the iOS home indicator */
    .stacks-footer {
        flex-wrap: wrap;
        row-gap: 0.35rem;
        padding: 0.6rem 0.75rem calc(0.6rem + env(safe-area-inset-bottom, 0px));
    }

    .stacks-footer-note {
        flex: 1 1 100%;
        margin-left: 0;
        font-size: 0.72rem;
        line-height: 1.3;
    }

    .stacks-body {
        padding: 0 0.75rem 0.75rem;
    }

    .stacks-pane {
        padding-top: 0.75rem;
    }

    /* Settings first, full width, one setting per row */
    .stacks-exposure-layout {
        gap: 0.75rem;
    }

    .stacks-settings-row.stacks-settings-panel {
        order: -1;
        flex: 1 1 100%;
        min-width: 0;
        padding: 0.5rem 0.6rem 0.6rem;
    }

    .stacks-exposure-main {
        flex: 1 1 100%;
        min-width: 0;
    }

    .stacks-bb-row {
        flex-wrap: wrap;
        row-gap: 0.4rem;
    }

    /* Tables: full-width scroll containers */
    .stacks-body .stacks-table-wrap {
        display: block;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .stacks-table {
        font-size: 0.8rem;
    }

        /* Slimmer inputs: the 5-column Stack Exposure table then fits a
           375px screen without sideways scroll */
        .stacks-table input[type="number"] {
            width: 56px;
        }

        .stacks-table .w-num {
            width: 64px;
        }

        .stacks-table th:nth-child(2),
        .stacks-table td.stacks-label {
            width: auto;
            min-width: 84px;
        }

    /* Wide tables (Team Stacks, Game Stacks) scroll sideways; keep the
       identifying columns pinned so the row stays readable while scrolling */
    .stacks-teams-table th:nth-child(1),
    .stacks-teams-table td:nth-child(1),
    .stacks-teams-table th:nth-child(2),
    .stacks-teams-table td:nth-child(2),
    .stacks-table-qb th:nth-child(1),
    .stacks-table-qb td:nth-child(1),
    .stacks-table-qb th:nth-child(2),
    .stacks-table-qb td:nth-child(2),
    .stacks-games-table th:nth-child(1),
    .stacks-games-table td:nth-child(1) {
        position: sticky;
        left: 0;
        z-index: 2;
        background: var(--liq-bg-secondary);
    }

    .stacks-teams-table th:nth-child(2),
    .stacks-teams-table td:nth-child(2),
    .stacks-table-qb th:nth-child(2),
    .stacks-table-qb td:nth-child(2) {
        left: 40px;   /* after the On / allow column */
        box-shadow: 4px 0 6px -4px var(--liq-shadow);
    }

    .stacks-games-table th:nth-child(1),
    .stacks-games-table td:nth-child(1) {
        box-shadow: 4px 0 6px -4px var(--liq-shadow);
    }

    /* Header cells are sticky-top already; pinned ones need both + a higher layer */
    .stacks-teams-table thead th:nth-child(1),
    .stacks-teams-table thead th:nth-child(2),
    .stacks-table-qb thead th:nth-child(1),
    .stacks-table-qb thead th:nth-child(2),
    .stacks-games-table thead th:nth-child(1) {
        z-index: 3;
        background: var(--liq-bg-tertiary);
    }

    .stacks-games-status {
        font-size: 0.75rem;
    }

    /* Footer: note drops to its own row under the buttons */
    .stacks-footer {
        flex-wrap: wrap;
        padding: 0.6rem 0.75rem;
        gap: 0.5rem;
    }

        .stacks-footer-note {
            order: 3;
            flex: 1 1 100%;
            margin-left: 0;
            font-size: 0.72rem;
        }

        .stacks-footer #stacksDoneBtn {
            margin-left: auto;
        }
}

/* Stack Exposure (NFL) extras cell: [⇄ 1 2 3] · [⌥ 2 3 4] */
.stacks-row-extras .stacks-x-glyph {
    display: inline-flex;
    align-items: center;
    color: var(--liq-text-secondary);
    font-size: 0.72rem;
    margin-right: 0.05rem;
}

.stacks-row-extras .stacks-x-sep {
    width: 1px;
    height: 18px;
    background: var(--liq-border-color);
    margin: 0 0.25rem;
}

.stacks-row-extras .stacks-chip-x.stacks-chip-sm {
    width: 22px;
}

/* NFL shapes table: seven columns incl. the extras cell - trim the others
   so the table + settings column still fit a 1280 screen side by side */
.stacks-table-qb th:nth-child(2),
.stacks-table-qb td.stacks-label {
    width: 118px;
}

.stacks-table-qb .w-mates {
    width: 128px;
}

    .stacks-table-qb .stacks-row-mates .stacks-chip.stacks-chip-sm {
        width: 30px;
    }

.stacks-table-qb .w-num {
    width: 84px;
}

    .stacks-table-qb input[type="number"] {
        width: 70px;
    }

.stacks-table-qb .w-extras {
    width: 238px;   /* [⇄ – 1 2 3] · [– 2 3 4] */
}

    .stacks-table-qb .stacks-row-extras .stacks-chip-x.stacks-chip-sm {
        width: 21px;
        font-size: 0.66rem;
    }

    .stacks-table-qb .stacks-row-extras {
        gap: 0.15rem;
    }

/* Global run-back / secondary size chips in the settings column (NFL) */
.stacks-global-sizes {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
}

    .stacks-global-sizes .stacks-x-glyph {
        color: var(--liq-text-secondary);
        font-size: 0.75rem;
        margin-right: 0.15rem;
    }

    .stacks-global-sizes .stacks-chip.stacks-chip-sm {
        width: 26px;
        height: 24px;
    }

.stacks-setting > label .stacks-label-note {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    opacity: 0.75;
    margin-left: 0.3rem;
}

/* Stack rules by size (MLB): compact table inside the settings panel */
.stacks-size-table {
    margin-top: 0.35rem;
    font-size: 0.78rem;
}

    .stacks-size-table th {
        font-weight: 600;
        white-space: nowrap;
        padding: 0.15rem 0.3rem;
    }

    .stacks-size-table td {
        padding: 0.2rem 0.3rem;
        vertical-align: middle;
    }

    .stacks-size-table .w-sz {
        width: 42px;
    }

    .stacks-size-table td.stacks-sz-cell {
        font-weight: 600;
        color: var(--liq-accent-green);
    }

    .stacks-size-table .stacks-size-orders {
        display: flex;
        flex-wrap: wrap;
        gap: 0.15rem;
    }

    .stacks-size-table select.stacks-size-gap {
        width: 72px;
    }

/* Inherited-cell collapse: a row that has not been customised shows one quiet
   pill instead of its full chip set, so the rows that ARE custom stand out.
   Chips stay in the DOM; only their display is swapped. */
.stacks-inherit-pill {
    display: none;
    border: 1px dashed var(--liq-border-color);
    background: transparent;
    color: var(--liq-text-secondary);
    border-radius: 4px;
    padding: 0.05rem 0.4rem;
    font-size: 0.7rem;
    line-height: 1.5;
    white-space: nowrap;
    cursor: pointer;
}

    .stacks-inherit-pill:hover {
        border-style: solid;
        border-color: rgba(var(--liq-accent-rgb), 0.55);
        color: var(--liq-text-primary);
    }

/* Hide every child, then bring the pill back: the extras cell also carries
   glyph and separator spans that would otherwise strand next to the pill. */
.stacks-order-chips.is-default:not(.is-open) > * {
    display: none;
}

.stacks-order-chips.is-default:not(.is-open) > .stacks-inherit-pill {
    display: inline-block;
}

/* Opposing-exclusion option picker: sits inline on the system rule row for
   sports that offer a choice (soccer). Sized to not crowd the rule name. */
.rule-item-actions .rule-oppex-option {
    width: auto;
    max-width: 190px;
    font-size: 0.72rem;
    padding: 0.1rem 1.4rem 0.1rem 0.4rem;
}

/* Football single game: captain seat table + QB-stack knob (Stack Exposure settings panel) */
.stacks-captain-table { margin-top: 0.25rem; }
/* Ten columns: the padding is where the width goes, not the inputs. Tightened
   so the whole rule fits without a sideways scroll on a ~900px pane. */
.stacks-captain-table th, .stacks-captain-table td { padding: 0.15rem 0.2rem; vertical-align: middle; }
/* .stacks-table input[type="number"] sets 80px and outranks a plain class
   pair on specificity, so these carry the attribute selector too.
   Without it every number box rendered at 80px, the Bring cell could not
   hold two of them, and every row wrapped to double height. */
.stacks-captain-table input[type="number"] { width: 3rem; padding-left: 0.3rem; padding-right: 0.15rem; }
.stacks-sg-select { width: auto; max-width: 8rem; }
.stacks-sg-inline-label { font-size: 0.8rem; color: var(--liq-text-secondary, #6c757d); margin-right: 0.5rem; }
.stacks-setting-sgqb .stacks-bb-row { flex-wrap: wrap; gap: 0.5rem; }

/* Captain rule columns: the conditional that applies when THIS position holds
   the seat. Separated from the exposure columns by a rule so the two halves of
   the table do not read as one row of settings. */
.stacks-captain-table th.stacks-rule-col:first-of-type,
.stacks-captain-table td.stacks-cap-matecell {
    border-left: 1px solid var(--liq-border, #dee2e6);
}
.stacks-captain-table th.stacks-rule-col {
    font-weight: 600;
    color: var(--liq-text-secondary, #6c757d);
}
/* The two range cells hold input + "to" + input. nowrap alone does not save
   them: the auto table layout squeezes whichever column has the shorter header
   until the inputs wrap onto a second line and every row doubles in height. A
   floor keeps them intact and lets the table scroll sideways instead, which is
   the behaviour the pane is already set up for. */
.stacks-cap-matecell {
    white-space: nowrap;
    min-width: 7rem;
}
/* Bounded counts are dropdowns now; only the percentage boxes are still
   number inputs. Their spinner arrows appear on hover and eat exactly the
   width the placeholder needs, which is what clipped "any" to "an". Hide the
   spinner and give the box room for its own placeholder. */
.stacks-modal input[type="number"]::-webkit-outer-spin-button,
.stacks-modal input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.stacks-modal input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

.stacks-captain-table select.stacks-cap-mmin,
.stacks-captain-table select.stacks-cap-mmax,
.stacks-captain-table select.stacks-cap-rb,
.stacks-captain-table select.stacks-cap-rbmax {
    width: auto;
    min-width: 3.3rem;
    display: inline-block;
    padding: 0.1rem 1.1rem 0.1rem 0.35rem;   /* room for the caret */
    background-position: right 0.25rem center;
}
.stacks-captain-table input[type="number"].stacks-cap-pct { width: 3.2rem; display: inline-block; }
/* Group header: three column groups that mean different things */
.stacks-cap-grouphead th { border-bottom: 0; padding-bottom: 0; }
.stacks-cap-grouphead .stacks-grp {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--liq-text-secondary, #6c757d);
    text-align: center;
}
.stacks-captain-table thead tr:last-child th { padding-top: 0.1rem; }
.stacks-cap-dash {
    display: inline-block;
    padding: 0 0.12rem;
    font-size: 0.72rem;
    color: var(--liq-text-secondary, #6c757d);
}
.stacks-cap-poschips { display: flex; gap: 0.15rem; flex-wrap: nowrap; }
.stacks-cap-poschips .stacks-chip { min-width: 1.8rem; padding: 0.1rem 0.15rem; font-size: 0.7rem; }
.stacks-cap-poschips .stacks-chip:disabled { opacity: 0.4; cursor: not-allowed; }
.stacks-sg-counts { flex-wrap: wrap; gap: 0.4rem; margin-top: 0.6rem; align-items: center; }
.stacks-sg-counts .stacks-sg-num { width: 4.2rem; }
.stacks-row-off .stacks-cap-matecell,
.stacks-row-off .stacks-cap-poschips { opacity: 0.45; }

/* The row in words, under the row it describes. Present only when the row has
   a rule, so an untouched table stays one line per position. */
.stacks-captain-table tr.stacks-cap-say td {
    padding: 0.05rem 0.4rem 0.35rem 3.1rem;
    border-top: 0;
    font-size: 0.76rem;
    color: var(--liq-text-secondary, #6c757d);
    font-style: italic;
}
.stacks-captain-table tr.stacks-cap-say + tr > td { border-top-width: 1px; }
.stacks-footer-caprule { color: var(--liq-text-secondary, #6c757d); }

/* Single game: the captain table is the widest thing in the modal and the
   shapes table beside it is three rows, so the settings column takes its own
   full-width row rather than being squeezed into the 300px sidebar. */
.stacks-exposure-sg .stacks-settings-row.stacks-settings-panel {
    flex: 1 1 100%;
    min-width: 0;
}
/* Backstop: whatever the column ends up being, the table scrolls inside it
   rather than being clipped by the panel's overflow:hidden. */
.stacks-setting-captain {
    overflow-x: auto;
    max-width: 100%;
}
.stacks-sg-side { flex-wrap: wrap; gap: 0.4rem; margin-top: 0.6rem; align-items: center; }
.stacks-sg-side .stacks-sg-select { max-width: 12rem; }

/* Contradiction between this modal's captain rules and the Rules tab's
   Showdown templates. Loud on purpose: the failure it prevents is a pool that
   comes back empty with nothing said about why. */
.stacks-conflict {
    border: 1px solid var(--bs-danger, #dc3545);
    border-left-width: 3px;
    border-radius: 0.4rem;
    padding: 0.6rem 0.75rem;
    margin-bottom: 0.9rem;
    background: rgba(220, 53, 69, 0.06);
}
.stacks-conflict-h { font-size: 0.85rem; font-weight: 600; color: var(--bs-danger, #dc3545); }
.stacks-conflict ul { margin: 0.35rem 0 0.35rem 0; padding-left: 1.2rem; font-size: 0.8rem; }
.stacks-conflict-f { font-size: 0.75rem; color: var(--liq-text-secondary, #6c757d); }

/* Tab rule counts: how many rules a tab is holding, so four tabs of settings
   do not all have to be opened to find out which ones are doing anything. */
.stacks-tab-count {
    display: inline-block;
    margin-left: 0.35rem;
    min-width: 1.05rem;
    padding: 0 0.25rem;
    border-radius: 0.6rem;
    font-size: 0.65rem;
    line-height: 1.05rem;
    text-align: center;
    background: var(--liq-accent, #0d6efd);
    color: #fff;
}

/* Pairings tab */
.stacks-pairs { max-width: 760px; }
.pairs-sec {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--liq-text-secondary, #6c757d);
    margin: 1.1rem 0 0.35rem;
}
.pairs-group { display: flex; flex-direction: column; gap: 0.1rem; }
.pairs-row {
    display: flex; align-items: flex-start; gap: 0.6rem;
    padding: 0.35rem 0.4rem; border-radius: 0.35rem;
}
.pairs-row:hover { background: rgba(var(--liq-accent-rgb, 13, 110, 253), 0.05); }
.pairs-row select.pairs-num {
    width: 4.6rem;
    flex: 0 0 4.6rem;
    padding: 0.15rem 1.1rem 0.15rem 0.4rem;
    background-position: right 0.3rem center;
}
.pairs-switch { flex: 0 0 4.2rem; margin: 0.1rem 0 0; padding-left: 2.6rem; }
.pairs-label { font-size: 0.85rem; display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.pairs-why { font-size: 0.73rem; color: var(--liq-text-secondary, #6c757d); }

/* ============================================================
   Research tab (football single game)
   Bars are HTML: the sets are small, every value is printed beside its bar
   rather than hidden behind a hover, and the pane is built while hidden --
   the one case a canvas measures zero-width and paints nothing.
   Series colours are the two validated categorical slots, stepped separately
   for the dark surface rather than flipped.
   ============================================================ */
.stacks-captain-tab, .rsch { max-width: 900px; }
.rsch { --rsch-s1: #2a78d6; --rsch-s2: #eb6834; }
[data-bs-theme="dark"] .rsch { --rsch-s1: #3987e5; --rsch-s2: #d95926; }

.rsch-intro { font-size: 0.85rem; color: var(--liq-text-secondary, #6c757d); margin-bottom: 0.9rem; }
.rsch-h { font-size: 0.95rem; font-weight: 600; margin: 1.4rem 0 0.1rem; }
.rsch-sub { font-size: 0.78rem; color: var(--liq-text-secondary, #6c757d); margin-bottom: 0.5rem; }
.rsch-note { font-size: 0.78rem; color: var(--liq-text-secondary, #6c757d); margin-top: 0.75rem; }

.rsch-tiles { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.rsch-tile {
    flex: 1 1 200px; min-width: 0;
    border: 1px solid var(--liq-border, #dee2e6);
    border-radius: 0.5rem; padding: 0.7rem 0.8rem;
    display: flex; flex-direction: column; gap: 0.15rem;
}
.rsch-tile-n { font-size: 1.6rem; font-weight: 700; line-height: 1.05; color: var(--rsch-s1); }
.rsch-tile-l { font-size: 0.8rem; }
.rsch-tile-s { font-size: 0.72rem; color: var(--liq-text-secondary, #6c757d); }

.rsch-bars { display: flex; flex-direction: column; gap: 0.3rem; }
.rsch-row { display: flex; align-items: center; gap: 0.6rem; }
.rsch-label { flex: 0 0 11rem; font-size: 0.8rem; text-align: right; }
.rsch-track { flex: 1 1 auto; min-width: 0; height: 0.85rem; display: flex; gap: 2px; }
.rsch-fill {
    display: block; height: 100%; background: var(--rsch-s1);
    border-radius: 0 4px 4px 0;   /* rounded data-end, square against the baseline */
}
.rsch-fill.rsch-s2 { background: var(--rsch-s2); }
.rsch-track-2 { flex-direction: column; gap: 2px; height: 1.2rem; }
.rsch-track-2 .rsch-fill { height: calc(50% - 1px); }
.rsch-val { flex: 0 0 5.5rem; font-size: 0.78rem; font-variant-numeric: tabular-nums; color: var(--liq-text-secondary, #6c757d); }

.rsch-legend { display: flex; gap: 1rem; margin-bottom: 0.4rem; }
.rsch-key { font-size: 0.75rem; display: inline-flex; align-items: center; gap: 0.3rem; }
.rsch-swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; background: var(--rsch-s1); }
.rsch-swatch.rsch-s2 { background: var(--rsch-s2); }

.rsch-table { margin-top: 0.4rem; font-size: 0.8rem; max-width: 32rem; }
.rsch-table th, .rsch-table td { padding: 0.25rem 0.4rem; }
.rsch-rule-row td { border-top: 2px solid var(--liq-border, #dee2e6); }
.rsch-move-big { font-weight: 600; }
.rsch-move-small { color: var(--liq-text-secondary, #6c757d); }

.rsch-sources { margin-top: 1.2rem; padding-top: 0.6rem; border-top: 1px solid var(--liq-border, #dee2e6); font-size: 0.75rem; }
.rsch-sources > span { color: var(--liq-text-secondary, #6c757d); }
.rsch-sources ul { list-style: none; padding: 0; margin: 0.25rem 0 0; }
.rsch-sources li { margin-bottom: 0.15rem; }

@media (max-width: 640px) {
    .rsch-label { flex-basis: 7rem; }
    .rsch-val { flex-basis: 4.5rem; }
}

/* ============================================================
   PHONES
   Measured on a 375x812 viewport against the DK Showdown slate.
   The captain table wanted 907px inside a 351px pane, a 2.58x
   overflow: a phone showed Position, Min % and Max % and hid the
   entire rule behind a sideways scroll with no cue it was there.
   Ten columns cannot be made to fit, so below this breakpoint the
   table stops being a table and each position becomes a block,
   which is the shape the Pairings tab already uses successfully.
   ============================================================ */
@media (max-width: 700px) {

    /* --- tab bar: five tabs need 403px in 375. Tighten them so they
       fit, and if a future tab still overflows, fade the right edge so
       the scroll is visible instead of silent. --- */
    .stacks-tabbar {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        position: relative;
    }
    .stacks-tabbar::-webkit-scrollbar { display: none; }
    .stacks-tab {
        padding: 0.45rem 0.4rem;
        font-size: 0.8rem;
        flex: 0 0 auto;
    }
    .stacks-tab-count { margin-left: 0.2rem; }

    .stacks-body { padding-left: 0.75rem; padding-right: 0.75rem; }

    /* --- captain table becomes one block per position --- */
    .stacks-setting-captain { overflow-x: visible; }
    .stacks-captain-table,
    .stacks-captain-table tbody,
    .stacks-captain-table tr,
    .stacks-captain-table td { display: block; width: auto; }
    .stacks-captain-table thead { display: none; }

    .stacks-captain-table tr[data-pos] {
        border: 1px solid var(--liq-border-color);
        border-radius: 8px;
        padding: 0.55rem 0.7rem 0.35rem;
        margin-bottom: 0.55rem;
        background: var(--liq-bg-tertiary);
    }
    .stacks-captain-table tr[data-pos] > td {
        display: flex;
        align-items: center;
        gap: 0.6rem;
        border: 0;
        padding: 0.22rem 0;
        min-width: 0;
    }
    /* the cell's own heading, which the hidden thead used to carry */
    .stacks-captain-table tr[data-pos] > td[data-label]::before {
        content: attr(data-label);
        flex: 0 0 8.2rem;
        font-size: 0.68rem;
        font-weight: 600;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--liq-text-secondary);
    }

    /* first two cells ride together as the block's header: checkbox,
       position name, and the pool figure pulled over to the right */
    .stacks-captain-table tr[data-pos] > td:first-child {
        float: left;
        padding-right: 0.5rem;
        padding-top: 0.1rem;
    }
    .stacks-captain-table tr[data-pos] > td.stacks-label {
        font-weight: 700;
        font-size: 1rem;
        padding-bottom: 0.35rem;
        border-bottom: 1px solid var(--liq-border-color);
        margin-bottom: 0.35rem;
    }
    .stacks-captain-table tr[data-pos] > td.stacks-pool-cell {
        justify-content: flex-start;
        font-size: 0.8rem;
    }
    .stacks-captain-table tr[data-pos] > td.stacks-pool-cell::before {
        content: "In the pool";
        flex: 0 0 8.2rem;
        font-size: 0.68rem;
        font-weight: 600;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--liq-text-secondary);
    }

    /* controls get room to be tapped: 44px targets, not 22 */
    .stacks-captain-table input[type="number"],
    .stacks-captain-table select { min-height: 2.5rem; }
    .stacks-captain-table input[type="number"].stacks-cap-mmin,
    .stacks-captain-table input[type="number"].stacks-cap-mmax,
    .stacks-captain-table input[type="number"].stacks-cap-rb,
    .stacks-captain-table input[type="number"].stacks-cap-rbmax,
    .stacks-captain-table input[type="number"].stacks-cap-pct,
    .stacks-captain-table input[type="number"].stacks-cap-min,
    .stacks-captain-table input[type="number"].stacks-cap-max { width: 3.6rem; }
    .stacks-captain-table select.stacks-cap-mmin,
    .stacks-captain-table select.stacks-cap-mmax,
    .stacks-captain-table select.stacks-cap-rb,
    .stacks-captain-table select.stacks-cap-rbmax { min-width: 4rem; }
    .stacks-cap-poschips .stacks-chip {
        min-width: 2.6rem;
        min-height: 2.2rem;
        font-size: 0.78rem;
    }
    .stacks-captain-table .stacks-cap-allow { width: 1.2rem; height: 1.2rem; }

    /* the sentence sits under its block, full width */
    .stacks-captain-table tr.stacks-cap-say {
        display: block;
        margin: -0.35rem 0 0.55rem;
    }
    .stacks-captain-table tr.stacks-cap-say td {
        display: block;
        padding: 0 0.7rem 0.5rem;
        font-size: 0.78rem;
    }

    /* ownership window: keep the two boxes and their words on one line
       instead of wrapping into three orphaned rows */
    .stacks-sg-side,
    .stacks-sg-counts { row-gap: 0.35rem; }
    .stacks-sg-side .stacks-sg-num { width: 4.2rem; min-height: 2.5rem; }
    .stacks-sg-side .stacks-sg-inline-label { margin-right: 0.2rem; }
    .stacks-sg-side .stacks-cap-dash { padding: 0 0.15rem; }

    /* pairings already reflow; just make the controls tappable */
    .pairs-row select.pairs-num { min-height: 2.5rem; }
    .pairs-switch { padding-left: 2.4rem; }

    /* The pool size in a header, "Pool (20000)", is context rather than
       content, and on a Field build it pushed the Shapes table 22px past its
       pane so the header read "POOL (20000" and clipped. The figure is still
       in the column tooltip and in the footer note. */
    .stacks-pool-n { display: none; }

    /* Team Stacks is nine columns and 650px in a 351px pane, and it stays a
       table: a Showdown slate has two teams but an MLB slate has fifteen, and
       fifteen stacked blocks is worse than a sideways scroll rather than
       better.

       It needs nothing further here. The @media (max-width: 768px) block above
       already pins BOTH identifying columns -- the On checkbox and the team,
       with left: 40px so they sit side by side -- across Team Stacks, the QB
       table and Game Stacks, and carries the shadow that signals more content
       to the right. An earlier draft of this block re-declared the same
       selectors at left: 0, which at <=700px overrode that and stacked the
       team on top of the checkbox instead of beside it. Removed: the existing
       rule is both broader and correct. */
}
