/* ═══════════════════════════════════════════════════════════════════════
   Main Menu V2 — Phase A
   ═══════════════════════════════════════════════════════════════════════
   Scope: every rule in this file is scoped under `body.menu-v2`. With the
   feature flag off (the live default), nothing here activates. The v2 menu
   ships incrementally over Phases B–H; Phase A only lays the design-token
   floor and the background-plate primitives so later phases can build on
   them without ID churn.

   Source of truth: docs/v2/main-menu-redesign/_shared.css. When the design
   stabilises, this file will merge with that one and the mockups will start
   importing from here instead of carrying their own copy.

   Feature flag: localStorage key `meteor_v2_menu_v2_enabled` (read by the
   bootstrap code in a later phase). When `true`, the page sets
   `document.body.classList.add('menu-v2')` and these rules light up.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── DESIGN TOKENS ────────────────────────────────────────────────────
   Namespaced under body.menu-v2 so they don't bleed into legacy styles
   that already use `--color-primary`, `--font-display`, etc.
   These names match docs/v2/main-menu-redesign/_shared.css exactly. */

body.menu-v2 {
  /* Background palette */
  --mm-bg-void:        #04061a;
  --mm-bg-deep:        #06081f;
  --mm-bg-mid:         #121233;
  --mm-bg-violet:      #1f1448;
  --mm-bg-card:        rgba(20, 28, 60, 0.74);
  --mm-bg-card-strong: rgba(28, 22, 64, 0.88);

  /* Accents */
  --mm-cyan:           #5dd6ff;
  --mm-cyan-hot:       #8fe9ff;
  --mm-cyan-deep:      #1a4d7a;
  --mm-cyan-glow:      rgba(93, 214, 255, 0.55);

  --mm-violet:         #b48aff;
  --mm-violet-hot:     #d4b4ff;
  --mm-violet-deep:    #4a2d80;
  --mm-violet-glow:    rgba(180, 138, 255, 0.55);

  --mm-gold:           #ffd86b;
  --mm-gold-hot:       #ffe89c;
  --mm-gold-deep:      #a06b00;
  --mm-gold-glow:      rgba(255, 216, 107, 0.55);

  --mm-rose:           #ff8ab0;
  --mm-rose-glow:      rgba(255, 138, 176, 0.45);
  --mm-green-good:     #7af9c8;
  --mm-orange-fire:    #ff7e2e;
  --mm-red-hot:        #ff5d6b;

  /* Text */
  --mm-text-primary:   #ecf7ff;
  --mm-text-secondary: #bfd0ea;
  --mm-text-muted:     #94b4d2;
  --mm-text-faint:     rgba(157, 178, 215, 0.6);

  /* Borders */
  --mm-border-cyan:    rgba(93, 214, 255, 0.38);
  --mm-border-violet: rgba(180, 138, 255, 0.42);
  --mm-border-gold:    rgba(255, 216, 107, 0.45);
  --mm-border-faint:   rgba(120, 150, 200, 0.22);

  /* Spacing */
  --mm-gap-1:  6px;
  --mm-gap-2:  12px;
  --mm-gap-3:  20px;
  --mm-gap-4:  32px;
  --mm-gap-5:  48px;

  /* Layout */
  --mm-max-w:  1760px;
  --mm-pad-x:  clamp(20px, 3vw, 56px);
  --mm-pad-y:  clamp(16px, 2.4vw, 40px);

  /* Type scale (responsive) */
  --mm-t-display:   clamp(28px, 4.2vw, 64px);
  --mm-t-headline:  clamp(20px, 2.6vw, 40px);
  --mm-t-title:     clamp(16px, 1.6vw, 22px);
  --mm-t-body:      clamp(13px, 1vw, 16px);
  --mm-t-tag:       clamp(10px, 0.78vw, 12px);

  /* Motion */
  --mm-ease:        cubic-bezier(0.2, 0.85, 0.3, 1.0);
  --mm-t-fast:      120ms;
  --mm-t-mid:       240ms;
  --mm-t-slow:      420ms;

  /* Fonts — reuse the live Orbitron + Inter that index.html already loads. */
  --mm-font-display: "Orbitron", "Bank Gothic", "Inter", system-ui, sans-serif;
  --mm-font-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mm-font-mono:    "JetBrains Mono", "Fira Code", ui-monospace, monospace;

  /* Sci-fi corner cut */
  --mm-cut:    18px;
  --mm-cut-sm: 10px;
}

/* ─── BACKGROUND PLATE ─────────────────────────────────────────────────
   Full-bleed painted art layer using the game's existing WebP/PNG assets
   from assets/backgrounds/ (city skylines), assets/coach_bg/ (per-coach
   scenes), and assets/cc_bg/ (Command Check scenes). The element is set
   via inline `background-image` per-page; this rule only sizes/positions
   the layer. */

body.menu-v2 .mm-bg-plate {
  position: fixed;
  inset: 0;
  z-index: -8;
  pointer-events: none;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Coach-scene plates have illustration-heavy edges and an empty centre,
   so default cover-centring is correct. */
body.menu-v2 .mm-bg-plate--coach { background-position: 50% 50%; }
/* City plates: anchor lower so the painted skyline sits near the bottom. */
body.menu-v2 .mm-bg-plate--city  { background-position: 50% 75%; }
/* Command-Check plates: empty-centre party compositions, cover-centre. */
body.menu-v2 .mm-bg-plate--cc    { background-position: 50% 50%; }

/* ─── BACKGROUND SCRIM ─────────────────────────────────────────────────
   Sits between the painted plate and the UI to keep white text readable
   without killing the art. Soft centre-band + corner vignette + a darker
   bottom strip behind the toolbar. */

body.menu-v2 .mm-bg-scrim {
  position: fixed;
  inset: 0;
  z-index: -7;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      rgba(6, 8, 26, 0.35) 0%,
      rgba(6, 8, 26, 0.18) 30%,
      rgba(6, 8, 26, 0.18) 70%,
      rgba(6, 8, 26, 0.55) 100%),
    radial-gradient(ellipse 90% 70% at 50% 50%,
      transparent 40%,
      rgba(6, 8, 26, 0.45) 100%);
}
/* Stronger variant for dense Beat-2 pack-grid screens. */
body.menu-v2 .mm-bg-scrim--strong {
  background:
    linear-gradient(180deg,
      rgba(6, 8, 26, 0.5) 0%,
      rgba(6, 8, 26, 0.35) 30%,
      rgba(6, 8, 26, 0.35) 70%,
      rgba(6, 8, 26, 0.7) 100%),
    radial-gradient(ellipse 90% 70% at 50% 50%,
      transparent 25%,
      rgba(6, 8, 26, 0.55) 100%);
}

/* ─── BACKGROUND BASE FALLBACK ─────────────────────────────────────────
   If the painted plate's image hasn't loaded yet (first paint, cache
   miss), this deep-navy gradient sits underneath so the user never sees
   the legacy menu background bleeding through. Same colour as the
   mockup's body::before fallback. */

body.menu-v2::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -10;
  background: linear-gradient(180deg,
    var(--mm-bg-void) 0%,
    var(--mm-bg-mid) 50%,
    var(--mm-bg-void) 100%);
  pointer-events: none;
}

/* ═══════════════════════════════════════════════════════════════════════
   PHASE B — top bar, welcome hero, bottom strip
   ═══════════════════════════════════════════════════════════════════════
   Adds the new chrome around the legacy menu content. The legacy hero
   and ghost-button toolbar are hidden; their function moves to the new
   chrome (welcome hero + bottom strip). Center column and side panels
   remain untouched — those are Phase C/D's job.
   ═══════════════════════════════════════════════════════════════════════ */

/* Hide legacy hero and ghost-button toolbar so they don't duplicate v2 chrome. */
body.menu-v2 #main-menu header.menu-hero { display: none; }
body.menu-v2 #main-menu .menu-toolbar--launch { display: none; }
/* Reserve top + bottom space inside the dashboard so content doesn't slip
   under the fixed top bar / bottom strip. Phase H: tightened to give the
   four long boxes ~20% more vertical breathing room. */
/* On desktop (≥ 1024px) the v2 menu fits inside the viewport by design —
   pin both html + body to viewport height so `position: fixed` anchors
   correctly (when body grows past viewport, Chrome treats the document
   as the containing block for fixed elements and the bottom strip would
   shift down by the overflow amount). The legacy "stars-bg" decorative
   elements extend a few px past 100vh; clipping body overflow there
   suppresses an unwanted scrollbar on the dashboard. On smaller
   viewports (mobile/tablet, where mode cards stack vertically) the body
   keeps scrolling so the user can reach the bottom strip. */
/* #main-menu has `backdrop-filter: blur(10px)` which creates a new
   containing block for `position: fixed` descendants — top bar + bottom
   strip would anchor to #main-menu rather than the viewport. Capping
   #main-menu to 100vh snaps them back to the viewport edges. The
   dashboard content inside #main-menu gets its own internal scroll on
   small viewports (mobile/tablet) where the stacked mode cards exceed
   viewport height. */
/* High-specificity selector to defeat legacy
   `#main-menu.menu-dashboard.overlay.screen { overflow-y: auto }`
   (specificity 0,4,0,0). Without this, #main-menu got an outer scrollbar
   that took 8px from the right edge of fixed-positioned top bar + bottom
   strip on mobile/tablet. */
body.menu-v2 #main-menu.menu-dashboard.overlay.screen {
  height: 100vh;
  max-height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* #main-menu itself has class .menu-dashboard (single element with both
   .overlay + .screen + .menu-dashboard) — so we make the inner wrapper
   the scroll container. .menu-scale-root → .menu-scale-stage →
   .menu-scale-surface → .menu-dashboard-inner is the legacy chain;
   .menu-scale-root flexes to fill #main-menu and becomes the scroll
   container. Without this, the strip ended up trapped inside the
   scrolling area and slid up/down with the content. */
body.menu-v2 #main-menu > .menu-scale-root {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}
@media (min-width: 1024px) {
  html:has(body.menu-v2),
  body.menu-v2 {
    height: 100%;
    overflow: hidden;
  }
}

body.menu-v2 #main-menu .menu-dashboard-inner {
  /* Override the legacy 1560px max-width — let v2 use the full viewport
     (v2's own max-width-cap lives on .mm-content via --mm-max-w). This
     was the source of horizontal overflow on 13" laptops: the legacy
     parent was 1560px wide on a 1280px viewport, pushing the coach
     panel 56px off-screen left and the side rail 49px off-screen right. */
  max-width: 100%;
  width: 100%;
  /* Vertical padding scales with viewport. Top padding reserves clearance
     for the fixed 64px top bar; bottom for the fixed ~53px bottom strip.
     Round 21: shaved floor values down so the .menu-dashboard-inner stays
     ≤ viewport height on 13" laptops (was hitting 802px on 800px viewport).
     min 64px top + 50px bottom = exactly 64 + 53 of fixed-strip clearance,
     no slack. */
  padding-top: clamp(64px, 8vh, 80px);
  padding-bottom: clamp(50px, 6.5vh, 72px);
}

