/* ============================================================
   Campfire — css/camp-scene.css                        (WILD-02)
   THE CAMP SCENE'S LOOK: the art seam (an animal in its four poses)
   and the 2.5D diorama, for Learning's camps and Wild Friends alike.
   Moved out of css/learn.css unchanged (the class names keep their
   `lp-` prefix: renaming them is churn for nothing, WILD-02 D1); the
   hooks' few new rules (`cs-`) are at the end. The pair of
   js/camp-scene.js.

   ⚠ ONE FILE, TWO SHELLS. index.html and dash/index.html link it
   BEFORE css/learn.css and both workers precache it: A CHANGE HERE IS
   A PAIRED BUMP.
   ⚠ EVERY var() RESOLVES AGAINST branding.css ALONE (L17) — the wall
   loads no app.css. No custom property is declared in this file, and
   there is no hex here: every colour is a token.
   ⚠ REDUCED MOTION: every animation has a tail at the foot of this
   file. Anything that exists only to move is display:none there. The
   JavaScript half (the rAF loop) is in js/camp-scene.js.
   ============================================================ */

/* ── Animals: THE ART SEAM ─────────────────────────────────── */
.lp-animal {
    display: inline-flex; align-items: flex-end; justify-content: center;
    position: relative; line-height: 1; transform-origin: 50% 100%;
}
.lp-emo { font-size: 1em; }
.lp-emo-in { display: block; transform-origin: 50% 100%; transition: filter 0.6s; }
.lp-pose-alt     .lp-emo-in { transform: rotate(-7deg); }
.lp-pose-excited .lp-emo-in { transform: scale(1.12); }
.lp-pose-sleep   .lp-emo-in { transform: scale(1.04, 0.86); filter: brightness(0.8) saturate(0.75); }
.lp-pose-hidden  .lp-emo-in { filter: brightness(0); opacity: 0.85; }

/* The sprite strip: four poses side by side — IDLE · ALT · EXCITED · SLEEP. */
.lp-spr {
    width: 1.1em; height: 1.1em;
    background-repeat: no-repeat; background-size: 400% 100%; background-position: 0 0;
}
.lp-spr.lp-pose-alt     { background-position: 33.333% 0; }
.lp-spr.lp-pose-excited { background-position: 66.667% 0; }
.lp-spr.lp-pose-sleep   { background-position: 100% 0; }
.lp-spr.lp-pose-hidden  { background-position: 0 0; filter: brightness(0); opacity: 0.85; }

.lp-breathe { animation: lp-breathe 2.8s ease-in-out infinite; }
.lp-animal.lp-squash { animation: lp-squash 0.35s ease-out; }
.lp-hop    { animation: lp-hop 0.75s cubic-bezier(0.3, 0.7, 0.4, 1); }
.lp-chew   { animation: lp-chew 0.28s ease-in-out 5; }

/* ── The scene (a 2.5D diorama) ────────────────────────────── */
.lp-scene { position: absolute; inset: 0; overflow: hidden; isolation: isolate; }
.lp-sky { position: absolute; inset: 0; z-index: 0; }
.lp-sky-night { opacity: 0; transition: opacity 1.2s; }
.lp-scene.is-night .lp-sky-night { opacity: 1; }
.lp-theme-canyon .lp-sky-day   { background: linear-gradient(var(--learn-canyon-day-top), var(--learn-canyon-day-bot)); }
.lp-theme-canyon .lp-sky-night { background: linear-gradient(var(--learn-canyon-night-top), var(--learn-canyon-night-bot)); }
.lp-sun {
    position: absolute; right: 12%; top: 16%; width: 50px; height: 50px; border-radius: 50%; z-index: 0;
    background: var(--learn-sun); box-shadow: 0 0 40px 14px var(--learn-sun-glow);
    transition: opacity 1s, transform 1.2s;
}
.lp-moon {
    position: absolute; right: 14%; top: 17%; width: 38px; height: 38px; border-radius: 50%; z-index: 0;
    box-shadow: -10px 4px 0 0 var(--learn-moon); opacity: 0; transition: opacity 1.2s;
}
.lp-scene.is-night .lp-sun  { opacity: 0; transform: translateY(60px); }
.lp-scene.is-night .lp-moon { opacity: 1; }
.lp-stars { position: absolute; left: 0; top: 0; right: 0; height: 40%; opacity: 0; transition: opacity 1.5s; z-index: 0; }
.lp-scene.is-night .lp-stars { opacity: 1; }
.lp-stars i { position: absolute; border-radius: 50%; background: var(--learn-star); animation: lp-twinkle 3s ease-in-out infinite; }
.lp-mesa { position: absolute; left: 0; width: 100%; z-index: 1; pointer-events: none; transition: filter 1.2s; }
.lp-scene.is-night .lp-mesa { filter: brightness(0.42) saturate(0.7); }
.lp-theme-canyon .lp-rock-far  { fill: var(--learn-canyon-rock-far); }
.lp-theme-canyon .lp-rock-dark { fill: var(--learn-canyon-rock-dark); opacity: 0.35; }
.lp-theme-canyon .lp-rock      { fill: var(--learn-canyon-rock); }
.lp-ground { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; }
.lp-theme-canyon .lp-ground { background: linear-gradient(var(--learn-canyon-sand-far), var(--learn-canyon-sand-near)); }
.lp-pool { position: absolute; z-index: 2; border-radius: 50%; }
.lp-theme-canyon .lp-pool {
    background: radial-gradient(ellipse at 40% 40%, var(--learn-canyon-pool) 55%, var(--learn-canyon-pool-edge));
}
.lp-world { position: absolute; inset: 0; z-index: 3; }
.lp-veil {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 3000;
    pointer-events: none; opacity: 0; transition: opacity 1.2s;
}
.lp-scene.is-night .lp-veil { opacity: 1; }

