/* The Letter Garden — full-screen, wordless kids' game. Everything is big,
   bright and touch-first; the only readable text anywhere is Arabic letters.

   Visual system ("Toca-soft"): saturated toy colors, soft plum shadows (no
   black anywhere), chunky buttons with a darker bottom edge that physically
   press down, and springy motion.

   Motion system (after Emil Kowalski's design-eng rules):
   - custom curves, never the weak CSS built-ins
   - entrances from scale(.9)+opacity, never scale(0)
   - press feedback 120-160ms; exits always snappier than entries
   - transforms/opacity only; hover effects gated behind (hover:hover) */

:root {
  /* palette */
  --lg-ink: #4a3620; /* warm espresso contour — replaces the old cold navy */
  /* One keyboard-focus ring everywhere (accent-warm = "the live thing"), and a
     pale-gold twin for dark boards where orange would sink. */
  --lg-focus: #e8743c;
  --lg-focus-on-dark: #ffe49a;
  --lg-shadow: rgba(74, 54, 32, 0.2);
  --lg-cream: #fffaf0;
  --lg-cream-edge: #e5dcc8;
  --lg-paper-muted: #fffaf0;
  /* Primary action. Warm on purpose: the storybook palette is cream, espresso
     and green, and a cool blue button was the one element that read as app
     chrome rather than part of the toy. Tangerine keeps the same "press me"
     prominence while staying inside the language, and sits clear of the gold
     used for stars and finished stops. */
  --lg-action: #e8743c;
  --lg-action-edge: #b0501f;
  --lg-gold: #f3c955;
  --lg-gold-hi: #ffe49a;
  --lg-gold-edge: #c69434;
  --lg-gold-deep: #70501b;
  --lg-coral: #ee806f;
  --lg-green: #7fce54;
  --lg-green-deep: #4e9677;
  --lg-outline: 3px solid var(--lg-ink);
  --lg-lift-sm: 0 5px 0 var(--lg-ink);
  --lg-lift: 0 7px 0 var(--lg-ink);
  --lg-radius-sm: 18px;
  --lg-radius: 26px;
  --lg-radius-lg: 34px;
  /* sky (day defaults; the game sets these per day-phase) */
  --lg-sky-hi: #62cdf4;
  --lg-sky-mid: #96ecff;
  --lg-sky-lo: #ccfbef;
  /* motion */
  /* Duration scale (2026-07-24). Before this there were ~48 different
     sub-second timings, so nothing felt like it belonged to the same machine.
     Ambient loops (breathe, drift, twinkle) sit ABOVE this scale on purpose and
     keep their own long, hand-tuned periods and easings. */
  --lg-t-tick: 90ms;
  --lg-t-tap: 140ms;
  --lg-t-quick: 220ms;
  --lg-t-move: 320ms;
  --lg-t-enter: 460ms;
  --lg-t-arrive: 620ms;
  --lg-t-beat: 900ms;
  --lg-out: cubic-bezier(0.23, 1, 0.32, 1);
  --lg-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --lg-spring: cubic-bezier(0.34, 1.56, 0.44, 1);
  --lg-spring-big: cubic-bezier(0.34, 1.8, 0.5, 1);
}

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

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}

body {
  /* Flat, not a gradient: the sky is painted by the backdrop SVG now. A second
     gradient here could only disagree with it (different box, different
     anchoring) and that disagreement was the navy bar across the top. */
  background: var(--lg-sky-hi);
  font-family: ui-rounded, "Hiragino Maru Gothic ProN", system-ui, sans-serif;
  transition: background 620ms ease;
}

.lg-app { position: fixed; inset: 0; }

.art-backdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.lg-screen {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: max(10px, env(safe-area-inset-top)) 12px max(10px, env(safe-area-inset-bottom));
  animation: lg-screen-in 460ms var(--lg-spring) both;
}

/* Shared tactile primitives. Gameplay stays open; these surfaces are reserved
   for decisions, progress, rewards and navigation. */
.lg-panel {
  border: var(--lg-outline);
  border-radius: var(--lg-radius-lg);
  background: rgba(255, 250, 240, 0.96);
  box-shadow: var(--lg-lift);
}

.lg-tray {
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.96);
  box-shadow: var(--lg-lift-sm);
}

@keyframes lg-screen-in {
  from { opacity: 0; transform: scale(0.94) translateY(20px); }
  to { opacity: 1; transform: none; }
}

/* ---------- chrome ---------- */
.lg-topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  z-index: 5;
}

.lg-round-btn {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border: var(--lg-outline);
  border-radius: 50%;
  background: var(--lg-cream);
  box-shadow: var(--lg-lift-sm);
  color: var(--lg-ink);
  cursor: pointer;
  transition: transform 140ms var(--lg-spring), box-shadow 140ms var(--lg-out);
}

.lg-round-btn:active { transform: translateY(4px) scale(0.97); box-shadow: 0 1px 0 var(--lg-ink); }
.lg-round-btn.is-off { opacity: 0.4; }

.lg-big-btn {
  display: grid;
  place-items: center;
  min-width: 110px;
  height: 74px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius-sm);
  background: var(--lg-action);
  box-shadow: 0 6px 0 var(--lg-action-edge), 0 9px 0 var(--lg-ink);
  color: #fffdf7;
  cursor: pointer;
  transition: transform 140ms var(--lg-spring), box-shadow 140ms var(--lg-out);
}

.lg-big-btn:active { transform: translateY(6px) scale(0.98); box-shadow: 0 1px 0 var(--lg-action-edge), 0 4px 0 var(--lg-ink); }

/* ---------- living art ---------- */
/* NB: never use a PERCENTAGE transform-origin on art whose viewBox has a
   negative min-x (pet, mascot, egg, map stop, tile, pack). The percentage is
   applied as a raw user coordinate, so 50% lands half a viewBox to the RIGHT of
   the art's centre line and the piece drifts sideways as it animates. Use
   explicit px equal to the user coordinate you want, or transform-box: fill-box. */
.art-eyes { animation: lg-blink 4.6s infinite; transform-origin: center; transform-box: fill-box; }
@keyframes lg-blink {
  0%, 93%, 100% { transform: scaleY(1); }
  95.5% { transform: scaleY(0.08); }
}

.art-mascot-body { animation: lg-breathe 2.6s ease-in-out infinite; transform-origin: 0px 72px; }
.art-blob-body, .art-sprig-body { animation: lg-breathe 2.9s ease-in-out infinite; transform-origin: 50% 90%; }
.art-creature-body { animation: lg-breathe 3.1s ease-in-out infinite; transform-origin: 50% 92%; }
@keyframes lg-breathe {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-4px) scale(1.02, 0.985); }
}

/* backdrop ambience */
.art-cloud-a { animation: lg-drift 52s linear infinite; }
.art-cloud-b { animation: lg-drift 74s linear infinite; animation-delay: -34s; }
@keyframes lg-drift {
  from { transform: translateX(-180px); }
  to { transform: translateX(880px); }
}

.art-sun-glow { animation: lg-sun-breathe 6s ease-in-out infinite; transform-box: view-box; transform-origin: 620px 88px; }
@keyframes lg-sun-breathe { 50% { transform: scale(1.05); } }

.art-stars > * { animation: lg-twinkle 3.4s ease-in-out infinite; }
@keyframes lg-twinkle { 50% { opacity: 0.3; } }

.art-fireflies circle { animation: lg-firefly 5.2s ease-in-out infinite; }
@keyframes lg-firefly {
  0%, 100% { opacity: 0.25; transform: translate(0, 0); }
  50% { opacity: 1; transform: translate(10px, -14px); }
}

