/* ***************************************************************
 * MireGameKit - portrait first dark shell theme
 * One stylesheet for every game in the arcade: the splash veil, the
 * letterboxed portrait stage, the branded dialog cards, the full mf- ui
 * class inventory, and the generated arcade hub page. Portrait is native;
 * desktop simply centers the portrait column with neutral gutters. There is
 * no landscape concept anywhere in this file.
 * *************************************************************** */

/* ***************************************************************
 * Theme tokens (dom chrome only, per game palettes affect the canvas)
 * *************************************************************** */

:root {
  --mf-bg: #10131c;
  --mf-bg-2: #1c2230;
  --mf-surface: rgba(28, 34, 48, 0.86);
  --mf-surface-flat: rgba(16, 19, 28, 0.4);
  --mf-ink: #eef1f7;
  --mf-ink-dim: rgba(255, 255, 255, 0.55);
  --mf-faint: rgba(255, 255, 255, 0.12);
  --mf-accent: #b8a8d8;
  --mf-accent-soft: rgba(184, 168, 216, 0.14);
  --mf-danger: #f6465d;
  --mf-up: #0ecb81;
  --mf-card-border: rgba(184, 168, 216, 0.18);
  /* The crown / medal / trophy / favorite-star semantic gold. A token so day
     mode can swap in a deeper, more legible gold on the light parchment without
     touching the night value, which stays this exact bright gold. */
  --mf-gold: #ffd75e;
  --mf-brand-ink: #eef1f7;
  --mf-radius: 14px;
  --mf-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
    Arial, sans-serif;
}

/* ***************************************************************
 * Day mode token overrides (OPTIONAL warm parchment theme)
 * Selected by data-theme="day" on the <html> root. Absence or any unknown
 * value stays NIGHT (the unconditional dark tokens above). The majority of the
 * chrome reads these var(--mf-*) tokens, so re-pointing them here re-themes most
 * of the dialog cards, buttons, lists and hub to the light parchment palette in
 * one place; the hardcoded values that do NOT follow tokens are overridden in
 * the day-override block further down.
 * *************************************************************** */

:root[data-theme="day"] {
  --mf-bg: #faf9f5;
  --mf-bg-2: #efe9d9;
  --mf-surface: #ffffff;
  --mf-surface-flat: #f1eee7;
  --mf-ink: #2c2a26;
  --mf-ink-dim: #5c5850;
  --mf-faint: #e6e2d9;
  --mf-accent: #880e4f;
  --mf-accent-soft: rgba(136, 14, 79, 0.10);
  --mf-danger: #c62828;
  --mf-up: #4e7d2f;
  --mf-card-border: #e6e2d9;
  /* a deeper, saturated gold so crowns / medals / trophies / stars stay clearly
     legible on the light parchment, where the bright night gold washes out */
  --mf-gold: #e0a400;
}

/* ***************************************************************
 * Reset and base page (no scroll bounce inside the Telegram webview)
 * *************************************************************** */

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100dvh;
  width: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  font-family: var(--mf-font);
  font-size: 16px;
  color: var(--mf-ink);
  background: linear-gradient(160deg, var(--mf-bg) 0%, var(--mf-bg-2) 100%);
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* The single visibility switch used across every ui module */
.mf-hidden {
  display: none !important;
}

/* The outermost mount must carry the full viewport height so the percentage
 * height chain reaches the shell and the canvas; without this the shell
 * collapses to its content and the stage only fills the top of the screen */
#app-root {
  position: relative;
  width: 100%;
  height: 100%;
}

/* The splash veil overlays the whole app while present and never takes layout
 * space once the kit has removed it */
#splash-root {
  position: absolute;
  inset: 0;
  z-index: 50;
}

#splash-root:empty {
  display: none;
  pointer-events: none;
}

/* ***************************************************************
 * Shell - the portrait stage column
 * Fills the viewport on mobile; on desktop the column is capped so it never
 * stretches much past a 9:16 portrait frame and centers with dark gutters.
 * *************************************************************** */

.mf-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100dvh;
  margin: 0 auto;
  overflow: hidden;
  background: linear-gradient(160deg, var(--mf-bg) 0%, var(--mf-bg-2) 100%);
  /* Expose the device safe-area as variables for the UI control layers only.
   * The shell and canvas stay full-bleed to all four edges so the game art
   * reaches the screen edges with no dark bars; only the chrome (pause button,
   * menu, overlays) insets. Putting the inset back here as padding shrank the
   * canvas and let the dark shell background show as bars on any device with a
   * real notch or in Telegram fullscreen, which was the black-edge bug. */
  --mf-safe-top: env(safe-area-inset-top);
  --mf-safe-right: max(0px, env(safe-area-inset-right));
  --mf-safe-bottom: env(safe-area-inset-bottom);
  --mf-safe-left: max(0px, env(safe-area-inset-left));
}

/* The portrait column cap is a DESKTOP-centering device only and is gated by
 * viewport WIDTH, not by pointer type. A pointer:coarse gate was unreliable
 * inside the Telegram WebView, so the cap stayed live on phones and squeezed
 * every game into a narrow column with side gutters - the standard width gap the
 * owner saw in all games. A phone viewport is always far under 700px, so it now
 * always fills the full width with no gutters; only a genuinely wide desktop or
 * tablet viewport centers the portrait column with neutral side gutters. */
@media (min-width: 700px) {
  .mf-shell {
    max-width: calc(100vh * 0.5625);
  }
}

/* The stage canvas the engine draws into, never zoomable or scrollable */
.mf-canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}

/* The game shell box the canvas and overlays stack inside */
#game-shell {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
  overflow: hidden;
}

/* Menu and overlay mount points cover the stage */
#menu-root,
#overlay-root {
  position: absolute;
  inset: 0;
  z-index: 10;
}

#overlay-root {
  z-index: 30;
  pointer-events: none;
}

/* Overlay children take pointer events back when present */
#overlay-root > * {
  pointer-events: auto;
}

/* Empty mount points must not block the canvas */
#menu-root:empty,
#overlay-root:empty {
  pointer-events: none;
}

/* The menu root centers its single visible panel over the stage, kept clear of
 * the device notch and the Telegram fullscreen header by the safe-area insets */
#menu-root {
  display: flex;
  padding: calc(16px + var(--mf-safe-top, 0px))
    calc(16px + var(--mf-safe-right, 0px))
    calc(16px + var(--mf-safe-bottom, 0px))
    calc(16px + var(--mf-safe-left, 0px));
}

/* ***************************************************************
 * Short screen flag (set by the app host from measured pixels)
 * *************************************************************** */

body.mf-short .mf-card {
  padding: 14px 16px;
  gap: 9px;
}

body.mf-short .mf-title {
  font-size: 19px;
}

body.mf-short .mf-subtitle {
  font-size: 12px;
}

body.mf-short .mf-mascot {
  width: 90px;
}

body.mf-short .mf-brand-strip {
  height: 11px;
}

/* ***************************************************************
 * Splash + loading veil (the brand entry, doubles as the load veil)
 * *************************************************************** */

.mf-splash {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  /* A neutral dark veil, never the per game palette and never the day theme: the
     brand lockup uses the dark-background variant, so the splash stays dark in day
     mode too. Hardcoded (not the themed --mf-bg, which day flips to a light cream)
     so the brand mark never washes out on a light splash. */
  background: linear-gradient(160deg, #10131c 0%, #1c2230 100%);
  opacity: 1;
}

/* The centered icon over wordmark stack, the only content on the splash */
.mf-splash-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 24px;
}