.lp-prop, .lp-agent, .lp-fire, .lp-treat {
    position: absolute; left: 0; top: 0; width: 0; height: 0;
    pointer-events: none; will-change: transform;
}
.lp-pe {
    position: absolute; left: 0; bottom: -0.1em; transform: translateX(-50%);
    line-height: 1; display: block; white-space: nowrap;
}

.lp-agent .lp-shadow {
    position: absolute; left: 0; top: -6px; width: 48px; height: 12px; border-radius: 50%;
    background: radial-gradient(closest-side, var(--learn-shadow), transparent);
    transform: translateX(-50%);
}
.lp-agent-body { position: absolute; left: 0; bottom: 0; pointer-events: auto; cursor: pointer; }
.lp-face { display: block; transform-origin: 50% 100%; font-size: 58px; }
.lp-agent.is-hang .lp-face .lp-emo-in { transform: rotate(180deg); transform-origin: 50% 50%; }
/* `rotate` (not transform) so it stacks on the breathing animation. */
.lp-agent.is-hang .lp-face .lp-spr { rotate: 180deg; }
/* LEARN-17: a swimmer sits IN the water. The face drops by the part the
   clip hides (translate % is of its own height), so the waterline lands
   on the animal's spot instead of the clipped body floating above it on
   the far rim ("hiding behind the water"). No shadow on water; !important
   beats the opacity draw() writes inline every frame. */
.lp-agent.is-swim .lp-face { clip-path: inset(0 0 38% 0); translate: 0 38%; }
.lp-agent.is-swim .lp-shadow { opacity: 0 !important; }
.lp-zz { position: absolute; right: -6px; top: -4px; font-size: 18px; display: none; animation: lp-zz 2.4s ease-in-out infinite; }
.lp-agent.is-sleeping .lp-zz { display: block; }
.lp-scene.is-readonly .lp-agent-body { cursor: default; }

.lp-fire-glow {
    position: absolute; left: 0; bottom: -50px; width: 280px; height: 150px; transform: translateX(-50%); border-radius: 50%;
    background: radial-gradient(closest-side, var(--learn-fire-glow), var(--learn-fire-clear)); transition: opacity 0.8s;
}
.lp-fire-ring {
    position: absolute; left: 0; bottom: -14px; width: 92px; height: 26px; transform: translateX(-50%); border-radius: 50%;
    border: 6px solid var(--learn-fire-ring); background: var(--learn-shadow);
}
.lp-fire-logs  { font-size: 34px; }
.lp-fire-flame { bottom: 6px; transform-origin: 50% 100%; animation: lp-flick 0.8s ease-in-out infinite alternate; transition: font-size 0.6s; }
.lp-fire-flame[hidden] { display: none; }

/* ── LEARN-09: the drawn camp. Each piece sits on its own base line,
   centred on its (x, d) point, like the emoji it replaces. ── */
.lp-backdrop { position: absolute; inset: 0; z-index: 1; pointer-events: none; background-repeat: no-repeat; }
.lp-bd-night { opacity: 0; transition: opacity 1.2s; }
.lp-scene.is-night .lp-bd-night { opacity: 1; }
.lp-scene.has-backdrop .lp-mesa, .lp-scene.has-backdrop .lp-ground { display: none; }
/* The night painting is already dark. BUG-01 (Andy): no veil over the ground
   (it greyed the animals and bubbles below the horizon, not the ones above);
   only the drawn props take on the night (below). */
.lp-scene.has-backdrop.is-night .lp-veil { opacity: 0; }
/* …and the drawn props take on the painting's moonlight (the fire and the
   animals are left to the veil, so the firelight still reaches them). */
.lp-scene.has-backdrop .lp-prop, .lp-scene.has-backdrop .lp-pool { transition: filter 1.2s; }
.lp-scene.has-backdrop.is-night .lp-prop, .lp-scene.has-backdrop.is-night .lp-pool { filter: brightness(0.62) saturate(0.45); }
.lp-scene .lp-pool.has-art { background-repeat: no-repeat; background-size: 100% 100%; background-position: 50% 50%; border-radius: 0; }
.lp-pimg, .lp-fimg, .lp-timg {
    display: block; max-width: none; pointer-events: none;
    user-select: none; -webkit-user-select: none; -webkit-user-drag: none;
}
.lp-pimg { position: absolute; left: 0; bottom: -2px; width: auto; transform: translateX(-50%); }
.lp-fimg { position: absolute; left: 0; bottom: -10px; width: 118px; height: auto; transform: translateX(-50%); }
.lp-fimg-b { opacity: 0; }
.lp-fire.is-full .lp-fimg-a { animation: lp-fire-a 0.9s step-end infinite; }
.lp-fire.is-full .lp-fimg-b { animation: lp-fire-b 0.9s step-end infinite; }
.lp-timg { height: 20px; width: auto; }
/* An animal at camp stands ON its shadow. As an inline box it sat on the
   text baseline, ~0.2em above the bottom of its line (the descender gap). */
