/* ═══════════════════════════════════════════════════════════════════════════
   MLB STAGE — the #/mlb night-game treatment
   ---------------------------------------------------------------------------
   Owner (2026-08-07): "totally revolutionize the mlb page to be flashy and cool."

   WHAT WAS WRONG, MEASURED. The page ran 4,522px as: dark nav -> dark slate ->
   navy hero -> ~1,900px of ONE uniform light-grey floor carrying six near-
   identical white list cards -> two dark bands -> navy -> footer. The hero was a
   static wall of type, the Value Landscape was a 2px line in a 150px box, and
   every module below the hero shared one rhythm (head row + ranked list). Nothing
   crescendoed and nothing had depth.

   THE MOVE. The whole page becomes one dark broadcast stage instead of a light
   slab bookended by dark. Cards become glass on that field with a per-section
   accent rim, the hero gains real depth (layered glows + a field-geometry plate),
   and the slate becomes a live marquee. No section entrance animation — see the
   note below for why that was built twice and removed twice.

   SCOPING + UNDO. Undo is: delete this file and its one <link> in index.html. No
   existing rule was edited.

   `#homeStage` IS NOT A SUFFICIENT SCOPE, despite appearances. The PORTAL at `#/`
   renders it too, so anything that PAINTS must additionally require `.hv2`, the
   MLB stage's own wrapper, which is absent from #homeStage on `#/`. An earlier
   version scoped the field to `#homeStage` alone — on the strength of having
   checked `#/rankings`, where MAIN.hv2-stage really is `display: none` — and
   shipped a black portal with the portal's own navy headings unreadable on top of
   it. Checking one other route is not checking every other route.

   CONTRAST IS THE RISK, NOT THE PALETTE. A previous dark-band pass on this page
   shipped a background swap without theming the contents and left names at 1.1:1.
   So this file inventories all 49 text-bearing element types measured on the live
   page and themes the 22 that were dark-on-light. That inventory is the section
   marked "INVERTED CONTENT" — do not add a dark surface here without extending it.
   ═══════════════════════════════════════════════════════════════════════════ */

#homeStage {
  --ms-bg:      #05080f;
  --ms-bg2:     #0a1020;
  --ms-panel:   rgba(150,180,225,.055);
  --ms-panel2:  rgba(150,180,225,.085);
  --ms-line:    rgba(150,180,225,.14);
  --ms-line2:   rgba(150,180,225,.24);
  --ms-text:    #eef4fc;
  --ms-mut:     #9fb4d0;
  --ms-dim:     #708aab;
  --ms-brand:   #4f8ff7;
  --ms-cyan:    #22d3ee;
  --ms-violet:  #a78bfa;
  --ms-emerald: #34d399;
  --ms-amber:   #fbbf24;
  --ms-rose:    #fb7185;
  /* Seventh accent. Six hues could not give seven cards a distinct rim, and both
     grids count nth-child within themselves, so the second grid repeated the
     first's blue/violet. Teal sits between cyan and emerald but both are two
     cards away in page order, and it echoes the #0f766e this card is given in
     _hv2VsMarketHtml. */
  --ms-teal:    #2dd4bf;

}

/* ── The field ────────────────────────────────────────────────────────────
   MEASURED: #homeStage is 1220px inside a 1440px viewport — MAIN.hv2-stage sits
   in DIV.page (`padding: 0 32px 100px`) inside a BODY painted rgb(238,242,247).
   So a background on #homeStage alone leaves a 110px LIGHT GUTTER down both
   sides and a 100px light band above the footer, which is exactly what the first
   attempt shipped. The field therefore paints on a VIEWPORT-FIXED backdrop
   layer, not on the element.

   IT IS ABSOLUTE, NOT FIXED, AND THAT IS THE WHOLE POINT. A viewport-fixed
   layer also covers FOOTER#siteLegalFooter, which lives OUTSIDE #homeStage and
   whose text is rgb(12,31,56) / rgb(32,56,79) — about 1.2:1 on this field. The
   first version did exactly that and made the footer unreadable. Bounding the
   layer to the stage's own height means the footer keeps the light background it
   was designed for, and no rule here has to reach outside #homeStage.

   `background-attachment: fixed` still pins the glows to the VIEWPORT, so they
   stay anchored while 4,100px of content scrolls over them — the depth of a
   fixed layer without its blast radius.

   IT PAINTS ON `.hv2`, NOT ON `#homeStage`, AND THAT DISTINCTION IS LOAD-BEARING.
   `#homeStage` is NOT unique to this page. The PORTAL at `#/` renders it too — the
   first version scoped the field to `#homeStage` on the strength of having checked
   `#/rankings` (where MAIN.hv2-stage really is `display: none`) and shipped a black
   portal with the portal's own navy headings on top of it: "What managr does" and
   "What makes it different" at rgb(12,31,56) on rgb(5,8,15), about 1.2:1.
   Checking one other route is not checking every other route.

   `.hv2` is the honest discriminator: it is the MLB stage's own wrapper and it is
   absent from #homeStage on `#/` (measured). Everything that PAINTS therefore hangs
   off `.hv2`. The custom properties above may stay on #homeStage — they only
   resolve, they never render. */
#homeStage .hv2 {
  position: relative;
  z-index: 1;
  background-color: var(--ms-bg);
  color: var(--ms-text);

  /* HOVER SURFACES — the same failure as the header warning, one level down.
     redesign.css hovers four row types with `background: var(--surface-soft)`,
     a LIGHT #f6f8fb built for the light page. Inside this dark stage that puts
     a near-white bar under near-white text. MEASURED 2026-08-08 on the live
     board: .hv2-edge__row (Managr vs Market) and .hv2-news__row (Player News)
     hovered at 1.04:1 — invisible. The inventory below themed resting colours
     and missed hover, so only .hv2-lb__row had an explicit override.
     Rebinding the TOKEN rather than listing selectors fixes all four at once
     and covers any row type added later — which is the trap that caused this.

     DECLARED ON `.hv2`, NOT ON `#homeStage`. It arrived on #homeStage, where it
     was inert only by luck: #homeStage renders on the PORTAL and every workspace
     too, and a token that feeds `background` is paint by proxy. Measured at the
     time: 41 rules consume --surface-soft and none of them matched an element
     inside #homeStage on #/, #/dashboard or #/research — true, but a fact about
     today's markup, not a property of the scope. On `.hv2` it cannot reach
     another route at all, and the four row types still inherit it. */
  --surface-soft: rgba(150,180,225,.06);

  /* HOVER TEXT — the same bug in the other channel, found only because fixing
     the background above stopped masking it. Every card on this stage is an
     <a>, and the light page hovers links DARK:

       a:hover { color: var(--brand-deep) }   styles.css
       a:hover { color: var(--accent-deep) }  polish.css   (later file, wins)

     Both resolve to rgb(22,73,127) — navy, correct on white, near-invisible on
     this field. MEASURED 2026-08-08: hovering "Open Rankings" 1.82:1, the KPI
     tiles 1.82, My Fantasy 1.89, a game card 1.96, a Beat row 2.01, a Player
     News row 2.04. All six are the SAME rule, not six defects.

     Rebound as tokens rather than as `#homeStage .hv2 a:hover { color: … }`,
     which would score 10301 and CLOBBER the deliberate white-on-hover rules
     already in this file (.hv2-lb__name, .hv2-slate__all, .hv2-blog__head a,
     all 10200). Rebinding touches no specificity, so those still win.
     Safe on the same test as above: measured ZERO elements inside .hv2
     rendering either token at rest, and ZERO stage-scoped rules consuming
     them — so this reaches the link hover colour and nothing else. */
  --accent-deep: var(--ms-text);
  --brand-deep:  var(--ms-text);
}
#homeStage .hv2::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  z-index: -1;
  pointer-events: none;
  background-color: var(--ms-bg);
  background-image:
    radial-gradient(920px 520px at 14% -6%,  rgba(79,143,247,.20), transparent 62%),
    radial-gradient(760px 460px at 88% 4%,   rgba(167,139,250,.16), transparent 60%),
    radial-gradient(1100px 700px at 50% 42%, rgba(34,211,238,.055), transparent 66%),
    repeating-linear-gradient(115deg, rgba(150,180,225,.022) 0 1px, transparent 1px 74px);
  background-attachment: fixed, fixed, fixed, scroll;
}

/* ── NO ENTRANCE ANIMATION ON THE SECTIONS — deliberate, twice over ───────
   Two versions of a section reveal were built and both were removed:

   1. An IntersectionObserver scroll-reveal shipped a page where all 8 sections
      measured inView:true / opacity:0. An observer does not reliably deliver its
      first callback while the tab is not being rendered, and the setTimeout
      backstop added to rescue it is throttled in exactly the same state, so both
      recovery paths failed together.
   2. Replacing it with a pure-CSS `@keyframes` fade-up did not help either: a
      suspended tab does not advance animations, so every section sat at the
      `from` keyframe — opacity 0 — with `animation-fill-mode: both` unable to
      save it, because the animation had not finished, it had not started.

   The common failure is structural: ANY technique whose resting state is
   invisible converts "this tab is not being painted right now" into "this page
   is blank", and it does so in precisely the conditions where nobody is looking
   to catch it. Content is not allowed to depend on motion having run.

   The page is not short of motion — the slate marquee, the hero aurora sweep,
   the live pulse and the hover lifts all animate, and every one of them fails to
   a correct, fully readable static state. Do not reintroduce a section reveal
   without solving the resting-state problem first. */

/* ═══ SLATE MARQUEE ═══════════════════════════════════════════════════════
   Was a static clipped row where the 15th game died mid-card at the right edge.
   Now it scrolls continuously. _hv2SlateHtml() emits the game track TWICE (the
   second copy aria-hidden) and the animation translates exactly -50%, so the
   loop is seamless with no JS and no measurement. */
#homeStage .hv2 .hv2-slate {
  background: linear-gradient(180deg, #070c17, #0a1120);
  border-bottom: 1px solid var(--ms-line);
  padding: 0;
  margin: 0;
}
#homeStage .hv2 .hv2-slate__inner {
  max-width: none;
  padding: 14px 0 16px;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
#homeStage .hv2 .hv2-slate__head {
  padding: 0 28px 12px;
  max-width: 1680px;
  margin: 0 auto;
}
#homeStage .hv2 .hv2-slate__title {
  color: var(--ms-text);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
