/* ============ World map ============ */
.viewport { position: absolute; inset: 0; overflow: hidden; touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.viewport.is-panning { cursor: grabbing; }
.viewport:focus { outline: none; }
.viewport:focus-visible { box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 6px rgba(58,37,80,.5); }
/* The whole island moves as one GPU layer. */
.world { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; }
.world-svg { position: absolute; overflow: visible; display: block; pointer-events: none; }
.world-svg.is-off { display: none; }
.raster { position: absolute; display: block; pointer-events: none; }
.raster[hidden] { display: none; }
.hl { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.fx-burst { position: absolute; overflow: visible; pointer-events: none; }
.deco, .actors, .glow, .labels, .fx { position: absolute; left: 0; top: 0; width: 0; height: 0; }
.labels { pointer-events: none; }
.isle-label { position: absolute; transform: translate(-50%, -50%) scale(clamp(1, calc(var(--iz, 1) * .8), 2.6)); transform-origin: 50% 50%; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 6px; border-radius: 999px; background: rgba(255,255,255,.94); box-shadow: 0 0 0 1.5px rgba(58,37,80,.22), 0 3px 8px rgba(58,37,80,.15);
  font: 700 13px/1.1 var(--font-display); color: var(--ink); }
.isle-label i { width: 11px; height: 11px; border-radius: 50%; flex: none; }
.map-a11y { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: hidden; }
.deco-item { position: absolute; transform: translate(-50%, -50%); pointer-events: none; }
.deco-item svg { display: block; overflow: visible; }

/* The live island SVG only shows for a moment before its picture is ready: keep it still. */
.world-svg [class*="sq-"]:not(.sq-build):not(.sq-drop), .world-svg .sel-ring { animation: none !important; }

.map-hud { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); z-index: 5; pointer-events: none; }
.map-filters-live { pointer-events: auto; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: center; }
.map-filters-live .chip { background: #fff6d8; box-shadow: var(--shadow-soft); }
.map-fit { position: absolute; right: max(14px, env(safe-area-inset-right, 0px)); bottom: 14px; z-index: 5; }

/* Gentle bobbing for the little islets and clouds: each stays in its own spot. */
.deco-islet { animation: isletBob var(--t, 6s) ease-in-out infinite; animation-delay: calc(var(--d, 0s) * -1); }
@keyframes isletBob { 0%, 100% { transform: translate(-50%, -50%); } 50% { transform: translate(-50%, calc(-50% - var(--a, 6px))); } }
.deco-cloud { animation: cloudBob 9s ease-in-out infinite; animation-delay: calc(var(--d, 0s) * -1); opacity: .95; }
@keyframes cloudBob { 0%, 100% { transform: translate(-50%, -50%); } 50% { transform: translate(calc(-50% + 6px), calc(-50% - 3px)); } }

/* One-off events (these play once, so they're fine inside the island picture) */
.sq-drop { animation: drop .7s var(--ease-pop) both; }
@keyframes drop { 0% { transform: translateY(-80px); opacity: 0; } 60% { opacity: 1; } }
.sq-build { transform-box: fill-box; transform-origin: bottom center; animation: build .9s var(--ease-pop) both; }
@keyframes build { 0% { transform: scale(.2, 0); opacity: 0; } 50% { transform: scale(1.12, 1.15); opacity: 1; } 75% { transform: scale(.96, .94); } 100% { transform: scale(1); } }
.sq-burst-piece { animation: burst 1.3s cubic-bezier(.2,.8,.3,1) both; }
@keyframes burst { 0% { transform: translate(0, -30px) scale(.2); opacity: 0; } 20% { opacity: 1; } 100% { transform: translate(var(--dx), var(--dy)) scale(1); opacity: 0; } }
.sq-plus { animation: plus 1.8s ease-out both; }
@keyframes plus { 0% { transform: translateY(10px); opacity: 0; } 20% { opacity: 1; transform: translateY(0); } 80% { opacity: 1; } 100% { transform: translateY(-24px); opacity: 0; } }

/* Ambient motion used in previews outside the map (cards, popups) */
.sq-bob { animation: bob 2.4s ease-in-out infinite; }
@keyframes bob { 50% { transform: translateY(-5px); } }
.sq-float { animation: float 3.2s ease-in-out infinite; }
@keyframes float { 50% { transform: translateY(-4px); } }
.sq-twinkle { animation: twinkle 2.2s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes twinkle { 50% { opacity: .3; transform: scale(.6); } }
.sq-glow { animation: glow 2.6s ease-in-out infinite; }
@keyframes glow { 50% { opacity: .55; } }
.sq-spin { animation: spin 6s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ============ Sky (follows your clock) ============ */
.sky { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
#app { position: relative; z-index: 1; }
.sky-layer { position: absolute; inset: 0; opacity: 0; transition: opacity 2.4s ease; }
.sky-layer.on { opacity: 1; }
.sky-morning { background: linear-gradient(180deg, #5ec8f5 0%, #8fdcfb 45%, #d3f3ff 100%); }
.sky-evening { background: linear-gradient(180deg, #4b3a8f 0%, #a1528f 30%, #f07a6a 58%, #ffb36b 80%, #ffd99a 100%); }
.sky-night { background: radial-gradient(ellipse at 70% 20%, #2c3d86 0%, transparent 55%), linear-gradient(180deg, #0d1540 0%, #1a2364 45%, #33307a 80%, #4b3a8f 100%); }
.sky-night canvas { position: absolute; inset: 0; }

.sun { position: absolute; left: 62%; top: calc(var(--hud-h) + 24px); width: 110px; height: 110px; border-radius: 50%;
  background: radial-gradient(circle at 42% 40%, #fffbe0, #ffe680 45%, #ffc93c 80%);
  box-shadow: 0 0 60px 24px rgba(255, 236, 150, .65), 0 0 160px 80px rgba(255, 240, 190, .35); }
.sun i { position: absolute; inset: -70%; border-radius: 50%;
  background: repeating-conic-gradient(rgba(255,250,210,.32) 0 7deg, transparent 7deg 22deg);
  -webkit-mask: radial-gradient(circle, transparent 32%, #000 34%, transparent 70%); mask: radial-gradient(circle, transparent 32%, #000 34%, transparent 70%);
  animation: spin 80s linear infinite; }
/* Sunset: a big low-ish sun high enough to see, half tucked behind a bank of pink clouds. */
.sunset-sun { position: absolute; left: 66%; top: calc(var(--hud-h) + 30px); width: 150px; height: 150px; margin-left: -75px; border-radius: 50%;
  background: radial-gradient(circle at 50% 42%, #fff6d2, #ffd27a 38%, #ff9a5c 72%, #ff7a5a 100%);
  box-shadow: 0 0 60px 26px rgba(255, 170, 110, .5), 0 0 180px 90px rgba(255, 130, 120, .22); }
.sunset-glow { position: absolute; inset: auto 0 0 0; height: 50%; background: linear-gradient(0deg, rgba(255,210,150,.5), transparent); }
.ss-cloud { position: absolute; display: block; height: auto; filter: drop-shadow(0 4px 6px rgba(140, 60, 90, .18)); }
.ss-cloud.c1 { left: calc(66% - 150px); top: calc(var(--hud-h) + 128px); }
.ss-cloud.c2 { left: calc(66% + 10px); top: calc(var(--hud-h) + 150px); }
.ss-cloud.c3 { left: calc(66% - 40px); top: calc(var(--hud-h) + 92px); opacity: .9; }
.moon { position: absolute; left: 62%; top: calc(var(--hud-h) + 24px); width: 74px; height: 74px; border-radius: 50%;
  background: radial-gradient(circle at 38% 38%, #fffbe8, #f2ecc8 60%, #d9cf9e);
  box-shadow: 0 0 40px 14px rgba(255, 250, 220, .35), 0 0 140px 60px rgba(160, 180, 255, .2); }
.moon i { position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(circle at 70% 30%, rgba(0,0,0,0) 46%, rgba(0,0,0,0) 47%), radial-gradient(circle at 30% 62%, rgba(180,170,120,.35) 0 7%, transparent 8%), radial-gradient(circle at 60% 72%, rgba(180,170,120,.28) 0 5%, transparent 6%); }

/* Island lighting per time of day: a colour filter on the island picture itself (never the sky). */
.tint { display: none; }
/* The island picture has this colour baked in; the live SVG and the small floating pieces get it here. */
:root[data-phase="evening"] .world-svg, :root[data-phase="evening"] .deco-item svg { filter: sepia(.32) saturate(1.25) hue-rotate(-14deg) brightness(.93); }
:root[data-phase="night"] .world-svg, :root[data-phase="night"] .deco-item svg { filter: hue-rotate(18deg) saturate(.72) brightness(.6) contrast(1.06); }
:root[data-phase="night"] .isle-label { background: rgba(236,232,255,.9); }
:root[data-phase="evening"] { --cloud: #ffe0d4; --cloud-shade: #f2a7a4; }
:root[data-phase="night"] { --cloud: #6c7bb8; --cloud-shade: #4a5592; }
:root[data-phase="night"] .deco-cloud { opacity: .55; }
:root[data-phase="night"] .actor-fig svg { filter: brightness(.9) saturate(.92); }

.firefly { position: absolute; width: 5px; height: 5px; margin: -2.5px; border-radius: 50%; background: #fff6a8; box-shadow: 0 0 8px 3px rgba(255, 240, 150, .8); opacity: 0; pointer-events: none; }
:root[data-phase="night"] .firefly, :root[data-phase="evening"] .firefly:nth-child(3n) { animation: firefly var(--t, 4s) ease-in-out infinite; animation-delay: calc(var(--d, 0s) * -1); }
@keyframes firefly { 0%, 100% { opacity: 0; transform: translate(0, 0); } 30% { opacity: 1; } 50% { opacity: .9; transform: translate(10px, -14px); } 80% { opacity: .2; transform: translate(-6px, -24px); } }

/* ============ Characters ============ */
.actor { position: absolute; left: 0; top: 0; width: 0; height: 0; cursor: pointer; will-change: transform; -webkit-tap-highlight-color: transparent; }
.actor:focus { outline: none; }
.actor-fig { position: absolute; left: 0; bottom: 0; transform: translateX(-50%) scale(var(--s, 1)); transform-origin: 50% 100%; }
.actor-fig svg { display: block; overflow: visible; }
.actor:focus-visible .actor-fig svg { filter: drop-shadow(0 0 2px #fff) drop-shadow(0 0 2px #3a2550); }
.actor-fig.jump { animation: hop .62s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes hop { 0% { transform: translateX(-50%) scale(var(--s, 1)); } 18% { transform: translateX(-50%) translateY(2px) scale(calc(var(--s, 1) * 1.08), calc(var(--s, 1) * .9)); } 45% { transform: translateX(-50%) translateY(-18px) scale(calc(var(--s, 1) * .96), calc(var(--s, 1) * 1.06)); } 75% { transform: translateX(-50%) translateY(0) scale(calc(var(--s, 1) * 1.05), calc(var(--s, 1) * .95)); } 100% { transform: translateX(-50%) scale(var(--s, 1)); } }
.actor-name { position: absolute; left: 0; top: 4px; transform: translateX(-50%) scale(clamp(.75, var(--iz, 1), 1.6)); transform-origin: 50% 0; white-space: nowrap;
  font: 800 9px/1 var(--font-body); color: #fff; background: var(--npc, #9b5de5); padding: 3px 6px 3px; border-radius: 999px; border: 1.5px solid #fff; box-shadow: 0 1px 0 rgba(58,37,80,.35); pointer-events: none; }
.actor-name.me { background: #3a2550; }
.actors.hide-names .actor-name { display: none; }
.bubble { position: absolute; left: 0; bottom: 64px; transform: translateX(-50%) scale(clamp(.8, var(--iz, 1), 1.9)); transform-origin: 50% 100%;
  width: max-content; max-width: 190px; padding: 8px 11px; border-radius: 14px; background: var(--cream); border: 2.5px solid #fff; box-shadow: 0 0 0 2px var(--gold), 0 6px 14px rgba(58,37,80,.25);
  font: 700 12px/1.3 var(--font-body); color: var(--ink); text-align: center; z-index: 5; animation: bubbleIn .28s var(--ease-pop); cursor: default; }
.bubble b { display: block; font-family: var(--font-display); font-size: 12.5px; margin-bottom: 2px; }
.bubble::after { content: ''; position: absolute; bottom: -10px; left: 50%; margin-left: -7px; border: 7px solid transparent; border-top-color: var(--gold); }
.bubble .btn { margin-top: 6px; min-height: 30px; font-size: 12px; padding: 2px 10px; }
@keyframes bubbleIn { from { opacity: 0; transform: translateX(-50%) translateY(6px) scale(calc(clamp(.8, var(--iz, 1), 1.9) * .85)); } }
.is-puff .bubble { bottom: 40px; }
.is-puff .actor-fig { bottom: -9px; }
.puff-fig { animation: puffBob 4s ease-in-out infinite; }
@keyframes puffBob { 0%, 100% { transform: translateX(-50%) rotate(-1.5deg); } 50% { transform: translateX(calc(-50% + 3px)) translateY(-3px) rotate(1.5deg); } }
.puff-fig.jump { animation: puffHop .7s cubic-bezier(.3,1.6,.5,1); }
@keyframes puffHop { 40% { transform: translateX(-50%) translateY(-14px) rotate(-4deg); } }
.puff-spout { transform-box: fill-box; transform-origin: 50% 100%; animation: spout 3.2s ease-in-out infinite; }
@keyframes spout { 0%, 55%, 100% { transform: scale(1, 1); opacity: 1; } 70% { transform: scale(1.1, 1.3); } 85% { opacity: .6; } }

.hearts { position: absolute; left: 0; bottom: 50px; width: 0; height: 0; pointer-events: none; }
.hearts i { position: absolute; left: 0; bottom: 0; animation: heartUp 2.2s ease-out both; animation-delay: var(--d); }
@keyframes heartUp { 0% { opacity: 0; transform: translate(0, 10px) scale(.4); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(var(--x), -70px) scale(1.1); } }

.av-leg, .av-arm { transform-box: fill-box; transform-origin: 50% 0; }
.av-tool, .av-juggle, .av-think { display: none; }
.is-working .av-tool, .is-working .av-think { display: inline; }
.is-juggling .av-juggle { display: inline; }
.is-idle .av-body { animation: avBreathe 2.8s ease-in-out infinite; }
@keyframes avBreathe { 50% { transform: translateY(-.7px); } }
.is-walking .av-body { animation: avStep .36s ease-in-out infinite alternate; }
@keyframes avStep { from { transform: translateY(0); } to { transform: translateY(-1.4px); } }
.is-walking .av-leg.l, .is-walking .av-arm.r { animation: avSwing .36s ease-in-out infinite alternate; }
.is-walking .av-leg.r, .is-walking .av-arm.l { animation: avSwing .36s ease-in-out infinite alternate-reverse; }
@keyframes avSwing { from { transform: rotate(-20deg); } to { transform: rotate(20deg); } }
.look-left .av-eyes { transform: translateX(-1px); }
.is-walking:not(.look-left) .av-eyes { transform: translateX(1px); }
.is-working .av-arm.r { animation: avHammer .5s ease-in infinite alternate; }
.is-working .av-tool { transform-box: view-box; transform-origin: 8px -10px; animation: avTool .5s ease-in infinite alternate; }
@keyframes avHammer { from { transform: rotate(-70deg); } to { transform: rotate(10deg); } }
@keyframes avTool { from { transform: rotate(-60deg); } to { transform: rotate(14deg); } }
.is-working .av-body { animation: avBreathe 1s ease-in-out infinite; }
.av-think { animation: float 2.4s ease-in-out infinite; }
.av-ball { transform-box: view-box; }
.is-juggling .av-ball.b1 { animation: juggle 1.2s linear infinite; }
.is-juggling .av-ball.b2 { animation: juggle 1.2s linear infinite; animation-delay: -.4s; }
.is-juggling .av-ball.b3 { animation: juggle 1.2s linear infinite; animation-delay: -.8s; }
.is-juggling .av-ball.b4 { animation: juggle 1.2s linear infinite; animation-delay: -.6s; }
@keyframes juggle {
  0% { transform: translate(-8px, 36px); } 20% { transform: translate(-7px, 8px); } 40% { transform: translate(0, -2px); }
  60% { transform: translate(7px, 8px); } 80% { transform: translate(8px, 36px); } 100% { transform: translate(-8px, 36px); }
}

@media (max-width: 900px) {
  .map-fit { right: max(10px, env(safe-area-inset-right, 0px)); bottom: 10px; }
  .sun { width: 74px; height: 74px; left: auto; right: 9%; top: calc(var(--hud-h) + 14px); }
  .moon { width: 56px; height: 56px; left: auto; right: 12%; top: calc(var(--hud-h) + 18px); }
  .sunset-sun { width: 104px; height: 104px; margin-left: -52px; left: 70%; top: calc(var(--hud-h) + 18px); }
  .ss-cloud.c1 { width: 170px; left: calc(70% - 120px); top: calc(var(--hud-h) + 86px); }
  .ss-cloud.c2 { width: 130px; left: calc(70% + 0px); top: calc(var(--hud-h) + 100px); }
  .ss-cloud.c3 { width: 100px; left: calc(70% - 30px); top: calc(var(--hud-h) + 62px); }
}
/* While you drag, characters keep walking but pause their arm/leg swing, which keeps frames light. */
.viewport.is-panning .actor *, .viewport.is-panning .deco-item { animation-play-state: paused !important; }

/* Sitting on a park bench: a lap over the seat and full-length legs hanging down, swinging a little. */
.av-lap { display: none; }
.is-sitting .av-lap { display: inline; }
.is-sitting .av-leg { transform-origin: 50% 0; }
.is-sitting .av-leg.l { animation: dangle 2.6s ease-in-out infinite; }
.is-sitting .av-leg.r { animation: dangle 2.6s ease-in-out infinite reverse; animation-delay: -.7s; }
@keyframes dangle { 0%, 100% { transform: rotate(-7deg); } 50% { transform: rotate(7deg); } }
.is-sitting .av-body { animation: avBreathe 3.4s ease-in-out infinite; }
/* While you're being boosted, the lightstick glows softly. */
.av-held .ls-glow { opacity: 0; }
.is-boosted .av-held .ls-glow { animation: lsGlow 1.6s ease-in-out infinite; }
.is-boosted .av-held .ls-heart { animation: lsHeart 1.6s ease-in-out infinite; }
@keyframes lsGlow { 0%, 100% { opacity: .35; } 50% { opacity: .95; } }
@keyframes lsHeart { 0%, 100% { fill: #e9dcff; } 50% { fill: #ffffff; } }

/* ============ Weather ============ */
.rainbow { position: absolute; left: 50%; top: calc(var(--hud-h) + 40px); width: min(900px, 130vw); aspect-ratio: 2 / 1; transform: translateX(-50%); opacity: 0; transition: opacity 4s ease; pointer-events: none; overflow: hidden; }
.rainbow i { position: absolute; inset: 0 0 -100% 0; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, transparent 56%, rgba(155,93,229,.55) 57%, rgba(74,144,226,.55) 59.5%, rgba(79,191,106,.55) 62%, rgba(255,211,77,.6) 64.5%, rgba(255,154,61,.55) 67%, rgba(240,90,90,.5) 69.5%, transparent 71%);
  filter: blur(2px); }
:root[data-rainbow] .rainbow { opacity: .75; }
:root[data-phase="evening"][data-rainbow] .rainbow { opacity: .5; }
.rain { position: absolute; inset: 0; z-index: 4; pointer-events: none; opacity: 0; transition: opacity 3s ease; overflow: hidden; }
.rain i { position: absolute; inset: -100% 0 0 0; height: 200%;
  background-image: repeating-linear-gradient(104deg, transparent 0 22px, rgba(220,235,255,.2) 22px 23px, transparent 23px 71px);
  animation: rainFall .9s linear infinite; }
.rain i + i { background-size: 61px 100%; opacity: .7; animation-duration: 1.3s; }
@keyframes rainFall { to { transform: translate3d(-12%, 50%, 0); } }
:root[data-rain] .rain { opacity: .7; }
.ripples { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; display: none; }
:root[data-rain] .ripples { display: block; }
.ripple { position: absolute; width: 14px; height: 6px; margin: -3px -7px; border-radius: 50%; border: 1.5px solid rgba(235,248,255,.9); opacity: 0;
  animation: ripple var(--t, 1.8s) ease-out infinite; animation-delay: calc(var(--d, 0s) * -1); }
@keyframes ripple { 0% { transform: scale(.2); opacity: .9; } 100% { transform: scale(1.6); opacity: 0; } }

/* ============ Friends: wave, cheer; you: yawn and stretch at night ============ */
.is-waving .av-arm.r { animation: wave .32s ease-in-out 5 alternate !important; }
@keyframes wave { from { transform: rotate(-165deg); } to { transform: rotate(-125deg); } }
.is-cheering .av-arm.l { animation: cheerL .3s ease-in-out 6 alternate !important; }
.is-cheering .av-arm.r { animation: cheerR .3s ease-in-out 6 alternate !important; }
@keyframes cheerL { from { transform: rotate(150deg); } to { transform: rotate(175deg); } }
@keyframes cheerR { from { transform: rotate(-150deg); } to { transform: rotate(-175deg); } }
.av-yawn { display: none; }
.is-yawning .av-yawn { display: inline; animation: yawn 2.4s ease-in-out both; transform-box: fill-box; transform-origin: center; }
.is-yawning .av-mouth { display: none; }
.is-yawning .av-eyes { transform: scaleY(.35); transform-box: fill-box; transform-origin: center; transition: transform .3s; }
@keyframes yawn { 0% { transform: scale(.3); } 25%, 75% { transform: scale(1); } 100% { transform: scale(.3); } }
.is-stretching .av-arm.l { animation: stretchL 2.2s ease-in-out both !important; }
.is-stretching .av-arm.r { animation: stretchR 2.2s ease-in-out both !important; }
.is-stretching .av-body { animation: stretchBody 2.2s ease-in-out both !important; }
@keyframes stretchL { 0%, 100% { transform: rotate(0); } 30%, 70% { transform: rotate(165deg); } }
@keyframes stretchR { 0%, 100% { transform: rotate(0); } 30%, 70% { transform: rotate(-165deg); } }
@keyframes stretchBody { 0%, 100% { transform: translateY(0); } 30%, 70% { transform: translateY(-1.6px); } }

/* ============ Coins flying into the wallet ============ */
.fly-coin { position: fixed; left: 0; top: 0; z-index: 90; width: 26px; height: 26px; margin: -13px; pointer-events: none; will-change: transform, opacity; }
.fly-coin svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 2px 2px rgba(58,37,80,.3)); }
.fly-plus { position: fixed; z-index: 91; pointer-events: none; font: 700 1rem/1 var(--font-display); color: #2a7a2a; background: #fff; padding: 4px 10px; border-radius: 999px;
  box-shadow: 0 0 0 2px #8fe36b, 0 4px 10px rgba(58,37,80,.2); transform: translate(-50%, -50%); animation: flyPlus 1.6s ease-out forwards; white-space: nowrap; }
@keyframes flyPlus { 0% { opacity: 0; transform: translate(-50%, -20%) scale(.7); } 20% { opacity: 1; transform: translate(-50%, -60%) scale(1.05); } 100% { opacity: 0; transform: translate(-50%, -160%) scale(1); } }
.wallet-bump { animation: walletBump .5s var(--ease-pop); }
@keyframes walletBump { 30% { transform: scale(1.18); } }
