:root {
  color-scheme: dark;
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100dvh;
  background: #000;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

#stage {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100dvh;
  background: #000;
  perspective: 1200px;
  overflow: hidden;
}

.slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  background: #000;
  transform-origin: center center;
  will-change: transform, opacity, filter, clip-path;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
}

.slide.empty {
  color: #555;
  font: 500 14px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  text-align: center;
  padding: 2rem;
}

.slide.empty::before {
  content: "drop images into /public/images/";
  display: block;
}

#hud {
  position: fixed;
  left: 50%;
  bottom: max(1rem, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  padding: 0.4rem 0.7rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: #fff;
  font: 500 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease;
  z-index: 10;
}

#hud[hidden] {
  display: none;
}

#hud.visible {
  opacity: 1;
}

#info {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 0 1.25rem max(2rem, env(safe-area-inset-bottom)) 1.25rem;
  z-index: 20;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 55%,
    rgba(0, 0, 0, 0.55) 90%,
    rgba(0, 0, 0, 0.7) 100%
  );
  animation: info-fade-in 0.3s ease-out;
}

#info[hidden] {
  display: none;
}

#info::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: auto;
}

.info-row {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #fff;
  font: 500 13px/1 ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
  margin-bottom: 0.6rem;
}

.info-sep {
  opacity: 0.5;
  font-weight: 400;
}

.info-hint {
  position: relative;
  font: 500 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}

@keyframes info-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

body.paused #stage::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at center, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.25) 100%);
  pointer-events: none;
  z-index: 5;
  animation: info-fade-in 0.3s ease-out;
}

/* ============================================================
 * silly transitions — each animation pair is `<name>-out`
 * (current slide leaves) and `<name>-in` (new slide enters).
 * Direction (1 = forward, -1 = backward) is passed as
 * `--dir` so animations can mirror.
 * ============================================================ */

.slide.exiting,
.slide.entering {
  pointer-events: none;
}

/* slide-horizontal */
@keyframes slide-h-out {
  to { transform: translateX(calc(-100% * var(--dir, 1))); }
}
@keyframes slide-h-in {
  from { transform: translateX(calc(100% * var(--dir, 1))); }
  to   { transform: translateX(0); }
}
.t-slide-h.exiting  { animation: slide-h-out 0.42s cubic-bezier(0.4, 0, 0.2, 1) forwards; }
.t-slide-h.entering { animation: slide-h-in  0.42s cubic-bezier(0.4, 0, 0.2, 1) forwards; }

/* slide-vertical */
@keyframes slide-v-out {
  to { transform: translateY(calc(-100% * var(--dir, 1))); }
}
@keyframes slide-v-in {
  from { transform: translateY(calc(100% * var(--dir, 1))); }
  to   { transform: translateY(0); }
}
.t-slide-v.exiting  { animation: slide-v-out 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards; }
.t-slide-v.entering { animation: slide-v-in  0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards; }

/* fade */
@keyframes fade-out { to { opacity: 0; } }
@keyframes fade-in  { from { opacity: 0; } to { opacity: 1; } }
.t-fade.exiting  { animation: fade-out 0.55s ease-out forwards; }
.t-fade.entering { animation: fade-in  0.55s ease-out forwards; }

/* zoom-in: outgoing zooms huge & fades, incoming pops from small */
@keyframes zoom-in-out {
  to { transform: scale(2.4); opacity: 0; filter: blur(8px); }
}
@keyframes zoom-in-in {
  from { transform: scale(0.2); opacity: 0; filter: blur(4px); }
  to   { transform: scale(1);   opacity: 1; filter: blur(0); }
}
.t-zoom-in.exiting  { animation: zoom-in-out  0.55s cubic-bezier(0.5, 0, 0.7, 0.2) forwards; }
.t-zoom-in.entering { animation: zoom-in-in   0.55s cubic-bezier(0.16, 1, 0.3, 1) forwards; }

