/*
  Lili's Little Rescue Shop — scene-specific styling.
  Shared chrome (topbar, speech bubble, character states, the base
  confetti/completion system) lives in games/shared/game-shell.css —
  this file covers Lili's cozy fix-it workshop backdrop, the two
  character slots (Lili + whichever friend is visiting), and the six
  challenges' own draggable/tappable pieces.

  UNLIKE the other five games (which are all "tap the one correct
  target among distractors"), every challenge here is solved by
  DRAGGING or building up taps on a single object — there is no
  multiple-choice tap target anywhere in this file. Draggable pieces
  are positioned with plain top/left percentages for their resting
  spot, then nudged during a drag with the --dragx/--dragy custom
  properties below so the base centering transform and the live drag
  offset never fight over the same `transform` value.
*/

#gameStage{
  background:
    radial-gradient(circle at 50% 0%, color-mix(in srgb, #FFE9C7 55%, transparent), transparent 46%),
    linear-gradient(175deg, #FBEFE0 0%, #F3DCC0 45%, #E6C79C 100%);
}
#gameStage::before{
  /* Warm wooden workbench strip along the bottom — everything in every
     challenge visually "sits on" this. */
  content:""; position:absolute; left:0; right:0; bottom:0; height:20%; z-index:1;
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,0.05) 0 2px, transparent 2px 46px),
    linear-gradient(to top, #B98356 0%, #C9976A 100%);
  pointer-events:none;
}
.shop-window{
  position:absolute; z-index:1; right:5%; top:3%; width:min(30vw,180px); height:min(22vw,132px);
  border-radius:16px; pointer-events:none;
  background:radial-gradient(circle at 40% 30%, rgba(255,246,214,0.95), rgba(255,225,160,0.35) 60%, transparent 75%);
}
.shop-shelf{ z-index:1; }
.ribbon-strand{
  width:6px; height:22%; top:0; border-radius:0 0 6px 6px; transform-origin:top center;
  background:linear-gradient(180deg, #FF9FC2, #E5568C);
  animation:env-sway-rock 4.6s ease-in-out infinite;
}
.ribbon-strand-1{ left:58%; }
.ribbon-strand-2{ left:88%; height:16%; animation-duration:3.9s; animation-delay:-1.1s; background:linear-gradient(180deg, #FFC22E, #E5A400); }

/* ---------- Lili (always present, left side) ---------- */
/* Slightly larger than the friend character opposite her (19vw/120px)
   so she reads clearly as the main helper, not just another character. */
#liliChar{ left:4%; top:13%; width:min(27vw,172px); height:min(27vw,172px); z-index:10; }
#liliChar .speech-bubble-game{
  left:100%; top:50%; margin-left:14px; right:auto; bottom:auto;
  width:min(58vw,250px);
  transform-origin:left center; transform:translateY(-50%) scale(0.92);
}
#liliChar .speech-bubble-game.is-visible{ transform:translateY(-50%) scale(1); }
#liliChar .speech-bubble-game::after{ content:none; }

/* ---------- the visiting friend (right side, swapped per challenge) ---------- */
.friend-character{
  right:4%; top:13%; left:auto; width:min(19vw,120px); height:min(19vw,120px); z-index:9;
  opacity:0; transform:translateX(30px); transition:opacity .35s ease, transform .35s ease; pointer-events:none;
}
.friend-character.is-visible{ opacity:1; transform:translateX(0); }
.friend-bubble{
  right:100%; left:auto; top:50%; margin-right:14px; bottom:auto;
  width:min(50vw,220px);
  transform-origin:right center; transform:translateY(-50%) scale(0.92);
}
.friend-bubble.is-visible{ transform:translateY(-50%) scale(1); }
.friend-bubble::after{ content:none; }

#challengeField{ position:absolute; inset:0; z-index:5; }

/* ---------- shared draggable-piece plumbing ---------- */
.rescue-piece{
  position:absolute; touch-action:none; cursor:grab; user-select:none; -webkit-tap-highlight-color:transparent;
  transform:translate(calc(-50% + var(--dragx,0px)), calc(-50% + var(--dragy,0px)));
}
.rescue-piece.is-dragging{ cursor:grabbing; z-index:20; transition:none; }
.rescue-piece:not(.is-dragging){ transition:transform .32s cubic-bezier(.34,1.56,.64,1); }
.rescue-piece:focus-visible{ outline:3px solid var(--blue); outline-offset:6px; border-radius:16px; }
.rescue-piece.is-settled{ cursor:default; }

/* A gentle, funny "not yet" bounce-back — distinct from the tap games'
   sharper .obj-wrong shake, since nothing here is ever "wrong", just
   not finished yet. */
@keyframes rescue-boing{
  0%,100%{ transform:translate(calc(-50% + var(--dragx,0px)), calc(-50% + var(--dragy,0px))) scale(1); }
  30%{ transform:translate(calc(-50% + var(--dragx,0px)), calc(-50% + var(--dragy,0px))) scale(1.1) rotate(-4deg); }
  60%{ transform:translate(calc(-50% + var(--dragx,0px)), calc(-50% + var(--dragy,0px))) scale(0.95) rotate(3deg); }
}
.rescue-piece.is-boing{ animation:rescue-boing .45s ease; }

/* A compact two-line "what to do" header for the current challenge,
   anchored near the top of the play area rather than floating over the
   interactive object itself. Unlike the old always-on hint pill, this
   shrinks out of the way the moment the player starts interacting with
   the target (see minimizeChallengeHeader() in the JS), so the stage
   stays visually clean once they've got the idea instead of leaving a
   box parked over the gameplay for the rest of the challenge. */
.challenge-header{
  /* z-index:12 — appended directly to #gameStage (not #challengeField,
     which sits in a lower stacking context at z-index:5) so it always
     paints above #liliChar/.friend-character (z-index:10/9) and can
     never be silently covered by a speech bubble, on any breakpoint.
     top:32% (28% mobile) clears Lili's speech bubble even in its worst
     case — a two-line wrap — at short/wide viewports like 768x700,
     where the character row's fixed-height bubble eats a bigger slice
     of a shorter stage than it does on a tall desktop viewport. */
  position:absolute; left:50%; top:32%; transform:translateX(-50%) scale(1); z-index:12;
  max-width:86%; text-align:center;
  background:var(--surface); border:2px solid var(--line); border-radius:18px;
  padding:8px 20px; box-shadow:0 3px 0 var(--line); pointer-events:none;
  transition:opacity .3s ease, transform .3s ease;
}
.challenge-header-title{
  display:block; font-weight:800; font-size:clamp(0.82rem,2.3vw,0.98rem); color:var(--coral);
}
.challenge-header-sub{
  display:block; font-weight:700; font-size:clamp(0.74rem,2vw,0.86rem); color:var(--ink); opacity:0.85; margin-top:1px;
}
.challenge-header.is-minimized{
  opacity:0; transform:translateX(-50%) scale(0.85) translateY(-8px);
}
@media (max-width:600px){
  .challenge-header{ top:28%; padding:6px 14px; max-width:80%; }
}

/* ================= Challenge 1: Gerry's Tangled Bow ================= */
.knot-wrap{ left:50%; top:52%; width:clamp(130px,27vw,196px); height:clamp(130px,27vw,196px); }
.knot-svg{ width:100%; height:100%; display:block; filter:drop-shadow(0 8px 10px rgba(0,0,0,0.2)); }
.knot-wrap[data-tugs="0"] .knot-loop{ transform:scale(1); }
.knot-wrap[data-tugs="1"] .knot-loop{ transform:scale(0.86) rotate(-6deg); }
.knot-wrap[data-tugs="2"] .knot-loop{ transform:scale(0.68) rotate(-12deg); }
.knot-loop{ transform-origin:50% 52.5%; transition:transform .35s ease; }

/* A gentle "notice me" pulse before the player has touched the ribbon
   at all — applied to the SVG child, never to .knot-wrap itself, since
   .knot-wrap's own transform already carries its drag position (see
   the shared draggable-piece comment above); animating that directly
   would silently fight the drag offset. Stops the instant a drag or
   tap begins (JS removes the class in attachDrag's onStart). */
@keyframes knot-idle-pulse{
  0%,100%{ transform:scale(1); }
  50%{ transform:scale(1.06); }
}
.knot-wrap.is-idle-pulse .knot-svg{ animation:knot-idle-pulse 1.7s ease-in-out infinite; }

/* First-interaction drag tutorial: a small hand that tugs the loose
   ribbon end in a short back-and-forth arc, positioned as a child of
   .knot-wrap itself (so it sits right on the visible loose end and
   moves with it). Removed by JS on first real interaction or after a
   few seconds, whichever comes first — never nags once the player has
   started. */
.drag-tutorial{
  position:absolute; left:60%; top:76%; z-index:2; pointer-events:none;
  font-size:clamp(1.6rem,5vw,2.1rem); line-height:1; transform:translate(-50%,-50%);
  filter:drop-shadow(0 3px 4px rgba(0,0,0,0.25));
  animation:tutorial-tug 1.5s ease-in-out infinite;
}
@keyframes tutorial-tug{
  0%,100%{ transform:translate(-50%,-50%) translate(0,0) rotate(0deg); opacity:0.9; }
  45%{ transform:translate(-50%,-50%) translate(-16px,20px) rotate(-14deg); opacity:1; }
}
/* Reduced motion: swap the animated hand for a static outlined arrow +
   a highlight ring around the loose end — still communicates "grab and
   pull here" without any repeating motion. */
.drag-tutorial.is-static{ animation:none; font-size:clamp(1.3rem,4vw,1.7rem); }
.drag-tutorial.is-static .tutorial-ring{
  position:absolute; left:50%; top:50%; width:2.6em; height:2.6em; transform:translate(-50%,-50%);
  border:3px dashed var(--coral); border-radius:50%; opacity:0.85;
}

/* ================= Challenge 2: Ellie's Crooked Bow ================= */
.bow-target{
  position:absolute; width:clamp(56px,12vw,86px); height:clamp(56px,12vw,86px);
  border:3px dashed color-mix(in srgb, var(--purple) 60%, transparent); border-radius:50%;
  opacity:0.7; transform:translate(-50%,-50%);
}
.bow-drag{ width:clamp(58px,13vw,92px); height:clamp(58px,13vw,92px); }
.bow-drag svg{ width:100%; height:100%; filter:drop-shadow(0 6px 8px rgba(0,0,0,0.22)); }

/* ================= Challenge 3: BunBun's Button Problem ================= */
.button-target{
  position:absolute; border:3px dashed color-mix(in srgb, var(--blue) 55%, transparent); border-radius:50%;
  opacity:0.75; transform:translate(-50%,-50%);
}
.button-piece svg{ width:100%; height:100%; filter:drop-shadow(0 6px 8px rgba(0,0,0,0.2)); }
.stitch-needle{
  position:absolute; z-index:9; font-size:1.6rem; pointer-events:none; opacity:0;
  transform:translate(-50%,-50%) rotate(-35deg);
}
.stitch-needle.is-stitching{ animation:stitch-pass .6s ease 2; }
@keyframes stitch-pass{
  0%{ opacity:0; transform:translate(-70%,-70%) rotate(-35deg); }
  15%{ opacity:1; }
  50%{ transform:translate(-30%,-30%) rotate(-35deg); }
  85%{ opacity:1; }
  100%{ opacity:0; transform:translate(-70%,-70%) rotate(-35deg); }
}

/* ================= Challenge 4: Milo's Mess ================= */
.mess-part svg{ width:100%; height:100%; filter:drop-shadow(0 6px 8px rgba(0,0,0,0.22)); }
.mess-part-a{ width:clamp(64px,13vw,96px); height:clamp(64px,13vw,96px); }
.mess-part-b{ width:clamp(64px,13vw,96px); height:clamp(64px,13vw,96px); }
.mess-spark{
  position:absolute; z-index:9; font-size:2.2rem; pointer-events:none; opacity:0; transform:translate(-50%,-50%) scale(0.5);
}
.mess-spark.is-bursting{ animation:mess-spark-burst .8s ease forwards; }
@keyframes mess-spark-burst{
  0%{ opacity:0; transform:translate(-50%,-50%) scale(0.4) rotate(0deg); }
  30%{ opacity:1; transform:translate(-50%,-50%) scale(1.3) rotate(-10deg); }
  60%{ transform:translate(-50%,-50%) scale(1) rotate(8deg); }
  100%{ opacity:0; transform:translate(-50%,-50%) scale(1.1) rotate(0deg); }
}

/* ================= Challenge 5: Dodo's Silly Problem ================= */
.jar-wrap{
  position:absolute; left:50%; top:56%; width:clamp(110px,24vw,170px); height:clamp(130px,28vw,200px);
  cursor:pointer; touch-action:manipulation; -webkit-tap-highlight-color:transparent;
  transform:translate(-50%,-50%);
}
.jar-wrap:focus-visible{ outline:3px solid var(--blue); outline-offset:6px; border-radius:16px; }
.jar-wrap svg{ width:100%; height:100%; display:block; filter:drop-shadow(0 10px 12px rgba(0,0,0,0.24)); }
.jar-wrap.is-wiggling{ animation:jar-wiggle .35s ease; }
@keyframes jar-wiggle{
  0%,100%{ transform:translate(-50%,-50%) rotate(0deg); }
  25%{ transform:translate(-50%,-50%) rotate(-7deg); }
  50%{ transform:translate(-50%,-50%) rotate(6deg); }
  75%{ transform:translate(-50%,-50%) rotate(-4deg); }
}
.jar-wrap.is-popping{ animation:jar-pop-off .6s ease forwards; }
@keyframes jar-pop-off{
  0%{ transform:translate(-50%,-50%) rotate(0deg) scale(1); opacity:1; }
  40%{ transform:translate(-50%,-140%) rotate(60deg) scale(0.9); opacity:1; }
  100%{ transform:translate(120%,-220%) rotate(220deg) scale(0.6); opacity:0; }
}

/* ================= Challenge 6: The Big Rescue (finale) ================= */
.rescue-item{ position:absolute; width:clamp(56px,12vw,84px); height:clamp(56px,12vw,84px); cursor:pointer; touch-action:manipulation; -webkit-tap-highlight-color:transparent; transform:translate(-50%,-50%); }
.rescue-item svg{ width:100%; height:100%; filter:drop-shadow(0 6px 8px rgba(0,0,0,0.2)); }
.rescue-item:focus-visible{ outline:3px solid var(--blue); outline-offset:6px; border-radius:16px; }
.rescue-item.is-rolling{ animation:rescue-roll 2.6s ease-in-out infinite; }
@keyframes rescue-roll{
  0%,100%{ transform:translate(-50%,-50%) rotate(0deg); }
  50%{ transform:translate(calc(-50% + 40px),-50%) rotate(180deg); }
}
.rescue-item.is-spinning{ animation:rescue-spin 1.4s linear infinite; }
@keyframes rescue-spin{
  from{ transform:translate(-50%,-50%) rotate(0deg); }
  to{ transform:translate(-50%,-50%) rotate(360deg); }
}
.rescue-item.is-resolved{ animation:rescue-item-resolved .5s ease forwards; }
@keyframes rescue-item-resolved{ to{ transform:translate(-50%,-50%) scale(0.5); opacity:0; } }
.rescue-piece.is-resolved{ animation:rescue-piece-resolved .5s ease forwards; }
@keyframes rescue-piece-resolved{ to{ transform:translate(calc(-50% + var(--dragx,0px)), calc(-50% + var(--dragy,0px))) scale(0.5); opacity:0; } }
.finale-friends-row{
  position:absolute; left:50%; bottom:6%; transform:translateX(-50%); z-index:8;
  display:flex; gap:6px; pointer-events:none;
}
.finale-friends-row img{ width:clamp(34px,7vw,50px); height:clamp(34px,7vw,50px); object-fit:contain; filter:drop-shadow(0 4px 6px rgba(0,0,0,0.2)); }

@media (prefers-reduced-motion:reduce){
  .ribbon-strand, .rescue-item.is-rolling, .rescue-item.is-spinning{ animation:none; }
  .rescue-piece.is-boing{ animation:none; }
  .jar-wrap.is-wiggling{ animation:none; }
  .rescue-piece:not(.is-dragging){ transition:none; }
  .knot-wrap.is-idle-pulse .knot-svg{ animation:none; }
  .drag-tutorial{ animation:none; }
  /* Interactive elements stay fully usable — only the decorative /
     celebratory MOTION is removed, per game-shell.css's own pattern.
     The JS also swaps in the static hand/ring tutorial directly when
     prefers-reduced-motion is on, so this is a defense-in-depth match
     for that same state rather than the only place it's handled. */
}

@media (max-width:600px){
  #liliChar{ width:138px; height:138px; }
  #liliChar .speech-bubble-game{ width:min(48vw,190px); }
  .friend-character{ width:96px; height:96px; }
  .friend-bubble{ width:min(42vw,170px); }
  .shop-window{ width:34vw; height:26vw; }
}