.lp-agent .lp-spr { display: block; }
.lp-treat .lp-pe { font-size: 28px; animation: lp-drop 0.45s cubic-bezier(0.3, 1.4, 0.5, 1); }
.lp-treat.is-eaten .lp-pe { transform: translateX(-50%) scale(0); transition: transform 0.3s; animation: none; }
.lp-heart { position: absolute; z-index: 4500; pointer-events: none; font-size: 18px; animation: lp-rise 1.1s ease-out forwards; }

.lp-camp-empty {
    position: absolute; left: 50%; top: 34%; transform: translateX(-50%); z-index: 4000;
    width: min(300px, 82%); text-align: center;
    background: var(--learn-hud-bg); color: var(--learn-hud-ink);
    border-radius: var(--radius-lg); padding: 12px 14px; font-size: 16px;
}
.lp-camp-empty[hidden] { display: none; }
/* LEARN-32 C4: the fact bubble sits LOW in the camp (the stage's bottom
   edge, just above the Let's go card) and stays until its ✕ or a tap. */
.lp-acard {
    position: absolute; left: 50%; bottom: 12px; z-index: 5000; transform: translateX(-50%);
    width: min(360px, 92%); display: flex; gap: 12px; align-items: flex-start;
    background: var(--surface); color: var(--text-primary);
    border-radius: var(--radius-lg); padding: 12px 14px; box-shadow: var(--shadow-lg);
    pointer-events: auto;
}
.lp-acard[hidden] { display: none; }
.lp-acard { padding-right: 40px; }
.lp-acard-x {
    position: absolute; top: 6px; right: 6px; width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%; background: var(--surface-2); color: var(--text-secondary);
    font-size: 16px; line-height: 1; cursor: pointer;
}
.lp-acard-ani { font-size: 52px; flex: none; }
.lp-acard-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lp-acard-text b { font-family: var(--font-heavy); font-size: 17px; }
.lp-acard-fact { font-size: 16px; line-height: 1.35; margin-top: 2px; }   /* LEARN-14: the animal's fact */