#homeStage .hv2 .hv2-slate__dot {
  background: var(--ms-emerald);
  box-shadow: 0 0 0 3px rgba(52,211,153,.18), 0 0 12px rgba(52,211,153,.8);
  animation: msPulse 2.4s ease-in-out infinite;
}
@keyframes msPulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(52,211,153,.18), 0 0 12px rgba(52,211,153,.8); }
  50%      { box-shadow: 0 0 0 6px rgba(52,211,153,.05), 0 0 18px rgba(52,211,153,.35); }
}
#homeStage .hv2 .hv2-slate__live {
  color: #0a1120;
  background: var(--ms-cyan);
  border-radius: 999px;
  padding: 2px 8px;
  font-weight: 900;
  letter-spacing: .1em;
}
#homeStage .hv2 .hv2-slate__all { color: var(--ms-mut); }
#homeStage .hv2 .hv2-slate__all:hover { color: var(--ms-text); }

/* The viewport: fade the two ends so cards enter and leave instead of being
   guillotined by the edge. */
#homeStage .hv2 .ms-marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
#homeStage .hv2 .ms-marquee__rail { display: flex; width: max-content; animation: msScroll 64s linear infinite; }
#homeStage .hv2 .ms-marquee:hover .ms-marquee__rail { animation-play-state: paused; }
@keyframes msScroll { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }

#homeStage .hv2 .hv2-slate__track { display: flex; gap: 10px; padding: 0 5px; flex: 0 0 auto; }
#homeStage .hv2 .hv2-game {
  background: var(--ms-panel);
  border: 1px solid var(--ms-line);
  border-radius: 10px;
  min-width: 208px;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
#homeStage .hv2 .hv2-game:hover {
  background: var(--ms-panel2);
  border-color: var(--ms-line2);
  transform: translateY(-2px);
}
#homeStage .hv2 .hv2-game__time { color: var(--ms-dim); font-size: 11px; letter-spacing: .06em; }
#homeStage .hv2 .hv2-game__abbr { color: var(--ms-text); }
#homeStage .hv2 .hv2-game__sp   { color: var(--ms-dim); }
#homeStage .hv2 .hv2-game__bar  { border-radius: 2px; box-shadow: 0 0 10px currentColor; }

/* ═══ HERO STAGE ══════════════════════════════════════════════════════════ */
#homeStage .hv2 .hv2-masthead--showcase {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(900px 460px at 50% 118%, rgba(79,143,247,.30), transparent 70%),
    linear-gradient(180deg, #070d1c 0%, #0b1426 62%, #070c18 100%);
  border-bottom: 1px solid var(--ms-line);
  padding-block: 78px 64px;
}
/* Field-geometry plate: a diamond + two arcs, drawn in CSS so there is no asset
   to ship and it scales at any width. Deliberately near-invisible (.05 alpha) —
   it reads as texture, not decoration. */
#homeStage .hv2 .hv2-masthead--showcase::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -46%;
  width: 1180px;
  height: 1180px;
  transform: translateX(-50%) rotate(45deg);
  border: 1px solid rgba(150,190,255,.055);
  border-radius: 46px;
  background: linear-gradient(135deg, rgba(79,143,247,.05), transparent 55%);
  pointer-events: none;
}
/* Aurora sweep — one slow horizontal pass. 22s so it is felt, not watched. */
#homeStage .hv2 .hv2-masthead--showcase::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 32%, rgba(120,180,255,.085) 50%, transparent 68%);
  transform: translate3d(-35%, 0, 0);
  animation: msSweep 22s ease-in-out infinite;
  pointer-events: none;
}
@keyframes msSweep {
  0%, 100% { transform: translate3d(-35%, 0, 0); }
  50%      { transform: translate3d(35%, 0, 0); }
}
#homeStage .hv2 .hv2-hero { position: relative; z-index: 2; }

#homeStage .hv2 .hv2-hero__wordmark {
  color: #fff;
  text-shadow: 0 0 46px rgba(120,175,255,.42);
}
#homeStage .hv2 .hv2-hero__sport {
  background: linear-gradient(92deg, var(--ms-cyan), var(--ms-brand) 55%, var(--ms-violet));
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  font-weight: 600;
}
#homeStage .hv2 .hv2-hero__title { color: #fff; text-shadow: 0 6px 40px rgba(4,10,22,.6); }
/* The accent line is already display:block (it broke mid-line otherwise — see
   project_fantasy_mlb_showcase_band). Gradient wash, same direction as the
   wordmark so the two read as one system. */
#homeStage .hv2 .hv2-hero__title b {
  background: linear-gradient(92deg, #7cc4ff 0%, var(--ms-brand) 46%, var(--ms-violet) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
#homeStage .hv2 .hv2-hero__lede { color: #a9c1dd; }

#homeStage .hv2 .hv2-btn {
  border-radius: 999px;
  border: 1px solid var(--ms-line2);
  background: rgba(150,180,225,.07);
  color: var(--ms-text);
  backdrop-filter: blur(8px);
  transition: transform .16s ease, background .16s ease, border-color .16s ease, box-shadow .16s ease;
}
#homeStage .hv2 .hv2-btn:hover {
  transform: translateY(-2px);
  background: rgba(150,180,225,.13);
  border-color: rgba(150,190,255,.42);
}
/* Face deepened from #4f8ff7 -> #2f6fd8 to clear AA on its own label.
   For a gradient the honest test is the text against its LIGHTEST stop, not its
   average: the old top stop put white 14px/700 at 3.18:1, under the 4.5 bar (the
   button is bold but 14px, so it is not "large text" and gets no 3:1 allowance).
   #356cc8 measures 5.08:1. The hue is unchanged — this is the same blue a step
   deeper, so the CTA still reads as the brand accent against the field, and the
   glow beneath it does the lifting that the lighter fill used to attempt.
   The saturated #4f8ff7 survives as --ms-brand for rims, icons and the KPI
   hairline, where it sits under no text and its brightness is the point. */
#homeStage .hv2 .hv2-btn--primary {
  background: linear-gradient(180deg, #356cc8, #1f52a8);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 8px 26px rgba(47,111,216,.44), inset 0 1px 0 rgba(255,255,255,.22);
}
/* The primary CTA must RESTATE its background on hover, not just its shadow.
   `.hv2-btn:hover` scores (1,3,0) and `.hv2-btn--primary` only (1,2,0), so the
   generic hover's translucent grey outranked the primary's gradient: the button
   went flat grey on hover while its glow bloomed underneath — a lit shadow around
   a dead face. NOT a regression from the .hv2 rescoping; the same pair was
   (1,2,0) vs (1,1,0) before it, so the gradient always lost. This rule ties the
   generic at (1,3,0) and wins on order, being later in the file.

   BOTH STATES ARE JUDGED ON THE GRADIENT'S LIGHTEST STOP, not its average — that
   is where a vertical gradient is worst for white text. History worth keeping,
   because the obvious move was the wrong one twice over: the face used to be
   #4f8ff7 (3.18:1 at rest, under AA), and the first attempt at this hover
   BRIGHTENED it to #6ba3ff, reaching 2.53:1 — the label got harder to read the
   moment you pointed at it. Both states are now deep enough to clear the bar,
   with the resting face at 5.08:1 and this one at 4.54:1.

   Hover is a shade LIGHTER than rest, which is the conventional direction, and
   the real work is done by the halo rather than the fill: a brighter bloom around
   a deep face reads as lit far better than brightening the face did. */
#homeStage .hv2 .hv2-btn--primary:hover {
  background: linear-gradient(180deg, #3a74d4, #245ab4);
  border-color: transparent;
  box-shadow: 0 14px 38px rgba(79,143,247,.65), 0 0 0 1px rgba(150,190,255,.35), inset 0 1px 0 rgba(255,255,255,.28);
}

/* ── KPI pillars ──────────────────────────────────────────────────────────
   Numbers stay HARDCODED and paint instantly. No count-up: the owner rejected
   it twice (it read as "still loading") and the functions were deleted. Do not
   reintroduce one here. */
#homeStage .hv2 .hv2-kpis { position: relative; z-index: 2; gap: 12px; }
#homeStage .hv2 .hv2-kpi {
  position: relative;
  background: linear-gradient(180deg, rgba(150,180,225,.085), rgba(150,180,225,.03));
  border: 1px solid var(--ms-line);
  border-radius: 14px;
  overflow: hidden;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
#homeStage .hv2 .hv2-kpi::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--ms-brand), transparent);
  opacity: .8;
}
#homeStage .hv2 .hv2-kpi:hover {
  transform: translateY(-3px);
  border-color: rgba(150,190,255,.4);
  box-shadow: 0 14px 40px rgba(3,8,20,.6);
}
#homeStage .hv2 .hv2-kpi__n {
  color: #fff;
  letter-spacing: -.03em;
  text-shadow: 0 0 30px rgba(120,175,255,.35);
}
#homeStage .hv2 .hv2-kpi__n.is-pos { color: var(--ms-emerald); text-shadow: 0 0 30px rgba(52,211,153,.45); }
/* --ms-mut, NOT --ms-dim, and the reason is a backdrop the inventory missed.
   The header note above measures "dim #708aab 5.7:1 … all against #05080f", and
   that is correct — against the FIELD. But the KPI labels do not sit on the
   field: the tile is a lighter panel, measured rgb(38,60,97), where the same ink
   is 3.12:1. The .hv2-stat__sub labels are the same story on rgb(30,35,45).
   --ms-mut #9fb4d0 gives 5.21 on the KPI panel and 7.43 on the stat panel.

   The claim was not wrong, it was measured somewhere else. Any --ms-dim leaf
   that renders on a raised panel rather than the field needs re-checking the
   same way. */
#homeStage .hv2 .hv2-kpi__l { color: var(--ms-mut); letter-spacing: .1em; }
#homeStage .hv2 .hv2-kpi.is-edge::before { background: linear-gradient(90deg, transparent, var(--ms-emerald), transparent); }

/* ═══ CARDS ═══════════════════════════════════════════════════════════════
   One glass treatment, differentiated by an accent rim rather than by shape —
   six differently-shaped cards would read as noise, six differently-lit ones
   read as sections. --ms-a is set per card by the section rules below. */
#homeStage .hv2 .hv2-card {
  --ms-a: var(--ms-brand);
  position: relative;
  background: linear-gradient(180deg, rgba(150,180,225,.07), rgba(150,180,225,.028));
  border: 1px solid var(--ms-line);
  border-radius: 16px;
  box-shadow: 0 22px 60px rgba(2,6,16,.5);
  backdrop-filter: blur(10px);
  overflow: hidden;
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
/* ACCENT BLOOM AND TOP HAIRLINE REMOVED 2026-08-12 (owner: "eliminate these
   color shadows in these 4 boxes").

   Both were built for the DARK broadcast stage, where a 260px radial gradient of
   the card's accent colour at .12 opacity read as light falling on glass, and a
   1px accent gradient along the top edge read as a lit rim. The masthead is
   light now and the cards are white, so the same two effects render as a
   coloured smudge in the corner and a coloured streak along the top — measured
   on Top Players as radial-gradient(circle, rgb(29,95,167)) sitting on
   rgb(255,255,255).

   THE ACCENT RIM BESIDE EACH TITLE STAYS. That is the solid 5px bar carrying the
   per-card hue, which is the deliberate section marker, not a glow. Removing the
   diffuse colour and keeping the solid mark is the whole point: the colour still
   identifies the card, it just no longer bleeds across it.

   To restore for a dark surface, put both blocks back; --ms-a is untouched. */