/* The brand icon breathes gently while the game loads behind the veil */
.mf-splash-logo img:first-child {
  width: 84px;
  height: 84px;
  animation: mf-pulse 2.2s ease-in-out infinite;
}

/* The wordmark keeps its wide ratio, sized by height */
.mf-splash-logo img:last-child {
  height: 22px;
  width: auto;
  opacity: 0.9;
}

/* The two-tone splash wordmark rendered as text rather than an image, so the
 * Mire bordeaux and Games grey read true. The .mf-brand-mire and
 * .mf-brand-games spans inside it carry the colors (those rules already exist),
 * this rule just sets the bold size and slight tracking of the lockup */
.mf-splash-word {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 800;
  font-size: 28px;
  letter-spacing: 0.4px;
  line-height: 1;
}

/* The single fade out, kept under the spec cap of four tenths of a second */
.mf-splash-fade {
  opacity: 0;
  transition: opacity 380ms ease;
}

/* Soft scale and opacity pulse for the brand icon */
@keyframes mf-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.7;
  }
  50% {
    transform: scale(1.08);
    opacity: 1;
  }
}

/* ***************************************************************
 * Brand strip + cta (the quiet repetition on resting surfaces)
 * *************************************************************** */

/* The brand lockup strip pinned at the top of every dialog card: the icon and
 * the Mire wordmark side by side, centered and quiet, never the bare word */
.mf-brand-strip {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 14px;
  margin-bottom: 2px;
  opacity: 0.92;
}

/* The brand icon, a square mark that scales with the strip height */
.mf-brand-icon {
  height: 100%;
  aspect-ratio: 1 / 1;
  background: url("assets/brand/trademire-icon-dark.svg") center / contain
    no-repeat;
}

/* The Mire Games wordmark, two-tone text so the brand colors read true: a flat
 * single-color svg could not show Mire in bordeaux and Games in grey */
.mf-brand-text {
  height: 100%;
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.2px;
  line-height: 1;
}

/* The wordmark reuses the logo icon's exactly two colors so the mark and the
 * text read as one lockup: Mire takes the accent-circle burgundy, Games takes
 * the figure grey. Both hex values are lifted straight from the icon svg. */
.mf-brand-mire {
  color: #d96f8a;
}
.mf-brand-games {
  color: #b8b0c2;
}

/* When the strip carries an explicit img instead of a background */
.mf-brand-strip-img {
  height: 13px;
  width: auto;
  opacity: 0.55;
}

/* The single game over call to action row, quiet by design */
.mf-brand-cta {
  margin-top: 4px;
  text-align: center;
  font-size: 12px;
  color: var(--mf-ink-dim);
}

.mf-brand-cta a {
  color: var(--mf-accent);
  text-decoration: none;
}

.mf-brand-cta a:hover {
  text-decoration: underline;
}

/* ***************************************************************
 * Cards and typography
 * *************************************************************** */

.mf-card {
  position: relative;
  margin: auto;
  width: min(420px, 100%);
  max-height: 100%;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
  background: var(--mf-surface);
  border: 1px solid var(--mf-card-border);
  border-radius: var(--mf-radius);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(8px);
}

/* The flexible middle slot inside a card stacks its content vertically */
.mf-card-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.mf-title {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--mf-ink);
  text-align: center;
}

/* Secondary line under the title. Readability is lifted a touch with a larger
 * size and a clearer ink that still reads as secondary, not as a heading */
.mf-subtitle {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(238, 241, 247, 0.85);
  text-align: center;
}

/* ***************************************************************
 * Buttons (touch targets stay at or above forty eight pixels)
 * *************************************************************** */

.mf-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 12px 16px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  color: var(--mf-ink);
  background: rgba(184, 168, 216, 0.1);
  border: 1px solid var(--mf-card-border);
  border-radius: 11px;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.05s ease;
}

.mf-btn:hover {
  background: rgba(184, 168, 216, 0.18);
}

.mf-btn:active {
  transform: scale(0.98);
}

.mf-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Primary call to action carries the accent emphasis. A subtle vertical
 * gradient gives the fill depth and a soft purple glow lifts it off the card,
 * without changing the layout or size of the button */