/* sparkle touch trail — pure toy delight, spawned by the shell on drag */
.lg-spark {
  position: fixed;
  z-index: 70;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  pointer-events: none;
  background: radial-gradient(circle, #fffdf7 20%, var(--lg-gold) 55%, transparent 72%);
  border-radius: 50%;
  animation: lg-spark 620ms var(--lg-out) forwards;
}

.lg-spark.is-pink { background: radial-gradient(circle, #fffdf7 20%, var(--lg-coral) 55%, transparent 72%); }
.lg-spark.is-blue { background: radial-gradient(circle, #fffdf7 20%, #62cdf4 55%, transparent 72%); }

@keyframes lg-spark {
  from { opacity: 1; transform: translate(0, 0) scale(1); }
  to { opacity: 0; transform: translate(var(--sx, 0), var(--sy, 14px)) scale(0.2); }
}

/* ---------- home map: winding trail ---------- */
.map-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  z-index: 2;
  margin: 0 -12px;
}

.map-path {
  position: relative;
  max-width: 460px;
  margin: 0 auto;
  /* height set inline by the game: one bend per world */
}

.map-trail { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

.map-stop {
  position: absolute;
  width: clamp(108px, 29vw, 138px);
  aspect-ratio: 1;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  transform: translate(-50%, -50%);
}

.map-stop:disabled { cursor: default; }
.map-stop-art { width: 100%; aspect-ratio: 1; display: block; transition: transform 140ms var(--lg-spring); }
.map-stop.is-current .map-stop-art { animation: lg-bounce 2.1s var(--lg-spring) infinite; }
.map-stop.is-current::before {
  content: "";
  position: absolute;
  inset: -10% -10% 7%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(243, 201, 85, 0.5), rgba(243, 201, 85, 0) 68%);
  animation: lg-halo 2.1s ease-in-out infinite;
  pointer-events: none;
}

.map-stop.is-done:active .map-stop-art, .map-stop.is-current:active .map-stop-art { transform: translateY(5px) scale(0.97); }

@media (hover: hover) and (pointer: fine) {
  .map-stop.is-done:hover .map-stop-art, .map-stop.is-current:hover .map-stop-art { transform: translateY(-4px); }
}

@keyframes lg-bounce {
  0%, 100% { transform: translateY(0); }
  12% { transform: translateY(-13px) scale(1.02, 0.98); }
  24% { transform: translateY(0) scale(0.98, 1.02); }
  32% { transform: translateY(0) scale(1); }
}

@keyframes lg-halo {
  50% { transform: scale(1.16); opacity: 0.6; }
}

.map-here {
  position: absolute;
  transform: translate(-50%, -100%);
  margin-top: -34px;
  pointer-events: none;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  gap: 0;
}

.map-here .art-pet { width: 52px; height: auto; margin-left: -14px; }

.map-bloom {
  position: absolute;
  transform: translate(-50%, 0);
  margin-top: 26px;
  pointer-events: none;
  z-index: 1;
}

.art-bloom { animation: lg-bloom-in 620ms var(--lg-spring) both, lg-sway 4.4s ease-in-out infinite 600ms; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes lg-bloom-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes lg-sway {
  0%, 100% { rotate: -3deg; }
  50% { rotate: 3deg; }
}

/* Earned vs unearned must be a CATEGORY difference, not a transparency one
   (2026-07-25). These were both cream — #fffaf0 filled versus the same cream at
   45% opacity — sitting on a cream/mint coin face, so an earned star was nearly
   invisible and children concluded they hadn't earned any. Gold-filled versus
   hollow reads instantly at a glance and at any size, and gold is already the
   game's reward motif (ART.md §2: gold is a motif, not a contour). */
.map-star-on path { fill: var(--lg-gold); stroke: var(--lg-gold-edge); stroke-width: 4; }
.map-star-off path { fill: none; stroke: var(--lg-ink); stroke-width: 4; opacity: 0.5; }

/* ---------- meet a letter ---------- */
.meet-stage {
  /* Hug the content instead of stretching to fill the column, and stay
     centred in whatever space is left. */
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  z-index: 2;
  width: min(520px, calc(100% - 12px));
  max-height: min(680px, calc(100% - 86px));
  margin: auto;
  padding: clamp(22px, 4vh, 40px);
  border: var(--lg-outline);
  border-radius: var(--lg-radius-lg);
  background: rgba(255, 250, 240, 0.96);
  box-shadow: var(--lg-lift);
}

.meet-card {
  position: relative;
  border: none;
  background: none;
  cursor: pointer;
  animation: lg-arrive 460ms var(--lg-spring);
  transition: transform 140ms var(--lg-spring);
}

.meet-card:active { transform: scale(0.96); }
.meet-card .art-blob { width: clamp(220px, 62vw, 300px); height: auto; }
.meet-card.is-born { animation: meet-born 620ms var(--lg-spring-big); }
@keyframes meet-born {
  0% { transform: scale(0.2); opacity: 0; }
  70% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); }
}

/* Make-it-happen intro pieces (2026-07-18): the child taps/fuses these to
   CAUSE the reveal — no passive watching. */
.meet-make { display: flex; gap: 18px; align-items: center; }
.meet-piece {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  animation: lg-arrive 460ms var(--lg-spring) backwards;
  animation-delay: calc(var(--pi, 0) * 90ms);
  transition: transform 140ms var(--lg-spring), filter 140ms var(--lg-out);
}
.meet-piece .art-blob { width: clamp(110px, 26vw, 150px); height: auto; }
.meet-piece:active { transform: scale(0.94); }
.meet-piece.is-set {
  transform: scale(1.08);
  filter: drop-shadow(0 0 14px rgba(255, 210, 62, 0.75));
}
.meet-make.is-fusing .meet-piece {
  animation: meet-fuse-in 460ms var(--lg-out) forwards;
}
@keyframes meet-fuse-in {
  60% { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(0.1); opacity: 0; }
}

/* The sleeping bud: a letter waits inside until the child wakes it. */
.meet-bud {
  width: clamp(140px, 38vw, 190px);
  aspect-ratio: 1;
  border: none;
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%, #fffaf0, #ffe49a 58%, #f3c955 90%);
  box-shadow: 0 6px 0 #c69434, 0 12px 22px -8px var(--lg-shadow);
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 44px;
  animation: meet-bud-pulse 1.8s ease-in-out infinite;
}
.meet-bud:active { transform: scale(0.94); }
.meet-bud.is-popped { animation: meet-bud-pop 320ms var(--lg-out) forwards; }
@keyframes meet-bud-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}
@keyframes meet-bud-pop {
  60% { transform: scale(1.25); opacity: 1; }
  100% { transform: scale(0.1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .meet-bud { animation: none; } }

@keyframes lg-arrive {
  from { transform: scale(0.88) translateY(24px); opacity: 0; }
  to { transform: scale(1) translateY(0); opacity: 1; }
}

.meet-dots, .play-dots { display: flex; gap: 8px; }
.meet-dots i, .play-dots i {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--lg-ink);
  background: var(--lg-paper-muted);
  box-shadow: none;
  transition: transform 320ms var(--lg-spring), background 220ms var(--lg-out);
}
.meet-dots i.is-on, .play-dots i.is-on { background: var(--lg-gold); transform: scale(1.22); }
.play-dots i.is-done { background: var(--lg-green); }

.meet-nav, .stars-nav { display: flex; align-items: center; gap: 18px; }

/* ---------- play chrome ---------- */
.play-prompt {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: min(620px, calc(100% - 128px));
  min-height: 82px;
  margin: 0 auto 8px;
  padding: 5px 14px 8px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.96);
  box-shadow: var(--lg-lift-sm);
  z-index: 4;
}

.play-mascot { flex: 0 0 auto; }

.play-bubble {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 110px;
  padding: 8px 18px 10px;
  border: 2px solid var(--lg-ink);
  border-radius: var(--lg-radius-sm);
  background: #fffaf0;
  box-shadow: 0 4px 0 var(--lg-ink);
  cursor: pointer;
  transition: transform 140ms var(--lg-spring);
}

.play-bubble:active { transform: scale(0.96); }

.play-bubble::before {
  content: "";
  position: absolute;
  left: -8px;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 4px;
  border-left: 2px solid var(--lg-ink);
  border-bottom: 2px solid var(--lg-ink);
  background: #fffaf0;
  transform: translateY(-50%) rotate(45deg);
}

.play-bubble-glyph {
  display: grid;
  place-items: center;
  min-width: 1.35em;
  min-height: 1.22em;
  font-family: "Amiri Quran", serif;
  font-size: 38px;
  line-height: 1;
  color: var(--lg-ink);
  position: relative;
  transform: translateY(-0.04em);
}

.play-bubble-glyph.is-latin { font-family: inherit; font-size: 22px; font-weight: 800; transform: none; }
.play-bubble-icon { color: rgba(74, 54, 32, 0.55); display: grid; position: relative; }

.play-dots { position: absolute; top: 18px; right: 82px; }

.play-stage {
  flex: 1;
  /* Cap the playfield (2026-07-24). Unbounded, this filled the whole column —
     on a tablet that's ~800px of sky for 3 or 4 bubbles, so targets sat far
     from the prompt and the field read as empty. Capped, the action happens
     just under the prompt and the backdrop hills fill the space below, which
     is what the scenery is there for. */
  max-height: min(620px, 62vh);
  position: relative;
  overflow: hidden;
  z-index: 2;
  border-radius: 18px;
  /* rising and falling pieces dissolve at the stage's top edge instead of
     getting sliced by an invisible line under the prompt row */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #0a1f1a 64px);
  mask-image: linear-gradient(to bottom, transparent 0, #0a1f1a 64px);
}

/* ---------- bubble pop ---------- */
.pop-sky { position: absolute; inset: 0; }

/* Perf (iPad, 2026-07-18): bubbles/fallers position with an inline transform
   (composited) and top:0 anchor — no per-frame layout, and no drop-shadow
   filter on moving elements (the tile art carries its own depth edge).
   Pop/shake animations live on the inner svg so they never fight the
   positional transform on the wrapper. */
.pop-bubble {
  position: absolute;
  top: 0;
  width: clamp(96px, 26vw, 132px);
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  will-change: transform;
}

.pop-bubble svg { width: 100%; display: block; }
.pop-bubble.is-popped { pointer-events: none; }
.pop-bubble.is-popped svg { animation: lg-pop 460ms var(--lg-out) forwards; }

@keyframes lg-pop {
  30% { transform: scale(1.22); opacity: 1; }
  100% { transform: scale(0.3); opacity: 0; }
}

/* Try-again is a small wobble, not a head-shake "no": for a 4-year-old a big
   shake reads as being told off. Reduced motion drops it; the sound remains. */
.is-shake { animation: lg-shake 420ms var(--lg-out); }
@keyframes lg-shake {
  0%, 100% { transform: translateX(0) rotate(0); }
  30% { transform: translateX(-4px) rotate(-1.5deg); }
  65% { transform: translateX(3px) rotate(1deg); }
}
.lg-reduce-motion .is-shake { animation: none; }
@media (prefers-reduced-motion: reduce) { .is-shake { animation: none; } }

/* ---------- catch ---------- */
.catch-field { position: absolute; inset: 0; }

.catch-faller {
  position: absolute;
  top: 0;
  width: clamp(86px, 23vw, 118px);
  transform: translateX(-50%);
  will-change: transform;
  pointer-events: none;
}

.catch-faller svg { width: 100%; display: block; }

.catch-basket {
  position: absolute;
  bottom: 3%;
  left: 50%;
  width: clamp(130px, 34vw, 170px);
  transform: translateX(-50%);
  pointer-events: none;
  filter: drop-shadow(0 5px 6px var(--lg-shadow));
}

.catch-basket svg { width: 100%; display: block; }

/* ---------- pairs ---------- */
.pairs-grid {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  place-content: center;
  padding: 12px;
  max-width: 460px;
  margin: 0 auto;
}

@media (min-aspect-ratio: 1/1) {
  .pairs-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 620px; }
}

.pairs-card {
  width: clamp(100px, 24vw, 150px);
  justify-self: center;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  transition: transform 140ms var(--lg-spring);
  animation: lg-arrive 320ms var(--lg-spring) backwards;
}

.pairs-card:nth-child(2) { animation-delay: 50ms; }
.pairs-card:nth-child(3) { animation-delay: 100ms; }
.pairs-card:nth-child(4) { animation-delay: 150ms; }
.pairs-card:nth-child(5) { animation-delay: 200ms; }
.pairs-card:nth-child(6) { animation-delay: 250ms; }

.pairs-card svg { width: 100%; display: block; }
.pairs-card:active { transform: scale(0.95); }
.pairs-card.is-selected { transform: translateY(-5px) scale(1.08); filter: drop-shadow(0 6px 0 var(--lg-ink)); }
.pairs-card.is-matched { animation: lg-matched 620ms var(--lg-out) forwards; pointer-events: none; }

@keyframes lg-matched {
  40% { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(0.92); opacity: 0.35; }
}

/* ---------- feed ---------- */
.feed-scene {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 4px 0 14px;
}

.feed-creature { width: clamp(170px, 44vw, 230px); }
.feed-creature svg { width: 100%; display: block; }
.feed-creature.is-chomp .art-creature-body { animation: lg-chomp 460ms var(--lg-spring); transform-origin: 50% 70%; }

@keyframes lg-chomp {
  30% { transform: scale(1.14, 0.86); }
  60% { transform: scale(0.94, 1.08); }
}

.feed-tray { display: flex; gap: clamp(8px, 3vw, 22px); }

.feed-food {
  width: clamp(96px, 26vw, 128px);
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  filter: drop-shadow(0 5px 0 var(--lg-ink));
  transition: transform 140ms var(--lg-spring);
  animation: lg-arrive 320ms var(--lg-spring) backwards;
}

.feed-food:nth-child(2) { animation-delay: 60ms; }
.feed-food:nth-child(3) { animation-delay: 120ms; }
.feed-food:nth-child(4) { animation-delay: 180ms; }

.feed-food svg { width: 100%; display: block; }
.feed-food:active { transform: scale(0.94); }

.feed-food.is-flying {
  transform: translate(var(--fly-x), var(--fly-y)) scale(0.25);
  opacity: 0;
  transition: transform 460ms var(--lg-in-out), opacity 460ms var(--lg-out);
  pointer-events: none;
}

/* ---------- stars & party ---------- */
.stars-stage, .party-stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 30px;
  z-index: 2;
  width: min(520px, calc(100% - 20px));
  max-height: min(620px, calc(100% - 88px));
  margin: 16px auto 10px;
  padding: clamp(28px, 6vh, 54px) 24px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius-lg);
  background: rgba(255, 250, 240, 0.96);
  box-shadow: var(--lg-lift);
}

.stars-row, .party-stars { display: flex; gap: 14px; }

.stars-star { color: rgba(140, 128, 160, 0.3); transform: scale(0.6); }
.stars-star.is-on {
  color: var(--lg-gold);
  animation: lg-star-land 620ms var(--lg-spring-big) forwards;
}
.stars-star.is-on svg path { stroke: var(--lg-gold-edge); stroke-width: 3; }

@keyframes lg-star-land {
  0% { transform: scale(0.2) rotate(-40deg); opacity: 0; }
  60% { transform: scale(1.25) rotate(8deg); opacity: 1; }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}

.party-mascot { animation: lg-dance 1s ease-in-out infinite; transform-origin: 0px 72px; }
.party-pet .art-pet-body { animation: lg-dance 1s ease-in-out infinite reverse; }
@keyframes lg-dance {
  0%, 100% { transform: rotate(-6deg) translateY(0); }
  25% { transform: rotate(0deg) translateY(-13px); }
  50% { transform: rotate(6deg) translateY(0); }
  75% { transform: rotate(0deg) translateY(-13px); }
}

/* ---------- confetti ---------- */
.lg-confetti-layer { position: fixed; z-index: 60; pointer-events: none; }
/* One shape family from the garden: petals and round seeds, no paper strips. */
.lg-confetti-layer i {
  position: absolute;
  width: 11px;
  height: 15px;
  border-radius: 70% 0 70% 0;
  animation: lg-confetti 1.05s var(--lg-out) forwards;
}

.lg-confetti-layer i.is-round { width: 11px; height: 11px; border-radius: 50%; }
.lg-confetti-layer i.is-drop { width: 9px; height: 12px; border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; }
.lg-confetti-layer i.is-chip { width: 12px; height: 6px; border-radius: 2px; }
.lg-confetti-layer i.is-seed { width: 8px; height: 11px; border-radius: 50%; }
.lg-confetti-layer i.is-glint { width: 13px; height: 13px; border-radius: 0; clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%); }
.lg-burst-ring { position: absolute; left: -30px; top: -10px; width: 60px; height: 20px; border: 3px solid #fffdf7; box-shadow: 0 0 0 2px #62cdf4; border-radius: 50%; animation: lg-burst-ring 700ms ease-out forwards; }
@keyframes lg-burst-ring { from { transform: scale(0.3); opacity: 1; } to { transform: scale(2.2); opacity: 0; } }

@keyframes lg-confetti {
  from { transform: translate(0, 0) rotate(0); opacity: 1; }
  to { transform: translate(var(--dx), var(--dy)) rotate(var(--rot)); opacity: 0; }
}

/* ---------- per-world scenery tint ---------- */
/* Tint the SCENERY, never the sky. Applied to the whole SVG this saturated the
   sky rect too, so the sky rendered more saturated than the identical hex on
   <body> behind it — and that mismatch was visible as a band across the top
   wherever the compositor let the body show through. */
/* Retired 2026-10-01: the tint saturated every scene ×1.28 and rotated hues up
   to 65°, so the locked palette never reached the screen (pink moons, magenta
   peaks). Chapter identity now comes from the land art (backdrop biome). */
.art-scenery-tint { filter: none; }

/* ---------- daily training & stamp calendar ---------- */
.map-daily-row {
  position: absolute;
  top: max(10px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  padding: 8px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.96);
  box-shadow: var(--lg-lift-sm);
  z-index: 6;
}

.map-daily,
.map-calendar,
.map-checkup,
.map-pet,
.map-album {
  position: relative;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  min-width: 62px;
  padding: 0;
  border: 2px solid var(--lg-ink);
  border-radius: 50%;
  cursor: pointer;
  transition: transform 140ms var(--lg-spring), box-shadow 140ms var(--lg-out);
}

.map-daily {
  background: radial-gradient(circle at 34% 28%, #ffe49a, #c69434 78%);
  box-shadow: 0 4px 0 #c69434;
  color: #fffaf0;
  animation: lg-bounce 2s var(--lg-spring) infinite;
}

.map-daily:active { transform: translateY(4px); box-shadow: 0 1px 0 #c69434; }
.map-daily.is-stamped { animation: none; box-shadow: 0 5px 0 #c69434; }

.map-daily-check {
  position: absolute;
  right: -4px;
  bottom: -4px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: linear-gradient(#b7e779, var(--lg-green));
  box-shadow: 0 2px 0 var(--lg-green-deep);
  color: #2f5c46;
}

.map-calendar {
  background: var(--lg-cream);
  box-shadow: 0 4px 0 var(--lg-ink);
  color: var(--lg-ink);
}

.map-calendar:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--lg-ink); }

.stamps-stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  z-index: 2;
}

.stamps-moon { color: #c69434; }

.stamps-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
  max-width: 400px;
  padding: 16px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.94);
  box-shadow: var(--lg-lift);
}

.stamp-cell {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 2px solid var(--lg-ink);
  border-radius: 13px;
  background: #e5dcc8;
  color: #a89478;
  font-weight: 800;
  font-size: 15px;
}

.stamp-cell.is-stamped { background: #ffe49a; color: var(--lg-gold); }
.stamp-cell.is-stamped svg path { fill: var(--lg-gold); stroke: var(--lg-gold-edge); stroke-width: 4; }
.stamp-cell.is-today { outline: 4px solid #62cdf4; outline-offset: 2px; }
.stamp-cell.is-future { opacity: 0.45; }

/* ---------- trace ---------- */
.trace-wrap { position: absolute; inset: 0; }

.trace-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 22px;
  background: rgba(255, 250, 240, 0.92);
  box-shadow: inset 0 0 0 4px rgba(74, 54, 32, 0.12), inset 0 -6px 0 rgba(74, 54, 32, 0.06);
  cursor: crosshair;
  touch-action: none;
}

.trace-clear { position: absolute; right: 10px; bottom: 10px; width: 48px; height: 48px; }

/* ---------- the Letter Pet & sticker album ---------- */
.map-pet, .map-album {
  display: grid;
  grid-auto-flow: column;
  place-items: center;
  place-content: center;
  gap: 4px;
  background: var(--lg-cream);
  box-shadow: 0 4px 0 var(--lg-ink);
  color: var(--lg-gold-edge);
  font-size: 18px;
  font-weight: 900;
  transition: transform 140ms var(--lg-spring), box-shadow 140ms var(--lg-out);
}

.map-pet:active, .map-album:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--lg-ink); }

.map-pet { overflow: hidden; }
.map-pet .art-pet { display: block; }
.map-album b { color: var(--lg-ink); font-size: 17px; line-height: 1; }

.lg-star-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px 9px;
  border: 2px solid var(--lg-ink);
  border-radius: 999px;
  background: var(--lg-cream);
  box-shadow: 0 4px 0 var(--lg-ink);
  color: var(--lg-gold-edge);
  font-size: 18px;
  font-weight: 900;
}

.lg-star-chip b { color: var(--lg-ink); }

.hatch-stage, .pet-stage, .album-stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  z-index: 2;
}