/* ─── Disable the legacy menu-scale wrapper when v2 is active ───────
   The legacy menu was a fixed 1560×900 canvas scaled via CSS transform
   to fit smaller viewports, with a minScale: 0.72 floor — meaning the
   menu never shrunk below ~1123px wide and tablets/phones got clipped.
   v2 uses fluid CSS grid/flex, so the scale wrappers must let go of
   their fixed widths and skip the transform. Without this override,
   .menu-scale-surface stays 1560px wide and `transform: scale(0.72)`
   produces an off-screen menu on any viewport under 1560 / 0.72 = 2166px. */
body.menu-v2 .menu-scale-root {
  flex: 1;
  width: 100%;
  display: block;
  overflow: visible;
  padding: 0;
}
body.menu-v2 .menu-scale-stage {
  width: 100%;
  height: auto;
  position: static;
  overflow: visible;
}
body.menu-v2 .menu-scale-surface {
  width: 100%;
  height: auto;
  max-height: none;
  transform: none;
  position: static;
  overflow: visible;
}

/* ─── TOP BAR ───────────────────────────────────────────────────────── */
body.menu-v2 .mm-top-bar {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 64px;
  padding: 0 var(--mm-pad-x);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: linear-gradient(180deg, rgba(8, 8, 24, 0.94), rgba(8, 8, 24, 0.6));
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--mm-border-faint);
  z-index: 12;
  font-family: var(--mm-font-body);
  color: var(--mm-text-primary);
}
body.menu-v2 .mm-top-bar::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--mm-cyan), transparent);
  opacity: 0.5;
  pointer-events: none;
}
body.menu-v2 .mm-top-bar__brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
body.menu-v2 .mm-top-bar__brand-text {
  font-family: var(--mm-font-display);
  display: inline-flex;
  align-items: baseline;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
body.menu-v2 .mm-top-bar__brand-name {
  font-weight: 900;
  letter-spacing: 0.22em;
  font-size: 13px;
  text-transform: uppercase;
  background: linear-gradient(180deg, var(--mm-cyan-hot), var(--mm-violet));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  flex-shrink: 0;
}
body.menu-v2 .mm-top-bar__brand-tagline {
  font-family: var(--mm-font-body);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--mm-text-muted);
  /* Shrink first if the viewport is tight, but keep the tagline visible.
     The chrome's left-aligned brand area still forces single-row layout
     via white-space: nowrap on the parent. */
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Hide the long tagline on narrow viewports (phones / very small windows)
   so the chip and gear stay on the same row without wrapping. */
@media (max-width: 900px) {
  body.menu-v2 .mm-top-bar__brand-tagline { display: none; }
}
body.menu-v2 .mm-top-bar__right {
  display: flex;
  align-items: center;
  gap: 12px;
}
body.menu-v2 .mm-top-bar__player {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 14px 6px 6px;
  border-radius: 999px;
  background: rgba(20, 28, 60, 0.65);
  border: 1px solid var(--mm-border-faint);
  font-size: 13px;
  font-weight: 700;
}
body.menu-v2 .mm-top-bar__player-svg {
  /* Phase H round 8: the avatar now renders the active student's chosen
     emoji icon (matches the dropdown rows). Sized + framed so the emoji
     reads cleanly against the soft violet backdrop without competing
     with the nickname text next to it. */
  width: 28px; height: 28px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(180, 138, 255, 0.28), rgba(28, 22, 64, 0.55));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  line-height: 1;
  border: 1px solid var(--mm-border-violet);
}
body.menu-v2 .mm-top-bar__player-name {
  color: var(--mm-text-primary);
}

/* ─── WELCOME HERO ──────────────────────────────────────────────────── */
body.menu-v2 .mm-welcome-hero {
  position: relative;
  z-index: 2;
  text-align: center;
  margin: clamp(10px, 1.4vh, 22px) auto var(--mm-gap-3);
  padding: 0 var(--mm-pad-x);
  max-width: var(--mm-max-w);
}
body.menu-v2 .mm-eyebrow {
  font-family: var(--mm-font-display);
  font-size: clamp(9px, 0.8vw, 11px);
  letter-spacing: 0.42em;
  color: var(--mm-cyan);
  text-transform: uppercase;
  margin: 0 0 6px;
  opacity: 0.9;
}
body.menu-v2 .mm-greeting {
  font-family: var(--mm-font-display);
  /* Phase H polish (round 3): smaller greeting so the actionable subline
     can carry weight — kids should look at "Pick up where you left off"
     not at "WELCOME BACK". */
  font-size: clamp(16px, 1.9vw, 26px);
  font-weight: 800;
  letter-spacing: 0.04em;
  background: linear-gradient(180deg, #ffffff 0%, var(--mm-cyan) 70%, var(--mm-violet-hot) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 0 20px rgba(93, 214, 255, 0.3);
  margin: 0;
  text-transform: uppercase;
}
body.menu-v2 .mm-greeting::after {
  content: "";
  display: block;
  margin: 8px auto 0;
  width: 80px; height: 2px;
  background: linear-gradient(90deg, transparent, var(--mm-cyan), transparent);
}
body.menu-v2 .mm-subline {
  /* Promoted: this is the line a 6yo should land on. Larger + brighter
     than the greeting above. */
  font-size: clamp(15px, 1.4vw, 20px);
  font-family: var(--mm-font-display);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--mm-cyan-hot);
  text-shadow: 0 0 12px var(--mm-cyan-glow);
  margin: 8px 0 0;
}

/* ─── BOTTOM STRIP ──────────────────────────────────────────────────── */
body.menu-v2 .mm-bottom-strip {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  padding: 10px var(--mm-pad-x);
  border-top: 1px solid var(--mm-border-faint);
  background: linear-gradient(0deg, rgba(8, 8, 24, 0.94), rgba(8, 8, 24, 0.4));
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  z-index: 12;
}
body.menu-v2 .mm-bottom-strip::before {
  content: "";
  position: absolute; left: 0; right: 0; top: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--mm-cyan), transparent);
  opacity: 0.5;
  pointer-events: none;
}
body.menu-v2 .mm-bottom-strip {
  /* Phase H polish: toolbar on the left, tip on the right. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--mm-gap-3);
}
body.menu-v2 .mm-bottom-strip__toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  flex-wrap: wrap;
}
body.menu-v2 .mm-bottom-strip__tip {
  font-size: 12px;
  color: var(--mm-text-muted);
  font-family: var(--mm-font-body);
  flex-shrink: 0;
  text-align: right;
}
body.menu-v2 .mm-bottom-strip__tip-star {
  color: var(--mm-gold);
  font-size: 13px;
  margin-right: 2px;
}
/* Uniform bottom-toolbar buttons. Phase H polish: every button — including
   the relocated #btn-scoring-rules which had unique legacy styling — gets
   the SAME treatment. Icon left, label right, single row, no wrap. */
body.menu-v2 .mm-bottom-strip__toolbar > .mm-bottom-strip__btn,
body.menu-v2 .mm-bottom-strip__toolbar > button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: rgba(20, 28, 60, 0.55) !important;
  border: 1px solid var(--mm-border-faint) !important;
  color: var(--mm-text-secondary) !important;
  font-family: var(--mm-font-display) !important;
  font-size: 12px !important;
  letter-spacing: 0.20em !important;
  text-transform: uppercase !important;
  font-weight: 700 !important;
  border-radius: 999px !important;
  cursor: pointer;
  height: auto !important;
  line-height: 1.2 !important;
  white-space: nowrap;
  transition:
    border-color var(--mm-t-fast),
    color var(--mm-t-fast),
    box-shadow var(--mm-t-fast);
}
body.menu-v2 .mm-bottom-strip__toolbar > .mm-bottom-strip__btn:hover,
body.menu-v2 .mm-bottom-strip__toolbar > button:hover {
  border-color: var(--mm-cyan) !important;
  color: var(--mm-cyan) !important;
  box-shadow: 0 0 12px var(--mm-cyan-glow) !important;
}
body.menu-v2 .mm-bottom-strip__btn-icon {
  font-size: 14px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  filter: saturate(1.1);
}
body.menu-v2 .mm-bottom-strip__btn-label {
  display: inline-block;
}
/* Toolbar stays in ONE row — never wraps to two. */
body.menu-v2 .mm-bottom-strip__toolbar {
  flex-wrap: nowrap !important;
}
/* ─── Phase H round 20: mobile-only compaction for the bottom strip.
   On <600px viewports the 4 buttons + tip text overflowed the row.
   Hide the tip, shrink button labels to icon-only, and let the toolbar
   centre itself across the full strip width. */
@media (max-width: 600px) {
  body.menu-v2 .mm-bottom-strip {
    justify-content: center;
    padding-left: 8px;
    padding-right: 8px;
  }
  body.menu-v2 .mm-bottom-strip__tip { display: none; }
  body.menu-v2 .mm-bottom-strip__toolbar { gap: 6px; }
  body.menu-v2 .mm-bottom-strip__toolbar > .mm-bottom-strip__btn,
  body.menu-v2 .mm-bottom-strip__toolbar > button {
    padding: 8px 10px !important;
    font-size: 11px !important;
    letter-spacing: 0.12em !important;
  }
  body.menu-v2 .mm-bottom-strip__btn-label {
    /* Icon-only at the smallest sizes — labels become aria-hidden visual
       noise. Touch-target stays large because padding is preserved. */
    display: none;
  }
}
/* Phase H polish: neutralise any legacy ::before / ::after icons added
   by styles/style.css for the bottom toolbar buttons. The legacy CSS
   uses #main-menu #btn-* selectors with high specificity; we match it
   with body.menu-v2 #main-menu #btn-* so v2 wins. */
body.menu-v2 #main-menu #btn-how-to-play::before,
body.menu-v2 #main-menu #btn-settings::before,
body.menu-v2 #main-menu #btn-scoring-rules::before,
body.menu-v2 #main-menu #btn-view-story::before,
body.menu-v2 #main-menu #btn-how-to-play::after,
body.menu-v2 #main-menu #btn-settings::after,
body.menu-v2 #main-menu #btn-scoring-rules::after,
body.menu-v2 #main-menu #btn-view-story::after {
  content: none !important;
  display: none !important;
}
/* Uniform pill for every toolbar button — beats `#main-menu #btn-*`
   (specificity 0,2,0,0) by adding our own body class + #main-menu +
   #btn-id chain (0,2,1,0). */