/* ── LEARN-11: the other themes' scene rules (the map's stay in learn.css). ── */
.lp-theme-arctic .lp-sky-day   { background: linear-gradient(var(--learn-arctic-day-top), var(--learn-arctic-day-bot)); }
.lp-theme-arctic .lp-sky-night { background: linear-gradient(var(--learn-arctic-night-top), var(--learn-arctic-night-bot)); }
.lp-theme-arctic .lp-rock-far  { fill: var(--learn-arctic-rock-far); }
.lp-theme-arctic .lp-rock-dark { fill: var(--learn-arctic-rock-dark); opacity: 0.35; }
.lp-theme-arctic .lp-rock      { fill: var(--learn-arctic-rock); }
.lp-theme-arctic .lp-ground { background: linear-gradient(var(--learn-arctic-sand-far), var(--learn-arctic-sand-near)); }
.lp-theme-arctic .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-arctic-pool) 55%, var(--learn-arctic-pool-edge)); }
.lp-theme-island .lp-sky-day   { background: linear-gradient(var(--learn-island-day-top), var(--learn-island-day-bot)); }
.lp-theme-island .lp-sky-night { background: linear-gradient(var(--learn-island-night-top), var(--learn-island-night-bot)); }
.lp-theme-island .lp-rock-far  { fill: var(--learn-island-rock-far); }
.lp-theme-island .lp-rock-dark { fill: var(--learn-island-rock-dark); opacity: 0.35; }
.lp-theme-island .lp-rock      { fill: var(--learn-island-rock); }
.lp-theme-island .lp-ground { background: linear-gradient(var(--learn-island-sand-far), var(--learn-island-sand-near)); }
.lp-theme-island .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-island-pool) 55%, var(--learn-island-pool-edge)); }
.lp-theme-jungle .lp-sky-day   { background: linear-gradient(var(--learn-jungle-day-top), var(--learn-jungle-day-bot)); }
.lp-theme-jungle .lp-sky-night { background: linear-gradient(var(--learn-jungle-night-top), var(--learn-jungle-night-bot)); }
.lp-theme-jungle .lp-rock-far  { fill: var(--learn-jungle-rock-far); }
.lp-theme-jungle .lp-rock-dark { fill: var(--learn-jungle-rock-dark); opacity: 0.35; }
.lp-theme-jungle .lp-rock      { fill: var(--learn-jungle-rock); }
.lp-theme-jungle .lp-ground { background: linear-gradient(var(--learn-jungle-sand-far), var(--learn-jungle-sand-near)); }
.lp-theme-jungle .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-jungle-pool) 55%, var(--learn-jungle-pool-edge)); }
.lp-theme-ocean .lp-sky-day   { background: linear-gradient(var(--learn-ocean-day-top), var(--learn-ocean-day-bot)); }
.lp-theme-ocean .lp-sky-night { background: linear-gradient(var(--learn-ocean-night-top), var(--learn-ocean-night-bot)); }
.lp-theme-ocean .lp-rock-far  { fill: var(--learn-ocean-rock-far); }
.lp-theme-ocean .lp-rock-dark { fill: var(--learn-ocean-rock-dark); opacity: 0.35; }
.lp-theme-ocean .lp-rock      { fill: var(--learn-ocean-rock); }
.lp-theme-ocean .lp-ground { background: linear-gradient(var(--learn-ocean-sand-far), var(--learn-ocean-sand-near)); }
.lp-theme-ocean .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-ocean-pool) 55%, var(--learn-ocean-pool-edge)); }
.lp-theme-outback .lp-sky-day   { background: linear-gradient(var(--learn-outback-day-top), var(--learn-outback-day-bot)); }
.lp-theme-outback .lp-sky-night { background: linear-gradient(var(--learn-outback-night-top), var(--learn-outback-night-bot)); }
.lp-theme-outback .lp-rock-far  { fill: var(--learn-outback-rock-far); }
.lp-theme-outback .lp-rock-dark { fill: var(--learn-outback-rock-dark); opacity: 0.35; }
.lp-theme-outback .lp-rock      { fill: var(--learn-outback-rock); }
.lp-theme-outback .lp-ground { background: linear-gradient(var(--learn-outback-sand-far), var(--learn-outback-sand-near)); }
.lp-theme-outback .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-outback-pool) 55%, var(--learn-outback-pool-edge)); }
.lp-theme-rainforest .lp-sky-day   { background: linear-gradient(var(--learn-rainforest-day-top), var(--learn-rainforest-day-bot)); }
.lp-theme-rainforest .lp-sky-night { background: linear-gradient(var(--learn-rainforest-night-top), var(--learn-rainforest-night-bot)); }
.lp-theme-rainforest .lp-rock-far  { fill: var(--learn-rainforest-rock-far); }
.lp-theme-rainforest .lp-rock-dark { fill: var(--learn-rainforest-rock-dark); opacity: 0.35; }
.lp-theme-rainforest .lp-rock      { fill: var(--learn-rainforest-rock); }
.lp-theme-rainforest .lp-ground { background: linear-gradient(var(--learn-rainforest-sand-far), var(--learn-rainforest-sand-near)); }
.lp-theme-rainforest .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-rainforest-pool) 55%, var(--learn-rainforest-pool-edge)); }
.lp-theme-safaripark .lp-sky-day   { background: linear-gradient(var(--learn-safaripark-day-top), var(--learn-safaripark-day-bot)); }
.lp-theme-safaripark .lp-sky-night { background: linear-gradient(var(--learn-safaripark-night-top), var(--learn-safaripark-night-bot)); }
.lp-theme-safaripark .lp-rock-far  { fill: var(--learn-safaripark-rock-far); }
.lp-theme-safaripark .lp-rock-dark { fill: var(--learn-safaripark-rock-dark); opacity: 0.35; }
.lp-theme-safaripark .lp-rock      { fill: var(--learn-safaripark-rock); }
.lp-theme-safaripark .lp-ground { background: linear-gradient(var(--learn-safaripark-sand-far), var(--learn-safaripark-sand-near)); }
.lp-theme-safaripark .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-safaripark-pool) 55%, var(--learn-safaripark-pool-edge)); }
.lp-theme-savanna .lp-sky-day   { background: linear-gradient(var(--learn-savanna-day-top), var(--learn-savanna-day-bot)); }
.lp-theme-savanna .lp-sky-night { background: linear-gradient(var(--learn-savanna-night-top), var(--learn-savanna-night-bot)); }
.lp-theme-savanna .lp-rock-far  { fill: var(--learn-savanna-rock-far); }
.lp-theme-savanna .lp-rock-dark { fill: var(--learn-savanna-rock-dark); opacity: 0.35; }
.lp-theme-savanna .lp-rock      { fill: var(--learn-savanna-rock); }
.lp-theme-savanna .lp-ground { background: linear-gradient(var(--learn-savanna-sand-far), var(--learn-savanna-sand-near)); }
.lp-theme-savanna .lp-pool { background: radial-gradient(ellipse at 40% 40%, var(--learn-savanna-pool) 55%, var(--learn-savanna-pool-edge)); }
.lp-theme-ocean .lp-fire-glow { background: radial-gradient(closest-side, var(--learn-ocean-fire-glow), var(--learn-ocean-fire-clear)); }

/* ── WILD-02: the hooks ─────────────────────────────────────── */
/* Editable props are picked up by their picture; the camp doesn't pan. */
.lp-scene.is-editable { touch-action: none; }
.lp-scene.is-editable .lp-prop > * { pointer-events: auto; cursor: grab; }
.lp-prop.is-lifted { filter: drop-shadow(0 10px 6px var(--learn-shadow)); }
.lp-prop.is-lifted > * { cursor: grabbing; }
.lp-pool.is-lifted { filter: drop-shadow(0 10px 6px var(--learn-shadow)); cursor: grabbing; }   /* CAMPS-DRAG: the pool moves too */

