/* ==========================================================================
   TRANSITIONS — the headline feature. Two page-turn effects, chosen per
   DESTINATION route by js/transitions.js (TRANSITION_BY_ROUTE), plus a
   reduced-motion fallback. Transforms/opacity only — no canvas, no
   rasterization. All durations/eases are tokens so timing lives in one place.
   ========================================================================== */

/* While a transition is running, #app hosts two absolutely-positioned
   layers stacked on top of one another. JS sets an explicit inline height
   on #app (matching the taller of the two sections) so the layout doesn't
   collapse while both children are taken out of flow. */
#app.is-transitioning {
  position: relative;
  overflow: hidden;
}
.tr-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  /* the layers are viewport-sized now; clip a tall page's below-fold content
     rather than letting it overflow the animating box */
  overflow: hidden;
}

/* ==========================================================================
   PAPER CURL — outgoing page rotates away on its left edge like a page
   in a book, revealing the paper-coloured back (wobbly torn edge) and the
   static incoming page underneath. ~650ms.
   ========================================================================== */
#app.tr-curl {
  perspective: 2000px;
}
.tr-curl-in {
  z-index: 1;
}
.tr-curl-out {
  z-index: 3;
  transform-origin: left center;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  will-change: transform;
  animation: curlOutFwd var(--dur-curl) var(--ease-curl) forwards;
}
.tr-curl-out.is-reverse {
  transform-origin: right center;
  animation-name: curlOutRev;
}
@keyframes curlOutFwd { from { transform: rotateY(0deg); } to { transform: rotateY(-180deg); } }
@keyframes curlOutRev { from { transform: rotateY(0deg); } to { transform: rotateY(180deg); } }

/* the back face of the turning page: flat kraft paper with a wobbly cut
   edge, only visible once the page has rotated past 90deg */
.tr-curl-out::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--paper);
  filter: url(#wobble);
  transform: rotateY(180deg);
  backface-visibility: hidden;
}

/* a soft shadow that sweeps across the incoming page as the outgoing
   page lifts away from it */
.tr-curl-shade {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(10,59,65,0.65), rgba(10,59,65,0) 55%);
  opacity: 0;
  animation: curlShadeFwd var(--dur-curl) var(--ease-curl) forwards;
}
.tr-curl-shade.is-reverse {
  background: linear-gradient(270deg, rgba(10,59,65,0.65), rgba(10,59,65,0) 55%);
}
@keyframes curlShadeFwd { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0; } }

/* ==========================================================================
   PANEL WIPE — the incoming page is covered by 6 wobbly-edged kraft
   panels that slide out alternately up/down with a stagger, revealing
   the new page frame by frame like a comic-book gutter. ~550ms.
   ========================================================================== */
.tr-wipe-in { z-index: 1; }
.tr-wipe-overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
}
.wipe-panel {
  flex: 1 1 0;
  height: 100%;
  background: var(--paper);
  filter: url(#wobble);
  transform: translateY(0) rotate(0deg);
  transition: transform var(--dur-wipe) var(--ease-wipe);
}
.wipe-panel.dir-up.out { transform: translateY(-120%) rotate(-3deg); }
.wipe-panel.dir-down.out { transform: translateY(120%) rotate(3deg); }

/* ==========================================================================
   REDUCED MOTION — both transitions collapse to a 120ms opacity crossfade.
   Non-negotiable: honoured both here and short-circuited in JS so the
   curl/wipe DOM never gets built in the first place.
   ========================================================================== */
.tr-fade-out { z-index: 3; animation: trFadeOut var(--dur-reduced) linear forwards; }
.tr-fade-in { z-index: 1; animation: trFadeIn var(--dur-reduced) linear forwards; }
@keyframes trFadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes trFadeIn { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .tr-curl-out, .tr-curl-out::after, .tr-curl-shade, .wipe-panel {
    animation: none !important;
    transition: none !important;
  }
}