body.menu-v2 #main-menu #btn-how-to-play,
body.menu-v2 #main-menu #btn-settings,
body.menu-v2 #main-menu #btn-scoring-rules,
body.menu-v2 #main-menu #btn-view-story {
  display: inline-flex !important;
  flex-direction: row !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 8px !important;
  min-height: 0 !important;
  height: auto !important;
  width: auto !important;
  margin: 0 !important;
  padding: 8px 16px !important;
  background: rgba(20, 28, 60, 0.55) !important;
  border: 1px solid var(--mm-border-faint) !important;
  border-radius: 999px !important;
  color: var(--mm-text-secondary) !important;
  font-family: var(--mm-font-display) !important;
  font-size: 12px !important;
  font-weight: 700 !important;
  letter-spacing: 0.20em !important;
  text-transform: uppercase !important;
  line-height: 1.2 !important;
  white-space: nowrap !important;
  box-shadow: none !important;
}
body.menu-v2 #main-menu #btn-how-to-play:hover,
body.menu-v2 #main-menu #btn-settings:hover,
body.menu-v2 #main-menu #btn-scoring-rules:hover,
body.menu-v2 #main-menu #btn-view-story:hover {
  background: rgba(20, 28, 60, 0.55) !important;
  border-color: var(--mm-cyan) !important;
  color: var(--mm-cyan) !important;
  box-shadow: 0 0 12px var(--mm-cyan-glow) !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   PHASE C + D — mode cards (welcome view) + pack-select view
   ═══════════════════════════════════════════════════════════════════════
   The legacy 3-column layout is hidden; the new content area renders one
   of two views at a time:
     * .mm-view--welcome      — 3 mode cards (Mission / Storm / Ultimate)
     * .mm-view--pack-select  — pack tile grid with mode-specific framing
   View toggling is class-driven by the JS (data-active-view="welcome|pack").

   The legacy #btn-numerai-lounge and #coach-of-the-day-chip-host are
   physically relocated into a temporary side rail on the right; Phase E
   will refine them into the full Coach-of-the-Day panel.
   ═══════════════════════════════════════════════════════════════════════ */

/* Hide the entire legacy column layout when v2 is on. */
body.menu-v2 #main-menu .menu-columns { display: none; }

/* Main v2 content area — takes the space between hero and bottom strip.
   Default: 2-col (main + side rail). With a Coach of the Day panel
   present (Phase E), the layout becomes 3-col (coach | main | side rail). */
body.menu-v2 .mm-content {
  position: relative;
  width: 100%;
  max-width: var(--mm-max-w);
  margin: 0 auto;
  padding: 0 var(--mm-pad-x);
  display: grid;
  grid-template-columns: 1fr minmax(240px, 280px);
  gap: var(--mm-gap-3);
  align-items: start;
}
body.menu-v2 .mm-content[data-has-coach-panel="true"] {
  /* Phase H polish (round 2/18) → round 31 (May 2026 user request):
   *   All five visible tiles on the welcome view (COTD | Mission | Storm |
   *   Ultimate | Side rail) share THE SAME WIDTH. The trick is CSS
   *   subgrid: the outer container declares 5 equal-width columns; the
   *   intermediate wrappers (.mm-content__main, .mm-view--welcome,
   *   .mm-mode-grid) all use grid-template-columns: subgrid so the 3
   *   mode-cards align exactly with the middle 3 outer columns. Without
   *   subgrid, the inner mode-grid's gap would steal a few pixels from
   *   each mode-card vs. COTD/side-rail (9px @ 14px gap on a 1440px
   *   viewport), giving the lopsided look the user flagged.
   *
   *   Column layout when welcome view active:
   *     1: COTD (.mm-coach-panel)
   *     2: Mission card  ─┐
   *     3: Storm card     │ via subgrid through mode-grid
   *     4: Ultimate card ─┘
   *     5: Side rail (stacks numerai-lounge / dashboard / leaderboard
   *        vertically; each tile = 1 column wide via width:100%).
   *
   * minmax(0, 1fr) is critical: bare 1fr defaults to minmax(auto, 1fr),
   * where auto is content-based, so the side rail's ~290px-natural-width
   * lounge tile would force the grid past viewport width and overflow. */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(8px, 1vw, 14px);
  padding-left: clamp(12px, 1.5vw, 28px);
  padding-right: clamp(12px, 1.5vw, 28px);
  align-items: stretch;   /* coach panel + mode-card row + side rail share row height */
}
/* Subgrid pass-through: .mm-content__main occupies the middle 3 columns
   and re-projects them to its children. .mm-view--welcome and
   .mm-mode-grid each forward the subgrid so the 3 mode-cards land in
   the outer columns 2-4. */
body.menu-v2 .mm-content[data-has-coach-panel="true"] > .mm-content__main {
  grid-column: 2 / 5;
  display: grid;
  grid-template-columns: subgrid;
  gap: inherit;
}
body.menu-v2 .mm-content[data-active-view="welcome"] > .mm-content__main > .mm-view--welcome {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  gap: inherit;
  /* Replace the original flex-column layout — the mode-grid is the only
     direct child today, so subgrid → mode-grid is sufficient. */
}
body.menu-v2 .mm-content[data-active-view="welcome"] > .mm-content__main > .mm-view--welcome > .mm-mode-grid {
  grid-column: 1 / -1;
  /* Override the standalone repeat(3, 1fr) below — we now inherit
     column tracks from the outer grid via subgrid. */
  grid-template-columns: subgrid;
}
/* Pack-select view (different layout) just fills the middle area as
   a single block — no subgrid involvement. */
body.menu-v2 .mm-content[data-active-view="pack-select"] > .mm-content__main > .mm-view--pack-select {
  grid-column: 1 / -1;
}
/* Phase H round 29: align the bottom of the Coach of the Day panel with
   the bottom of the pack-select stack ("Elite" box) by using the
   inherited `align-items: stretch` — both columns share the row height.
   Coach panel chrome (chip + svg + name + tagline + cta row) is ~340px;
   pack-stack with 4 categories is ~600px → pack-stack drives the row,
   coach panel stretches to match with the cta-row pinned to the bottom
   via margin-top:auto (already set on .mm-coach-panel__cta-row).
   The round-22 cap (transmission max-height below) prevents Pink-style
   long transmission text from blowing the coach panel up beyond the
   pack-stack height, which was the original inflate-on-13"-laptop bug. */
body.menu-v2 .mm-content[data-active-view="pack-select"] {
  align-items: stretch;
}
/* 13"-laptop / narrow-desktop breakpoint. Bumped from 1280 → 1366 so the
   common 13" Windows laptop resolution (1366×768) AND viewport-as-1280
   variants both hit this rule. Collapses to 2-col (coach + main) with
   side rail spanning the bottom row. */
@media (max-width: 1366px) {
  body.menu-v2 .mm-content[data-has-coach-panel="true"] {
    grid-template-columns: minmax(220px, 280px) minmax(0, 1fr);
  }
  body.menu-v2 .mm-content[data-has-coach-panel="true"] .mm-side-rail {
    grid-column: 1 / -1;
    flex-direction: row;
    display: flex;
    gap: var(--mm-gap-2);
  }
  body.menu-v2 .mm-content[data-has-coach-panel="true"] .mm-side-rail > * {
    flex: 1 1 0;
    min-width: 0;
  }
}
@media (max-width: 900px) {
  body.menu-v2 .mm-content,
  body.menu-v2 .mm-content[data-has-coach-panel="true"] {
    /* minmax(0, 1fr) instead of bare 1fr — same reason as the desktop
       3-col rule above. Bare `1fr` defaults to `minmax(auto, 1fr)` where
       `auto` is content-based, so the coach panel's natural width
       (~700px) was forcing the single column to 700px wide on a 375px
       mobile viewport. minmax(0, 1fr) lets the column actually shrink
       to viewport width. */
    grid-template-columns: minmax(0, 1fr);
  }
  /* Side-rail tiles also need to shrink — same min-width-0 idiom. */
  body.menu-v2 .mm-content[data-has-coach-panel="true"] .mm-side-rail > * {
    min-width: 0;
  }
}

/* When the v2 coach panel is present, hide the legacy small chip — the
   panel now owns "who is on duty". The chip host stays in the DOM (in the
   side rail) so its inner content still renders if anyone re-targets it,
   but its display is `none`. */
body.menu-v2 .mm-content[data-has-coach-panel="true"] #coach-of-the-day-chip-host {
  display: none;
}

/* Phase H round 19: daily hook ribbon styles removed — the ribbon element
   itself is no longer injected (see mainMenuV2.js). Coach of the Day panel
   on the left column is the single surface for coach-of-the-day messaging. */

/* ─── Thin Ultimate strip (when player is far from unlock) ────────── */
body.menu-v2 .mm-mode-card--ultimate-thin {
  display: flex !important;
  flex-direction: row !important;
  align-items: center !important;
  justify-content: flex-start !important;
  gap: 12px;
  padding: 10px 16px;
  height: auto;
  min-height: 56px;
  align-self: end;            /* sit at the bottom of the row */
  background: linear-gradient(90deg, rgba(40, 24, 0, 0.5), rgba(6, 6, 20, 0.7));
  border: 1px dashed var(--mm-border-gold);
  border-radius: 12px;
  color: var(--mm-gold);
  font-family: var(--mm-font-body);
  text-align: left;
  cursor: pointer;
  clip-path: none;
  text-transform: none;
}
body.menu-v2 .mm-mode-card--ultimate-thin:hover {
  border-style: solid;
  filter: brightness(1.08);
  transform: none;
}
body.menu-v2 .mm-mode-card__thin-icon {
  font-size: 20px;
  flex-shrink: 0;
}
body.menu-v2 .mm-mode-card__thin-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
body.menu-v2 .mm-mode-card__thin-title {
  font-family: var(--mm-font-display);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mm-gold);
}
body.menu-v2 .mm-mode-card__thin-sub {
  font-size: 11px;
  color: var(--mm-text-muted);
  margin-top: 2px;
}
body.menu-v2 .mm-mode-card__thin-count {
  font-family: var(--mm-font-display);
  font-size: 13px;
  font-weight: 900;
  color: var(--mm-gold);
  flex-shrink: 0;
  letter-spacing: 0.06em;
}
/* When the thin strip is used, give it less vertical weight than the
   full mode cards — it sits at the bottom of its grid cell. */
body.menu-v2 .mm-mode-grid:has(.mm-mode-card--ultimate-thin) {
  grid-template-rows: 1fr auto;
}

/* View slot — welcome view (mode cards) and pack-select view share this.
   Each layer needs height: 100% so the bottom mode-card / coach-panel
   row stretches to match the outer grid row's full height. */
body.menu-v2 .mm-content__main { height: 100%; align-self: stretch; }
body.menu-v2 .mm-view { display: none; }
body.menu-v2 .mm-content[data-active-view="welcome"] .mm-view--welcome { display: flex; flex-direction: column; height: 100%; }
body.menu-v2 .mm-content[data-active-view="pack-select"] .mm-view--pack-select { display: block; height: 100%; }

/* ─── MODE CARDS (welcome view) ─────────────────────────────────────── */