/* A thought bubble with a picture, over the animal's head. It rides on the
   body (so it hops with it) and is never mirrored; draw() keeps it
   readable at the back of the camp. */
.cs-bubble {
    position: absolute; left: 0; bottom: 78px; z-index: 2;
    width: 46px; height: 46px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface); box-shadow: var(--shadow-md);
    transform: translateX(-50%); transform-origin: 50% 100%;
    pointer-events: none;
}
.cs-bubble::before, .cs-bubble::after {
    content: ''; position: absolute; border-radius: 50%; background: var(--surface);
    box-shadow: var(--shadow-sm);
}
.cs-bubble::before { width: 10px; height: 10px; left: 50%; bottom: -10px; margin-left: -9px; }
.cs-bubble::after  { width: 6px; height: 6px; left: 50%; bottom: -17px; margin-left: -6px; }
.cs-bubble-img { display: block; width: 34px; height: 34px; object-fit: contain; pointer-events: none; }
.cs-bubble.cs-pop { animation: cs-pop 0.4s ease-out; }

/* A drag in progress: the picture rides above the finger. */
/* BUG-02: over the ground it stands on its landing spot at the size it will be
   there (--sz, set per move), with a shadow on the spot; in the air (over the
   tray or the sky) it is the tray picture, centred above the finger. */
.cs-drag { position: absolute; left: 0; top: 0; z-index: 6000; pointer-events: none; will-change: transform; }   /* --sz: set by the script (default 62px below) */
.cs-drag-pic {
    position: absolute; left: 0; bottom: 0; width: var(--sz, 62px); height: var(--sz, 62px);
    transform: translate(-50%, -10px);            /* held a little above its spot */
    transition: width 0.08s linear, height 0.08s linear, opacity 0.12s;
    filter: drop-shadow(0 10px 4px var(--learn-shadow));
}
.cs-drag-img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: 50% 100%; }
.cs-drag-img.cs-icon > svg { width: 100%; height: 100%; }
.cs-drag-shadow {        /* the landing spot: a ring on the ground */
    position: absolute; left: 0; top: 0; width: max(30px, calc(var(--sz, 62px) * 1.0)); height: max(10px, calc(var(--sz, 62px) * 0.32));
    transform: translate(-50%, -50%); border-radius: 50%; box-sizing: border-box;
    border: 2.5px solid var(--wild-spot); background: radial-gradient(closest-side, var(--learn-shadow), transparent);
    animation: cs-spot 1s ease-in-out infinite alternate;
}
@keyframes cs-spot { from { opacity: 0.65; } to { opacity: 1; } }
.cs-drag.is-air .cs-drag-pic { transform: translate(-50%, 50%) scale(1.05); }
.cs-drag.is-air .cs-drag-shadow { display: none; }
.cs-drag.is-ok .cs-drag-shadow { border-color: var(--wild-target); background: radial-gradient(closest-side, var(--wild-target), transparent); }
.cs-drag.is-no .cs-drag-pic { opacity: 0.5; filter: grayscale(0.8); }
.cs-drag.is-no .cs-drag-shadow { opacity: 0.35; animation: none; }
/* BUG-03: over another thing (it will slide off): a grey ring, the picture a little see-through. */
.cs-drag.is-bump .cs-drag-shadow { border-color: var(--learn-shadow); border-style: dashed; animation: none; }
.cs-drag.is-bump .cs-drag-pic { opacity: 0.7; }
.lp-prop.is-bump { opacity: 0.7; }
.lp-prop.is-sliding { transition: transform 0.25s ease-out; }
.lp-agent.is-target .lp-shadow { opacity: 1 !important; transform: translateX(-50%) scale(1.5) !important; background: radial-gradient(closest-side, var(--wild-target), transparent); }
.lp-agent.is-target .lp-face { filter: drop-shadow(0 0 5px var(--wild-target)) drop-shadow(0 0 2px var(--wild-target)); }   /* BUG-02 */
/* BUG-02: the fire or a prop that takes what's dragged glows. */
.lp-fire.is-target .lp-fimg, .lp-prop.is-target > .lp-pimg { filter: drop-shadow(0 0 6px var(--wild-target)) drop-shadow(0 0 2px var(--wild-target)); }

/* A picture flying to an element (a coin to the wallet). */
.cs-fly { position: fixed; left: 0; top: 0; z-index: 9000; pointer-events: none; margin: -18px 0 0 -18px; }
.cs-fly-img { display: block; width: 36px; height: 36px; object-fit: contain; }

/* Mud over the sprite (no new art); its opacity is set by mud(). */
.cs-mud { position: absolute; inset: 0; pointer-events: none; }
.cs-mud svg { display: block; width: 100%; height: 100%; }
.cs-mud ellipse { fill: var(--wild-mud); }

