/* Continuous side-scroll transition. The persistent #ihs-backdrop provides the
   biome scenery; here we only slide the pipe in from the right and animate the
   couple. The world content slides out left (see worlds.css .ihs-slide-out-left).
   The overlay is transparent so the sliding content + backdrop stay visible. */
#ihs-transition {
  position: fixed; inset: 0; z-index: 900; pointer-events: none; opacity: 0;
  overflow: hidden; image-rendering: pixelated;
  --ihs-to-bg: var(--ihs-sky);
  background: transparent;
}
#ihs-transition.is-active { opacity: 1; }
/* the mirrored biome scene inside the overlay is not needed (backdrop shows it) */
#ihs-transition .ihs-scene, #ihs-transition .ihs-card { display: none; }

/* Black screen between worlds: fades to black during the blackout phase (over
   the pipe/couple), holds with a spinning logo, then fades out during reveal as
   the new world fades in. Top-most layer so it covers everything. */
#ihs-transition .ihs-dest {
  position: absolute; inset: 0; background: #000; z-index: 10; opacity: 0; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
}
#ihs-transition.is-blackout .ihs-dest { animation: ihs-toblack 0.55s ease-in forwards; }
#ihs-transition.is-reveal   .ihs-dest { animation: ihs-fromblack 1.1s ease-out forwards; }
@keyframes ihs-toblack   { from { opacity: 0; } to { opacity: 1; } }
@keyframes ihs-fromblack { from { opacity: 1; } to { opacity: 0; } }
/* Spinning Iron Hills logo as the loading indicator on the black screen */
#ihs-transition .ihs-loading-logo {
  width: clamp(160px, 50vw, 260px); height: auto; image-rendering: auto;
  opacity: 0;
}
#ihs-transition.is-blackout .ihs-loading-logo {
  opacity: 1; animation: ihs-logo-spin 1.4s linear infinite;
}
/* logo vanishes immediately when the reveal begins so it never overlaps content */
#ihs-transition.is-reveal .ihs-loading-logo { opacity: 0 !important; animation: none; }
/* When leaving a locked world, grey the spinning coin directly (not just via the
   parent filter) so it never flashes colour for a frame as blackout begins. */
#ihs-transition.ihs-locked-view .ihs-loading-logo { filter: grayscale(1) brightness(0.85); }
@keyframes ihs-logo-spin { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } }

/* Ground strip the pipe/sprite stand on (matches the world ground height) */
#ihs-transition .ihs-tr-ground {
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--ihs-ground-h); z-index: 2;
}

/* Warp pipe: slides IN from the right during slideout, then stays put. */
#ihs-transition .ihs-warp-pipe {
  position: absolute; bottom: var(--ihs-ground-h); right: 12%; width: 84px; height: 84px; z-index: 5;
  background-image: url('../img/tiles/pipe_full.png');
  background-repeat: no-repeat; background-size: 84px 84px;
  background-color: transparent; border: none; box-shadow: none;
  transform: translateX(140vw);   /* start off-screen right */
}
#ihs-transition.biome-castle .ihs-warp-pipe { background-image: url('../img/tiles/pipe_castle.png'); }
#ihs-transition.biome-underground .ihs-warp-pipe { background-image: url('../img/tiles/pipe_underground.png'); }
/* pipe slides into place during slideout and stays for run/jump/pipe */
@keyframes ihs-pipe-in { from { transform: translateX(140vw); } to { transform: translateX(0); } }
#ihs-transition.is-slideout .ihs-warp-pipe,
#ihs-transition.is-run .ihs-warp-pipe,
#ihs-transition.is-jump .ihs-warp-pipe,
#ihs-transition.is-pipe .ihs-warp-pipe { transform: translateX(0); }
#ihs-transition.is-slideout .ihs-warp-pipe { animation: ihs-pipe-in 1.05s cubic-bezier(0.33,0,0.2,1) forwards; }

/* Scroll-scrub: while the overlay is active but NOT in any is-<phase> class, the
   pipe position is driven purely by --ihs-progress (0 = off-screen, 1 = in place).
   --ihs-progress is set on #ihs-app and inherits down to #ihs-transition. */
#ihs-transition.is-active:not(.is-slideout):not(.is-run):not(.is-jump):not(.is-pipe):not(.is-blackout):not(.is-reveal) .ihs-warp-pipe {
  transform: translateX(calc((1 - var(--ihs-progress, 0)) * 140vw));
}
#ihs-transition[data-dir="back"].is-active:not(.is-slideout):not(.is-run):not(.is-jump):not(.is-pipe):not(.is-blackout):not(.is-reveal) .ihs-warp-pipe {
  transform: translateX(calc((1 - var(--ihs-progress, 0)) * -140vw));
}

/* Backward navigation mirrors the whole run-into-pipe scene: flip the overlay
   horizontally so the pipe enters from the LEFT and the couple runs right→left.
   (Only the pipe+hero layers flip, not the dest fade.) */