body.menu-v2 .mm-mode-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Tightened gap so each individual mode-card width = coach panel width
     (5-column visual rhythm). */
  gap: clamp(8px, 1vw, 14px);
  /* Stretch to match coach + side-rail height in the outer 3-col grid. */
  height: 100%;
  align-self: stretch;
  /* Phase H polish (round 5/18): row height scales properly on 13" laptops.
     Old `clamp(400px, 56vh, 640px)` had a 400px floor which combined with
     hero (~83px) + top-bar (64px) + bottom-strip (52px) + vertical
     padding pushed total layout past 800px → page scrolled on 13"
     screens. New floor 300px + smaller vh slope keeps the row generous
     on wide screens but lets it shrink to fit 768/800px-tall viewports. */
  min-height: clamp(300px, 48vh, 560px);
}
@media (max-width: 900px) {
  body.menu-v2 .mm-mode-grid { grid-template-columns: 1fr; }
}

body.menu-v2 .mm-mode-card {
  position: relative;
  cursor: pointer;
  border: 1px solid var(--mm-border-faint);
  border-radius: 14px;
  /* Phase H polish: stretch to the row height alongside the coach panel. */
  height: 100%;
  align-self: stretch;
  padding: clamp(14px, 1.6vh, 22px) clamp(12px, 1vw, 18px) clamp(12px, 1.4vh, 18px);
  background:
    radial-gradient(ellipse 80% 40% at 50% 100%, rgba(93, 214, 255, 0.16), transparent 70%),
    linear-gradient(180deg, rgba(8, 26, 56, 0.7), rgba(6, 8, 30, 0.92));
  color: var(--mm-text-primary);
  font-family: var(--mm-font-body);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition: transform var(--mm-t-fast), box-shadow var(--mm-t-fast), filter var(--mm-t-fast);
  clip-path: polygon(
    var(--mm-cut) 0, calc(100% - var(--mm-cut)) 0, 100% var(--mm-cut),
    100% calc(100% - var(--mm-cut)), calc(100% - var(--mm-cut)) 100%,
    var(--mm-cut) 100%, 0 calc(100% - var(--mm-cut)), 0 var(--mm-cut)
  );
}
body.menu-v2 .mm-mode-card:hover {
  transform: translateY(-4px);
  filter: brightness(1.08);
}
body.menu-v2 .mm-mode-card--mission { color: var(--mm-cyan);   border-color: var(--mm-border-cyan); }
body.menu-v2 .mm-mode-card--storm   { color: var(--mm-violet); border-color: var(--mm-border-violet); background: radial-gradient(ellipse 80% 40% at 50% 100%, rgba(180, 138, 255, 0.22), transparent 70%), linear-gradient(180deg, rgba(40, 14, 70, 0.6), rgba(10, 6, 30, 0.94)); }
body.menu-v2 .mm-mode-card--ultimate { color: var(--mm-gold);   border-color: var(--mm-border-gold);   background: radial-gradient(ellipse 80% 40% at 50% 100%, rgba(255, 216, 107, 0.16), transparent 70%), linear-gradient(180deg, rgba(40, 24, 0, 0.6), rgba(6, 6, 20, 0.96)); }
body.menu-v2 .mm-mode-card--ultimate.is-locked { cursor: not-allowed; filter: brightness(0.85); }

body.menu-v2 .mm-mode-card__emblem {
  width: clamp(56px, 7vh, 90px);
  height: clamp(56px, 7vh, 90px);
  filter: drop-shadow(0 0 14px currentColor);
  margin-bottom: 2px;
}
body.menu-v2 .mm-mode-card__name {
  font-family: var(--mm-font-display);
  font-size: clamp(14px, 1.4vw, 20px);
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-shadow: 0 0 18px currentColor;
  white-space: nowrap;       /* keep "METEOR STORM" on one line */
  text-align: center;
}
body.menu-v2 .mm-mode-card__tagline {
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
}
body.menu-v2 .mm-mode-card__verb-badge {
  margin: 4px 0 2px;
  padding: 10px 16px 12px;
  border: 1px solid currentColor;
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.25));
  display: flex; flex-direction: column; align-items: center;
  gap: 2px;
}
body.menu-v2 .mm-mode-card__verb {
  font-family: var(--mm-font-display);
  font-size: clamp(14px, 1.4vw, 18px);
  font-weight: 900;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-shadow: 0 0 12px currentColor;
}
body.menu-v2 .mm-mode-card__verb-sub {
  font-size: 9px;
  letter-spacing: 0.22em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
}
body.menu-v2 .mm-mode-card__stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  width: 100%;
  /* Phase H polish (round 3): align all 3 cards' stat strips to the SAME
     vertical anchor near the bottom — push the stats with margin-top:auto
     AND fix their distance from the CTA so a kid sees a consistent row
     of "current / next" data across cards. */
  margin-top: auto;
  margin-bottom: 0;
}
body.menu-v2 .mm-mode-card__cta {
  /* Same anchor: CTA sits flush below the stats, fixed offset from the
     card's bottom edge regardless of how much pitch text was above. */
  flex-shrink: 0;
}
body.menu-v2 .mm-mode-card__stat {
  padding: 6px 4px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--mm-border-faint);
  border-radius: 8px;
  text-align: center;
}
body.menu-v2 .mm-mode-card__stat-label {
  font-family: var(--mm-font-display);
  font-size: 8px;
  letter-spacing: 0.22em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
}
body.menu-v2 .mm-mode-card__stat-value {
  font-family: var(--mm-font-display);
  font-size: clamp(11px, 1vw, 13px);
  font-weight: 800;
  color: var(--mm-text-primary);
  margin-top: 2px;
}
body.menu-v2 .mm-mode-card__stat-value--violet { color: var(--mm-violet); }
body.menu-v2 .mm-mode-card__stat-value--gold   { color: var(--mm-gold); }
body.menu-v2 .mm-mode-card__pitch-accent       { color: var(--mm-cyan); }
body.menu-v2 .mm-mode-card__pitch {
  font-size: clamp(11px, 0.9vw, 13px);
  color: var(--mm-text-secondary);
  line-height: 1.4;
  margin: 4px 4px 8px;
}
body.menu-v2 .mm-mode-card__cta {
  margin-top: auto;
  padding: 8px 14px;
  font-family: var(--mm-font-display);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  border-radius: 999px;
  border: 1px solid currentColor;
  background: rgba(0, 0, 0, 0.4);
  color: currentColor;
}
body.menu-v2 .mm-mode-card__lock {
  position: absolute;
  top: 10px; right: 10px;
  padding: 3px 8px;
  font-family: var(--mm-font-display);
  font-size: 9px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--mm-gold);
  background: rgba(0, 0, 0, 0.6);
  border: 1px solid var(--mm-border-gold);
  border-radius: 999px;
  display: none;
}
body.menu-v2 .mm-mode-card--ultimate.is-locked .mm-mode-card__lock { display: inline-block; }

/* ─── PACK SELECT VIEW ──────────────────────────────────────────────── */

body.menu-v2 .mm-pack-banner {
  display: flex;
  align-items: center;
  /* Phase H round 12: tightened to keep title + subtitle + dropdowns +
     back button on ONE row. Reduced gap and padding; selectively shrank
     each child below. flex-wrap: nowrap prevents the banner from
     stacking even when the viewport gets narrow. */
  gap: 10px;
  flex-wrap: nowrap;
  padding: 8px 14px;
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(20, 36, 88, 0.6), rgba(8, 14, 36, 0.6));
  border: 1px solid var(--mm-border-cyan);
  margin-bottom: var(--mm-gap-3);
}
body.menu-v2 .mm-content[data-mode="storm"] .mm-pack-banner {
  background: linear-gradient(180deg, rgba(60, 24, 70, 0.65), rgba(20, 8, 36, 0.65));
  border-color: var(--mm-border-violet);
}
/* Phase H round 9 / round 12: title-only treatment (no pill, no icon).
   Bold uppercase header — sized to harmonize with the BACK button so
   the whole banner reads as a single row. white-space: nowrap prevents
   "METEOR STORM" from wrapping when dropdowns appear next to it. */
body.menu-v2 .mm-pack-banner__chip {
  font-family: var(--mm-font-display);
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--mm-cyan);
  font-weight: 900;
  text-shadow: 0 0 14px rgba(93, 214, 255, 0.5);
  white-space: nowrap;
  flex-shrink: 0;
}
body.menu-v2 .mm-content[data-mode="storm"] .mm-pack-banner__chip {
  color: var(--mm-violet);
  background: transparent;
  border: 0;
  text-shadow: 0 0 14px rgba(180, 138, 255, 0.5);
}
body.menu-v2 .mm-pack-banner__text {
  font-size: 12px;
  color: var(--mm-text-secondary);
  /* Subtitle is the only flexible child — if the row gets tight, this
     gets the ellipsis treatment first, not the title or the dropdowns. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1 1 auto;
}
body.menu-v2 .mm-pack-back {
  margin-left: auto;
  font-family: var(--mm-font-display);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(20, 28, 60, 0.6);
  border: 1px solid var(--mm-border-faint);
  color: var(--mm-text-secondary);
  cursor: pointer;
}
body.menu-v2 .mm-pack-back:hover { color: var(--mm-cyan); border-color: var(--mm-border-cyan); }

/* Phase H round 11/30: pack-options container holds:
     - City dropdown (always visible in pack-select — mission + storm)
     - Speed dropdown (storm-only — wrapped in .mm-pack-banner__storm-only)
   Subtitle has flex:1 1 auto so it absorbs the spare row space, naturally
   pushing options + back to the right edge. */
body.menu-v2 .mm-pack-banner__options {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
/* Storm-only wrapper around the speed dropdown — hidden in mission mode
   since mission uses its own per-level difficulty progression. */
body.menu-v2 .mm-pack-banner__storm-only { display: none; }
body.menu-v2 .mm-content[data-mode="storm"] .mm-pack-banner__storm-only {
  display: inline-flex;
  align-items: center;
}
/* Phase H round 14: dropdowns now match the BACK button's font (10px /
   0.22em letter-spacing) and footprint exactly. Wrap padding tuned so
   the pill is as tight as BACK, with just enough right padding to host
   the caret without overlap. */
body.menu-v2 .mm-pack-banner__select-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  /* Phase H round 17: tightened so the wrap = BACK's 24px content height.
     select inside is forced to 14px, +4px+4px wrap padding, +2px borders
     ≈ 24px overall. */
  padding: 4px 18px 4px 8px;
  border-radius: 999px;
  background: rgba(20, 28, 60, 0.55);
  border: 1px solid var(--mm-border-violet);
  color: var(--mm-text-primary);
  cursor: pointer;
  transition: border-color var(--mm-t-fast), box-shadow var(--mm-t-fast);
  flex-shrink: 0;
}
body.menu-v2 .mm-pack-banner__select-wrap:hover,
body.menu-v2 .mm-pack-banner__select-wrap:focus-within {
  border-color: var(--mm-violet);
  box-shadow: 0 0 8px rgba(180, 138, 255, 0.4);
}
body.menu-v2 .mm-pack-banner__select-wrap::after {
  /* Custom dropdown caret. */
  content: "▾";
  position: absolute;
  right: 7px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  font-size: 9px;
  color: var(--mm-violet);
}
body.menu-v2 .mm-pack-banner__select-icon {
  font-size: 10px;
  line-height: 1;
}
body.menu-v2 .mm-pack-banner__select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background: transparent;
  border: 0;
  outline: none;
  /* Phase H round 17: match BACK exactly — font, size, tracking, weight,
     and HEIGHT. !important is needed on font-family + font-size + height
     because the browser silently enforces form-control defaults on
     <select> elements regardless of CSS specificity:
       - font-family bumped to a system font without !important.
       - font-size bumped to 16px without !important (was 10px in CSS
         but rendered as 16px — verified via preview_inspect).
       - height defaulted to ~48px regardless of font-size/padding —
         the browser treats <select> as a min-touch-target control.
     Forcing line-height:1 + an explicit height collapses the select to
     the same 24px footprint BACK has. */
  font-family: var(--mm-font-display) !important;
  font-size: 10px !important;
  font-weight: 400;
  letter-spacing: 0.22em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--mm-text-primary);
  cursor: pointer;
  /* The legacy global `select, input[type="text"] { width:100%;
     padding:12px; font-size:1.1rem; }` rule in styles/style.css adds
     100% width and 12px padding to every <select>. Reset all three here. */
  width: auto;
  padding: 0;
  /* Shrink-wrap to content width. */
  min-width: 0;
  /* The browser's user-agent stylesheet applies min-height: 48px to
     <select> as a touch-target minimum, which silently inflated the pill
     to ~48px tall regardless of font-size and padding. Verified via
     preview_inspect — without min-height: 0, computed min-height was
     48px even though our font + padding were tiny. Forcing min-height
     to 0 lets our explicit height take effect; matches BACK's content
     box exactly. */
  min-height: 0 !important;
  height: 14px !important;
  box-sizing: content-box;
}
body.menu-v2 .mm-pack-banner__select option {
  /* Options render via the OS popup, so re-skin them to match the v2
     dark theme as much as the platform allows. */
  background: #14182c;
  color: var(--mm-text-primary);
  font-family: var(--mm-font-body);
  font-size: 12px;
  letter-spacing: normal;
  text-transform: none;
}

