    /* Page shell + theme tokens */
    .bsp-page {
        --bsp-bg: #f8fafc;
        --bsp-card: #ffffff;
        --bsp-text: #0f172a;
        --bsp-muted: #64748b;
        --bsp-border: #e2e8f0;
        --bsp-accent: #c0392b;
        --bsp-grass: #16a34a;
        --bsp-dirt: #c8a47a;
        --bsp-glove: #8b4513;
        --bsp-glove-shadow: #5c2e0a;
        background: var(--bsp-bg);
        min-height: 100vh;
        padding: 1rem 1rem 3rem;
    }
    .bsp-wrap { max-width: 760px; margin: 0 auto; }

    .bsp-topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: .75rem; }
    .bsp-back {
        font: inherit; color: var(--bsp-muted); text-decoration: none;
        display: inline-flex; align-items: center; gap: .35rem; font-size: .85rem;
    }
    .bsp-back:hover { color: var(--bsp-text); }
    .bsp-live {
        display: inline-flex; align-items: center; gap: .35rem;
        font-size: .75rem; font-weight: 700; color: #b91c1c; letter-spacing: .04em;
    }
    .bsp-live-dot {
        width: .5rem; height: .5rem; border-radius: 50%;
        background: #ef4444; animation: bsp-pulse 1.4s infinite;
    }
    .bsp-live-dot.is-err { background: #d1d5db; animation: none; }
    @keyframes bsp-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

    /* === Hero summary: gloves + scores === */
    .bsp-meta { text-align: center; margin-bottom: .25rem; }
    .bsp-meta-label { font-size: .7rem; font-weight: 700; color: var(--bsp-muted); letter-spacing: .12em; text-transform: uppercase; }
    .bsp-title { text-align: center; font-family: 'Fraunces', Georgia, serif; font-size: clamp(1.5rem, 4vw, 2rem); font-weight: 800; margin: .25rem 0 1rem; color: var(--bsp-text); }

    .bsp-summary {
        background: var(--bsp-card);
        border: 1px solid var(--bsp-border);
        border-radius: 18px;
        padding: 1.25rem 1.25rem 1rem;
        margin-bottom: 1rem;
        box-shadow: 0 4px 14px rgba(0,0,0,.04);
    }
    .bsp-inning-line {
        display: flex; justify-content: center; align-items: center; gap: .35rem;
        margin-bottom: .75rem;
        font-weight: 700; color: var(--bsp-text);
    }
    .bsp-inning-arrow { color: var(--bsp-accent); font-size: 1rem; line-height: 1; }
    .bsp-info-icon {
        width: 1rem; height: 1rem; border-radius: 50%;
        border: 1.5px solid var(--bsp-muted); color: var(--bsp-muted);
        font-size: .65rem; display: inline-flex; align-items: center; justify-content: center; font-weight: 700;
    }

    .bsp-scores {
        display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem;
        align-items: center; margin-bottom: 1rem;
    }
    .bsp-team-block { text-align: center; }
    .bsp-glove,
    .bsp-bat {
        width: clamp(70px, 16vw, 110px);
        height: clamp(70px, 16vw, 110px);
        margin: 0 auto;
        display: block;
    }
    /* Swap glove ↔ bat based on which team is at bat. The at-bat
       team gets the bat; the fielding team keeps the glove. CSS-only
       swap so it stays in sync with the .is-batting class the
       render() function already toggles. */
    .bsp-bat { display: none; }
    .bsp-team-block.is-batting .bsp-glove { display: none; }
    .bsp-team-block.is-batting .bsp-bat { display: block; }
    .bsp-team-code {
        margin-top: .35rem; font-weight: 700; font-size: 1.05rem;
        color: var(--bsp-text); letter-spacing: .04em;
    }
    .bsp-team-score {
        font-family: 'Inter', system-ui, sans-serif;
        font-size: clamp(3rem, 11vw, 5rem); font-weight: 800;
        font-variant-numeric: tabular-nums; line-height: 1;
        color: var(--bsp-text);
    }
    .bsp-team-block.is-batting .bsp-team-score { color: var(--bsp-accent); }
    .bsp-mid {
        display: flex; flex-direction: column; align-items: center; gap: .35rem;
    }

    /* BSO row */
    .bsp-bso-row { display: flex; justify-content: center; align-items: center; gap: .75rem; flex-wrap: wrap; }
    .bsp-bso-group { display: flex; align-items: center; gap: .35rem; }
    .bsp-bso-letter { font-size: .75rem; font-weight: 700; color: var(--bsp-muted); width: .8rem; }
    .bsp-bso-dot {
        width: .65rem; height: .65rem; border-radius: 50%;
        background: var(--bsp-border); border: 1px solid #cbd5e1;
    }
    .bsp-bso-dot.is-on.b { background: #16a34a; border-color: #15803d; }
    .bsp-bso-dot.is-on.s { background: #ef4444; border-color: #b91c1c; }
    .bsp-bso-dot.is-on.o { background: #f59e0b; border-color: #b45309; }

    /* === Live card: batter, pitcher, count, base diamond, pitch trail === */
    .bsp-live-card {
        position: relative;
        background: linear-gradient(135deg, #166534 0%, #14532d 60%, #052e16 100%);
        border-radius: 18px;
        padding: 1rem 1.25rem 1.25rem;
        color: #fff;
        overflow: hidden;
        margin-bottom: 1rem;
        box-shadow: 0 8px 24px rgba(20,83,45,.35);
    }
    /* Subtle field-grass pattern overlay */
    .bsp-live-card::before {
        content: ''; position: absolute; inset: 0;
        background:
          radial-gradient(circle at 20% 80%, rgba(255,255,255,.06), transparent 60%),
          repeating-linear-gradient(135deg, rgba(255,255,255,.025) 0 6px, transparent 6px 12px);
        pointer-events: none;
    }
    .bsp-live-head {
        position: relative;
        display: grid; grid-template-columns: auto 1fr 1fr auto; gap: .75rem;
        align-items: center; font-size: .85rem; margin-bottom: .5rem;
    }
    .bsp-live-cap {
        background: rgba(0,0,0,.35); padding: .25rem .55rem; border-radius: 6px;
        font-weight: 700; font-size: .8rem; letter-spacing: .04em;
    }
    .bsp-live-roles-label { font-size: .65rem; font-weight: 700; color: rgba(255,255,255,.6); letter-spacing: .08em; text-transform: uppercase; }
    .bsp-live-roles-name  { font-size: .95rem; font-weight: 700; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .bsp-live-roles-block { min-width: 0; }
    .bsp-live-roles-stats {
        font-size: .68rem; font-weight: 600;
        color: rgba(255,255,255,.7);
        font-variant-numeric: tabular-nums;
        margin-top: .15rem;
        line-height: 1.25;
    }
    .bsp-live-roles-stats .bsp-stat-recent {
        color: rgba(255,255,255,.55);
        font-weight: 500;
        font-size: .65rem;
        margin-left: .25rem;
    }
    .bsp-live-roles-stats .bsp-stat-pill {
        display: inline-block;
        font-size: .56rem; font-weight: 800;
        padding: .05rem .25rem; border-radius: 3px;
        margin-right: .2rem;
        text-transform: uppercase; letter-spacing: .04em;
    }
    .bsp-live-roles-stats .bsp-stat-pill.r-hit { background: rgba(94,234,212,.25); color: #5eead4; }
    .bsp-live-roles-stats .bsp-stat-pill.r-walk { background: rgba(74,222,128,.25); color: #4ade80; }
    .bsp-live-roles-stats .bsp-stat-pill.r-out { background: rgba(251,191,36,.22); color: #fbbf24; }
    .bsp-live-roles-stats .bsp-stat-pill.r-strikeout { background: rgba(248,113,113,.22); color: #f87171; }
    .bsp-live-roles-stats .bsp-stat-pill.r-hr { background: rgba(251,191,36,.3); color: #fbbf24; }

    /* Live card body: batter+strike-zone art on the left fills as much
       width as it can; pitch trail on the right is a vertical column
       of mini-grids (one per pitch in the current AB). Old layout
       capped the art at 220px which left a huge dead-green column. */
    .bsp-live-body {
        position: relative; min-height: 220px;
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: stretch;
        gap: 1rem;
    }
    .bsp-batter-art {
        width: 100%; height: auto;
        max-height: 260px;
        display: block;
    }
    .bsp-live-stack {
        display: flex; flex-direction: column; gap: .35rem;
        align-items: stretch; min-width: 0;
    }
    .bsp-count-row { display: none; }   /* redundant — BSO row above shows the count */
    .bsp-mini-diamond { width: 22px; height: 22px; }

    .bsp-pitch-list {
        display: flex; flex-direction: column; gap: .35rem;
        background: rgba(0,0,0,.35);
        padding: .55rem .5rem; border-radius: 10px;
        align-items: center;
        min-width: 72px;
    }
    .bsp-pitch-list-head {
        font-size: .58rem; font-weight: 800;
        text-transform: uppercase; letter-spacing: .08em;
        color: rgba(255,255,255,.55);
        align-self: center; margin-bottom: .15rem;
    }
    /* Each pitch is a tiny strike-zone grid SVG with a dot showing
       where it landed. Ball=green, Strike=red, Foul=amber. The (x,y)
       location is currently deterministic per pitch index (see the
       JS), but the JSON shape is forwards-compatible with real
       user-tap data (Phase A). */
    .bsp-pitch-grid {
        width: 56px; height: 56px;
        display: flex; align-items: center; justify-content: center;
        position: relative;
    }
    .bsp-pitch-grid svg { width: 100%; height: 100%; display: block; }
    .bsp-pitch-grid-empty {
        width: 56px; height: 56px;
        border: 1px dashed rgba(255,255,255,.18); border-radius: 6px;
    }
    .bsp-pitch-empty {
        font-size: .72rem; color: rgba(255,255,255,.55);
        padding: .25rem 0;
    }
    @media (max-width: 480px) {
        .bsp-live-body { grid-template-columns: minmax(0, 1fr) 76px; gap: .5rem; }
        .bsp-pitch-grid, .bsp-pitch-grid-empty { width: 44px; height: 44px; }
        .bsp-pitch-list { min-width: 56px; padding: .4rem .3rem; }
    }
    .bsp-pitch-label-ball   { color: #4ade80; }
    .bsp-pitch-label-strike { color: #f87171; }
    .bsp-pitch-label-foul   { color: #fbbf24; }
    .bsp-pitch-empty { font-size: .8rem; color: rgba(255,255,255,.55); font-style: italic; }

    /* Mini diamond (in BSO badge area) */
    .bsp-mid-diamond-svg { width: 70px; height: 70px; }

    /* === Collapsible details === */
    .bsp-collapse {
        background: var(--bsp-card); border: 1px solid var(--bsp-border);
        border-radius: 12px; margin-bottom: .75rem; overflow: hidden;
    }
    .bsp-collapse-head {
        display: flex; justify-content: space-between; align-items: center;
        padding: .85rem 1rem; cursor: pointer; user-select: none;
        font-weight: 600; font-size: .9rem;
    }
    .bsp-collapse-head:hover { background: #f8fafc; }
    .bsp-collapse-body { display: none; padding: .25rem 1rem 1rem; }
    .bsp-collapse.is-open .bsp-collapse-body { display: block; }
    .bsp-collapse-arrow { transition: transform 200ms; }
    .bsp-collapse.is-open .bsp-collapse-arrow { transform: rotate(180deg); }

    /* Compact linescore */
    .bsp-line { width: 100%; border-collapse: collapse; font-size: .85rem; font-variant-numeric: tabular-nums; min-width: 480px; }
    .bsp-line th, .bsp-line td { padding: .35rem .55rem; text-align: center; border: 1px solid var(--bsp-border); }
    .bsp-line th { background: var(--bsp-bg); color: var(--bsp-muted); font-weight: 600; font-size: .75rem; text-transform: uppercase; letter-spacing: .04em; }
    .bsp-line tr td:first-child, .bsp-line tr th:first-child { text-align: left; font-weight: 600; }
    .bsp-line td.bsp-current { background: rgba(192,57,43,.08); }
    .bsp-line td.bsp-tot { background: #f8fafc; font-weight: 700; }
    .bsp-line-wrap { overflow-x: auto; }

    /* Lineup card (Ship 3): two-team batting order with positions.
       Current batter row highlighted with --bsp-accent. Subbed-off
       players appear in a faded "Bench" subsection below each team. */
    .bsp-lineup-grid {
        display: grid; gap: 1rem;
        grid-template-columns: 1fr;
    }
    @media (min-width: 640px) {
        .bsp-lineup-grid { grid-template-columns: 1fr 1fr; }
    }
    .bsp-lineup-team {
        background: #f8fafc;
        border: 1px solid #e2e8f0;
        border-radius: 10px;
        padding: .75rem .85rem;
    }
    .bsp-lineup-team-head {
        display: flex; align-items: center; justify-content: space-between;
        gap: .5rem; margin-bottom: .5rem;
    }
    .bsp-lineup-team-name {
        font-size: .85rem; font-weight: 700; color: #0f172a;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .bsp-lineup-team-tag {
        font-size: .65rem; font-weight: 700;
        padding: .15rem .45rem; border-radius: 999px;
        background: #cbd5e1; color: #0f172a;
        text-transform: uppercase; letter-spacing: .04em;
    }
    .bsp-lineup-team-tag.is-batting { background: #f97316; color: #fff; }
    .bsp-lineup-list { display: grid; gap: .25rem; }
    .bsp-lineup-row {
        display: grid;
        grid-template-columns: 1.25rem 2rem 1fr 2.5rem;
        gap: .35rem; align-items: center;
        padding: .3rem .45rem;
        background: #fff;
        border: 1px solid transparent;
        border-radius: 6px;
        font-size: .8rem;
    }
    .bsp-lineup-row.is-current {
        background: #fff7ed;
        border-color: #fb923c;
        box-shadow: 0 1px 4px rgba(251,146,60,0.25);
    }
    .bsp-lineup-row .bsp-lp-order { color: #94a3b8; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; }
    .bsp-lineup-row .bsp-lp-num { color: #475569; font-weight: 600; font-variant-numeric: tabular-nums; font-family: ui-monospace, monospace; }
    .bsp-lineup-row .bsp-lp-name { font-weight: 600; color: #0f172a; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .bsp-lineup-row.is-empty .bsp-lp-name { color: #94a3b8; font-style: italic; font-weight: 500; }
    .bsp-lineup-row .bsp-lp-pos {
        font-size: .65rem; font-weight: 700;
        background: #e0e7ff; color: #4338ca;
        padding: .15rem .35rem; border-radius: 4px;
        text-align: center;
    }
    .bsp-lineup-row .bsp-lp-pos.is-unset { background: transparent; color: #cbd5e1; font-weight: 500; }
    .bsp-lineup-bench-head {
        font-size: .65rem; text-transform: uppercase; letter-spacing: .06em;
        color: #94a3b8; font-weight: 700;
        margin: .65rem 0 .25rem;
    }
    .bsp-lineup-bench-row {
        font-size: .75rem; color: #64748b;
        padding: .2rem .45rem;
    }

    /* Field positions: SVG diamond + outfield with the fielding team's
       players placed by position. Mirrors the editor's diamond view. */
    .bsp-field-wrap {
        position: relative;
        width: 100%; max-width: 460px; margin: 0 auto;
        aspect-ratio: 1 / 0.95;
    }
    .bsp-field-wrap svg { width: 100%; height: 100%; display: block; }
    .bsp-field-pos {
        position: absolute;
        transform: translate(-50%, -50%);
        background: #fff;
        border: 2px solid #cbd5e1;
        border-radius: 8px;
        padding: .25rem .4rem;
        text-align: center;
        font-size: .7rem; font-weight: 700;
        color: #0f172a;
        min-width: 3.25rem; max-width: 5.5rem;
        line-height: 1.15;
        box-shadow: 0 2px 6px rgba(0,0,0,0.08);
    }
    .bsp-field-pos.is-filled { border-color: #c0392b; }
    .bsp-field-pos.is-empty { color: #94a3b8; border-style: dashed; }
    .bsp-field-pos .bsp-fp-abbr {
        display: block; font-size: .58rem; letter-spacing: .04em; text-transform: uppercase;
        color: #94a3b8;
    }
    .bsp-field-pos.is-filled .bsp-fp-abbr { color: #c0392b; }
    .bsp-field-pos .bsp-fp-name {
        display: block; font-size: .7rem;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .bsp-field-meta {
        text-align: center;
        font-size: .72rem;
        color: #64748b;
        margin-top: .65rem;
    }
    @media (max-width: 480px) {
        .bsp-field-pos { font-size: .62rem; min-width: 2.85rem; max-width: 4.5rem; padding: .2rem .3rem; }
        .bsp-field-pos .bsp-fp-abbr { font-size: .52rem; }
        .bsp-field-pos .bsp-fp-name { font-size: .62rem; }
    }

    /* Live transitions / announcements layer. Overlays the live card
       (the green batter+zone scene). Three layers stack from subtle to
       loud:
         - .bsp-pitch-flash: small pitch-result badge near the count
         - .bsp-ab-banner: big AB-outcome banner across the scene
         - .bsp-next-up: persistent "up next" line under the batter row
       JS triggers them via classes; CSS handles the fade/slide. */
    .bsp-live-card { position: relative; overflow: hidden; }

    .bsp-pitch-flash {
        position: absolute; top: 3rem; right: .85rem;
        z-index: 3; pointer-events: none;
        font-size: .85rem; font-weight: 800; letter-spacing: .06em;
        text-transform: uppercase;
        padding: .35rem .75rem; border-radius: 7px;
        color: #fff; box-shadow: 0 6px 18px rgba(0,0,0,.35);
        opacity: 0; transform: translateY(-8px);
        transition: opacity .25s, transform .25s;
    }
    .bsp-pitch-flash.is-visible { opacity: 1; transform: translateY(0); }
    .bsp-pitch-flash.is-ball   { background: #16a34a; }
    .bsp-pitch-flash.is-strike { background: #ef4444; }
    .bsp-pitch-flash.is-foul   { background: #f59e0b; color: #1f1505; }

    .bsp-ab-banner {
        position: absolute; inset: 0;
        z-index: 4; pointer-events: none;
        display: flex; align-items: center; justify-content: center;
        flex-direction: column; gap: .4rem;
        text-align: center;
        background: rgba(2,6,23,.55);
        backdrop-filter: blur(2px);
        opacity: 0;
        transition: opacity .25s;
        padding: 1rem;
    }
    .bsp-ab-banner.is-visible { opacity: 1; }
    .bsp-ab-banner-result {
        font-size: 2rem; font-weight: 900; letter-spacing: .04em;
        text-transform: uppercase;
        line-height: 1;
        text-shadow: 0 4px 18px rgba(0,0,0,.55);
        animation: bsp-pop .55s ease-out;
    }
    .bsp-ab-banner-batter {
        font-size: .9rem; font-weight: 700; color: rgba(255,255,255,.92);
        text-shadow: 0 2px 8px rgba(0,0,0,.6);
    }
    .bsp-ab-banner-rbi {
        font-size: .78rem; font-weight: 700; color: #fde68a;
        letter-spacing: .06em; text-transform: uppercase;
        text-shadow: 0 2px 8px rgba(0,0,0,.55);
    }
    .bsp-ab-banner.is-walk      .bsp-ab-banner-result { color: #4ade80; }
    .bsp-ab-banner.is-strikeout .bsp-ab-banner-result { color: #f87171; }
    .bsp-ab-banner.is-out       .bsp-ab-banner-result { color: #fbbf24; }
    .bsp-ab-banner.is-hit       .bsp-ab-banner-result { color: #5eead4; }
    .bsp-ab-banner.is-hr        .bsp-ab-banner-result { color: #fbbf24; font-size: 2.4rem; }
    .bsp-ab-banner.is-run       .bsp-ab-banner-result { color: #fde68a; }
    .bsp-ab-banner.is-side      .bsp-ab-banner-result { color: #cbd5e1; font-size: 1.5rem; }
    @keyframes bsp-pop {
        0%   { transform: scale(.65); opacity: 0; }
        45%  { transform: scale(1.05); opacity: 1; }
        100% { transform: scale(1); opacity: 1; }
    }

    .bsp-next-up {
        position: absolute; left: 0; right: 0; bottom: 0;
        z-index: 2; pointer-events: none;
        background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.55) 100%);
        padding: 1.5rem .85rem .55rem;
        font-size: .8rem; color: rgba(255,255,255,.85);
        text-align: left;
        opacity: 0; transition: opacity .2s;
    }
    .bsp-next-up.is-visible { opacity: 1; }
    .bsp-next-up strong { color: #fff; font-weight: 700; }
    .bsp-next-up-eyebrow {
        display: inline-block;
        font-size: .58rem; font-weight: 800; letter-spacing: .12em;
        text-transform: uppercase;
        color: rgba(255,255,255,.55);
        margin-right: .35rem;
    }
    @media (max-width: 480px) {
        .bsp-ab-banner-result { font-size: 1.5rem; }
        .bsp-ab-banner.is-hr .bsp-ab-banner-result { font-size: 1.75rem; }
    }

    /* Pitcher Heat Map (Phase E). Tabs across the top (one per pitcher
       that has thrown this game), a centered strike-zone grid below,
       legend + meta footer underneath. */
    .bsp-heatmap-tabs {
        display: flex; flex-wrap: wrap; gap: .35rem;
        margin-bottom: .65rem;
    }
    .bsp-heatmap-tab {
        font: inherit; font-size: .75rem; font-weight: 700;
        padding: .35rem .65rem; border-radius: 999px;
        border: 1px solid var(--border-color, #e2e8f0);
        background: #fff; color: var(--text-secondary, #475569);
        cursor: pointer;
    }
    .bsp-heatmap-tab.is-active {
        background: #c0392b; color: #fff; border-color: #c0392b;
    }
    .bsp-heatmap-tab-pitches {
        font-size: .65rem; font-weight: 600;
        margin-left: .25rem; opacity: .8;
    }
    .bsp-heatmap-grid-wrap {
        position: relative; width: 100%;
        max-width: 320px; margin: 0 auto;
        aspect-ratio: 1 / 1;
    }
    .bsp-heatmap-grid-wrap svg { width: 100%; height: 100%; display: block; }
    .bsp-heatmap-legend {
        display: flex; flex-wrap: wrap; gap: .85rem;
        justify-content: center;
        margin-top: .65rem;
        font-size: .72rem; color: var(--bsp-muted, #64748b);
        font-weight: 600;
    }
    .bsp-heatmap-legend-item { display: inline-flex; align-items: center; gap: .35rem; }
    .bsp-heatmap-dot {
        width: .65rem; height: .65rem; border-radius: 50%;
        display: inline-block; border: 1.5px solid #fff;
        box-shadow: 0 0 0 1px rgba(0,0,0,.15);
    }
    .bsp-heatmap-dot.is-ball   { background: #22c55e; }
    .bsp-heatmap-dot.is-strike { background: #ef4444; }
    .bsp-heatmap-dot.is-foul   { background: #f59e0b; }
    .bsp-heatmap-dot.is-hit    { background: #5eead4; }
    .bsp-heatmap-dot.is-swing {
        background: #ef4444; border-color: #1f2937;
        box-shadow: 0 0 0 1.5px #1f2937, 0 0 0 2.5px #fff;
    }
    .bsp-heatmap-meta {
        text-align: center;
        font-size: .7rem;
        color: var(--bsp-muted, #64748b);
        margin-top: .35rem;
    }

    /* Compact game log */
    .bsp-log-row { display: grid; grid-template-columns: 2.5rem 1fr auto auto; gap: .65rem; padding: .35rem 0; font-size: .85rem; border-bottom: 1px solid #f1f5f9; }
    .bsp-log-row:last-child { border-bottom: 0; }
    .bsp-log-row.is-play { font-style: italic; color: var(--bsp-muted); }
    .bsp-log-inning { color: var(--bsp-muted); font-weight: 600; }
    .bsp-log-result { font-weight: 700; }
    .bsp-log-result.r-walk      { color: #16a34a; }
    .bsp-log-result.r-strikeout { color: #dc2626; }
    .bsp-log-result.r-out       { color: #d97706; }
    .bsp-log-result.r-hit       { color: #0e7490; }
    .bsp-log-result.r-hr        { color: #b45309; }
    .bsp-log-pitches { color: var(--bsp-muted); font-variant-numeric: tabular-nums; }
    .bsp-log-empty { text-align: center; padding: 1rem; color: var(--bsp-muted); font-size: .85rem; }

    /* Embedded board (e.g. inside the Baseball Duel) — neutralize the
       full-page shell so it sits inline among other content. */
    .bsp-page.bsp-embedded { min-height: 0; padding: 0; background: transparent; }
    .bsp-page.bsp-embedded .bsp-wrap { max-width: none; margin: 0; }

    /* Duel board: surface the running count in plain numbers. The pro
       spectator shows the count as dots only (numeric row hidden); in the
       duel a legible "balls - strikes · outs" strip next to the pitch
       trail makes it unmistakable that the count is tracking. */
    .bsp-page.bsp-embedded .bsp-count-row {
        display: flex; align-items: center; justify-content: center; gap: .45rem;
        background: rgba(0,0,0,.4); border-radius: 8px;
        padding: .4rem .55rem; margin-bottom: .4rem;
        color: #fff; font-weight: 800; font-variant-numeric: tabular-nums;
    }
    .bsp-page.bsp-embedded .bsp-count-bs { font-size: 1rem; letter-spacing: .02em; }
    .bsp-page.bsp-embedded .bsp-count-outs { font-size: .8rem; color: rgba(255,255,255,.85); }
    /* Bigger, clearer B/S/O dots on the duel summary card. */
    .bsp-page.bsp-embedded .bsp-bso-dot { width: .8rem; height: .8rem; }
    .bsp-page.bsp-embedded .bsp-bso-letter { font-size: .85rem; }
    .bsp-page.bsp-embedded .bsp-count-cap {
        font-size: .6rem; font-weight: 800; letter-spacing: .08em;
        text-transform: uppercase; color: rgba(255,255,255,.55);
    }
