/* ---- Main menu: the treehouse hall ----------------------------------------
   The painting (assets/ui/menu-hall.webp, 1672×941) is the menu, and it fills
   the screen edge to edge, notch and status-bar side included: its spare edges
   (up to the drawn controls) are cropped first, then whatever is still missing
   is made up by stretching it a little (at most 25-30%). The drawn controls always
   stay inside the safe area, a few pixels clear of the notch and the screen's
   edges; any sliver the painting can't reach without pushing them out (beside a
   notch) is filled by a crisp mirrored continuation of its own edge.
   The controls are drawn in the painting and the buttons sit exactly over them.
   Placement is in painting pixels: a .p box is placed on the stage from
   --x --y --w --h; a .q box is placed the same way inside its .p parent, whose
   box it inherits as --X --Y --W --H. --k is one painting pixel on screen, for
   type and effects. A .cut is a live copy of the painting under its box, so a
   control can pop, breathe or hop without a seam (it matches the art exactly
   at rest). Live text sits on spots cleared in the art. Animations touch only
   transform, opacity and filter. */

.menu {
  position: absolute; inset: 0; z-index: 20; display: none; overflow: hidden; pointer-events: none;
  container-type: size; background: #1c1007;
  --art: url('../../assets/ui/menu-hall.webp');
  /* Its outer 360 px strips with the drawn controls painted out (left strip on
     top, right below), for the mirrored fill past its edges. */
  --art-side: url('../../assets/ui/menu-hall-side.webp');
  /* Keep-out at each side: the safe-area inset (notch, cutout, status bar) plus
     a little air, and never less than 10 px from the glass. The controls need
     1616 × 892 of the painting (28 px each side, 20 top, 29 bottom); they get the
     room between the keep-outs (--aw), and the full height less 8 px top and
     bottom (the home indicator may overlap the dock, as in any landscape game).
     menu-scene.js measures the menu (--mw --mh) and the insets (--safe-*, set
     here on .menu) in pixels: after the phone turns, iOS can keep the portrait
     insets and container sizes in these sums until the menu is reopened, which
     stretched the hall over the notch. The container units are only the
     fallback until the first measure. */
  --pl: max(10px, var(--safe-l, 0px) + 6px);
  --pr: max(10px, var(--safe-r, 0px) + 6px);
  --aw: calc(var(--mw, 100cqw) - var(--pl) - var(--pr));
  --ah: var(--mh, 100cqh);
  /* The stage is centred on that room. --tw is the width it wants: enough to
     reach both screen edges, but no wider than keeps the controls in the room.
     --h0 is the painting's height at the uniform scale that covers --tw × --ah,
     short of cropping into the controls; the stage then stretches to fill the
     rest, at most 25% across (30% down, so 4:3 tablets fill too). */
  --tw: min(var(--aw) + 2 * max(var(--pl), var(--pr)), var(--aw) * 1672 / 1616);
  --h0: min(max(var(--tw) * 941 / 1672, var(--ah)), var(--aw) * 941 / 1616, (var(--ah) - 16px) * 941 / 892);
  --w0: calc(var(--h0) * 1672 / 941);
  --sw: min(max(var(--w0), var(--tw)), var(--w0) * 1.25);
  --sh: min(max(var(--h0), var(--ah)), var(--h0) * 1.3);
  /* Centred across; down, a crop is shared 20 : 29 between top and bottom. */
  --sl: calc(var(--pl) + (var(--aw) - var(--sw)) / 2);
  --st: calc(min(0px, (var(--ah) - var(--sh)) * 20 / 49) + max(0px, (var(--ah) - var(--sh)) / 2));
  --cream: #fff3d6;
}
.app[data-screen="menu"] .menu { display: block; }
.menu button { pointer-events: auto; font: inherit; color: inherit; -webkit-tap-highlight-color: transparent; cursor: pointer; }
.menu button:focus-visible { outline: 3px solid #ffe394; outline-offset: 2px; }
.mh-sr, .mh-title h1, .menu .menu-best {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Backdrop: past the painting's edges ------------------------------- */
/* Each side continues the painting as its own crisp mirror image (under the
   notch, and past the stretch limit on very wide screens). The sides mirror
   the cleaned edge strips, so the profile and gear don't reflect; top and
   bottom (tall tablets) mirror only the painting's spare rows above and below
   the controls. Past those it is the plain dark wood of .menu. */
.mh-back { position: absolute; inset: 0; overflow: hidden; animation: mh-fade .8s ease backwards; }
.mh-back i { position: absolute; top: var(--st); left: var(--sl); width: var(--sw); height: var(--sh); background: no-repeat; }
.mh-back i.l, .mh-back i.r { background-image: var(--art-side); background-size: calc(360 * 100% / 1672) 200%; transform: scaleX(-1); }
.mh-back i.l { background-position: 0 0; left: calc(var(--sl) - var(--sw) + 1px); -webkit-mask-image: linear-gradient(90deg, #000, #000 17%, transparent 21.5%); mask-image: linear-gradient(90deg, #000, #000 17%, transparent 21.5%); }
.mh-back i.r { background-position: 100% 100%; left: calc(var(--sl) + var(--sw) - 1px); -webkit-mask-image: linear-gradient(270deg, #000, #000 17%, transparent 21.5%); mask-image: linear-gradient(270deg, #000, #000 17%, transparent 21.5%); }
.mh-back i.t, .mh-back i.b { background-image: var(--art); background-size: 100% 100%; transform: scaleY(-1); }
.mh-back i.t { top: calc(var(--st) - var(--sh) + 1px); -webkit-mask-image: linear-gradient(#000, #000 1.6%, transparent 2.1%); mask-image: linear-gradient(#000, #000 1.6%, transparent 2.1%); }
.mh-back i.b { top: calc(var(--st) + var(--sh) - 1px); -webkit-mask-image: linear-gradient(0deg, #000, #000 2.5%, transparent 3.1%); mask-image: linear-gradient(0deg, #000, #000 2.5%, transparent 3.1%); }
@keyframes mh-fade { from { opacity: 0; } }

/* ---- Stage ------------------------------------------------------------- */
.mh-stage {
  position: absolute; left: var(--sl); top: var(--st); width: var(--sw); height: var(--sh);
  container-type: size; --k: calc(100cqh / 941);
  animation: mh-open .9s var(--ease-out) backwards;
}
@keyframes mh-open { from { opacity: 0; transform: scale(1.05); } }
.mh-art { position: absolute; inset: 0; background: var(--art) 0 0 / 100% 100% no-repeat; }
/* Opening: one warm sweep of light across the hall. */
.mh-stage::after {
  content: ''; position: absolute; inset: 0; z-index: 9; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(112deg, transparent 38%, rgba(255,232,170,.32) 50%, transparent 62%) 0 0 / 260% 100% no-repeat;
  animation: mh-sweep 1.5s ease-out .35s both;
}
@keyframes mh-sweep { from { background-position: 100% 0; opacity: 1; } 85% { opacity: 1; } to { background-position: 0 0; opacity: 0; } }

.p, .q { position: absolute; box-sizing: border-box; }
.p {
  left: calc(var(--x) * 100% / 1672); top: calc(var(--y) * 100% / 941);
  width: calc(var(--w) * 100% / 1672); height: calc(var(--h) * 100% / 941);
  --X: var(--x); --Y: var(--y); --W: var(--w); --H: var(--h);
}
.q {
  left: calc((var(--x) - var(--X)) * 100% / var(--W)); top: calc((var(--y) - var(--Y)) * 100% / var(--H));
  width: calc(var(--w) * 100% / var(--W)); height: calc(var(--h) * 100% / var(--H));
}
.cut {
  position: absolute; inset: 0; pointer-events: none;
  background: var(--art) no-repeat;
  background-size: calc(1672 * 100% / var(--w)) calc(941 * 100% / var(--h));
  background-position: calc(var(--x) * 100% / (1672 - var(--w))) calc(var(--y) * 100% / (941 - var(--h)));
}
.cut.soft {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent), linear-gradient(transparent, #000 9%, #000 91%, transparent);
  -webkit-mask-composite: source-in; mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent), linear-gradient(transparent, #000 9%, #000 91%, transparent);
  mask-composite: intersect;
}
.cut.round { -webkit-mask-image: radial-gradient(closest-side, #000 78%, transparent); mask-image: radial-gradient(closest-side, #000 78%, transparent); }

/* Live text, written over the spots cleared in the painting. */
.mh-t {
  display: block; margin: 0; font-size: calc(var(--fs) * var(--k)); font-style: normal; font-weight: 700; line-height: 1; text-align: left;
  white-space: nowrap; color: #fff; paint-order: stroke fill; transform-origin: 0 50%;
  /* --sx: the painting's stretch (set by menu-scene.js), so the text stretches with it. */
  transform: scale(calc(var(--fit, 1) * var(--sx, 1)), var(--fit, 1));
}

/* ---- Buttons ----------------------------------------------------------- */
.mh-btn { padding: 0; border: 0; background: none; border-radius: calc(var(--k) * 26); }
.mh-in { position: absolute; inset: 0; transition: transform .4s var(--spring), filter .25s; }
.mh-btn:active .mh-in { transform: scale(1.045); filter: brightness(1.14) saturate(1.06); transition-duration: .07s; }

/* Profile: avatar, level, name, XP. */
.mh-profile { border-radius: calc(var(--k) * 20) 999px 999px calc(var(--k) * 20); }
.pf-avatar {
  overflow: hidden; display: grid; place-items: end center; border-radius: calc(var(--k) * 9);
  background: radial-gradient(circle at 50% 22%, #fbf3bf, #dcd998 42%, #b4c07c 78%, #9aae68);
}
.pf-avatar.framed { box-shadow: 0 0 0 calc(var(--k) * 4) var(--fb), 0 0 0 calc(var(--k) * 7) var(--fa); }
.pf-avatar img { width: 128%; height: 128%; max-width: none; object-fit: contain; margin-bottom: -28%; -webkit-user-drag: none; }
.pf-avatar img:not([src]) { visibility: hidden; }
.pf-level { text-align: center; transform-origin: 50% 50%; -webkit-text-stroke: calc(var(--k) * 5) #1a0800; text-shadow: 0 calc(var(--k) * 2) 0 #1a0800; font-variant-numeric: tabular-nums; }
.pf-name { color: #fff; -webkit-text-stroke: calc(var(--k) * 3) #050302; text-shadow: 0 calc(var(--k) * 2) 0 rgba(5,3,1,.75); }
.pf-name small { display: none; }
.pf-bar i {
  position: absolute; left: 0; top: 0; bottom: 0; min-width: 7%; border-radius: 999px; overflow: hidden;
  background: linear-gradient(#bdf7c8, #6ae392 30%, #3cc070 68%, #2a9a52); box-shadow: inset 0 calc(var(--k) * -2) 0 rgba(10,70,30,.35);
  transition: width .9s var(--ease-out);
}
.pf-bar i::after {
  content: ''; position: absolute; inset: 0; background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.75) 50%, transparent 70%);
  transform: translateX(-100%); animation: mh-bar 5s ease-in-out 2s infinite;
}
@keyframes mh-bar { 0%, 70% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
.pf-xp { text-align: center; transform-origin: 50% 50%; color: #f4efcf; -webkit-text-stroke: calc(var(--k) * 2.5) #070803; text-shadow: 0 calc(var(--k) * 1.5) 0 rgba(0,0,0,.55); font-variant-numeric: tabular-nums; }

/* Status: account chip, online dot, offline-pack line (auth-client mounts the chip). */
.menu-connection { display: flex; align-items: center; justify-content: flex-start; gap: 8px; min-width: 0; font-size: max(10px, calc(var(--k) * 17)); }
.menu-connection > * { pointer-events: auto; }
#offline-status { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #f6e8c4; text-shadow: 0 1px 3px #000, 0 0 8px rgba(0,0,0,.8); }
.menu .auth-account-button { max-width: 100%; background: rgba(34,18,7,.82); border-color: rgba(200,146,82,.75); box-shadow: 0 3px 8px rgba(0,0,0,.4); }

/* Corner knobs: fullscreen and sound, carved like the gear. */
.mh-knobs { display: flex; align-items: center; justify-content: flex-end; gap: max(4px, calc(var(--k) * 12)); }
.mh-knob {
  flex: none; display: grid; place-items: center; width: max(28px, calc(var(--k) * 56)); aspect-ratio: 1; padding: 0; border: 0; border-radius: 50%; color: #f8e7bd;
  background: radial-gradient(circle at 50% 32%, #6e4320, #3a200b 72%);
  box-shadow: inset 0 0 0 max(2px, calc(var(--k) * 4)) #a8733d, 0 0 0 max(1.5px, calc(var(--k) * 3)) #23120a, 0 calc(var(--k) * 5) calc(var(--k) * 10) rgba(0,0,0,.45);
  transition: transform .3s var(--spring);
}
.mh-knob[hidden] { display: none; }
.mh-knob .mi, .mh-knob > svg { display: grid; width: 50%; height: 50%; }
.mh-knob .mi svg { width: 100%; height: 100%; }
.mh-knob:active { transform: scale(.88); transition-duration: .06s; }
.mh-xp { display: none; }

/* Acorns and the gear. */
.mh-purse { border-radius: 999px; }
#acorn-total { text-align: center; transform-origin: 50% 50%; -webkit-text-stroke: calc(var(--k) * 4) #120a02; text-shadow: 0 calc(var(--k) * 2) 0 rgba(0,0,0,.6); font-variant-numeric: tabular-nums; }
#acorn-total.bump { animation: mh-bump .5s var(--spring); }
@keyframes mh-bump { 40% { transform: scale(calc(var(--fit, 1) * var(--sx, 1) * 1.25), calc(var(--fit, 1) * 1.25)); color: #fff6c0; } }
.mh-gear { border-radius: 50%; }
.mh-gear .cut { transition: transform .6s var(--spring); }
.mh-gear:active .cut { transform: rotate(45deg); }

/* ---- Title, Play, rows ------------------------------------------------- */
.mh-title { pointer-events: none; }
/* A shine that sweeps across the letters only (menu-title.png is their mask). */
.mh-title-shine {
  -webkit-mask: url('../../assets/ui/menu-title.png') 0 0 / 100% 100%; mask: url('../../assets/ui/menu-title.png') 0 0 / 100% 100%;
  background: linear-gradient(102deg, transparent 42%, rgba(255,255,255,.95) 50%, transparent 58%) 0 0 / 320% 100% no-repeat;
  animation: mh-title 7s ease-in-out 1.1s infinite;
}
@keyframes mh-title { 0% { background-position: 100% 0; } 22%, 100% { background-position: 0 0; } }

.mh-play { border-radius: 999px; }
.mh-play .cut { animation: mh-pulse 2.4s ease-in-out infinite; }
@keyframes mh-pulse { 50% { transform: scale(1.022); } }
.mh-pill { border-radius: 999px; overflow: hidden; pointer-events: none; animation: mh-pulse 2.4s ease-in-out infinite; }
.mh-shine {
  position: absolute; inset: 0; background: linear-gradient(105deg, transparent 32%, rgba(255,255,255,.7) 47%, rgba(255,255,255,.15) 55%, transparent 64%);
  transform: translateX(-110%); animation: mh-shine 4.5s ease-in-out 1.3s infinite;
}
@keyframes mh-shine { 0%, 60% { transform: translateX(-110%); } 84%, 100% { transform: translateX(110%); } }
.mh-aura {
  border-radius: 999px; pointer-events: none; mix-blend-mode: screen;
  box-shadow: 0 0 calc(var(--k) * 34) calc(var(--k) * 10) rgba(150,255,150,.55), inset 0 0 calc(var(--k) * 26) rgba(220,255,210,.5);
  opacity: .45; animation: mh-aura 2.4s ease-in-out infinite;
}
@keyframes mh-aura { 0%, 100% { opacity: .15; transform: scale(.985); } 50% { opacity: .9; transform: scale(1.025); } }
.mh-play:active .mh-aura { opacity: 1; animation: none; }

.mh-row { border-radius: calc(var(--k) * 30); }
.mh-row b { color: #fffff3; -webkit-text-stroke: calc(var(--k) * 5) #170400; text-shadow: 0 calc(var(--k) * 2.5) 0 rgba(20,6,0,.7); }
.mh-row small { font-weight: 500; color: #fffff8; -webkit-text-stroke: calc(var(--k) * 3) #060000; text-shadow: 0 calc(var(--k) * 1.5) 0 rgba(10,2,0,.6); }
.mh-card { border-radius: calc(var(--k) * 26); }
#menu-trials-note { color: #fffffa; -webkit-text-stroke: calc(var(--k) * 4) #010302; text-shadow: 0 calc(var(--k) * 1.5) 0 rgba(0,0,0,.6); }
/* Rows and the card catch the light now and then. */
.mh-row .mh-in::after, .mh-card .mh-in::after {
  content: ''; position: absolute; inset: 6% 2%; border-radius: inherit; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(105deg, transparent 35%, rgba(255,236,190,.22) 50%, transparent 65%) 0 0 / 300% 100% no-repeat;
  animation: mh-gleam 9s ease-in-out 2.2s infinite;
}
.mh-card .mh-in::after { animation-delay: 2.6s; }
@keyframes mh-gleam { 0% { background-position: 100% 0; } 16%, 100% { background-position: 0 0; } }

/* ---- Daily gift ------------------------------------------------------- */
.mh-daily { border-radius: calc(var(--k) * 12) calc(var(--k) * 12) 40% 40%; }
.mh-gift { pointer-events: none; }
.mh-daily.ready .mh-gift .cut { transform-origin: 50% 85%; animation: mh-gift 2.8s ease-in-out infinite; }
@keyframes mh-gift { 0%, 62%, 100% { transform: none; } 68% { transform: translateY(-7%) rotate(-7deg) scale(1.1); } 76% { transform: translateY(0) rotate(5deg) scale(1.04); } 84% { transform: rotate(-2deg); } }
.mh-daily.ready::before {
  content: ''; position: absolute; left: -30%; right: -30%; top: 2%; bottom: 10%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
  background: radial-gradient(closest-side, rgba(255,226,140,.55), rgba(255,226,140,0)); opacity: .6; animation: mh-glow 2.2s ease-in-out infinite;
}
@keyframes mh-glow { 0%, 100% { opacity: .35; transform: scale(.92); } 50% { opacity: 1; transform: scale(1.04); } }
.mh-daily-tag {
  display: flex; align-items: center; justify-content: center; border-radius: 999px; font-size: calc(var(--fs) * var(--k)); color: #ffeec4; transform-origin: 50% 0;
  background: linear-gradient(#3f6b33, #1f4220); box-shadow: inset 0 0 0 calc(var(--k) * 3) #d9ac4a, 0 calc(var(--k) * 4) calc(var(--k) * 8) rgba(0,0,0,.45);
  text-shadow: 0 calc(var(--k) * 1.5) 0 rgba(0,0,0,.5);
}
.mh-daily.ready .mh-daily-tag { display: none; }

/* ---- Dock -------------------------------------------------------------- */
.mh-tile { border-radius: calc(var(--k) * 28); }
.mh-glint { position: absolute; inset: 6% 8% 22%; border-radius: calc(var(--k) * 20); overflow: hidden; pointer-events: none; mix-blend-mode: screen; }
.mh-glint::after {
  content: ''; position: absolute; inset: -20% -60%; background: linear-gradient(105deg, transparent 40%, rgba(255,240,200,.55) 50%, transparent 60%);
  transform: translateX(-80%); animation: mh-glint 8s ease-in-out calc(1s + var(--i) * .12s) infinite;
}
@keyframes mh-glint { 0% { transform: translateX(-80%); } 12%, 100% { transform: translateX(80%); } }
.mh-tile:active .mh-in { transform: scale(1.07) translateY(-2%); }

/* The centre emblem fans out the extras. */
.mh-more { z-index: 2; }
.mh-emblem { position: absolute; inset: 0; border-radius: 50%; }
.mh-emblem .cut { transition: transform .45s var(--spring); }
.mh-emblem::after {
  content: ''; position: absolute; inset: 16%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
  box-shadow: 0 0 calc(var(--k) * 26) calc(var(--k) * 8) rgba(255,214,120,.4); opacity: 0; animation: mh-soft 3.4s ease-in-out infinite;
}
@keyframes mh-soft { 50% { opacity: 1; } }
.mh-more.open .mh-emblem .cut { transform: rotate(90deg) scale(1.06); }
.mh-more.open .mh-emblem .badge { opacity: 0; }
.mh-fan { position: absolute; left: 50%; top: 50%; width: 0; height: 0; --R: max(84px, calc(var(--k) * 200)); }
.mh-fan-item {
  position: absolute; left: 0; top: 0; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 0; border: 0; background: none;
  transform: translate(-50%, -50%) scale(.2); opacity: 0; visibility: hidden;
  transition: transform .35s var(--ease-out), opacity .2s, visibility 0s .35s;
}
.mh-more.open .mh-fan-item {
  transform: translate(-50%, -50%) translate(calc(var(--cx) * var(--R)), calc(var(--cy) * var(--R) - var(--R) * .3)) scale(1); opacity: 1; visibility: visible;
  transition: transform .5s var(--spring) calc(var(--i) * .05s), opacity .2s calc(var(--i) * .05s), visibility 0s;
}
.mh-fan-face {
  --f: max(44px, calc(var(--k) * 96));
  display: flex; align-items: center; justify-content: center; width: var(--f); height: var(--f); border-radius: 50%; color: #ffe39a;
  background: radial-gradient(circle at 50% 30%, #3e5a3e, #1d321f 70%);
  box-shadow: inset 0 0 0 max(2px, calc(var(--k) * 4)) #c48a4c, 0 0 0 2px #2e1a0a, 0 6px 14px rgba(0,0,0,.5);
}
.mh-fan-face .mi { width: 58%; height: 58%; display: flex; filter: drop-shadow(0 2px 0 rgba(0,0,0,.4)); }
.mh-fan-face .mi svg { width: 100%; height: 100%; }
.mh-fan-item small {
  padding: 1px 8px 2px; border-radius: 8px; font-size: max(11px, calc(var(--k) * 21)); font-weight: 700; color: var(--cream); white-space: nowrap;
  background: linear-gradient(#7a4a24, #4e2c12); box-shadow: 0 0 0 1.5px #2e1a0a, 0 2px 4px rgba(0,0,0,.4);
}
.mh-fan-item:active .mh-fan-face { transform: scale(.9); }
.mh-fan-item .badge { top: -4px; right: -2px; }

/* Notification badges. */
.menu .badge {
  position: absolute; z-index: 2; top: 0; right: 2%; min-width: max(18px, calc(var(--k) * 36)); height: max(18px, calc(var(--k) * 36)); padding: 0 4px;
  display: grid; place-items: center; border-radius: 999px; font-style: normal; font-size: max(10px, calc(var(--k) * 20)); font-weight: 700; color: #fff; font-variant-numeric: tabular-nums;
  background: linear-gradient(#ff7a5c, #d6402a); border: 2px solid #fff; box-shadow: 0 2px 0 #7a1d10, 0 3px 8px rgba(0,0,0,.35); animation: mh-badge 2.8s ease-in-out infinite;
}
.menu .badge[hidden] { display: none; }
.mh-daily .badge { top: 8%; right: 0; }
.mh-emblem .badge { top: 0; right: 0; }
@keyframes mh-badge { 0%, 80%, 100% { transform: scale(1); } 86% { transform: scale(1.25); } 92% { transform: scale(.95); } }

/* ---- The cast ---------------------------------------------------------- */
/* The ellipse is the tap target; the copy inside breathes and hops. */
.mh-actor { border-radius: 50%; pointer-events: auto; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.mh-actor .cut {
  -webkit-mask-image: radial-gradient(closest-side, #000 58%, transparent 98%); mask-image: radial-gradient(closest-side, #000 58%, transparent 98%);
  transform-origin: 50% 90%; animation: mh-breathe calc(3.4s + var(--i) * .35s) ease-in-out calc(var(--i) * -.8s) infinite;
}
@keyframes mh-breathe { 50% { transform: scale(1.005, 1.014); } }
.mh-actor.hop .cut { animation: mh-hop .65s var(--spring); }
.mh-actor.fidget .cut { animation: mh-fidget 1s ease-in-out; }
@keyframes mh-hop { 0% { transform: scale(1.05, .97); } 35% { transform: translateY(-2.5%) scale(.985, 1.06); } 70% { transform: scale(1.03, .99); } 100% { transform: none; } }
@keyframes mh-fidget { 0%, 100% { transform: rotate(0); } 30% { transform: rotate(-1.4deg) scale(1.01); } 65% { transform: rotate(1.1deg); } }
@media (hover: hover) and (pointer: fine) {
  .mh-actor:hover .cut { filter: brightness(1.07); }
}
.mh-bubble {
  position: absolute; z-index: 3; left: 50%; top: 4%; padding: .45em .8em; border-radius: 1em; white-space: nowrap; pointer-events: none;
  font-size: max(12px, calc(var(--k) * 26)); font-weight: 700; color: #3a2410; background: #fff8e6; border: 2px solid #c48a4c;
  box-shadow: 0 3px 0 rgba(46,26,10,.35), 0 8px 18px rgba(0,0,0,.3);
  --bx: -50%; --by: -100%; transform: translate(var(--bx), var(--by)); animation: mh-bubble 2.1s var(--spring) forwards;
}
.mh-bubble::after { content: ''; position: absolute; left: 50%; top: 100%; margin-left: -7px; border: 7px solid transparent; border-top-color: #c48a4c; }
.mh-bubble.side { left: 88%; top: 44%; --bx: 0%; --by: -50%; }
.mh-bubble.side::after { left: auto; right: 100%; top: 50%; margin: -7px 0 0; border-top-color: transparent; border-right-color: #c48a4c; }
@keyframes mh-bubble {
  0% { opacity: 0; transform: translate(var(--bx), calc(var(--by) + 40%)) scale(.5); }
  14% { opacity: 1; transform: translate(var(--bx), var(--by)) scale(1); }
  82% { opacity: 1; transform: translate(var(--bx), var(--by)); }
  100% { opacity: 0; transform: translate(var(--bx), calc(var(--by) - 30%)); }
}
.mh-heart { position: absolute; z-index: 3; left: 50%; top: 20%; width: max(14px, calc(var(--k) * 30)); aspect-ratio: 1; pointer-events: none; color: #ff7a8a; animation: mh-heart 1.3s ease-out forwards; }
.mh-heart svg { width: 100%; height: 100%; filter: drop-shadow(0 2px 0 rgba(120,20,40,.35)); }
@keyframes mh-heart { from { opacity: 1; transform: translate(-50%, 0) scale(.4); } to { opacity: 0; transform: translate(calc(-50% + var(--dx)), -260%) scale(1.1) rotate(var(--r)); } }

/* ---- Light and air ----------------------------------------------------- */
.mh-light > * { pointer-events: none; }
/* Lantern glow: a soft flicker and swell over each flame. */
.mh-glow {
  border-radius: 50%; mix-blend-mode: screen;
  background: radial-gradient(closest-side, rgba(255,214,130,.42), rgba(255,170,70,.16) 48%, rgba(255,170,70,0));
  animation: mh-flicker 3.2s steps(1) var(--d, 0s) infinite, mh-swell 4.6s ease-in-out var(--d, 0s) infinite alternate;
}
@keyframes mh-flicker { 0% { opacity: 1; } 12% { opacity: .78; } 18% { opacity: 1; } 47% { opacity: .88; } 52% { opacity: 1; } 78% { opacity: .74; } 83% { opacity: .95; } }
@keyframes mh-swell { from { transform: scale(.9); } to { transform: scale(1.08); } }
/* Sun shafts through the canopy windows. */
.mh-rays { overflow: hidden; mix-blend-mode: screen; }
.mh-rays i {
  position: absolute; top: -30%; height: 160%; width: 9%; left: var(--l); transform-origin: 50% 0; transform: rotate(28deg);
  background: linear-gradient(rgba(255,244,200,.34), rgba(255,226,150,.12) 55%, rgba(255,226,150,0) 85%);
  filter: blur(calc(var(--k) * 4)); opacity: .5; animation: mh-ray 9s ease-in-out infinite alternate;
}
.mh-rays i:nth-child(1) { --l: 30%; }
.mh-rays i:nth-child(2) { --l: 52%; width: 6%; animation-delay: -3s; animation-duration: 11s; }
.mh-rays i:nth-child(3) { --l: 72%; width: 12%; animation-delay: -6s; }
.mh-rays i:nth-child(4) { --l: 90%; width: 5%; animation-delay: -1.5s; animation-duration: 13s; }
@keyframes mh-ray { 0% { opacity: .2; } 50% { opacity: .75; } 100% { opacity: .35; } }
/* The waterfall keeps falling. */
.mh-falls {
  mix-blend-mode: screen; opacity: .55;
  background: repeating-linear-gradient(180deg, rgba(255,255,255,0) 0, rgba(255,255,255,.4) 7%, rgba(255,255,255,0) 14%) 0 0 / 100% 200%;
  -webkit-mask-image: radial-gradient(closest-side, #000 40%, transparent); mask-image: radial-gradient(closest-side, #000 40%, transparent);
  animation: mh-falls 1.4s linear infinite;
}
@keyframes mh-falls { to { background-position: 0 100%; } }

/* Motes and falling leaves. */
.mh-air { overflow: hidden; }
.mh-motes i {
  position: absolute; left: var(--x, 50%); bottom: -3%; width: max(4px, calc(var(--k) * 8)); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, #fffbe0, rgba(255,214,110,.9) 40%, rgba(255,214,110,0) 72%); opacity: 0;
  animation: mh-mote var(--t, 14s) linear var(--d, 0s) infinite;
}
.mh-motes i:nth-child(1) { --x: 42%; --t: 15s; --d: -2s; }
.mh-motes i:nth-child(2) { --x: 55%; --t: 12s; --d: -8s; }
.mh-motes i:nth-child(3) { --x: 63%; --t: 17s; --d: -4s; }
.mh-motes i:nth-child(4) { --x: 71%; --t: 13s; --d: -11s; }
.mh-motes i:nth-child(5) { --x: 78%; --t: 16s; --d: -6s; }
.mh-motes i:nth-child(6) { --x: 86%; --t: 14s; --d: -1s; }
.mh-motes i:nth-child(7) { --x: 92%; --t: 18s; --d: -13s; }
.mh-motes i:nth-child(8) { --x: 48%; --t: 19s; --d: -15s; width: max(3px, calc(var(--k) * 5)); }
.mh-motes i:nth-child(9) { --x: 60%; --t: 11s; --d: -3s; width: max(3px, calc(var(--k) * 5)); }
.mh-motes i:nth-child(10) { --x: 67%; --t: 20s; --d: -9s; }
.mh-motes i:nth-child(11) { --x: 82%; --t: 12s; --d: -7s; width: max(3px, calc(var(--k) * 5)); }
.mh-motes i:nth-child(12) { --x: 97%; --t: 15s; --d: -12s; }
.mh-motes i:nth-child(13) { --x: 36%; --t: 16s; --d: -5s; }
.mh-motes i:nth-child(14) { --x: 74%; --t: 22s; --d: -17s; width: max(5px, calc(var(--k) * 11)); }
@keyframes mh-mote {
  0% { opacity: 0; transform: translate(0, 0); } 10% { opacity: .9; }
  35% { transform: translate(-3cqw, -38cqh); } 60% { opacity: .75; transform: translate(2cqw, -66cqh); }
  90% { opacity: .5; } 100% { opacity: 0; transform: translate(-2cqw, -104cqh); }
}
.mh-leaves i {
  position: absolute; top: -3%; width: max(9px, calc(var(--k) * 22)); aspect-ratio: 13 / 8; border-radius: 0 100% 0 100%; opacity: .9;
  background: linear-gradient(135deg, #b9e36a, #4f8f2b); animation: mh-leaf 18s linear infinite;
}
.mh-leaves i:nth-child(1) { left: 44%; animation-delay: -2s; }
.mh-leaves i:nth-child(2) { left: 52%; animation-duration: 16s; animation-delay: -9s; background: linear-gradient(135deg, #f2c14e, #c9792b); }
.mh-leaves i:nth-child(3) { left: 61%; animation-duration: 19s; animation-delay: -5s; }
.mh-leaves i:nth-child(4) { left: 70%; animation-duration: 15s; animation-delay: -12s; background: linear-gradient(135deg, #e88a4a, #b04a22); }
.mh-leaves i:nth-child(5) { left: 78%; animation-delay: -7s; }
.mh-leaves i:nth-child(6) { left: 86%; animation-duration: 17s; animation-delay: -1s; background: linear-gradient(135deg, #f2c14e, #c9792b); }
.mh-leaves i:nth-child(7) { left: 94%; animation-duration: 12s; animation-delay: -10s; }
.mh-leaves i:nth-child(8) { left: 8%; animation-duration: 21s; animation-delay: -14s; }
.mh-leaves i:nth-child(9) { left: 30%; animation-duration: 14s; animation-delay: -4s; background: linear-gradient(135deg, #f2c14e, #c9792b); }
@keyframes mh-leaf {
  0% { transform: translate(0, 0) rotate(0); }
  25% { transform: translate(2cqw, 28cqh) rotate(140deg); }
  50% { transform: translate(-1cqw, 56cqh) rotate(250deg); }
  75% { transform: translate(2cqw, 84cqh) rotate(390deg); }
  100% { transform: translate(0, 110cqh) rotate(520deg); }
}

/* Twinkles: a four-point glint now and then on the gold and the map. */
.mh-tw {
  opacity: 0; transform: scale(0); mix-blend-mode: screen;
  background: radial-gradient(closest-side, #fff, rgba(255,240,180,.85) 35%, rgba(255,226,150,.4) 70%, transparent);
  -webkit-mask: radial-gradient(closest-side, #000 18%, transparent 30%), linear-gradient(90deg, transparent 46%, #000 50%, transparent 54%), linear-gradient(transparent 46%, #000 50%, transparent 54%);
  mask: radial-gradient(closest-side, #000 18%, transparent 30%), linear-gradient(90deg, transparent 46%, #000 50%, transparent 54%), linear-gradient(transparent 46%, #000 50%, transparent 54%);
  animation: mh-tw 6s ease-in-out var(--d, 0s) infinite;
}
@keyframes mh-tw { 0%, 70%, 100% { opacity: 0; transform: scale(0) rotate(0); } 78% { opacity: 1; transform: scale(1) rotate(30deg); } 88% { opacity: 0; transform: scale(.3) rotate(60deg); } }

/* Leaves that burst out of Play. */
.mh-fx { position: absolute; inset: 0; z-index: 8; pointer-events: none; }
.mh-fx i {
  position: absolute; width: max(10px, calc(var(--k) * 24)); aspect-ratio: 13 / 8; margin: -4px 0 0 -6px; border-radius: 0 100% 0 100%;
  background: linear-gradient(135deg, #c3ea72, #4f8f2b); animation: mh-burst .8s cubic-bezier(.2, .7, .3, 1) forwards;
}
.mh-fx i:nth-child(3n) { background: linear-gradient(135deg, #ffe08a, #e9a33e); }
@keyframes mh-burst { from { transform: translate(0, 0) rotate(0) scale(.6); opacity: 1; } to { transform: translate(var(--dx), var(--dy)) rotate(var(--r)) scale(1); opacity: 0; } }

.menu .ver { position: absolute; z-index: 4; right: calc(6px + var(--safe-r)); bottom: calc(2px + var(--safe-b)); font-size: 9px; color: rgba(255,255,255,.45); text-shadow: 0 1px 2px rgba(0,0,0,.6); pointer-events: none; }

/* ---- Pointer and screen variants --------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  .mh-btn:hover .mh-in { transform: scale(1.02); filter: brightness(1.08); }
  .mh-tile:hover .mh-in { transform: scale(1.04) translateY(-1.5%); }
  .mh-gear:hover .cut { transform: rotate(22deg); }
  .mh-knob:hover { transform: scale(1.08); }
}
/* Small screens: the account chip and online dot keep the status slot to themselves. */
@media (max-height: 560px), (max-width: 760px) {
  #offline-status { display: none; }
}