#homeStage .hv2 .hv2-card:hover {
  border-color: rgba(150,190,255,.34);
  box-shadow: 0 28px 74px rgba(2,6,16,.62);
}
#homeStage .hv2 .hv2-card__head {
  border-bottom: 1px solid var(--ms-line);
  background: rgba(6,11,22,.35);
  position: relative;
  z-index: 1;
}
#homeStage .hv2 .hv2-card__title { color: #fff; }
#homeStage .hv2 .hv2-card__body  { position: relative; z-index: 1; }
#homeStage .hv2 .hv2-accent {
  box-shadow: 0 0 14px var(--ms-a);
  background: var(--ms-a) !important; /* overrides the inline per-card colour */
}
#homeStage .hv2 .hv2-eyebrow { color: var(--ms-dim); }
#homeStage .hv2 .hv2-card__all {
  color: var(--ms-mut);
  border: 1px solid var(--ms-line);
  border-radius: 999px;
  padding: 5px 11px;
  transition: color .16s ease, border-color .16s ease, background .16s ease;
}
#homeStage .hv2 .hv2-card__all:hover {
  color: #fff;
  border-color: rgba(150,190,255,.45);
  background: rgba(150,180,225,.1);
}

/* Per-section accent hues, in page order.

   EVERY RULE HERE MUST SET `--ms-a` ON `.hv2-card` ITSELF, never on something
   inside it. `_hv2Card` puts the rim in `.hv2-card__head` and the section's own
   markup in `.hv2-card__body`, which are SIBLING subtrees — and custom
   properties inherit downward, not sideways. Value Landscape was written as
   `.hv2-land { --ms-a: cyan }`, but `.hv2-land` IS the body content, so the
   declaration landed below the rim and could never reach it: the card fell back
   to the `--ms-a: var(--ms-brand)` default and the showpiece rendered the same
   blue as Top Players. Measured rgb(79,143,247) where cyan #22d3ee was intended.
   `:has()` targets the card from a body-only marker (used 33× elsewhere in the
   site's CSS). The wrapper-div idiom the other sections use (`.hv2-beat`,
   `.hv2-statwrap`) would need an app.js change, which would cost this file its
   "undo = delete the file and its one <link>" property. */
#homeStage .hv2 .hv2-card:has(.hv2-land) { --ms-a: var(--ms-cyan); }
#homeStage .hv2 .hv2-grid > :nth-child(1) .hv2-card,
#homeStage .hv2 .hv2-grid > .hv2-card:nth-child(1) { --ms-a: var(--ms-brand); }
#homeStage .hv2 .hv2-grid > :nth-child(2) .hv2-card,
#homeStage .hv2 .hv2-grid > .hv2-card:nth-child(2) { --ms-a: var(--ms-violet); }
/* Second grid gets its own pair. `nth-child` counts within EACH grid, so the two
   rules above hand both grids the same blue/violet and Managr vs Market repeated
   Top Players. Keyed to the content it holds rather than `:nth-of-type(2)`,
   which would silently re-colour whichever grid happened to be second if the
   page order ever changes. Teal is the cool half, rose the warm half, so the two
   cards separate side by side; rose also stays clear of the amber directly below
   it. The rose "market is higher" deltas INSIDE the teal card still read as a
   signal rather than as the card's own identity. */
#homeStage .hv2 .hv2-grid:has(.hv2-edge) > .hv2-card:nth-child(1) { --ms-a: var(--ms-teal); }
#homeStage .hv2 .hv2-grid:has(.hv2-edge) > .hv2-card:nth-child(2) { --ms-a: var(--ms-rose); }
#homeStage .hv2 .hv2-beat    .hv2-card { --ms-a: var(--ms-amber); }
#homeStage .hv2 .hv2-statwrap .hv2-card { --ms-a: var(--ms-emerald); }

/* ═══ VALUE LANDSCAPE — the showpiece ═════════════════════════════════════
   Was a 2px line in a 150px box reading as an empty card. Given real height, a
   glowing stroke and a deeper fill, it becomes the visual anchor of the page.
   The SVG uses preserveAspectRatio="none", so height is set on the element. */
#homeStage .hv2 .hv2-land__chart {
  height: 300px;
  filter: drop-shadow(0 0 14px rgba(34,211,238,.4));
}
#homeStage .hv2 .hv2-land__chart path[fill^="url"] { opacity: 1; }
#homeStage .hv2 .hv2-land__chart path[stroke] { stroke: var(--ms-cyan) !important; stroke-width: 2.5; }
#homeStage .hv2 .hv2-land__chart line { stroke: rgba(150,180,225,.1) !important; }
#homeStage .hv2 .hv2-land__meta { color: var(--ms-dim); border-top: 1px solid var(--ms-line); padding-top: 12px; }
#homeStage .hv2 .hv2-land__meta span:nth-child(2) { color: var(--ms-mut); font-style: italic; }

/* ═══ INVERTED CONTENT ════════════════════════════════════════════════════
   The 22 element types measured dark-on-light on the previous build. Each is
   re-themed explicitly rather than by a blanket `color: inherit`, because these
   carry MEANING (rank, delta direction, position colour) that a blanket rule
   flattens. Counts are from the live page at 1440px. */

/* Ranked lists — Top Players / Top Dynasty (n=20 each) */
#homeStage .hv2 .hv2-lb__rank { color: var(--ms-dim); }
#homeStage .hv2 .hv2-lb__name { color: var(--ms-text); }
#homeStage .hv2 .hv2-lb__name:hover { color: #fff; }
#homeStage .hv2 .hv2-lb__val  { color: #fff; font-weight: 800; }
#homeStage .hv2 .hv2-lb tr,
#homeStage .hv2 .hv2-lb li,
#homeStage .hv2 .hv2-lb__row { border-color: var(--ms-line) !important; }
#homeStage .hv2 .hv2-lb__row:hover { background: rgba(150,180,225,.06); }

/* Position filter chips (n=18) */
#homeStage .hv2 .hv2-poschip {
  color: var(--ms-mut);
  background: rgba(150,180,225,.07);
  border: 1px solid var(--ms-line);
  border-radius: 999px;
  transition: color .14s ease, background .14s ease, border-color .14s ease;
}
#homeStage .hv2 .hv2-poschip:hover { color: #fff; background: rgba(150,180,225,.14); }
#homeStage .hv2 .hv2-poschip.is-on,
#homeStage .hv2 .hv2-poschip[aria-pressed="true"] {
  color: #06101f;
  background: var(--ms-brand);
  border-color: transparent;
  font-weight: 800;
}

/* Managr vs Market (n=22 + 4 + 2). The teal/red pair moves UP the scale rather
   than being neutralised — buy-low vs market-ahead is the point of the module. */
#homeStage .hv2 .hv2-edge__nm    { color: var(--ms-text); }
#homeStage .hv2 .hv2-edge__delta { color: var(--ms-emerald); }
#homeStage .hv2 .hv2-edge__h     { color: var(--ms-emerald); letter-spacing: .1em; }
/* The "market is higher" side is rose. Keyed to the modifiers the markup really
   emits (`--love` / `--fade`, see _hv2VsMarketHtml): this block used to select
   `.hv2-edge__col--market` and `.is-neg`, neither of which is ever rendered, so
   the rule above painted BOTH columns emerald and a market-ahead ▼ read as a
   positive. Green on the sell-side is the one colour it must never be. */
#homeStage .hv2 .hv2-edge__delta--fade { color: var(--ms-rose); }
#homeStage .hv2 .hv2-edge__h--fade     { color: var(--ms-rose); }
#homeStage .hv2 .hv2-edge__note  { color: var(--ms-dim); border-top: 1px solid var(--ms-line); }

/* Player News (n=7 each) */
#homeStage .hv2 .hv2-news__hl   { color: var(--ms-text); }
#homeStage .hv2 .hv2-news__meta { color: var(--ms-dim); }
/* The <b> inside the meta line — the source, e.g. "Carlos Vargas · SEA" — needs
   naming SEPARATELY. Theming .hv2-news__meta only sets a colour for its children
   to INHERIT, and redesign.css hits the bold directly with
   `.hv2-news__meta b { color: var(--text-2) }`. A direct match beats an inherited
   value at any specificity, so the stage's colour never reached it: measured
   rgb(32,56,79) on this field, 1.66:1 at 12.5px/700, where AA wants 4.5.
   Same shape as the legal-footer <p> further down this file — when a child
   element has its own colour rule, inheritance is not a fix.
   --ms-mut rather than the parent's --ms-dim: it is the emphasised half of the
   line, and it lands at 9.5:1. */
#homeStage .hv2 .hv2-news__meta b { color: var(--ms-mut); }
#homeStage .hv2 .hv2-news__src  { background: rgba(150,180,225,.16); color: var(--ms-text); border-radius: 4px; }
#homeStage .hv2 .hv2-news li,
#homeStage .hv2 .hv2-news__row  { border-color: var(--ms-line) !important; }

/* From the blog (n=3 each) */
#homeStage .hv2 .hv2-blog__head h2 { color: #fff; }
#homeStage .hv2 .hv2-blog__head a  { color: var(--ms-mut); }
#homeStage .hv2 .hv2-blog__head a:hover { color: #fff; }
#homeStage .hv2 .blog-card {
  background: linear-gradient(180deg, rgba(150,180,225,.07), rgba(150,180,225,.028));
  border: 1px solid var(--ms-line);
  border-radius: 14px;
  overflow: hidden;
  transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease;
}
#homeStage .hv2 .blog-card:hover {
  transform: translateY(-4px);
  border-color: rgba(150,190,255,.36);
  box-shadow: 0 22px 56px rgba(2,6,16,.6);
}
#homeStage .hv2 .blog-card__cat     { color: var(--ms-cyan); letter-spacing: .12em; }
#homeStage .hv2 .blog-card__title   { color: #fff; }
#homeStage .hv2 .blog-card__excerpt { color: var(--ms-mut); }
#homeStage .hv2 .blog-card__meta    { color: var(--ms-dim); }