.mf-btn-primary {
  color: var(--mf-bg);
  background: linear-gradient(180deg, #c8bbe4 0%, var(--mf-accent) 100%);
  border-color: transparent;
  box-shadow: 0 8px 22px rgba(184, 168, 216, 0.4),
    0 0 18px rgba(184, 168, 216, 0.28);
}

.mf-btn-primary:hover {
  background: linear-gradient(180deg, #d4c9ec 0%, #c8bbe4 100%);
}

/* Watch-ad continue button: the single standard rewarded-ad action across every
 * game (on-death revive, the-claw +seconds, the game-over double-coins). A gold
 * fill plus an "AD" marker pill so players always read it as "free continue by
 * watching an ad". One definition here drives all games. */
.mf-btn-ad {
  color: #2a2300;
  background: linear-gradient(180deg, #ffe08a 0%, #f5b800 100%);
  border-color: transparent;
  font-weight: 800;
  box-shadow: 0 8px 22px rgba(245, 184, 0, 0.4),
    0 0 18px rgba(255, 215, 94, 0.3);
}

.mf-btn-ad:hover {
  background: linear-gradient(180deg, #ffe9a8 0%, #ffce3a 100%);
}

/* the classic film-strip marker prefixed inside the button; a pseudo-element with
 * an inline-SVG film strip (dark frame, gold sprocket holes) so it reads as a
 * rewarded VIDEO ad and survives the overlay re-setting the button's textContent */
.mf-btn-ad::before {
  content: '';
  display: inline-block;
  width: 1.7em;
  height: 1.7em;
  margin-right: 8px;
  vertical-align: middle;
  background: center / contain no-repeat
    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.5' y='3' width='19' height='18' rx='3' fill='%232a2300'/><g fill='%23ffd75e'><rect x='4' y='5.2' width='1.7' height='1.7' rx='.4'/><rect x='4' y='9' width='1.7' height='1.7' rx='.4'/><rect x='4' y='12.8' width='1.7' height='1.7' rx='.4'/><rect x='4' y='16.6' width='1.7' height='1.7' rx='.4'/><rect x='18.3' y='5.2' width='1.7' height='1.7' rx='.4'/><rect x='18.3' y='9' width='1.7' height='1.7' rx='.4'/><rect x='18.3' y='12.8' width='1.7' height='1.7' rx='.4'/><rect x='18.3' y='16.6' width='1.7' height='1.7' rx='.4'/><path d='M10 8.5 L10 15.5 L15.5 12 Z'/></g></svg>");
}

/* Mock rewarded ad button, a gold offer that stands apart from the actions */
.mf-btn-ad {
  color: #2a1d10;
  background: linear-gradient(180deg, #ffd75e, #f0b429);
  border-color: transparent;
  font-weight: 700;
  box-shadow: 0 8px 22px rgba(240, 180, 41, 0.32);
}

.mf-btn-ad:hover {
  filter: brightness(1.06);
}

/* Row holding the single mock ad offer above the action buttons */
.mf-ad-row {
  display: flex;
  margin-top: 10px;
}

.mf-ad-row > .mf-btn {
  flex: 1 1 0;
}

/* ***************************************************************
 * Browser layout edit mode (only present with the ?edit flag)
 * *************************************************************** */

/* The full viewport overlay; it ignores pointer events so the game shows
   through, only its handles and panels are interactive */
.mf-edit-root {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  touch-action: none;
}

/* A draggable anchor handle: a large transparent hit area around a small dot */
.mf-edit-handle {
  position: fixed;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
  cursor: move;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* The visible dot marking the exact anchor point */
.mf-edit-dot {
  border-radius: 50%;
  background: var(--mf-accent);
  border: 2px solid #ffffff;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.5);
}

/* The active anchor glows gold so the selection is obvious */
.mf-edit-handle-active .mf-edit-dot {
  background: #ffd75e;
  transform: scale(1.2);
}

/* The small caption naming each anchor under its dot */
.mf-edit-caption {
  position: absolute;
  top: 100%;
  margin-top: 2px;
  padding: 1px 6px;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: rgba(8, 6, 14, 0.85);
  border-radius: 6px;
  white-space: nowrap;
  pointer-events: none;
}

/* The dashed box drawn around the selected anchor */
.mf-edit-selbox {
  position: fixed;
  border: 1px dashed var(--mf-accent);
  border-radius: 6px;
  pointer-events: none;
  z-index: 59;
}

/* The floating inspector with the live editable numbers and the toolbar */
.mf-edit-inspector {
  position: fixed;
  left: 12px;
  bottom: 12px;
  z-index: 61;
  pointer-events: auto;
  min-width: 180px;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgba(16, 19, 28, 0.92);
  border: 1px solid var(--mf-faint);
  color: var(--mf-ink);
  font-size: 13px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}

.mf-edit-inspector-title {
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--mf-accent);
}

.mf-edit-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 4px 0;
}

.mf-edit-field input {
  width: 80px;
  padding: 4px 6px;
  border-radius: 6px;
  border: 1px solid var(--mf-faint);
  background: rgba(0, 0, 0, 0.35);
  color: var(--mf-ink);
  font: inherit;
}

.mf-edit-toolbar {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}

.mf-edit-tool {
  min-height: 34px;
  padding: 6px 10px;
  font-size: 13px;
}

/* The save confirm dialog json box */
.mf-edit-json {
  width: 100%;
  height: 140px;
  margin: 8px 0;
  font-family: "Courier New", ui-monospace, monospace;
  font-size: 12px;
  color: var(--mf-ink);
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--mf-faint);
  border-radius: 8px;
  resize: none;
}

.mf-edit-confirm {
  z-index: 70;
  /* the editor root is pointer-events:none so the live scene shows through; the
     confirm dialog must re-enable clicks or its Save/Close buttons are dead */
  pointer-events: auto;
}

/* Row of buttons sharing one line, each grows to fill its share */
.mf-btn-row {
  display: flex;
  gap: 10px;
}

.mf-btn-row:empty {
  display: none;
}

.mf-btn-row > .mf-btn {
  flex: 1 1 0;
}

/* Game-over actions can run to four buttons (watch-ad / play again / share /
 * exit). Let the row wrap and give the wide gold watch-ad button its own full
 * line so the long "watch ad: 2x coins" label never wraps to three lines and
 * crushes its neighbours. Scoped to the game-over card so the revive overlay's
 * own .mf-btn-ad (a two-button row) is untouched. */
.mf-gameover-actions {
  flex-wrap: wrap;
}

.mf-gameover-actions > .mf-btn-ad {
  flex: 1 1 100%;
}

/* Compact per-level reward screen: stack the two buttons full-width with a small
 * gap so the gold Nx coin grab leads and the continue button sits right under it. */
.mf-gameover-compact {
  gap: 10px;
}

.mf-gameover-compact > .mf-btn {
  flex: 1 1 100%;
}

/* Quiet text button for secondary navigation links. It lays out an optional
 * leading icon and a label on one centered row, the icon sitting just left of
 * the text with a small gap */
.mf-link-btn {
  flex: 1 1 calc(50% - 4px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 48px;
  padding: 11px 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--mf-accent);
  background: rgba(184, 168, 216, 0.07);
  border: 1px solid var(--mf-card-border);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.mf-link-btn:hover {
  background: rgba(184, 168, 216, 0.15);
}

/* A slightly more prominent secondary button for the two feature links
 * (Leaderboard and All Games). It keeps the quiet link footprint but reads
 * one step louder with an accent-tinted fill and a clearer accent border */
.mf-link-btn-feature {
  color: var(--mf-ink);
  background: rgba(184, 168, 216, 0.14);
  border-color: rgba(184, 168, 216, 0.4);
}

.mf-link-btn-feature:hover {
  background: rgba(184, 168, 216, 0.22);
}

/* A coming-soon link: the feature is not live yet, so the entry stays visible
 * but reads as inert. It dims, drops any hover lift and shows a not-allowed
 * cursor so a tap obviously does nothing. Listed for hover too so it overrides
 * the feature link's brighter hover when a shop link is both feature and soon */
.mf-link-btn-soon,
.mf-link-btn-soon:hover {
  opacity: 0.45;
  cursor: not-allowed;
  background: rgba(184, 168, 216, 0.08);
  border-color: rgba(184, 168, 216, 0.18);
}

/* Row that wraps the panel link buttons and the mute toggle */
.mf-links-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* The more games cross promotion button, an anchor styled as a link button.
 * It resets the anchor underline and centers its label like the other link
 * buttons so it sits cleanly among them and on the game over card */
.mf-more-btn {
  text-decoration: none;
  color: var(--mf-accent);
}

.mf-more-btn:hover {
  text-decoration: none;
}

/* The standalone more games row under the game over actions, one centered
 * link button that fills the card width like the action buttons above it */
.mf-more-row {
  display: flex;
}

.mf-more-row > .mf-more-btn {
  flex: 1 1 auto;
}

/* ***************************************************************
 * Toggle group (difficulty and mode pickers)
 * *************************************************************** */

.mf-toggle-group {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: rgba(16, 19, 28, 0.5);
  border: 1px solid var(--mf-faint);
  border-radius: 11px;
}

.mf-toggle {
  flex: 1 1 0;
  min-height: 40px;
  padding: 9px 4px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--mf-ink-dim);
  background: transparent;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.mf-toggle:hover {
  color: var(--mf-ink);
}

/* Selected segment stands out in the accent */
.mf-toggle-active {
  color: var(--mf-bg);
  background: var(--mf-accent);
}

.mf-toggle-active:hover {
  color: var(--mf-bg);
}

/* The small inline icon (a globe, target, trophy, and so on) sitting left of a
 * link button label. It is sized to about a quarter of a square and inherits
 * the button color through currentColor so it always matches its label */
.mf-link-icon {
  flex: 0 0 auto;
  display: block;
  width: 16px;
  height: 16px;
  color: currentColor;
}

/* A compact icon-only button used for wordless menu controls like the mute
 * toggle; the svg inside inherits the button color through currentColor */
.mf-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  color: var(--mf-ink-dim);
  background: rgba(184, 168, 216, 0.07);
  border: 1px solid var(--mf-card-border);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.mf-icon-btn:hover {
  color: var(--mf-ink);
  background: rgba(184, 168, 216, 0.15);
}

/* The mute toggle pinned to the top-right corner of the main menu card */
.mf-mute-btn {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
}

/* The how-to shortcut pinned to the top-left corner of the paused card */
.mf-howto-btn {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
}

/* The back-to-hub control pinned to the top-left corner of the main menu card,
 * mirroring the mute on the right so a thumb never lands on both at once. It
 * gives every platform a visible way back to the arcade even where there is no
 * native back chrome (the Android and iOS wrappers). */
.mf-back-btn {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
}

/* A larger icon button for the pause menu controls, brighter than the subtle
 * menu toggles since these are the main interaction on the paused card */
.mf-icon-btn-lg {
  width: 64px;
  height: 64px;
  border-radius: 14px;
  color: var(--mf-ink);
}

/* The safe primary control (resume) carries the accent fill so it stands out */
.mf-icon-btn-primary {
  color: var(--mf-bg);
  background: var(--mf-accent);
  border-color: var(--mf-accent);
}

.mf-icon-btn-primary:hover {
  color: var(--mf-bg);
  background: var(--mf-accent);
}

/* The centered row of icon controls on the paused card. It grows to fill the
 * button row so justify-content can truly center the icons rather than letting
 * the shrink-to-content row hug the left edge */
.mf-pause-actions {
  display: flex;
  flex: 1 1 auto;
  justify-content: center;
  gap: 18px;
  flex-wrap: wrap;
}

/* The inline how-to text revealed by the corner icon on the paused card */
.mf-pause-howto {
  text-align: left;
}

.mf-pause-howto p {
  margin: 7px 0;
}

/* Size every pause icon uniformly regardless of its own svg attributes */
.mf-pause-actions svg {
  width: 30px;
  height: 30px;
}

/* The paused card stacks its controls in two tiers, so the action group runs
 * as a column: resume on its own row above the quieter restart and menu row */
.mf-pause-actions {
  flex-direction: column;
  gap: 12px;
}

/* One tier of the paused controls. The primary tier holds resume alone and the
 * secondary tier splits the two destructive choices evenly across the width */
.mf-pause-row {
  display: flex;
  gap: 12px;
}

.mf-pause-row-secondary {
  justify-content: center;
}

/* Each action button stacks its glyph over a short caption, so a bare arrow or
 * home glyph always reads with a plain word under it. It grows to share its row
 * with any siblings and keeps a comfortable thumb-sized minimum height */
.mf-icon-btn-action {
  flex: 1 1 0;
  flex-direction: column;
  gap: 6px;
  width: auto;
  min-height: 72px;
  padding: 12px 8px;
  border-radius: 14px;
  color: var(--mf-ink);
}

/* The resume tier reads as the loud default, taller than the secondary pair */
.mf-pause-row-primary .mf-icon-btn-action {
  min-height: 84px;
}

/* The glyph slot keeps the icon centered above the caption in the column */
.mf-action-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* The caption under the glyph names the action in plain words */
.mf-action-label {
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
}

/* The inline confirm step shown over the action tiers before a destructive
 * pause action. It is a tight centered column with the prompt above its row */
.mf-pause-confirm {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: stretch;
}

/* The confirm prompt sits a touch bolder than a plain subtitle so the question
 * reads as the focus of this step */
.mf-pause-confirm-title {
  font-weight: 600;
  color: var(--mf-ink);
}

/* Cancel and the bold accept share one row, each filling half its width */
.mf-pause-confirm-row {
  display: flex;
  gap: 10px;
}

.mf-pause-confirm-row > .mf-btn {
  flex: 1 1 0;
}

/* ***************************************************************
 * Language picker
 * *************************************************************** */

/* The drop-down list of shipped languages, opened from the language link
 * button; a simple full width column that flows under the links row */
.mf-lang-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
  padding: 8px;
  background: rgba(16, 19, 28, 0.5);
  border: 1px solid var(--mf-faint);
  border-radius: 11px;
}

/* One language option, each labeled in its own native script */
.mf-lang-option {
  min-height: 44px;
  padding: 10px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  color: var(--mf-ink-dim);
  background: rgba(184, 168, 216, 0.07);
  border: 1px solid var(--mf-card-border);
  border-radius: 9px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.mf-lang-option:hover {
  color: var(--mf-ink);
  background: rgba(184, 168, 216, 0.15);
}

/* The currently active language stands out in the accent */
.mf-lang-active {
  color: var(--mf-bg);
  background: var(--mf-accent);
}

.mf-lang-active:hover {
  color: var(--mf-bg);
  background: var(--mf-accent);
}

/* ***************************************************************
 * How to scoring guide
 * *************************************************************** */

/* Heading above the scoring guide grid */
.mf-howto-score-title {
  margin-top: 6px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--mf-ink-dim);
}

/* Column of scoring rows, each an icon, a name and its points */
.mf-howto-scores {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* One scoring row: icon on the left, name in the middle, points on the right */
.mf-howto-score-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  background: rgba(16, 19, 28, 0.5);
  border: 1px solid var(--mf-faint);
  border-radius: 10px;
}

/* The sprite icon canvas, a fixed square that never shrinks */
.mf-howto-score-icon {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
}

/* The item name fills the remaining width. min-width 0 lets the flex item shrink
   below its content width, and overflow-wrap breaks a long word, so a long name
   wraps onto the next line instead of overflowing the row sideways. */
.mf-howto-score-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: break-word;
  font-size: 14px;
  font-weight: 600;
  color: var(--mf-ink);
}

/* The point value reads in the gain green so the reward pops */
.mf-howto-score-value {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 800;
  color: var(--mf-up);
}

/* A worthless or penalty item dims its value in the danger tone */
.mf-howto-score-zero {
  color: var(--mf-danger);
}

/* A non-scoring item shows a localized effect phrase instead of a short number,
   so its slot must be allowed to shrink and WRAP to the next line rather than
   overflow the row sideways. This overrides the fixed value slot above (declared
   later so it wins) only for the effect label. */
.mf-howto-score-effect {
  flex: 0 1 auto;
  min-width: 0;
  white-space: normal;
  overflow-wrap: break-word;
  text-align: right;
  font-size: 12px;
  font-weight: 700;
  color: var(--mf-ink-dim);
}

/* ***************************************************************
 * Stats row
 * *************************************************************** */

.mf-stats-row {
  display: flex;
  gap: 8px;
}

.mf-stat {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 10px 6px;
  background: var(--mf-surface-flat);
  border: 1px solid var(--mf-faint);
  border-radius: 10px;
}

/* First line of a stat is its big value, the label is the dim second line */
.mf-stat strong {
  font-size: 18px;
  font-weight: 700;
  color: var(--mf-ink);
}

.mf-stat span {
  font-size: 10px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--mf-ink-dim);
}

/* A tiny dim glyph sitting above the stat value (a crown on Best, a coin on
 * Coins). It is quiet so the number still leads the cell, and it tints itself
 * through currentColor to match the dim label tone */
.mf-stat-icon {
  display: block;
  width: 19px;
  height: 19px;
  color: var(--mf-ink-dim);
}

/* size the inner svg to the cell, a notch larger than the shared link-icon
 * default so the crown and currency tokens read clearly above the value */
.mf-stat-icon svg {
  width: 19px;
  height: 19px;
}

/* the premium gold lift for the crown and star marquee icons. Scoped under
 * .mf-stat so it outranks the .mf-stat span label color rule that also catches
 * this span; the plain single class would tie on specificity and lose */
.mf-stat .mf-stat-icon-gold,
.mf-stat .mf-stat-icon-gold svg {
  color: var(--mf-gold);
}

/* a real collectible art token sits a touch larger than the flat glyph so the
 * sprite detail reads, and contains itself so it never distorts */
.mf-stat-icon-art {
  width: 22px;
  height: 22px;
}

.mf-stat-icon-art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ***************************************************************
 * Lists (buyable, progress, leaderboard, howto rows)
 * *************************************************************** */

.mf-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* The board list shows ten rows at most; the rest scrolls inside the card so
   the header, tabs and back action stay put while the player browses ranks */
.mf-board-list {
  max-height: 552px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Slim on-brand scrollbar for the kit's scrolling surfaces. The thumb derives
   from the accent token, so the day and night themes both stay on palette
   instead of falling back to the platform's default chrome */
.mf-card,
.mf-board-list {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--mf-accent) 38%, transparent) transparent;
}

