/* Looping photo carousels (screens 6, 7, 10, 13, 14). */

/* Tap-to-focus looping filmstrip: every photo is a permanent element
   positioned by its own --distance from whichever is centered (custom
   properties set from JS), so tapping a photo changes everyone's --distance
   at once and the whole strip slides over as one continuous transition,
   instead of slots just popping to new content. */
.carousel {
  position: relative;
  width: 100%;
  height: 45vh;
}

.carousel-photo {
  position: absolute;
  top: 50%;
  left: 50%;
  cursor: pointer;
  border: 6px solid #ffffff;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
  border-radius: 4px;
  /* No width/height and no object-fit on purpose: only capping max-width/
     max-height lets each photo keep its own aspect ratio, so nothing gets
     cropped and there's no letterboxed blank space inside a forced box. */
  max-width: 24vw;
  max-height: 30vh;
  /* --rotate is a unitless number (e.g. 6, -12); multiplying by 1deg inside
     calc() is what turns it into an actual angle. */
  transform: translate(-50%, -50%) translateX(calc(var(--distance, 0) * 26vw))
    rotate(calc(var(--rotate, 0) * 1deg)) scale(var(--scale, 1));
  transition: transform 0.45s ease, opacity 0.45s ease;
}

/* "Hey, tap me!" cue (screen6 only, see initLoopingCarousel's hintTap
   option and its one-time follow-up on a different photo after the first
   tap-to-zoom) - a little game-icon-style wiggle plus a soft glow pulse,
   cleared the moment the hinted photo is actually tapped. Reproduces
   .carousel-photo's own translateX/rotate/scale formula (not just a
   hardcoded "centered" transform) and adds the wiggle as an offset on top -
   the follow-up hint lands on a non-centered photo (real --distance/--rotate
   values), and overwriting those with a bare translate(-50%,-50%) snapped it
   to the center's position, hiding it behind the actual centered photo. */
@keyframes carousel-hint-wiggle {
  0%,
  40%,
  100% {
    transform: translate(-50%, -50%) translateX(calc(var(--distance, 0) * 26vw))
      rotate(calc(var(--rotate, 0) * 1deg)) scale(var(--scale, 1));
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
  }
  10% {
    transform: translate(-50%, -50%) translateX(calc(var(--distance, 0) * 26vw))
      rotate(calc((var(--rotate, 0) * 1deg) - 8deg)) scale(calc(var(--scale, 1) * 1.06));
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3), 0 0 20px 6px rgba(255, 255, 255, 0.7);
  }
  20% {
    transform: translate(-50%, -50%) translateX(calc(var(--distance, 0) * 26vw))
      rotate(calc((var(--rotate, 0) * 1deg) + 6deg)) scale(var(--scale, 1));
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
  }
  30% {
    transform: translate(-50%, -50%) translateX(calc(var(--distance, 0) * 26vw))
      rotate(calc((var(--rotate, 0) * 1deg) - 4deg)) scale(calc(var(--scale, 1) * 1.04));
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3), 0 0 20px 6px rgba(255, 255, 255, 0.7);
  }
}

.carousel-photo--hint {
  animation: carousel-hint-wiggle 2.4s ease-in-out infinite;
}

/* On phones a horizontal strip doesn't leave enough width per photo - slide
   vertically instead (same near->far pattern, top to bottom). */