/* zoom-out: outgoing shrinks, incoming grows from huge */
@keyframes zoom-out-out {
  to { transform: scale(0.05); opacity: 0; }
}
@keyframes zoom-out-in {
  from { transform: scale(2.4); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}
.t-zoom-out.exiting  { animation: zoom-out-out 0.55s cubic-bezier(0.7, 0, 0.84, 0) forwards; }
.t-zoom-out.entering { animation: zoom-out-in  0.55s cubic-bezier(0.16, 1, 0.3, 1) forwards; }

/* spin: 360 + scale */
@keyframes spin-out {
  to { transform: rotate(calc(360deg * var(--dir, 1))) scale(0); opacity: 0; }
}
@keyframes spin-in {
  from { transform: rotate(calc(-360deg * var(--dir, 1))) scale(0); opacity: 0; }
  to   { transform: rotate(0) scale(1); opacity: 1; }
}
.t-spin.exiting  { animation: spin-out 0.7s cubic-bezier(0.55, 0.05, 0.5, 0.5) forwards; }
.t-spin.entering { animation: spin-in  0.7s cubic-bezier(0.16, 1, 0.3, 1) forwards; }

/* flip-x: 3D card flip horizontal */
@keyframes flip-x-out {
  from { transform: rotateY(0); }
  to   { transform: rotateY(calc(90deg * var(--dir, 1))); opacity: 0; }
}
@keyframes flip-x-in {
  from { transform: rotateY(calc(-90deg * var(--dir, 1))); opacity: 0; }
  to   { transform: rotateY(0); opacity: 1; }
}
.t-flip-x.exiting  { animation: flip-x-out 0.45s ease-in  forwards; }
.t-flip-x.entering { animation: flip-x-in  0.45s ease-out forwards; animation-delay: 0.45s; }

/* flip-y: vertical flip */
@keyframes flip-y-out {
  to { transform: rotateX(calc(90deg * var(--dir, 1))); opacity: 0; }
}
@keyframes flip-y-in {
  from { transform: rotateX(calc(-90deg * var(--dir, 1))); opacity: 0; }
  to   { transform: rotateX(0); opacity: 1; }
}
.t-flip-y.exiting  { animation: flip-y-out 0.45s ease-in  forwards; }
.t-flip-y.entering { animation: flip-y-in  0.45s ease-out forwards; animation-delay: 0.45s; }

/* blur-swap */
@keyframes blur-out {
  to { filter: blur(40px); opacity: 0; transform: scale(1.2); }
}
@keyframes blur-in {
  from { filter: blur(40px); opacity: 0; transform: scale(0.92); }
  to   { filter: blur(0);    opacity: 1; transform: scale(1); }
}
.t-blur.exiting  { animation: blur-out 0.45s ease-in  forwards; }
.t-blur.entering { animation: blur-in  0.55s ease-out forwards; }

/* shake-out */
@keyframes shake-out {
  0%   { transform: translate(0); }
  20%  { transform: translate(-12px, 6px) rotate(-2deg); }
  40%  { transform: translate(10px, -6px) rotate(2deg); }
  60%  { transform: translate(-8px, 4px) rotate(-1deg); }
  80%  { transform: translate(6px, -4px) rotate(1deg); }
  100% { transform: translate(0) scale(0.6); opacity: 0; }
}
@keyframes shake-in {
  from { transform: scale(0.6); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}
.t-shake.exiting  { animation: shake-out 0.6s ease-in-out forwards; }
.t-shake.entering { animation: shake-in  0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards; animation-delay: 0.3s; }

/* iris: clip-path circle reveal */
@keyframes iris-out {
  from { clip-path: circle(80% at 50% 50%); }
  to   { clip-path: circle(0%  at 50% 50%); }
}
@keyframes iris-in {
  from { clip-path: circle(0%  at 50% 50%); }
  to   { clip-path: circle(80% at 50% 50%); }
}
.t-iris.exiting  { animation: iris-out 0.5s ease-in  forwards; }
.t-iris.entering { animation: iris-in  0.55s ease-out forwards; animation-delay: 0.1s; }

/* fall: outgoing falls off screen with rotation, incoming drops in */
@keyframes fall-out {
  to { transform: translateY(120%) rotate(calc(35deg * var(--dir, 1))); opacity: 0; }
}
@keyframes fall-in {
  from { transform: translateY(-120%) rotate(calc(-25deg * var(--dir, 1))); opacity: 0; }
  to   { transform: translateY(0) rotate(0); opacity: 1; }
}
.t-fall.exiting  { animation: fall-out 0.6s cubic-bezier(0.7, 0, 0.84, 0) forwards; }
.t-fall.entering { animation: fall-in  0.65s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.1s; }

/* swoosh: diagonal slide */
@keyframes swoosh-out {
  to { transform: translate(calc(-120% * var(--dir, 1)), 80%) rotate(calc(-15deg * var(--dir, 1))); opacity: 0; }
}
@keyframes swoosh-in {
  from { transform: translate(calc(120% * var(--dir, 1)), -80%) rotate(calc(15deg * var(--dir, 1))); opacity: 0; }
  to   { transform: translate(0, 0) rotate(0); opacity: 1; }
}
.t-swoosh.exiting  { animation: swoosh-out 0.5s cubic-bezier(0.7, 0, 0.84, 0) forwards; }
.t-swoosh.entering { animation: swoosh-in  0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards; }

/* invert-flash: brief invert + bright flash */
@keyframes invert-out {
  0%   { filter: invert(0); }
  50%  { filter: invert(1) brightness(2); }
  100% { filter: invert(0); opacity: 0; }
}
@keyframes invert-in {
  0%   { filter: invert(1) brightness(2); opacity: 0; }
  50%  { filter: invert(1) brightness(2); opacity: 1; }
  100% { filter: invert(0) brightness(1); opacity: 1; }
}
.t-invert.exiting  { animation: invert-out 0.35s linear forwards; }
.t-invert.entering { animation: invert-in  0.35s linear forwards; }

/* bounce */
@keyframes bounce-out {
  to { transform: scale(0); opacity: 0; }
}
@keyframes bounce-in {
  0%   { transform: scale(0); opacity: 0; }
  60%  { transform: scale(1.18); opacity: 1; }
  80%  { transform: scale(0.94); }
  100% { transform: scale(1); }
}
.t-bounce.exiting  { animation: bounce-out 0.35s ease-in forwards; }
.t-bounce.entering { animation: bounce-in  0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.1s; }

/* wipe-diagonal */
@keyframes wipe-out {
  from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
  to   { clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%); }
}
@keyframes wipe-in {
  from { clip-path: polygon(0 0, 0 0, 0 100%, 0 100%); }
  to   { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
}
.t-wipe.exiting  { animation: wipe-out 0.5s ease-in-out forwards; }
.t-wipe.entering { animation: wipe-in  0.5s ease-in-out forwards; animation-delay: 0.1s; }

/* squish */
@keyframes squish-out {
  to { transform: scaleY(0.02) scaleX(1.4); opacity: 0; }
}
@keyframes squish-in {
  from { transform: scaleY(0.02) scaleX(1.4); opacity: 0; }
  to   { transform: scaleY(1) scaleX(1); opacity: 1; }
}
.t-squish.exiting  { animation: squish-out 0.35s ease-in  forwards; }
.t-squish.entering { animation: squish-in  0.55s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.2s; }

/* kaleido-spin: spin many times with hue shift */
@keyframes kaleido-out {
  to { transform: rotate(calc(720deg * var(--dir, 1))) scale(0); filter: hue-rotate(360deg); opacity: 0; }
}
@keyframes kaleido-in {
  from { transform: rotate(calc(-720deg * var(--dir, 1))) scale(0); filter: hue-rotate(-360deg); opacity: 0; }
  to   { transform: rotate(0) scale(1); filter: hue-rotate(0); opacity: 1; }
}
.t-kaleido.exiting  { animation: kaleido-out 0.85s cubic-bezier(0.55, 0.05, 0.5, 0.5) forwards; }
.t-kaleido.entering { animation: kaleido-in  0.85s cubic-bezier(0.16, 1, 0.3, 1) forwards; }

/* pixelate-fade (cheap pixelate using contrast + blur) */
@keyframes pix-out {
  to { filter: contrast(0.4) blur(20px) saturate(2); opacity: 0; transform: scale(1.05); }
}
@keyframes pix-in {
  from { filter: contrast(0.4) blur(20px) saturate(2); opacity: 0; transform: scale(0.95); }
  to   { filter: contrast(1) blur(0) saturate(1); opacity: 1; transform: scale(1); }
}
.t-pix.exiting  { animation: pix-out 0.4s ease-in  forwards; }
.t-pix.entering { animation: pix-in  0.5s ease-out forwards; animation-delay: 0.1s; }

/* skew-glitch */
@keyframes glitch-out {
  0%   { transform: translate(0) skew(0); filter: hue-rotate(0); }
  20%  { transform: translate(-8px, 4px) skew(-6deg); filter: hue-rotate(90deg) saturate(2); }
  40%  { transform: translate(6px, -2px) skew(8deg); filter: hue-rotate(-90deg) saturate(2); }
  60%  { transform: translate(-4px, 6px) skew(-3deg); filter: hue-rotate(180deg); }
  100% { transform: translate(0) skew(0) scale(0.7); opacity: 0; }
}
@keyframes glitch-in {
  0%   { transform: scale(0.7) skew(6deg); opacity: 0; filter: hue-rotate(180deg); }
  100% { transform: scale(1) skew(0); opacity: 1; filter: hue-rotate(0); }
}
.t-glitch.exiting  { animation: glitch-out 0.45s steps(8, end) forwards; }
.t-glitch.entering { animation: glitch-in  0.35s ease-out forwards; animation-delay: 0.4s; }

/* door-swing: rotate from edge */
@keyframes door-out {
  to { transform: rotateY(calc(-110deg * var(--dir, 1))); transform-origin: calc(50% - 50% * var(--dir, 1)) 50%; opacity: 0; }
}
@keyframes door-in {
  from { transform: rotateY(calc(110deg * var(--dir, 1))); transform-origin: calc(50% + 50% * var(--dir, 1)) 50%; opacity: 0; }
  to   { transform: rotateY(0); opacity: 1; }
}
.t-door.exiting  { animation: door-out 0.5s ease-in  forwards; transform-origin: calc(50% - 50% * var(--dir, 1)) 50%; }
.t-door.entering { animation: door-in  0.5s ease-out forwards; animation-delay: 0.45s; transform-origin: calc(50% + 50% * var(--dir, 1)) 50%; }

@media (prefers-reduced-motion: reduce) {
  .slide.exiting, .slide.entering {
    animation: fade-out 0.2s linear forwards, fade-in 0.2s linear forwards !important;
  }
}
