/* ===========================================================================
   MLB Game Detail -- PHONE REWORK (pregame only)
   /static/css/mlb/mlb-game-phone.css
   ---------------------------------------------------------------------------
   WHY THIS FILE EXISTS
   The pregame game page (Props | Overview | Weather) was designed for the
   desktop grid and then shrunk. On a handset it is unreadable: the app ships
   NO <meta viewport>, so a phone lays this page out on a 980px canvas and
   zooms it to ~390pt of glass (measured x0.398). Every dimension in here is
   CANVAS px -- divide by ~2.51 before judging it. 32px of type reads as
   ~12.7pt, which is the app's phone body size (see nfl-game-detail.css
   section 11, the reference implementation this sheet matches).

   REVERTIBLE BY DELETING ONE <link>. Nothing was added to mlb-game-detail.css
   and no rule here exists outside the single @media (max-width: 1000px) block
   below, so removing the tag in templates/index.html restores HEAD exactly.

   SCOPE RULES (contract section E)
     * one @media (max-width: 1000px) block, nothing outside it;
     * every selector starts at #mlb-game-detail;
     * ASCII only (mlb-game-detail.css is double-encoded -- this one is not,
       and it stays that way);
     * no :root, no custom property definitions. The --gd-* tokens are
       inherited from #mlb-game-detail in mlb-game-detail.css.

   THE PREGAME GATE
   The live and final pages share .mlb-gd-tabs / .mlb-gd-tab / .mlb-gd-team-*
   with the pregame page and MUST NOT change. There is no state class on the
   root, but there is a reliable structural tell: gameDetailMLB.js pushes a
   {id:"live"} tab if and only if showLive is true, and showDecisionTabs is
   its exact negation (gameDetailMLB.js:798). So

       #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"]))

   IS the pregame page -- ONCE phase A has painted. The scaffold paints ~500ms
   earlier and has no live tab yet, so a started game briefly matched the gate
   and its header + tab bar rendered at phone-pregame size, then collapsed
   (108px/32px -> 64px/23px) when phase A landed -- a shift HEAD did not have
   on a page this rework must leave alone. The scaffold cannot tell the two
   apart on a cold direct load, so renderScaffold stamps data-scaffold on its
   own tab bar on phone and the gate excludes it; the phone chrome starts at
   phase A, when the live tab is decidable:

       #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"],
                                 .mlb-gd-tabs[data-scaffold]))

   Every rule that touches a class the live/final layout also renders carries
   that prefix. New classes (mlb-gd-p*, mlb-gd-mrow*,
   mlb-gd-sp2*, mlb-gd-lu-*, mlb-gd-lines-strip, wxp-*) exist only in the
   phone builders' output, so they take the plain #mlb-game-detail prefix.
   If :has() is unsupported the whole gated rule is dropped and the tabs keep
   their current 23px sizing -- degraded, never broken.
   The info/props/weather PANELS are always in the DOM but are only reachable
   through those three tabs, so panel-interior rules need no gate: on a live
   or final page they are permanently [hidden].
   =========================================================================== */