@media (max-width: 600px) {
  .carousel {
    height: 62vh;
  }

  .carousel-photo {
    max-width: 55vw;
    max-height: 14vh;
    transform: translate(-50%, -50%) translateY(calc(var(--distance, 0) * 12vh))
      rotate(calc(var(--rotate, 0) * 1deg)) scale(var(--scale, 1));
  }

  /* Mirrors .carousel-photo's own translateY override above - same reason
     the base keyframes mirror its translateX form. */
  @keyframes carousel-hint-wiggle {
    0%,
    40%,
    100% {
      transform: translate(-50%, -50%) translateY(calc(var(--distance, 0) * 12vh))
        rotate(calc(var(--rotate, 0) * 1deg)) scale(var(--scale, 1));
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
    }
    10% {
      transform: translate(-50%, -50%) translateY(calc(var(--distance, 0) * 12vh))
        rotate(calc((var(--rotate, 0) * 1deg) - 8deg)) scale(calc(var(--scale, 1) * 1.06));
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3), 0 0 20px 6px rgba(255, 255, 255, 0.7);
    }
    20% {
      transform: translate(-50%, -50%) translateY(calc(var(--distance, 0) * 12vh))
        rotate(calc((var(--rotate, 0) * 1deg) + 6deg)) scale(var(--scale, 1));
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
    }
    30% {
      transform: translate(-50%, -50%) translateY(calc(var(--distance, 0) * 12vh))
        rotate(calc((var(--rotate, 0) * 1deg) - 4deg)) scale(calc(var(--scale, 1) * 1.04));
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3), 0 0 20px 6px rgba(255, 255, 255, 0.7);
    }
  }

  /* Shrunk specifically on the screens that pair a carousel with a message
     (and, on 6/7/13/14, an absolutely-positioned arrow-row near the bottom)
     - frees up room to let the carousel above be bigger without the two
     overlapping. screen26 has no carousel of its own but leads straight
     into screen27's, so its message is kept at the same size on purpose. */
  #screen6 .message,
  #screen7 .message,
  #screen10 .message,
  #screen13 .message,
  #screen14 .message,
  #screen26 .message,
  #screen27 .message {
    font-size: 1.5rem;
  }

  /* screen7/14 specifically: longer messages than their carousel-screen
     siblings above, which still overlapped the .arrow-row below even at
     1.5rem on a short mobile viewport (browser chrome eating into the
     visible height) - confirmed from screenshots. Shrunk further, on top
     of the 1.5rem rule above (source order breaks the tie in its favor). */
  #screen7 .message,
  #screen14 .message {
    font-size: 1.2rem;
  }

  /* .arrow-btn used to stay full desktop size here on purpose (see prior
     comment), but that - combined with a mobile browser's address bar
     shrinking the actually-visible height below what `.stage`'s 100svh
     already accounts for - left too little clearance between a carousel
     screen's message and its arrow-row, overlapping in practice (confirmed
     from screenshots on screen7/14). Shrinking the arrows themselves and
     pulling them closer to the true bottom edge reclaims that clearance. */
  .arrow-row {
    gap: 2rem;
  }

  /* :not(.arrow-row--top) matters here - .arrow-row--top (screen8's back
     arrow, .vase-back-row) sets `bottom: auto` to anchor from `top`
     instead, and a bare `.arrow-row { bottom: ... }` has the same
     specificity but comes later in the file, so it would win and hand
     .arrow-row--top a real `bottom` value again. With both `top` and
     `bottom` set, an absolutely positioned auto-height box stretches to
     span the gap between them and centers its content inside that span
     (.arrow-row's own `align-items: center` does that centering) - so the
     back arrow rendered in the middle of the screen instead of pinned at
     the top (confirmed from a screenshot) until this was scoped away from
     .arrow-row--top. */
  .arrow-row:not(.arrow-row--top) {
    bottom: 1.25rem;
  }

  .arrow-btn {
    font-size: 1.9rem;
  }

  /* screen8's intro message is unusually long for a plain text screen (it's
     also the mini-quiz lead-in) and had no mobile size reduction at all -
     at the full 2.5rem desktop size it wrapped to enough lines to fill
     nearly the whole short mobile viewport, butting straight up against
     its own .arrow-row--top back arrow above it (confirmed from a
     screenshot). Shrunk plus a bit of breathing room under the arrow. */
  #screen8 .message {
    font-size: 1.4rem;
    margin-top: 1rem;
  }

  /* screen28: photo + a long message + button together overflowed a short
     mobile viewport at desktop sizing (confirmed from a screenshot - the
     button was clipped off the bottom, same "browser chrome eats into the
     visible height" root cause as the other screens above). Shrunk the
     message and tightened the screen's own gap on top of .final-photo's own
     mobile max-height reduction, same combination used for screen7/14. */
  #screen28 {
    gap: 1.25rem;
  }

  #screen28 .message {
    font-size: 1.75rem;
  }
}