.hatch-egg, .pet-big, .party-pet {
  position: relative;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
}

.hatch-egg .art-egg-body { animation: lg-wiggle 1.6s ease-in-out infinite; transform-origin: 0px 40px; }
@keyframes lg-wiggle {
  0%, 100% { transform: rotate(0); }
  30% { transform: rotate(-4deg); }
  60% { transform: rotate(4deg); }
}

.hatch-pet { animation: lg-arrive 620ms var(--lg-spring-big); }
/* User-space pivot: the body axis (x=0) at ground level (y=50). A percentage
   here resolves against the view-box, and because this viewBox starts at
   min-x=-70 that put the pivot at user x=70 — scaling the pet 9.8 units off
   centre, which is why it read as misaligned in the map button. */
.art-pet-body { transform-origin: 0px 50px; }
.pet-big .art-pet-body, .party-pet .art-pet-body, .hatch-pet .art-pet-body { animation: lg-breathe 3s ease-in-out infinite; }

.hatch-hues { display: flex; gap: 12px; }
.hatch-hue {
  width: 46px;
  height: 46px;
  border: 3px solid var(--lg-ink);
  border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, hsl(var(--h) 64% 76%), hsl(var(--h) 58% 56%) 75%);
  box-shadow: 0 4px 0 hsl(var(--h) 44% 38%), 0 8px 14px -6px var(--lg-shadow);
  cursor: pointer;
  transition: transform 140ms var(--lg-spring), box-shadow 140ms var(--lg-out);
}
.hatch-hue:active { transform: translateY(3px); box-shadow: 0 1px 0 hsl(var(--h) 44% 38%); }
.hatch-hue.is-picked { outline: 4px solid var(--lg-gold); outline-offset: 3px; }

.pet-bubble {
  position: absolute;
  top: -18px;
  right: -26px;
  display: grid;
  place-items: center;
  min-width: 52px;
  height: 52px;
  border-radius: 50% 50% 50% 12%;
  background: linear-gradient(#fffdf7, var(--lg-cream));
  box-shadow: 0 4px 0 var(--lg-cream-edge), 0 10px 16px -8px var(--lg-shadow);
  color: var(--lg-ink);
  font-family: "Amiri Quran", serif;
  font-size: 26px;
  line-height: 1;
  z-index: 2;
  animation: lg-arrive 320ms var(--lg-spring);
}

.play-pet { flex: 0 0 auto; cursor: pointer; }
.is-hop .art-pet-body, .play-pet.is-hop .art-pet-body {
  animation: lg-hop 620ms var(--lg-spring-big);
}
@keyframes lg-hop {
  0% { transform: translateY(0); }
  32% { transform: translateY(-22px) scale(0.94, 1.08) rotate(-4deg); }
  62% { transform: translateY(0) scale(1.1, 0.88); }
  82% { transform: scale(0.97, 1.04); }
  100% { transform: scale(1); }
}

.play-pet.is-sad .art-pet-body { animation: lg-droop 900ms var(--lg-out); }
@keyframes lg-droop {
  0% { transform: translateY(0); }
  30% { transform: translateY(5px) scale(1.04, 0.94) rotate(2deg); }
  100% { transform: translateY(0); }
}

.pet-shelf {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  max-width: 420px;
  padding: 12px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.92);
  box-shadow: var(--lg-lift);
}

.pet-shelf.pet-bodies { grid-template-columns: repeat(5, minmax(0, 1fr)); }

.pet-color-rack {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  max-width: 420px;
  padding: 10px 14px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.92);
  box-shadow: var(--lg-lift);
}
.pet-color-rack > strong { color: var(--lg-ink); font-size: 14px; }
.pet-color-options { display: flex; gap: 9px; }
.pet-color-swatch {
  width: 32px;
  height: 32px;
  padding: 0;
  border: 3px solid #fffdf7;
  border-radius: 50%;
  background: hsl(var(--h) 72% 62%);
  box-shadow: 0 0 0 2px var(--lg-ink), 0 3px 0 var(--lg-ink);
  cursor: pointer;
}
.pet-color-swatch.is-picked { outline: 4px solid var(--lg-gold); outline-offset: 3px; }
.pet-color-swatch:active { transform: translateY(2px); box-shadow: 0 0 0 2px var(--lg-ink), 0 1px 0 var(--lg-ink); }

.pet-acc {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px;
  border: 2px solid var(--lg-ink);
  border-radius: 16px;
  background: var(--lg-paper-muted);
  box-shadow: 0 4px 0 var(--lg-ink);
  cursor: pointer;
  transition: transform 140ms var(--lg-spring);
}

.pet-acc:active { transform: translateY(3px) scale(0.98); box-shadow: 0 1px 0 var(--lg-ink); }
/* "Not yours yet" must not look like "broken" — and since 2026-10-01 not grey
   either: a greyed hat on a greyed pet hid the very thing to save up for. Full
   colour shows what the child would get; the gold star price chip carries the
   state. */
.pet-acc:not(.is-owned) .pet-acc-art { opacity: 1; filter: none; }
.pet-acc.is-worn { border-color: var(--lg-ink); background: #fffaf0; outline: 3px solid var(--lg-gold); outline-offset: 2px; }

.pet-acc-cost {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--lg-gold-edge);
  font-size: 13px;
  font-weight: 900;
}

.album-pack { position: relative; padding: 0; border: none; background: none; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 4px; transition: transform 140ms var(--lg-spring); }
.album-pack:active { transform: scale(0.95); }
.album-pack .art-pack { animation: lg-wiggle 2s ease-in-out infinite; transform-origin: 0px 44px; }

.album-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  max-width: 420px;
  padding: 14px;
  border: var(--lg-outline);
  border-radius: var(--lg-radius);
  background: rgba(255, 250, 240, 0.92);
  box-shadow: var(--lg-lift);
}

.album-slot {
  display: grid;
  place-items: center;
  min-height: 88px;
  border: 2px solid var(--lg-ink);
  border-radius: var(--lg-radius-sm);
  background: var(--lg-paper-muted);
}
.album-slot.is-new { animation: lg-sticker-land 620ms var(--lg-spring-big); }
/* Uncollected stickers: one flat paper tone over the whole motif (CSS beats the
   art's presentation attributes); line-only parts stay lines. */