.mf-card::-webkit-scrollbar,
.mf-board-list::-webkit-scrollbar {
  width: 6px;
}

.mf-card::-webkit-scrollbar-track,
.mf-board-list::-webkit-scrollbar-track {
  background: transparent;
}

.mf-card::-webkit-scrollbar-thumb,
.mf-board-list::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--mf-accent) 38%, transparent);
  border-radius: 999px;
}

.mf-card::-webkit-scrollbar-thumb:hover,
.mf-board-list::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--mf-accent) 60%, transparent);
}

.mf-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: var(--mf-surface-flat);
  border: 1px solid var(--mf-faint);
  border-radius: 11px;
}

/* The row main label grows to fill the space between art and trailing control */
.mf-list-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--mf-ink);
}

/* Stacked label plus hint wrapper inside a row */
.mf-list-desc {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.mf-list-desc .mf-list-label {
  flex: 0 0 auto;
}

/* Secondary hint text, also used for right aligned price and status notes */
.mf-list-hint {
  font-size: 12px;
  color: var(--mf-accent);
}

/* Small square art slot for a buyable row preview */
.mf-item-preview {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border-radius: 10px;
  background: rgba(16, 19, 28, 0.5);
  border: 1px solid var(--mf-faint);
  overflow: hidden;
}

/* The sprite the shop draws into the preview box, scaled to fill the slot */
.mf-item-preview-art {
  display: block;
  width: 100%;
  height: 100%;
}

/* A locked preview dims until the item is owned */
.mf-item-locked {
  filter: grayscale(1);
  opacity: 0.5;
}

/* The equipped or maxed state chip */
.mf-active-chip {
  flex: 0 0 auto;
  padding: 3px 9px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--mf-up);
  background: rgba(14, 203, 129, 0.14);
  border: 1px solid rgba(14, 203, 129, 0.35);
  border-radius: 999px;
}

