/* ---------- screen companions (js/companions.js) ---------- */
/* Two layers: a fixed one for the companions on the grass, and one that
   scrolls with the page for those on the panels. Only the companions catch
   clicks; the page underneath stays usable. Above the panels, below the left
   column (28), the menu panel (30) and toasts (40). */
.companions {
  position: fixed; inset: 0; z-index: 25; overflow: hidden;
  pointer-events: none;
}
.companions-page {
  position: absolute; inset: auto; left: 0; top: 0; width: 100%; height: 0;
  overflow: visible; overflow-x: clip;
}
.companions[hidden] { display: none; }

/* A companion: its feet are at the element's origin; --h / --half are its size */
.buddy {
  position: absolute; left: 0; top: 0; width: 0; height: 0;
  pointer-events: none; outline: none; touch-action: none;
  transition: opacity 0.4s;
  --u: 4px;
}
.buddy.leaving { opacity: 0; }
.buddy.held { z-index: 1; }
/* The clickable area: the companion's body */
.buddy::before {
  content: ""; position: absolute; left: calc(var(--half) * -1); top: calc(var(--h) * -1);
  width: calc(var(--half) * 2); height: var(--h);
  pointer-events: auto; cursor: grab;
}
.buddy.held::before { cursor: grabbing; }
.buddy:focus-visible::before { box-shadow: 0 0 0 2px var(--gold); border-radius: 8px; }
.buddy .squash, .buddy .mv { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.buddy .spr { position: absolute; image-rendering: pixelated; pointer-events: none; }
.buddy .shadow {
  position: absolute; left: calc(var(--half) * -1.1); top: -6px; width: calc(var(--half) * 2.2); height: 10px;
  border-radius: 50%; background: radial-gradient(closest-side, var(--shadow), transparent);
  transition: opacity 0.2s;
}
.buddy.airborne .shadow { opacity: 0; }
/* Mascots without their own walk hop along; held ones wriggle */
.buddy .mv.css-hop { animation: hop 0.9s infinite; }
.buddy .mv.css-wriggle { animation: wriggle 0.22s ease-in-out infinite; }
/* Name tag, like the one above players in game: shown on hover or focus */
.buddy .tag {
  position: absolute; left: 0; bottom: calc(var(--h) + 8px); transform: translateX(-50%);
  padding: 1px 6px; white-space: nowrap;
  font: 15.5px var(--font-mono); color: #fff; background: rgba(0, 0, 0, 0.45); border-radius: 2px;
  opacity: 0; transition: opacity 0.15s; pointer-events: none;
}
/* Light theme: a light tag with dark text, readable on the day sky */
:root[data-theme-now="light"] .buddy .tag { color: #1f2a2a; background: rgba(255, 255, 255, 0.85); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); }
.buddy:hover .tag, .buddy:focus-visible .tag, .buddy.held .tag { opacity: 1; }
.buddy .bubble {
  left: 0; top: auto; bottom: calc(var(--h) + 14px); max-width: 220px; font-size: 13.5px;
  white-space: normal; overflow-wrap: anywhere; text-wrap: balance; /* long lines wrap inside the bubble */
}
.buddy:has(.bubble.show) .tag { opacity: 0; }

/* A server mascot asleep while its server restarts: floating z z Z */
.zzz { position: absolute; left: 10px; bottom: calc(var(--h) * 0.7); display: none; pointer-events: none; font: 700 15.5px var(--font-mono); color: #fff; text-shadow: 2px 2px 0 #3f3f3f; }
.buddy.asleep .zzz { display: block; }
.zzz span { position: absolute; left: 0; bottom: 0; opacity: 0; animation: zzz 3s ease-in infinite; }
.zzz span:nth-child(2) { animation-delay: 1s; font-size: 19.5px; }
.zzz span:nth-child(3) { animation-delay: 2s; font-size: 23.5px; }
@keyframes zzz {
  0% { opacity: 0; transform: translate(0, 0); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translate(18px, -42px); }
}

/* ---------- particles: vanilla particle textures (packs/vanilla) ---------- */
.walker-fx {
  position: absolute; left: -8px; top: -8px; width: 16px; height: 16px;
  background: center / 100% no-repeat; image-rendering: pixelated; pointer-events: none;
  animation: walker-fx var(--t, 0.8s) ease-out forwards;
}
@keyframes walker-fx {
  from { transform: translate(var(--x0), var(--y0)); opacity: 1; }
  to { transform: translate(var(--x1), var(--y1)); opacity: 0; }
}
.walker-fx.smoke { left: -10px; top: -10px; width: 20px; height: 20px; opacity: 0.8; }
.walker-fx.splash { left: -6px; top: -6px; width: 12px; height: 12px; }
.walker-fx.portal { filter: sepia(1) hue-rotate(230deg) saturate(6) brightness(0.9); }
.walker-fx.crumb, .walker-fx.chip { left: -2px; top: -2px; width: 4px; height: 4px; background-size: 32px; animation-timing-function: ease-in; }
.walker-fx.zzz { width: auto; height: auto; font: 700 15.5px var(--font-mono); color: #fff; text-shadow: 2px 2px 0 #3f3f3f; }

/* ---------- candy (the trick-or-treat event), dirt pillars ---------- */
.walker-candy {
  position: absolute; left: 0; top: 0; width: 24px; height: 24px;
  background: center / 100% no-repeat; image-rendering: pixelated; pointer-events: none;
}
/* Held up to the mouth while eating: bobs with the chewing, eaten bite by bite */
.held-candy {
  position: absolute; width: 20px; height: 20px; z-index: 1; pointer-events: none;
  background: center / 100% no-repeat; image-rendering: pixelated;
  animation: chew 0.4s ease-in-out infinite, candy-eaten 1.6s steps(4) forwards;
}
@keyframes chew { 50% { translate: 0 -2px; } }
@keyframes candy-eaten { to { clip-path: inset(0 0 0 100%); } }
.walker-block {
  position: absolute; left: 0; top: 0; width: 28px; height: 28px;
  background: center / 100% no-repeat; image-rendering: pixelated; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
}
/* ---------- TNT ---------- */
/* The 奇比 switch: they drink an invisibility potion and fade away, or shimmer back */
.buddy.vanish { opacity: 0; transition: opacity 0.8s ease-in; }
.buddy.unvanish { animation: unvanish 0.9s ease-out; }
@keyframes unvanish { from { opacity: 0; } }
.walker-fx.effect { left: -6px; top: -6px; width: 12px; height: 12px; opacity: 0.85; animation-duration: 1.2s; }
/* A companion that hasn't made its entrance yet */
.buddy.unseen { visibility: hidden; }
/* Held things: a water bucket, an empty bucket */
.held-item {
  position: absolute; width: 20px; height: 20px; z-index: 1; pointer-events: none;
  background: center / 100% no-repeat; image-rendering: pixelated;
}
/* Water placed from a bucket (biome-blue, animated like the game's water) */
.walker-water {
  position: absolute; left: 0; top: 0; width: 56px; height: 24px; z-index: 1; pointer-events: none; opacity: 0.8;
  background: #3f76e4 0 0 / 28px 896px repeat; background-blend-mode: multiply; image-rendering: pixelated;
  animation: water-flow 2s steps(32) infinite, water-in 0.15s ease-out; transform-origin: 50% 100%;
  transition: scale 0.3s ease-in, opacity 0.3s;
}
.walker-water.gone { scale: 1 0; opacity: 0; }
@keyframes water-flow { to { background-position: 0 -896px; } }
@keyframes water-in { from { scale: 1 0; } }
/* Team entrances: the happy ghast, an ender pearl, a lightning bolt */
.walker-ghast { position: absolute; left: 0; top: 0; width: 0; height: 0; z-index: -1; pointer-events: none; transition: opacity 0.7s; }
.walker-ghast .squash, .walker-ghast .mv { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.walker-ghast .spr { position: absolute; image-rendering: pixelated; }
.walker-ghast.gone { opacity: 0; }
.walker-pearl { position: absolute; left: 0; top: 0; width: 16px; height: 16px; pointer-events: none; background: center / 100% no-repeat; image-rendering: pixelated; }
.walker-bolt { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.walker-bolt polyline {
  fill: none; stroke: #f4f6ff; stroke-width: 4; stroke-linejoin: miter;
  filter: drop-shadow(0 0 6px #9fb6ff) drop-shadow(0 0 14px #6a7dff);
  animation: bolt 0.45s steps(3) forwards;
}
@keyframes bolt { 0%, 40% { opacity: 1; } 60% { opacity: 0.2; } 80% { opacity: 1; } 100% { opacity: 0; } }
.walker-skyflash { position: absolute; inset: 0; background: rgba(230, 236, 255, 0.45); pointer-events: none; animation: skyflash 0.45s ease-out forwards; }
@keyframes skyflash { to { opacity: 0; } }
/* Lit TNT flashes white, like primed TNT in game */
.walker-tnt, .held-tnt {
  position: absolute; width: 24px; height: 24px; pointer-events: none;
  background: center / 100% no-repeat; image-rendering: pixelated;
  animation: tnt-lit 0.5s steps(1) infinite;
}
.walker-tnt { left: 0; top: 0; }
.held-tnt { z-index: 1; }
.walker-tnt.landed { animation: tnt-lit 0.5s steps(1) infinite, tnt-swell 2.2s ease-in forwards; transform-origin: 50% 100%; }
@keyframes tnt-lit { 50% { filter: brightness(2.6) saturate(0.2); } }
@keyframes tnt-swell { 80% { scale: 1; } 100% { scale: 1.25; } }
.walker-flash {
  position: absolute; left: 0; top: 0; width: 160px; height: 160px; pointer-events: none; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.95), rgba(255, 236, 170, 0.6) 55%, transparent);
  animation: walker-flash 0.4s ease-out forwards;
}
@keyframes walker-flash { from { scale: 0.2; } to { scale: 1.3; opacity: 0; } }
.walker-fx.boom { left: -20px; top: -20px; width: 40px; height: 40px; animation-duration: 0.7s; }

/* ---------- fishing ---------- */
.walker-rod { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.walker-rod-line { position: absolute; width: 1px; background: rgba(30, 30, 30, 0.75); }
.walker-rod-bob {
  position: absolute; width: 6px; height: 6px;
  background: linear-gradient(#e43b3b 50%, #fff 50%); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
  animation: bob-float 1.6s ease-in-out infinite;
}
.walker-rod.bite .walker-rod-bob { animation: bob-bite 0.25s ease-in-out infinite; }
@keyframes bob-float { 50% { transform: translateY(2px); } }
@keyframes bob-bite { 50% { transform: translateY(6px); } }
.walker-rod-pole { position: absolute; width: 24px; height: 24px; background: center / 100% no-repeat; image-rendering: pixelated; }
.walker-rod.flip .walker-rod-pole { transform: scaleX(-1); }
.walker-catch {
  position: absolute; width: 28px; height: 28px; pointer-events: none;
  background: center / 100% no-repeat; image-rendering: pixelated;
  transition: left 0.6s cubic-bezier(0.3, 1.4, 0.5, 1), top 0.6s cubic-bezier(0.3, -0.6, 0.6, 1), opacity 0.4s;
}
.walker-catch.gone { opacity: 0; }
.walker-catch-name {
  position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%); white-space: nowrap;
  font: 13.5px var(--font-mono); text-shadow: 2px 2px 0 #3f3f3f;
}

/* ---------- something picked up off the page ---------- */
.walker-prop {
  z-index: 1; pointer-events: none;
  transition: left 0.45s ease, top 0.45s ease, transform 0.45s ease;
}
.walker-prop.lifted { transform: rotate(-4deg); }
.walker-prop.flung { animation: flung 0.5s ease-out; }
@keyframes flung { 30% { transform: translateY(-24px) rotate(25deg); } }

@media (max-width: 560px) {
  .walker-block { width: 21px; height: 21px; }
  .walker-water { width: 42px; height: 18px; background-size: 21px 672px; }
  @keyframes water-flow { to { background-position: 0 -672px; } }
}

/* ---------- social media Monbos peeking in from the right edge (js/socials.js) ---------- */
.socials {
  position: fixed; z-index: 26; right: 0; top: calc(var(--topbar-h, 65px) + 18px);
  display: flex; flex-direction: column; align-items: flex-end; gap: 16px; pointer-events: none;
}
/* Peeking from behind the edge: the Monbo stands just past the edge, tilted over so its head
   leans into the window (--H = its height, js/socials.js); pointed at, it leans out further */
.social {
  --H: 64px;
  position: relative; display: block; width: calc(var(--H) * 1.15); height: calc(var(--H) * 1.15);
  pointer-events: auto; outline: none;
}
/* The Monbo's feet are at this point (like .buddy), just outside the window */
.social-feet {
  position: absolute; left: calc(100% + var(--H) * 0.14); bottom: calc(var(--H) * 0.08); width: 0; height: 0;
  rotate: -58deg; transition: rotate 0.25s ease;
}
.social:hover .social-feet, .social:focus-visible .social-feet { rotate: -44deg; }
.social-feet .squash, .social-feet .mv { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.social-feet .spr { position: absolute; image-rendering: pixelated; pointer-events: none; }
/* The speech bubble with the platform's icon, always shown, to the Monbo's left */
.social-bubble {
  position: absolute; right: calc(100% - var(--H) * 0.15); top: calc(var(--H) * -0.05);
  display: grid; place-items: center; padding: 5px; border-radius: 10px;
  background: #fff; box-shadow: 0 2px 0 rgba(0, 0, 0, 0.18); transition: scale 0.15s;
}
.social-bubble::after {
  content: ""; position: absolute; left: 100%; top: 50%; translate: 0 -50%;
  border: 6px solid transparent; border-left-color: #fff; border-right: 0;
}
.social-bubble svg { display: block; width: 24px; height: 24px; }
.social:hover .social-bubble, .social:focus-visible .social-bubble { scale: 1.15; }
.social:focus-visible .social-bubble { outline: 2px solid var(--gold); outline-offset: 2px; }
/* Folded (js/socials.js): one Monbo, its bubble cycling through the platforms; the five sit
   stacked behind it until it's clicked, then fan out below it (it stays, a click folds them again) */
.social-hub { padding: 0; border: 0; background: none; font: inherit; cursor: pointer; transition: opacity 0.2s; }
.social-hub .social-bubble { width: 24px; height: 24px; box-sizing: content-box; }
.hub-icon { position: absolute; inset: 5px; opacity: 0; transition: opacity 0.35s; }
.hub-icon.on { opacity: 1; }
.socials > a.social {
  margin-top: calc(var(--H) * -1.15 - 16px); /* stacked on the one above: all behind the folded Monbo */
  opacity: 0; visibility: hidden; translate: 30px 0;
  transition: margin-top 0.3s ease, opacity 0.2s, translate 0.3s ease, visibility 0.3s;
}
.socials.open > a.social {
  margin-top: 0; opacity: 1; visibility: visible; translate: 0 0; transition-delay: calc(var(--i) * 40ms);
}
@media (max-width: 560px) {
  .socials { gap: 10px; }
  .socials > a.social { margin-top: calc(var(--H) * -1.15 - 10px); }
  .social-bubble { right: calc(100% - var(--H) * 0.2); }
  .social-bubble { padding: 4px; }
  .social-bubble svg { width: 18px; height: 18px; }
}