#ihs-transition[data-dir="back"] .ihs-warp-pipe { left: 12%; right: auto; transform: translateX(-140vw); }
@keyframes ihs-pipe-in-left { from { transform: translateX(-140vw); } to { transform: translateX(0); } }
#ihs-transition[data-dir="back"].is-slideout .ihs-warp-pipe { animation: ihs-pipe-in-left 1.05s cubic-bezier(0.33,0,0.2,1) forwards; }
#ihs-transition[data-dir="back"].is-run .ihs-warp-pipe,
#ihs-transition[data-dir="back"].is-jump .ihs-warp-pipe,
#ihs-transition[data-dir="back"].is-pipe .ihs-warp-pipe { transform: translateX(0); }
/* mirror the couple's run path to the left side */
#ihs-transition[data-dir="back"] .ihs-hero { transform: scaleX(-1); }
@keyframes ihs-run-back { from { left: calc(100% + 80px); } to { left: calc(12% + 90px); } }
#ihs-transition[data-dir="back"].is-run .ihs-hero { left: calc(12% + 90px);
  animation: ihs-run-back 1.3s steps(26) forwards, ihs-run-frames 0.4s steps(4) infinite; }
@keyframes ihs-jump-back {
  0%   { left: calc(12% + 90px); bottom: var(--ihs-ground-h); }
  50%  { left: calc(12% + 50px); bottom: 180px; }
  100% { left: calc(12% + 6px);  bottom: 156px; }
}
#ihs-transition[data-dir="back"].is-jump .ihs-hero { left: calc(12% + 6px); bottom: 156px;
  animation: ihs-jump-back 0.55s steps(9) forwards; }
#ihs-transition[data-dir="back"].is-pipe .ihs-hero { left: calc(12% + 6px); bottom: 60px;
  clip-path: inset(0 0 96px 0); z-index: 4;
  animation: ihs-pipe-down 0.8s linear forwards; }

/* Couple sprite (80×96, 4-frame run sheet), standing on the ground */
#ihs-transition .ihs-hero {
  position: absolute; bottom: var(--ihs-ground-h); left: -80px; width: 72px; height: 96px; z-index: 5;
  background-repeat: no-repeat; background-size: 288px 96px;
  image-rendering: pixelated; opacity: 0;
}
/* which of the couple runs — set per transition (alternates bride/groom) */
#ihs-transition .ihs-hero.hero-groom { background-image: url('../img/couple-groom.png'); }
#ihs-transition .ihs-hero.hero-bride { background-image: url('../img/couple-bride.png'); }
/* default before a character class is applied */
#ihs-transition .ihs-hero { background-image: url('../img/couple-groom.png'); }
/* hero hidden during slideout, appears to run once the pipe is settled */
#ihs-transition.is-run .ihs-hero,
#ihs-transition.is-jump .ihs-hero,
#ihs-transition.is-pipe .ihs-hero { opacity: 1; }

/* run: left -> up to just before the pipe */
@keyframes ihs-run { from { left: -80px; } to { left: calc(88% - 170px); } }
@keyframes ihs-run-frames { from { background-position-x: 0; } to { background-position-x: -288px; } }
#ihs-transition.is-run .ihs-hero {
  left: calc(88% - 170px);
  animation: ihs-run 1.3s steps(26) forwards, ihs-run-frames 0.4s steps(4) infinite;
}

/* jump: arc up onto the pipe rim (ground 72 + pipe 84 = 156px).
   Pipe: right:12% width:84px → center at 88%-42px. Hero box is 72px wide, so
   centering it on the pipe mouth needs left = 88%-42px-36px = 88%-78px. */
@keyframes ihs-jump {
  0%   { left: calc(88% - 170px); bottom: var(--ihs-ground-h); }
  50%  { left: calc(88% - 124px); bottom: 180px; }
  100% { left: calc(88% - 78px);  bottom: 156px; }
}
#ihs-transition.is-jump .ihs-hero {
  left: calc(88% - 78px); bottom: 156px; background-position-x: 0;
  animation: ihs-jump 0.55s steps(11) forwards;
}

/* pipe descent: authentic Mario "sink into the pipe" — the sprite lowers straight
   down while a clip-path hides everything that passes below the pipe rim (Y=156px:
   ground 72 + pipe 84). No fade: the body is progressively occluded by the rim, so
   it truly disappears INTO the mouth. bottom 156→60 (drops ~96px = one body height);
   clip inset-bottom 0→96 keeps the visible edge pinned at the rim. Pipe sits above
   the hero (higher z-index) so the rim itself masks the descending sprite too. */
@keyframes ihs-pipe-down {
  from { bottom: 156px; clip-path: inset(0 0 0 0); }
  to   { bottom: 60px;  clip-path: inset(0 0 96px 0); }
}
#ihs-transition.is-pipe .ihs-hero {
  left: calc(88% - 78px); bottom: 60px; background-position-x: 0;
  clip-path: inset(0 0 96px 0); z-index: 4;
  animation: ihs-pipe-down 0.8s linear forwards;
}
/* pipe rim covers the sinking sprite (hero z-index:4 during descent) */
#ihs-transition.is-pipe .ihs-warp-pipe { z-index: 6; }

@media (prefers-reduced-motion: reduce) {
  #ihs-transition .ihs-hero, #ihs-transition .ihs-warp-pipe { animation: none !important; }
  #ihs-transition .ihs-dest { animation: none !important; clip-path: none !important; }
  .ihs-world.ihs-slide-out-left, .ihs-world.ihs-slide-in-right { animation: none !important; }
}