/* The this-run chip on an ad-unlocked skin worn for the current session only,
 * tinted in the gold ad tone so it reads as a temporary wear, not a real unlock */
.mf-chip-run {
  color: #f0b429;
  background: rgba(240, 180, 41, 0.14);
  border-color: rgba(240, 180, 41, 0.4);
}

/* The locked invite gate hint on an invite item, a quiet right-aligned progress
 * label that does not wrap so the friends count stays on one line */
.mf-invite-gate {
  flex: 0 0 auto;
  text-align: right;
  white-space: nowrap;
  color: var(--mf-ink-dim);
}

/* Progress row state icon, a hollow circle until the goal is reached */
.mf-progress-icon {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--mf-ink-dim);
  opacity: 0.5;
}

.mf-progress-icon svg {
  width: 22px;
  height: 22px;
}

/* A completed progress row fills its circle in the up green */
.mf-progress-done {
  color: var(--mf-gold);
  opacity: 1;
}

/* Tier pip container for tiered buyables */
.mf-dots {
  display: flex;
  gap: 5px;
}

.mf-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid var(--mf-ink-dim);
}

/* An owned tier fills the pip with the accent */
.mf-dot-filled {
  background: var(--mf-accent);
  border-color: var(--mf-accent);
}

/* ***************************************************************
 * Leaderboard board rows
 * *************************************************************** */

.mf-board-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  font-size: 14px;
  background: var(--mf-surface-flat);
  border: 1px solid var(--mf-faint);
  border-radius: 10px;
}

/* Rank number leads the row */
.mf-board-rank {
  flex: 0 0 24px;
  font-weight: 700;
  color: var(--mf-ink-dim);
}

/* Round avatar between the rank and the name: the profile photo layers over a
   colored initial, so a missing or broken image falls back to the letter */
.mf-board-avatar {
  position: relative;
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
}

.mf-board-avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Player name fills the middle and ellipsizes */
.mf-board-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--mf-ink);
}

/* Score trails the row */
.mf-board-score {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--mf-ink);
  font-variant-numeric: tabular-nums;
}

/* Small level badge between the name and the score, for games with a level ladder.
   The up-triangle drawn before the number reads it as the player's climbed level. */
.mf-board-level {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--mf-accent-soft);
  color: var(--mf-accent);
  border: 1px solid var(--mf-accent);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.mf-board-level::before {
  content: '';
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 6px solid currentColor;
}

/* The signed in player's own row is highlighted in the accent */
.mf-board-me {
  background: var(--mf-accent-soft);
  border-color: var(--mf-accent);
}

.mf-board-me .mf-board-rank {
  color: var(--mf-accent);
}

/* The board title's inline trophy. SINGLE SOURCE: these three rules are the
   canonical leaderboard-title styling, kept byte-identical with the hub copy in
   player/styles/hub.css (.arcade-hub .mf-board-title*) and kit/leaderboard-shared.css.
   Without them here the in-game board (which only links this shell.css) falls back
   to the panel's white ink with the stroke="currentColor" trophy sitting unaligned
   at the top-left; with them the in-game header reads exactly like the hub board:
   a gold trophy inline right before the centered game-name title. */
.mf-board-title {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.mf-board-title-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  color: var(--mf-gold);
}

.mf-board-title-icon svg {
  display: block;
  width: 22px;
  height: 22px;
}

/* ***************************************************************
 * Overlays (pause, revive, game over)
 * *************************************************************** */

.mf-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(16px + var(--mf-safe-top, 0px))
    calc(16px + var(--mf-safe-right, 0px))
    calc(16px + var(--mf-safe-bottom, 0px))
    calc(16px + var(--mf-safe-left, 0px));
}

/* Dim backdrop behind an overlay card */
.mf-dim {
  position: absolute;
  inset: 0;
  background: rgba(8, 10, 16, 0.72);
  backdrop-filter: blur(3px);
}

/* The overlay card floats above the dim and reuses the menu card look */
.mf-overlay .mf-card {
  position: relative;
  z-index: 1;
  margin: 0;
}

/* Floating pause control anchored to the top right of the stage, pushed in by
 * the safe-area inset so it clears the notch and the Telegram fullscreen header */
.mf-pause-btn {
  position: absolute;
  /* the device safe area PLUS a fixed clearance so the pause control sits below
     Telegram's fullscreen close / collapse / menu chrome in the top corners,
     which it was overlapping at the plain safe-area inset */
  top: calc(max(12px, var(--mf-safe-top, 0px)) + 44px);
  right: max(12px, var(--mf-safe-right, 0px));
  z-index: 20;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  letter-spacing: 1px;
  color: var(--mf-ink);
  background: rgba(16, 19, 28, 0.6);
  border: 1px solid var(--mf-card-border);
  border-radius: 50%;
  cursor: pointer;
  backdrop-filter: blur(4px);
}

.mf-pause-btn:active {
  background: rgba(16, 19, 28, 0.85);
}