/* Generic leftovers measured dark: <small> (n=54), bare <h2> (n=2), the
   separator dot (n=6), stray <a> (n=1), and the Value Landscape's SVG <text>. */
#homeStage .hv2 small { color: var(--ms-dim); }
#homeStage .hv2 > h2,
#homeStage .hv2 .hv2-sectlabel h2 { color: #fff; }
#homeStage .hv2 .hv2-card__body a { color: var(--ms-text); }
#homeStage .hv2 .hv2-land__chart text,
#homeStage .hv2 .hv2-land__chart tspan { fill: var(--ms-mut); }

/* ═══ BOOM OR BUST + STAT LEADERS ═════════════════════════════════════════
   Already dark, but they were dark AGAINST a light floor. On the new field they
   need the opposite treatment: lift them OFF the background instead of sinking
   them into it, or the page loses the two beats it had. */
#homeStage .hv2 .hv2-beat .hv2-card,
#homeStage .hv2 .hv2-statwrap .hv2-card {
  background: linear-gradient(180deg, rgba(150,180,225,.1), rgba(150,180,225,.04));
  border-color: var(--ms-line2);
}
#homeStage .hv2 .hv2-mv__nm    { color: var(--ms-text); }
#homeStage .hv2 .hv2-mv__delta { color: var(--ms-emerald); }
#homeStage .hv2 .hv2-mv__bar,
#homeStage .hv2 .hv2-mv__fill  { border-radius: 999px; }
#homeStage .hv2 .hv2-stat__rk  { color: var(--ms-dim); }
#homeStage .hv2 .hv2-stat__nm  { color: var(--ms-mut); }
#homeStage .hv2 .hv2-stat__v   { color: #fff; }
#homeStage .hv2 .hv2-stat__lbl { color: #fff; letter-spacing: .1em; }
/* --ms-mut, not --ms-dim: these sit on the stat panel rgb(30,35,45), not on the
   field, where dim is 4.43:1. See the KPI-label note earlier in this file — same
   cause, same backdrop mistake. mut is 7.43 here. */
#homeStage .hv2 .hv2-stat__sub { color: var(--ms-mut); }

/* ═══ JUMP BACK IN ════════════════════════════════════════════════════════ */
#homeStage .hv2 .hv2-sectlabel {
  background: none;
  border-top: 1px solid var(--ms-line);
  padding-top: 44px;
}
#homeStage .hv2 .hv2-sectlabel span { color: var(--ms-dim); }
/* .hv2-ways ships a full-bleed navy gradient (rgb(12,33,64) -> rgb(13,39,72),
   width 1440 via margin-left:-130px). Against the old light floor that read as a
   closing band; against this field it is a lighter rectangle sitting on a darker
   page — the one place that still looked like the previous design. Cleared to a
   whisper of lift so the tiles close the page without a visible seam. It is
   background-IMAGE, not background-color, so `background: none` on the shorthand
   is what clears it. */
#homeStage .hv2 .hv2-ways {
  background-image: linear-gradient(180deg, rgba(150,180,225,.055), rgba(5,8,15,0) 72%);
}
#homeStage .hv2 .hv2-way {
  position: relative;
  background: linear-gradient(180deg, rgba(150,180,225,.07), rgba(150,180,225,.028));
  border: 1px solid var(--ms-line);
  border-radius: 14px;
  overflow: hidden;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
#homeStage .hv2 .hv2-way::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--ms-brand), transparent);
  opacity: 0;
  transition: opacity .18s ease;
}
#homeStage .hv2 .hv2-way:hover {
  transform: translateY(-3px);
  background: rgba(150,180,225,.11);
  border-color: rgba(150,190,255,.4);
  box-shadow: 0 18px 46px rgba(2,6,16,.55);
}
#homeStage .hv2 .hv2-way:hover::after { opacity: .9; }
#homeStage .hv2 .hv2-way__ic {
  color: var(--ms-brand);
  background: rgba(79,143,247,.13);
  border: 1px solid rgba(79,143,247,.26);
  border-radius: 10px;
}
#homeStage .hv2 .hv2-way__nm { color: #fff; }
#homeStage .hv2 .hv2-way__d  { color: var(--ms-dim); }

/* ═══ RESPONSIVE ══════════════════════════════════════════════════════════
   Below 700px the hero stops bleeding and owns its inset as a rounded card.
   That is NOT cosmetic: MAIN.hv2-stage carries `overflow: hidden auto`, so a
   100vw + negative-margin bleed gets its PAINT clipped while getBoundingClientRect
   still reports a correct full-width box — the geometry measures fine and the
   screenshot shows cut corners. See project_fantasy_mlb_showcase_band. */
@media (max-width: 900px) {
  #homeStage .hv2 .hv2-land__chart { height: 210px; }
  #homeStage .hv2 .hv2-masthead--showcase { padding-block: 52px 44px; }
}
@media (max-width: 700px) {
  #homeStage .hv2 .hv2-masthead--showcase::before { width: 760px; height: 760px; bottom: -54%; }
  /* Clear the fixed nav. NAV#siteNav is 108px tall at this width but BODY only
     reserves 56px of padding-top, so the first 52px of any page sits under it —
     app-wide and pre-existing, but the slate title is the first thing on this
     page and was landing at y=71, i.e. invisible. (Dropping the slate's original
     20px top margin for the marquee layout made it 22px worse, so part of this
     is mine.) 62px puts the title at ~119, clear of the bar with room to spare. */
  #homeStage .hv2 .hv2-slate__inner { padding-top: 62px; }
  #homeStage .hv2 .hv2-slate__head { padding-inline: 16px; }
  #homeStage .hv2 .hv2-land__chart { height: 170px; }
  #homeStage .hv2 .ms-marquee__rail { animation-duration: 42s; }
  #homeStage .hv2 .hv2-card { border-radius: 14px; }

  /* UNCLIP THE STAGE SO THE FIELD REACHES THE SCREEN EDGES.
     MAIN.hv2-stage picks up `overflow: hidden auto` at this width and is 343px
     inside a 375px viewport, so the 100vw backdrop had its PAINT clipped to that
     box while getBoundingClientRect still reported a correct full-width layer —
     a light strip down both screen edges that no measurement of the backdrop can
     see. Only the screenshot catches it. (Sizing the backdrop to 100% instead
     just relocates the seam; the clip is the problem, not the width.)
     `:has(.hv2)` because this element is NOT MLB-only — it is the shared stage,
     and it RENDERS on the portal and the workspaces (an earlier note here claimed
     it was `display: none` everywhere else, which was checked on #/rankings and is
     false for #/). Unscoped, this was the last rule in the file still reaching
     another route. Measured harmless at the time — 0px horizontal overflow on all
     eight routes at 375px — but harmless-today is not scoped.

     If `:has()` is ever unavailable the whole rule drops, and the cost is cosmetic
     and MLB-only: the dark field stops bleeding to the screen edges on phones.
     Nothing else depends on it. overflow-Y is left alone either way. */
  main.hv2-stage:has(.hv2) { overflow-x: visible; }
}

/* ═══ REDUCED MOTION ══════════════════════════════════════════════════════
   Everything animated here is decorative, so all of it stops — and the reveal
   resets to its VISIBLE end state rather than its hidden start, so the page is
   never left blank waiting for an observer that will not animate. */
@media (prefers-reduced-motion: reduce) {
  #homeStage .hv2 .ms-marquee__rail,
  #homeStage .hv2 .hv2-masthead--showcase::after,
  #homeStage .hv2 .hv2-slate__dot { animation: none; }
  #homeStage .hv2 .hv2-card,
  #homeStage .hv2 .hv2-way,
  #homeStage .hv2 .blog-card,
  #homeStage .hv2 .hv2-kpi,
  #homeStage .hv2 .hv2-btn { transition: none; }
  #homeStage .hv2 .hv2-card:hover,
  #homeStage .hv2 .hv2-way:hover,
  #homeStage .hv2 .blog-card:hover,
  #homeStage .hv2 .hv2-kpi:hover,
  #homeStage .hv2 .hv2-btn:hover { transform: none; }
}

/* ── Legal footer, MLB only ────────────────────────────────────────────────
   THE ONE RULE IN THIS FILE THAT REACHES OUTSIDE #homeStage, and it is guarded.
   FOOTER#siteLegalFooter is a sibling of the stage, so the stage's own scoping
   cannot touch it — which is why it kept its light slab under a dark page and
   read as a seam. Owner asked for it dark on the MLB page only.

   SCOPED ON body[data-page="mlb"], NOT data-route. `#/mlb` and the multi-sport
   portal `#/` BOTH report data-route="home" (parseHash maps 'mlb' -> home), so a
   data-route rule would darken the portal's footer too. app.js stamps data-page
   next to data-route for exactly this.

   EVERY text colour is set EXPLICITLY, not by a blanket inherit. The first dark
   pass on this page swapped a background and left footer text at ~1.2:1 (see the
   backdrop note above, which is why the field is bounded to the stage height).
   The seven leaf treatments here were inventoried live, and re-measured after:
     wordmark #eef4fc 18.4:1 · tagline/links #9fb4d0 9.4:1 · dim #708aab 5.7:1
   all against #05080f, all AA at their sizes.

   Undo is still "delete this file and its <link>" — the guard means the rule is
   inert on every other route even while the file is loaded. */
body[data-page="mlb"] #siteLegalFooter {
  /* GREY, NOT BLACK (owner, 2026-08-12). The near-black above was correct when
     this page was a dark broadcast stage; the v2 masthead is light, so a #05080f
     slab under a light page read as a black band bolted to the bottom.
     Only the PALETTE is re-pointed here. Every leaf rule below still names its
     token, so the seven explicit text treatments the dark pass inventoried keep
     working, and the contrast argument simply gets recomputed against the new
     ground rather than rebuilt. Re-measured against #e9edf3:
       wordmark #0c1f38 13.9:1 · tagline/links #3d4f66 7.4:1 · dim #566476 5.2:1
     all comfortably AA at their sizes. */
  --ms-bg:   #e9edf3;
  --ms-text: #0c1f38;
  --ms-mut:  #3d4f66;
  --ms-dim:  #566476;
  --ms-line: rgba(12, 31, 56, .12);
  --ms-cyan: #1d5fa7;
  background: var(--ms-bg);
  border-top: 1px solid var(--ms-line);
  color: var(--ms-mut);
}
body[data-page="mlb"] #siteLegalFooter .site-footer__wordmark { color: var(--ms-text); }
body[data-page="mlb"] #siteLegalFooter .site-footer__tagline  { color: var(--ms-mut); }
body[data-page="mlb"] #siteLegalFooter .site-footer__disclaimer { color: var(--ms-dim); }
body[data-page="mlb"] #siteLegalFooter a { color: var(--ms-mut); }
body[data-page="mlb"] #siteLegalFooter a:hover,
body[data-page="mlb"] #siteLegalFooter a:focus-visible { color: var(--ms-cyan); }
body[data-page="mlb"] #siteLegalFooter .site-footer__mail { color: var(--ms-mut); }
body[data-page="mlb"] #siteLegalFooter .site-footer__mail:hover { color: var(--ms-cyan); }
/* the "·" separators between Privacy / Terms — decorative, but still AA */
body[data-page="mlb"] #siteLegalFooter span { color: var(--ms-dim); }

