:root {
  /* Dawn sky behind the card: dusky at the zenith, warming to the horizon */
  --sky-deep: #3f4a73;
  --sky-mid: #77719b;
  --sky-warm: #b98a97;
  --sky-low: #f7d8bc;

  /* Soft pastel neutral, hint of pink — the card itself */
  --paper: #fbf6f1;
  --paper-shadow: #e6d9cc;
  --ink: #4a3a3a;
  --ink-soft: #7a6a68;
  --blush: #e8b8b3;
  --blush-deep: #c98c88;
  --gold: #b89773;
  --line: #d9c7bc;

  /* Space kept free around the card: side gutters + room for the hint line */
  --gutter: 20px;
  --reserve: 104px;

  /* svh where available, so the mobile URL bar doesn't clip the card */
  --vh: 1vh;

  /* How large the open spread is allowed to grow on a big screen. Everything
     (type, padding, ornaments) scales with it — tune this one value. */
  --card-max: 1400px;

  /* Book sizing — fluid: fills the viewport up to --card-max, and never
     exceeds it, so nothing is ever cut off. */
  --card-w: min(
    var(--card-max),
    100vw - 2 * var(--gutter),
    (var(--vh) * 100 - var(--reserve)) * 1.4615
  );
  --card-h: calc(var(--card-w) / 1.4615);
  --page-w: calc(var(--card-w) / 2);
  --page-h: var(--card-h);

  /* One "design pixel": equals 1px at the 380px design page width and shrinks
     with the page. Sizes are written as calc(<design px> * var(--u)). */
  --u: calc(var(--page-w) / 380);

  --ease: cubic-bezier(0.7, 0.05, 0.25, 1);
}

@supports (height: 1svh) {
  :root {
    --vh: 1svh;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  font-family: "Inter", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  /* Matches the sky, so the first paint never flashes light */
  background: var(--sky-deep);
  height: 100%;
  /* The card is always sized to fit, so the page never needs to scroll —
     no scrollbar, and no empty space to scroll into. Wheel and swipe are
     handled in JS instead (see scripts/main.js). */
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  background: linear-gradient(178deg, var(--sky-deep) 0%, var(--sky-low) 100%);
  min-height: calc(var(--vh) * 100);
}

.scene {
  position: relative;
  min-height: calc(var(--vh) * 100);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--gutter);
  perspective: 2400px;
  perspective-origin: 50% 45%;
}

/* ----- The night sky -----

   Everything here is gradients, so it resamples cleanly at any resolution:
   nothing to download, and nothing to pixelate on a large screen. Three star
   layers pulse out of phase (baked into background-images, so ~165 stars cost
   three composited layers rather than 165 DOM nodes), a milky band drifts, and
   a shooting star crosses every so often. */

.scene__ambient {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  background:
    /* the sun, still below the horizon */
    radial-gradient(70% 42% at 38% 104%, rgba(255, 216, 168, 0.75) 0%, transparent 64%),
    /* its light spilling upward */
    radial-gradient(120% 70% at 44% 96%, rgba(246, 190, 165, 0.45) 0%, transparent 62%),
    linear-gradient(
      178deg,
      var(--sky-deep) 0%,
      var(--sky-mid) 30%,
      var(--sky-warm) 58%,
      #e2a58d 80%,
      var(--sky-low) 100%
    );
}

/* A high cloud wisp, drifting slowly across the sky */
.sky__band {
  position: absolute;
  inset: -20%;
  z-index: 1;
  background:
    linear-gradient(
      74deg,
      transparent 30%,
      rgba(255, 226, 214, 0.16) 42%,
      rgba(255, 240, 232, 0.24) 50%,
      rgba(255, 214, 198, 0.14) 58%,
      transparent 70%
    );
  filter: blur(34px);
  will-change: transform;
  animation: band-drift 90s ease-in-out infinite alternate;
}

@keyframes band-drift {
  from {
    transform: translate3d(-1.5%, 1%, 0) rotate(-0.6deg);
  }
  to {
    transform: translate3d(1.5%, -1%, 0) rotate(0.6deg);
  }
}

/* ----- Stars -----
   One layer on the element, two more on its pseudo-elements, each pulsing on
   its own clock so the field shimmers instead of blinking in unison. */

.sky__stars {
  position: absolute;
  inset: 0;
  z-index: 2;
  /* Dawn washes the stars out from the horizon up */
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.92) 28%,
    rgba(0, 0, 0, 0.45) 52%,
    transparent 72%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.92) 28%,
    rgba(0, 0, 0, 0.45) 52%,
    transparent 72%
  );
}

.sky__stars::before,
.sky__stars::after {
  content: "";
  position: absolute;
  inset: 0;
}