/* The shared lives readout (hearts), a DOM element pinned with the EXACT same
   safe-area anchor as the pause button but on the left, so the lives always sit
   on the pause button's line, guaranteed, even when mobile Telegram pushes the
   chrome down. Vertically centred on the same 48px line as the pause button. */
.mf-lives-hud {
  position: absolute;
  top: calc(max(12px, var(--mf-safe-top, 0px)) + 44px);
  left: max(12px, var(--mf-safe-left, 0px));
  height: 48px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 5px;
  pointer-events: none;
}

.mf-lives-hud .mf-life {
  display: block;
}

.mf-lives-hud .mf-lives-count {
  font: 800 26px system-ui, -apple-system, sans-serif;
  color: currentColor;
  margin-right: 3px;
}

.mf-lives-hud.mf-hidden {
  display: none;
}

/* The shared top-left corner stat (a DOM text readout), pinned with the EXACT
   same safe-area anchor as the pause button and the lives HUD but on the left,
   so a game's headline stat (e.g. hold-snake's distance) always sits on the
   pause button's line on every host - mobile and web Telegram alike - instead of
   drifting like a canvas-drawn number. Vertically centred on the same 48px line
   as the pause button. */
.mf-corner-stat {
  position: absolute;
  top: calc(max(12px, var(--mf-safe-top, 0px)) + 44px);
  left: max(12px, var(--mf-safe-left, 0px));
  height: 48px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 3px;
  pointer-events: none;
  line-height: 1;
}

.mf-corner-stat .mf-corner-stat-value {
  font: 800 30px system-ui, -apple-system, sans-serif;
}

.mf-corner-stat .mf-corner-stat-unit {
  font: 700 18px system-ui, -apple-system, sans-serif;
  color: #9cc3aa;
  opacity: 0.9;
}

/* compact variant: a quieter, smaller sub-stat (opt-in per game, e.g. miro-flight
   distance) - hold-snake and other games keep the bold headline default above */
.mf-corner-stat--compact {
  height: 40px;
}

.mf-corner-stat--compact .mf-corner-stat-value {
  font: 600 23px system-ui, -apple-system, sans-serif;
}

.mf-corner-stat--compact .mf-corner-stat-unit {
  font: 600 14px system-ui, -apple-system, sans-serif;
  color: inherit;
  opacity: 0.7;
}

.mf-corner-stat.mf-hidden {
  display: none;
}

/* The transient centre wave/level banner: the game's menu mascot over a big label
   that pops in and fades out when the value increments. Cosmetic, no pointer. */
.mf-wave-banner {
  position: absolute;
  top: 38%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 25;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  pointer-events: none;
  text-align: center;
}

.mf-wave-banner .mf-wave-mascot {
  width: 116px;
  height: auto;
  display: block;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.45));
}

.mf-wave-banner .mf-wave-label {
  font: 900 54px system-ui, -apple-system, sans-serif;
  color: currentColor;
  letter-spacing: 1px;
  text-shadow: 0 3px 12px rgba(0, 0, 0, 0.55);
}

.mf-wave-banner.mf-hidden {
  display: none;
}

.mf-wave-banner.mf-wave-banner-play {
  display: flex;
  animation: mf-wave-pop 1.8s ease forwards;
}

@keyframes mf-wave-pop {
  0% {
    opacity: 0;
    transform: translate(-50%, -42%) scale(0.85);
  }
  14% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.05);
  }
  26% {
    transform: translate(-50%, -50%) scale(1);
  }
  76% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -54%) scale(1);
  }
}

/* ***************************************************************
 * Game over card
 * *************************************************************** */

/* New record banner, celebratory in the up green */
.mf-newbest {
  align-self: center;
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--mf-up);
  background: rgba(14, 203, 129, 0.14);
  border: 1px solid rgba(14, 203, 129, 0.35);
  border-radius: 999px;
}

/* Grade band chip, neutral accent fill with the band letter as its text */
.mf-grade-chip {
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 56px;
  padding: 8px 18px;
  font-size: 26px;
  font-weight: 800;
  letter-spacing: 1px;
  color: var(--mf-bg);
  background: var(--mf-accent);
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(184, 168, 216, 0.35);
}

/* Chip shown when the player used a revive this run */
.mf-revived-chip {
  align-self: center;
  padding: 4px 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--mf-accent);
  background: var(--mf-accent-soft);
  border: 1px solid var(--mf-card-border);
  border-radius: 999px;
}

/* The summary block on the game over card */
.mf-summary {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  background: var(--mf-surface-flat);
  border: 1px solid var(--mf-faint);
  border-radius: 11px;
}

.mf-summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 14px;
  color: var(--mf-ink-dim);
}

/* Right aligned tally value on each summary line */
.mf-summary-value {
  font-size: 16px;
  font-weight: 700;
  color: var(--mf-ink);
  font-variant-numeric: tabular-nums;
}

/* The soft-currency value grouped with the branded jeton mark on the row's right
   edge: the amount, then the M jeton just to its right. */
.mf-summary-coinval {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.mf-summary-coin-icon {
  display: inline-flex;
}

.mf-summary-coin-icon svg {
  width: 15px;
  height: 15px;
  display: block;
}

/* ***************************************************************
 * Revive bar (countdown)
 * *************************************************************** */

.mf-revive-bar-track {
  width: 100%;
  height: 8px;
  background: rgba(16, 19, 28, 0.6);
  border: 1px solid var(--mf-faint);
  border-radius: 999px;
  overflow: hidden;
}

.mf-revive-bar {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--mf-accent), var(--mf-up));
  border-radius: 999px;
}

/* When this flag is added the fill drains over the revive window */
.mf-revive-bar-shrink {
  width: 0%;
  transition: width 5000ms linear;
}

/* ***************************************************************
 * Toast (one snackbar slot above the thumb zone)
 * *************************************************************** */

.mf-toast-root {
  position: absolute;
  left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  z-index: 40;
  transform: translateX(-50%);
  display: flex;
  justify-content: center;
  width: 100%;
  pointer-events: none;
  padding: 0 16px;
}

.mf-toast {
  max-width: 320px;
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  color: var(--mf-ink);
  background: rgba(16, 19, 28, 0.92);
  border: 1px solid var(--mf-card-border);
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

/* The enter and visible state of a toast */
.mf-toast-show {
  opacity: 1;
  transform: translateY(0);
}

/* ***************************************************************
 * Mascot (optional menu art slot)
 * *************************************************************** */

.mf-mascot {
  display: block;
  width: 132px;
  height: auto;
  margin: 0 auto;
  image-rendering: auto;
}

/* The game-over mascot is standardized to one fixed square box across all 16
   games so a tall or wide mascot webp no longer renders larger or smaller than
   the others. object-fit contain scales each mascot to fit the box keeping its
   aspect, so none is stretched and all read at the same size. */
.mf-gameover-mascot {
  width: 120px;
  height: 120px;
  object-fit: contain;
}

body.mf-short .mf-gameover-mascot {
  width: 96px;
  height: 96px;
}

/* The paused card reuses the menu mascot at a smaller size so it sits neatly
 * under the Paused title without crowding the action buttons below it. */
.mf-pause-mascot {
  width: 96px;
  margin: 2px auto 10px;
}

/* ***************************************************************
 * Arcade hub page (generated dist/index.html only)
 * *************************************************************** */

.mf-hub {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  /* Always reserve the scrollbar gutter so toggling Favorites (which shortens
   * the grid and would otherwise drop the scrollbar) never widens the content
   * box and zooms the cards and heading. Favorites is an in-place filter, not a
   * separate page, so the layout must stay rock steady across the toggle. */
  scrollbar-gutter: stable;
  padding: 24px 16px max(24px, env(safe-area-inset-bottom));
  background: linear-gradient(160deg, var(--mf-bg) 0%, var(--mf-bg-2) 100%);
}

.mf-hub-title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
  text-align: center;
}