/* THREE OF THOSE RULES DID NOT WIN, AND THE PALETTE MATH ABOVE HID IT.
   Measured on the live footer 2026-08-08, background rgb(5,8,15):
     .site-footer__line   rgb(18,35,53)  1.26:1
     .site-footer__mail   rgb(32,56,79)  1.66:1
     footer nav links     rgb(32,56,79)  1.66:1
   The colours above are correct and do clear AA — they were simply never the
   ones applied. Two different cascade faults, neither visible from reading this
   block:

   1. INHERITANCE LOSES TO A DIRECT MATCH, at any specificity. The footer sets
      `color: var(--ms-mut)` for its children to inherit, but .site-footer__line
      is a <p>, and `p { color: var(--text) }` in polish.css matches it directly.
      A directly-matched declaration always beats an inherited value — specificity
      never enters into it. .site-footer__line is also simply absent from the list
      above, so nothing else claimed it.
   2. `!important` OUTRANKS SPECIFICITY. `a { color: … !important }` in styles.css
      scores 1 and still beats `body[data-page="mlb"] #siteLegalFooter a` at
      10102, because the latter is not marked important.

   So: name every element rather than relying on inheritance, and match the
   !important the base sheets use. Contrast after, against #05080f —
   --ms-mut #9fb4d0 = 9.5:1, --ms-dim #708aab = 5.6:1, both AA at these sizes. */
body[data-page="mlb"] #siteLegalFooter .site-footer__line { color: var(--ms-dim) !important; }
body[data-page="mlb"] #siteLegalFooter a,
body[data-page="mlb"] #siteLegalFooter .site-footer__mail { color: var(--ms-mut) !important; }
body[data-page="mlb"] #siteLegalFooter a:hover,
body[data-page="mlb"] #siteLegalFooter a:focus-visible,
body[data-page="mlb"] #siteLegalFooter .site-footer__mail:hover { color: var(--ms-cyan) !important; }

/* The 80px seam. DIV.page carries `padding: 0 32px 100px`, and the field backdrop
   is bounded to the stage's own height (deliberately — see the note above), so that
   padding paints BODY's rgb(238,242,247). While the footer was also light the band
   blended into it. Darkening the footer turned it into a light stripe sandwiched
   between two dark surfaces, which is worse than the seam it was meant to fix.
   Measured 4172 -> 4252 = 80px at 1280w.

   IT IS BODY THAT PAINTS IT, NOT .page. The first attempt here set a background on
   `.page`, reasoning that the seam was its bottom padding showing through. Measured
   with elementFromPoint 20px above the footer: the element there is BODY at
   rgb(238,242,247), because FOOTER#siteLegalFooter is a SIBLING of .page, not a
   child, so the gap sits below .page entirely and no rule on .page can reach it.
   Safe to paint BODY here: on this route the nav, the stage and now the footer are
   all dark, so there is no light surface left for it to fight with — and the
   data-page guard keeps it off every other route.

   `!important` IS LOAD-BEARING, and it is the narrower of the two options.
   theme-v2.css declares `body { background: var(--bg) !important }`, which beats a
   plain rule here no matter how specific — measured, the first version of this line
   lost and body stayed rgb(238,242,247). The tempting fix is to redeclare the token
   (`body[data-page="mlb"] { --bg: #05080f }`) and let their own !important resolve to
   it, but `var(--bg)` has 71 consumers across styles.css and polish.css and several
   use it as a COLOR (`.hero__chip { color: var(--bg) }`), so redefining it on BODY
   would inherit into every descendant and invert text. Overriding the one property on
   the one element is the smaller blast radius. */
body[data-page="mlb"] { background: #05080f !important; }

/* ══════════════════════════════════════════════════════════════════════════
   SPORT PORTAL — the MLB stage's design language, applied to #/
   ══════════════════════════════════════════════════════════════════════════
   Owner 2026-08-09: "I like the starting point for the home page, but I want
   the designs to be really cool and flashy like the mlb page."

   MEASURED both pages with one script before touching anything, because the
   gap is a specification, not a vibe:

     property        MLB stage (reference)              portal (before)
     font-weight     800 x204 / 400 x168 / 700 x132     400 x65 / 700 x53 / 800 x6
     radius          3px x83, 999px x72, 2px x60, 10px  3px x19, 999px x7, 6px x5
     box-shadow      0 0 10px rgb(233,238,246) x60      6 total, effectively flat
     tinted surface  rgba(150,180,225,.055) x30, .07    none
     motion          msScroll marquee, 844 transitions  0 animations
     density         1044 visible / 508 text            189 / 128

   WEIGHT IS THE HEADLINE FINDING and the dial nobody looks at: the reference is
   an 800-dominant page, the portal had SIX elements at 800. That single number
   explains "quiet" better than any size or spacing gap, so it is what most of
   this block moves.

   NO NEW FONT. The reference resolves to -apple-system on all 508 text nodes, and
   as of 2026-08-09 the site ships NO webfont at all: the one self-hosted face,
   Roboto Condensed for percentile-panel parity, was reverted to the system stack
   on the owner's call, and its @font-face went with it. Impact comes from scale,
   weight, tracking and case, which is also what the renderer's own comment already
   committed to.

   This sheet loads LAST (index.html: styles -> polish -> theme-v2 -> redesign ->
   decision-center -> mlb-stage), so these rules win without !important. The
   --ms-* tokens above are scoped to #homeStage and deliberately NOT reused here;
   the portal gets its own --pt-* set so the two stages can drift apart later. */

.pt-stage,
.pt {
  --pt-panel:  rgba(150, 180, 225, .055);
  --pt-panel2: rgba(150, 180, 225, .085);
  --pt-line:   rgba(150, 180, 225, .14);
  --pt-line2:  rgba(150, 180, 225, .24);
  --pt-brand:  #4f8ff7;
  --pt-cyan:   #22d3ee;
  --pt-ink:    #eef4fc;
  --pt-dim:    rgba(224, 236, 252, .62);
}

/* ── Hero stage ─────────────────────────────────────────────────────────── */
.pt-stage {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
/* Two stacked textures, both from the reference: a wide radial lift behind the
   headline and the 115deg pinstripe. Pseudo-elements so no markup changes and
   nothing can intercept a click. */
.pt-stage::before {
  content: '';
  position: absolute;
  inset: -10% -20% auto -20%;
  height: 150%;
  z-index: -2;
  background:
    radial-gradient(900px 460px at 50% 8%, rgba(79, 143, 247, .20), transparent 70%),
    radial-gradient(620px 380px at 82% 92%, rgba(34, 211, 238, .10), transparent 72%);
  pointer-events: none;
}
.pt-stage::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: repeating-linear-gradient(115deg,
              rgba(150, 180, 225, .022) 0 1px, transparent 1px 74px);
  pointer-events: none;
}

.pt-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
  padding: 6px 14px 6px 10px;
  border: 1px solid var(--pt-line2);
  border-radius: 999px;
  background: var(--pt-panel2);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--pt-ink);
}
.pt-eyebrow__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--pt-cyan);
  box-shadow: 0 0 0 0 rgba(34, 211, 238, .55);
  animation: ptPulse 2.4s cubic-bezier(.4, 0, .6, 1) infinite;
}
@keyframes ptPulse {
  0%   { box-shadow: 0 0 0 0 rgba(34, 211, 238, .55); }
  70%  { box-shadow: 0 0 0 9px rgba(34, 211, 238, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 211, 238, 0); }
}

.pt-stage__title {
  font-weight: 850;
  letter-spacing: -.035em;
  line-height: .92;
}
/* The accent word. background-clip:text needs a painted background, and the
   fallback colour matters: if the clip is unsupported the text must still be
   readable rather than transparent. */
.pt-em {
  background: linear-gradient(92deg, var(--pt-cyan), var(--pt-brand));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--pt-cyan);
}

.pt-cta {
  position: relative;
  font-weight: 800;
  letter-spacing: .01em;
  border-radius: 999px;
  background: linear-gradient(92deg, var(--pt-brand), #2f6fd8);
  box-shadow: 0 8px 26px rgba(47, 111, 216, .44), 0 0 14px rgba(79, 143, 247, .28);
  transition: transform .18s cubic-bezier(.16, 1, .3, 1),
              box-shadow .18s cubic-bezier(.16, 1, .3, 1);
}
.pt-cta:hover,
.pt-cta:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(47, 111, 216, .52), 0 0 22px rgba(79, 143, 247, .42);
}
.pt-cta__arrow { transition: transform .18s cubic-bezier(.16, 1, .3, 1); }
.pt-cta:hover .pt-cta__arrow { transform: translateX(4px); }

/* The "live proof strip" (.pt-stats/.pt-stat) that sat here was removed with its
   markup on 2026-08-09 at the owner's request. styles.css keeps a SEPARATE
   .pt-stat used by .pt-stats__grid — do not delete that one on a name match. */

/* ── Live ticker ────────────────────────────────────────────────────────── */
.pt-tick {
  position: relative;
  margin-top: 40px;
  padding: 12px 0;
  border-top: 1px solid var(--pt-line);
  border-bottom: 1px solid var(--pt-line);
  background: var(--pt-panel);
  overflow: hidden;
  /* Fade both ends so chips enter and leave instead of being cut mid-glyph. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.pt-tick__rail {
  display: flex;
  width: max-content;
  gap: 10px;
  animation: ptScroll 64s linear infinite;
  will-change: transform;
}
.pt-tick:hover .pt-tick__rail { animation-play-state: paused; }
/* -50% exactly, because the rail renders the chip list TWICE. Any other value
   jumps at the wrap. */
@keyframes ptScroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
.pt-tick__i {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 13px;
  border: 1px solid var(--pt-line);
  border-radius: 999px;
  background: var(--pt-panel2);
  white-space: nowrap;
}
/* 800, not 700. The reference is an 800-DOMINANT page (800 x204 vs 700 x132) and
   the ticker is the portal's largest single population of text nodes, so this one
   declaration is what actually flips the page's dominant weight to match. */
.pt-tick__nm { font-size: 12.5px; font-weight: 800; color: var(--pt-ink); }
.pt-tick__pos {
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--pt-dim);
}
.pt-tick__v {
  font-size: 12.5px;
  font-weight: 850;
  font-variant-numeric: tabular-nums;
  color: var(--pt-cyan);
}