/* Soap bubbles rising and popping. */
.cs-soap { position: absolute; z-index: 4600; pointer-events: none; transform: translate(-50%, -50%); animation: cs-soap 1.4s ease-out forwards; }
.cs-soap svg { display: block; width: 100%; height: 100%; overflow: visible; }
.cs-soap-ring { fill: var(--wild-soap); stroke: var(--wild-soap-rim); stroke-width: 1.2; }
.cs-soap-shine { fill: var(--wild-soap-shine); }

/* WILD-04: small pictures drawn from tokens ({svg: …}). */
.cs-icon { display: inline-block; }
.cs-icon svg { display: block; width: 100%; height: 100%; overflow: visible; }
.cs-i-main   { fill: var(--wild-basket); }
.cs-i-fill   { fill: var(--wild-basket-dark); }
.cs-i-rim    { fill: var(--wild-basket-dark); }
.cs-i-line, .cs-i-handle { stroke: var(--wild-basket-dark); }
.cs-icon-bowl .cs-i-main { fill: var(--wild-bowl); }
.cs-icon-bowl .cs-i-fill { fill: var(--wild-bowl-dark); }
.cs-i-q      { fill: var(--wild-star); }
.cs-i-qmark  { stroke: var(--wild-star-edge); }
.cs-i-qdot   { fill: var(--wild-star-edge); }
.cs-i-star   { fill: var(--wild-star); stroke: var(--wild-star-edge); stroke-width: 1.5; stroke-linejoin: round; }

/* WILD-09: tricks (on the face, so they stack on the draw transform). */
.lp-face.cs-trick[data-trick="spin"]   .lp-animal { animation: cs-t-spin 1.2s ease-in-out; }
.lp-face.cs-trick[data-trick="hop3"]   .lp-animal { animation: cs-t-hop 0.5s ease-out 3; }
.lp-face.cs-trick[data-trick="dive"]   .lp-animal { animation: cs-t-dive 1.6s ease-in-out; }
.lp-face.cs-trick[data-trick="perch"]  .lp-animal { animation: cs-t-perch 1.6s ease-in-out; }
.lp-face.cs-trick[data-trick="stand"]  .lp-animal { animation: cs-t-stand 1.6s ease-in-out; }
.lp-face.cs-trick[data-trick="roll"]   .lp-animal { animation: cs-t-roll 1.1s ease-in-out; }
.lp-face.cs-trick[data-trick="hide"]   .lp-animal { animation: cs-t-hide 1.6s ease-in-out; }
.lp-face.cs-trick[data-trick="splash"] .lp-animal { animation: cs-t-hop 0.45s ease-out 2; }
.lp-face.cs-trick[data-trick="hang"]   .lp-animal { animation: cs-t-hang 1.6s ease-in-out; }
.lp-face.cs-trick[data-trick="howl"]   .lp-animal { animation: cs-t-howl 1.6s ease-in-out; }
.cs-note { position: absolute; left: 10px; bottom: 70px; width: 20px; height: 24px; animation: cs-note 1.6s ease-out forwards; }
.cs-note svg { width: 100%; height: 100%; display: block; overflow: visible; }
.cs-note path { fill: none; stroke: var(--learn-hud-ink); stroke-width: 2.5; }
.cs-note ellipse { fill: var(--learn-hud-ink); }

/* ── Keyframes ─────────────────────────────────────────────── */
@keyframes lp-breathe { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.025, 0.965); } }
@keyframes lp-squash  { 0% { transform: scale(1.1, 0.86); } 100% { transform: none; } }
@keyframes lp-hop     { 0% { transform: scale(1.1, 0.85); } 25% { transform: translateY(-28px) scale(0.95, 1.08); } 60% { transform: translateY(-4px); } 80% { transform: scale(1.06, 0.92); } 100% { transform: none; } }
@keyframes lp-chew    { 0%, 100% { transform: none; } 50% { transform: scale(1.04, 0.94) translateY(2px); } }
@keyframes lp-zz      { 0% { transform: translate(0, 0); opacity: 0; } 30% { opacity: 1; } 100% { transform: translate(10px, -20px); opacity: 0; } }
@keyframes lp-flick   { 0% { transform: translateX(-50%) scale(1, 1); } 100% { transform: translateX(-50%) scale(1.08, 0.92) skewX(3deg); } }
@keyframes lp-drop    { 0% { transform: translate(-50%, -80px); opacity: 0; } 100% { transform: translate(-50%, 0); opacity: 1; } }
@keyframes lp-rise    { 0% { transform: translateY(0) scale(0.5); opacity: 1; } 100% { transform: translateY(-56px) scale(1.15); opacity: 0; } }
@keyframes lp-twinkle { 0%, 100% { opacity: 0.9; } 50% { opacity: 0.35; } }
@keyframes lp-fire-a  { 0% { opacity: 1; } 50% { opacity: 0; } }
@keyframes lp-fire-b  { 0% { opacity: 0; } 50% { opacity: 1; } }
@keyframes cs-t-spin  { 0% { transform: rotateY(0); } 100% { transform: rotateY(720deg); } }
@keyframes cs-t-hop   { 0%, 100% { transform: translateY(0); } 40% { transform: translateY(-34px); } }
@keyframes cs-t-dive  { 0%, 100% { transform: translateY(0); clip-path: inset(0 0 0 0); } 45%, 55% { transform: translateY(60%); clip-path: inset(0 0 60% 0); } }
@keyframes cs-t-perch { 0%, 100% { transform: translateY(0); } 35%, 65% { transform: translateY(-120px); } }
@keyframes cs-t-stand { 0%, 100% { transform: scale(1, 1); } 30%, 70% { transform: scale(0.9, 1.25); } }
@keyframes cs-t-roll  { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); } }
@keyframes cs-t-hide  { 0%, 40%, 100% { transform: scale(1); } 20%, 60% { transform: scale(0.2); } }
@keyframes cs-t-hang  { 0%, 100% { transform: rotate(0); } 30%, 70% { transform: translateY(-40px) rotate(180deg); } }
@keyframes cs-t-howl  { 0%, 100% { transform: rotate(0); } 25%, 75% { transform: rotate(-18deg) scale(1.05); } }
@keyframes cs-note    { 0% { transform: translate(0, 0); opacity: 0; } 20% { opacity: 1; } 100% { transform: translate(16px, -40px); opacity: 0; } }
@keyframes cs-pop      { 0% { transform: translateX(-50%) scale(0.4); } 60% { transform: translateX(-50%) scale(1.15); } 100% { transform: translateX(-50%) scale(1); } }
@keyframes cs-soap     { 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -260%) scale(1.15); } }