@media (max-width: 1000px) {

  /* =========================================================================
     E.0  PANEL CHASSIS
     ========================================================================= */

  /* The base sheet gives all three decision panels a flat 12px pad. The card
     layouts below need a real side gutter and a bottom gutter that clears the
     app's fixed tab bar (same 200px reasoning as nfl-game-detail.css:1806). */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="info"],
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="props"],
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] {
    padding: 14px 16px 180px;
    gap: 22px;
  }

  /* Section headings. The base sheet's .mlb-gd-section-title is .95rem
     (~6 physical px on the 0.398x glass), and every panel below reuses the
     class -- "Injury Report", "Weather-Adjusted Props". Sized once here.
     NOTE: this rule and the .mlb-gd-sp2 override in E.4 have IDENTICAL
     specificity (1,0,2), so this one must stay ABOVE it or the starter
     panel's heading loses its override. */
  #mlb-game-detail .mlb-gd-tab-panel .mlb-gd-section-title {
    font-size: 24px;
  }

  /* =========================================================================
     E.1  SHELL -- tab bar + header (section A)
     ========================================================================= */

  /* Props | Overview | Weather, three tabs on a 980px canvas: they fit
     centred at NFL's 32px/108px (nfl-game-detail.css:2792-2803) with room to
     spare, so no scroller and no nowrap hack. Gated: the live set is five
     tabs and keeps its 23px scrolling row. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-tabs {
    justify-content: center;
    gap: 0;
    padding: 0 12px;
    overflow-x: visible;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-tab {
    flex: 0 1 auto;
    min-height: 108px;            /* ~43 physical px -- the 44px touch target */
    padding: 14px 46px;
    font-size: 32px;
    font-weight: 600;
    justify-content: center;
  }

  /* =========================================================================
     E.0b  NFL PARITY PASS (founder, 2026-09-10)
     The phone page borrows the NFL game page's chrome outright: the same card
     ink and hairline, the same back control, the same outlined filter pills,
     and the same "@ over the kickoff" centre. Values are lifted verbatim from
     nfl-game-detail.css so the two sports cannot drift.
     ========================================================================= */

  /* =========================================================================
     E.0a  LOADING BLUR  (NFL nfl-game-detail.css 3122-3129, ported verbatim)
     The scaffold is derived from the URL plus a cached schedule row, so its
     numbers are provisional and -- on a cold deep link, where it cannot tell a
     live game from a pregame one -- its chrome still refines when phase A
     lands. A blur says "this is the shape, the detail is coming" instead of
     showing a sharp wrong answer. The BACK CONTROL stays sharp and tappable
     throughout, which is the whole reason the topbar is excluded.
     Phone-only: the desktop scaffold is byte-identical to HEAD and stays that
     way. The class is added in JS at every width; only this rule paints it.
     ========================================================================= */
  #mlb-game-detail > *:not(.mlb-gd-topbar) {
    transition: filter .28s ease, opacity .28s ease;
  }
  #mlb-game-detail.is-loading > *:not(.mlb-gd-topbar) {
    filter: blur(7px);
    opacity: .5;
    pointer-events: none;
  }
  @media (prefers-reduced-motion: reduce) {
    #mlb-game-detail > *:not(.mlb-gd-topbar) { transition: none; }
  }

  /* =========================================================================
     E.0c  LOADING SKELETON  (phone scaffold panel)
     The shape of the props tab, held at roughly its real height so the page
     does not collapse and bounce the footer while phase B loads. It is always
     behind the loading blur, so it only has to be the right SHAPE -- no detail
     and no spinner. Geometry comes from the real classes it reuses
     (.mlb-gd-pills--grid, .mlb-gd-pcard); only these bars are its own.
     ========================================================================= */
  #mlb-game-detail .mlb-gd-skel {
    display: flex;
    flex-direction: column;
    gap: 22px;
  }
  /* NOT the real pill's outline (founder 2026-09-10: the filters "load as empty
     boxes without the text"). A pill IS its label, so an outlined pill with
     nothing in it reads as finished chrome that failed to render its text --
     and then the real row arrives and only the words appear, which is why it
     felt like the filters loaded ahead of everything else. Give it the same
     placeholder ink as every other skeleton shape instead, so nothing in the
     skeleton impersonates a control. */
  #mlb-game-detail .mlb-gd-skel-pill {
    flex: 1 1 0;
    min-width: 0;
    height: 96px;                     /* the real .mlb-gd-pill */
    border-radius: 24px;
    background: #171A1A;
    border: 0;
  }
  #mlb-game-detail .mlb-gd-skel-cards {
    display: flex;
    flex-direction: column;
    gap: 16px;                        /* the real .mlb-gd-pcards */
  }
  #mlb-game-detail .mlb-gd-skel-head {
    display: flex;
    align-items: center;
    gap: 18px;
    padding-bottom: 16px;             /* the real .mlb-gd-pcard-h */
  }
  #mlb-game-detail .mlb-gd-skel-av {
    width: 90px;
    height: 90px;
    border-radius: 50%;
    flex: none;
  }
  #mlb-game-detail .mlb-gd-skel-id,
  #mlb-game-detail .mlb-gd-skel-l {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
    flex: 1 1 auto;
  }
  #mlb-game-detail .mlb-gd-skel-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    padding: 18px 0;                  /* the real .mlb-gd-mrow */
    min-height: 197px;
    box-sizing: border-box;
  }
  #mlb-game-detail .mlb-gd-skel-price {
    width: 200px;
    height: 76px;                     /* the real .mlb-gd-line-row */
    border-radius: 16px;
    flex: none;
  }
  #mlb-game-detail .mlb-gd-skel-bar { height: 34px; border-radius: 10px; }
  #mlb-game-detail .mlb-gd-skel-bar.short { height: 26px; }
  #mlb-game-detail .mlb-gd-skel-bar.w40 { width: 40%; }
  #mlb-game-detail .mlb-gd-skel-bar.w45 { width: 45%; }
  #mlb-game-detail .mlb-gd-skel-bar.w60 { width: 60%; }
  #mlb-game-detail .mlb-gd-skel-bar.w70 { width: 70%; }
  #mlb-game-detail .mlb-gd-skel-av,
  #mlb-game-detail .mlb-gd-skel-bar,
  #mlb-game-detail .mlb-gd-skel-price {
    background: #171A1A;
  }
  /* One slow pulse on the CARD, not on every bar: a dozen independently
     animating nodes under a 7px blur reads as noise. */
  @keyframes mlbGdSkelPulse { 0%, 100% { opacity: .55; } 50% { opacity: .9; } }
  #mlb-game-detail .mlb-gd-skel-card,
  #mlb-game-detail .mlb-gd-skel-pills {
    animation: mlbGdSkelPulse 1.5s ease-in-out infinite;
    pointer-events: none;
  }
  @media (prefers-reduced-motion: reduce) {
    #mlb-game-detail .mlb-gd-skel-card,
    #mlb-game-detail .mlb-gd-skel-pills { animation: none; }
  }

  /* --- tokens: undo the 2026-08-08 NAVY PIVOT on this layout --------------
     mlb-game-detail.css:4425 re-points --gd-surface* / --gd-line* to a
     blue-tinted navy (#121B2A surfaces, #2C3A4B hairlines) on the page root
     AND on each panel, so inheritance alone cannot reach it -- the same host
     list has to be re-declared. Everything the phone rework styles by hand is
     already on the NFL ink, but a dozen small parts still read the tokens (the
     price pill, the matchup chip, the lineup and arsenal chips), which is why
     "O 0.5 +1120" sat in a navy box on a near-black card. Same luminance,
     blue removed: the NFL --ngd-ink-* / --ngd-line* ladder.
     Live and final pages keep the navy -- they were not part of this rework. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])),
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-sb,
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-tabs,
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-topbar,
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-tab-panel[data-panel="info"],
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-tab-panel[data-panel="props"],
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-tab-panel[data-panel="weather"] {
    --gd-surface:   #08090A;   /* NFL --ngd-ink-075 */
    --gd-surface-2: #0B0C0C;   /* --ngd-ink-050 */
    --gd-surface-3: #131515;   /* --ngd-ink-100 */
    --gd-line:      #1F2323;   /* --ngd-line */
    --gd-line-strong: #2C3232; /* --ngd-line-hi */
  }

  /* NFL puts NOTHING behind the pill row and the group headings -- only the
     player cards carry a surface (#ngd-list and .ngd-pgroup are transparent).
     The props group is a .mlb-gd-card, so it was drawing a box around the
     pills and every card inside it; strip it back to bare on phone.
     TRAP (cost a round): the scoreboard .mlb-gd-sb used to be the FIRST
     selector of the SURFACES rule below and this bare rule was spliced in
     ahead of it, silently taking the header card's background with it. The
     two are separate rules now precisely so that cannot happen again. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="props"] .mlb-gd-props-group {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
  }

  /* --- surfaces: --ngd-ink-050 / --ngd-line-soft, radius 34 --- */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-sb,
  #mlb-game-detail .mlb-gd-tab-panel .mlb-gd-card,
  #mlb-game-detail .mlb-gd-lines-strip,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hours {
    background: #0B0C0C;
    border: 1px solid #171A1A;
    border-radius: 34px;
  }
  /* Tiles and carry cells are the inset surface, one step up from the card --
     NFL --ngd-ink-100 on --ngd-ink-050, same relationship. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-carry-cell {
    background: #131515;
    border: 1px solid #171A1A;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile { border-radius: 24px; }

  /* --- top bar + back control: nfl-game-detail.css 11.2 --- */
  /* The 110px min-height is the 44px TOUCH TARGET, not a visual box, so the
     row is pulled back up by most of its own dead space. */
  /* NFL leaves exactly 12px between the back row and the game card
     (nfl-game-detail.css: root gap 45 + topbar margin-bottom -33). The MLB
     root has no flex gap to pull against, so the same 12px is set directly --
     the -33 alone made the card OVERLAP the back row by 33px.
     The 35px side inset is NFL's page gutter, which the MLB header did not
     have: its card ran full-bleed 980 wide against NFL's 910. */
  #mlb-game-detail .mlb-gd-topbar {
    gap: 26px;
    min-height: 110px;
    /* 16px above is NFL's root padding-top; 12px below is what its root gap
       (45) minus the topbar's own pull (-33) leaves. Measured identical on
       both sports. */
    margin: 16px 35px 12px;
    padding: 0;
  }
  /* 21px under the card is what NFL leaves between .ngd-gamecard and .ngd-tabs
     (root gap 45, minus the tab row's own pull). The MLB root has no flex gap
     to pull against, so it is set here directly -- measured 0 before. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-sb {
    margin: 0 35px 21px;
  }
  /* Same 910px content column inside the panels. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="props"],
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="info"],
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] {
    padding-left: 35px;
    padding-right: 35px;
  }
  #mlb-game-detail .mlb-gd-back {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    min-height: 110px;
    padding: 0 14px 0 0;
    font-size: 33px;
    font-weight: 700;
  }
  #mlb-game-detail .mlb-gd-back svg { width: 34px; height: 34px; flex: none; }

  /* --- filter pills: outlined, teal only when on (NFL .ngd-posrow button) --- */
  #mlb-game-detail .mlb-gd-pills--grid .mlb-gd-pill {
    background: #0B0C0C;
    border: 1px solid #2C3232;
    border-radius: 24px;
    color: #8A9391;
    font-weight: 600;
  }
  #mlb-game-detail .mlb-gd-pills--grid .mlb-gd-pill.is-active {
    background: #0B0C0C;
    border-color: rgb(var(--theme-accent-rgb, 0, 211, 189));
    color: rgb(var(--theme-accent-rgb, 0, 211, 189));
  }

  /* Header: crest + code + club + first pitch, nothing else. applyHeaderOdds
     returns early on phone (contract A4) so the ML/RL pills and the total
     never render; the belt-and-braces hide below keeps a stale node from a
     desktop->phone resize out of the header. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-odds-row,
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-odds-ou {
    display: none;
  }
  /* NFL .ngd-gc-head: a three-column grid, the two identity blocks pinned to
     the TOP of the row (align-items:start) so the centre column hangs from the
     same baseline instead of floating between them. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-sb-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: start;
    gap: 18px;
    padding: 34px 28px 30px;
  }
  /* TRAP: the base phone sheet (mlb-game-detail.css:2144) turns .mlb-gd-team
     into a TWO-ROW grid -- "logo score" over "logo info" -- so a live header
     can stack the score above the club name. On a pregame page the score is
     hidden but its row is not, which pushed the name block ~10px below where
     NFL puts it. Restore the flat flex row NFL uses (.ngd-team), including
     its row-reverse mirroring for the home side. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 18px;
    min-width: 0;
  }
  /* row-reverse flips the MAIN AXIS, so flex-start is the RIGHT edge here --
     which is what mirrors the away block. The base sheet's flex-end packed the
     home crest and name to the LEFT of their column instead, leaving 96px of
     dead space against the card edge and squeezing the club name into the
     kickoff line. NFL leaves justify-content at its initial value for exactly
     this reason. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team-home {
    flex-direction: row-reverse;
    justify-content: flex-start;
  }
  /* align-self:start rides in from the same base grid rule and beats the flex
     container's align-items:center, which left the name block sitting 8px
     high against the crest. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team-info { text-align: left; min-width: 0; align-self: center; }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team-home .mlb-gd-team-info { text-align: right; }
  /* NFL's crest is an 84px rounded tile holding a 58px mark (.ngd-crest +
     .ngd-crest img). renderHeader emits a bare <img>, so the tile is built on
     the image itself: 84 box, 13px padding => a 58px content area. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team-logo {
    width: 84px;
    height: 84px;
    flex: none;
    padding: 13px;
    border-radius: 24px;
    border: 1px solid #1F2323;                 /* NFL --ngd-line */
    /* --c is the club's official primary, set inline by renderHeader. NFL
       dims it to a chip rather than a slab with exactly this gradient; a flat
       rgba(255,255,255,.05) tile was the last thing making the two headers
       read as different pages. */
    background-color: var(--c, #1f2a37);
    background-image: linear-gradient(158deg, rgba(0, 0, 0, .42), rgba(0, 0, 0, .74));
    object-fit: contain;
  }
  /* NFL's eyebrow is the club's PLACE -- "SAN FRANCISCO" over "49ers", not
     "SF". renderHeader emits .mlb-gd-team-city on phone for exactly this; the
     three-letter code stays hidden, as the base phone rules already had it.
     Values are NFL .ngd-team-city verbatim, including the ellipsis, which is
     what lets "SAN FRANCISCO" and "NEW YORK" share one column width. */
  /* CORRECTION (founder 2026-09-10: a live header was showing "COLORADO" over
     the score). This was briefly un-gated on the theory that .mlb-gd-team-city
     is a NEW class and so, per this sheet's rule at the top, exists only in the
     phone PREGAME header's output. It does not: renderHeader emits it for ANY
     phone header -- the condition there is a bare isPhone() -- so live and
     final pages got a city eyebrow the live layout never had.
     The rule at the top still holds; the class simply was not what it claimed.
     Hidden by default, revealed BY THE GATE, so the three states fall out
     right: known pregame (no marker, no live tab) -> shown and styled from
     frame one, which is why it was un-gated in the first place; live/final ->
     hidden; undecided scaffold -> hidden, then shown when phase A says
     pregame. */
  #mlb-game-detail .mlb-gd-team-city { display: none; }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team-city {
    display: block;
    font-size: 19px;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: #59615F;                   /* NFL --ngd-fg-mute */
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team-nick {
    font-size: 38px;
    font-weight: 800;
    letter-spacing: -.032em;
    line-height: 1.06;                /* NFL .ngd-team-name -- card height parity */
    margin-top: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* NFL's centre column is an "@" over a quiet mono kickoff line, not a big
     bold clock -- the matchup is the headline, the time is a detail. The "@"
     is drawn here because renderHeader emits no node for it. */
  /* --- header team blocks AS the team filter (NFL 11.3 "Team toggles") ---
     Phone pregame only. The chassis flips .is-on / aria-pressed in place and
     never re-creates the crest <img>, so everything here is a class state, not
     markup. Live and final headers paint scores and must keep white names and
     full-strength crests, which the :not(:has(...)) prefix already excludes;
     desktop never carries data-team-toggle at all. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team[data-team-toggle] {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    user-select: none;
    border-radius: 24px;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team[data-team-toggle] .mlb-gd-team-nick {
    color: #8A9391;                   /* NFL --ngd-fg-dim */
    transition: color .15s;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team[data-team-toggle] .mlb-gd-team-logo {
    opacity: .55;
    transition: opacity .15s;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team[data-team-toggle].is-on .mlb-gd-team-nick {
    color: rgb(var(--theme-accent-rgb, 0, 211, 189));
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team[data-team-toggle].is-on .mlb-gd-team-logo {
    opacity: 1;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-team[data-team-toggle]:focus-visible {
    outline: 4px solid rgb(var(--theme-accent-rgb, 0, 211, 189));
    outline-offset: 8px;
    border-radius: 24px;
  }

  /* NFL .ngd-gc-mid: the kickoff is the only thing standing between the two
     club names, so the column is capped and allowed to wrap rather than
     pushing either name into an ellipsis. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) #mlb-gd-center {
    max-width: 210px;
    padding: 0;
    /* .mlb-gd-state is a 3px-gap flex column for the live scoreboard's chip
       stack; the pregame centre is two nodes whose own margin does the
       spacing, exactly as NFL's .ngd-gc-mid does. */
    gap: 0;
    text-align: center;
  }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) #mlb-gd-center::before {
    content: "@";
    display: block;
    font-size: 30px;
    font-weight: 400;
    color: #59615F;                   /* NFL --ngd-fg-mute */
    line-height: 1.1;
  }
  /* The three-line centre (big mono clock over a date) is replaced on phone by
     ONE line -- "Thu 7:05 PM ET" -- which renderHeader emits as
     .mlb-gd-when-1line. The two source nodes stay in the DOM because the live
     module and the postponed path both write to them; they are simply hidden.
     Keyed on the 1-LINE NODE'S OWN PRESENCE as well as the gate, so the centre
     can never show the time three times over -- which is what the scaffold did
     before the gate learned its third state (founder-reported, 2026-09-10).
     The gate is still required: :has() matches on PRESENCE, not visibility, so
     on a live page where that node exists but is hidden this would otherwise
     suppress the live centre's own status lines. */
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) #mlb-gd-center:has(.mlb-gd-when-1line) .mlb-gd-when-time,
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) #mlb-gd-center:has(.mlb-gd-when-1line) .mlb-gd-when-date {
    display: none;
  }
  /* Same correction as .mlb-gd-team-city above: renderHeader's condition for
     this node is isPhone() plus "no postponed/live label", and that label is
     EMPTY on a cold load of a live game, so it can reach a live header too.
     Hidden by default, revealed by the gate. */
  #mlb-game-detail .mlb-gd-when-1line { display: none; }
  #mlb-game-detail:not(:has(.mlb-gd-tab[data-tab="live"], .mlb-gd-tabs[data-scaffold])) .mlb-gd-when-1line {
    display: block;
    font-size: 24px;                  /* NFL .ngd-gc-meta */
    line-height: 1.35;
    margin-top: 8px;
    color: #59615F;
    white-space: normal;
  }

  /* =========================================================================
     E.2  GAME LINES STRIP  (.mlb-gd-lines-strip, section C1)
     Prepended to the Overview panel on phone -- it is what the header gave up
     when applyHeaderOdds started returning early. Two rows (away, home), each
     [crest+code | ML | run line | total]: the reader compares DOWN a column,
     which is how the numbers actually relate.
     ========================================================================= */
  #mlb-game-detail .mlb-gd-lines-strip {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 20px 18px;
    background: #0B0C0C;              /* NFL --ngd-ink-050 (parity pass) */
    border: 1px solid #171A1A;
    border-radius: 34px;
  }
  #mlb-game-detail .mlb-gd-lines-row {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) repeat(3, minmax(0, 1fr));
    align-items: center;
    gap: 12px;
  }
  #mlb-game-detail .mlb-gd-lines-row + .mlb-gd-lines-row {
    padding-top: 14px;
    border-top: 1px solid var(--gd-line);
  }
  #mlb-game-detail .mlb-gd-lines-team {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
  }
  #mlb-game-detail .mlb-gd-lines-logo {
    flex: none;
    width: 52px;
    height: 52px;
    object-fit: contain;
  }
  #mlb-game-detail .mlb-gd-lines-code {
    font-size: 26px;
    font-weight: 800;
    letter-spacing: .06em;
    color: var(--gd-text);
  }
  #mlb-game-detail .mlb-gd-lines-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    min-width: 0;
    text-align: center;
  }
  #mlb-game-detail .mlb-gd-lines-lab {
    font-style: normal;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--gd-text-3);
    white-space: nowrap;
  }
  #mlb-game-detail .mlb-gd-lines-val {
    font-size: 30px;
    font-weight: 800;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
    color: var(--gd-text);
    white-space: nowrap;
  }

  /* =========================================================================
     E.3  PROPS TAB (section B)
     ========================================================================= */

  /* --- market pill row: All + 9 markets in a 5-across grid ---------------
     Two rows of five. A grid (not the base flex scroller) because every pill
     must be reachable without a horizontal swipe -- the same call the NFL
     position pills made at nfl-game-detail.css:2833-2841. */
  #mlb-game-detail .mlb-gd-pills--grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 16px;
    overflow: visible;
    flex-wrap: wrap;
    margin-bottom: 18px;
    padding: 2px 0 20px;
  }
  #mlb-game-detail .mlb-gd-pills--grid .mlb-gd-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 96px;             /* ~38 physical px + the row gap = >= 44 */
    padding: 0 10px;
    border-radius: 24px;          /* NFL .ngd-posrow button (parity pass) */
    font-size: 26px;
    font-weight: 700;
    line-height: 1.15;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* --- team group -------------------------------------------------------- */
  /* The logo + club band is gone (founder 2026-09-10): the header team blocks
     are the team filter now, so the away/home boundary is not a heading the
     reader needs. With no heading the two sections must read as ONE list, so
     the gap between them is the card gap, not a section gap. */
  #mlb-game-detail .mlb-gd-pgroup { margin-bottom: 16px; }
  #mlb-game-detail .mlb-gd-pgroup:last-child { margin-bottom: 0; }
  #mlb-game-detail .mlb-gd-pcards {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  /* --- one card per hitter ----------------------------------------------- */
  #mlb-game-detail .mlb-gd-pcard {
    background: #0B0C0C;              /* NFL --ngd-ink-050 (parity pass) */
    border: 1px solid #171A1A;        /* NFL --ngd-line-soft */
    border-radius: 34px;
    padding: 22px 22px 8px;
  }
  #mlb-game-detail .mlb-gd-pcard-h {
    display: flex;
    align-items: center;
    gap: 18px;
    min-width: 0;
    padding-bottom: 16px;
  }
  #mlb-game-detail .mlb-gd-pcard-ava {
    flex: none;
    width: 90px;
    height: 90px;
    display: block;
  }
  #mlb-game-detail .mlb-gd-pcard-ava img {
    width: 90px;
    height: 90px;
    border-radius: 50%;
    object-fit: cover;
    object-position: center top;
    background: rgba(34, 211, 238, .08);
    border: 1px solid rgba(255, 255, 255, .06);
  }
  /* Team-logo fallback (headshot 404): contain + pad so the crest is not
     cropped into a circle of shoulder. Same treatment as
     .mlb-gd-prop-avatar.is-fallback. */
  #mlb-game-detail .mlb-gd-pcard-ava img.is-fallback {
    object-fit: contain;
    padding: 10px;
  }
  #mlb-game-detail .mlb-gd-pcard-id {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
    flex: 1 1 auto;
  }
  #mlb-game-detail .mlb-gd-pcard-id .mlb-gd-prop-name {
    font-size: 35px;
    font-weight: 700;
    line-height: 1.1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  #mlb-game-detail .mlb-gd-pcard-m {
    font-size: 24px;
    color: var(--gd-text-2);
    letter-spacing: .03em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Opposing pitcher + his pitch-mix read. Neutral by default; is-good means
     the matchup helps the hitter, is-hard means it hurts him. */
  #mlb-game-detail .mlb-gd-pcard-chip {
    flex: none;
    max-width: 300px;
    padding: 10px 18px;
    border-radius: 999px;
    border: 1px solid var(--gd-line);
    background: var(--gd-surface-3);
    color: var(--gd-text-2);
    font-size: 24px;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  #mlb-game-detail .mlb-gd-pcard-chip.is-good {
    color: #4ade80;
    border-color: rgba(74, 222, 128, .30);
    background: rgba(34, 197, 94, .10);
  }
  #mlb-game-detail .mlb-gd-pcard-chip.is-hard {
    color: #f87171;
    border-color: rgba(248, 113, 113, .30);
    background: rgba(248, 113, 113, .10);
  }

  /* --- market row --------------------------------------------------------
     The row carries BOTH .mlb-gd-mrow and .mlb-gd-prop-player, because
     startLiveOddsUpdates (gameDetailMLB.js:553-616) walks
     .mlb-gd-prop-player[data-player][data-stat] and rewrites the
     .mlb-gd-line-row inside it. Everything below is scoped through .mlb-gd-mrow
     so the desktop .mlb-gd-prop-player grid (mlb-game-detail.css:571) and its
     phone override (:2337) are both out-specified without being edited. */
  #mlb-game-detail .mlb-gd-mrow.mlb-gd-prop-player {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 18px;
    padding: 18px 0;
    border-bottom: 1px solid var(--gd-line);
  }
  #mlb-game-detail .mlb-gd-pcard .mlb-gd-mrow:last-child { border-bottom: none; }
  #mlb-game-detail .mlb-gd-mrow-l {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  #mlb-game-detail .mlb-gd-mkt {
    font-size: 29px;
    font-weight: 700;
    color: var(--gd-text);
    line-height: 1.1;
  }
  #mlb-game-detail .mlb-gd-mrow-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
  }

  /* L5 strip: five bars, newest on the RIGHT (the builder reverses the
     newest-first Last5 array). Bars, not dots -- a bar reads as a result at
     ~8 physical px where a dot reads as noise. */
  #mlb-game-detail .mlb-gd-l5 {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: none;
  }
  #mlb-game-detail .mlb-gd-l5-lab {
    font-size: 20px;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--gd-text-3);
    margin-right: 3px;
  }
  #mlb-game-detail .mlb-gd-l5 i {
    display: block;
    width: 20px;
    height: 28px;
    border-radius: 6px;
    background: rgba(148, 163, 184, .18);
  }
  #mlb-game-detail .mlb-gd-l5 i.is-hit  { background: #22c55e; }
  #mlb-game-detail .mlb-gd-l5 i.is-miss { background: rgba(239, 68, 68, .55); }

  /* Factor pills. is-even is the phone-only third state (contract B7): a
     factor inside +/-5% still shows so a row never renders a bare market. */
  #mlb-game-detail .mlb-gd-mrow-meta .mlb-gd-factor {
    font-size: 22px;
    font-weight: 700;
    padding: 8px 18px;
    border-radius: 999px;
  }
  #mlb-game-detail .mlb-gd-mrow-meta .mlb-gd-factor.is-even {
    color: var(--gd-text-2);
    border-color: var(--gd-line-strong);
    background: rgba(148, 163, 184, .10);
  }

  /* --- price column -------------------------------------------------------
     .mlb-gd-line-row keeps its base display rules untouched (base
     mlb-game-detail.css:1050-1058: rows are display:none, .is-main is flex,
     and [data-expanded="true"] on the ancestor reveals the rest). NOTHING
     here sets `display` on .mlb-gd-line-row -- doing so would break the
     alt-line reveal. */
  #mlb-game-detail .mlb-gd-mrow-r {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    justify-self: end;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row {
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    min-width: 200px;
    min-height: 76px;
    padding: 0 18px;
    border-radius: 16px;
    border: 1px solid var(--gd-line);
    background: var(--gd-surface-3);
    font-variant-numeric: tabular-nums;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row.is-main {
    border-color: var(--gd-line-strong);
  }
  /* The price read as TWO nested boxes: the row above draws one, and the span
     INSIDE it draws another. That inner chip is the desktop treatment (base
     sheet mlb-game-detail.css:1063-1073 gives .mlb-gd-line-over its own fill,
     hairline and 6px radius) and it is what makes the price legible in a dense
     table row. On the phone the row itself IS the chip, so the inner one is
     just a box inside a box -- strip it back to bare text. */
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-over,
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-under {
    background: none;
    border: 0;
    border-radius: 0;
    min-width: 0;
    height: auto;
    padding: 0;
  }
  /* Add to parlay. The ROW is the visible box on this layout (the rule above
     just stripped the span's), so the added / busy / error tints go on the row
     and the SPAN is stretched to fill it so the tap target is the whole 200x76
     box rather than the 162x40 run of text inside it. ~30 physical px tall,
     which the 8px gap either side takes past the 44pt target.
     These must sit AFTER the .is-main rule or the main row's border-color wins
     on source order at equal specificity. */
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-over[data-leg-add] {
    flex: 1 1 auto;
    align-self: stretch;
    display: flex;
    align-items: center;
    /* Centred as one unit, which is how the price read before it became a
       control -- stretching the span to fill the row must not re-space the
       text inside it. */
    justify-content: center;
    gap: 10px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row.is-added-row {
    border-color: #22c55e;
    background: rgba(34, 197, 94, .12);
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row:has(.is-leg-busy) {
    opacity: .55;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row:has(.is-leg-error) {
    border-color: #f87171;
    background: rgba(248, 113, 113, .14);
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-ln {
    font-size: 27px;
    font-weight: 600;
    color: var(--gd-text-2);
    white-space: nowrap;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row em {
    font-style: normal;
    font-size: 29px;
    font-weight: 800;
    color: var(--gd-text);
    white-space: nowrap;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-line-row.is-main em { color: #86efac; }
  /* The alt-line chevron is a real control, so it gets a real target: 76
     canvas px is ~30 physical, and the 8px column gap either side of it takes
     the touched area past 44. The base phone rule leaves it at ~33 canvas px
     (~13 physical), which is a miss waiting to happen. */
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-more-btn {
    min-height: 76px;
    padding: 0;
    width: 100%;
  }
  #mlb-game-detail .mlb-gd-mrow-r .mlb-gd-more-btn svg { width: 36px; height: 36px; }

  /* --- collapsed card (one market picked) --------------------------------
     Header + the single market row on ONE line. Everything dropped here is
     dropped ONLY here, and each drop buys width the line cannot do without.
     MEASURED at the 980px canvas: 904px of usable card width against
     ava 74 + id 240 + L5 104 + factor 175 + price 200 + 4 gaps 72 = 865.
     What goes:
       * the pitcher chip (~300px) and the market label -- the active pill
         already names the market, so the label is a repeat;
       * the "L5" caption and 4px off each bar;
       * the SECOND factor pill.
     What must NOT go is the player's name: without the min-width below the
     identity column is the only flexible thing in the row and it collapses
     to "C..." -- measured, before the floor was added. */
  #mlb-game-detail .mlb-gd-pcard.is-one {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 16px 22px;
  }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-pcard-h {
    flex: 1 1 auto;
    min-width: 0;
    padding-bottom: 0;
  }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-pcard-id { min-width: 240px; }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-pcard-chip { display: none; }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-mkt { display: none; }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-mrow.mlb-gd-prop-player {
    display: flex;
    align-items: center;
    gap: 18px;
    flex: 0 1 auto;
    min-width: 0;
    padding: 0;
    border-bottom: none;
  }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-mrow-l { gap: 0; }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-l5-lab { display: none; }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-l5 i { width: 16px; }
  /* Sibling combinator, not :nth-of-type: .mlb-gd-l5 is a <span> too, so
     counting by tag would hide the wrong pill. */
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-factor ~ .mlb-gd-factor { display: none; }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-pcard-ava,
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-pcard-ava img {
    width: 74px;
    height: 74px;
  }
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-pcard-id .mlb-gd-prop-name {
    font-size: 31px;
  }
  /* The chevron keeps its tap target but stops padding the card out to look
     like a second row of content. */
  #mlb-game-detail .mlb-gd-pcard.is-one .mlb-gd-mrow-r .mlb-gd-more-btn {
    min-height: 56px;
  }

  /* =========================================================================
     E.4  OVERVIEW TAB (section C)
     ========================================================================= */

  /* --- head-to-head starter panel (.mlb-gd-sp2) --------------------------- */
  #mlb-game-detail .mlb-gd-sp2 {
    background: var(--gd-surface-2);
    border: 1px solid var(--gd-line);
    border-radius: 26px;
    padding: 22px 20px 24px;
  }
  #mlb-game-detail .mlb-gd-sp2 > h3,
  #mlb-game-detail .mlb-gd-sp2 .mlb-gd-section-title {
    font-size: 24px;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--gd-text-3);
    margin-bottom: 18px;
  }
  /* [away] VS [home]. The two sides sit against the outer edges so the
     comparison rows below read outward from the centre line. */
  #mlb-game-detail .mlb-gd-sp2-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: 14px;
    align-items: start;
    padding-bottom: 20px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--gd-line);
  }
  /* The four children (face, name, sub, arsenal) are flat siblings, so the
     stack is built with named areas rather than nested boxes: face spans the
     name+sub rows, the chips run full width underneath. */
  #mlb-game-detail .mlb-gd-sp2-who {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "spava spnm"
      "spava spsub"
      "spars spars";
    column-gap: 14px;
    row-gap: 4px;
    align-items: center;
    min-width: 0;
  }
  #mlb-game-detail .mlb-gd-sp2-ava {
    grid-area: spava;
    align-self: start;
    flex: none;
    width: 78px;
    height: 78px;
    border-radius: 50%;
    object-fit: cover;
    object-position: center top;
    background: rgba(148, 163, 184, .08);
    border: 1px solid rgba(255, 255, 255, .06);
  }
  #mlb-game-detail .mlb-gd-sp2-ava.is-fallback { object-fit: contain; padding: 8px; }
  #mlb-game-detail .mlb-gd-sp2-nm {
    grid-area: spnm;
    align-self: end;
    font-size: 30px;
    font-weight: 700;
    /* Wraps rather than ellipsising: at 980px each side gets ~400px and a
       three-word name has to stay readable, not become "Ry...". */
    line-height: 1.08;
    color: var(--gd-text);
    text-decoration: none;
  }
  #mlb-game-detail .mlb-gd-sp2-sub {
    grid-area: spsub;
    align-self: start;
    font-size: 22px;
    color: var(--gd-text-2);
    line-height: 1.25;
  }
  #mlb-game-detail .mlb-gd-sp2-vs {
    align-self: center;
    padding-top: 22px;
    font-size: 22px;
    font-weight: 800;
    letter-spacing: .14em;
    color: var(--gd-text-3);
  }
  /* Arsenal chips: top three pitches each, colour dot + label. */
  #mlb-game-detail .mlb-gd-sp2-ars {
    grid-area: spars;
    display: flex;
    flex-wrap: wrap;
    gap: 9px;
    margin-top: 12px;
  }
  /* The home starter is the mirror of the away one: face on the OUTSIDE edge,
     text ranged right, so the two read outward from the centre line the way
     the header's two teams do. */
  #mlb-game-detail .mlb-gd-sp2-who.is-home {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "spnm spava"
      "spsub spava"
      "spars spars";
    text-align: right;
  }
  #mlb-game-detail .mlb-gd-sp2-who.is-home .mlb-gd-sp2-ars { justify-content: flex-end; }
  #mlb-game-detail .mlb-gd-sp2-ars-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 15px;
    border-radius: 999px;
    border: 1px solid var(--gd-line);
    background: var(--gd-surface-3);
    color: var(--gd-text-2);
    font-size: 20px;
    font-weight: 700;
    white-space: nowrap;
  }
  #mlb-game-detail .mlb-gd-sp2-ars-chip i {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    flex: none;
  }

  /* Comparison rows: value | (label over split bar) | value. */
  #mlb-game-detail .mlb-gd-cmp-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 46%) minmax(0, 1fr);
    align-items: center;
    gap: 14px;
    padding: 13px 0;
  }
  #mlb-game-detail .mlb-gd-cmp-v {
    font-size: 34px;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--gd-text-2);
    white-space: nowrap;
  }
  #mlb-game-detail .mlb-gd-cmp-row > .mlb-gd-cmp-v:first-child  { text-align: left; }
  #mlb-game-detail .mlb-gd-cmp-row > .mlb-gd-cmp-v:last-child   { text-align: right; }
  /* Better side in teal -- lower wins for ERA/WHIP/HR9/BB9, higher for
     K9/IPG. The builder decides which side; this only paints it. */
  #mlb-game-detail .mlb-gd-cmp-v.is-win {
    color: rgb(var(--theme-accent-rgb, 0, 211, 189));
    font-weight: 800;
  }
  #mlb-game-detail .mlb-gd-cmp-mid {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
  }
  #mlb-game-detail .mlb-gd-cmp-lab {
    font-size: 23px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--gd-text-3);
    white-space: nowrap;
  }
  /* Split bar. Deliberately does NOT set flex on its children: the builder
     may size them with an inline width or an inline flex, and either works
     as long as this rule does not impose one. */
  #mlb-game-detail .mlb-gd-cmp-bar {
    display: flex;
    align-items: stretch;
    width: 100%;
    height: 12px;
    border-radius: 999px;
    overflow: hidden;
    background: rgba(148, 163, 184, .14);
  }
  #mlb-game-detail .mlb-gd-cmp-bar > * {
    display: block;
    min-height: 100%;
    background: rgba(148, 163, 184, .38);
  }
  /* Ink by STATE, never by position. The builder stamps is-win on the better
     half (gameDetailMLBMatchup.js), and for ERA/WHIP/HR9/BB9 the longer half
     is the WORSE one -- so colouring :first-child would put the teal cue
     under the losing arm and contradict the "Teal = better" footnote. A tie
     or an unannounced starter emits no is-win and both halves stay grey. */
  #mlb-game-detail .mlb-gd-cmp-bar > .is-win {
    background: rgba(0, 211, 189, .55);
  }

  /* The comparison panel's own legend ("Teal = better of the two this
     season"). Brand-new class, styled in neither sheet before this rule, so
     it fell back to the 16px UA default. */
  #mlb-game-detail .mlb-gd-sp2-foot {
    font-size: 21px;
    line-height: 1.4;
    color: var(--gd-text-3);
    margin-top: 16px;
  }

  /* --- lineup as ROWS (.mlb-gd-lu-rows) ----------------------------------
     Replaces the 15-column table below 1000px. The section, its data-*
     attributes and both toggle rows are unchanged, so the delegated handlers
     at gameDetailMLB.js:542-564 and applyLineupStats (which queries
     "[data-batter-stats][data-player-id]" then "[data-stat=...]" and is
     tag-agnostic) keep working against div rows with zero JS changes. */
  /* AWAY first, matching the lines strip, the props team groups and desktop.
     mlb-game-detail.css:4320-4323 interleaves sp-col(1) / home(2) / sp-col(3)
     / away(4) so each starter sat above the lineup he faces -- but the phone
     fork merges both starters into one .mlb-gd-sp2 card, so orders 1 and 3
     match nothing and only the inverted lineup pair survives. Re-pair here;
     gated on the row layout so a desktop-rendered table keeps the old flow. */
  #mlb-game-detail .mlb-gd-matchup-flow:has(.mlb-gd-lu-rows) .mlb-gd-sp2 { order: 1; }
  #mlb-game-detail .mlb-gd-matchup-flow:has(.mlb-gd-lu-rows) .mlb-gd-lineup-section.is-away { order: 2; }
  #mlb-game-detail .mlb-gd-matchup-flow:has(.mlb-gd-lu-rows) .mlb-gd-lineup-section.is-home { order: 3; }

  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) {
    padding: 18px 16px 8px;
    border-radius: 34px;
  }

  /* HR FOCUS, made real on the row layout. The desktop preset is scoped to
     .mlb-gd-lineup-table (mlb-game-detail.css:4360-4372) and so could never
     reach these rows -- the pill lit up and nothing moved. The row now emits
     FIVE figures and this pair of rules picks the three that answer the
     question being asked: contact by default, power under HR Focus. Both sets
     are filled by applyLineupStats, which writes any [data-stat] it finds, so
     no JS runs on the toggle. */
  #mlb-game-detail .mlb-gd-lu-figs .mlb-gd-lu-fig[data-fig="iso"],
  #mlb-game-detail .mlb-gd-lu-figs .mlb-gd-lu-fig[data-fig="avg_ev"] {
    display: none;
  }
  #mlb-game-detail .mlb-gd-lineup-section[data-hr-focus="1"] .mlb-gd-lu-fig[data-fig="ops"],
  #mlb-game-detail .mlb-gd-lineup-section[data-hr-focus="1"] .mlb-gd-lu-fig[data-fig="k_pct"] {
    display: none;
  }
  #mlb-game-detail .mlb-gd-lineup-section[data-hr-focus="1"] .mlb-gd-lu-fig[data-fig="iso"],
  #mlb-game-detail .mlb-gd-lineup-section[data-hr-focus="1"] .mlb-gd-lu-fig[data-fig="avg_ev"] {
    display: block;
  }

  /* In-flight feedback for a mode/range refetch. gameDetailMLB.js adds
     .is-loading to the section around /mlb/get_lineup_stats; the only rule
     that consumed it (mlb-game-detail.css:718) targets .mlb-gd-lineup-tablewrap,
     which the row layout does not emit -- so the phone showed stale figures
     at full opacity and stayed tappable. Header pills sit OUTSIDE .mlb-gd-lu-rows
     and stay live, as the desktop rule intends. */
  #mlb-game-detail .mlb-gd-lineup-section.is-loading .mlb-gd-lu-rows {
    opacity: .5;
    pointer-events: none;
    transition: opacity 120ms ease;
  }

  /* Tint legend under the rows -- 10.5px in the base sheet (~4 physical px). */
  #mlb-game-detail .mlb-gd-lu-legend-row { margin: 0 4px 4px; }
  #mlb-game-detail .mlb-gd-lu-legend-row .mlb-gd-legend {
    font-size: 21px;
    gap: 10px;
  }
  #mlb-game-detail .mlb-gd-lu-legend-row .mlb-gd-legend-dot {
    width: 16px;
    height: 16px;
    margin-left: 14px;
  }
  #mlb-game-detail .mlb-gd-lu-legend-row .mlb-gd-legend-dot:first-child { margin-left: 0; }
  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) .mlb-gd-lineup-header {
    gap: 14px;
    padding: 2px 0 16px;
    margin-bottom: 10px;
  }
  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) .mlb-gd-lineup-logo {
    width: 62px;
    height: 62px;
  }
  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) .mlb-gd-lineup-team-name {
    font-size: 32px;
  }
  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) .mlb-gd-lineup-head-col {
    gap: 12px;
    row-gap: 12px;
  }
  /* Toggle pills carry the 44px target: 88 canvas px of height plus the
     group's own 2px pad. */
  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) .mlb-gd-lineup-pill {
    min-height: 88px;
    padding: 0 26px;
    font-size: 24px;
  }
  #mlb-game-detail .mlb-gd-lineup-section:has(.mlb-gd-lu-rows) .mlb-gd-lineup-toggle {
    padding: 4px;
    gap: 6px;
  }

  #mlb-game-detail .mlb-gd-lu-rows {
    display: flex;
    flex-direction: column;
  }
  #mlb-game-detail .mlb-gd-lu-row {
    display: grid;
    grid-template-columns: 44px 84px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 16px;
    padding: 16px 4px;
    border-bottom: 1px solid var(--gd-line);
  }
  #mlb-game-detail .mlb-gd-lu-row:last-child { border-bottom: none; }
  #mlb-game-detail .mlb-gd-lu-ord {
    font-size: 26px;
    font-weight: 800;
    color: var(--gd-text-3);
    text-align: center;
    font-variant-numeric: tabular-nums;
  }
  #mlb-game-detail .mlb-gd-lu-row .mlb-gd-lineup-avatar {
    width: 84px;
    height: 84px;
  }
  #mlb-game-detail .mlb-gd-lu-id {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  #mlb-game-detail .mlb-gd-lu-id .mlb-gd-lineup-name-link { font-size: 33px; }
  #mlb-game-detail .mlb-gd-lu-row .mlb-gd-lineup-meta {
    font-size: 21px;
    gap: 10px;
    flex-wrap: wrap;
  }
  #mlb-game-detail .mlb-gd-lu-row .mlb-gd-lineup-hand {
    font-size: 20px;
    padding: 3px 12px;
    border-radius: 8px;
  }
  /* Role tags (Top Target / Boom-Bust) are assigned at hydration and sit in
     the identity column. 9.5px natural is ~4 physical px -- unreadable. */
  #mlb-game-detail .mlb-gd-lu-row .mlb-gd-role-tag {
    font-size: 20px;
    padding: 4px 14px;
  }

  /* Three tinted figures (OPS / K% / AB per HR). The BOX is on [data-stat]
     itself, not on the wrapper: applyLineupStats writes textContent onto that
     element and rewrites its className (stripping only lineup-* tints), so the
     static caption must live in a SIBLING element -- an <i>/<small>/<b>
     alongside it -- and the tint must land on the box the reader sees. */
  #mlb-game-detail .mlb-gd-lu-figs {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: none;
  }
  #mlb-game-detail .mlb-gd-lu-figs > * {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    min-width: 0;
    text-align: center;
  }
  #mlb-game-detail .mlb-gd-lu-figs i,
  #mlb-game-detail .mlb-gd-lu-figs small,
  #mlb-game-detail .mlb-gd-lu-figs b {
    font-style: normal;
    font-size: 20px;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--gd-text-3);
  }
  #mlb-game-detail .mlb-gd-lu-figs [data-stat] {
    display: block;
    min-width: 112px;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid var(--gd-line);
    background: var(--gd-surface-3);
    color: var(--gd-text);
    font-size: 28px;
    font-weight: 700;
    line-height: 1.1;
    text-align: center;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* The six tier tints, added by lineupTier() at hydration. Exact alphas and
     inks copied from mlb-game-detail.css:726-731, which scopes them to
     .mlb-gd-lineup-table -- the phone rows are not a table, so they need the
     same palette under this scope. */
  #mlb-game-detail .mlb-gd-lu-figs .lineup-green-3 { background: rgba(34, 197, 94, 0.30); color: #bbf7d0; font-weight: 700; }
  #mlb-game-detail .mlb-gd-lu-figs .lineup-green-2 { background: rgba(34, 197, 94, 0.18); color: #d9f99d; }
  #mlb-game-detail .mlb-gd-lu-figs .lineup-green-1 { background: rgba(34, 197, 94, 0.09); color: #ecfccb; }
  #mlb-game-detail .mlb-gd-lu-figs .lineup-red-1   { background: rgba(239, 68, 68, 0.10); color: #fed7aa; }
  #mlb-game-detail .mlb-gd-lu-figs .lineup-red-2   { background: rgba(239, 68, 68, 0.20); color: #fca5a5; }
  #mlb-game-detail .mlb-gd-lu-figs .lineup-red-3   { background: rgba(239, 68, 68, 0.32); color: #fecaca; font-weight: 700; }

  /* Pitch-mix pill, same button renderPitchMixCell emits (minus its <td>). */
  #mlb-game-detail .mlb-gd-lu-row .mlb-gd-pm-pill {
    min-width: 96px;
    min-height: 76px;
    padding: 0 20px;
    font-size: 26px;
    border-radius: 999px;
  }

  /* --- injuries: one column (contract C4) --------------------------------- */
  #mlb-game-detail .mlb-gd-inj-grid { grid-template-columns: 1fr; gap: 18px; }
  #mlb-game-detail .mlb-gd-inj-team { font-size: 24px; }
  #mlb-game-detail .mlb-gd-inj-row { padding: 14px 0; }
  #mlb-game-detail .mlb-gd-inj-name   { font-size: 28px; }
  #mlb-game-detail .mlb-gd-inj-pos    { font-size: 21px; margin-left: 12px; }
  #mlb-game-detail .mlb-gd-inj-status { font-size: 20px; padding: 4px 12px; }
  #mlb-game-detail .mlb-gd-inj-desc   { font-size: 23px; margin-top: 6px; line-height: 1.4; }
  #mlb-game-detail .mlb-gd-inj-return { font-size: 21px; margin-top: 4px; }
  #mlb-game-detail .mlb-gd-inj-empty,
  #mlb-game-detail .mlb-gd-empty      { font-size: 24px; padding: 14px 0; }

  /* =========================================================================
     E.5  WEATHER TAB (section D)
     All of it is scoped through the weather PANEL as well as the root, so the
     shared renderWeatherPanel consumers (player-dashboard Q2, the props
     popup) keep the sizes they were designed with even when they render
     inside this page.
     ========================================================================= */

  /* The phone stack (.wxt.wxt-ph) is one column of full-width cards. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-ph { gap: 18px; }

  /* --- 1. verdict -------------------------------------------------------- */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict {
    display: flex;
    align-items: center;
    gap: 22px;
    padding: 24px 22px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict-ring { flex: none; }
  /* 190px canvas = ~76 physical px -- the score is the headline of the tab. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict .wxt-gauge {
    width: 190px;
    height: 190px;
  }
  /* The gauge's own rating label is a 10px SVG <text> (~4 physical px) and it
     sits outside .wxp-field, so the field rule above cannot reach it. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict .wxt-gauge-rating {
    font-size: 22px;
  }
  /* wxtGauge lays the number out to leave room for a rating word beneath it
     (baseline y=57 of a 120 viewBox, rating at y=76). The phone verdict shows
     the tier OUTSIDE the ring and passes an empty rating, so the number was
     left sitting at 36% of the ring instead of on its centre. Push it back to
     the middle; SVG y is an attribute, so this has to be a transform. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict .wxt-gauge-num {
    transform: translateY(15px);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict-txt { min-width: 0; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict-tier {
    font-size: 40px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--tone, var(--gd-text));
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict-cap {
    font-size: 21px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--gd-text-3);
    margin-top: 4px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-verdict-line {
    font-size: 26px;
    line-height: 1.45;
    color: var(--gd-text-2);
    margin-top: 12px;
  }

  /* --- 2. condition tiles ------------------------------------------------ */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tiles {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    padding: 20px 18px;
    background: #131515;              /* NFL --ngd-ink-100 (parity pass) */
    border: 1px solid #171A1A;
    border-radius: 24px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile-lbl {
    font-size: 22px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--gd-text-3);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile-main {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile-main > i {
    font-size: 32px;
    width: 40px;
    text-align: center;
    flex: none;
    color: var(--tone, var(--gd-text-2));
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile-val {
    font-size: 38px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--gd-text);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-tile-sub {
    font-size: 23px;
    line-height: 1.4;
    color: var(--gd-text-2);
  }

  /* --- 3. field, FULL CARD WIDTH ----------------------------------------
     E3: the desktop stage is capped at 360px (mlb-game-detail.css:3266) --
     that cap is what made the phone field a stamp. renderWindyField is called
     with width:910 and the stage below lets the SVG use all of it. The cap is
     lifted only for a stage that sits inside .wxp-field, so the desktop
     .wxt-fld-stage is untouched. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field {
    padding: 18px 16px 18px;
    overflow: hidden;
  }
  /* The stage is the ONLY thing standing between renderWindyField's 910px
     SVG and the card edge. The desktop .wxt-fld-stage cap stays where it is. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field-stage,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field .wxt-fld-stage,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field .wh-stage {
    flex: 1 1 auto;
    width: 100%;
    max-width: none;
    min-width: 0;
    margin: 0 auto;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field .wh-stage svg {
    width: 100%;
    height: auto;
    display: block;
  }
  /* Caption naming the park + the wind. */
  /* renderWindyField injects its own <style> with fixed px type, which does
     NOT scale with the 910px width we ask for -- the carry distances drawn on
     the grass land at 15px. Overridden here; the SVG has no id scope of its
     own so this is the only place it can be reached. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field svg text {
    font-size: 22px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field-cap {
    margin-top: 14px;
    padding: 14px 16px;
    text-align: center;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: .06em;
    line-height: 1.4;
    color: var(--gd-text-2);
    border: 1px solid var(--gd-line);
    border-radius: 16px;
  }
  /* Carry strip under the field: LF | CF | RF. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-carry {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    margin-top: 14px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-carry-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-width: 0;
    padding: 16px 10px;
    background: #131515;              /* NFL --ngd-ink-100 (parity pass) */
    border: 1px solid var(--gd-line);
    border-radius: 18px;
    text-align: center;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-carry-lbl {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--gd-text-3);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-carry-val {
    font-size: 34px;
    font-weight: 800;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--tone, var(--gd-text));
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-carry-sub {
    font-size: 20px;
    color: var(--gd-text-3);
  }

  /* --- 4. hourly row -----------------------------------------------------
     .wxp-hours is a .wxt-card (title + body), so the three cells are laid
     out on .wxp-hr-body, NOT on the card. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hours { padding-bottom: 18px; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-body {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    padding: 16px 18px 0;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 18px 10px;
    background: var(--gd-surface-2);
    border: 1px solid var(--gd-line);
    border-radius: 20px;
    text-align: center;
  }
  /* First pitch is the hour that matters -- it gets the blue card. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-cell.is-first {
    border-color: rgba(92, 168, 240, .28);
    background: rgba(92, 168, 240, .10);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-time {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    font-size: 26px;
    font-weight: 700;
    color: var(--gd-text);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-badge {
    font-size: 20px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #5CA8F0;
    background: rgba(92, 168, 240, .18);
    border-radius: 8px;
    padding: 4px 12px;
    white-space: nowrap;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-ic   { font-size: 40px; margin: 4px 0; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-temp {
    font-size: 36px;
    font-weight: 800;
    color: var(--gd-text);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-wind,
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-cond {
    font-size: 22px;
    line-height: 1.35;
    color: var(--gd-text-2);
  }
  /* Fallback branch (roof closed, or an ingest with no forecast_hours) emits
     ONE cell plus this note as siblings inside the 3-column grid, so without
     a span the note lands as grid item 2 -- a column of wrapped text beside
     the hour instead of a caption under it. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-note {
    grid-column: 1 / -1;
    font-size: 22px;
    line-height: 1.4;
    color: var(--gd-text-3);
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-hr-carry {
    font-size: 24px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--tone, var(--gd-text-2));
  }

  /* --- 5. weather-adjusted props: capped list + reveal -------------------- */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props { padding: 18px 16px; }
  /* The rows are wxRowHtml verbatim, so they carry the pre-existing wx-*
     classes, sized by mlb-game-detail.css:2414-2425 at that sheet's older
     ~1.35x phone scale (12-16px = 4.8-6.4 physical px). Bring them up to this
     sheet's band; single-class base rules lose to the id scope with no
     !important. Scoped through .wxp-props so the desktop groups, the player
     dashboard and the props popup keep their own sizes. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wxrow {
    grid-template-columns: 84px minmax(0, 1fr) auto;
    gap: 18px;
    padding: 22px 0;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-ava {
    width: 84px;
    height: 84px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-bet {
    font-size: 28px;
    gap: 12px;
    margin-top: 6px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-hand {
    font-size: 20px;
    padding: 3px 12px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-chips {
    gap: 10px;
    margin-top: 12px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wxchip {
    font-size: 22px;
    padding: 6px 16px;
  }
  /* The pill grows with its two children, so its height is set explicitly or
     the 26/28px glyphs clip against the base sheet's 48px box. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-pill {
    height: 76px;
    padding: 0 20px;
    gap: 12px;
    border-radius: 16px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-ic { font-size: 26px; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-props .mlb-gd-wx-od { font-size: 28px; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-more-wrap { display: block; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    min-height: 96px;
    margin-top: 12px;
    padding: 0 20px;
    background: var(--gd-surface-3);
    border: 1px solid var(--gd-line-strong);
    border-radius: 20px;
    color: rgb(var(--theme-accent-rgb, 0, 211, 189));
    font-size: 26px;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
  }
  /* details/summary variant: kill the disclosure triangle so the row reads as
     a button either way. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] summary.wxp-more {
    list-style: none;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] summary.wxp-more::-webkit-details-marker {
    display: none;
  }

  /* --- shared weather chrome at phone scale ------------------------------
     Whatever of the existing wxt-* furniture the phone builder reuses
     (card titles, the roof / no-data messages) has to come up to the same
     size band or it reads as fine print next to the tiles above. */
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-card { border-radius: 24px; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-card-title {
    font-size: 24px;
    letter-spacing: .12em;
    padding: 20px 20px 0;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-card-sub { font-size: 22px; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-msg {
    padding: 60px 26px;
    font-size: 26px;
    line-height: 1.5;
    border-radius: 26px;
  }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-msg-venue { font-size: 36px; }
  #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxt-roof-pill {
    font-size: 20px;
    padding: 6px 18px;
  }

  /* =========================================================================
     E.6  REDUCED MOTION
     Only two things move on this layout: the CSS transitions this sheet adds
     to the pressable chrome, and the 15 animated gust nodes renderWindyField
     injects into the field SVG. Both stop. The field still draws -- the wind
     arrows just hold still, which is the whole point of the preference.
     ========================================================================= */
  @media (prefers-reduced-motion: reduce) {
    #mlb-game-detail .mlb-gd-pills--grid .mlb-gd-pill,
    #mlb-game-detail .mlb-gd-pcard-chip,
    #mlb-game-detail .mlb-gd-mrow-meta .mlb-gd-factor,
    #mlb-game-detail .mlb-gd-lu-row .mlb-gd-pm-pill,
    #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-more {
      transition: none !important;
    }
    #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field .wh2-gust,
    #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field .wh-gust,
    #mlb-game-detail .mlb-gd-tab-panel[data-panel="weather"] .wxp-field svg * {
      animation: none !important;
    }
  }
}
