:root {
  color-scheme: dark;
  font-family: "Trebuchet MS", "Segoe UI", sans-serif;
  color: #fff7ed;
  background: #0a0d1a;
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  --night: #0a0d1a;
  --violet: #39234f;
  --mauve: #90609b;
  --gold: #ffb64c;
  --cream: #fff0c9;
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  min-width: 280px;
  height: 100%;
  min-height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  background: var(--night);
}

button {
  font: inherit;
}

.experience {
  position: relative;
  width: 100%;
  height: 100%;
  height: 100svh;
  min-height: 420px;
  overflow: hidden;
  isolation: isolate;
}

.welcome {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: max(32px, env(safe-area-inset-top)) 28px max(32px, env(safe-area-inset-bottom));
  text-align: center;
  background:
    radial-gradient(ellipse at 50% 44%, rgb(112 74 141 / 45%), transparent 52%),
    linear-gradient(155deg, #291c49 0%, #21183c 55%, #17132d 100%);
}

.welcome__content {
  width: min(100%, 460px);
  transform: translateY(-2vh);
}

.eyebrow {
  margin: 0 0 14px;
  color: #d4b8df;
  font-size: clamp(0.75rem, 3vw, 1rem);
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

h1 {
  margin: 0;
  font-size: clamp(2.2rem, 10vw, 4rem);
  line-height: 1.03;
  letter-spacing: -0.055em;
}

h1 span {
  display: block;
  color: var(--gold);
}

.welcome__description {
  max-width: 28rem;
  margin: 26px auto 30px;
  color: #f0e5f4;
  font-size: clamp(1rem, 4.6vw, 1.4rem);
  line-height: 1.55;
}

.enter-button {
  min-width: 210px;
  min-height: 60px;
  padding: 14px 28px;
  border: 0;
  border-radius: 999px;
  color: #2c1b43;
  background: var(--gold);
  box-shadow: 0 8px 26px rgb(10 6 24 / 28%);
  cursor: pointer;
  font-size: 1.2rem;
  font-weight: 800;
  transition: background-color 160ms ease, transform 160ms ease;
}

.enter-button:hover {
  transform: translateY(-2px);
  background: #ffca70;
}

.enter-button:focus-visible {
  outline: 3px solid #fff7ed;
  outline-offset: 5px;
}

.welcome__note {
  margin: 18px 0 0;
  color: #d4b8df;
  font-size: 0.95rem;
}

.motion-note {
  max-width: 30rem;
  margin: 14px auto 0;
  color: var(--cream);
  font-size: 0.9rem;
  line-height: 1.4;
}

.motion-note[hidden] {
  display: none;
}

/* Scene: the 941x1672 layered art, scaled to fit with plain bands above/below. */
.scene {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--night);
}

.scene[hidden] {
  display: none;
}

/* Fixed art-sized canvas. app.js sets --stage-scale so the whole stage
   shrinks or grows as one unit and every layer stays registered. */
.stage {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 941px;
  height: 1672px;
  overflow: hidden;
  transform: translate(-50%, -50%) scale(var(--stage-scale, 1));
  transform-origin: center;
}

/* Each layer is a trimmed PNG placed by its manifest offset (inline style). */
.layer {
  position: absolute;
  display: block;
  max-width: none;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* Light overlays: soft radial glows added by app.js at hotspot positions.
   They are lit and still by default; motion only runs while the scene is
   playing and the device has not asked for reduced motion. */
.glow {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0.8;
}

.glow--window,
.glow--pumpkin,
.glow--lantern {
  background: radial-gradient(circle, rgb(255 196 96 / 85%) 0%, rgb(255 140 40 / 35%) 38%, transparent 70%);
}

.glow--pumpkin {
  background: radial-gradient(circle, rgb(255 160 50 / 85%) 0%, rgb(255 100 20 / 35%) 40%, transparent 70%);
}

.glow--moon {
  background: radial-gradient(circle, rgb(200 215 255 / 50%) 0%, rgb(150 170 235 / 22%) 45%, transparent 70%);
  opacity: 0.85;
}

.scene:not(.scene--reduced-motion) .glow--window,
.scene:not(.scene--reduced-motion) .glow--pumpkin,
.scene:not(.scene--reduced-motion) .glow--lantern {
  animation: flicker var(--glow-speed) steps(1, end) var(--glow-delay) infinite;
}

.scene:not(.scene--reduced-motion) .glow--moon {
  animation: moon-breathe 7s ease-in-out infinite;
}

/* Pausing freezes each glow on its current frame; Play resumes from there. */
.scene--paused .glow {
  animation-play-state: paused !important;
}

@keyframes flicker {
  0% { opacity: 0.8; }
  12% { opacity: 0.55; }
  18% { opacity: 0.95; }
  41% { opacity: 0.7; }
  47% { opacity: 1; }
  73% { opacity: 0.6; }
  80% { opacity: 0.9; }
}

@keyframes moon-breathe {
  0%, 100% { opacity: 0.6; transform: scale(0.96); }
  50% { opacity: 1; transform: scale(1.06); }
}

/* Fog: each band is a stage-wide window onto a 2x-wide strip whose blobs repeat
   every 941px, so sliding the strip by exactly one tile loops with no seam. */
.fog {
  position: absolute;
  left: 0;
  width: 941px;
  overflow: hidden;
  pointer-events: none;
}

.fog__drift {
  width: 1882px;
  height: 100%;
  background-repeat: repeat-x;
  background-size: 941px 100%;
  background-image:
    radial-gradient(ellipse 240px 42% at 18% 55%, rgb(190 205 235 / 55%), transparent 100%),
    radial-gradient(ellipse 300px 36% at 52% 42%, rgb(190 205 235 / 45%), transparent 100%),
    radial-gradient(ellipse 220px 46% at 84% 60%, rgb(190 205 235 / 50%), transparent 100%);
  filter: blur(14px);
}

.fog--hill { top: 250px; height: 220px; opacity: 0.55; }
.fog--town { top: 520px; height: 260px; opacity: 0.7; }
.fog--ground { top: 1200px; height: 300px; opacity: 0.6; }

.scene:not(.scene--reduced-motion) .fog__drift {
  animation: fog-drift 70s linear infinite;
}

.scene:not(.scene--reduced-motion) .fog--town .fog__drift {
  animation-duration: 50s;
}

.scene:not(.scene--reduced-motion) .fog--ground .fog__drift {
  animation-direction: reverse;
  animation-duration: 90s;
}

.scene--paused .fog__drift {
  animation-play-state: paused !important;
}

@keyframes fog-drift {
  to { transform: translateX(-941px); }
}

/* Branch sway: small rotations about the pivots in hotspots.json (branchPivots),
   written relative to each layer's own top-left offset. */
.layer--left-foreground-upper-branches {
  transform-origin: 34px 226px;
}

.layer--right-foreground-upper-branches {
  transform-origin: 402px 134px;
}

.scene:not(.scene--reduced-motion) .layer--left-foreground-upper-branches {
  animation: branch-sway 9s ease-in-out infinite alternate;
}

.scene:not(.scene--reduced-motion) .layer--right-foreground-upper-branches {
  animation: branch-sway 11s ease-in-out -4s infinite alternate-reverse;
}

@keyframes branch-sway {
  from { transform: rotate(-1.4deg); }
  to { transform: rotate(1.4deg); }
}

/* Shutters: the two halves of layer 10, clipped at its midpoint and swung about
   their hinge edges (shutterHinges in hotspots.json). They rest flat and open;
   a gust throws each outward, then it slams back against the wall. --swing
   flips the direction so both free edges come toward the viewer. */
.layer--shutter-left {
  clip-path: inset(0 53px 0 0);
  transform-origin: 27px 44px;
  --swing: 1;
}

.layer--shutter-right {
  clip-path: inset(0 0 0 53px);
  transform-origin: 75px 44px;
  --swing: -1;
}

.scene:not(.scene--reduced-motion) .layer--shutter-left {
  animation: shutter-bang 7s ease-in-out infinite;
}

.scene:not(.scene--reduced-motion) .layer--shutter-right {
  animation: shutter-bang 7s ease-in-out -2.3s infinite;
}

@keyframes shutter-bang {
  0%, 58% { transform: perspective(260px) rotateY(0deg); }
  66% { transform: perspective(260px) rotateY(calc(var(--swing) * 42deg)); }
  70% { transform: perspective(260px) rotateY(0deg); }
  73% { transform: perspective(260px) rotateY(calc(var(--swing) * 9deg)); }
  76%, 100% { transform: perspective(260px) rotateY(0deg); }
}

.scene--paused .layer--left-foreground-upper-branches,
.scene--paused .layer--right-foreground-upper-branches,
.scene--paused .layer--shutter-left,
.scene--paused .layer--shutter-right {
  animation-play-state: paused !important;
}

/* Story 1 ornaments: unlit until a tap adds .glow--lit, then they fade in. */
.glow--ornament {
  background: radial-gradient(circle, #fff 0%, var(--ornament-color) 28%, transparent 68%);
  opacity: 0;
  transition: opacity 400ms ease;
}

.glow--star {
  background: radial-gradient(circle, #fff 0%, rgb(255 226 120 / 85%) 30%, transparent 70%);
  opacity: 0;
  transition: opacity 400ms ease;
}

.glow--lit {
  opacity: 1;
}

/* The one tap target over the door. Transparent; the art shows through. */
.door-target {
  position: absolute;
  left: 399px;
  top: 924px;
  width: 207px;
  height: 323px;
  padding: 0;
  border: 0;
  border-radius: 100px 100px 12px 12px;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.door-target:focus-visible {
  outline: 6px solid var(--cream);
  outline-offset: 6px;
}

/* Snow gust: flakes burst from the doorway while a pale wash covers the stage.
   Both are created and removed by door-story.js for each reveal. */
.snow-wash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at 54% 65%, #fff 0%, #e4eeff 50%, #b9cbee 100%);
}

.snow-flake {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: #fff;
  box-shadow: 0 0 8px 2px rgb(255 255 255 / 70%);
}

/* Idle hint: a soft pulsing halo around the door. */
.door-target--hinting {
  box-shadow: 0 0 40px 12px rgb(255 226 150 / 55%);
}

.scene:not(.scene--reduced-motion) .door-target--hinting {
  animation: door-hint 2.4s ease-in-out infinite;
}

.scene--paused .door-target {
  animation-play-state: paused !important;
}

@keyframes door-hint {
  0%, 100% { box-shadow: 0 0 14px 2px rgb(255 226 150 / 15%); }
  50% { box-shadow: 0 0 46px 16px rgb(255 226 150 / 65%); }
}

.story-hint {
  position: absolute;
  z-index: 1;
  right: 16px;
  bottom: max(72px, calc(env(safe-area-inset-bottom) + 56px));
  left: 16px;
  width: fit-content;
  max-width: min(32rem, calc(100% - 32px));
  margin: 0 auto;
  padding: 10px 14px;
  border-radius: 12px;
  color: #fff7ed;
  background: rgb(10 13 26 / 82%);
  font-size: 0.9rem;
  line-height: 1.4;
  text-align: center;
  pointer-events: none;
}

.story-hint:empty {
  display: none;
}

/* Story 3: the sleigh silhouette and its screen effects. Everything here is
   invisible at rest; moon-story.js animates it and removes the temporary bits. */
.sleigh {
  position: absolute;
  top: 0;
  left: 0;
  width: 364px;
  height: 80px;
  max-width: none;
  opacity: 0;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

.sparkle,
.sparkle-dust {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  border-radius: 50%;
}

/* Gold glitter shed behind the sleigh. */
.sparkle-dust {
  background: radial-gradient(circle, #fff6c8 0%, #ffcf5a 45%, transparent 75%);
}

/* A four-point glint for the star twinkle wave. */
.sparkle {
  width: 34px;
  height: 34px;
  background:
    linear-gradient(90deg, transparent 0%, #fff 50%, transparent 100%) center / 100% 3px no-repeat,
    linear-gradient(0deg, transparent 0%, #fff 50%, transparent 100%) center / 3px 100% no-repeat,
    radial-gradient(circle, #fff 0%, rgb(255 255 255 / 0%) 55%);
}

/* A soft dark vignette that dims the edges so the moon and sleigh stand out. */
.night-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at 29% 13%, transparent 12%, rgb(4 6 22 / 62%) 75%);
}

/* Tap target: a circle over the moon (hotspots.json moon: x 277, y 214, r 164). */
.moon-target {
  position: absolute;
  left: 113px;
  top: 50px;
  width: 328px;
  height: 328px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.moon-target:focus-visible {
  outline: 6px solid var(--cream);
  outline-offset: 6px;
}

.moon-target--hinting {
  box-shadow: 0 0 60px 18px rgb(255 240 190 / 40%);
}

.scene:not(.scene--reduced-motion) .moon-target--hinting {
  animation: door-hint 2.4s ease-in-out infinite;
}

.scene--paused .moon-target,
.scene--paused .clock-target {
  animation-play-state: paused !important;
}

/* Story 2: tap target over the tower clock, and the close-up scene it opens. */
.clock-target {
  position: absolute;
  /* Centered on the clock (556, 449); 136 art px is 44+ css px at 320-wide phones. */
  left: 488px;
  top: 381px;
  width: 136px;
  height: 136px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.clock-target:focus-visible {
  outline: 6px solid var(--cream);
  outline-offset: 4px;
}

.clock-target--hinting {
  box-shadow: 0 0 36px 10px rgb(255 226 150 / 55%);
}

.scene:not(.scene--reduced-motion) .clock-target--hinting {
  animation: door-hint 2.4s ease-in-out infinite;
}

.closeup {
  position: absolute;
  top: 0;
  left: 0;
  width: 941px;
  height: 1672px;
  overflow: hidden;
}

.closeup[hidden] {
  display: none;
}

.closeup__scene {
  position: absolute;
  top: 0;
  left: 0;
  width: 941px;
  height: 1672px;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* Drag surface: the clock face, centered on the hands' pivot (480, 866). */
.closeup__face {
  position: absolute;
  top: 495px;
  left: 109px;
  width: 742px;
  height: 742px;
  border-radius: 50%;
  cursor: grab;
  touch-action: none;
}

.closeup__face:active {
  cursor: grabbing;
}

/* Each hand sits with its hub on the face center and turns about it. */
.closeup__hand {
  position: absolute;
  pointer-events: none;
  filter: drop-shadow(0 5px 6px rgb(0 0 0 / 55%));
}

.closeup__hand img {
  display: block;
}

/* Sizes and pivots come from assets/story2/clock-hands.json (hub = face center). */
.closeup__hand--hour {
  top: 661.3px;
  left: 447.7px;
  width: 66px;
  height: 241px;
  transform-origin: 32.3px 204.7px;
}

.closeup__hand--minute {
  top: 554.9px;
  left: 447.7px;
  width: 65px;
  height: 343px;
  transform-origin: 32.3px 311.1px;
}

/* A glow instead of a box outline, which would swing around with the hand. */
.closeup__hand--minute:focus-visible {
  outline: none;
  filter: drop-shadow(0 0 12px var(--cream)) drop-shadow(0 0 4px var(--cream)) drop-shadow(0 5px 6px rgb(0 0 0 / 55%));
}

.closeup__hand--hinting {
  filter: drop-shadow(0 0 14px rgb(255 226 150 / 90%)) drop-shadow(0 5px 6px rgb(0 0 0 / 55%));
}

.scene-controls {
  display: flex;
  gap: 8px;
  position: absolute;
  z-index: 1;
  top: max(16px, env(safe-area-inset-top));
  right: max(16px, env(safe-area-inset-right));
}

.pause-control {
  min-width: 52px;
  min-height: 48px;
  padding: 10px 16px;
  border: 1px solid rgb(255 240 201 / 45%);
  border-radius: 999px;
  color: #fff7ed;
  background: rgb(10 13 26 / 88%);
  box-shadow: 0 3px 14px rgb(0 0 0 / 28%);
  cursor: pointer;
  font-size: 0.95rem;
  font-weight: 700;
}

.pause-control:hover {
  background: #39234f;
}

.pause-control:focus-visible {
  outline: 3px solid var(--cream);
  outline-offset: 3px;
}

.experience-status {
  position: absolute;
  z-index: 1;
  right: 16px;
  bottom: max(16px, env(safe-area-inset-bottom));
  left: 16px;
  width: fit-content;
  max-width: min(32rem, calc(100% - 32px));
  margin: 0 auto;
  padding: 10px 14px;
  border-radius: 12px;
  color: #fff7ed;
  background: rgb(10 13 26 / 92%);
  font-size: 0.875rem;
  line-height: 1.4;
  text-align: center;
}

.experience-status:empty {
  display: none;
}

@media (max-height: 560px) {
  .welcome__content {
    transform: none;
  }

  .welcome__description {
    margin: 14px auto 16px;
  }

  .enter-button {
    min-height: 52px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}