/* ── Reduced motion: every animation above stops ───────────── */
/* ── CAMPS-04: bubbles that say one thing; what answers them glows ── */
.cs-i-soap   { fill: var(--wild-soap); stroke: var(--wild-soap-rim); stroke-width: 1.6; }
.cs-i-shine  { fill: var(--wild-soap-shine); }
.cs-i-drop   { fill: var(--wild-soap-rim); }
.cs-i-hand   { fill: var(--wild-star); stroke: var(--wild-star-edge); stroke-width: 1.6; stroke-linejoin: round; }
.cs-i-moon   { fill: var(--learn-moon); stroke: var(--wild-star-edge); stroke-width: 1.2; }
.cs-i-z      { stroke: var(--learn-hud-ink); }
.cs-bowlfood { position: relative; display: block; }
.cs-bowlfood svg { display: block; width: 100%; height: 100%; }
.cs-bowl-over { position: absolute; left: 50%; top: 2%; width: 66%; height: 66%; transform: translateX(-50%); object-fit: contain; pointer-events: none; }
.cs-bubble.is-big { box-shadow: 0 0 0 3px var(--wild-target), var(--shadow-md); }
.cs-glow { filter: drop-shadow(0 0 8px var(--wild-target)) drop-shadow(0 0 3px var(--wild-target)); animation: cs-glow 0.9s ease-in-out infinite; }
.lp-prop.cs-glow, .lp-fire.cs-glow { animation: none; }
.lp-prop.cs-glow > *, .lp-fire.cs-glow > img { animation: cs-bounce 0.9s ease-in-out infinite; }
.cs-ball { cursor: pointer; }
.cs-ball .lp-pe { display: block; transform-origin: 50% 50%; pointer-events: auto; }   /* BUG-01: tappable (the treat layer is pointer-events: none) */
@keyframes cs-glow { 0%, 100% { opacity: 1; } 50% { opacity: 0.85; } }
@keyframes cs-bounce { 0%, 100% { translate: 0 0; } 50% { translate: 0 -8%; } }

@media (prefers-reduced-motion: reduce) { .cs-drag-pic { transition: none; } .cs-drag-shadow { animation: none; } }   /* BUG-02 */
@media (prefers-reduced-motion: reduce) {
    .lp-breathe, .lp-animal.lp-squash, .lp-hop, .lp-chew,
    .lp-fire-flame, .lp-stars i, .lp-treat .lp-pe, .lp-zz,
    .lp-fire.is-full .lp-fimg-a, .lp-fire.is-full .lp-fimg-b { animation: none; }
    .lp-heart { display: none; }
    .lp-sky-night, .lp-veil, .lp-sun, .lp-moon, .lp-stars, .lp-mesa,
    .lp-emo-in, .lp-fire-glow, .lp-fire-flame, .lp-bd-night,
    .lp-scene.has-backdrop .lp-prop, .lp-scene.has-backdrop .lp-pool { transition: none; }
    /* WILD-02: a bubble appears; soap bubbles sit still for a moment. */
    .cs-bubble.cs-pop, .cs-soap, .lp-face.cs-trick .lp-animal, .cs-note { animation: none; }
    .cs-glow, .lp-prop.cs-glow > *, .lp-fire.cs-glow > img { animation: none; }
}

/* ── CAMPS-05: the berry bush (the world's bush, berries drawn on it), the
   shop building bobbing when something new is affordable, the lantern's
   light at night. ── */