/* Phase H round 9: dropped the 2-column quadrant grid in favour of a
   vertical stack — every category takes a full-width row so its tiles
   read as one horizontal sweep. Old `.mm-pack-quadrants` rules kept as
   no-ops via the same flex/stack treatment for any legacy callers. */
body.menu-v2 .mm-pack-stack,
body.menu-v2 .mm-pack-quadrants {
  display: flex;
  flex-direction: column;
  gap: var(--mm-gap-2);
  /* Phase H round 29: removed the 20-72px padding-bottom that was added
     in round 22 to clear the bottom strip. With the dashboard now
     scrolling internally (round 20+), the strip clearance is handled
     by the dashboard's own scroll, not by stack padding. Removing this
     also lets the pack-stack column visually end at the LAST category
     (Elite), so `align-items: stretch` aligns the coach panel's bottom
     to the visible Elite box — not to an invisible padding extension. */
  padding-bottom: 0;
}
body.menu-v2 .mm-pack-cat {
  background: linear-gradient(180deg, rgba(20, 28, 60, 0.78), rgba(10, 14, 38, 0.86));
  border: 1px solid var(--mm-border-cyan);
  border-radius: 12px;
  /* Round 22: shaved per-category vertical padding so 4 categories +
     banner fit comfortably on shorter viewports. */
  padding: 10px 14px;
  margin-bottom: 0;
}
body.menu-v2 .mm-pack-cat--violet { border-color: var(--mm-border-violet); }
body.menu-v2 .mm-pack-cat--gold   { border-color: var(--mm-border-gold); }
body.menu-v2 .mm-pack-cat__head {
  font-family: var(--mm-font-display);
  font-size: 10px;
  letter-spacing: 0.28em;
  color: var(--mm-cyan);
  text-transform: uppercase;
  margin-bottom: 8px;
}
body.menu-v2 .mm-pack-cat--violet .mm-pack-cat__head { color: var(--mm-violet); }
body.menu-v2 .mm-pack-cat--gold   .mm-pack-cat__head { color: var(--mm-gold); }
body.menu-v2 .mm-pack-grid {
  /* Phase H round 9: each category's tiles sit on ONE row. The JS sets
     --mm-pack-cols to the count of packs in that category so the row
     spreads evenly. On narrow viewports we fall back to auto-fit. */
  display: grid;
  grid-template-columns: repeat(var(--mm-pack-cols, 5), 1fr);
  gap: 10px;
}
@media (max-width: 1100px) {
  body.menu-v2 .mm-pack-grid {
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  }
}
body.menu-v2 .mm-pack-tile {
  position: relative;
  cursor: pointer;
  background: linear-gradient(180deg, rgba(28, 22, 64, 0.85), rgba(12, 14, 36, 0.95));
  border: 1px solid var(--mm-border-faint);
  border-radius: 10px;
  padding: 10px 8px;
  min-height: 90px;
  text-align: center;
  font-family: var(--mm-font-body);
  color: var(--mm-text-primary);
  transition: transform var(--mm-t-fast), border-color var(--mm-t-fast), box-shadow var(--mm-t-fast);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px;
}
body.menu-v2 .mm-pack-tile:hover {
  transform: translateY(-2px);
  border-color: var(--mm-cyan);
  box-shadow: 0 0 14px var(--mm-cyan-glow);
}
body.menu-v2 .mm-content[data-mode="storm"] .mm-pack-tile:hover {
  border-color: var(--mm-violet);
  box-shadow: 0 0 14px var(--mm-violet-glow);
}
body.menu-v2 .mm-pack-tile__name {
  font-family: var(--mm-font-display);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}
body.menu-v2 .mm-pack-tile__meta {
  font-size: 9px;
  letter-spacing: 0.18em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
}

/* ─── COACH OF THE DAY PANEL (Phase E) ──────────────────────────────── */

/* Coach panel must stretch to match the mode-card row's height (Phase H). */
body.menu-v2 .mm-coach-panel {
  height: 100%;
  /* Phase H round 5/18: matches the mode-grid min-height so all four
     long boxes share an identical vertical anchor. Floor pulled back
     to 300px so the row fits on 13"-laptop viewports without scrolling. */
  min-height: clamp(300px, 48vh, 560px);
  /* The transmission block sits in the middle; cta-row uses margin-top:
     auto to pin itself to the panel bottom, which keeps the Coach Journal
     button aligned with the 3 mode-card CTAs. Flex direction is already
     set on the .mm-coach-panel rule below — this is just clarification. */
}
body.menu-v2 .mm-coach-panel {
  /* Defaults are overridden by JS via inline custom properties on pick. */
  --mm-coach-rgb:    180, 138, 255;
  --mm-coach-accent: #b48aff;
  --mm-coach-glow:   rgba(180, 138, 255, 0.55);
  --mm-coach-border: rgba(180, 138, 255, 0.45);

  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(14px, 1.6vh, 22px) clamp(12px, 1.2vw, 20px) clamp(12px, 1.4vh, 18px);
  /* Phase H polish: bump panel opacity so the painted coach background
     becomes atmosphere behind the panel, not a competing character. */
  background:
    radial-gradient(ellipse 80% 50% at 50% 12%, rgba(var(--mm-coach-rgb), 0.32), transparent 72%),
    linear-gradient(180deg, rgba(20, 18, 50, 0.88), rgba(12, 14, 36, 0.94));
  border: 1px solid var(--mm-coach-border);
  border-radius: 14px;
  clip-path: polygon(
    var(--mm-cut) 0, calc(100% - var(--mm-cut)) 0, 100% var(--mm-cut),
    100% calc(100% - var(--mm-cut)), calc(100% - var(--mm-cut)) 100%,
    var(--mm-cut) 100%, 0 calc(100% - var(--mm-cut)), 0 var(--mm-cut)
  );
  color: var(--mm-text-primary);
  overflow: hidden;
  transition: border-color var(--mm-t-mid), background var(--mm-t-mid);
}
body.menu-v2 .mm-coach-panel__chip {
  font-family: var(--mm-font-display);
  font-size: 9px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--mm-coach-border);
  color: var(--mm-coach-accent);
  margin-bottom: 12px;
}
body.menu-v2 .mm-coach-panel__svg {
  width: clamp(120px, 14vh, 180px);
  height: clamp(120px, 14vh, 180px);
  display: flex;
  align-items: center;
  justify-content: center;
  filter: drop-shadow(0 0 18px var(--mm-coach-glow));
  margin-bottom: 12px;
}
body.menu-v2 .mm-coach-panel__svg svg {
  width: 100%;
  height: 100%;
  display: block;
}
body.menu-v2 .mm-coach-panel__name {
  font-family: var(--mm-font-display);
  font-size: clamp(15px, 1.4vw, 20px);
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mm-coach-accent);
  text-shadow: 0 0 18px var(--mm-coach-glow);
}
body.menu-v2 .mm-coach-panel__tagline {
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
  margin-top: 4px;
  margin-bottom: 12px;
}
body.menu-v2 .mm-coach-panel__transmission {
  width: 100%;
  background: rgba(0, 0, 0, 0.4);
  border-left: 2px solid var(--mm-coach-accent);
  border-radius: 0 8px 8px 0;
  padding: 10px 12px;
  font-family: var(--mm-font-mono);
  font-size: clamp(10px, 0.85vw, 12px);
  color: var(--mm-text-secondary);
  text-align: left;
  line-height: 1.45;
  /* Phase H round 29: cap the transmission so super-long coach lore
     (e.g. Pink Nova's "2,190,000 times" essay) doesn't make the coach
     panel taller than the pack-stack — that pushed the panel's CTA row
     below the Elite box and broke the bottom-alignment between the
     two columns. Overflow scrolls inside the transmission block. */
  max-height: clamp(140px, 24vh, 260px);
  overflow-y: auto;
}
body.menu-v2 .mm-coach-panel__transmission-eyebrow {
  display: block;
  font-family: var(--mm-font-display);
  font-size: 8px;
  letter-spacing: 0.32em;
  color: var(--mm-coach-accent);
  text-transform: uppercase;
  margin-bottom: 4px;
  opacity: 0.9;
}
body.menu-v2 .mm-coach-panel__transmission-body { display: block; }
body.menu-v2 .mm-coach-panel__cta-row {
  display: flex;
  gap: 6px;
  /* Phase H round 5: push the CTA row to the BOTTOM of the panel so the
     Coach Journal button aligns horizontally with the 3 mode-card CTAs.
     padding-top adds ~5% of viewport height as breathing room between
     the "Transmission incoming" block and the CTA row. */
  margin-top: auto;
  padding-top: clamp(18px, 5vh, 40px);
  width: 100%;
}
body.menu-v2 .mm-coach-panel__cta {
  flex: 1;
  padding: 8px 10px;
  font-family: var(--mm-font-display);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  border-radius: 999px;
  background: rgba(20, 28, 60, 0.65);
  border: 1px solid var(--mm-border-faint);
  color: var(--mm-text-secondary);
  cursor: pointer;
  transition: all var(--mm-t-fast);
}
body.menu-v2 .mm-coach-panel__cta:hover {
  border-color: var(--mm-coach-accent);
  color: var(--mm-coach-accent);
  box-shadow: 0 0 14px var(--mm-coach-glow);
}
body.menu-v2 .mm-coach-panel__cta--primary {
  background: linear-gradient(180deg, rgba(var(--mm-coach-rgb), 0.28), rgba(var(--mm-coach-rgb), 0.1));
  border-color: var(--mm-coach-border);
  color: var(--mm-coach-accent);
  flex: 1 1 auto;          /* primary takes available width */
}
/* Phase H polish: secondary "Pick Another" is a compact icon-only button
   so the visual hierarchy is clearer (primary action vs. utility swap). */