/* The brand lockup: the icon next to the Mire wordmark on one row */
.mf-hub-lockup {
  display: flex;
  align-items: center;
  gap: 9px;
}

.mf-hub-title img {
  width: auto;
}

/* The colored brand mark, the hero icon of the landing */
.mf-hub-mark {
  height: 30px;
}

/* The Mire Games wordmark beside the mark, now two-tone live text so it matches
 * the splash and dialog lockups and reads the brand colors true */
.mf-hub-word {
  display: flex;
  align-items: baseline;
  gap: 5px;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 0.3px;
}

.mf-hub-title h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: var(--mf-ink);
}

/* The search + favorites toolbar above the game grid, pinned to the top so it
   stays reachable while the long game list scrolls under it */
.mf-hub-tools {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  gap: 10px;
  max-width: 720px;
  margin: 0 auto 16px;
  padding: 12px 0;
  align-items: center;
  background: var(--mf-bg);
  box-shadow: 0 8px 14px -10px rgba(0, 0, 0, 0.7);
}

/* The back control closes the arcade webview, sitting at the start of the bar */
.mf-hub-back {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  color: var(--mf-ink);
  background: var(--mf-surface);
  border: 1px solid var(--mf-card-border);
  border-radius: 12px;
  cursor: pointer;
}

.mf-hub-back:active {
  background: var(--mf-bg-2);
}

.mf-hub-search {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 42px;
  padding: 10px 14px;
  font-family: inherit;
  font-size: 15px;
  color: var(--mf-ink);
  background: var(--mf-surface);
  border: 1px solid var(--mf-card-border);
  border-radius: 12px;
  outline: none;
}

.mf-hub-search::placeholder {
  color: var(--mf-ink-dim);
}

.mf-hub-search:focus {
  border-color: var(--mf-accent);
}

.mf-hub-favchip {
  flex: 0 0 auto;
  min-height: 42px;
  padding: 0 14px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  color: var(--mf-ink-dim);
  background: var(--mf-surface);
  border: 1px solid var(--mf-card-border);
  border-radius: 12px;
  cursor: pointer;
}

.mf-hub-favchip.on {
  color: var(--mf-gold);
  border-color: var(--mf-gold);
}

/* The footer meta row keeps the favorite star and crown progress off the banner
   art, so neither collides with the game name baked into the image */
.mf-hub-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 28px;
  margin-top: 2px;
}

.mf-hub-card-art .mf-hub-meta {
  margin: 0 14px 8px;
}

/* The favorite star toggle anchors the left of the footer meta row */
.mf-hub-fav {
  order: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: -4px;
  padding: 0;
  color: var(--mf-ink-dim);
  background: transparent;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.12s ease, background 0.12s ease;
}

.mf-hub-fav.on {
  color: var(--mf-gold);
}

/* Hover styling only on real pointer devices, so a phone tap never leaves a
   sticky hover that overrides the gold favorited state */
@media (hover: hover) {
  .mf-hub-fav:hover {
    color: var(--mf-ink);
    background: rgba(255, 255, 255, 0.06);
  }

  .mf-hub-fav.on:hover {
    color: var(--mf-gold);
  }
}

.mf-hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
  max-width: 720px;
  margin: 0 auto;
}

.mf-hub-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px;
  text-decoration: none;
  background: var(--mf-surface);
  border: 1px solid var(--mf-card-border);
  border-left: 3px solid var(--mf-accent);
  border-radius: var(--mf-radius);
  transition: transform 0.1s ease, background 0.15s ease, box-shadow 0.2s ease;
}

.mf-hub-card:hover {
  background: rgba(28, 34, 48, 0.96);
  transform: translateY(-2px);
}

.mf-hub-card strong {
  font-size: 15px;
  font-weight: 700;
  color: var(--mf-ink);
}

.mf-hub-card span {
  font-size: 12px;
  line-height: 1.4;
  color: var(--mf-ink-dim);
}

/* Art cards carry the hero banner edge to edge above the text block */
.mf-hub-card-art {
  padding: 0;
  gap: 0;
  overflow: hidden;
}

.mf-hub-card-art img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-bottom: 1px solid var(--mf-card-border);
}

.mf-hub-card-art strong {
  margin: 10px 14px 2px;
}

.mf-hub-card-art span {
  margin: 10px 14px 6px;
}

/* The overlaid, localizable game name on an art hub card. It replaces the title
 * that used to be painted into the hero webp, so the name now comes from the
 * string tables (i18n) and can be translated or restyled without redrawing art.
 * Pinned top-left over the hero, white with the game accent underline so it
 * reads like the old baked stamp. width:max-content keeps the underline tight
 * to the text. The more specific selector overrides the art-card strong margin. */
.mf-hub-card-art .mf-hub-card-title {
  position: absolute;
  top: 8px;
  left: 12px;
  margin: 0;
  padding: 0 0 4px;
  width: max-content;
  max-width: calc(100% - 24px);
  font-size: 15px;
  font-weight: 800;
  line-height: 1.15;
  color: #fff;
  letter-spacing: 0.2px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.75), 0 0 2px rgba(0, 0, 0, 0.6);
  border-bottom: 3px solid var(--mf-card-accent, #fff);
  z-index: 2;
  pointer-events: none;
}

/* A soft dark scrim only behind cards that carry the overlaid title, so the
 * white name stays legible over a bright hero. Art-integral cards (no overlay)
 * are left untouched. :has keeps the scrim scoped to titled cards. */
.mf-hub-card-art:has(.mf-hub-card-title)::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 46%;
  background: linear-gradient(180deg, rgba(8, 11, 18, 0.62) 0%, rgba(8, 11, 18, 0) 100%);
  z-index: 1;
  pointer-events: none;
}

/* The crown progress reads as light gold text on the right of the footer meta
   row, no heavy pill so it stops crowding the card */
.mf-hub-crowns {
  order: 2;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  font-weight: 800;
  color: var(--mf-gold);
}

/* A fully crowned game glows gold so a maxed game stands out in the grid */
.mf-hub-card-crowned {
  border-color: var(--mf-gold);
  box-shadow: 0 0 18px rgba(255, 215, 94, 0.45);
}

/* ***************************************************************
 * Invite panel
 * *************************************************************** */

/* The headline count of friends joined toward the reward */
.mf-invite-progress {
  font-size: 16px;
  font-weight: 800;
  color: var(--mf-ink);
}

/* The reward state line, dim while locked and gold once unlocked */
.mf-invite-reward {
  font-size: 13px;
  font-weight: 600;
  color: var(--mf-ink-dim);
}

.mf-invite-reward-on {
  color: var(--mf-gold);
}

/* The promo redeem block on the invite panel, a touch of top spacing to set it
 * apart from the invite reward line above */
.mf-redeem-box {
  margin-top: 8px;
}

/* The promo code input: a dark field that matches the panel chrome and grows to
 * fill the row beside the redeem button */