.sky__stars {
  background:
    radial-gradient(1.06px 1.06px at 23.80% 37.00%, rgba(255, 253, 247, 0.70) 0%, transparent 100%),
    radial-gradient(0.84px 0.84px at 6.55% 86.12%, rgba(255, 253, 247, 0.85) 0%, transparent 100%),
    radial-gradient(1.08px 1.08px at 47.03% 47.64%, rgba(255, 253, 247, 0.51) 0%, transparent 100%),
    radial-gradient(1.14px 1.14px at 63.49% 52.32%, rgba(255, 253, 247, 0.72) 0%, transparent 100%),
    radial-gradient(0.88px 0.88px at 6.40% 59.11%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(1.23px 1.23px at 86.55% 71.88%, rgba(255, 253, 247, 0.74) 0%, transparent 100%),
    radial-gradient(1.18px 1.18px at 92.11% 17.06%, rgba(255, 253, 247, 0.63) 0%, transparent 100%),
    radial-gradient(0.78px 0.78px at 93.56% 9.75%, rgba(255, 253, 247, 0.54) 0%, transparent 100%),
    radial-gradient(1.00px 1.00px at 96.55% 14.34%, rgba(255, 253, 247, 0.60) 0%, transparent 100%),
    radial-gradient(1.24px 1.24px at 35.09% 58.43%, rgba(255, 253, 247, 0.72) 0%, transparent 100%),
    radial-gradient(1.10px 1.10px at 92.89% 99.10%, rgba(255, 253, 247, 0.52) 0%, transparent 100%),
    radial-gradient(1.04px 1.04px at 86.06% 90.47%, rgba(255, 253, 247, 0.74) 0%, transparent 100%),
    radial-gradient(0.87px 0.87px at 21.11% 57.35%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.18px 1.18px at 85.39% 8.85%, rgba(255, 253, 247, 0.61) 0%, transparent 100%),
    radial-gradient(1.16px 1.16px at 15.08% 72.91%, rgba(255, 253, 247, 0.80) 0%, transparent 100%),
    radial-gradient(1.13px 1.13px at 4.42% 4.49%, rgba(255, 253, 247, 0.58) 0%, transparent 100%),
    radial-gradient(1.30px 1.30px at 88.09% 50.54%, rgba(255, 253, 247, 0.57) 0%, transparent 100%),
    radial-gradient(0.82px 0.82px at 7.70% 3.14%, rgba(255, 253, 247, 0.61) 0%, transparent 100%),
    radial-gradient(0.89px 0.89px at 61.05% 57.63%, rgba(255, 253, 247, 0.83) 0%, transparent 100%),
    radial-gradient(0.98px 0.98px at 89.67% 27.15%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(1.07px 1.07px at 64.39% 55.93%, rgba(255, 253, 247, 0.83) 0%, transparent 100%),
    radial-gradient(0.88px 0.88px at 50.70% 50.54%, rgba(255, 253, 247, 0.84) 0%, transparent 100%),
    radial-gradient(0.95px 0.95px at 52.11% 1.15%, rgba(255, 253, 247, 0.68) 0%, transparent 100%),
    radial-gradient(0.74px 0.74px at 2.01% 63.22%, rgba(255, 253, 247, 0.70) 0%, transparent 100%),
    radial-gradient(1.12px 1.12px at 46.63% 35.26%, rgba(255, 253, 247, 0.75) 0%, transparent 100%),
    radial-gradient(1.11px 1.11px at 2.22% 81.34%, rgba(255, 253, 247, 0.84) 0%, transparent 100%),
    radial-gradient(0.89px 0.89px at 25.11% 59.27%, rgba(255, 253, 247, 0.60) 0%, transparent 100%),
    radial-gradient(0.93px 0.93px at 31.27% 60.61%, rgba(255, 253, 247, 0.76) 0%, transparent 100%),
    radial-gradient(0.89px 0.89px at 2.69% 73.52%, rgba(255, 253, 247, 0.54) 0%, transparent 100%),
    radial-gradient(0.81px 0.81px at 80.38% 26.78%, rgba(255, 253, 247, 0.62) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 69.81% 34.98%, rgba(255, 253, 247, 0.63) 0%, transparent 100%),
    radial-gradient(0.90px 0.90px at 85.55% 32.08%, rgba(255, 253, 247, 0.71) 0%, transparent 100%),
    radial-gradient(0.77px 0.77px at 88.49% 22.50%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(0.81px 0.81px at 19.08% 83.85%, rgba(255, 253, 247, 0.56) 0%, transparent 100%),
    radial-gradient(0.91px 0.91px at 80.72% 80.63%, rgba(255, 253, 247, 0.50) 0%, transparent 100%),
    radial-gradient(0.91px 0.91px at 29.19% 27.12%, rgba(255, 253, 247, 0.62) 0%, transparent 100%),
    radial-gradient(0.70px 0.70px at 41.98% 61.36%, rgba(255, 253, 247, 0.83) 0%, transparent 100%),
    radial-gradient(1.27px 1.27px at 88.00% 43.44%, rgba(255, 253, 247, 0.82) 0%, transparent 100%),
    radial-gradient(1.10px 1.10px at 22.21% 83.67%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(0.84px 0.84px at 28.90% 65.24%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.24px 1.24px at 58.87% 46.40%, rgba(255, 253, 247, 0.73) 0%, transparent 100%),
    radial-gradient(1.05px 1.05px at 92.39% 89.97%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(0.88px 0.88px at 74.53% 32.36%, rgba(255, 253, 247, 0.72) 0%, transparent 100%),
    radial-gradient(0.90px 0.90px at 52.50% 59.14%, rgba(255, 253, 247, 0.55) 0%, transparent 100%),
    radial-gradient(0.91px 0.91px at 86.17% 78.23%, rgba(255, 253, 247, 0.53) 0%, transparent 100%),
    radial-gradient(1.18px 1.18px at 53.46% 17.13%, rgba(255, 253, 247, 0.82) 0%, transparent 100%),
    radial-gradient(1.08px 1.08px at 80.61% 0.75%, rgba(255, 253, 247, 0.80) 0%, transparent 100%),
    radial-gradient(0.86px 0.86px at 4.99% 80.80%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(0.70px 0.70px at 42.30% 77.65%, rgba(255, 253, 247, 0.47) 0%, transparent 100%),
    radial-gradient(1.21px 1.21px at 12.69% 96.12%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(0.89px 0.89px at 50.21% 59.76%, rgba(255, 253, 247, 0.59) 0%, transparent 100%),
    radial-gradient(0.81px 0.81px at 64.69% 36.08%, rgba(255, 253, 247, 0.58) 0%, transparent 100%),
    radial-gradient(0.93px 0.93px at 12.38% 71.60%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(0.93px 0.93px at 17.86% 65.45%, rgba(255, 253, 247, 0.77) 0%, transparent 100%),
    radial-gradient(0.92px 0.92px at 62.29% 35.69%, rgba(255, 253, 247, 0.65) 0%, transparent 100%),
    radial-gradient(0.85px 0.85px at 70.29% 34.72%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(0.95px 0.95px at 69.52% 30.64%, rgba(255, 253, 247, 0.62) 0%, transparent 100%),
    radial-gradient(1.24px 1.24px at 87.97% 37.42%, rgba(255, 253, 247, 0.77) 0%, transparent 100%),
    radial-gradient(1.19px 1.19px at 26.22% 12.31%, rgba(255, 253, 247, 0.71) 0%, transparent 100%),
    radial-gradient(1.14px 1.14px at 88.73% 66.76%, rgba(255, 253, 247, 0.68) 0%, transparent 100%),
    radial-gradient(0.79px 0.79px at 10.31% 0.49%, rgba(255, 253, 247, 0.76) 0%, transparent 100%),
    radial-gradient(0.81px 0.81px at 4.43% 96.52%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(1.21px 1.21px at 84.15% 35.84%, rgba(255, 253, 247, 0.72) 0%, transparent 100%),
    radial-gradient(1.18px 1.18px at 83.62% 57.91%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(0.76px 0.76px at 76.74% 71.52%, rgba(255, 253, 247, 0.75) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 93.46% 16.65%, rgba(255, 253, 247, 0.55) 0%, transparent 100%),
    radial-gradient(1.07px 1.07px at 17.98% 83.11%, rgba(255, 253, 247, 0.75) 0%, transparent 100%),
    radial-gradient(0.95px 0.95px at 39.37% 54.47%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.15px 1.15px at 50.03% 41.28%, rgba(255, 253, 247, 0.51) 0%, transparent 100%),
    radial-gradient(1.01px 1.01px at 69.08% 67.39%, rgba(255, 253, 247, 0.64) 0%, transparent 100%);
  animation: twinkle-a 7s ease-in-out infinite alternate;
}

.sky__stars::before {
  background:
    radial-gradient(1.13px 1.13px at 52.20% 96.05%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(0.92px 0.92px at 70.42% 11.02%, rgba(255, 253, 247, 0.50) 0%, transparent 100%),
    radial-gradient(1.58px 1.58px at 74.64% 28.14%, rgba(255, 253, 247, 0.73) 0%, transparent 100%),
    radial-gradient(1.55px 1.55px at 40.16% 6.22%, rgba(255, 253, 247, 0.70) 0%, transparent 100%),
    radial-gradient(1.66px 1.66px at 15.09% 55.89%, rgba(255, 253, 247, 0.43) 0%, transparent 100%),
    radial-gradient(1.15px 1.15px at 54.00% 63.88%, rgba(255, 253, 247, 0.38) 0%, transparent 100%),
    radial-gradient(1.01px 1.01px at 93.98% 99.63%, rgba(255, 253, 247, 0.67) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 81.34% 1.78%, rgba(255, 253, 247, 0.37) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 75.20% 95.95%, rgba(255, 253, 247, 0.66) 0%, transparent 100%),
    radial-gradient(1.35px 1.35px at 86.78% 25.46%, rgba(255, 253, 247, 0.73) 0%, transparent 100%),
    radial-gradient(1.53px 1.53px at 52.69% 26.72%, rgba(255, 253, 247, 0.43) 0%, transparent 100%),
    radial-gradient(1.00px 1.00px at 60.39% 55.35%, rgba(255, 253, 247, 0.61) 0%, transparent 100%),
    radial-gradient(1.36px 1.36px at 91.65% 14.45%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(1.27px 1.27px at 0.98% 34.80%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(0.96px 0.96px at 63.31% 30.98%, rgba(255, 253, 247, 0.74) 0%, transparent 100%),
    radial-gradient(1.35px 1.35px at 91.00% 35.81%, rgba(255, 253, 247, 0.62) 0%, transparent 100%),
    radial-gradient(1.37px 1.37px at 40.30% 95.98%, rgba(255, 253, 247, 0.51) 0%, transparent 100%),
    radial-gradient(1.07px 1.07px at 19.56% 75.89%, rgba(255, 253, 247, 0.69) 0%, transparent 100%),
    radial-gradient(1.55px 1.55px at 53.70% 92.02%, rgba(255, 253, 247, 0.37) 0%, transparent 100%),
    radial-gradient(1.52px 1.52px at 92.60% 24.08%, rgba(255, 253, 247, 0.69) 0%, transparent 100%),
    radial-gradient(0.97px 0.97px at 65.75% 7.50%, rgba(255, 253, 247, 0.60) 0%, transparent 100%),
    radial-gradient(1.03px 1.03px at 24.17% 26.52%, rgba(255, 253, 247, 0.47) 0%, transparent 100%),
    radial-gradient(1.29px 1.29px at 72.49% 39.28%, rgba(255, 253, 247, 0.57) 0%, transparent 100%),
    radial-gradient(1.50px 1.50px at 51.57% 96.74%, rgba(255, 253, 247, 0.44) 0%, transparent 100%),
    radial-gradient(1.50px 1.50px at 31.82% 63.98%, rgba(255, 253, 247, 0.58) 0%, transparent 100%),
    radial-gradient(1.36px 1.36px at 42.27% 32.87%, rgba(255, 253, 247, 0.72) 0%, transparent 100%),
    radial-gradient(1.70px 1.70px at 55.59% 36.80%, rgba(255, 253, 247, 0.65) 0%, transparent 100%),
    radial-gradient(1.31px 1.31px at 30.33% 59.15%, rgba(255, 253, 247, 0.56) 0%, transparent 100%),
    radial-gradient(1.51px 1.51px at 19.21% 70.39%, rgba(255, 253, 247, 0.53) 0%, transparent 100%),
    radial-gradient(1.28px 1.28px at 44.56% 53.63%, rgba(255, 253, 247, 0.35) 0%, transparent 100%),
    radial-gradient(1.27px 1.27px at 26.34% 82.63%, rgba(255, 253, 247, 0.65) 0%, transparent 100%),
    radial-gradient(1.31px 1.31px at 21.12% 74.06%, rgba(255, 253, 247, 0.63) 0%, transparent 100%),
    radial-gradient(1.39px 1.39px at 2.76% 90.61%, rgba(255, 253, 247, 0.75) 0%, transparent 100%),
    radial-gradient(0.92px 0.92px at 9.87% 83.74%, rgba(255, 253, 247, 0.56) 0%, transparent 100%),
    radial-gradient(1.54px 1.54px at 75.93% 25.26%, rgba(255, 253, 247, 0.52) 0%, transparent 100%),
    radial-gradient(1.33px 1.33px at 5.83% 18.81%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(1.68px 1.68px at 34.73% 81.96%, rgba(255, 253, 247, 0.51) 0%, transparent 100%),
    radial-gradient(1.51px 1.51px at 0.75% 33.93%, rgba(255, 253, 247, 0.68) 0%, transparent 100%),
    radial-gradient(1.16px 1.16px at 3.35% 28.48%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.30px 1.30px at 53.84% 38.23%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(1.06px 1.06px at 12.46% 76.49%, rgba(255, 253, 247, 0.50) 0%, transparent 100%),
    radial-gradient(1.02px 1.02px at 21.36% 78.72%, rgba(255, 253, 247, 0.47) 0%, transparent 100%),
    radial-gradient(1.32px 1.32px at 43.59% 38.84%, rgba(255, 253, 247, 0.65) 0%, transparent 100%),
    radial-gradient(1.33px 1.33px at 15.41% 16.45%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.23px 1.23px at 80.32% 95.67%, rgba(255, 253, 247, 0.60) 0%, transparent 100%),
    radial-gradient(1.24px 1.24px at 16.86% 77.80%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.13px 1.13px at 75.81% 79.93%, rgba(255, 253, 247, 0.45) 0%, transparent 100%),
    radial-gradient(0.91px 0.91px at 25.06% 64.48%, rgba(255, 253, 247, 0.40) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 49.27% 88.97%, rgba(255, 253, 247, 0.42) 0%, transparent 100%),
    radial-gradient(1.16px 1.16px at 93.09% 14.62%, rgba(255, 253, 247, 0.74) 0%, transparent 100%),
    radial-gradient(1.59px 1.59px at 74.35% 44.52%, rgba(255, 253, 247, 0.72) 0%, transparent 100%),
    radial-gradient(1.61px 1.61px at 51.40% 61.25%, rgba(255, 253, 247, 0.61) 0%, transparent 100%),
    radial-gradient(1.07px 1.07px at 77.39% 23.71%, rgba(255, 253, 247, 0.70) 0%, transparent 100%),
    radial-gradient(0.96px 0.96px at 83.92% 27.02%, rgba(255, 253, 247, 0.51) 0%, transparent 100%),
    radial-gradient(1.15px 1.15px at 90.90% 30.41%, rgba(255, 253, 247, 0.36) 0%, transparent 100%);
  animation: twinkle-b 11s ease-in-out infinite alternate;
}

.sky__stars::after {
  background:
    radial-gradient(1.39px 1.39px at 54.81% 84.49%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 34.38% 97.39%, rgba(255, 253, 247, 0.46) 0%, transparent 100%),
    radial-gradient(1.43px 1.43px at 22.48% 99.87%, rgba(255, 253, 247, 0.51) 0%, transparent 100%),
    radial-gradient(1.27px 1.27px at 41.96% 44.72%, rgba(255, 253, 247, 0.45) 0%, transparent 100%),
    radial-gradient(1.30px 1.30px at 40.81% 56.26%, rgba(255, 253, 247, 0.54) 0%, transparent 100%),
    radial-gradient(1.51px 1.51px at 29.84% 21.99%, rgba(255, 253, 247, 0.58) 0%, transparent 100%),
    radial-gradient(1.69px 1.69px at 51.57% 75.67%, rgba(255, 253, 247, 0.53) 0%, transparent 100%),
    radial-gradient(1.20px 1.20px at 39.73% 77.72%, rgba(255, 253, 247, 0.63) 0%, transparent 100%),
    radial-gradient(1.17px 1.17px at 36.72% 65.31%, rgba(255, 253, 247, 0.44) 0%, transparent 100%),
    radial-gradient(2.04px 2.04px at 41.51% 46.66%, rgba(255, 253, 247, 0.53) 0%, transparent 100%),
    radial-gradient(2.07px 2.07px at 32.10% 69.91%, rgba(255, 253, 247, 0.56) 0%, transparent 100%),
    radial-gradient(1.38px 1.38px at 96.56% 23.64%, rgba(255, 253, 247, 0.64) 0%, transparent 100%),
    radial-gradient(1.24px 1.24px at 2.19% 91.04%, rgba(255, 253, 247, 0.35) 0%, transparent 100%),
    radial-gradient(1.82px 1.82px at 91.59% 86.97%, rgba(255, 253, 247, 0.57) 0%, transparent 100%),
    radial-gradient(2.05px 2.05px at 30.79% 55.78%, rgba(255, 253, 247, 0.48) 0%, transparent 100%),
    radial-gradient(1.55px 1.55px at 0.84% 76.98%, rgba(255, 253, 247, 0.38) 0%, transparent 100%),
    radial-gradient(1.21px 1.21px at 2.77% 82.36%, rgba(255, 253, 247, 0.36) 0%, transparent 100%),
    radial-gradient(1.30px 1.30px at 3.37% 86.56%, rgba(255, 253, 247, 0.52) 0%, transparent 100%),
    radial-gradient(1.43px 1.43px at 87.63% 24.91%, rgba(255, 253, 247, 0.61) 0%, transparent 100%),
    radial-gradient(1.67px 1.67px at 76.19% 79.39%, rgba(255, 253, 247, 0.41) 0%, transparent 100%),
    radial-gradient(1.42px 1.42px at 68.52% 5.55%, rgba(255, 253, 247, 0.40) 0%, transparent 100%),
    radial-gradient(1.48px 1.48px at 88.64% 20.73%, rgba(255, 253, 247, 0.47) 0%, transparent 100%),
    radial-gradient(1.25px 1.25px at 89.50% 38.94%, rgba(255, 253, 247, 0.42) 0%, transparent 100%),
    radial-gradient(1.42px 1.42px at 47.09% 99.85%, rgba(255, 253, 247, 0.63) 0%, transparent 100%),
    radial-gradient(1.33px 1.33px at 91.08% 22.22%, rgba(255, 253, 247, 0.62) 0%, transparent 100%),
    radial-gradient(1.27px 1.27px at 17.36% 65.24%, rgba(255, 253, 247, 0.31) 0%, transparent 100%),
    radial-gradient(1.65px 1.65px at 63.83% 35.41%, rgba(255, 253, 247, 0.64) 0%, transparent 100%),
    radial-gradient(1.40px 1.40px at 46.37% 10.62%, rgba(255, 253, 247, 0.41) 0%, transparent 100%),
    radial-gradient(1.82px 1.82px at 11.71% 60.23%, rgba(255, 253, 247, 0.34) 0%, transparent 100%),
    radial-gradient(1.47px 1.47px at 25.04% 0.88%, rgba(255, 253, 247, 0.59) 0%, transparent 100%),
    radial-gradient(1.44px 1.44px at 22.88% 68.06%, rgba(255, 253, 247, 0.44) 0%, transparent 100%),
    radial-gradient(1.86px 1.86px at 29.87% 73.46%, rgba(255, 253, 247, 0.64) 0%, transparent 100%),
    radial-gradient(2.09px 2.09px at 7.28% 78.71%, rgba(255, 253, 247, 0.58) 0%, transparent 100%),
    radial-gradient(1.99px 1.99px at 76.04% 37.14%, rgba(255, 253, 247, 0.56) 0%, transparent 100%),
    radial-gradient(1.39px 1.39px at 36.70% 73.52%, rgba(255, 253, 247, 0.34) 0%, transparent 100%),
    radial-gradient(1.84px 1.84px at 81.11% 80.72%, rgba(255, 253, 247, 0.43) 0%, transparent 100%),
    radial-gradient(1.22px 1.22px at 65.44% 90.35%, rgba(255, 253, 247, 0.54) 0%, transparent 100%),
    radial-gradient(1.27px 1.27px at 34.64% 80.38%, rgba(255, 253, 247, 0.31) 0%, transparent 100%),
    radial-gradient(1.81px 1.81px at 23.38% 76.84%, rgba(255, 253, 247, 0.37) 0%, transparent 100%),
    radial-gradient(1.72px 1.72px at 21.23% 53.27%, rgba(255, 253, 247, 0.32) 0%, transparent 100%);
  animation: twinkle-c 16s ease-in-out infinite alternate;
}

@keyframes twinkle-a {
  from {
    opacity: 0.78;
  }
  to {
    opacity: 1;
  }
}

@keyframes twinkle-b {
  from {
    opacity: 1;
  }
  to {
    opacity: 0.72;
  }
}

@keyframes twinkle-c {
  from {
    opacity: 0.88;
  }
  to {
    opacity: 1;
  }
}

/* ----- Bright stars -----
   A handful of larger stars with a real glow, placed and timed in JS so they
   never fall into a pattern. */

.sky__bright {
  position: absolute;
  inset: 0;
  z-index: 3;
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.8) 26%,
    rgba(0, 0, 0, 0.3) 46%,
    transparent 62%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.8) 26%,
    rgba(0, 0, 0, 0.3) 46%,
    transparent 62%
  );
}

.sky__bright span {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 253, 1) 0%,
    rgba(226, 226, 255, 0.6) 45%,
    transparent 72%
  );
  box-shadow: 0 0 calc(var(--size) * 3.4) rgba(226, 232, 255, 0.9);
  opacity: var(--op);
  will-change: opacity, transform;
  animation: star-pulse var(--dur) ease-in-out var(--delay) infinite alternate;
}

@keyframes star-pulse {
  from {
    opacity: calc(var(--op) * 0.35);
    transform: scale(0.85);
  }
  to {
    opacity: var(--op);
    transform: scale(1.15);
  }
}

/* ----- Shooting star -----
   Idle by default. Position, angle, length, speed and the gap between
   appearances are all rolled fresh each time in scripts/main.js, so it never
   repeats the same streak. */

.sky__shooting {
  position: absolute;
  top: 10%;
  left: -10%;
  z-index: 4;
  width: 180px;
  height: 1.5px;
  border-radius: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 250, 240, 0.85) 82%,
    rgba(255, 255, 255, 1) 100%
  );
  filter: blur(0.4px);
  opacity: 0;
  will-change: transform, opacity;
}

/* ----- Stage: the card plus its shadow on the table -----

   preserve-3d is required here, otherwise this wrapper would flatten the
   cover's flip. The two shadows are pseudo-elements pushed behind the card
   in Z: a tight contact shadow and a wide ambient one. Closed, only half the
   spread is on the table, so both are scaled to the cover; they grow to the
   full spread as it opens, in step with the flip. */

.stage {
  position: relative;
  flex: 0 0 auto;
  width: var(--card-w);
  height: var(--card-h);
  transform-style: preserve-3d;
}

.stage::before,
.stage::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: calc(8 * var(--u));
  background: rgba(74, 52, 74, 1);
  transform-origin: center;
  transition:
    transform 1.3s var(--ease),
    opacity 1.3s var(--ease);
}

/* Close shadow: lifts the card off a sky that is nearly as pale as it is */
.stage::before {
  filter: blur(calc(12 * var(--u)));
  opacity: 0.26;
  transform: translate3d(calc(3 * var(--u)), calc(8 * var(--u)), -2px) scaleX(0.5);
}

/* Wide, soft cast below, thrown by the low sun */
.stage::after {
  filter: blur(calc(46 * var(--u)));
  opacity: 0.2;
  transform: translate3d(calc(8 * var(--u)), calc(26 * var(--u)), -1px) scaleX(0.5);
}

/* Opening doubles the surface, so the shadow spreads and lightens with it */
.stage.is-open::before {
  opacity: 0.22;
  transform: translate3d(calc(3 * var(--u)), calc(8 * var(--u)), -2px) scaleX(1);
}

.stage.is-open::after {
  opacity: 0.16;
  transform: translate3d(calc(7 * var(--u)), calc(22 * var(--u)), -1px) scaleX(1);
}

/* ----- Card ----- */

.card {
  position: relative;
  width: var(--card-w);
  height: var(--card-h);
  transform-style: preserve-3d;
  transform: translateX(calc(var(--page-w) / -2));
  transition: transform 1.1s var(--ease);

  /* reset button styles */
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
  outline: none;
}

.card:focus-visible {
  box-shadow: 0 0 0 3px rgba(201, 140, 136, 0.35);
  border-radius: 8px;
}

.card.is-open {
  transform: translateX(0);
}

/* ----- Inside right page ----- */

.page {
  position: absolute;
  top: 0;
  width: var(--page-w);
  height: 100%;
  background: var(--paper);
  border-radius: 2px 8px 8px 2px;
  box-shadow:
    inset 8px 0 16px -12px rgba(74, 58, 58, 0.25),
    0 30px 60px -30px rgba(74, 58, 58, 0.35);
  overflow: hidden;
}

.page--right {
  left: var(--page-w);
}

/* Subtle paper texture on the interior */
.page::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 100% 0%, rgba(232, 184, 179, 0.14), transparent 55%),
    radial-gradient(140% 100% at 0% 100%, rgba(184, 151, 115, 0.06), transparent 60%);
}

.page__inner {
  position: relative;
  height: 100%;
  padding: calc(44 * var(--u)) calc(36 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* ----- Cover (right half, flips on left edge) ----- */

.card__cover {
  position: absolute;
  top: 0;
  left: var(--page-w);
  width: var(--page-w);
  height: 100%;
  transform-origin: left center;
  transform-style: preserve-3d;
  transition: transform 1.3s var(--ease);
  will-change: transform;
}

.card.is-open .card__cover {
  transform: rotateY(-180deg);
}

.cover-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: 2px 8px 8px 2px;
  overflow: hidden;
  background: var(--paper);
  box-shadow:
    0 30px 60px -30px rgba(74, 58, 58, 0.5),
    0 10px 30px -20px rgba(74, 58, 58, 0.3);
}

.cover-face--front {
  background:
    radial-gradient(120% 80% at 80% 10%, #fbeae6 0%, transparent 55%),
    radial-gradient(100% 100% at 10% 100%, #f2e4dc 0%, transparent 60%),
    linear-gradient(160deg, #fbf6f1 0%, #f4e7df 100%);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(32 * var(--u));
}

.cover-face--front::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    rgba(74, 58, 58, 0.18) 0%,
    rgba(74, 58, 58, 0.04) 6%,
    transparent 20%
  );
}

.cover-face--back {
  transform: rotateY(180deg);
  /* mirrors the interior-right page background for consistency */
  background: var(--paper);
  box-shadow:
    inset -8px 0 16px -12px rgba(74, 58, 58, 0.25),
    0 30px 60px -30px rgba(74, 58, 58, 0.35);
  border-radius: 8px 2px 2px 8px;
}

.cover-face--back::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 0% 0%, rgba(232, 184, 179, 0.14), transparent 55%),
    radial-gradient(140% 100% at 100% 100%, rgba(184, 151, 115, 0.06), transparent 60%);
}

/* ----- Cover content ----- */

.cover-frame {
  position: relative;
  width: 100%;
  height: 100%;
  border: 1px solid var(--line);
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: calc(40 * var(--u)) calc(28 * var(--u));
  gap: calc(18 * var(--u));
}

.cover-frame::before,
.cover-frame::after {
  content: "";
  position: absolute;
  width: calc(14 * var(--u));
  height: calc(14 * var(--u));
  border: 1px solid var(--blush-deep);
  opacity: 0.5;
}
.cover-frame::before {
  top: calc(12 * var(--u));
  left: calc(12 * var(--u));
  border-right: none;
  border-bottom: none;
}
.cover-frame::after {
  bottom: calc(12 * var(--u));
  right: calc(12 * var(--u));
  border-left: none;
  border-top: none;
}

.cover-eyebrow {
  margin: 0;
  font-size: max(9px, calc(11 * var(--u)));
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.baby-name {
  margin: 0;
  font-family: "Parisienne", "Cormorant Garamond", cursive;
  font-weight: 400;
  color: var(--blush-deep);
  line-height: 1;
}

.baby-name--cover {
  font-size: calc(68 * var(--u));
  text-align: center;
}

.baby-name--inside {
  font-size: calc(44 * var(--u));
  margin: calc(4 * var(--u)) 0 calc(8 * var(--u));
}

.cover-date {
  margin: 0;
  font-family: "Cormorant Garamond", serif;
  font-size: max(12px, calc(18 * var(--u)));
  font-style: italic;
  color: var(--ink-soft);
  letter-spacing: 0.06em;
}

.cover-ornament {
  color: var(--blush-deep);
  opacity: 0.7;
  width: calc(80 * var(--u));
  margin-top: calc(6 * var(--u));
}
.cover-ornament svg {
  display: block;
  width: 100%;
  height: auto;
}

/* ----- Inside content ----- */

.photo {
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 60%;
  background: linear-gradient(160deg, #f0e2da, #e4d0c4);
  background-size: cover;
  background-position: center;
  border-radius: 3px;
  box-shadow:
    0 12px 24px -18px rgba(74, 58, 58, 0.6),
    inset 0 0 0 6px rgba(255, 255, 255, 0.6),
    inset 0 0 0 7px var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: calc(20 * var(--u));
}

.photo__label {
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  color: var(--ink-soft);
  opacity: 0.55;
  font-size: 14px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

.photo.has-image .photo__label {
  display: none;
}

.page__quote {
  margin: 0;
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  font-size: max(11.5px, calc(15 * var(--u)));
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: calc(260 * var(--u));
}

/* Photo and quote centred in their page, so a tall page doesn't leave the
   pair stranded at the top */
.cover-face--back .page__inner {
  justify-content: center;
}

.eyebrow {
  /* Balances the block against the family footer, which is pinned to the
     bottom — the slack is shared instead of piling up in one gap */
  margin: auto 0 calc(6 * var(--u));
  font-size: max(9px, calc(10.5 * var(--u)));
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.divider {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: calc(12 * var(--u)) 0 calc(18 * var(--u));
  width: 60%;
}
.divider span {
  flex: 1;
  height: 1px;
  background: var(--line);
}
.divider__dot {
  flex: 0 0 auto !important;
  width: 4px !important;
  height: 4px !important;
  border-radius: 50%;
  background: var(--blush-deep) !important;
}

.details {
  list-style: none;
  padding: 0;
  margin: 0 0 calc(20 * var(--u));
  font-family: "Cormorant Garamond", serif;
  font-size: max(12px, calc(17 * var(--u)));
  line-height: 1.7;
  color: var(--ink);
}
.details li {
  font-style: italic;
}

.family {
  margin-top: auto;
  padding-top: calc(16 * var(--u));
  border-top: 1px dashed var(--line);
  width: 100%;
}
.family__parents {
  margin: 0 0 4px;
  font-size: max(10.5px, calc(13 * var(--u)));
  color: var(--ink-soft);
  letter-spacing: 0.04em;
}
.family__parents strong {
  display: block;
  margin-top: 4px;
  font-weight: 500;
  font-size: max(12px, calc(15 * var(--u)));
  color: var(--ink);
  letter-spacing: 0.06em;
}
.family__sister {
  margin: calc(8 * var(--u)) 0 0;
  font-family: "Cormorant Garamond", serif;
  font-style: italic;
  font-size: max(11px, calc(14 * var(--u)));
  color: var(--ink-soft);
}

/* ----- Hint ----- */

/* In normal flow under the card — never floating over it, whatever the screen
   size. The space it needs is what --reserve holds back from the card. */
.hint {
  flex: 0 0 auto;
  margin: 20px 0 0;
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(92, 62, 66, 0.85);
  opacity: 0.7;
  transition: opacity 0.5s ease;
  pointer-events: none;
}

.hint::before {
  content: "◦ ";
  color: var(--blush-deep);
}

.hint.is-hidden {
  opacity: 0;
}

/* ----- Responsive -----

   Narrow portrait screens can't fit a side-by-side spread at a readable size,
   so the book turns vertical: the cover hinges on its TOP edge and flips up,
   leaving the photo page above and the details page below. Same markup, same
   3D flip — only the axis changes. */

@media (max-width: 639px) and (orientation: portrait) {
  :root {
    --gutter: 16px;
    --reserve: 96px;

    /* One full-width page; two of them stacked must fit the viewport height */
    --page-w: min(420px, 100vw - 2 * var(--gutter));
    --page-h: min(
      (var(--vh) * 100 - var(--reserve)) / 2,
      var(--page-w) * 1.368
    );
    --card-w: var(--page-w);
    --card-h: var(--page-h);

    /* Stacked pages are shorter than the design page, so the scale has to
       follow the height too — otherwise the text page overflows on small phones */
    --u: min(calc(var(--page-w) / 380), calc(var(--page-h) / 390));
  }

  .scene {
    perspective: 1600px;
    perspective-origin: 50% 50%;
  }

  /* Keep the hint to one or two lines so it stays inside its reserved space */
  .hint {
    margin-top: 14px;
    font-size: 10.5px;
    letter-spacing: 0.18em;
  }

  /* Stacked pages: the stage is one page wide and two tall, and the shadow
     grows downward instead of sideways */
  .stage {
    width: var(--page-w);
    height: calc(var(--page-h) * 2);
  }

  .stage::before {
    transform: translate3d(0, 0, -2px) scaleY(0.5);
  }
  .stage::after {
    transform: translate3d(0, 0, -1px) scaleY(0.5);
  }
  .stage.is-open::before {
    transform: translate3d(0, 0, -2px) scaleY(1);
  }
  .stage.is-open::after {
    transform: translate3d(0, 0, -1px) scaleY(1);
  }

  .card {
    width: var(--page-w);
    height: calc(var(--page-h) * 2);
    transform: translateY(calc(var(--page-h) / -2));
  }
  .card.is-open {
    transform: translateY(0);
  }

  /* Interior page: now the lower half */
  .page {
    height: var(--page-h);
    border-radius: 2px 2px 8px 8px;
    box-shadow:
      inset 0 8px 16px -12px rgba(74, 58, 58, 0.25),
      0 30px 60px -30px rgba(74, 58, 58, 0.35);
  }
  .page--right {
    left: 0;
    top: var(--page-h);
  }

  /* Cover: sits over the lower half, hinged along its top edge */
  .card__cover {
    left: 0;
    top: var(--page-h);
    width: var(--page-w);
    height: var(--page-h);
    transform-origin: center top;
  }
  .card.is-open .card__cover {
    transform: rotateX(180deg);
  }

  .cover-face {
    border-radius: 2px 2px 8px 8px;
  }

  /* Spine shading follows the hinge to the top edge */
  .cover-face--front::before {
    background: linear-gradient(
      180deg,
      rgba(74, 58, 58, 0.18) 0%,
      rgba(74, 58, 58, 0.04) 6%,
      transparent 20%
    );
  }

  .cover-face--back {
    transform: rotateX(180deg);
    border-radius: 8px 8px 2px 2px;
    box-shadow:
      inset 0 -8px 16px -12px rgba(74, 58, 58, 0.25),
      0 -30px 60px -30px rgba(74, 58, 58, 0.35);
  }

  /* Tighter gutters inside the pages — vertical room is the scarce one here */
  .page__inner {
    padding: calc(24 * var(--u)) calc(30 * var(--u));
  }
  .details {
    line-height: 1.55;
    margin-bottom: calc(12 * var(--u));
  }

  .photo {
    max-height: 62%;
  }
}

/* Short landscape screens (phone turned sideways): height is the scarce axis,
   so claw back the margins the portrait layout can afford. */
@media (orientation: landscape) and (max-height: 540px) {
  :root {
    --gutter: 12px;
    --reserve: 72px;
  }

  .hint {
    margin-top: 10px;
    font-size: 10px;
    letter-spacing: 0.18em;
  }

  .page__inner {
    padding: calc(28 * var(--u)) calc(30 * var(--u));
  }
  .details {
    line-height: 1.5;
    margin-bottom: calc(12 * var(--u));
  }
}

/* Reduced motion: freeze the table into a composed still rather than
   removing the scene. Motes keep the scattered positions JS gave them. */
@media (prefers-reduced-motion: reduce) {
  .card,
  .card__cover,
  .stage::before,
  .stage::after {
    transition-duration: 0.001s;
  }

  .sky__band,
  .sky__stars,
  .sky__stars::before,
  .sky__stars::after,
  .sky__bright span {
    animation: none;
  }

  /* A shooting star is motion by definition — drop it rather than freeze
     a streak mid-sky */
  .sky__shooting {
    display: none;
  }
}