/* ── Sport cards ────────────────────────────────────────────────────────── */
/* REVERTED 2026-08-09 (owner: "the pick a sport looks like AI; revert back").
   Two passes today restyled the picker: cc2da01 put dark-surface card rules here
   (.pt-pick/.pt-hero/.pt-card/.pt-tag), and 263e757 then wrapped the section in a
   full-bleed navy .pt-picker band to make the cyan legible. Both are gone. The
   picker is back to the light treatment in styles.css, which never left — it
   still holds the complete original .pt-hero/.pt-grid/.pt-card/.pt-tag set.
   NOTE the a11y history so nobody re-lands the first pass alone: on the light
   body the cyan .pt-tag--live measured 1.61:1, an AA failure, and ci_gate's a11y
   check is blocking. styles.css's original uses --green on --green-soft and does
   not have that problem. The defect belonged to the dark-on-light pass, so
   removing BOTH passes resolves it; removing only the second would restore it. */

/* ── Section headings ───────────────────────────────────────────────────── */
.pt-sec__title,
.pt-why__t {
  font-weight: 850;
  letter-spacing: -.02em;
}
.pt-col__n {
  font-weight: 850;
  background: linear-gradient(92deg, var(--pt-cyan), var(--pt-brand));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--pt-cyan);
}

/* ── Responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 760px) {
  .pt-tick { margin-top: 28px; }
  .pt-tick__rail { animation-duration: 44s; }
}

/* Motion is decoration here; the ticker repeats the day's finals, which are
   available elsewhere, so removing it costs a reduced-motion user nothing. */
@media (prefers-reduced-motion: reduce) {
  .pt-tick__rail { animation: none; transform: none; }
  .pt-eyebrow__dot { animation: none; }
  .pt-cta,
  .pt-hero,
  .pt-card { transition: none; }
  .pt-cta:hover,
  .pt-hero:hover { transform: none; }
}

/* Feed-status dot on each ticker chip. Green = the feed reported success on the
   last refresh; dim = skipped or served from the previous run. Colour is not the
   only carrier — the chip is labelled with the feed's own name either way. */
.pt-tick__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(150, 180, 225, .34);
  flex: 0 0 auto;
}
.pt-tick__dot.is-ok {
  background: var(--pt-cyan);
  box-shadow: 0 0 7px rgba(34, 211, 238, .55);
}


/* ── Ticker: final scores ───────────────────────────────────────────────────
   Replaced a rail of data-feed NAMES, which read as filler. Scores need a
   different chip: fixed-width numerals so the rail does not jitter as it
   scrolls, and a weight/opacity split so the winner is readable at a glance
   without colour doing the work (colour alone would fail for ~8% of men). */
.pt-sc { gap: 7px; padding: 7px 14px; }
.pt-sc__t {
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .06em;
  color: rgba(224, 236, 252, .70);
}
.pt-sc__n {
  font-size: 13px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: rgba(224, 236, 252, .55);
  min-width: 10px;
  text-align: right;
}
/* The winner: full-strength ink and a heavier cut. Not colour-only. */
.pt-sc__n.is-w { color: var(--pt-ink); font-weight: 850; }
.pt-sc__at {
  font-size: 9.5px;
  font-weight: 700;
  color: rgba(224, 236, 252, .34);
  padding: 0 1px;
}
/* Extra innings — the only game-state detail worth the space. */
.pt-sc__x {
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .08em;
  color: var(--pt-cyan);
  padding-left: 2px;
}
/* Leading label so the rail says what it is on first read. */
.pt-sc--lead {
  background: rgba(34, 211, 238, .12);
  border-color: rgba(34, 211, 238, .40);
}
.pt-sc__lead {
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #7fe9fb;
}

/* Ownership-unresolved notice on the decision pages. Deliberately styled as a
   BLOCKED state, not a neutral empty one: an empty state says "nothing to show",
   which reads as "no moves this week" and is exactly the wrong conclusion. This
   says we cannot answer, and why. */
.dc-empty--blocked {
  border-left: 3px solid #d97706;
  background: rgba(217, 119, 6, .07);
  padding: 14px 16px;
  border-radius: 0 8px 8px 0;
  line-height: 1.55;
}

/* ═══ DE-GENERICISING THE STAGE ═══════════════════════════════════════════
   Owner, 2026-08-12: "the actual design and visuals of the home page is what
   looks ai generated." A copy pass had already landed and missed the point —
   the tells here are visual, and three of them measured at 1440px:

     · TRI-STOP CYAN->BLUE->VIOLET GRADIENT TEXT, TWICE, STACKED. The wordmark's
       "baseball" (#22d3ee -> #4f8ff7 -> #a78bfa) sat directly above the headline
       accent (#7cc4ff -> #4f8ff7 -> #a78bfa) at 68px/900. This exact ramp is the
       single most recognisable machine-made-landing-page signature there is.
     · HERO FULLY CENTRED — text-align:center across a 1284px container.
     · FOUR KPI CARDS AT EXACTLY 312px EACH — a symmetric feature-card row, the
       most generic layout pattern going.

   1. ONE ACCENT, NOT A RAINBOW. The headline drops to a single flat accent.
      The WORDMARK KEEPS ITS GRADIENT ON PURPOSE: that lockup is the brand, the
      owner picked it out by name earlier today and asked for it in the hub
      heroes. Killing both would have edited the logo rather than the page. One
      gradient is identity; two adjacent ones are a template. Removing the
      louder, larger of the pair also buys real hierarchy — the eye now goes
      wordmark, then headline, instead of fighting two rainbows at once.

   2. LEFT-ALIGN, AND MOVE THE LIGHT TO MATCH. Centred everything is the tell;
      a left-aligned hero over an asymmetric glow reads as composed. The
      showcase glow is re-aimed from 50% to 30% so the brightest point sits
      under the text rather than behind the empty right half — leaving it
      centred is what makes a left-aligned hero look broken instead of designed.

   3. THE KPI STRIP STOPS BEING FOUR CARDS. Same four figures, re-set as one
      left-aligned line separated by hairlines. A stat line reads as a fact
      about the product; four equal bordered tiles read as a template slot.
      Contrast is safe: --ms-mut was chosen at 5.21:1 against the RAISED KPI
      panel (see the note above); dropping the panel puts those labels on the
      field, where the same ink measures higher, not lower.

   Everything below the hero is untouched. */

/* 1 — single accent */
#homeStage .hv2 .hv2-hero__title b {
  background: none;
  -webkit-background-clip: border-box;
          background-clip: border-box;
  color: #7cc4ff;
}

/* 2 — asymmetric hero */
#homeStage .hv2 .hv2-masthead--showcase {
  text-align: left;
  background:
    radial-gradient(900px 460px at 30% 118%, rgba(79,143,247,.30), transparent 70%),
    linear-gradient(180deg, #070d1c 0%, #0b1426 62%, #070c18 100%);
}
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero,
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__l { align-items: flex-start; text-align: left; }
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__lede { margin-left: 0; margin-right: auto; max-width: 54ch; }
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__ctas { justify-content: flex-start; }

/* 3 — the KPI stat-line block that stood here is REMOVED (2026-08-13). It was
   written for the four-across hero that has since been replaced by the
   .hv2-mastrail layout, so every rule in it was either dead or wrong:
     · `.hv2-kpis { display:flex; gap:0 34px }` lost outright to
       redesign.css's `#homeStage .hv2 .hv2-mastrail .hv2-kpis` (grid, 1fr 1fr)
     · the `.hv2-kpi` hairlines lost the same way — the divider now visible on
       the right column is theirs (rgba(13,35,64,.1) at 28px), not this one's
       (--ms-line2 at 22px)
     · `:hover .hv2-kpi__n { color: #cfe4ff }` was the only rule still winning,
       and it is a dark-theme colour that is near-invisible on the light stage
   Deleting beats leaving it to lose quietly: the next person measuring this
   grid would have found two competing sources for one hairline. */

/* ═══ LIGHTS DOWN ═════════════════════════════════════════════════════════
   Owner, 2026-08-12: "i think the ai look is more the lighting effects and
   stuff." Correct, and it is the whole lighting model rather than one effect.
   Inventoried on this sheet:

     backdrop   THREE stacked radial orbs on #homeStage .hv2::before —
                blue 14%/-6% .20, VIOLET 88%/4% .16, cyan 50%/42% .055,
                all background-attachment:fixed so they hang in place
     ambient    an aurora sweep on the showcase ::after, animated 22s on a loop
     bloom      text-shadow 0 0 46px on the wordmark, 0 0 30px on every KPI
                number, 0 0 30px emerald on +4.3%
     neon       box-shadow 0 0 10px currentColor on the slate bars,
                0 0 14px on card accents

   Blue-violet-cyan orbs + a drifting light + glowing numerals IS the generated
   look. It is one recognisable template — the "ethereal glass" AI-SaaS hero —
   and no amount of copy or alignment gets out from under it while the lights
   are still on. Real data products do not make their numbers emit light.

   What changes: one restrained tint instead of a three-hue mesh, no moving
   ambient, and no bloom on type. What does NOT change: the page stays dark, the
   diamond field-plate texture stays, hover feedback stays. This is a lighting
   pass, not a re-theme — the structure and palette are untouched.

   Contrast is unaffected: every glow removed sits BEHIND or AROUND already-solid
   text (#fff numerals, #fff wordmark) and adds no luminance to the glyph itself.
   Removing bloom cannot lower a contrast ratio. */

/* 1 — one tint, not a mesh. The violet and cyan orbs go; the blue is halved and
       stays to keep the field from reading flat. The diagonal line texture is
       kept — it is texture, not lighting, and it is what stops the flat tone
       looking empty. */
#homeStage .hv2::before {
  background-image:
    radial-gradient(1000px 560px at 18% -8%, rgba(79,143,247,.11), transparent 64%),
    repeating-linear-gradient(115deg, rgba(150,180,225,.022) 0 1px, transparent 1px 74px);
  background-attachment: fixed, scroll;
}

/* 2 — no drifting ambient. A light that sweeps the hero every 22 seconds is the
       single most "generated" thing on the page; it also repaints a full-width
       layer forever for no informational gain. */
#homeStage .hv2 .hv2-masthead--showcase::after { display: none; animation: none; }