body.menu-v2 .mm-coach-panel__cta--icon {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  padding: 0;
  letter-spacing: 0;
  font-size: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ─── SIDE RAIL ──────────────────────────────────────────────────────
   Three tiles: Numerai Lounge (relocated from legacy menu), Dashboard,
   and Leaderboard. Phase E hides the legacy chip via CSS; Phase H
   adds the Dashboard + Leaderboard tiles to match the mockup. */
body.menu-v2 .mm-side-rail {
  display: flex;
  flex-direction: column;
  gap: var(--mm-gap-2);
}

/* New v2-styled tiles (Phase H polish). The relocated legacy lounge
   button keeps its own rule below. */
body.menu-v2 .mm-side-tile {
  position: relative;
  padding: 14px 14px;
  background: linear-gradient(180deg, rgba(28, 22, 64, 0.78), rgba(12, 14, 36, 0.9));
  border: 1px solid var(--mm-border-faint);
  border-radius: 12px;
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  transition: transform var(--mm-t-fast), filter var(--mm-t-fast), box-shadow var(--mm-t-fast);
  overflow: hidden;
  clip-path: polygon(
    var(--mm-cut-sm) 0, calc(100% - var(--mm-cut-sm)) 0, 100% var(--mm-cut-sm),
    100% calc(100% - var(--mm-cut-sm)), calc(100% - var(--mm-cut-sm)) 100%,
    var(--mm-cut-sm) 100%, 0 calc(100% - var(--mm-cut-sm)), 0 var(--mm-cut-sm)
  );
}
body.menu-v2 .mm-side-tile:hover { transform: translateX(4px); filter: brightness(1.1); }
body.menu-v2 .mm-side-tile--dashboard { border-color: var(--mm-border-cyan); }
body.menu-v2 .mm-side-tile--scores    { border-color: var(--mm-border-gold); }
body.menu-v2 .mm-side-tile--lounge    { border-color: var(--mm-border-violet); }
/* Lounge tile is also the relocated legacy button — wipe out the inherited
   button styling so it looks identical to Dashboard / Leaderboard. */
body.menu-v2 .mm-side-tile.mm-side-tile--lounge {
  background: linear-gradient(180deg, rgba(28, 22, 64, 0.78), rgba(12, 14, 36, 0.9));
  color: var(--mm-text-primary);
  text-align: left;
  font-family: var(--mm-font-body);
  font-size: inherit;
}
body.menu-v2 .mm-side-tile__icon {
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--mm-border-faint);
  flex-shrink: 0;
}
body.menu-v2 .mm-side-tile__icon--cyan   { border-color: var(--mm-border-cyan); }
body.menu-v2 .mm-side-tile__icon--gold   { border-color: var(--mm-border-gold); }
body.menu-v2 .mm-side-tile__icon--violet { border-color: var(--mm-border-violet); }
body.menu-v2 .mm-side-tile__body { flex: 1; min-width: 0; text-align: left; }
body.menu-v2 .mm-side-tile__title {
  font-family: var(--mm-font-display);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mm-text-primary);
}
body.menu-v2 .mm-side-tile__sub {
  font-size: 10px;
  color: var(--mm-text-muted);
  margin-top: 2px;
}
body.menu-v2 .mm-side-tile__pip {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
body.menu-v2 .mm-side-tile__pip--cyan   { background: var(--mm-cyan);   box-shadow: 0 0 8px var(--mm-cyan); }
body.menu-v2 .mm-side-tile__pip--gold   { background: var(--mm-gold);   box-shadow: 0 0 8px var(--mm-gold); }
body.menu-v2 .mm-side-tile__pip--violet { background: var(--mm-violet); box-shadow: 0 0 8px var(--mm-violet); }

/* "· Year 2"-style meta tag inside the player chip */
body.menu-v2 .mm-top-bar__player-meta {
  color: var(--mm-text-muted);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.04em;
  margin-left: 2px;
}

/* Top-bar gear icon (settings) */
body.menu-v2 .mm-top-bar__icon-btn {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--mm-border-faint);
  background: rgba(20, 28, 60, 0.55);
  color: var(--mm-text-secondary);
  border-radius: 8px;
  font-size: 15px;
  cursor: pointer;
  transition: border-color var(--mm-t-fast), color var(--mm-t-fast), box-shadow var(--mm-t-fast);
}
body.menu-v2 .mm-top-bar__icon-btn:hover {
  border-color: var(--mm-cyan);
  color: var(--mm-cyan);
  box-shadow: 0 0 14px var(--mm-cyan-glow);
}

/* Brand mark icon next to the brand text */
body.menu-v2 .mm-top-bar__brand-mark {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
}
/* The legacy lounge button + coach chip are moved here. Re-skin them to
   match the v2 tile look without altering their IDs.
   Phase H follow-up: force ROW layout (icon | body | pip) so the lounge
   tile renders identically to the Dashboard + Leaderboard tiles below it.
   The high-specificity `body.menu-v2 .mm-side-rail > #btn-numerai-lounge`
   selector beats the base `.mm-side-tile` rule, so column-stacking was
   leaking in. */
body.menu-v2 .mm-side-rail > #btn-numerai-lounge {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  padding: 14px 14px;
  background: linear-gradient(180deg, rgba(28, 22, 64, 0.78), rgba(12, 14, 36, 0.9));
  border: 1px solid var(--mm-border-violet);
  border-radius: 12px;
  color: var(--mm-text-primary);
  cursor: pointer;
  width: 100%;
  text-align: left;
  font-family: var(--mm-font-body);
}
body.menu-v2 .mm-side-rail > #btn-numerai-lounge:hover {
  border-color: var(--mm-violet);
  box-shadow: 0 0 14px var(--mm-violet-glow);
}
/* Title needs to stay single-line so it sits beside the icon, not wrap
   underneath it. */
body.menu-v2 .mm-side-rail > #btn-numerai-lounge .mm-side-tile__title {
  white-space: nowrap;
}
body.menu-v2 .mm-side-rail > #coach-of-the-day-chip-host {
  width: 100%;
}

/* ═══════════════════════════════════════════════════════════════════════
   PHASE G — Parent profile dropdown
   ═══════════════════════════════════════════════════════════════════════
   The top-bar player chip becomes a dropdown trigger ONLY when the auth
   snapshot says parent-login with 2+ children. In every other mode
   (guest, student, single-child parent), the chip stays as a static
   label — `data-mm-multi="false"` makes the caret + dropdown markup
   never render at all. */

body.menu-v2 .mm-top-bar__player[data-mm-multi="true"] {
  cursor: pointer;
  position: relative;
  transition: border-color var(--mm-t-fast), box-shadow var(--mm-t-fast);
}
body.menu-v2 .mm-top-bar__player[data-mm-multi="true"]:hover {
  border-color: var(--mm-cyan);
  box-shadow: 0 0 10px var(--mm-cyan-glow);
}
body.menu-v2 .mm-top-bar__player-caret {
  margin-left: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--mm-text-muted);
  font-size: 10px;
  transition: transform var(--mm-t-fast);
}
body.menu-v2 .mm-top-bar__player[aria-expanded="true"] .mm-top-bar__player-caret {
  transform: rotate(180deg);
}

body.menu-v2 .mm-profile-dropdown {
  position: fixed;
  top: 60px;
  right: 20px;
  min-width: 260px;
  padding: 8px;
  background: linear-gradient(180deg, rgba(20, 22, 50, 0.98), rgba(12, 14, 36, 0.98));
  border: 1px solid var(--mm-border-cyan);
  border-radius: 12px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6), 0 0 20px var(--mm-cyan-glow);
  display: none;
  flex-direction: column;
  gap: 2px;
  z-index: 50;
  clip-path: polygon(
    var(--mm-cut-sm) 0, calc(100% - var(--mm-cut-sm)) 0, 100% var(--mm-cut-sm),
    100% calc(100% - var(--mm-cut-sm)), calc(100% - var(--mm-cut-sm)) 100%,
    var(--mm-cut-sm) 100%, 0 calc(100% - var(--mm-cut-sm)), 0 var(--mm-cut-sm)
  );
}
body.menu-v2 .mm-profile-dropdown.is-open { display: flex; }

body.menu-v2 .mm-profile-dropdown__pill {
  font-family: var(--mm-font-display);
  font-size: 8px;
  letter-spacing: 0.28em;
  color: var(--mm-gold);
  padding: 4px 10px;
  background: rgba(255, 216, 107, 0.12);
  border: 1px solid var(--mm-border-gold);
  border-radius: 999px;
  text-align: center;
  text-transform: uppercase;
  margin: 4px 6px 8px;
}
body.menu-v2 .mm-profile-dropdown__group {
  font-family: var(--mm-font-display);
  font-size: 9px;
  letter-spacing: 0.32em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
  padding: 6px 10px 4px;
}
body.menu-v2 .mm-profile-dropdown__item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  background: transparent;
  border: 1px solid transparent;
  font-family: var(--mm-font-body);
  font-size: 13px;
  color: var(--mm-text-primary);
  cursor: pointer;
  text-align: left;
  font-weight: 600;
}
body.menu-v2 .mm-profile-dropdown__item:hover {
  background: rgba(93, 214, 255, 0.08);
  border-color: var(--mm-border-cyan);
}
body.menu-v2 .mm-profile-dropdown__item--active {
  background: rgba(93, 214, 255, 0.12);
  border-color: var(--mm-border-cyan);
}
body.menu-v2 .mm-profile-dropdown__item--active::after {
  content: "●";
  margin-left: auto;
  color: var(--mm-cyan);
  font-size: 10px;
}
body.menu-v2 .mm-profile-dropdown__avatar {
  /* Phase H round 7: the avatar now renders the emoji icon the parent
     picked when creating the nickname (🐨, 🚀, 🦋, etc.). Sized + framed
     so the emoji reads cleanly against the violet ring without colliding
     with the surrounding row. */
  width: 28px; height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  line-height: 1;
  background: radial-gradient(circle, rgba(180, 138, 255, 0.28), rgba(28, 22, 64, 0.55));
  border: 1px solid var(--mm-border-violet);
  flex-shrink: 0;
}
body.menu-v2 .mm-profile-dropdown__name { flex: 1; min-width: 0; }
body.menu-v2 .mm-profile-dropdown__divider {
  height: 1px;
  background: var(--mm-border-faint);
  margin: 6px 4px;
}
body.menu-v2 .mm-profile-dropdown__item--ghost {
  color: var(--mm-text-secondary);
  font-weight: 500;
}
body.menu-v2 .mm-profile-dropdown__item--signout {
  color: var(--mm-rose);
}