.mf-redeem-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 10px 12px;
  font-size: 14px;
  color: var(--mf-ink);
  background: var(--mf-surface-flat);
  border: 1px solid var(--mf-card-border);
  border-radius: 10px;
  outline: none;
  text-transform: uppercase;
}

/* The invite link box, selectable and wrapping so the full link is readable */
.mf-invite-link {
  padding: 10px 12px;
  font-size: 12px;
  word-break: break-all;
  user-select: all;
  color: var(--mf-accent);
  background: rgba(16, 19, 28, 0.5);
  border: 1px solid var(--mf-faint);
  border-radius: 10px;
}

/* ***************************************************************
 * Responsive (portrait only; desktop just keeps the centered column)
 * *************************************************************** */

/* Phones: let the menu card use the full width and scroll */
@media (max-width: 560px) {
  .mf-card {
    width: 100%;
    border-radius: 16px;
  }

  #menu-root {
    padding: 12px;
    align-items: stretch;
  }

  .mf-title {
    font-size: 21px;
  }
}

/* Very short stages: trim card padding so it never clips off screen */
@media (max-height: 420px) {
  .mf-card {
    padding-top: 14px;
    padding-bottom: 14px;
  }
}

/* ***************************************************************
 * Day mode hardcoded overrides (OPTIONAL warm parchment theme)
 * These rules patch the values that do NOT read the --mf-* tokens and so would
 * look broken on the light parchment background. Every selector here is gated
 * under :root[data-theme="day"] so NIGHT stays byte-identical; placed at the end
 * of the file so each override wins on source order against the matching dark
 * rule of equal specificity. The gold watch-ad button (.mf-btn-ad) and every
 * gold #ffd75e crown/medal/trophy semantic are intentionally left UNCHANGED.
 * *************************************************************** */

/* Subtitle was near-white (rgba(238,241,247,0.85)) - invisible on a light card */
:root[data-theme="day"] .mf-subtitle {
  color: #5c5850;
}

/* Primary CTA was a fixed lavender gradient; day reads as white-on-burgundy. The
   text color stays var(--mf-bg) (now near-white) which is correct on burgundy. */
:root[data-theme="day"] .mf-btn-primary {
  background: linear-gradient(135deg, #a8324f 0%, #880e4f 100%);
  box-shadow: 0 8px 20px rgba(136, 14, 79, 0.28);
}

:root[data-theme="day"] .mf-btn-primary:hover {
  background: linear-gradient(135deg, #b53d5a 0%, #98185c 100%);
}

/* Overlay scrim was a heavy dark veil; day uses a soft warm-grey wash */
:root[data-theme="day"] .mf-dim {
  background: rgba(44, 42, 38, 0.40);
}

/* Card drop shadow was a deep black; day uses a soft warm shadow */
:root[data-theme="day"] .mf-card {
  box-shadow: 0 10px 30px rgba(80, 60, 30, 0.12),
    0 2px 8px rgba(80, 60, 30, 0.06);
}

/* Corner-stat unit was a fixed mint green; day uses a warm dim grey */
:root[data-theme="day"] .mf-corner-stat .mf-corner-stat-unit {
  color: #716a60;
}

/* Toggle group track was a dark fill; day uses a flat parchment fill */
:root[data-theme="day"] .mf-toggle-group {
  background: #f1eee7;
  border-color: #e6e2d9;
}

/* New-best banner used fixed neon-green tints; day uses the muted day up-green */
:root[data-theme="day"] .mf-newbest {
  background: rgba(78, 125, 47, 0.12);
  border-color: rgba(78, 125, 47, 0.30);
}

/* Revive bar track was a dark fill; day uses a faint warm-grey track */
:root[data-theme="day"] .mf-revive-bar-track {
  background: rgba(44, 42, 38, 0.10);
}

/* Brand wordmark colors were tuned for dark; day uses readable-on-white tones */
:root[data-theme="day"] .mf-brand-mire {
  color: #d96f8a;
}

:root[data-theme="day"] .mf-brand-games {
  color: #b8b0c2;
}

/* Faint lavender washes on the icon and link buttons; day matches the burgundy */
:root[data-theme="day"] .mf-icon-btn,
:root[data-theme="day"] .mf-link-btn {
  background: rgba(136, 14, 79, 0.06);
}

/* The faint icon-btn wash above (specificity 0,3,0) would otherwise defeat the
   base .mf-icon-btn-primary accent fill (0,1,0) and wash out the Resume action.
   Restore the solid burgundy fill + white glyph for the primary, placed after the
   wash so equal-specificity source order wins. */
:root[data-theme="day"] .mf-icon-btn-primary,
:root[data-theme="day"] .mf-icon-btn-primary:hover {
  color: var(--mf-bg);
  background: var(--mf-accent);
  border-color: var(--mf-accent);
}

/* ***************************************************************
 * Day mode Step-4 audit overrides (additional hardcoded breakages)
 * Hardcoded dark fills / near-white text used on surfaces visible in day mode,
 * found by scanning the whole file; each repainted to the day palette. Gold
 * #ffd75e semantics and the layout-edit overlay (?edit dev tool, not user UI)
 * are intentionally excluded.
 * *************************************************************** */

/* This-run skin chip: gold-on-dark ad tone reads fine, but its raw values are
   kept. (left unchanged - gold semantic) */

/* Equipped/maxed chip used fixed neon-green tints; align to the day up-green */
:root[data-theme="day"] .mf-active-chip {
  background: rgba(78, 125, 47, 0.12);
  border-color: rgba(78, 125, 47, 0.30);
}

/* Item preview slot bg was a dark fill; day uses a flat parchment fill */
:root[data-theme="day"] .mf-item-preview {
  background: #f1eee7;
}

/* The floating pause button lives over the GAMEPLAY canvas, which is still dark in
   day mode (no in-game day repaint), so a bright white pill was glaring on the dark
   scene. Keep it a calm dark translucent pill with a light glyph in day too - the
   same comfortable treatment night uses over the same dark game. The icon color is
   forced light here because --mf-ink is dark in day and would vanish otherwise. */
:root[data-theme="day"] .mf-pause-btn {
  background: rgba(18, 22, 30, 0.5);
  color: #eef1f7;
  border-color: rgba(255, 255, 255, 0.16);
}

:root[data-theme="day"] .mf-pause-btn:active {
  background: rgba(18, 22, 30, 0.66);
}

/* Lang picker list + drop bg were dark fills; day uses the flat parchment fill */
:root[data-theme="day"] .mf-lang-list {
  background: #f1eee7;
}

:root[data-theme="day"] .mf-lang-option {
  background: rgba(136, 14, 79, 0.06);
}

/* How-to score rows had a dark fill; day uses the flat parchment fill */
:root[data-theme="day"] .mf-howto-score-row {
  background: #f1eee7;
}

/* Toast snackbar was a dark pill with a black shadow; day uses a light pill */
:root[data-theme="day"] .mf-toast {
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 6px 18px rgba(80, 60, 30, 0.18);
}

/* Invite link box bg was a dark fill; day uses the flat parchment fill */
:root[data-theme="day"] .mf-invite-link {
  background: #f1eee7;
}

/* Hub tools bar shadow was a heavy black; soften for the light page */
:root[data-theme="day"] .mf-hub-tools {
  box-shadow: 0 8px 14px -10px rgba(80, 60, 30, 0.45);
}

/* Hub card hover bg was a fixed dark slate; day lifts toward warm parchment */
:root[data-theme="day"] .mf-hub-card:hover {
  background: #fbfaf6;
}