/* 3 — type stops emitting light */
#homeStage .hv2 .hv2-hero__wordmark { text-shadow: none; }
#homeStage .hv2 .hv2-kpi__n { text-shadow: none; }
#homeStage .hv2 .hv2-kpi__n.is-pos { text-shadow: none; }

/* 4 — objects stop emitting light. The slate bars keep their colour as the
       team cue; they just no longer halo. */
#homeStage .hv2 .hv2-game__bar { box-shadow: none; }
#homeStage .hv2 .hv2-accent { box-shadow: none; }

/* 5 — the primary CTA keeps hover feedback, loses the coloured bloom: a 38px
       .65-alpha blue cast under a button is stage lighting, not elevation. */
#homeStage .hv2 .hv2-btn--primary:hover {
  box-shadow: 0 6px 18px rgba(4,10,22,.45), 0 0 0 1px rgba(150,190,255,.28), inset 0 1px 0 rgba(255,255,255,.22);
}

/* ═══ LIGHT STAGE ═════════════════════════════════════════════════════════
   Owner, 2026-08-12: "make the home page light theme like the rest of the site."

   The stage was the only dark surface on a light product — the rankings board,
   the profile, the hub heroes and the portal chrome are all light — which is the
   "one dark section in a light page" problem: it reads as a slab pasted in from
   somewhere else rather than as the same product's front door.

   DONE AS A TOKEN REMAP, NOT A REWRITE. The sheet's own header records that it
   "inventories all 49 text-bearing element types measured on the live page and
   themes the 22 that were dark-on-light" — so almost everything here already
   reads its colour from the --ms-* set. Re-pointing those nine structural tokens
   at the SITE's palette (--bg / --surface / --text-1..3 / --hairline) flips the
   large majority in one place and keeps the two in sync from here on. What is
   left after that is the handful of rules that hardcoded #fff rather than going
   through a token; those are listed out below because they are exactly the ones
   that would otherwise turn white-on-white and vanish.

   ACCENTS ARE DARKENED, NOT REUSED. Same measured lesson as the hub-hero
   gradient earlier today: cyan #22d3ee reads 1.1-2.5:1 on a light tint and the
   emerald and amber are no better. Each accent moves to its dark-on-light
   sibling, holding the hue so the seven card rims stay distinguishable.

   Appended rather than edited in place so the dark stage is one deletion away if
   this is not wanted. */

#homeStage {
  /* structure — mapped onto the site's own light tokens */
  --ms-bg:      #eef2f7;
  --ms-bg2:     #ffffff;
  --ms-panel:   #ffffff;
  --ms-panel2:  #f5f8fc;
  --ms-line:    rgba(13,35,64,.10);
  --ms-line2:   rgba(13,35,64,.22);
  --ms-text:    #0c1f38;
  --ms-mut:     #20384f;
  --ms-dim:     #2b3e52;
  /* accents — dark-on-light siblings, hue preserved */
  --ms-brand:   #1d5fa7;
  --ms-cyan:    #0e7490;
  --ms-violet:  #6d28d9;
  --ms-emerald: #047857;
  --ms-amber:   #b45309;
  --ms-rose:    #be123c;
  --ms-teal:    #0f766e;
}

/* The page ground. The original note above explains why this is set on the one
   property of the one element rather than by redefining --bg, which has 71
   consumers and several that use it as a COLOR — that reasoning still holds, so
   this stays the same shape and only changes the value. */
body[data-page="mlb"] { background: #eef2f7 !important; }

/* Field + hero grounds */
#homeStage .hv2::before {
  background-color: var(--ms-bg);
  background-image:
    radial-gradient(1000px 560px at 18% -8%, rgba(29,95,167,.07), transparent 64%),
    repeating-linear-gradient(115deg, rgba(13,35,64,.03) 0 1px, transparent 1px 74px);
}
#homeStage .hv2 .hv2-masthead--showcase {
  background:
    radial-gradient(900px 460px at 30% 118%, rgba(29,95,167,.10), transparent 70%),
    linear-gradient(180deg, #ffffff 0%, #f4f7fb 62%, #eef2f7 100%);
  border-bottom: 1px solid var(--ms-line);
}
#homeStage .hv2 .hv2-masthead--showcase::before { border-color: rgba(13,35,64,.06); background: none; }
#homeStage .hv2 .hv2-slate { background: linear-gradient(180deg, #ffffff, #f5f8fc); }

/* THE HARDCODED WHITES. Each of these bypassed the token set, so the remap above
   cannot reach them and every one would render white-on-white. Listed in source
   order so this stays checkable against the file. */
#homeStage .hv2 .hv2-hero__wordmark,
#homeStage .hv2 .hv2-hero__title,
#homeStage .hv2 .hv2-card__title,
#homeStage .hv2 .hv2-lb__name:hover,
#homeStage .hv2 .hv2-lb__val,
#homeStage .hv2 .hv2-poschip:hover,
#homeStage .hv2 .hv2-blog__head h2,
#homeStage .hv2 .hv2-blog__head a:hover,
#homeStage .hv2 .blog-card__title,
#homeStage .hv2 .hv2-sectlabel h2,
#homeStage .hv2 .hv2-stat__v,
#homeStage .hv2 .hv2-stat__lbl,
#homeStage .hv2 .hv2-way__nm,
#homeStage .hv2 .hv2-kpi__n { color: var(--ms-text); }

#homeStage .hv2 .hv2-hero__title { text-shadow: none; }
#homeStage .hv2 .hv2-hero__lede { color: var(--ms-mut); }
#homeStage .hv2 .hv2-poschip:hover { background: rgba(13,35,64,.06); }

/* The primary CTA keeps its filled-blue treatment — it is the one place white
   type is correct, because it sits on a solid brand fill. */
#homeStage .hv2 .hv2-btn--primary,
#homeStage .hv2 .hv2-btn--primary:hover { color: #ffffff; }
#homeStage .hv2 .hv2-btn {
  border-color: var(--ms-line2);
  background: #ffffff;
  color: var(--ms-text);
}
#homeStage .hv2 .hv2-btn--primary { background: linear-gradient(180deg, #2a6cc4, #1d5fa7); border-color: transparent; }

/* Light-stage contrast corrections — found by sweeping all 586 text nodes on the
   stage and computing each against its effective background, not by eye.
   Seven came back under 3:1; four were real and are fixed here.

   The three that were NOT: the "→" glyphs inside .hv2-btn--primary measured 1.12
   against the PAGE colour because the sweep resolves backgrounds via
   backgroundColor and that button is filled with a background-IMAGE gradient, so
   the walker stepped straight past it. They are white on solid blue and correct.
   Recording it because the same blind spot will re-fire on any gradient-filled
   control the next time this sweep is run. */

/* #7cc4ff was picked for a DARK field two commits ago and measures 1.67:1 here —
   the accent that fixed the AI-gradient tell becomes the worst contrast failure
   on the page the moment the ground flips. Site brand instead: 5.9:1. */
#homeStage .hv2 .hv2-hero__title b { color: #1d5fa7; }

/* The wordmark's "r" inherits #5ea3e6 from theme-v2, tuned for the dark nav. */
#homeStage .hv2 .hv2-hero__wordmark b { color: #1d5fa7; }

/* Active position chip: the remap gave it a brand FILL while its label stayed
   dark ink — 2.95:1 on its own background. White on the fill. */
#homeStage .hv2 .hv2-poschip.is-on,
#homeStage .hv2 .hv2-poschip[aria-pressed="true"] { color: #ffffff; }

/* Card footnotes ("...chance of an elite season vs a bust year") were near-white
   for the dark stage. */
#homeStage .hv2 .hv2-edge__note { color: var(--ms-mut); }
#homeStage .hv2 .hv2-edge__note b { color: var(--ms-text); }

/* Light-stage surface corrections. Found by sweeping every element for
   TRANSLUCENT dark fills — the first survey only looked at opaque backgrounds
   (alpha > .5) and therefore walked straight past all of these, which is why the
   card headers still read grey after the remap looked "done".

   .hv2-card__head was `rgba(6,11,22,.35)` — a 35% BLACK wash. Over the dark
   stage that is an invisible darkening; over a white card it is a grey band, on
   all seven cards. Replaced with the light panel tint so the header separates
   from the body the same way, in the same direction as the new ground.

   Everything else the sweep returned was rgba(13,35,64,.1) — the remapped
   hairline — which is correct for light and left alone. */
#homeStage .hv2 .hv2-card__head {
  background: var(--ms-panel2);
  border-bottom: 1px solid var(--ms-line);
}
/* Card shells carried a blue-grey translucent wash for the dark field. On light
   they should be the site's plain white surface, like every other card in the
   product. */
#homeStage .hv2 .hv2-card,
#homeStage .hv2 .blog-card,
#homeStage .hv2 .hv2-way { background: var(--ms-bg2); }
/* Slate header text was near-white (#e9eef6) for the dark band. */
#homeStage .hv2 .hv2-slate__head { color: var(--ms-text); }

/* ═══ NO SHADOWS ══════════════════════════════════════════════════════════
   Owner, 2026-08-12: "the design looks odd. remove shadows because those look
   ai generated."

   MEASURED first — 43 shadowed elements, and the "odd" is mostly two of them:

     .hv2-card  x7   rgba(2,6,16,.50)  0 22px 60px   <- 50% near-BLACK, 60px blur
     .hv2-slate x1   rgba(8,20,40,.35) 0 ...
     .hv2-btn   x1   rgba(47,111,216,.44) 0 8px 26px <- coloured blue bloom
     .hv2-game  x30  rgba(13,35,64,.04) 0 1px 2px    <- already correct
     .hv2-kpi   x4   rgba(13,35,64,.05) 0 1px 2px    <- already correct

   The first three were drawn for a DARK stage, where a heavy black bloom reads
   as depth against a near-black field. Against #eef2f7 the same values are a
   grey smudge under every card — that is the specific thing that looked wrong
   after the theme flip, and it is a straight consequence of flipping the ground
   without re-deriving the elevation.

   All of them go rather than being re-tinted, which is what was asked. The
   surfaces do not lose their edges: every one of these already carries a
   1px rgba(13,35,64,.1) hairline from the light remap, so separation moves from
   elevation to line — which is the correct model for a dense data page anyway,
   and matches the board and profile.

   FOCUS RINGS ARE NOT TOUCHED. Selectors are explicit rather than a blanket
   `* { box-shadow: none }` precisely so nothing here can reach a
   :focus-visible ring — removing those would be an a11y regression and the
   gate treats it as blocking. */