/* ═══════════════════════════════════════════════════════════════════════
   PHASE F — Ultimate locked modal
   ═══════════════════════════════════════════════════════════════════════
   When the player taps a locked Ultimate card, a richer modal shows the
   unlock criterion, current progress, and qualified packs. Replaces the
   legacy `showCityUnlockModal` alert. Closing returns to the welcome view
   without launching anything; "Play Meteor Storm" routes into the v2
   pack-select-storm flow so the player can immediately go work on a pack.
   ═══════════════════════════════════════════════════════════════════════ */

body.menu-v2 .mm-ult-veil {
  position: fixed;
  inset: 0;
  background: rgba(6, 8, 26, 0.78);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  z-index: 80;
  animation: mm-ult-veil-in 0.18s var(--mm-ease) both;
}
@keyframes mm-ult-veil-in { from { opacity: 0; } to { opacity: 1; } }

body.menu-v2 .mm-ult-modal {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(600px, 92vw);
  max-height: 84vh;
  overflow-y: auto;
  z-index: 81;
  padding: 28px 28px 22px;
  background:
    radial-gradient(ellipse 70% 40% at 50% 0%, rgba(255, 216, 107, 0.18), transparent 70%),
    linear-gradient(180deg, rgba(48, 30, 80, 0.96), rgba(20, 12, 40, 0.98));
  border: 1px solid var(--mm-border-gold);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.75),
    0 0 36px var(--mm-gold-glow);
  color: var(--mm-text-primary);
  font-family: var(--mm-font-body);
  clip-path: polygon(
    var(--mm-cut) 0, calc(100% - var(--mm-cut)) 0, 100% var(--mm-cut),
    100% calc(100% - var(--mm-cut)), calc(100% - var(--mm-cut)) 100%,
    var(--mm-cut) 100%, 0 calc(100% - var(--mm-cut)), 0 var(--mm-cut)
  );
  animation: mm-ult-shake-in 0.55s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}
@keyframes mm-ult-shake-in {
  0%   { transform: translate(-50%, -50%); opacity: 0; }
  10%  { opacity: 1; }
  20%  { transform: translate(calc(-50% - 6px), -50%); }
  40%  { transform: translate(calc(-50% + 6px), -50%); }
  60%  { transform: translate(calc(-50% - 3px), -50%); }
  80%  { transform: translate(calc(-50% + 3px), -50%); }
  100% { transform: translate(-50%, -50%); }
}

body.menu-v2 .mm-ult-modal__close {
  position: absolute;
  top: 18px; right: 18px;
  width: 28px; height: 28px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--mm-border-faint);
  color: var(--mm-text-secondary);
  font-size: 14px;
  cursor: pointer;
}
body.menu-v2 .mm-ult-modal__close:hover {
  color: var(--mm-gold);
  border-color: var(--mm-gold);
}

body.menu-v2 .mm-ult-modal__head {
  text-align: center;
  margin-bottom: 18px;
}
body.menu-v2 .mm-ult-modal__title {
  font-family: var(--mm-font-display);
  font-size: 22px;
  font-weight: 900;
  letter-spacing: 0.16em;
  color: var(--mm-gold);
  text-transform: uppercase;
  text-shadow: 0 0 18px var(--mm-gold-glow);
}
body.menu-v2 .mm-ult-modal__subtitle {
  font-size: 12px;
  color: var(--mm-text-muted);
  letter-spacing: 0.08em;
  margin-top: 6px;
}

body.menu-v2 .mm-ult-modal__criterion {
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--mm-border-gold);
  border-radius: 14px;
  padding: 14px 16px;
  text-align: center;
  margin: 14px 0 18px;
}
body.menu-v2 .mm-ult-modal__criterion-label {
  font-family: var(--mm-font-display);
  font-size: 10px;
  letter-spacing: 0.32em;
  color: var(--mm-gold);
  text-transform: uppercase;
}
body.menu-v2 .mm-ult-modal__criterion-body {
  font-size: 14px;
  color: var(--mm-text-primary);
  margin-top: 6px;
  line-height: 1.4;
}
body.menu-v2 .mm-ult-modal__criterion-body strong {
  color: var(--mm-gold);
}

body.menu-v2 .mm-ult-modal__progress { margin: 18px 0; }
body.menu-v2 .mm-ult-modal__progress-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
}
body.menu-v2 .mm-ult-modal__progress-label {
  font-family: var(--mm-font-display);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mm-text-muted);
}
body.menu-v2 .mm-ult-modal__progress-count {
  font-family: var(--mm-font-display);
  font-size: 16px;
  font-weight: 900;
  color: var(--mm-gold);
}
body.menu-v2 .mm-ult-modal__progress-bar {
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
  position: relative;
}
body.menu-v2 .mm-ult-modal__progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--mm-gold), #ff9e3d);
  border-radius: 999px;
  box-shadow: 0 0 10px var(--mm-gold-glow);
  transition: width var(--mm-t-slow) var(--mm-ease);
}

body.menu-v2 .mm-ult-modal__list {
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--mm-border-faint);
  border-radius: 12px;
  padding: 12px 14px;
  margin-top: 14px;
}
body.menu-v2 .mm-ult-modal__list-head {
  font-family: var(--mm-font-display);
  font-size: 11px;
  letter-spacing: 0.22em;
  color: var(--mm-text-muted);
  text-transform: uppercase;
  margin-bottom: 8px;
}
body.menu-v2 .mm-ult-row {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 6px 0;
  border-bottom: 1px dashed var(--mm-border-faint);
  font-size: 13px;
}
body.menu-v2 .mm-ult-row:last-child { border-bottom: none; }
body.menu-v2 .mm-ult-row__check { color: var(--mm-green-good); font-weight: 800; }
body.menu-v2 .mm-ult-row__name  { color: var(--mm-text-primary); }
body.menu-v2 .mm-ult-row__score {
  font-family: var(--mm-font-display);
  font-weight: 800;
  color: var(--mm-gold);
  font-size: 14px;
}
body.menu-v2 .mm-ult-empty {
  margin: 4px 0;
  color: var(--mm-text-muted);
  font-size: 13px;
  text-align: center;
}

body.menu-v2 .mm-ult-modal__ctas {
  display: flex;
  gap: var(--mm-gap-2);
  justify-content: center;
  margin-top: 18px;
}
body.menu-v2 .mm-ult-modal__cta {
  font-family: var(--mm-font-display);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 800;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid var(--mm-border-faint);
  background: transparent;
  color: var(--mm-text-secondary);
  cursor: pointer;
  transition: all var(--mm-t-fast);
}
body.menu-v2 .mm-ult-modal__cta:hover {
  border-color: var(--mm-violet);
  color: var(--mm-violet);
}
body.menu-v2 .mm-ult-modal__cta--primary {
  border-color: var(--mm-border-gold);
  background: linear-gradient(180deg, rgba(255, 216, 107, 0.22), rgba(255, 158, 61, 0.1));
  color: var(--mm-gold);
}
body.menu-v2 .mm-ult-modal__cta--primary:hover {
  background: linear-gradient(180deg, var(--mm-gold), #ff9e3d);
  color: #1a1438;
  box-shadow: 0 0 18px var(--mm-gold-glow);
}

/* ═══════════════════════════════════════════════════════════════════════
   PHASE H round 23 — HALL OF METEORS (v2 Leaderboard modal)
   ═══════════════════════════════════════════════════════════════════════
   Triggered by the Leaderboard side tile click. Replaces the legacy
   scores-panel for the v2 menu — same data source (meteor_scores
   localStorage), redesigned for kid-friendly readability:
     - Medal emoji 🥇🥈🥉 for top 3.
     - Active student row glows gold + "YOU" badge.
     - One mini-board per pack, grouped by category.
     - Empty slots render so the player sees the goal (5 open ranks).
   ═══════════════════════════════════════════════════════════════════════ */
body.menu-v2 .mm-lb-veil {
  position: fixed;
  inset: 0;
  background: rgba(6, 8, 26, 0.78);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  z-index: 80;
  animation: mm-lb-veil-in 0.18s var(--mm-ease) both;
}
@keyframes mm-lb-veil-in { from { opacity: 0; } to { opacity: 1; } }

body.menu-v2 .mm-lb-modal {
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(960px, 94vw);
  max-height: 86vh;
  overflow-y: auto;
  z-index: 81;
  padding: clamp(20px, 3.2vh, 32px) clamp(20px, 3vw, 36px);
  background:
    radial-gradient(ellipse 70% 50% at 50% 0%, rgba(255, 216, 107, 0.18), transparent 70%),
    linear-gradient(180deg, rgba(28, 22, 64, 0.96), rgba(10, 12, 32, 0.98));
  border: 1px solid var(--mm-border-gold);
  border-radius: 18px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.6), 0 0 24px var(--mm-gold-glow);
  color: var(--mm-text-primary);
  font-family: var(--mm-font-body);
  animation: mm-lb-modal-in 0.22s var(--mm-ease) both;
  clip-path: polygon(
    18px 0, calc(100% - 18px) 0, 100% 18px,
    100% calc(100% - 18px), calc(100% - 18px) 100%,
    18px 100%, 0 calc(100% - 18px), 0 18px
  );
}
@keyframes mm-lb-modal-in {
  from { opacity: 0; transform: translate(-50%, -46%) scale(0.96); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

body.menu-v2 .mm-lb-modal__close {
  position: absolute;
  top: 14px; right: 14px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid var(--mm-border-faint);
  color: var(--mm-text-secondary);
  cursor: pointer;
  font-size: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all var(--mm-t-fast);
}
body.menu-v2 .mm-lb-modal__close:hover {
  color: var(--mm-gold);
  border-color: var(--mm-border-gold);
  box-shadow: 0 0 10px var(--mm-gold-glow);
}

body.menu-v2 .mm-lb-modal__head {
  text-align: center;
  margin-bottom: 18px;
}
body.menu-v2 .mm-lb-modal__eyebrow {
  font-family: var(--mm-font-display);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mm-gold);
  margin-bottom: 4px;
}
body.menu-v2 .mm-lb-modal__title {
  font-family: var(--mm-font-display);
  font-size: clamp(20px, 2.4vw, 28px);
  font-weight: 900;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--mm-gold);
  text-shadow: 0 0 22px var(--mm-gold-glow);
}
body.menu-v2 .mm-lb-modal__subtitle {
  font-size: 12px;
  color: var(--mm-text-secondary);
  margin-top: 4px;
}

/* Scope toggle: Family / Squad / All pill switcher. Each pill shows
   its current member-count badge. Active state uses the gold theme. */