.art-sticker-ghost * { stroke: #c9bda4; }
.art-sticker-ghost [fill]:not([fill="none"]) { fill: #c9bda4; }
@keyframes lg-sticker-land {
  0% { transform: scale(2) rotate(14deg); opacity: 0; }
  60% { transform: scale(0.94) rotate(-3deg); opacity: 1; }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}
.album-complete { color: var(--lg-gold); }

.party-pair { display: flex; align-items: flex-end; gap: 10px; }

@media (max-width: 480px) {
  .play-pet .art-pet { width: 44px; height: auto; }
  .pet-shelf, .album-grid { max-width: 340px; }
}

/* The hidden attribute must always win over explicit display values. */
[hidden] { display: none !important; }

/* ---------- blending (build) game ---------- */
.build-scene {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  padding: 8px 0;
}

.build-slots { display: flex; gap: 12px; }

.build-slot {
  display: grid;
  place-items: center;
  width: clamp(88px, 23vw, 118px);
  aspect-ratio: 1;
  border: 4px dashed rgba(74, 54, 32, 0.35);
  border-radius: 50%;
  background: rgba(255, 250, 240, 0.55);
}

.build-slot.is-filled { border-style: solid; border-color: rgba(74, 54, 32, 0.15); }
.build-slot svg { width: 100%; display: block; animation: lg-arrive 320ms var(--lg-spring); }

.build-tray { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(6px, 2vw, 16px); }

.build-tile {
  width: clamp(88px, 22vw, 116px);
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  filter: drop-shadow(0 6px 8px var(--lg-shadow));
  transition: transform 140ms var(--lg-spring), opacity 200ms ease;
  animation: lg-arrive 320ms var(--lg-spring) backwards;
}

.build-tile:nth-child(2) { animation-delay: 50ms; }
.build-tile:nth-child(3) { animation-delay: 100ms; }
.build-tile:nth-child(4) { animation-delay: 150ms; }
.build-tile:nth-child(5) { animation-delay: 200ms; }

.build-tile svg { width: 100%; display: block; }
.build-tile:active { transform: scale(0.94); }
.build-tile.is-used { opacity: 0.18; pointer-events: none; transform: scale(0.85); }

/* ---------- feedback polish ---------- */
.pop-bubble.is-no svg .tile-face { fill: #e5dcc8; }

.pop-cross {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  animation: lg-arrive 220ms var(--lg-out);
  pointer-events: none;
}

.pop-cross svg { width: 46%; }

.play-bubble.is-pulse { animation: lg-prompt-pulse 900ms var(--lg-spring); }
@keyframes lg-prompt-pulse {
  0%, 100% { transform: scale(1); }
  30% { transform: scale(1.14); box-shadow: 0 5px 0 var(--lg-cream-edge), 0 0 24px rgba(255, 226, 122, 0.95); }
  60% { transform: scale(1.05); }
}

.pairs-card.is-demo { animation: lg-demo-glow 620ms ease 2; }
@keyframes lg-demo-glow {
  0%, 100% { transform: scale(1); filter: none; }
  50% { transform: scale(1.14); filter: drop-shadow(0 0 14px rgba(255, 214, 110, 1)); }
}

/* ---------- check-up & skill flower ---------- */
.map-checkup {
  background: radial-gradient(circle at 34% 28%, #e6d6f0, #8c74b0 78%);
  box-shadow: 0 4px 0 #5e4680;
  color: #fffdf7;
}

.map-checkup:active { transform: translateY(4px); box-shadow: 0 1px 0 #5e4680; }

.pet-flower, .party-flower { display: grid; place-items: center; }
.party-flower { animation: lg-arrive 620ms var(--lg-spring-big); }

@media (max-width: 520px) {
  .map-daily, .map-calendar, .map-pet, .map-album, .map-checkup {
    width: 52px;
    height: 52px;
    min-width: 52px;
  }
  .map-daily-row { gap: 5px; padding: 6px; }
  .play-prompt { width: calc(100% - 116px); min-height: 72px; padding-inline: 8px; }
  .play-prompt .play-mascot { display: none; }
  .play-dots { top: 76px; right: 16px; }
}

/* ---------- production polish ---------- */
.map-tap {
  position: absolute;
  left: 50%;
  bottom: 100%;
  margin: 0 0 2px -22px;
  color: #e8743c;
  filter: drop-shadow(0 2px 3px rgba(80, 30, 10, 0.4));
  animation: lg-tap 1.1s ease-in-out infinite;
  pointer-events: none;
  z-index: 3;
}

@keyframes lg-tap {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(12px); }
}

.pet-stage, .album-stage, .stamps-stage {
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  justify-content: flex-start;
  padding: 12px 0 24px;
}

.pet-stage > :first-child, .album-stage > :first-child { margin-top: 4px; }

/* Pet room wardrobe (2026-07-18): pet pinned up top, shelves swipe sideways —
   vertical scrolling never hides the character. */
.pet-stage.pet-room {
  overflow-y: hidden;
  gap: 10px;
  padding: 4px 0 12px;
  width: 100%;
}
.pet-hero {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  width: 100%;
}
.pet-hero .lg-star-chip { position: absolute; top: 4px; left: 50%; transform: translateX(-50%); }
.pet-hero .pet-flower { position: absolute; right: 10px; bottom: 2px; }
.pet-racks {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(560px, calc(100% - 16px));
}
.pet-room .pet-shelf,
.pet-room .pet-shelf.pet-bodies {
  display: flex;
  grid-template-columns: none;
  max-width: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  gap: 10px;
  padding: 10px 12px;
  scrollbar-width: none;
}
.pet-room .pet-shelf::-webkit-scrollbar { display: none; }
.pet-room .pet-acc { flex: 0 0 auto; width: 82px; }

/* ---------- reduced motion: keep gentle fades, drop movement ---------- */
@media (prefers-reduced-motion: reduce) {
  .art-mascot-body, .art-blob-body, .art-creature-body, .art-pet-body,
  .map-stop.is-current .map-stop-art, .map-stop.is-current::before,
  .party-mascot, .party-pet .art-pet-body, .art-eyes, .map-daily,
  .art-cloud-a, .art-cloud-b, .art-sun-glow, .art-stars > *,
  .art-fireflies circle, .art-bloom, .hatch-egg .art-egg-body,
  .album-pack .art-pack, .map-tap { animation: none; }
  .lg-screen { animation: lg-screen-fade 220ms ease both; }
  .lg-spark { display: none; }
  @keyframes lg-screen-fade {
    from { opacity: 0; }
    to { opacity: 1; }
  }
}

/* ---------- Blend Machine (spec: specs/02-letter-garden-v2.md) ---------- */
/* Two part-tiles pushed together fuse into the spoken syllable. */
.blend-scene {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 300px;
  overflow: hidden;
  touch-action: none; /* the whole scene is a drag surface */
}
.blend-glow {
  position: absolute;
  left: 50%;
  top: 46%;
  width: 130px;
  height: 130px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 240, 180, 0.55), rgba(255, 240, 180, 0));
  animation: blend-breathe 2600ms var(--lg-out) infinite;
  pointer-events: none;
}
@keyframes blend-breathe {
  0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.7; }
  50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
}
.blend-part {
  position: absolute;
  width: clamp(84px, 24vw, 116px);
  transform: translate(-50%, -50%);
  background: none;
  border: 0;
  padding: 0;
  cursor: grab;
  transition: left 460ms var(--lg-spring), top 420ms var(--lg-spring), scale 200ms var(--lg-out);
  animation: lg-arrive 320ms var(--lg-spring) backwards;
}
.blend-part svg { width: 100%; display: block; pointer-events: none; }
.blend-part.is-held { transition: none; cursor: grabbing; z-index: 3; scale: 1.08; }
.blend-part.is-lifted { scale: 1.12; filter: drop-shadow(0 10px 14px rgba(58, 44, 72, 0.28)); }
.blend-part.is-near { scale: 1.16; }
.blend-part.is-fusing {
  transition: left 320ms var(--lg-out), top 380ms var(--lg-out);
  z-index: 2;
  animation: blend-squash 460ms var(--lg-out) 320ms both;
}
.blend-part.is-gone { opacity: 0; pointer-events: none; }
@keyframes blend-squash {
  0% { scale: 1; }
  70% { scale: 1.2 0.7; }
  100% { scale: 0.2; opacity: 0; }
}
.blend-born {
  position: absolute;
  left: 50%;
  top: 46%;
  width: clamp(110px, 32vw, 150px);
  transform: translate(-50%, -50%);
  animation: blend-born-in 620ms var(--lg-spring-big) both;
  pointer-events: none;
}
.blend-born svg { width: 100%; display: block; }
@keyframes blend-born-in {
  0% { transform: translate(-50%, -50%) scale(0.3); opacity: 0; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}

/* ---------- the joining stage (2026-07-18): un-fuse, chain, parade ---------- */
.unfuse-scene {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 300px;
  display: grid;
  place-items: center;
  touch-action: none;
}
.unfuse-whole {
  width: clamp(130px, 38vw, 180px);
  padding: 0;
  border: 0;
  background: none;
  cursor: grab;
  /* --strain: the tile stretches sideways as the child pulls, telegraphing
     that it WANTS to come apart. */
  transform: scaleX(calc(1 + var(--strain, 0) * 0.22)) scaleY(calc(1 - var(--strain, 0) * 0.1));
  transition: transform 140ms var(--lg-out);
}
.unfuse-whole.is-held { cursor: grabbing; }
.unfuse-whole svg { width: 100%; display: block; pointer-events: none; }
.unfuse-halves {
  display: flex;
  flex-direction: row-reverse; /* first letter on the right, reading order */
  gap: 26px;
}
.unfuse-half { width: clamp(96px, 26vw, 128px); }
.unfuse-half svg { width: 100%; display: block; }
.unfuse-half.is-r { animation: unfuse-fly-r 460ms var(--lg-spring-big) both; }
.unfuse-half.is-l { animation: unfuse-fly-l 460ms var(--lg-spring-big) both; }
@keyframes unfuse-fly-r {
  0% { transform: translateX(-40px) scale(0.6); opacity: 0; }
  100% { transform: translateX(0) scale(1); opacity: 1; }
}
@keyframes unfuse-fly-l {
  0% { transform: translateX(40px) scale(0.6); opacity: 0; }
  100% { transform: translateX(0) scale(1); opacity: 1; }
}
.unfuse-quiz { display: flex; gap: 16px; }
.unfuse-pick {
  width: clamp(88px, 24vw, 118px);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  animation: lg-arrive 320ms var(--lg-spring) backwards;
}
.unfuse-pick:nth-child(2) { animation-delay: 70ms; }
.unfuse-pick:nth-child(3) { animation-delay: 140ms; }
.unfuse-pick svg { width: 100%; display: block; pointer-events: none; }

.chain-base {
  position: absolute;
  left: 64%;
  top: 46%;
  width: clamp(110px, 30vw, 148px);
  transform: translate(-50%, -50%);
  transition: width 320ms var(--lg-spring);
}
.chain-base svg { width: 100%; display: block; }
.chain-base.is-near { scale: 1.1; }
.chain-base.is-grown {
  width: clamp(140px, 40vw, 190px);
  animation: blend-born-in 620ms var(--lg-spring-big);
}

/* ---------- biome chapters on the journey map (specs/02) ---------- */
/* Feathered color washes behind the trail — one land per qaida chapter. */
.map-band {
  position: absolute;
  left: 50%;
  width: 100vw;
  transform: translateX(-50%);
  pointer-events: none;
  filter: blur(2px);
}
.map-band.biome-meadow {
  background: linear-gradient(180deg, transparent, rgba(122, 205, 106, 0.22) 25%, rgba(122, 205, 106, 0.22) 75%, transparent);
}
.map-band.biome-orchard {
  background: linear-gradient(180deg, transparent, rgba(255, 178, 92, 0.24) 25%, rgba(255, 194, 46, 0.18) 75%, transparent);
}
.map-band.biome-lagoon {
  background: linear-gradient(180deg, transparent, rgba(96, 190, 232, 0.22) 25%, rgba(126, 208, 242, 0.18) 75%, transparent);
}
.map-band.biome-night {
  background: linear-gradient(180deg, transparent, rgba(74, 59, 122, 0.32) 25%, rgba(58, 44, 96, 0.28) 75%, transparent);
}
.map-band.biome-peaks {
  background: linear-gradient(180deg, transparent, rgba(163, 183, 214, 0.26) 25%, rgba(195, 211, 234, 0.2) 75%, transparent);
}
.map-band.biome-river {
  background: linear-gradient(180deg, transparent, rgba(79, 179, 232, 0.2) 25%, rgba(92, 194, 62, 0.14) 75%, transparent);
}
.map-deco {
  position: absolute;
  width: 64px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  opacity: 0.92;
  animation: lg-sway 5.5s ease-in-out infinite;
}
.map-deco svg { width: 100%; display: block; }
@media (prefers-reduced-motion: reduce) { .map-deco { animation: none; } }

/* Scaffolded retry (specs/02): after a wrong pick, the chosen option quietly
   leaves — the child always lands on success within a tap or two. Opacity +
   desaturation only, so positioned elements never jump. */
.is-scaffolded {
  opacity: 0.1 !important;
  pointer-events: none !important;
  filter: saturate(0.3);
  transition: opacity 460ms var(--lg-out), filter 480ms var(--lg-out);
}

/* ---------- ambient life (specs/02): the garden breathes even at rest ---------- */
.lg-ambient {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 4; /* a soft overlay above the scene, below the topbar (z 5) */
  overflow: hidden;
  opacity: 0.9;
}
.lg-butterfly {
  position: absolute;
  left: -60px;
  width: 34px;
  /* ease-in-out between the meander keyframes = little hovers and surges,
     not a conveyor belt; --amb-dir mirrors the whole flight path. */
  animation: bf-cross var(--amb-dur, 26s) ease-in-out var(--amb-delay, 0s) infinite;
}
.lg-butterfly svg { width: 100%; display: block; }
.bf-wing { transform-origin: 20px 17px; animation: bf-flap var(--flap-dur, 0.32s) ease-in-out infinite; }
.bf-l { animation-name: bf-flap-l; }
.bf-r { animation-name: bf-flap-r; }
@keyframes bf-flap-l { 0%,100% { transform: scaleX(1); } 50% { transform: scaleX(0.35); } }
@keyframes bf-flap-r { 0%,100% { transform: scaleX(1); } 50% { transform: scaleX(0.35); } }
@keyframes bf-cross {
  0%   { transform: translate(0, 0) rotate(-4deg); }
  14%  { transform: translate(calc(var(--amb-dir, 1) * 16vw), -16px) rotate(7deg); }
  26%  { transform: translate(calc(var(--amb-dir, 1) * 22vw), 8px) rotate(-5deg); }
  38%  { transform: translate(calc(var(--amb-dir, 1) * 27vw), -4px) rotate(3deg); }
  56%  { transform: translate(calc(var(--amb-dir, 1) * 50vw), var(--amb-rise, -20px)) rotate(8deg); }
  68%  { transform: translate(calc(var(--amb-dir, 1) * 58vw), 10px) rotate(-6deg); }
  80%  { transform: translate(calc(var(--amb-dir, 1) * 66vw), -8px) rotate(4deg); }
  100% { transform: translate(calc(var(--amb-dir, 1) * 108vw), -12px) rotate(-4deg); }
}
.lg-firefly-amb {
  position: absolute;
  left: -20px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: radial-gradient(circle, #fffdf7 10%, #ffe49a 45%, transparent 72%);
  animation: ff-cross var(--amb-dur, 26s) linear var(--amb-delay, 0s) infinite,
             ff-glow 2.4s ease-in-out infinite;
}
@keyframes ff-cross {
  0%   { transform: translate(0, 0); }
  50%  { transform: translate(52vw, var(--amb-rise, -24px)); }
  100% { transform: translate(106vw, 0); }
}
@keyframes ff-glow { 0%,100% { opacity: 0.25; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .lg-ambient { display: none; } }
/* Perf: the ambient layer sits behind the play panel during mini-games —
   invisible work; stop compositing it entirely. */
body.lg-in-game .lg-ambient { display: none; }

/* ---------- mastery garden: plants that grow with what the child knows ---------- */
.map-plant {
  position: absolute;
  width: 54px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  filter: drop-shadow(0 3px 3px rgba(58, 44, 72, 0.18));
  animation: lg-sway 4.8s ease-in-out infinite;
}
.map-plant svg { width: 100%; display: block; }
@media (prefers-reduced-motion: reduce) { .map-plant { animation: none; } }

/* ---------- grown-up corner (parent-gated) ---------- */
.lg-topbar-right { display: flex; align-items: center; gap: 8px; }
.lg-grownup-dot {
  width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid rgba(74, 54, 32, 0.25);
  background: rgba(255, 250, 240, 0.5);
  cursor: pointer; padding: 0;
  transition: transform 220ms var(--lg-out), background 0.2s ease;
}
.lg-grownup-dot::after { content: "•••"; font-size: 11px; color: rgba(74,54,32,0.5); line-height: 22px; }
.lg-grownup-dot.is-holding { transform: scale(1.25); background: var(--lg-gold-hi); animation: gu-hold 3s linear; }
@keyframes gu-hold { from { box-shadow: 0 0 0 0 var(--lg-gold); } to { box-shadow: 0 0 0 10px transparent; } }

.gu-scroll { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 6px 2px 30px; display: flex; flex-direction: column; gap: 14px; }
.lg-grownup .lg-panel { padding: 16px 18px; }
.gu-head h2 { margin: 0 0 4px; font-size: 1.4rem; color: var(--lg-ink); }
.gu-head p { margin: 0 0 12px; color: #70501b; }
.gu-stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.gu-stat { text-align: center; }
.gu-stat b { display: block; font-size: 1.5rem; color: var(--lg-ink); }
.gu-stat span { font-size: 0.72rem; color: #70501b; }
.gu-section h3 { margin: 0 0 8px; color: var(--lg-ink); font-size: 1.05rem; }
.gu-sub { margin: -4px 0 10px; color: #70501b; font-size: 0.85rem; }
.gu-legend { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 10px; font-size: 0.78rem; color: #70501b; }
.gu-legend span { display: inline-flex; align-items: center; gap: 5px; }
.gu-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }
.gu-strong { background: #7fce54; } .gu-growing { background: #f3c955; }
.gu-love { background: #ee806f; } .gu-new { background: #e5dcc8; }
.gu-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 6px; }
.gu-cell {
  aspect-ratio: 1; border-radius: 12px; display: grid; place-items: center;
  border: 2px solid rgba(74,54,32,0.18);
}
.gu-cell.gu-strong { background: rgba(92,194,62,0.22); border-color: #7fce54; }
.gu-cell.gu-growing { background: rgba(243,201,85,0.22); border-color: #f3c955; }
.gu-cell.gu-love { background: rgba(238,128,111,0.2); border-color: #ee806f; }
.gu-cell.gu-new { background: rgba(216,205,184,0.18); }
.gu-ar { font-family: "Amiri Quran", serif; font-size: 1.3rem; color: var(--lg-ink); }
.gu-ask-cards { display: flex; gap: 10px; }
.gu-ask-card { flex: 1; text-align: center; padding: 14px 8px; border-radius: 18px; border: var(--lg-outline); background: var(--lg-cream); box-shadow: var(--lg-lift-sm); }
.gu-ask-ar { display: block; font-family: "Amiri Quran", serif; font-size: 2.4rem; color: var(--lg-ink); }
.gu-ask-name { font-size: 0.85rem; color: #70501b; }
.gu-ask-none { color: #70501b; font-size: 0.9rem; }

/* ---------- say-it-with-me + Quran-word capstone ---------- */
.meet-card.is-your-turn { animation: meet-your-turn 1.6s var(--lg-spring) infinite; }
.meet-card.is-your-turn::after {
  /* A drawn "your turn" bubble (palette ink + paper), never a platform emoji. */
  content: "";
  position: absolute; top: -6px; right: -6px;
  width: 44px; height: 40px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 40'%3E%3Cpath d='M6 4H38Q42 4 42 8V24Q42 28 38 28H20L10 36V28H6Q2 28 2 24V8Q2 4 6 4Z' fill='%23fffdf7' stroke='%234a3620' stroke-width='3' stroke-linejoin='round'/%3E%3Cpath d='M14 13Q17 16 14 19M20 10Q25 16 20 22M26 8Q33 16 26 24' fill='none' stroke='%23e8743c' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  animation: lg-bounce 0.9s var(--lg-spring) infinite;
}
@keyframes meet-your-turn {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); filter: drop-shadow(0 0 14px var(--lg-gold-hi)); }
}
.party-capstone {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-bottom: 12px; padding: 10px 16px;
  border-radius: var(--lg-radius);
  background: linear-gradient(90deg, var(--lg-gold-hi), #ffe49a);
  border: var(--lg-outline);
  color: var(--lg-gold-deep); font-weight: 800; font-size: 0.95rem;
  text-align: center; line-height: 1.35;
  animation: lg-pop 620ms var(--lg-spring-big) both;
}
.party-capstone svg { flex-shrink: 0; }

/* ---------- pet radiance: shines with what the child knows (specs/02) ---------- */
.pet-big { position: relative; }
.pet-aura {
  position: absolute;
  left: 50%; top: 48%;
  width: calc(180px + var(--pet-radiance, 0) * 120px);
  height: calc(180px + var(--pet-radiance, 0) * 120px);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  opacity: calc(0.25 + var(--pet-radiance, 0) * 0.6);
  background: radial-gradient(circle,
    rgba(255, 236, 150, calc(0.35 + var(--pet-radiance, 0) * 0.4)) 0%,
    rgba(255, 224, 120, 0.18) 42%,
    transparent 70%);
  animation: pet-radiate 3.4s ease-in-out infinite;
}
.pet-big.is-radiant .pet-aura::after {
  content: "";
  position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle, transparent 55%, rgba(255,245,190,calc(var(--pet-radiance,0)*0.5)) 72%, transparent 78%);
}
.pet-big > svg, .pet-big .art-pet { position: relative; z-index: 1; }
@keyframes pet-radiate {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50% { transform: translate(-50%, -50%) scale(1.06); }
}
@media (prefers-reduced-motion: reduce) { .pet-aura { animation: none; } }

/* ---------- touch impact (2026-07-24): the tactile channel iOS leaves open ----------
   The Vibration API is Android-only — iPadOS Safari has no haptics for web
   apps at all — so on the target device the *visual* recoil is what makes a
   tap feel physical. Fired from Haptics.impact() on whatever the finger hit,
   alongside the buzz wherever a buzz is actually available. */
.is-impact { animation: lg-impact 140ms var(--lg-out, var(--lg-out)); }
.is-impact-soft { animation: lg-impact-soft 140ms var(--lg-out, var(--lg-out)); }
@keyframes lg-impact {
  0% { transform: scale(1); }
  38% { transform: scale(0.9); }
  100% { transform: scale(1); }
}
@keyframes lg-impact-soft {
  0% { transform: scale(1); }
  40% { transform: scale(0.965); }
  100% { transform: scale(1); }
}
/* Reduced motion still deserves confirmation that the tap registered — keep a
   brief opacity dip instead of the scale punch. */
@media (prefers-reduced-motion: reduce) {
  .is-impact, .is-impact-soft { animation: lg-impact-flat 140ms var(--lg-out); }
  @keyframes lg-impact-flat {
    0% { opacity: 1; }
    45% { opacity: 0.72; }
    100% { opacity: 1; }
  }
}

/* The egg answers every tap: a sharp shudder that settles. Paired with the
   escalating cracks in Art.egg() so tap 1 and tap 2 are unmistakably
   different — the old build repainted so fast the child saw nothing. */
.art-egg.is-wobble .art-egg-tap { animation: lg-egg-wobble 460ms var(--lg-out, var(--lg-out)); transform-origin: 0px 40px; }
@keyframes lg-egg-wobble {
  0% { transform: rotate(0deg) scale(1); }
  18% { transform: rotate(-5deg) scale(1.04, 0.96); }
  40% { transform: rotate(4.5deg) scale(0.97, 1.03); }
  62% { transform: rotate(-2.5deg) scale(1.02, 0.98); }
  82% { transform: rotate(1.2deg) scale(1); }
  100% { transform: rotate(0deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) { .art-egg.is-wobble .art-egg-tap { animation: none; } }

/* Journey-map hierarchy (2026-07-24): the live stop must win the screen.
   Locked stops sit back — smaller, softer, no competing contour — so a garden
   full of not-yet-earned worlds reads as "more to grow" instead of a wall of
   locks. The current stop already bounces and carries a halo; recessing its
   neighbours is what actually makes it read as the one place to go. */
.map-stop.is-locked { opacity: 1; }
.map-stop.is-locked .map-stop-art { transform: scale(0.8); }
.map-stop.is-locked:active .map-stop-art { transform: scale(0.78); }
/* Done stops stay warm and golden but stop shouting over the live one. */
.map-stop.is-done .map-stop-art { transform: scale(0.94); }
.map-stop.is-current .map-stop-art { transform-origin: 0px 50px; }
@media (prefers-reduced-motion: reduce) {
  .map-stop.is-current .map-stop-art { animation: none; }
  .map-stop.is-current::before { animation: none; }
}

/* ---------- reduced motion, comprehensively (2026-07-24) ----------
   There were 30 infinite animations and 9 hand-written guards, and the guards
   were never going to keep up one selector at a time. Looping ambient motion is
   what actually causes vestibular discomfort, while brief one-shot feedback is
   what makes a wordless UI legible — a child still needs to see the tile respond
   to a tap. So: every loop stops after a single pass, one-shots are untouched,
   and this covers animations added later without needing a new guard. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-iteration-count: 1 !important; }
  /* One allowed pass of a 52-74s cloud drift is still a minute of crawl. */
  .art-cloud-a, .art-cloud-b { animation: none !important; }
}

/* ---------- un-fuse: make the PULL discoverable (2026-07-24) ----------
   This is the only mini-game that needs a drag; every other one is tapped, and
   the joined tile looked identical to a tappable tile. A child tapped it
   forever. Three wordless cues now say "two things, stuck": a seam, arrows
   pointing apart, and an idle tug that performs the gesture on their behalf. */
.unfuse-pull { display: flex; align-items: center; justify-content: center; gap: 6px; }
.unfuse-whole { position: relative; }
.unfuse-seam {
  position: absolute;
  top: 16%; bottom: 22%; left: 50%;
  width: 3px; margin-left: -1.5px;
  border-radius: 2px;
  background: repeating-linear-gradient(to bottom, var(--lg-ink) 0 5px, transparent 5px 10px);
  opacity: 0.32;
  pointer-events: none;
}
.unfuse-arrow {
  color: var(--lg-action);
  width: clamp(20px, 5vw, 28px);
  opacity: 0.75;
  pointer-events: none;
}
.unfuse-arrow svg { width: 100%; display: block; }
.unfuse-arrow.is-r { transform: scaleX(-1); }
/* The demonstration: both arrows lean out and the tile strains, then lets go —
   the same stretch the child's own drag produces, so the gesture is legible. */
.unfuse-whole.is-tugging { animation: unfuse-tug 1100ms var(--lg-out); }
@keyframes unfuse-tug {
  0%, 100% { transform: scaleX(1) scaleY(1); }
  38% { transform: scaleX(1.16) scaleY(0.94); }
  56% { transform: scaleX(1.16) scaleY(0.94); }
}
.unfuse-whole.is-tugging ~ .unfuse-arrow,
.unfuse-pull:has(.is-tugging) .unfuse-arrow { animation: unfuse-arrow-out 1100ms var(--lg-out); }
@keyframes unfuse-arrow-out {
  0%, 100% { transform: translateX(0); opacity: 0.75; }
  38%, 56% { transform: translateX(-7px); opacity: 1; }
}
.unfuse-pull:has(.is-tugging) .unfuse-arrow.is-r { animation-name: unfuse-arrow-out-r; }
@keyframes unfuse-arrow-out-r {
  0%, 100% { transform: scaleX(-1) translateX(0); opacity: 0.75; }
  38%, 56% { transform: scaleX(-1) translateX(-7px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .unfuse-whole.is-tugging { animation: none; }
  .unfuse-pull:has(.is-tugging) .unfuse-arrow { animation: none; opacity: 1; }
}

/* ---------- drag demonstration for Fuse and Chain (2026-07-24) ----------
   Both games accept a plain tap, so unlike un-fuse they never dead-end — but
   nothing showed that a piece is meant to TRAVEL to a target, and the is-near
   highlight only appears once a drag is already under way. Each draggable drifts
   a short way along its own vector toward the target (--hint-dx/--hint-dy, set
   from live geometry) and settles. Applied to every candidate, never only the
   correct one: Chain is a quiz and demoing the right tile would give it away. */
.is-dragdemo {
  animation: drag-demo 1250ms var(--lg-out);
}
@keyframes drag-demo {
  0%, 100% { transform: translate(0, 0); }
  42% {
    transform: translate(calc(var(--hint-dx, 0) * 15px), calc(var(--hint-dy, 0) * 15px));
  }
  62% {
    transform: translate(calc(var(--hint-dx, 0) * 15px), calc(var(--hint-dy, 0) * 15px));
  }
}
/* The receiving end answers, so the pair reads as "from here, to there". */
.is-drop-target { animation: drop-target 1250ms var(--lg-out); }
@keyframes drop-target {
  0%, 100% { transform: scale(1); filter: none; }
  50% { transform: scale(1.06); filter: brightness(1.07); }
}
@media (prefers-reduced-motion: reduce) {
  .is-dragdemo, .is-drop-target { animation: none; }
}

/* ---------- wardrobe shelves: show that they scroll (2026-07-25) ----------
   The shelves hid the scrollbar and replaced it with nothing, so a shelf whose
   last tile happened to land flush read as COMPLETE and children never swiped.
   The edge holding more content now fades, and tiles snap, so the gesture has
   both an invitation and a satisfying landing. Classes come from wireShelf(). */
.pet-room .pet-shelf { scroll-snap-type: x proximity; scroll-padding-left: 12px; }
.pet-room .pet-acc { scroll-snap-align: center; }
.pet-room .pet-shelf.can-right {
  -webkit-mask-image: linear-gradient(to right, #0a1f1a 0, #0a1f1a 84%, transparent 100%);
          mask-image: linear-gradient(to right, #0a1f1a 0, #0a1f1a 84%, transparent 100%);
}
.pet-room .pet-shelf.can-left {
  -webkit-mask-image: linear-gradient(to left, #0a1f1a 0, #0a1f1a 84%, transparent 100%);
          mask-image: linear-gradient(to left, #0a1f1a 0, #0a1f1a 84%, transparent 100%);
}
.pet-room .pet-shelf.can-left.can-right {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #0a1f1a 9%, #0a1f1a 91%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #0a1f1a 9%, #0a1f1a 91%, transparent 100%);
}

/* The day-count stat doubles as the way into the stamp calendar, which moved out
   of the child's toolbar and into the grown-up corner (2026-07-25). */
.gu-stat.gu-stamps-link {
  border: none;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: inherit;
  transition: transform 140ms var(--lg-out);
}
.gu-stat.gu-stamps-link:active { transform: scale(0.97); }

/* ---------- fingers on every new letter (2026-07-25) ----------
   Dragging across the meet card warms the letter up and it speaks again. Purely
   tactile: always succeeds, earns nothing, and never gates the Next button — a
   toll booth on the intro is on the declined list. --traced is driven from the
   drag distance; the sparkle trail comes free from the global spark layer. */
.meet-card { position: relative; --traced: 0; }
.meet-card::after {
  content: "";
  position: absolute;
  inset: -8%;
  border-radius: 28px;
  background: radial-gradient(circle, rgba(243, 201, 85, 0.5), rgba(243, 201, 85, 0) 68%);
  opacity: var(--traced);
  pointer-events: none;
  transition: opacity 140ms var(--lg-out);
}
.meet-card.is-traced { animation: meet-traced 620ms var(--lg-spring); }
@keyframes meet-traced {
  0% { transform: scale(1); }
  45% { transform: scale(1.07); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .meet-card.is-traced { animation: none; }
}

/* Boat Letters: the live chapter, grounded in one quiet paper riverbank. */
.lg-boat-chapter {
  background: radial-gradient(ellipse at 50% 32%, #fffdf7 0%, #fffaf0 42%, #ccfbef 100%);
}
.lg-boat-chapter[data-garden-phase="night"] {
  background: radial-gradient(ellipse at 50% 32%, #6064a0, #34375f);
}
.garden-scenery, .garden-land { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.garden-shore-boat { position: absolute; bottom: 1%; left: 4%; width: clamp(180px, 25vw, 310px); }
.garden-boat { display: block; width: 100%; height: auto; overflow: visible; }
.garden-reeds { position: absolute; width: clamp(76px, 12vw, 150px); right: 1%; bottom: 1%; }
.lg-calm-garden .lg-ambient, .lg-calm-garden .lg-spark { display: none; }
.lg-boat-chapter .lg-screen { animation: lg-screen-fade 220ms ease both; }
.lg-boat-chapter .meet-stage,
.lg-boat-chapter .stars-stage,
.lg-boat-chapter .party-stage {
  border: 0; background: none; box-shadow: none; padding: 12px;
  width: min(620px, 100%); margin: auto; flex: 0 1 auto;
}
.lg-boat-chapter .meet-stage { gap: 18px; padding-bottom: 72px; }
.lg-boat-chapter .meet-card .art-blob { width: clamp(260px, 34vw, 390px); max-height: 49vh; }
.lg-boat-chapter .meet-card { padding: 0; }
.lg-boat-chapter .meet-bud { border: 3px solid #4a3620; background: radial-gradient(circle at 35% 28%, #fffdf7, #ffe49a 65%, #c69434); box-shadow: 0 7px 0 #70501b; }
.lg-boat-chapter .meet-dots { padding: 10px 16px; background: #fffaf0; border-radius: 24px; }

.play-pet { border: 0; padding: 0; background: none; cursor: pointer; }

.lg-boat-chapter .play-mascot > svg { width: 78px; height: 98px; }



.lg-boat-chapter .play-dots { position: static; align-self: center; padding: 9px 12px; background: #fffaf0; border-radius: 30px; gap: 7px; }
.lg-boat-chapter .play-stage { width: min(760px, 100%); flex: 1; max-height: min(540px, 60vh); min-height: 0; margin: 0 auto 10px; mask-image: none; -webkit-mask-image: none; overflow: hidden; }
.lg-boat-chapter .feed-scene { padding: 0 5px 16px; }
.lg-boat-chapter .feed-creature { width: clamp(190px, 27vw, 264px); max-height: 58%; }
.lg-boat-chapter .feed-creature > svg { height: 100%; max-height: 32vh; }
.lg-boat-chapter .art-creature-body > path:first-of-type { stroke: #4a3620; stroke-width: 3; }
.lg-boat-chapter .art-creature-mouth > ellipse:first-child { fill: #4a3620; }
.lg-boat-chapter .art-creature-mouth > ellipse:nth-child(2) { fill: #ee806f; }
.lg-boat-chapter .art-creature-mouth > path { fill: #fffdf7; }
.lg-boat-chapter .feed-tray { width: 100%; justify-content: center; gap: 10px; padding: 10px 4px; border-bottom: 9px solid #c9bda4; border-radius: 30px; background: #fffaf0; }
.lg-boat-chapter .feed-food { width: min(22%, 124px); }
.lg-boat-chapter .stars-stage { gap: 18px; padding-bottom: 70px; }
.garden-reward { width: clamp(220px, 38vw, 370px); }
.garden-reward .is-grown .garden-petals { animation: garden-bloom 620ms var(--lg-spring) both; transform-box: fill-box; transform-origin: center bottom; }
@keyframes garden-bloom { from { opacity: 0; scale: .7; } to { opacity: 1; scale: 1; } }
.lg-boat-chapter .stars-row { padding: 10px 22px; border-radius: 40px; background: #fffaf0; }
.lg-boat-chapter .party-stage { gap: 8px; padding-bottom: 28px; }
.lg-boat-chapter .party-pair { gap: 16px; }
.lg-boat-chapter .party-pair svg { max-height: 150px; }
.lg-boat-chapter .party-stars { padding: 0 20px; border-radius: 40px; background: #fffaf0; }
.lg-boat-chapter .party-stars svg { width: 44px; height: 44px; }
.garden-reward-finished { width: clamp(180px, 30vw, 290px); }
.map-boat-landmark { position: absolute; width: 200px; transform: translate(-50%, -38%); pointer-events: none; z-index: 1; }
.lg-boat-chapter button:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 5px; }
@media (max-width: 600px) {


  .lg-boat-chapter .play-mascot { display: none; }


  .lg-boat-chapter .play-dots { padding: 8px; gap: 5px; }
  .lg-boat-chapter .play-dots i { width: 11px; height: 11px; }
  .lg-boat-chapter .play-stage { max-height: 58vh; margin-bottom: 80px; }
  .lg-boat-chapter .meet-stage { padding-bottom: 84px; }
  .garden-shore-boat { left: 0; width: 180px; bottom: 0; }
  .map-boat-landmark { width: 160px; }
}
@media (max-height: 650px) {
  .lg-boat-chapter .meet-stage { gap: 8px; padding-bottom: 10px; }
  .lg-boat-chapter .meet-card .art-blob { max-height: 45vh; width: 250px; }


  .lg-boat-chapter .play-stage { margin-bottom: 22px; max-height: 61vh; }
  .lg-boat-chapter .feed-creature > svg { max-height: 26vh; }
  .lg-boat-chapter .stars-stage { padding-bottom: 0; gap: 8px; }
  .garden-reward { width: 220px; }
  .garden-reward-finished { width: 170px; }
  .lg-boat-chapter .party-pair svg { max-height: 94px; }
  .lg-boat-chapter .party-stage { padding-bottom: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .lg-boat-chapter *, .lg-boat-chapter *::before, .lg-boat-chapter *::after { animation: none !important; transition: none !important; }
  .lg-boat-chapter .feed-food.is-flying { transform: none; opacity: .25; }
}
.lg-boat-chapter:has(.lg-stars, .lg-party) .garden-shore-boat { visibility: hidden; }
.gu-motion-toggle { margin-top: 12px; }
.gu-motion-toggle[aria-pressed="true"] { background: #b7e779; }
.lg-reduce-motion *, .lg-reduce-motion *::before, .lg-reduce-motion *::after { animation: none !important; transition: none !important; }
body.lg-reduce-motion .lg-ambient, body.lg-reduce-motion .lg-spark { display: none; }
.lg-reduce-motion .feed-food.is-flying { transform: none; opacity: .25; }

/* A calm corrective cue for a first recognition activity. */
.lg-boat-chapter .pop-bubble.is-helpful{filter:drop-shadow(0 0 9px #f3c955)}
/* Reward portraits keep eye contact even during the idle blink cycle. */
.art-face[data-mood="delighted"] .art-eyes,
.art-face[data-mood="proud"] .art-eyes { animation: none; transform: none; }
/* Live optional practice: the learning object remains the focus. */
.garden-practice-links{display:flex;gap:10px;justify-content:center}
.garden-practice-links button,.practice-button,.practice-replay{border:3px solid #4a3620;border-radius:20px;background:#fffaf0;color:#4a3620;min-width:54px;min-height:50px;font:28px 'Amiri Quran',serif;cursor:pointer;box-shadow:0 4px 0 #c9bda4}
.garden-practice-links button{padding:0 14px;font-size:24px}.garden-practice-links span{font:16px system-ui}
.practice-heading{display:flex;align-items:center;justify-content:center;gap:24px;margin:76px auto 4px;flex-shrink:0}
.practice-replay{font-size:44px;width:96px}
.practice-stage{width:min(760px,96%);min-height:0;flex:1;margin:0 auto 14px}
.dot-garden,.garden-paths{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px}
.dot-bed,.path-paper{position:relative;width:min(500px,94%);background:#fffaf0;border:3px solid #a89478;border-radius:36px}
.dot-bed{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;min-height:190px;max-height:340px}
.dot-base{font:140px/1 'Geeza Pro','Arial',sans-serif;pointer-events:none;color:#4a3620}
.dot-zone{height:54px;width:150px;box-shadow:none;border:2px dashed #a89478;min-height:48px;font:24px system-ui;letter-spacing:12px;background:#e5dcc8}
.practice-tools{display:flex;gap:18px;justify-content:center}.dot-seed{touch-action:none;position:relative;z-index:3;font:30px system-ui}
.practice-button:disabled{opacity:.45;cursor:default}.is-dragging{z-index:20!important;position:relative;pointer-events:auto;filter:drop-shadow(0 8px 6px #a89478)}
.practice-button.is-selected,.feed-food[aria-pressed=true]{outline:4px solid #4e9677;outline-offset:4px}
.dot-zone.is-help,.dot-answers .is-help{background:#ffe49a}.dot-answers{display:flex;gap:28px}.dot-answers button{font-size:80px;min-width:100px;min-height:120px}
.practice-listen{font-size:50px;color:#4e9677}.practice-status{height:20px;color:#4e9677}
.path-paper{flex:1;max-height:360px;min-height:180px;overflow:hidden}
.path-paper canvas{width:100%;height:100%;position:absolute;inset:0;touch-action:none}
.path-guide{position:absolute;inset:0;display:grid;place-items:center;font:180px 'Geeza Pro',Arial,sans-serif;color:#c9bda4;pointer-events:none}
.path-guide[hidden]{display:none}
.lg-boat-chapter .feed-scene{gap:8px}.feed-basket{width:150px;min-height:58px;border:3px solid #4a3620;border-radius:12px 12px 32px 32px;background:#e5dcc8;color:#4a3620;font:48px/1 system-ui;cursor:pointer;flex-shrink:0}
.lg-boat-chapter .feed-food{touch-action:none;position:relative}.lg-boat-chapter .feed-creature{display:flex;justify-content:center;max-height:38%;pointer-events:none}
.lg-boat-chapter .feed-creature>.lg-animal{height:100%!important;width:auto!important;aspect-ratio:420/470}
.lg-boat-chapter .feed-creature>svg{max-height:22vh}
@media(max-height:650px){.practice-heading{margin-top:64px;height:70px}.practice-heading>.lg-animal{height:68px!important;width:61px!important}.practice-heading>svg{height:68px;width:62px}.dot-garden,.garden-paths{gap:8px}.dot-base{font-size:110px}.dot-zone{height:48px}.practice-tools{gap:12px}.practice-button{min-height:46px}.lg-boat-chapter .stars-stage,.lg-boat-chapter .party-stage{gap:10px}.lg-boat-chapter .feed-creature{max-height:29%}.feed-basket{min-height:48px;font-size:36px}}

.lg-boat-chapter .feed-scene{justify-content:flex-start;gap:4px}
.lg-boat-chapter .feed-creature{height:180px;max-height:none;flex-shrink:0}
.lg-boat-chapter .feed-tray{margin-top:auto}
.feed-basket{background:none;border:0;box-shadow:none;padding:0;width:150px;height:60px}
.feed-basket svg{display:block;width:100%;height:100%}
@media(max-height:650px){.lg-boat-chapter .feed-creature{height:120px;max-height:none}.feed-basket{height:48px;min-height:48px}}

.dot-zone{position:relative}.dot-zone::before{content:attr(data-hint);position:absolute;inset:0;display:grid;place-items:center;color:#a89478;opacity:.30;pointer-events:none;letter-spacing:12px}
.dot-zone span{position:relative;z-index:1}
.feed-creature.is-chomp .lg-animal{animation:lg-seed-thanks 450ms ease-out}
@keyframes lg-seed-thanks{50%{transform:translateY(-5px) rotate(3deg)}}
@media(prefers-reduced-motion:reduce){.feed-creature.is-chomp .lg-animal{animation:none}}
.lg-reduce-motion .feed-creature.is-chomp .lg-animal{animation:none}
.practice-heading{margin:6px auto;height:86px}
.practice-replay{height:76px;line-height:1;font-family:'Geeza Pro',Arial,sans-serif}
.practice-tools{flex-shrink:0}.practice-tools .practice-button{height:52px;line-height:1;font-family:system-ui,sans-serif}
@media(max-height:650px){.practice-heading{margin:4px auto;height:72px}.practice-replay{height:66px}.practice-stage{margin-bottom:4px}}

.dot-zone::before{content:none}.dot-zone .dot-hint,.dot-zone .dot-placed{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none}
.dot-zone .dot-hint{opacity:.25}.dot-zone .dot-cluster{position:relative;display:flex;justify-content:center;gap:5px;letter-spacing:0;line-height:1;font:18px/1 system-ui}
.dot-cluster i{font-style:normal}.dot-zone .dots-3{display:grid;grid-template-columns:18px 18px;grid-template-rows:15px 15px;gap:0}.dots-3 i:first-child{grid-column:1/3;justify-self:center}
/* A quieter, permanent garden map. Clear destinations, one current stop. */
.lg-screen.lg-home{background:transparent}
.map-title{position:absolute;left:22px;top:15px;margin:0;font:700 24px/44px ui-rounded,system-ui,sans-serif;color:#4a3620}
.lg-home .lg-topbar{min-height:56px;flex-shrink:0}
.lg-home .map-daily-row{position:relative;top:auto;left:auto;transform:none;align-self:center;max-width:100%;margin:12px 0 8px;padding:6px 12px;border:1px solid #e5dcc8;border-radius:26px;box-shadow:0 5px 0 #e5dcc8;gap:12px;flex-shrink:0}
.lg-home .map-daily-row button{width:58px;height:58px;min-width:48px;border-radius:18px;background:#fffdf7;border:2px solid #c9bda4;box-shadow:0 3px 0 #c9bda4}
.map-practice-garden{display:flex;align-items:center;justify-content:center;gap:14px;align-self:center;width:min(400px,94%);min-height:52px;margin:8px 0 14px;border:2px solid #4e9677;border-radius:20px;background:#fffaf0;color:#2f5c46;box-shadow:0 4px 0 #c9bda4;font:600 17px system-ui;cursor:pointer;flex-shrink:0}
.map-practice-garden:disabled{opacity:.45;cursor:default}.map-practice-garden:active:not(:disabled){transform:translateY(2px)}
.lg-home .map-scroll{mask-image:linear-gradient(transparent,#0a1f1a 22px,#0a1f1a calc(100% - 20px),transparent)}
.lg-home .map-path{max-width:470px}.lg-home .map-stop{width:clamp(100px,27vw,126px)}
.lg-home .map-stop.is-current .map-stop-art{animation:none;transform:scale(1.04);transform-origin:center}
.lg-home .map-stop.is-current::before{animation:none;inset:-7px;border:3px solid #4e9677;background:#b7e77955;border-radius:50%}
.lg-home .map-stop.is-locked .map-stop-art{transform:scale(.72);opacity:1}
.lg-home .map-here{pointer-events:none}.lg-home .map-deco{opacity:1}.lg-home .map-band{opacity:.55}
.lg-home .map-boat-landmark{width:160px}
.practice-garden-hub{width:min(700px,100%);margin:auto;z-index:2;text-align:center;color:#4a3620}
.practice-garden-hub h1{font:700 28px ui-rounded,system-ui}.practice-garden-hub p{font:16px system-ui;color:#4e9677}
.practice-garden-choices{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin:24px 0}
.practice-garden-choices button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;min-height:190px;padding:12px;border:3px solid #4a3620;border-radius:26px;background:#fffaf0;box-shadow:0 6px 0 #c9bda4;cursor:pointer;color:#4a3620}
.practice-garden-choices strong{font:600 16px system-ui}.practice-symbol{display:grid;place-items:center;min-height:110px;font:38px 'Geeza Pro',Arial,sans-serif}
.practice-garden-choices button:active{transform:translateY(3px);box-shadow:0 3px 0 #c9bda4}
.lg-screen button:focus-visible{outline:4px solid var(--lg-focus);outline-offset:4px}
@media(max-width:600px){.map-title{left:18px;font-size:22px}.lg-home .map-daily-row{gap:8px;padding:6px 8px}.lg-home .map-daily-row button{width:52px;height:52px}.practice-garden-choices{grid-template-columns:1fr;gap:12px;margin:16px 0}.practice-garden-choices button{flex-direction:row;justify-content:flex-start;min-height:92px;padding:6px 18px}.practice-garden-choices button>.lg-animal{width:68px!important;height:76px!important}.practice-garden-choices button>svg{width:68px;height:76px}.practice-symbol{min-height:76px;width:88px;font-size:32px}.practice-garden-hub h1{margin:12px 0}}
.lg-home .map-daily-row .map-daily{color:#b0501f}
.lg-home .map-daily-row .map-checkup{color:#4e9677}

/* Keep the scenery; navigation is readable through pictures, never prose. */
.map-practice-garden{width:112px;min-height:54px;gap:18px;margin:8px 0 10px}
.practice-garden-choices button{position:relative;gap:8px;overflow:hidden;background:linear-gradient(#fffdf7,#fffaf0)}
.practice-garden-choices .practice-picture{display:block;width:100%;height:auto;max-height:200px;flex:1;min-width:0}
.practice-play{display:grid;place-items:center;width:42px;height:42px;border-radius:50%;background:#b7e779;flex-shrink:0}
.album-grid{width:min(420px,100%);box-sizing:border-box;gap:10px;flex-shrink:0;background:#fffaf0;border-color:#70501b;box-shadow:0 6px 0 #a89478}
.album-slot{min-width:0;min-height:0;aspect-ratio:1;padding:3px;border:1px dashed #c9bda4;border-radius:18px;background:#e5dcc8;box-shadow:inset 0 2px 3px #80634112}
.album-slot .art-sticker{display:block;width:100%;height:100%;max-width:88px;max-height:88px;min-width:0}
@media(max-width:600px){.practice-garden-choices button{flex-direction:row;justify-content:center;min-height:118px;padding:8px 16px}.practice-garden-choices .practice-picture{width:160px;height:110px;flex:0 1 190px}.album-grid{gap:7px;padding:10px}}

/* ---------- living lands (2026-10-01) ---------- */
/* Travel paths are short loops in viewBox pixels; inner groups flap/bob. All of
   it is scenery: no pointer events, and removed entirely under reduced motion. */
.art-life { pointer-events: none; }
.art-life .life-travel, .art-life .life-fall, .art-life .life-jump, .art-life .life-ring,
.art-life .life-drift, .art-life .life-flap, .art-life .life-bob, .art-life .life-spin, .art-life .life-glide {
  transform-box: fill-box; transform-origin: 50% 50%;
}
.art-life .life-flap { animation: life-flap 0.32s ease-in-out infinite alternate; }
.art-life .life-bob { animation: life-bob 1.8s ease-in-out infinite alternate; }
.art-life .life-hover-a { animation: life-hover-a 9s ease-in-out infinite; }
.art-life .life-hover-b { animation: life-hover-b 11s ease-in-out infinite; }
.art-life .life-orbit-a { animation: life-orbit 4.6s linear infinite; }
.art-life .life-orbit-b { animation: life-orbit 5.4s linear infinite reverse; }
.art-life .life-fall { animation: life-fall 7.5s linear infinite; opacity: 0; }
.art-life .life-spin { animation: life-spin 2.4s ease-in-out infinite alternate; }
.art-life .life-jump { animation: life-jump 7s ease-in-out infinite; opacity: 0; }
.art-life .life-ring { animation: life-ring 7s ease-out infinite; opacity: 0; transform-origin: 50% 50%; }
.art-life .life-glide-a { animation: life-glide 26s linear infinite; }
.art-life .life-glide-b { animation: life-glide 32s linear infinite; }
.art-life .life-glide { animation: life-wings 1.6s ease-in-out infinite alternate; }
.art-life .life-drift { animation: life-drift 30s linear infinite; }
@keyframes life-flap { from { transform: scaleX(1); } to { transform: scaleX(0.35); } }
@keyframes life-bob { from { transform: translateY(-2px) rotate(-3deg); } to { transform: translateY(2px) rotate(3deg); } }
@keyframes life-hover-a { 0%,100% { transform: translate(0,0); } 25% { transform: translate(30px,-26px); } 50% { transform: translate(-8px,-40px); } 75% { transform: translate(-26px,-12px); } }
@keyframes life-hover-b { 0%,100% { transform: translate(0,0); } 30% { transform: translate(-28px,-20px); } 60% { transform: translate(14px,-38px); } 80% { transform: translate(24px,-10px); } }
@keyframes life-orbit { from { transform: rotate(0deg) translateX(22px) rotate(0deg); } to { transform: rotate(360deg) translateX(22px) rotate(-360deg); } }
@keyframes life-fall { 0% { opacity: 0; transform: translate(0,0); } 10% { opacity: 1; } 50% { transform: translate(18px,70px); } 90% { opacity: 1; } 100% { opacity: 0; transform: translate(-6px,150px); } }
@keyframes life-spin { from { transform: rotate(-40deg); } to { transform: rotate(40deg); } }
@keyframes life-jump { 0%,70% { opacity: 0; transform: translate(0,0) rotate(0); } 72% { opacity: 1; } 80% { transform: translate(24px,-34px) rotate(-30deg); } 88% { opacity: 1; transform: translate(48px,0) rotate(40deg); } 90%,100% { opacity: 0; transform: translate(48px,4px) rotate(40deg); } }
@keyframes life-ring { 0%,88% { opacity: 0; transform: scale(0.4); } 90% { opacity: 1; } 100% { opacity: 0; transform: scale(1.8); } }
@keyframes life-glide { from { transform: translateX(0); } to { transform: translateX(900px); } }
@keyframes life-wings { from { transform: scaleY(1); } to { transform: scaleY(0.55); } }
@keyframes life-drift { 0% { transform: translate(0,0); } 25% { transform: translate(-272px,44px); } 50% { transform: translate(-512px,100px); } 75% { transform: translate(-692px,124px); } 100% { transform: translate(-860px,130px); } }
.lg-reduce-motion .art-life { display: none; }
@media (prefers-reduced-motion: reduce) { .art-life { display: none; } }
.garden-scenery .garden-life{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}

/* ---------- meet sign reveal + letter trail (2026-10-01) ---------- */
.meet-card .art-sign .sign-wipe { transform-box: fill-box; transform-origin: 100% 50%; }
.meet-card .art-sign[data-dir="ltr"] .sign-wipe { transform-origin: 0% 50%; }
.meet-card.is-born .art-sign .sign-wipe { animation: sign-wipe 1100ms cubic-bezier(.45,.05,.4,1) 260ms both; }
.art-sign .sign-pen { opacity: 0; }
.meet-card.is-born .art-sign .sign-pen { animation: sign-pen 1100ms cubic-bezier(.45,.05,.4,1) 260ms both; }
.meet-card.is-born .art-sign[data-dir="ltr"] .sign-pen { animation-name: sign-pen-ltr; }
@keyframes sign-wipe { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes sign-pen { 0% { opacity: 0; translate: 0 0; } 10% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; translate: -190px 0; } }
@keyframes sign-pen-ltr { 0% { opacity: 0; translate: 0 0; } 10% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; translate: 190px 0; } }
.lg-reduce-motion .meet-card .art-sign .sign-wipe, .lg-reduce-motion .meet-card .art-sign .sign-pen { animation: none !important; }
@media (prefers-reduced-motion: reduce) { .meet-card .art-sign .sign-wipe, .meet-card .art-sign .sign-pen { animation: none !important; } }
.meet-trail { align-items: center; }
.meet-trail i.is-met {
  width: 40px; height: 34px; padding: 0; box-sizing: border-box;
  display: grid; place-items: center; overflow: hidden; border-radius: 10px 10px 12px 12px;
  background: #fffaf0; border: 2px solid #a89478; box-shadow: 0 2px 0 #c9bda4;
}
.meet-trail i.is-met svg { display: block; }

/* ---------- daily weather (2026-10-01) ---------- */
/* Behind the screen's content (the screen isolates its own stacking), over the
   map scroll on home, and under every control. */
.lg-screen { isolation: isolate; }
.lg-weather { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.lg-home > .lg-weather { z-index: 2; }
.wx-rain { position: absolute; inset: -20% 0 0; background: repeating-linear-gradient(105deg, transparent 0 26px, #ccfbef66 26px 28px, transparent 28px 61px); animation: wx-rain 0.9s linear infinite; }
.wx-rain.is-far { opacity: .55; background-size: 140% 140%; animation-duration: 1.4s; }
@keyframes wx-rain { from { transform: translate(0, 0); } to { transform: translate(-16px, 60px); } }
.wx-leaf { position: absolute; left: -40px; width: calc(28px * var(--k, 1)); height: calc(18px * var(--k, 1)); animation: wx-leaf 12s linear infinite; }
@keyframes wx-leaf { 0% { transform: translate(0, 0) rotate(0); } 25% { transform: translate(28vw, 26px) rotate(140deg); } 50% { transform: translate(55vw, -6px) rotate(250deg); } 75% { transform: translate(82vw, 30px) rotate(400deg); } 100% { transform: translate(115vw, 8px) rotate(540deg); } }
.wx-rainbow { position: absolute; left: -6%; top: 9%; width: min(70%, 460px); opacity: .5; }
.lg-home > .lg-weather .wx-rainbow { opacity: .35; }
.lg-reduce-motion .wx-rain, .lg-reduce-motion .wx-leaf { display: none; }
@media (prefers-reduced-motion: reduce) { .wx-rain, .wx-leaf { display: none; } }

/* ---------- land-made activity boards (2026-10-01) ---------- */
/* Every board stays mid-to-dark so cream tiles and dashed targets keep their
   contrast; the meadow keeps the original green board. */
.lg-app[data-land="orchard"] { --lg-board: linear-gradient(110deg, #ffe49a55 -10%, transparent 35%), repeating-linear-gradient(180deg, #c69434 0 34px, #70501b 34px 37px); --lg-board-edge: #70501b; }
.lg-app[data-land="lagoon"] { --lg-board: radial-gradient(circle at 30% 30%, #ccfbef 0 3px, transparent 4px) 0 0 / 46px 46px, radial-gradient(circle at 70% 75%, #96ecff 0 2px, transparent 3px) 0 0 / 46px 46px, linear-gradient(160deg, #62cdf4 -20%, #3a8fc4 45%, #34375f 105%); --lg-board-edge: #34375f; }
.lg-app[data-land="night"] { --lg-board: radial-gradient(ellipse at 50% -10%, #ffe49a66 0, transparent 55%), linear-gradient(170deg, #4a4d84, #23253f); --lg-board-edge: #23253f; }
.lg-app[data-land="peaks"] { --lg-board: repeating-linear-gradient(62deg, transparent 0 70px, #70501b44 70px 72px), linear-gradient(115deg, #c9bda4 -20%, #a89478 40%, #70501b 100%); --lg-board-edge: #70501b; }
.lg-app[data-land="river"] { --lg-board: repeating-linear-gradient(0deg, transparent 0 22px, #3e523666 22px 24px), repeating-linear-gradient(90deg, #647d4e 0 10px, #3e5236 10px 12px); --lg-board-edge: #3e5236; }

/* Writing Garden (v3): the meet reveal writes the letter with its real strokes,
   then the printed letter settles in and the strokes fade. Static signs (and
   reduced motion) show only the printed letter. */
.art-sign .sign-strokes { opacity: 0; }
.meet-card.is-born .art-sign:has(.sign-strokes) .sign-wipe { animation: none; }
.meet-card.is-born .art-sign:has(.sign-strokes) .sign-pen { display: none; }
.meet-card.is-born .art-sign:has(.sign-strokes) .sign-ink { animation: sign-ink-in 420ms ease-out calc(var(--t, 1s) + 0.35s) both; }
.meet-card.is-born .art-sign .sign-strokes { animation: sign-strokes-out 500ms ease-in calc(var(--t, 1s) + 0.45s) both; }
.meet-card.is-born .art-sign .sign-strokes path { stroke-dasharray: 100 100; animation: sign-stroke 420ms ease-in-out calc(var(--d) + 0.25s) both; }
.meet-card.is-born .art-sign .sign-strokes circle { transform-box: fill-box; transform-origin: 50% 50%; animation: sign-dot 220ms cubic-bezier(.3,1.6,.5,1) calc(var(--d) + 0.25s) both; }
@keyframes sign-stroke { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
@keyframes sign-dot { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes sign-strokes-out { 0% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sign-ink-in { from { opacity: 0; } to { opacity: 1; } }
.lg-reduce-motion .meet-card .art-sign .sign-strokes, .lg-reduce-motion .meet-card .art-sign .sign-ink { animation: none !important; }
@media (prefers-reduced-motion: reduce) { .meet-card .art-sign .sign-strokes, .meet-card .art-sign .sign-ink { animation: none !important; } }

/* ---------- v6 Letter Hunt ---------- */
.lg-play[data-activity="hunt"] .practice-stage { display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 8px; }
.hunt { position: relative; display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 8px; width: min(100%, 760px); height: 100%; margin: 0 auto; }
.hunt-scene { width: 100%; height: 100%; min-height: 300px; max-height: 100%; border: 3px solid #4a3620; border-radius: 28px; box-shadow: 0 6px 0 #4a3620; background: #96ecff; }
.hunt-spot { cursor: pointer; outline: none; }
.hunt-spot:focus-visible .hunt-thing { filter: drop-shadow(0 0 0 #e8743c) drop-shadow(0 0 6px #e8743c); }
.hunt-thing { transform-box: fill-box; transform-origin: 50% 100%; }
.hunt-spot.is-found .hunt-letter { fill: #4e9677; }
.hunt-spot.is-found .hunt-thing { animation: hunt-found 900ms cubic-bezier(.3,1.5,.5,1) both; }
.hunt-spot.is-kite.is-found .hunt-thing, .hunt-spot.is-cloud.is-found .hunt-thing, .hunt-spot.is-lantern.is-found .hunt-thing { animation-name: hunt-float; }
.hunt-spot.is-sail.is-found .hunt-thing, .hunt-spot.is-lily.is-found .hunt-thing { animation-name: hunt-bob; }
@keyframes hunt-found { 0% { transform: none; } 40% { transform: translateY(-8%) scale(1.12); } 100% { transform: scale(1.04); } }
@keyframes hunt-float { 0% { transform: none; } 50% { transform: translateY(-14%) rotate(-6deg); } 100% { transform: translateY(-6%); } }
@keyframes hunt-bob { 0%, 100% { transform: none; } 30% { transform: translateY(-6%) rotate(-4deg); } 65% { transform: translateY(2%) rotate(3deg); } }
.hunt-basket { display: flex; justify-content: center; gap: 8px; min-height: 46px; padding: 6px 10px; margin: 0 auto; border: 3px solid #4a3620; border-radius: 16px 16px 24px 24px; background: repeating-linear-gradient(90deg, #c69434 0 14px, #a89478 14px 16px); box-shadow: 0 4px 0 #70501b; min-width: 180px; }
.hunt-found { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: #fffaf0; border: 2px solid #4a3620; font: 22px/1 "Amiri Quran", serif; color: #4a3620; animation: hunt-drop 420ms cubic-bezier(.3,1.5,.5,1) both; padding-bottom: 6px; box-sizing: border-box; }
@keyframes hunt-drop { from { transform: translateY(-30px) scale(.5); opacity: 0; } to { transform: none; opacity: 1; } }
.lg-reduce-motion .hunt-spot .hunt-thing, .lg-reduce-motion .hunt-found { animation: none !important; }
@media (prefers-reduced-motion: reduce) { .hunt-spot .hunt-thing, .hunt-found { animation: none !important; } }

/* ---------- v7 Read Together ---------- */
.rt-stage { position: relative; display: grid; justify-items: center; align-content: center; gap: 14px; width: min(100%, 520px); margin: auto; padding: 8px 4px 24px; }
.rt-dots { display: flex; gap: 8px; }
.rt-dots i { width: 14px; height: 14px; border-radius: 50%; border: 2px solid #4a3620; background: #e5dcc8; }
.rt-dots i.is-on { background: #f3c955; transform: scale(1.2); }
.rt-dots i.is-done { background: #7fce54; }
.rt-card { width: min(78vw, 300px); }
.rt-card svg { display: block; width: 100%; height: auto; }
.rt-controls { display: grid; grid-template-columns: 1fr 1fr 1.3fr; gap: 10px; width: 100%; }
.rt-controls button { display: grid; justify-items: center; gap: 4px; padding: 10px 6px; border: 3px solid #4a3620; border-radius: 20px; background: #fffaf0; box-shadow: 0 4px 0 #70501b; color: #4a3620; font: 700 14px/1.2 ui-rounded, system-ui, sans-serif; cursor: pointer; }
.rt-controls button svg { width: 34px; height: 34px; }
.rt-controls .rt-read { background: #b7e779; }
.rt-controls .rt-not-yet { background: #e5dcc8; }
.rt-controls button:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 3px; }
.rt-friend { position: absolute; left: -10px; bottom: 112px; width: 64px; pointer-events: none; }
.rt-done { display: grid; justify-items: center; gap: 10px; padding: 18px; text-align: center; color: #4a3620; }
.gu-read-last { font-size: 14px; color: #70501b; }

/* ---------- v9 Family Garden ---------- */
.lg-who .who-stage { display: grid; place-items: center; min-height: 100%; }
.who-pets { display: flex; flex-wrap: wrap; justify-content: center; gap: 18px; max-width: 520px; padding: 20px; }
.who-pet { width: 140px; height: 150px; padding: 8px; border: 3px solid #4a3620; border-radius: 32px 32px 40px 40px; background: radial-gradient(ellipse at 50% 92%, #c9bda4 0 30%, transparent 31%), #fffaf0; box-shadow: 0 6px 0 #70501b; cursor: pointer; display: grid; place-items: end center; }
.who-pet > svg, .who-pet > .lg-animal { width: 100% !important; height: 100% !important; }
.who-pet.is-picked { transform: translateY(-8px) scale(1.06); transition: transform 260ms cubic-bezier(.3,1.6,.5,1); }
.who-pet:focus-visible, .gu-family-pet:focus-visible, .gu-family-add:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 3px; }
.gu-family-pets { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.gu-family-pet { width: 86px; height: 92px; padding: 4px; border: 2px solid #a89478; border-radius: 22px; background: #fffaf0; cursor: pointer; display: grid; place-items: end center; }
.gu-family-pet.is-active { border: 3px solid #4e9677; box-shadow: 0 0 0 3px #b7e779; }
.gu-family-pet > svg, .gu-family-pet > .lg-animal { width: 100% !important; height: 100% !important; }
.gu-family-add { display: grid; justify-items: center; gap: 2px; padding: 6px 10px; border: 2px dashed #a89478; border-radius: 22px; background: #fffdf7; color: #70501b; font: 700 13px ui-rounded, system-ui, sans-serif; cursor: pointer; }
.gu-family-add svg { width: 56px; height: 56px; }

/* ---------- v10 Moon Calendar ---------- */
.lg-season { position: absolute; left: 0; right: 0; top: 0; height: min(22vh, 150px); z-index: -1; pointer-events: none; overflow: hidden; }
.lg-season svg { width: 100%; height: 100%; display: block; }
.lg-home > .lg-season { z-index: 2; top: calc(max(10px, env(safe-area-inset-top)) + 54px); }
.lg-season .season-lamp { transform-box: fill-box; transform-origin: 50% 0; animation: season-sway 4s ease-in-out infinite alternate; }
.lg-season g:nth-of-type(odd) > .season-lamp { animation-delay: -2s; }
@keyframes season-sway { from { transform: rotate(-3deg); } to { transform: rotate(3deg); } }
.lg-reduce-motion .lg-season .season-lamp { animation: none; }
@media (prefers-reduced-motion: reduce) { .lg-season .season-lamp { animation: none; } }

/* ---------- v11 Sound Lab ---------- */
.lab { display: grid; justify-items: center; gap: 10px; width: min(100%, 560px); margin: 0 auto; padding-bottom: 10px; }
.lab-strip { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; min-height: 40px; }
.lab-made { min-width: 44px; height: 48px; padding: 0 8px; line-height: 2; overflow: visible; border: 2px solid #4a3620; border-radius: 12px; background: #fffaf0; font: 24px/1.5 "Amiri Quran", serif; color: #4a3620; cursor: pointer; }
.lab-bench { display: flex; align-items: center; gap: 10px; direction: rtl; }
.lab-slot { width: 74px; height: 84px; line-height: 2; overflow: visible; border: 3px dashed #a89478; border-radius: 20px; background: #fffdf7; font: 40px/1.6 "Amiri Quran", serif; color: #4a3620; cursor: pointer; }
.lab-slot.is-full { border-style: solid; border-color: #4a3620; background: #fffaf0; box-shadow: 0 4px 0 #70501b; }
.lab-plus { font: 800 28px ui-rounded, system-ui, sans-serif; color: #70501b; }
.lab-press { position: relative; width: min(100%, 300px); }
.lab-machine { display: block; width: 100%; height: auto; }
.lab-press.is-running .lab-gear { transform-box: fill-box; transform-origin: 50% 50%; animation: lab-gear 650ms ease-in-out; }
.lab-press.is-running .lab-machine { animation: lab-hum 650ms ease-in-out; }
@keyframes lab-gear { to { rotate: 180deg; } }
@keyframes lab-hum { 25% { transform: translateX(-2px); } 50% { transform: translateX(2px); } 75% { transform: translateX(-1px); } }
.lab-out { position: absolute; left: 50%; top: -14%; translate: -50% 0; width: 120px; padding: 0; overflow: visible; border: 0; background: none; font: 44px/1.5 "Amiri Quran", serif; color: #4a3620; cursor: pointer; }
.lab-out svg { display: block; width: 120px; height: auto; }
.lab-out.is-new { animation: lab-out 520ms cubic-bezier(.3,1.6,.5,1); }
@keyframes lab-out { from { scale: .4; } to { scale: 1; } }
.lab-tray { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; max-width: 100%; direction: rtl; }
.lab-tile { width: 48px; height: 56px; padding: 0; line-height: 2; overflow: visible; border: 2px solid #4a3620; border-radius: 12px; background: #fffaf0; box-shadow: 0 3px 0 #c9bda4; font: 28px/1.6 "Amiri Quran", serif; color: #4a3620; cursor: pointer; }
.lab-tile.is-mark { background: #ffe49a; font-size: 30px; }
.lab-tile:focus-visible, .lab-slot:focus-visible, .lab-out:focus-visible, .lab-made:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 2px; }
.lg-reduce-motion .lab-press .lab-gear, .lg-reduce-motion .lab-press .lab-machine, .lg-reduce-motion .lab-out { animation: none !important; }

/* ---------- v12 Garden Visitors ---------- */
.decorate-board { position: relative; }
.garden-visitor { position: absolute; z-index: 2; width: 56px; height: 56px; padding: 0; border: 0; background: none; cursor: pointer; }
.garden-visitor svg { display: block; width: 100%; height: 100%; overflow: visible; }
.garden-visitor:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 2px; border-radius: 50%; }
.garden-visitor.is-ground .visitor-walk { display: block; animation: visitor-wander 9s ease-in-out infinite; }
.garden-visitor.is-sky .visitor-walk { display: block; animation: visitor-flutter 6s ease-in-out infinite; }
.garden-visitor.is-water .visitor-walk { display: block; animation: visitor-bob 3.2s ease-in-out infinite alternate; }
.garden-visitor.is-hop { animation: visitor-hop 520ms cubic-bezier(.3,1.6,.5,1); }
@keyframes visitor-wander { 0%, 100% { transform: translateX(0) scaleX(1); } 45% { transform: translateX(34px) scaleX(1); } 50% { transform: translateX(34px) scaleX(-1); } 95% { transform: translateX(0) scaleX(-1); } }
@keyframes visitor-flutter { 0%, 100% { transform: translate(0, 0) rotate(-4deg); } 25% { transform: translate(18px, -10px) rotate(4deg); } 50% { transform: translate(30px, 4px) rotate(-3deg); } 75% { transform: translate(10px, 10px) rotate(3deg); } }
@keyframes visitor-bob { from { transform: translateY(0) rotate(-3deg); } to { transform: translateY(-5px) rotate(3deg); } }
@keyframes visitor-hop { 40% { translate: 0 -22px; } 100% { translate: 0 0; } }
.lg-reduce-motion .garden-visitor .visitor-walk, .lg-reduce-motion .garden-visitor.is-hop { animation: none; }
@media (prefers-reduced-motion: reduce) { .garden-visitor .visitor-walk, .garden-visitor.is-hop { animation: none; } }

/* ---------- v13 Letter Studio ---------- */
.studio { display: grid; justify-items: center; gap: 10px; width: min(100%, 620px); margin: 0 auto; padding-bottom: 8px; }
.studio-canvas { width: 100%; height: auto; border: 3px solid #4a3620; border-radius: 22px; box-shadow: 0 6px 0 #4a3620; cursor: crosshair; touch-action: manipulation; }
.studio-placed { animation: studio-stamp 260ms cubic-bezier(.3,1.6,.5,1); transform-box: fill-box; transform-origin: 50% 50%; }
@keyframes studio-stamp { from { opacity: 0; } to { opacity: 1; } }
.studio-inks { display: flex; gap: 10px; }
.studio-ink { width: 40px; height: 40px; border-radius: 50%; border: 3px solid #fffaf0; background: var(--ink); box-shadow: 0 0 0 2px #4a3620; cursor: pointer; }
.studio-ink.is-on { box-shadow: 0 0 0 3px #4a3620, 0 0 0 7px #f3c955; }
.studio-tray { display: flex; gap: 6px; overflow-x: auto; max-width: 100%; padding: 4px 4px 8px; direction: rtl; scrollbar-width: thin; }
.studio-stamp { flex: 0 0 auto; width: 52px; height: 56px; border: 2px solid #4a3620; border-radius: 14px; background: #fffaf0; box-shadow: 0 3px 0 #c9bda4; font: 30px/1.8 "Amiri Quran", serif; color: #4a3620; cursor: pointer; padding: 0; overflow: visible; }
.studio-stamp.is-sticker svg { display: block; margin: auto; }
.studio-stamp.is-on { background: #ffe49a; box-shadow: 0 3px 0 #70501b; transform: translateY(-3px); }
.studio-tools { display: flex; gap: 14px; align-items: center; }
.studio-stamp:focus-visible, .studio-ink:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 3px; }
.lg-reduce-motion .studio-placed { animation: none; }

/* ---------- v17 Gentle mode ---------- */
.lg-gentle .lg-weather, .lg-gentle .lg-season, .lg-gentle .art-life, .lg-gentle .art-fireflies, .lg-gentle .garden-life { display: none !important; }
.lg-gentle .lg-round-btn { width: 64px; height: 64px; }
.lg-gentle .lg-big-btn { min-height: 76px; }
.lg-gentle .art-cloud-a, .lg-gentle .art-cloud-b { animation: none; }
.garden-sibling { width: 70px; height: 74px; }
.garden-sibling .visitor-walk { animation-duration: 12s !important; }

/* ---------- v20 Garden Together ---------- */
.together { display: grid; gap: 12px; width: min(100%, 560px); margin: 0 auto; }
.together-pets { display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: 8px; }
.together-pet { justify-self: center; width: 96px; opacity: .6; transform: scale(.85); transition: transform 260ms cubic-bezier(.3,1.5,.5,1), opacity 260ms; }
.together-pet.is-turn { opacity: 1; transform: scale(1.08); filter: drop-shadow(0 0 0 #f3c955) drop-shadow(0 4px 8px #f3c95599); }
.together-pet.is-cheer { animation: together-cheer 700ms cubic-bezier(.3,1.6,.5,1); }
.together-pet > svg, .together-pet > .lg-animal { width: 100% !important; height: auto !important; }
@keyframes together-cheer { 40% { translate: 0 -18px; } 100% { translate: 0 0; } }
.together-basket { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; min-width: 90px; min-height: 46px; padding: 6px; border: 3px solid #4a3620; border-radius: 12px 12px 22px 22px; background: repeating-linear-gradient(90deg, #c69434 0 12px, #a89478 12px 14px); }
.together-basket i { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: #fffaf0; border: 2px solid #4a3620; font: 18px/1.8 "Amiri Quran", serif; font-style: normal; color: #4a3620; }
.together-board { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.together-card { position: relative; aspect-ratio: 3 / 4; border: 3px solid #4a3620; border-radius: 16px; background: #4e9677; box-shadow: 0 4px 0 #2f5c46; cursor: pointer; padding: 0; overflow: hidden; }
.together-back { position: absolute; inset: 8px; border-radius: 10px; background: radial-gradient(circle, #7fce54 0 18%, transparent 19%) 0 0 / 18px 18px, #4e9677; }
.together-face { position: absolute; inset: 0; display: grid; place-items: center; background: #fffaf0; font: 40px/1.8 "Amiri Quran", serif; color: #4a3620; opacity: 0; transition: opacity 160ms; }
.together-card.is-up .together-face, .together-card.is-matched .together-face { opacity: 1; }
.together-card.is-matched { box-shadow: 0 4px 0 #f3c955; border-color: #70501b; }
.together-card:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 3px; }
.lg-reduce-motion .together-pet, .lg-reduce-motion .together-pet.is-cheer { transition: none; animation: none; }

/* ---------- v21 Seasons of the Year ---------- */
.lg-year { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.lg-home > .lg-year { z-index: 2; }
.yr-fall { position: absolute; top: -24px; width: 18px; height: 18px; animation: yr-fall 11s linear infinite; }
.yr-fall svg { width: 100%; height: 100%; display: block; }
.lg-year[data-year="winter"] .yr-fall { width: 10px; height: 10px; }
@keyframes yr-fall { 0% { transform: translate(0, 0) rotate(0); } 50% { transform: translate(28px, 55vh) rotate(160deg); } 100% { transform: translate(-10px, 110vh) rotate(320deg); } }
.lg-gentle .lg-year { display: none !important; }
.lg-reduce-motion .lg-year { display: none; }
@media (prefers-reduced-motion: reduce) { .lg-year { display: none; } }

/* ---------- v22 Little Sprout ---------- */
/* A glow that follows the drawn shape (answer cards are often transparent
   buttons around a drawing), pulsing gently. */
.is-sprout-glow { z-index: 3; animation: sprout-glow 1.1s ease-in-out infinite alternate; }
@keyframes sprout-glow { from { filter: drop-shadow(0 0 3px #f3c955) drop-shadow(0 0 1px #ffe49a); } to { filter: drop-shadow(0 0 12px #f3c955) drop-shadow(0 0 4px #ffe49a); } }
.lg-home-btn.is-hold { position: relative; }
.lg-home-btn.is-hold::after { content: ""; position: absolute; inset: -7px; border-radius: 50%; border: 5px solid #f3c955; clip-path: inset(0 100% 0 0); }
.lg-home-btn.is-hold.is-holding::after { animation: sprout-hold 800ms linear forwards; }
@keyframes sprout-hold { to { clip-path: inset(0 0 0 0); } }
.lg-reduce-motion .is-sprout-glow { animation: none; filter: drop-shadow(0 0 8px #f3c955) drop-shadow(0 0 3px #ffe49a); }

/* ---------- v24 Letter Balloons ---------- */
.lg-play[data-activity="balloons"] .practice-stage { position: relative; }
.balloons { position: relative; width: min(100%, 560px); height: min(72vh, 620px); margin: 0 auto; overflow: hidden; border: 3px solid #4a3620; border-radius: 28px; background: linear-gradient(#96ecff, #ccfbef); box-shadow: 0 6px 0 #4a3620; }
.balloon { position: absolute; bottom: -150px; width: 96px; height: 134px; padding: 0; border: 0; background: none; cursor: pointer; animation: balloon-rise var(--rise, 15s) linear infinite; }
.balloon svg { display: block; width: 100%; height: 100%; }
.balloon.is-popped { animation: balloon-pop 380ms ease-out forwards; }
@keyframes balloon-rise { 0% { transform: translate(0, 0); } 50% { transform: translate(var(--sway, 12px), calc(-0.55 * min(72vh, 620px))); } 100% { transform: translate(0, calc(-1 * min(72vh, 620px) - 160px)); } }
@keyframes balloon-pop { to { transform: scale(1.5); opacity: 0; } }
.balloons.is-still .balloon { animation: none; bottom: auto; }
.balloons.is-still .balloon.is-popped { animation: none; opacity: 0; }
.balloon:focus-visible { outline: 4px solid var(--lg-focus); outline-offset: 2px; border-radius: 50%; }