#homeStage .hv2 .hv2-card,
#homeStage .hv2 .hv2-card:hover,
#homeStage .hv2 .hv2-slate,
#homeStage .hv2 .hv2-game,
#homeStage .hv2 .hv2-game:hover,
#homeStage .hv2 .hv2-kpi,
#homeStage .hv2 .hv2-kpi:hover,
#homeStage .hv2 .blog-card,
#homeStage .hv2 .blog-card:hover,
#homeStage .hv2 .hv2-way,
#homeStage .hv2 .hv2-way:hover,
#homeStage .hv2 .hv2-btn,
#homeStage .hv2 .hv2-btn:hover,
#homeStage .hv2 .hv2-btn--primary,
#homeStage .hv2 .hv2-btn--primary:hover {
  box-shadow: none;
}

/* ═══ ONE LEFT EDGE ═══════════════════════════════════════════════════════
   Owner, 2026-08-12: "formatting and design still looks odd."

   MEASURED at 1880px — the page had FOUR left edges:

     .hv2-hero / .hv2-kpis    298
     .hv2-card / .hv2-slate   350
     .hv2-hero__l             440   (wordmark, lede, CTAs)
     .hv2-hero__title         546

   So the headline started 106px right of its own siblings and 248px right of the
   stat row beneath it. Nothing lined up with anything.

   THE LEFT-ALIGN IN afd50ef4 ONLY REACHED THE TEXT. `text-align: left` governs
   inline content; these blocks were each centred by their own
   `max-width` + `margin: auto`, three deep and independently:

     .hv2-hero__title  max-width 788px   margin 105.9px auto
     .hv2-hero__l      max-width 1000px  margin 142px   auto
     .hv2-hero         max-width 1284px  margin 266px   auto

   Setting text-align on an ancestor cannot undo an auto margin on a descendant,
   which is why the hero read as left-aligned and still looked wrong.

   The hero is also 1284 wide against the page container's 1220, so it could not
   share the cards' edge at any alignment. Capping it to the CARD width (1180)
   and centring that block inside the full-bleed masthead lands it on exactly the
   same 350 the cards use — (1880 - 1180) / 2 = 350 — so the hero, the stat row,
   the slate and every card below now start on one line down the page.

   The title keeps a max-width: that is line-length control at 68px and is worth
   having. Only its auto margins go. */
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero,
#homeStage .hv2 .hv2-masthead--showcase .hv2-kpis {
  max-width: 1180px;
  margin-left: auto;
  margin-right: auto;
}
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__l {
  max-width: 100%;
  margin-left: 0;
  margin-right: 0;
}
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__title,
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__lede,
#homeStage .hv2 .hv2-masthead--showcase .hv2-hero__wordmark {
  margin-left: 0;
  margin-right: 0;
}

/* .hv2-sectlabel and .hv2-ways escape the container with `margin-left: -350px`
   and try to re-inset with `padding: 44px 318px`. Both numbers are hardcoded, so
   the inset only matches the container at one viewport — measured at 1880px the
   section heading landed at x=840 while every other element on the page sat at
   350, which is the last of the four edges.

   .hv2-masthead uses the same escape and KEEPS it: that one is genuinely
   full-bleed because it carries the hero's background band. These two carry no
   background (measured transparent), so the bleed buys nothing and only moves
   their text. Returned to the container and capped to the card width, which puts
   them on the same 350 as everything else at any viewport. */
#homeStage .hv2 .hv2-sectlabel,
#homeStage .hv2 .hv2-ways {
  margin-left: 0;
  margin-right: 0;
  max-width: 1180px;
  padding-left: 0;
  padding-right: 0;
  align-items: flex-start;
}

/* Centre the masthead KPIs across the player card's width (owner, 2026-08-13:
   "i just want these centered within the width of the player card").

   MEASURED first: the KPI block already spans the card exactly — both run
   x 1045 -> 1530, 485px — so nothing about the box needed moving. What was off
   was the CONTENT: `text-align: start` on the cells, so each stat hugged the
   left of its 229px column and the pair read as two ragged left edges inside a
   centred container.

   Centring the cells is the whole change. The two columns are equal (228.672px
   each), so centred content is symmetric about the card's midline. Deliberately
   NOT touching the grid, the gap, the card, or anything else on this rail — the
   previous two attempts here changed structure that measurement said was already
   correct, and both made it worse. */
#homeStage .hv2 .hv2-mastrail .hv2-kpi { text-align: center; }
/* …and make the second column's padding symmetric, or `text-align: center` lies.
   redesign.css gives the right-hand column `border-left: 1px` + `padding-left:
   28px` as the divider between the two stats. Centred text centres inside the
   PADDED box, so with 28px on the left and 0 on the right the content landed
   14px right of its own cell centre — measured: cell mid 1416, content mid 1430,
   exactly half the padding. Matching the right padding restores symmetry so the
   content centres on the cell, and the divider is untouched. */
#homeStage .hv2 .hv2-mastrail .hv2-kpi:nth-child(2n) { padding-right: 28px; }

/* No tile behind the masthead KPIs (owner, 2026-08-13: "remove the blue boxes,
   those werent in the old design").

   THEY CAME BACK BECAUSE OF THIS SESSION'S OWN CLEANUP, and that is worth stating
   plainly. `#homeStage .hv2 .hv2-kpi` up at :385 paints the ORIGINAL dark-stage
   KPI panel — linear-gradient(rgba(150,180,225,.085) -> .03) with a 1px --ms-line
   border and a 14px radius. Against the navy field that reads as a barely-there
   raised tile. Against the light stage the same translucent blue-grey over white
   reads as a solid pale blue box, which is exactly what appeared.

   The stat-line block deleted in 8a7cc28e had been holding it down with
   `background: none; border: 0`. I removed that block calling every rule in it
   "dead or wrong" — that was wrong: those two declarations were load-bearing on
   the light theme, and deleting them un-suppressed a dark-theme tile. The rest of
   that block genuinely was dead; these two were not.

   Suppressed here per-surface instead of restoring the old block, so the :385
   treatment still applies anywhere else it is used, and only the mastrail — the
   one place on a light ground — opts out. Border is left alone deliberately:
   redesign.css puts `border-left` on the second column as the divider between
   the two stats, and `border: 0` would take that with it. */
#homeStage .hv2 .hv2-mastrail .hv2-kpi {
  background: none;
  border-radius: 0;
  overflow: visible;
}

/* No rules between the masthead stats (owner, 2026-08-13: "remove the blue
   lines"). Two sources, both rgba(13,35,64,.12):

     .hv2-kpis   border-top  — the horizontal rule under the card
     .hv2-kpi    border-left — the vertical divider between the two columns

   Both are removed. The stats are already separated by a 16x28 grid gap and by
   being centred in equal columns; the rules were doing the same job a second
   time, which is what made the block read as ruled rather than laid out.

   THE CARD'S OWN BORDER STAYS. .hv2-proof keeps its 1px outline and
   .hv2-proof__face its avatar ring — those are the card, not lines between
   stats, and removing them would dissolve the panel the owner asked to centre
   these within two commits ago.

   The `padding-right: 28px` added in bddeaf23 stays too: it was there to
   balance the divider's `padding-left` so centred text sat on the cell's
   midline. With the divider gone the left padding remains (it is redesign.css's,
   not mine), so the symmetry is still doing work — dropping it now would push
   the right column 14px off centre again. */
#homeStage .hv2 .hv2-mastrail .hv2-kpis { border-top: 0; }
#homeStage .hv2 .hv2-mastrail .hv2-kpi { border: 0; }
/* The column divider needs the same :nth-child weight to clear. redesign.css
   sets it as `#homeStage .hv2 .hv2-mastrail .hv2-kpi:nth-child(2n)` — the
   pseudo-class takes it to (1,4,0), so the (1,3,0) rule above removes every
   border EXCEPT the one actually drawing the line. Measured: the block rule
   cleared, .hv2-kpi [left] survived at 1px. */
#homeStage .hv2 .hv2-mastrail .hv2-kpi:nth-child(2n) { border-left: 0; }

/* The last two survivors of the dark-stage KPI treatment (owner, 2026-08-13:
   "there's still these blue lines above 1358").

   :385-423 styles .hv2-kpi as a raised tile for the navy field. The background,
   border and radius were suppressed two commits ago; these two were not, because
   I fixed what I could SEE in a screenshot instead of reading the whole block:

     ::before   a 2px absolutely-positioned bar across the top of every cell,
                linear-gradient(90deg, transparent, --ms-brand, transparent) —
                rgb(29,95,167) on three cells and rgb(4,120,87) on the .is-edge
                one. That is the blue line above 1,358 and the green one above
                +4.3%.
     :hover     translateY(-3px) with box-shadow 0 14px 40px rgba(3,8,20,.6) —
                a heavy near-black lift built for a dark field, still armed on a
                white page. Not visible in a screenshot, which is why it survived
                two rounds of this.

   Both were held down by the stat-line block deleted in 8a7cc28e, along with the
   tile background restored in 45bd978c. Third symptom, one cause: that deletion
   removed a suppression layer, not just dead code. Reading :385-423 top to
   bottom and neutralising every property it sets is what closes this out. */
#homeStage .hv2 .hv2-mastrail .hv2-kpi::before { display: none; }
#homeStage .hv2 .hv2-mastrail .hv2-kpi:hover {
  transform: none;
  box-shadow: none;
  border-color: transparent;
}

/* ═══ THE MASTHEAD IS ONE PANEL ═══════════════════════════════════════════
   Owner, 2026-08-13: "maybe put this in one super light gray box" — the whole
   masthead: wordmark, headline, lede, search, CTAs, the live-from-the-model card
   and the four stats.

   .hv2-masthead--v2 already wraps exactly that content (measured x 350 -> 1530,
   the same span as every card below it) and was transparent, so this only needs
   a surface, not a new element or any change to the layout inside it.

   Box edges stay on the page grid at 350/1530 rather than bleeding wider. The
   alternative — negative margins so the inner content kept its 350 edge — would
   have put the panel's edge at 326 against cards at 350, i.e. bought inner
   alignment by breaking outer alignment. Every card on this page already works
   the other way: box on the grid, content inset from it. The masthead now
   matches that convention instead of inventing a second one.

   #f6f8fa against the page's #eef2f7: light enough to read as raised rather than
   as a different section, which is what "super light" has to mean on a ground
   that is already pale. The hairline does the edge definition the low contrast
   cannot, and there is no shadow — shadows were removed from this page on
   purpose earlier today. */
#homeStage .hv2 .hv2-masthead--v2 {
  background: #f6f8fa;
  border: 1px solid rgba(13, 35, 64, .07);
  border-radius: 18px;
  padding: 30px 28px 26px;
}