body.menu-v2 .mm-lb-scope {
  display: inline-flex;
  gap: 6px;
  margin-top: 12px;
  padding: 4px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--mm-border-faint);
  border-radius: 999px;
}
body.menu-v2 .mm-lb-scope-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  background: transparent;
  border: 0;
  color: var(--mm-text-secondary);
  font-family: var(--mm-font-display);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  cursor: pointer;
  transition: all var(--mm-t-fast);
}
body.menu-v2 .mm-lb-scope-pill:hover {
  color: var(--mm-text-primary);
}
body.menu-v2 .mm-lb-scope-pill.is-active {
  background: linear-gradient(180deg, rgba(255, 216, 107, 0.32), rgba(255, 158, 61, 0.18));
  color: var(--mm-gold);
  box-shadow: 0 0 12px rgba(255, 216, 107, 0.3);
}
body.menu-v2 .mm-lb-scope-pill__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  font-size: 9px;
  letter-spacing: 0;
  font-weight: 800;
  color: var(--mm-text-secondary);
}
body.menu-v2 .mm-lb-scope-pill.is-active .mm-lb-scope-pill__count {
  background: rgba(255, 216, 107, 0.25);
  color: var(--mm-gold);
}

/* "My Standing" hero strip — only when active student has scores. */
body.menu-v2 .mm-lb-standing {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px;
  margin-bottom: 18px;
  border-radius: 12px;
  background: linear-gradient(90deg,
    rgba(255, 216, 107, 0.18),
    rgba(255, 138, 176, 0.10),
    rgba(255, 216, 107, 0.18));
  border: 1px solid var(--mm-border-gold);
  box-shadow: 0 0 14px rgba(255, 216, 107, 0.18);
}
body.menu-v2 .mm-lb-standing__icon {
  font-size: 28px;
  line-height: 1;
  flex-shrink: 0;
}
body.menu-v2 .mm-lb-standing__body { flex: 1; min-width: 0; }
body.menu-v2 .mm-lb-standing__name {
  font-family: var(--mm-font-display);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mm-gold);
}
body.menu-v2 .mm-lb-standing__detail {
  font-size: 13px;
  color: var(--mm-text-primary);
  margin-top: 2px;
}
body.menu-v2 .mm-lb-standing__detail strong {
  color: var(--mm-gold);
  font-weight: 800;
}
body.menu-v2 .mm-lb-standing--empty {
  background: linear-gradient(90deg,
    rgba(180, 138, 255, 0.14),
    rgba(93, 214, 255, 0.10),
    rgba(180, 138, 255, 0.14));
  border-color: var(--mm-border-violet);
  box-shadow: none;
}
body.menu-v2 .mm-lb-standing--empty .mm-lb-standing__body {
  font-size: 13px;
  color: var(--mm-text-primary);
}

body.menu-v2 .mm-lb-body { display: flex; flex-direction: column; gap: 16px; }

/* Per-category wrapper (Core / Number Sense / Life Skills / Elite). */
body.menu-v2 .mm-lb-cat {
  background: linear-gradient(180deg, rgba(20, 28, 60, 0.55), rgba(10, 14, 36, 0.78));
  border: 1px solid var(--mm-border-cyan);
  border-radius: 12px;
  padding: 12px 14px;
}
body.menu-v2 .mm-lb-cat--violet { border-color: var(--mm-border-violet); }
body.menu-v2 .mm-lb-cat--gold   { border-color: var(--mm-border-gold); }
body.menu-v2 .mm-lb-cat__head {
  font-family: var(--mm-font-display);
  font-size: 10px;
  letter-spacing: 0.28em;
  color: var(--mm-cyan);
  text-transform: uppercase;
  margin-bottom: 10px;
}
body.menu-v2 .mm-lb-cat--violet .mm-lb-cat__head { color: var(--mm-violet); }
body.menu-v2 .mm-lb-cat--gold   .mm-lb-cat__head { color: var(--mm-gold); }

body.menu-v2 .mm-lb-cat__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 10px;
}

/* One mini-board per pack. */
body.menu-v2 .mm-lb-board {
  background: rgba(8, 10, 28, 0.72);
  border: 1px solid var(--mm-border-faint);
  border-radius: 10px;
  padding: 10px 12px;
}
/* Featured board (Ultimate Storm) — gold border + soft glow + spans full
   width of its category row so the Elite category reads as the climax. */
body.menu-v2 .mm-lb-board--featured {
  grid-column: 1 / -1;
  border-color: var(--mm-border-gold);
  background:
    radial-gradient(ellipse 50% 60% at 50% 0%, rgba(255, 216, 107, 0.14), transparent 70%),
    rgba(20, 14, 36, 0.85);
  box-shadow: 0 0 14px rgba(255, 216, 107, 0.22);
}
body.menu-v2 .mm-lb-board--featured .mm-lb-board__name {
  color: var(--mm-gold);
  text-shadow: 0 0 12px var(--mm-gold-glow);
}
body.menu-v2 .mm-lb-board__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--mm-border-faint);
}
body.menu-v2 .mm-lb-board__name {
  font-family: var(--mm-font-display);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mm-text-primary);
  font-weight: 800;
}
body.menu-v2 .mm-lb-board__mybest {
  font-size: 10px;
  color: var(--mm-gold);
  font-family: var(--mm-font-display);
  letter-spacing: 0.08em;
}
/* Header rank + score chip (legacy `.pack-board__selected-meta`) — gold
   rank + green score sitting right next to the pack name. */
body.menu-v2 .mm-lb-board__selected-meta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
body.menu-v2 .mm-lb-board__selected-rank {
  font-family: var(--mm-font-display);
  font-size: 11px;
  font-weight: 800;
  color: #fbbf24;
  text-shadow: 0 0 8px rgba(251, 191, 36, 0.4);
  letter-spacing: 0.05em;
}
body.menu-v2 .mm-lb-board__selected-score {
  font-family: var(--mm-font-display);
  font-size: 11px;
  font-weight: 800;
  color: #86efac;
  text-shadow: 0 0 8px rgba(74, 222, 128, 0.35);
  letter-spacing: 0.04em;
}
/* Click-to-centre affordance: tap an in-board student to see your
   neighbours. Cursor + hover indicate the board is interactive. */
body.menu-v2 .mm-lb-board--has-player {
  cursor: pointer;
  transition: border-color var(--mm-t-fast), box-shadow var(--mm-t-fast);
}
body.menu-v2 .mm-lb-board--has-player:hover,
body.menu-v2 .mm-lb-board--has-player:focus-visible {
  border-color: var(--mm-gold);
  box-shadow: 0 0 12px rgba(255, 216, 107, 0.25);
  outline: none;
}
/* Focused state — visible cue that rows are centered on the active
   student rather than top-5. */
body.menu-v2 .mm-lb-board--focused {
  border-color: var(--mm-gold);
  box-shadow: 0 0 16px rgba(255, 216, 107, 0.35);
}
body.menu-v2 .mm-lb-board__rows {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

/* Individual score row. */
body.menu-v2 .mm-lb-row {
  display: grid;
  grid-template-columns: 26px 1fr auto auto;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: 6px;
  font-size: 12px;
}
body.menu-v2 .mm-lb-row__rank {
  font-size: 14px;
  line-height: 1;
  text-align: center;
}
body.menu-v2 .mm-lb-row__rank-num {
  display: inline-block;
  font-family: var(--mm-font-display);
  font-size: 11px;
  font-weight: 800;
  color: var(--mm-text-muted);
}
body.menu-v2 .mm-lb-row__name {
  font-weight: 600;
  color: var(--mm-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
body.menu-v2 .mm-lb-row__you {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 999px;
  font-family: var(--mm-font-display);
  font-size: 8px;
  letter-spacing: 0.18em;
  font-weight: 800;
  background: var(--mm-gold);
  color: #1a1438;
}
body.menu-v2 .mm-lb-row__date {
  font-size: 10px;
  color: var(--mm-text-muted);
  letter-spacing: 0.04em;
}
body.menu-v2 .mm-lb-row__score {
  font-family: var(--mm-font-display);
  font-size: 12px;
  font-weight: 800;
  color: var(--mm-cyan);
  text-shadow: 0 0 8px rgba(93, 214, 255, 0.4);
}
body.menu-v2 .mm-lb-row--me {
  background: linear-gradient(90deg,
    rgba(255, 216, 107, 0.18),
    rgba(255, 216, 107, 0.10));
  border-left: 2px solid var(--mm-gold);
  box-shadow: 0 0 12px rgba(255, 216, 107, 0.2);
}
body.menu-v2 .mm-lb-row--me .mm-lb-row__name,
body.menu-v2 .mm-lb-row--me .mm-lb-row__score {
  color: var(--mm-gold);
  text-shadow: 0 0 10px var(--mm-gold-glow);
}
body.menu-v2 .mm-lb-row--empty .mm-lb-row__name { color: var(--mm-text-faint); font-style: italic; }
body.menu-v2 .mm-lb-row--empty .mm-lb-row__score { color: var(--mm-text-faint); }

/* Empty state — no scores anywhere. */
body.menu-v2 .mm-lb-empty {
  text-align: center;
  padding: 30px 16px;
  color: var(--mm-text-secondary);
}
body.menu-v2 .mm-lb-empty__icon {
  font-size: 40px;
  margin-bottom: 10px;
  filter: drop-shadow(0 0 16px var(--mm-gold-glow));
}
body.menu-v2 .mm-lb-empty__title {
  font-family: var(--mm-font-display);
  font-size: 16px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mm-gold);
  margin: 0 0 6px;
}
body.menu-v2 .mm-lb-empty__body {
  font-size: 13px;
  margin: 0;
}

/* Bottom CTA row. */
body.menu-v2 .mm-lb-modal__ctas {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 18px;
}
body.menu-v2 .mm-lb-modal__cta {
  font-family: var(--mm-font-display);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--mm-border-faint);
  background: transparent;
  color: var(--mm-text-secondary);
  cursor: pointer;
  transition: all var(--mm-t-fast);
}
body.menu-v2 .mm-lb-modal__cta:hover {
  border-color: var(--mm-violet);
  color: var(--mm-violet);
}
body.menu-v2 .mm-lb-modal__cta--primary {
  border-color: var(--mm-border-gold);
  background: linear-gradient(180deg, rgba(255, 216, 107, 0.22), rgba(255, 158, 61, 0.1));
  color: var(--mm-gold);
}
body.menu-v2 .mm-lb-modal__cta--primary:hover {
  background: linear-gradient(180deg, var(--mm-gold), #ff9e3d);
  color: #1a1438;
  box-shadow: 0 0 18px var(--mm-gold-glow);
}

/* ─── PHASE A SANITY CHECK ─────────────────────────────────────────────
   When this file is loaded but the feature flag is off, body.menu-v2 is
   absent and every rule above is inert. When a future phase sets the
   class, the v2 chrome activates and the legacy hero + ghost toolbar are
   hidden. Center column and side panels remain visible. */