.cs-berries {
    position: absolute; left: 0; transform: translateX(-50%); pointer-events: none;
    background:
        radial-gradient(circle at 22% 38%, var(--wild-berry) 0 7%, transparent 8%),
        radial-gradient(circle at 46% 22%, var(--wild-berry) 0 7%, transparent 8%),
        radial-gradient(circle at 70% 40%, var(--wild-berry) 0 7%, transparent 8%),
        radial-gradient(circle at 34% 64%, var(--wild-berry) 0 7%, transparent 8%),
        radial-gradient(circle at 60% 66%, var(--wild-berry) 0 7%, transparent 8%),
        radial-gradient(circle at 82% 60%, var(--wild-berry) 0 6%, transparent 7%);
}
.lp-prop[data-key="shop"].is-bob > .lp-pimg { animation: cs-shop-bob 1.1s ease-in-out infinite; }
@keyframes cs-shop-bob { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-7px); } }
.lp-prop[data-key="lantern"]::before {
    content: ''; position: absolute; left: 0; bottom: 10px; width: 120px; height: 90px; transform: translateX(-50%);
    border-radius: 50%; background: radial-gradient(closest-side, var(--learn-fire-glow), transparent); opacity: 0; transition: opacity 1.2s;
}
.lp-scene.is-night .lp-prop[data-key="lantern"]::before { opacity: 1; }
.lp-scene.has-backdrop.is-night .lp-prop[data-key="lantern"] { filter: none; }
@media (prefers-reduced-motion: reduce) {
    .lp-prop[data-key="shop"].is-bob > .lp-pimg { animation: none; }
}

/* ── BUG-04 (Andy): what a thing holds or grows, drawn on it ──
   A water bowl: dim when empty, a drop for each drink left above it.
   A food bowl / the feed station: the food waiting in it.
   A berry bush / garden: its fruit, small while it grows, full size and
   bouncing when it's ready to pick. A pillow or blanket under a sleeper. */
.cs-extra { position: absolute; left: 0; transform: translateX(-50%); pointer-events: none; display: flex; justify-content: center; align-items: flex-end; }
.lp-prop.is-empty > .lp-pimg { filter: grayscale(0.85) brightness(0.92); opacity: 0.8; }
.cs-drops { gap: 2px; }
.cs-drops i { display: block; width: 5px; height: 7px; border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; background: var(--learn-k-water); box-shadow: 0 0 0 1px var(--learn-shadow); }
.cs-held { flex-wrap: wrap; gap: 0; }
.cs-held .cs-held-img { margin: 0 -3px; filter: drop-shadow(0 1px 1px var(--learn-shadow)); }
.cs-fruit { flex-wrap: wrap; gap: 1px; transform-origin: 50% 100%; transition: transform 0.6s ease-out; }
.cs-fruit .cs-fruit-img { filter: drop-shadow(0 1px 1px var(--learn-shadow)); }
.lp-prop.is-ripe { cursor: pointer; }
.lp-prop.is-ripe > .cs-fruit { animation: cs-ripe-bounce 1.1s ease-in-out infinite; }
@keyframes cs-ripe-bounce { 0%, 100% { transform: translateX(-50%) translateY(0) scale(1); } 50% { transform: translateX(-50%) translateY(-6px) scale(1.06); } }
.cs-bedding { position: absolute; left: 0; bottom: -10px; transform: translateX(-50%); pointer-events: none; }
.cs-bedding .cs-bed-img { display: block; height: 34px; width: auto; }
@media (prefers-reduced-motion: reduce) {
    .lp-prop.is-ripe > .cs-fruit { animation: none; }
    .cs-fruit { transition: none; }
}
/* BUG-04: a pillow / teddy put down, a duck in the pond (tap: back to the tray). */
.cs-thing { cursor: pointer; }
.cs-thing .lp-pe { display: block; pointer-events: auto; }
.cs-duck .lp-pe { animation: cs-duck-bob 2.4s ease-in-out infinite; }
@keyframes cs-duck-bob { 0%, 100% { transform: translateX(-50%) translateY(0) rotate(-3deg); } 50% { transform: translateX(-50%) translateY(-3px) rotate(3deg); } }
@media (prefers-reduced-motion: reduce) { .cs-duck .lp-pe { animation: none; } }

/* BUG-05 (Andy): a hungry / thirsty bubble shows as many pictures as it still needs (2–5),
   overlapping and a little tilted; the bubble stretches into a pill around them. */
.cs-bubble.is-stack { width: auto; min-width: 46px; padding: 0 7px; border-radius: 999px; }
.cs-stack { display: flex; align-items: center; }
.cs-stack-i { display: block; flex: none; }
.cs-stack-i + .cs-stack-i { margin-left: -17px; }
.cs-stack .cs-bubble-img { width: 30px; height: 30px; filter: drop-shadow(0 1px 1px var(--learn-shadow)); }
.cs-stack-i:nth-child(1) { transform: rotate(-12deg); }
.cs-stack-i:nth-child(2) { transform: rotate(7deg) translateY(-2px); }
.cs-stack-i:nth-child(3) { transform: rotate(-5deg) translateY(1px); }
.cs-stack-i:nth-child(4) { transform: rotate(11deg) translateY(-1px); }
.cs-stack-i:nth-child(5) { transform: rotate(-8deg); }
