/* Version 3 — Paper Scrapbook.
   Warm paper, washi tape, handwriting, and photographs you can pick up.
   Rounded display type, generous rotation, nothing perfectly square. */

:root {
  --paper: #f6efe3;
  --paper-2: #efe4d2;
  --card: #fffdf8;
  --ink: #3a3026;
  --ink-soft: #7b6c59;
  --plum: #7c5cc4;
  --plum-deep: #4f3a86;
  --mint: #6fbfa9;
  --sun: #f2b544;
  --rose: #e98fa4;
  --tape: rgba(242, 181, 68, 0.55);
  --line: rgba(58, 48, 38, 0.14);
  --shadow: 0 16px 36px rgba(96, 72, 44, 0.16);
  --display: "Baloo 2", system-ui, sans-serif;
  --hand: "Caveat", cursive;
  --sans: "Nunito", system-ui, sans-serif;
  --pad: clamp(18px, 5vw, 88px);

  /* A little bouquet flower for the pointer, and a heart over anything clickable. */
  --cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='34' height='34' viewBox='0 0 34 34'><g fill='%23d9c2ff' stroke='%234f3a86' stroke-width='1.4'><circle cx='17' cy='8.5' r='5.6'/><circle cx='25.4' cy='14.6' r='5.6'/><circle cx='22.2' cy='24.4' r='5.6'/><circle cx='11.8' cy='24.4' r='5.6'/><circle cx='8.6' cy='14.6' r='5.6'/></g><circle cx='17' cy='17' r='4.4' fill='%23f2b544' stroke='%234f3a86' stroke-width='1.4'/></svg>") 17 17, auto;
  --cursor-hand: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='34' height='34' viewBox='0 0 34 34'><path d='M17 30C8 23 3 18 3 11.5a7 7 0 0 1 14-2.5 7 7 0 0 1 14 2.5C31 18 26 23 17 30z' fill='%23ff9fb2' stroke='%234f3a86' stroke-width='1.6'/><circle cx='11' cy='10.5' r='2' fill='%23fff'/></svg>") 17 17, pointer;
}

html,
body {
  cursor: var(--cursor);
}

a,
button,
[role="button"],
[data-embed],
.letter,
.hotspot,
[data-lightbox] {
  cursor: var(--cursor-hand);
}

body {
  background-color: var(--paper);
  /* Paper grain built from gradients so the page ships no texture file. */
  background-image: radial-gradient(rgba(140, 115, 80, 0.07) 1px, transparent 1px),
    radial-gradient(rgba(140, 115, 80, 0.05) 1px, transparent 1px),
    linear-gradient(180deg, #f8f2e8, #f1e7d6);
  background-size: 18px 18px, 11px 11px, 100% 100%;
  background-position: 0 0, 6px 8px, 0 0;
  color: var(--ink);
  font: 400 clamp(15px, 1.05vw, 17px) / 1.7 var(--sans);
  overflow-x: hidden;
}

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.04;
  margin: 0;
  letter-spacing: -0.01em;
}

h2 {
  font-size: clamp(36px, 6.4vw, 96px);
}

h3 {
  font-size: clamp(20px, 1.9vw, 28px);
}

p {
  margin: 0;
}

.hand {
  font-family: var(--hand);
  font-size: clamp(19px, 1.8vw, 27px);
  color: var(--plum);
}

.eyebrow {
  font-family: var(--hand);
  font-size: clamp(19px, 1.7vw, 26px);
  color: var(--mint);
  margin-bottom: 4px;
}

.note {
  text-align: center;
  font-family: var(--hand);
  font-size: 20px;
  color: var(--ink-soft);
  margin-top: 22px;
}

.section-head {
  position: relative;
  z-index: 1;
  padding: clamp(60px, 11vh, 160px) var(--pad) clamp(22px, 4vh, 48px);
  max-width: 900px;
}

.button {
  display: inline-block;
  background: var(--plum);
  color: #fff;
  border: 0;
  border-radius: 30px;
  padding: 11px 20px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 14.5px;
  text-decoration: none;
  box-shadow: 0 6px 0 rgba(79, 58, 134, 0.45);
  transition: transform 0.2s, box-shadow 0.2s;
}

.button:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 0 rgba(79, 58, 134, 0.45);
}

.button:active {
  transform: translateY(3px);
  box-shadow: 0 2px 0 rgba(79, 58, 134, 0.45);
}

.button.is-small {
  padding: 8px 15px;
  font-size: 13px;
  box-shadow: 0 4px 0 rgba(79, 58, 134, 0.45);
}

/* --------------------------------------------------------------- tape bits */
.tape {
  position: absolute;
  width: 92px;
  height: 26px;
  background: var(--tape);
  box-shadow: 0 1px 4px rgba(90, 70, 40, 0.18);
  z-index: 4;
  pointer-events: none;
}

.tape::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.28) 0 4px, transparent 4px 9px);
}

.tape-tl {
  top: -12px;
  left: 14px;
  transform: rotate(-7deg);
}

.tape-br {
  bottom: -12px;
  right: 16px;
  transform: rotate(5deg);
  background: rgba(111, 191, 169, 0.5);
}

/* --------------------------------------------------------------- preloader */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 9800;
  background: var(--paper);
  display: grid;
  place-content: center;
  gap: 18px;
  justify-items: center;
}

.preloader-note {
  font-family: var(--hand);
  font-size: clamp(26px, 5vw, 48px);
  color: var(--plum);
}

.preloader-bar {
  width: min(260px, 50vw);
  height: 8px;
  border: 2px solid var(--ink);
  border-radius: 20px;
  display: block;
  overflow: hidden;
}

.preloader-bar i {
  display: block;
  height: 100%;
  background: var(--sun);
  transform-origin: left;
  transform: scaleX(0);
}

/* ------------------------------------------------------------------ chrome */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: linear-gradient(90deg, var(--sun), var(--rose), var(--plum));
  transform-origin: left;
  transform: scaleX(0);
  z-index: 7000;
}

/* -------------------------------------------------------------- ribbon svg */
/* The ribbon is as tall as the page below the hero. Its height and its path are
   both written by js/main.js, because the page's height is not knowable from
   CSS: this used to be a hard 2600px, which was right when it was written and
   stopped reaching the last few years as the page grew. */
.ribbon {
  position: absolute;
  top: 100vh;
  left: 50%;
  transform: translateX(-50%);
  width: min(1180px, 94vw);
  height: 2600px;
  color: rgba(124, 92, 196, 0.3);
  pointer-events: none;
  z-index: 0;
}

/* -------------------------------------------------------------------- hero */
/* Full-bleed: the photograph covers the whole first screen. */
.hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 520px;
  overflow: hidden;
  /* Fills the letterbox on portrait screens with the photo's own sky and lake. */
  background: linear-gradient(180deg, #e6eef0 0%, #d4e4e8 45%, #4f96a6 46%, #3f8a99 100%);
}

.hero-window {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.develop {
  position: absolute;
  inset: 0;
  z-index: 6;
  background: radial-gradient(circle at 50% 45%, #f7f1e6, #e9dfcf);
  opacity: 0;
  pointer-events: none;
}

/* A soft paper vignette at the bottom so the tagline reads over the water. */
.hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 30%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to top, rgba(40, 30, 60, 0.38), rgba(40, 30, 60, 0));
}

.corner-sticker {
  position: absolute;
  top: 22px;
  right: var(--pad);
  z-index: 7;
  font-family: var(--display);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  background: var(--tape);
  padding: 7px 14px;
  transform: rotate(4deg);
  box-shadow: 0 2px 6px rgba(90, 70, 40, 0.15);
}

.hero-subject {
  pointer-events: none;
}

/* Letters: one absolutely placed element per glyph, in frame coordinates. */
.hero-name .letter {
  position: absolute;
  display: block;
  transform-origin: 50% 100%;
}

.hero-name .hop,
.hero-name .bob {
  display: block;
  width: 100%;
  height: 100%;
  transform-origin: 50% 100%;
}

.hero-name .letter img {
  width: 100%;
  height: 100%;
  object-fit: fill;
  transform-origin: 50% 100%;
  user-select: none;
  -webkit-user-drag: none;
}

.hotspot {
  position: absolute;
  z-index: 4;
  background: none;
  border: 0;
  padding: 0;
  border-radius: 40%;
}

.hotspot:focus-visible {
  outline: 2px dashed var(--plum);
}

/* Handwritten tagline over the lower-left of the photo. */
.tagline {
  position: absolute;
  z-index: 7;
  left: var(--pad);
  bottom: clamp(56px, 10vh, 110px);
  margin: 0;
  pointer-events: none;
}

.tagline-text {
  display: block;
  font-family: var(--hand);
  font-weight: 700;
  font-size: clamp(34px, 4.6vw, 72px);
  line-height: 1;
  color: #fff;
  transform: rotate(-4deg);
  text-shadow: 0 2px 0 var(--plum-deep), 0 6px 22px rgba(40, 25, 80, 0.45);
}

/* Caveat's ascenders and descenders overflow its em box, and .tagline-text
   sets line-height: 1, so the shared .sp-mask clip cropped the tops of the k,
   t and ll and the tail of the y. The tagline is revealed with a fade and a
   40% rise rather than the full slide-up the [data-split] headings use, so
   nothing here depends on the clip and it can simply be turned off. Padding
   the mask instead cannot fix it: the bottom padding needed for the descender
   is exactly what would leave the glyph visible before it rises. */
.tagline-text .sp-mask {
  overflow: visible;
  padding-bottom: 0;
  margin-bottom: 0;
}

.tagline-line {
  display: block;
  width: 100%;
  height: clamp(12px, 1.4vw, 20px);
  margin-top: 4px;
  transform: rotate(-4deg);
  overflow: visible;
}

.tagline-line path {
  fill: none;
  stroke: var(--sun);
  stroke-width: 6;
  stroke-linecap: round;
}

.scribble {
  position: absolute;
  font-family: var(--hand);
  font-size: clamp(21px, 2.2vw, 32px);
  z-index: 7;
  pointer-events: none;
}

.scribble-3 {
  bottom: 2.4vh;
  left: 50%;
  translate: -50% 0;
  color: #fff;
  text-shadow: 0 2px 10px rgba(40, 25, 80, 0.5);
  animation: bob 2.4s ease-in-out infinite;
}

@keyframes bob {
  50% {
    translate: -50% 8px;
  }
}

@media (max-width: 760px) {
  .tagline {
    bottom: 64px;
  }
}

.confetti {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 5;
}

.confetti i {
  position: absolute;
  top: -6vh;
  width: 8px;
  height: 12px;
  border-radius: 2px;
  background: var(--sun);
  opacity: 0.5;
  animation: drift linear infinite;
}

.confetti i:nth-child(3n) {
  background: var(--rose);
}

.confetti i:nth-child(3n + 1) {
  background: var(--mint);
}

@keyframes drift {
  0% {
    transform: translate3d(0, -8vh, 0) rotate(0);
  }
  100% {
    transform: translate3d(10vw, 115vh, 0) rotate(560deg);
  }
}

/* ------------------------------------------------------------------- hello */
/* Sized by its own content. It used to be min-height:100vh with the content
   centred, which on a 900px-tall viewport left 185px of dead space above the
   eyebrow and the same below, because the heading and the one paragraph only
   need about 530px. The padding alone gives the section its breathing room. */
.hello {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(60px, 10vh, 120px) var(--pad);
  max-width: 1480px;
  margin: 0 auto;
}

.hello h2 {
  font-size: clamp(56px, 9vw, 150px);
  line-height: 1;
}

.hello .eyebrow { margin-bottom: 14px; }

.hello-text {
  font-family: var(--display);
  font-size: clamp(24px, 3.4vw, 54px);
  line-height: 1.58;
  margin-top: clamp(24px, 4vh, 48px);
  max-width: 36ch;
}

/* -------------------------------------------------------------------- path */
.path-list {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(32px, 5vh, 64px);
  padding: 0 var(--pad) clamp(48px, 7vh, 100px);
  max-width: 1620px;
  margin: 0 auto;
  /* How far a photo cluster is allowed to run out into the page's side
     padding. It stops 26px short of the padding, because the frames are
     rotated and a tilted corner reaches further than the box does; bleeding
     the full padding put a corner off the edge of the window. Capped at 56px
     so the overhang stays deliberate rather than whatever 5vw happens to be
     on a wide monitor. */
  --bleed: clamp(0px, calc(var(--pad) - 26px), 56px);
}

/* Note on one side, a big taped photo collage on the other, alternating. The
   note's column is a fixed width, not a share of the row, so the text block
   measures the same whatever the window is doing; all the extra space goes to
   the photos. The photo column also overhangs the page padding on its outer
   edge, which is where the rest of the size comes from: wider costs nothing,
   taller costs scrolling. */
.step {
  display: grid;
  grid-template-columns: minmax(0, 545px) minmax(0, 1fr);
  gap: clamp(20px, 2.6vw, 48px);
  align-items: center;
}

.step.is-flip {
  grid-template-columns: minmax(0, 1fr) minmax(0, 545px);
}

.step .step-photos {
  margin-right: calc(-1 * var(--bleed));
  margin-left: auto;
}

.step.is-flip .step-photos {
  margin-right: auto;
  margin-left: calc(-1 * var(--bleed));
}

.step.is-flip .step-note {
  order: 2;
}

.step-note {
  position: relative;
  background: var(--card);
  border-radius: 6px;
  padding: clamp(22px, 3vw, 40px);
  box-shadow: var(--shadow);
  transform: rotate(var(--r, 0deg));
}

.pin {
  position: absolute;
  top: -10px;
  left: 50%;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--rose);
  box-shadow: 0 3px 6px rgba(90, 60, 40, 0.3), inset 0 -3px 4px rgba(0, 0, 0, 0.12);
}

.note-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.note-year {
  font-family: var(--display);
  font-weight: 800;
  font-size: 15px;
  background: var(--sun);
  border-radius: 20px;
  padding: 4px 12px;
}

.note-kind {
  font-family: var(--hand);
  font-size: 20px;
  color: var(--mint);
}

.note-sub {
  color: var(--plum);
  margin-top: 6px;
  font-weight: 600;
}

.note-meta {
  color: var(--ink-soft);
  font-size: 13.5px;
  margin-top: 4px;
}

.note-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  list-style: none;
  padding: 0;
  margin: 14px 0 0;
}

.note-tags li {
  font-size: 12px;
  background: var(--paper-2);
  border-radius: 20px;
  padding: 5px 11px;
}

.note-points {
  margin: 14px 0 0;
  padding-left: 18px;
  display: grid;
  gap: 9px;
  font-size: 14.5px;
}

.note-points li::marker {
  color: var(--rose);
}

/* A cluster of polaroids, each at its OWN aspect ratio. It used to be an
   absolutely positioned stack where every photo was cropped to 4:3, which
   turned Minko's portrait phone shots into a square-ish band and hid parts of
   one photo behind another. Now the images keep their real shape (--ar, set
   from naturalWidth/naturalHeight in main.js) and the cluster is a two-column
   grid, so a tall photo makes a tall cell instead of being cut. The scrapbook
   feel comes from the rotation, tape and shadow rather than from overlap. */
.step-photos {
  position: relative;
  width: 100%;
  display: grid;
  /* Each column is as wide as its photo's aspect ratio, which is what makes
     the two photos in the row the same height. The fr values are written by
     sizeCluster once the photos report their shapes; this fallback is what you
     see for the instant before that. */
  grid-template-columns: 1fr 1fr;
  align-items: start;
  /* No gap. The frames are placed by their own negative margins, because the
     overlap has to be a fixed number of pixels at the frame's edge rather than
     a share of the row. */
  gap: 0;
  /* A reserved strip across the top for the year stamp, and one across the
     bottom for the place. Nothing with text is inside the pile any more, so no
     amount of overlap can cover a word. */
  padding: 34px 0 0;
}

.step-photos.count-1 {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
}

.snap {
  position: relative;
  margin: 0;
  background: #fff;
  /* The bottom border is wider than the sides, which is what makes a frame
     read as a polaroid. It used to be a figcaption holding the place name;
     the place now sits under the whole pile instead, because a frame pulled up
     over another frame covered it. */
  padding: 10px 10px 16px;
  box-shadow: 0 18px 40px rgba(96, 72, 44, 0.22);
  transform: rotate(var(--r, 0deg));
}

.snap img {
  display: block;
  width: 100%;
  /* The fallback only applies for the instant before the image reports its
     own size, and to a photo that fails to load. */
  aspect-ratio: var(--ar, 4 / 3);
  object-fit: cover;
}

.step-place {
  /* order has to be set explicitly: the two frames in the row are given order
     1 and 2 and the third frame order 3, so anything left at the default 0
     would be laid out before them and take the row's first cell. */
  order: 4;
  grid-column: 1 / -1;
  font-family: var(--hand);
  font-size: clamp(17px, 1.5vw, 23px);
  color: var(--ink-soft);
  text-align: center;
  margin: 10px 0 0;
  /* Above every frame, so it stays legible even where a tilted corner reaches
     into the line. */
  position: relative;
  z-index: 7;
}

.count-1 .snap-0 {
  width: min(88%, 440px);
}

/* Two photos in the top row at a matched height, the one on the stamp side
   dropped so the tops are not level, and the third centred underneath them,
   pulled up over both. The cluster is deliberately tight: three frames that
   read as a pile rather than as a grid.

   Every overlap is a fixed pixel amount at the frame's edge, never a fraction
   of the picture, and the frame carries 10px of white on each side, so an
   overlap of 24px eats about 14px of the photo underneath. That is what keeps
   a face from being covered at any column width.

   Which photo sits left and which is dropped is decided by sizeCluster in
   main.js, not here, because it depends on the photos' shapes: order and the
   is-lap and is-drop classes come from JS, and these rules only say what they
   mean. */
.snap.is-lap {
  margin-left: -24px;
  z-index: 2;
}

/* The frame on the stamp side drops down the page. */
.snap.is-drop {
  margin-top: clamp(12px, 2.6vw, 36px);
}

/* The third photo sits on its own row, pulled back up over the pair. Its width
   comes from sizeCluster, which derives it from the row's height so that a
   portrait third and a landscape third end up a similar height rather than a
   similar width. */
.count-3 .snap-2 {
  order: 3;
  grid-column: 1 / span 2;
  grid-row: 2;
  justify-self: center;
  width: var(--third-w, 46%);
  margin-top: -62px;
  z-index: 3;
}

/* The mirrored-step overrides that used to swap the two grid columns are gone:
   which photo sits where is now decided from the photos' shapes in main.js,
   and applies the same way to a mirrored step. */

/* The stamp lives in the 34px strip reserved at the top of the cluster, in
   whichever outer corner is away from the note. Because the strip is padding
   on the cluster rather than space a photo happens to leave, the stamp can
   never land on a photo, whatever shapes the photos turn out to be. That used
   to depend on the second photo being dropped far enough, and it was not. */
.year-stamp {
  position: absolute;
  z-index: 6;
  top: -6px;
  right: -4px;
  width: clamp(62px, 5.4vw, 80px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 3px dashed var(--plum);
  color: var(--plum);
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(17px, 1.6vw, 23px);
  background: rgba(255, 253, 248, 0.85);
  transform: rotate(-14deg);
}

.is-flip .year-stamp {
  right: auto;
  left: -4px;
}

/* The old .count-3 overrides are gone: the stamp's strip is reserved for every
   cluster now, so there is nothing per-count left to correct. */

@media (max-width: 880px) {
  .step,
  .step.is-flip {
    grid-template-columns: 1fr;
  }

  .step.is-flip .step-note {
    order: 0;
  }
}

/* -------------------------------------------------------------------- film
   Two labelled shelves. Everything Minko has made is on screen at once: the
   long-form films on the top shelf, the vertical reels on the shelf below,
   each shape in a frame of its own so nothing is cropped or letterboxed.

   This replaced a feature screen with a tab per film. The tab hid half the
   work — on arrival the section claimed two films and showed one — and tabs
   are for alternative views of one thing, not for a body of work. */
.shelves {
  width: min(1480px, 100%);
  margin: 0 auto;
  padding: 0 var(--pad);
}

.shelf + .shelf { margin-top: clamp(32px, 4vh, 54px); }

.shelf-label {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 14px;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(60, 45, 38, 0.16);
}

.shelf-label b {
  font: 800 clamp(17px, 1.5vw, 21px)/1 var(--sans);
  color: var(--plum-deep);
}

.shelf-label span {
  font-family: var(--hand);
  font-size: clamp(16px, 1.4vw, 20px);
  color: var(--ink-soft);
}

/* Two columns for the 16:9 films, four for the 9:16 reels. At these widths
   both shelves come out a similar height, which is what makes the pair read
   as one block rather than two unrelated rows. */
.shelf--films .shelf-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px);
}

.shelf--reels .shelf-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 22px);
}

/* One tile, both shelves. --ratio carries the film's own shape, so the frame
   matches the footage and object-fit: cover has nothing to crop. */
.tile { margin: 0; }

.tile-media {
  position: relative;
  aspect-ratio: var(--ratio, 16 / 9);
  background: #000;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow);
}

.tile-media video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Once it is playing with controls, switch to contain: the viewer is watching
   now, so the whole frame matters more than filling the tile. */
.tile.is-playing .tile-media video { object-fit: contain; }

.tile-badge {
  position: absolute;
  top: 9px;
  right: 9px;
  font: 600 11px/1 var(--sans);
  letter-spacing: 0.4px;
  color: #fff;
  background: rgba(29, 26, 36, 0.7);
  border-radius: 999px;
  padding: 5px 9px;
}

.tile-play {
  position: absolute;
  inset: auto 10px 10px auto;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: var(--sun);
  color: #2a2420;
  font-size: 14px;
  display: grid;
  place-items: center;
  cursor: var(--cursor-hand);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  transition: transform 0.2s;
}

.tile-play:hover { transform: scale(1.08); }
.tile.is-playing .tile-play { display: none; }

.tile figcaption { padding: 10px 2px 0; }
.tile figcaption strong { display: block; font: 700 clamp(14px, 1.2vw, 16px)/1.3 var(--sans); }
.tile figcaption span { font-size: 12.5px; color: var(--ink-soft); }

@media (max-width: 880px) {
  .shelf--films .shelf-row { grid-template-columns: minmax(0, 1fr); }
  .shelf--reels .shelf-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
  .tile-play { transition: none; }
}

/* ------------------------------------------------------------------- album
   The deck reader. A shelf of decks down the left, the chosen deck paging
   one slide at a time on the right. Slides are prerendered WebP images. */
.album {
  background: var(--paper-2);
  padding: clamp(50px, 9vh, 110px) 0;
  border-top: 2px dashed rgba(58, 48, 38, 0.2);
  border-bottom: 2px dashed rgba(58, 48, 38, 0.2);
}

.album-inner {
  display: grid;
  gap: clamp(24px, 4vh, 44px);
  max-width: 1420px;
  margin: 0 auto;
  padding: 0 var(--pad);
}

.album-head .hand {
  margin-top: 4px;
}

.reader {
  display: grid;
  grid-template-columns: minmax(230px, 310px) minmax(0, 1fr);
  gap: clamp(20px, 2.6vw, 44px);
  align-items: start;
}

/* ------------------------------------------------------------- the shelf */
.reader-shelf {
  display: grid;
  gap: 14px;
  position: sticky;
  top: clamp(16px, 4vh, 40px);
}

.reader-list {
  display: grid;
  gap: 12px;
}

.shelf-item {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr);
  gap: 13px;
  align-items: center;
  text-align: left;
  padding: 11px;
  background: var(--card);
  border: 0;
  border-radius: 6px;
  box-shadow: 0 8px 18px rgba(96, 72, 44, 0.12);
  rotate: var(--r, 0deg);
  transition: rotate 0.3s ease, translate 0.3s ease, box-shadow 0.3s ease;
}

.shelf-item:hover {
  rotate: 0deg;
  translate: 3px -2px;
  box-shadow: 0 14px 26px rgba(96, 72, 44, 0.2);
}

/* The open deck straightens up and gets a strip of washi tape. */
.shelf-item[aria-selected="true"] {
  position: relative;
  rotate: 0deg;
  background: #fff;
  box-shadow: 0 14px 30px rgba(96, 72, 44, 0.24);
  outline: 2px solid var(--plum);
  outline-offset: -2px;
}

.shelf-item[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -9px;
  width: 64px;
  height: 17px;
  translate: -50% 0;
  rotate: -2.5deg;
  background: var(--tape);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}

.shelf-thumb {
  display: block;
  overflow: hidden;
  border-radius: 3px;
  background: var(--paper-2);
}

.shelf-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.shelf-copy {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.shelf-kind {
  font-family: var(--hand);
  font-size: 17px;
  line-height: 1.1;
  color: var(--mint);
}

.shelf-copy strong {
  font-family: var(--display);
  font-weight: 700;
  font-size: 15px;
  line-height: 1.25;
  color: var(--ink);
}

.shelf-meta {
  font-size: 12px;
  color: var(--ink-soft);
}

.reader-all {
  justify-self: start;
  margin-top: 4px;
}

/* -------------------------------------------------------------- the stage */
.reader-main {
  display: grid;
  gap: 14px;
  min-width: 0;
}

.reader-stage {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--card);
  border-radius: 8px;
  padding: 10px;
  box-shadow: var(--shadow);
  overflow: hidden;
}

.reader-stage img {
  position: absolute;
  inset: 10px;
  width: calc(100% - 20px);
  height: calc(100% - 20px);
  object-fit: contain;
  opacity: 0;
  /* Hidden slides must not swallow the click meant for the visible one. */
  pointer-events: none;
  transition: opacity 0.34s ease;
}

.reader-stage img.is-on {
  opacity: 1;
  pointer-events: auto;
}

/* A slide that could not be fetched, after one retry. The frame shows a paper
   card with a short note instead of the browser's broken-image icon. */
.reader-stage img.is-missing,
.reader-pips img.is-missing {
  background: var(--paper-2);
  object-fit: contain;
}

.reader-stage:has(img.is-missing.is-on)::after {
  content: "this slide did not load — try the pdf, or reload the page";
  position: absolute;
  inset: 10px;
  z-index: 1;
  display: grid;
  place-content: center;
  padding: 20px;
  text-align: center;
  font-family: var(--hand);
  font-size: 21px;
  color: var(--ink-soft);
  background: var(--paper-2);
  border-radius: 4px;
}

.reader-nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  width: 44px;
  height: 44px;
  display: grid;
  place-content: center;
  translate: 0 -50%;
  font-size: 22px;
  line-height: 1;
  color: var(--ink);
  background: rgba(255, 253, 248, 0.92);
  border: 1px solid var(--line);
  border-radius: 50%;
  box-shadow: 0 6px 16px rgba(96, 72, 44, 0.22);
  transition: scale 0.2s ease, opacity 0.2s ease;
}

.reader-nav:hover { scale: 1.08; }
.reader-nav.is-prev { left: 16px; }
.reader-nav.is-next { right: 16px; }
.reader-nav:disabled { opacity: 0.3; }

.reader-hint {
  position: absolute;
  right: 18px;
  bottom: 12px;
  z-index: 2;
  font-size: 17px;
  color: var(--plum-deep);
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}

.reader-stage:hover .reader-hint { opacity: 0.85; }

.reader-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.reader-count {
  font-family: var(--hand);
  font-size: 21px;
  color: var(--plum-deep);
}

.reader-bar .button {
  margin-left: auto;
}

/* ---------------------------------------------------------- thumbnails */
.reader-pips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.reader-pips button {
  width: 62px;
  padding: 0;
  overflow: hidden;
  background: var(--card);
  border: 2px solid transparent;
  border-radius: 4px;
  box-shadow: 0 3px 8px rgba(96, 72, 44, 0.14);
  transition: translate 0.2s ease, border-color 0.2s ease;
}

.reader-pips button:hover { translate: 0 -3px; }
.reader-pips button[aria-current="true"] { border-color: var(--plum); }

.reader-pips img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* Stack the shelf above the stage once there is no room beside it. */
@media (max-width: 860px) {
  .reader {
    grid-template-columns: minmax(0, 1fr);
  }

  .reader-shelf {
    position: static;
    grid-auto-flow: row;
  }

  .reader-list {
    grid-auto-flow: column;
    grid-auto-columns: minmax(210px, 1fr);
    gap: 10px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding: 6px 2px 12px;
  }

  .shelf-item {
    scroll-snap-align: start;
    rotate: 0deg;
  }

  .reader-nav.is-prev { left: 8px; }
  .reader-nav.is-next { right: 8px; }
  .reader-pips button { width: 50px; }
}

/* ------------------------------------------------------------------ beyond */
.beyond {
  position: relative;
  overflow: hidden;
  padding-bottom: clamp(70px, 12vh, 150px);
}

.doodles {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

.doodle {
  position: absolute;
  opacity: 0.55;
  animation: floaty 6s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}

@keyframes floaty {
  50% {
    translate: 0 -10px;
  }
}

.egg-count {
  display: inline-block;
  margin-top: 14px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 14px;
  background: #fff6cf;
  padding: 6px 14px;
  border-radius: 3px;
  transform: rotate(-2deg);
  box-shadow: 0 4px 10px rgba(90, 70, 40, 0.12);
}

.egg-count b {
  color: var(--plum);
}

/* A dense 12-column board. Each card has a span that fits the shape of its
   photo arrangement, and the rows fill completely at desktop widths. */
.scatter {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-flow: row dense;
  gap: clamp(14px, 1.6vw, 24px);
  padding: 0 var(--pad);
  max-width: 1480px;
  margin: 0 auto;
  align-items: start;
}

.bit {
  position: relative;
  background: var(--card);
  border-radius: 6px;
  padding: 14px 14px 18px;
  box-shadow: var(--shadow);
  transform: rotate(var(--r, 0deg));
  touch-action: pan-y;
  outline-offset: 4px;
}

.bit-twins { grid-column: span 5; }
.bit-ballet { grid-column: span 3; }
.bit-cats { grid-column: span 4; }
.bit-travel { grid-column: span 6; }
.bit-food { grid-column: span 6; }
.bit-crafts { grid-column: span 4; }
.bit-forky { grid-column: span 3; }
.bit-coffee { grid-column: span 2; }
.bit-bear { grid-column: span 3; }

@media (max-width: 1100px) {
  .scatter {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .bit-twins,
  .bit-travel,
  .bit-food {
    grid-column: span 6;
  }

  .bit {
    grid-column: span 3;
  }
}

@media (max-width: 640px) {
  .scatter {
    grid-template-columns: 1fr;
  }

  .bit,
  .bit-twins,
  .bit-travel,
  .bit-food {
    grid-column: auto;
  }
}

.bit.is-found .bit-tap {
  background: var(--mint);
  color: #fff;
}

.bit-tap {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 3;
  font-family: var(--hand);
  font-size: 17px;
  background: #fff;
  color: var(--plum);
  border-radius: 20px;
  padding: 1px 10px;
  box-shadow: 0 3px 8px rgba(90, 70, 40, 0.15);
  pointer-events: none;
  transition: transform 0.3s;
}

.bit:hover .bit-tap {
  transform: rotate(-4deg) scale(1.08);
}

.bit-copy {
  padding: 12px 4px 0;
}

.bit-emoji {
  font-size: 24px;
  display: inline-block;
  transition: transform 0.4s;
}

.bit:hover .bit-emoji {
  transform: rotate(-14deg) scale(1.25);
}

.bit-copy h3 {
  margin: 2px 0 4px;
  font-size: clamp(19px, 1.6vw, 25px);
}

.bit-head {
  font-family: var(--hand);
  font-size: 20px;
  color: var(--plum);
  line-height: 1.2;
}

.bit-story {
  font-size: 13.5px;
  color: var(--ink-soft);
  margin-top: 6px;
  line-height: 1.55;
}

/* --- photo arrangements ------------------------------------------------ */
.gal {
  position: relative;
  width: 100%;
  filter: drop-shadow(0 8px 12px rgba(96, 72, 44, 0.22));
}

.ph {
  position: absolute;
  display: block;
  overflow: hidden;
  transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.ph img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  user-select: none;
}

.bit:hover .ph:nth-child(odd) {
  transform: rotate(-4deg) scale(1.04);
}

.bit:hover .ph:nth-child(even) {
  transform: rotate(4deg) scale(1.06);
}

/* Shapes */
.sh-circle {
  border-radius: 50%;
  aspect-ratio: 1;
  border: 5px solid #fff;
}

.sh-arch {
  border-radius: 999px 999px 10px 10px;
  border: 5px solid #fff;
}

.sh-heart {
  aspect-ratio: 1 / 0.92;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 92'><path d='M50 90C20 68 0 50 0 27 0 11 12 0 27 0c10 0 18 6 23 15C55 6 63 0 73 0c15 0 27 11 27 27 0 23-20 41-50 63z'/></svg>") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 92'><path d='M50 90C20 68 0 50 0 27 0 11 12 0 27 0c10 0 18 6 23 15C55 6 63 0 73 0c15 0 27 11 27 27 0 23-20 41-50 63z'/></svg>") center / 100% 100% no-repeat;
}

/* Postage stamp: a white border band with a grid of round holes punched
   through it, so only the edge reads as perforated. */
.sh-stamp {
  background: #fff;
  padding: 8px;
  -webkit-mask: linear-gradient(#000 0 0) content-box, radial-gradient(circle, transparent 4.4px, #000 5px) -8px -8px / 16px 16px;
  mask: linear-gradient(#000 0 0) content-box, radial-gradient(circle, transparent 4.4px, #000 5px) -8px -8px / 16px 16px;
}

.sh-blob {
  border-radius: 62% 38% 54% 46% / 48% 60% 40% 52%;
  animation: morph 9s ease-in-out infinite;
}

@keyframes morph {
  33% {
    border-radius: 40% 60% 38% 62% / 58% 42% 58% 42%;
  }
  66% {
    border-radius: 55% 45% 64% 36% / 40% 56% 44% 60%;
  }
}

.sh-plate {
  border-radius: 50%;
  aspect-ratio: 1;
  border: 7px solid #fff;
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.06);
}

/* Embroidery hoop: a wooden ring with a clamp tab on top. */
.sh-hoop {
  border-radius: 50%;
  aspect-ratio: 1;
  border: 11px solid #cfa165;
  box-shadow: inset 0 0 0 3px #a47a40;
  overflow: visible;
}

.sh-hoop img {
  border-radius: 50%;
}

.sh-hoop::before {
  content: "";
  position: absolute;
  top: -22px;
  left: 50%;
  width: 22px;
  height: 18px;
  translate: -50% 0;
  background: #a47a40;
  border-radius: 4px 4px 2px 2px;
}

.sh-cloud {
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 80'><path d='M22 78C9 78 0 69 0 57c0-11 8-20 19-21C20 21 32 10 47 10c11 0 21 6 26 16 2-1 5-1 7-1 11 0 20 9 20 21 0 2 0 4-1 6 1 3 1 5 1 8 0 10-8 18-18 18z'/></svg>") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 80'><path d='M22 78C9 78 0 69 0 57c0-11 8-20 19-21C20 21 32 10 47 10c11 0 21 6 26 16 2-1 5-1 7-1 11 0 20 9 20 21 0 2 0 4-1 6 1 3 1 5 1 8 0 10-8 18-18 18z'/></svg>") center / 100% 100% no-repeat;
}

/* Layouts, per card */
.gal-twins { aspect-ratio: 4 / 3; }
.gal-twins .ph-0 { width: 60%; left: 2%; top: 4%; }
.gal-twins .ph-1 { width: 38%; right: 2%; top: 0; }
.gal-twins .ph-2 { width: 40%; right: 8%; bottom: 0; }

.gal-ballet { aspect-ratio: 3 / 4.1; }
.gal-ballet .ph-0 { width: 66%; height: 70%; left: 0; top: 0; }
.gal-ballet .ph-1 { width: 50%; right: 0; top: 40%; z-index: 2; }
.gal-ballet .ph-2 { width: 44%; height: 40%; left: 10%; bottom: 0; }

.gal-cats { aspect-ratio: 1 / 0.92; }
.gal-cats .ph-0 { width: 60%; height: 64%; left: 0; top: 0; }
.gal-cats .ph-1 { width: 40%; right: 2%; top: 2%; }
.gal-cats .ph-2 { width: 34%; left: 8%; bottom: 0; }
.gal-cats .ph-3 { width: 50%; right: 0; bottom: 2%; z-index: 2; }

/* Travel: a fanned stack of postage stamps that spreads on hover. */
.gal-travel { aspect-ratio: 16 / 8; }
.gal-travel .ph {
  width: 30%;
  aspect-ratio: 3 / 3.6;
  top: 8%;
  left: calc(var(--i) * 17.5%);
  transform: rotate(var(--t));
}
.gal-travel .ph-0 { --i: 0; --t: -12deg; }
.gal-travel .ph-1 { --i: 1; --t: -5deg; top: 2%; }
.gal-travel .ph-2 { --i: 2; --t: 3deg; z-index: 2; }
.gal-travel .ph-3 { --i: 3; --t: 9deg; top: 4%; }
.gal-travel .ph-4 { --i: 4; --t: 15deg; top: 12%; }
.bit-travel:hover .gal-travel .ph {
  transform: rotate(calc(var(--t) * 0.4)) translateX(calc((var(--i) - 2) * 14%)) translateY(-4%);
}

/* Food: plates scattered on a table. */
.gal-food { aspect-ratio: 16 / 8.4; }
.gal-food .ph-0 { width: 34%; left: 0; top: 4%; }
.gal-food .ph-1 { width: 24%; left: 31%; top: 0; z-index: 2; }
.gal-food .ph-2 { width: 28%; left: 52%; top: 12%; }
.gal-food .ph-3 { width: 22%; right: 0; top: 0; }
.gal-food .ph-4 { width: 26%; left: 26%; bottom: 0; z-index: 3; }

.gal-crafts { aspect-ratio: 1 / 0.95; }
.gal-crafts .ph-0 { width: 64%; left: 2%; top: 9%; }
.gal-crafts .ph-1 { width: 38%; height: 44%; right: 0; top: 0; }
.gal-crafts .ph-2 { width: 34%; height: 38%; right: 6%; bottom: 0; z-index: 2; }
.gal-crafts .ph-3 { width: 28%; left: 0; bottom: 0; z-index: 3; }

.gal-forky { aspect-ratio: 1 / 0.92; }
.gal-forky .ph-0 { width: 100%; height: 100%; left: 0; top: 0; }

.gal-coffee { aspect-ratio: 1 / 1.1; }
.gal-coffee .ph-0 { width: 100%; height: 100%; left: 0; top: 0; }

/* Two photos now: the cloud-shaped one fills the cell and the graduation one
   is tucked onto its lower corner, overlapping it. Written here because
   styles.css positions these clusters per bit, and a second photo with no
   coordinates would stack in the top-left corner. */
.gal-bear { aspect-ratio: 1 / 0.95; }
.gal-bear .ph-0 { width: 80%; height: 82%; left: 0; top: 0; }
.gal-bear .ph-1 { width: 42%; right: 0; bottom: 0; z-index: 2; }

/* ----------------------------------------------------------------- contact */
.contact {
  position: relative;
  z-index: 1;
  padding: clamp(60px, 10vh, 130px) var(--pad) 0;
  max-width: 1100px;
  margin: 0 auto;
  text-align: center;
}

.contact h2 {
  font-size: clamp(48px, 10vw, 150px);
  color: var(--plum-deep);
}

.contact-card {
  position: relative;
  background: var(--card);
  border-radius: 6px;
  padding: clamp(28px, 4vw, 56px);
  box-shadow: var(--shadow);
  margin-top: 30px;
  display: grid;
  gap: 18px;
  justify-items: center;
  transform: rotate(-0.8deg);
}

.big-link {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(20px, 3.2vw, 44px);
  color: var(--plum-deep);
  text-decoration: none;
  border-bottom: 4px solid var(--sun);
  overflow-wrap: anywhere;
}

.contact-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
}

.contact-note {
  font-size: 13.5px;
  color: var(--ink-soft);
}

.skills {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 18px;
  margin-top: clamp(50px, 8vh, 100px);
  text-align: left;
}

.sticky {
  background: #fff6cf;
  border-radius: 3px;
  padding: 16px;
  transform: rotate(var(--r, 0deg));
  box-shadow: var(--shadow);
}

.sticky:nth-child(even) {
  background: #e4f4ee;
}

.sticky h4 {
  margin: 0 0 6px;
  font-family: var(--display);
  font-size: 15px;
  color: var(--plum);
}

.sticky p {
  font-size: 13px;
  color: var(--ink-soft);
}

.foot {
  margin-top: clamp(50px, 8vh, 90px);
  padding: 20px 0;
  border-top: 2px dashed var(--line);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 13px;
  color: var(--ink-soft);
}

/* ===================================================================== fx */
.stage-fx {
  position: fixed;
  inset: 0;
  z-index: 9600;
  pointer-events: none;
  overflow: hidden;
}

.bit-confetti {
  position: absolute;
  width: 9px;
  height: 13px;
  border-radius: 2px;
}

.bit-confetti.is-char {
  width: auto;
  height: auto;
  background: none;
  font-style: normal;
  line-height: 1;
}

.trail-mark {
  position: absolute;
  font-style: normal;
  font-size: 14px;
  line-height: 1;
  translate: -50% -50%;
}

.speech {
  position: absolute;
  translate: -50% -100%;
  background: #fff;
  color: var(--plum-deep);
  font-family: var(--hand);
  font-size: clamp(20px, 2vw, 28px);
  padding: 8px 18px;
  border-radius: 22px;
  border: 2px solid var(--ink);
  white-space: nowrap;
  box-shadow: 4px 4px 0 var(--ink);
}

.speech::after {
  content: "";
  position: absolute;
  left: 22px;
  bottom: -11px;
  width: 16px;
  height: 16px;
  background: #fff;
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: rotate(45deg);
}

/* twins */
.egg-twins {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 3vw, 44px);
}

.egg-twins figure {
  margin: 0;
  background: #fff;
  padding: 10px 10px 0;
  width: min(260px, 38vw);
  box-shadow: 0 24px 50px rgba(60, 40, 20, 0.3);
}

.egg-twins figure:first-child {
  transform: rotate(-6deg);
}

.egg-twins figure.taller {
  transform: rotate(6deg);
}

.egg-twins img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

.egg-twins figcaption {
  font-family: var(--hand);
  font-size: 22px;
  text-align: center;
  padding: 8px 0 10px;
  color: var(--plum-deep);
}

/* ballet */
.egg-dancer {
  position: absolute;
  left: 0;
  bottom: 18vh;
  font-size: 64px;
  line-height: 1;
}

/* map */
.egg-map {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(58, 48, 38, 0.38);
  backdrop-filter: blur(3px);
  pointer-events: auto;
  padding: 20px;
}

.map-card {
  position: relative;
  width: min(860px, 94vw);
  background: #fbf3e2;
  background-image: radial-gradient(rgba(140, 115, 80, 0.1) 1px, transparent 1px);
  background-size: 14px 14px;
  border-radius: 8px;
  padding: 26px clamp(16px, 3vw, 34px) 30px;
  box-shadow: 0 30px 80px rgba(40, 25, 10, 0.4);
  transform: rotate(-1deg);
}

.map-close {
  position: absolute;
  top: 10px;
  right: 14px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: #fff;
  font-size: 22px;
  line-height: 1;
}

.map-svg {
  width: 100%;
  height: auto;
  margin-top: 6px;
}

.map-svg .land path {
  fill: #e6d6b8;
  stroke: #b89c6f;
  stroke-width: 2;
  stroke-dasharray: 5 6;
}

.map-svg .route {
  fill: none;
  stroke: var(--plum);
  stroke-width: 3;
  stroke-linecap: round;
}

.map-svg .pins path {
  fill: var(--rose);
  stroke: var(--ink);
  stroke-width: 1.5;
}

.map-stamp {
  position: absolute;
  right: 6%;
  bottom: 18%;
  display: grid;
  place-items: center;
  width: 120px;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 4px double var(--plum);
  color: var(--plum);
  font-family: var(--display);
  font-weight: 800;
  font-size: 36px;
  line-height: 0.9;
  background: rgba(255, 255, 255, 0.6);
  opacity: 0;
  transform: rotate(-12deg);
}

.map-stamp small {
  display: block;
  font-family: var(--hand);
  font-weight: 600;
  font-size: 18px;
}

.map-note {
  font-family: var(--hand);
  font-size: 22px;
  color: var(--ink-soft);
  text-align: center;
  margin-top: 8px;
}

/* cats */
.egg-kitten {
  position: absolute;
  left: 0;
  display: grid;
  justify-items: center;
}

.kitten-body {
  font-size: 46px;
  line-height: 1;
  display: block;
}

.kitten-name {
  font-family: var(--hand);
  font-size: 18px;
  color: var(--plum-deep);
  background: #fff;
  border-radius: 12px;
  padding: 0 8px;
  margin-top: -4px;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}

/* food */
.egg-snack {
  position: absolute;
  top: 0;
  font-size: 40px;
  line-height: 1;
}

/* crafts */
.egg-yarn {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.egg-ball {
  position: absolute;
  left: 0;
  top: 0;
  font-size: 54px;
  line-height: 1;
}

/* forky */
.egg-forky {
  position: absolute;
  left: 50%;
  bottom: 0;
  translate: -50% 0;
  display: flex;
  align-items: flex-start;
  gap: 4px;
}

.forky-body {
  position: relative;
  font-size: clamp(120px, 16vw, 200px);
  line-height: 1;
  display: block;
}

.forky-body .eye {
  position: absolute;
  top: 46%;
  width: 0.16em;
  height: 0.16em;
  border-radius: 50%;
  background: #fff;
  border: 3px solid var(--ink);
}

.forky-body .eye::after {
  content: "";
  position: absolute;
  inset: 22%;
  border-radius: 50%;
  background: var(--ink);
  animation: googly 0.6s ease-in-out infinite alternate;
}

.forky-body .eye.l {
  left: 30%;
}

.forky-body .eye.r {
  left: 50%;
  top: 43%;
}

.forky-body .brow {
  position: absolute;
  left: 30%;
  top: 37%;
  width: 0.4em;
  height: 4px;
  background: var(--rose);
  border-radius: 4px;
  transform: rotate(-8deg);
}

@keyframes googly {
  to {
    transform: translate(25%, 20%);
  }
}

.forky-say {
  font-family: var(--hand);
  font-size: 34px;
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: 20px;
  padding: 2px 16px;
  box-shadow: 4px 4px 0 var(--ink);
  margin-top: 20px;
}

/* coffee */
.egg-coffee {
  position: absolute;
  translate: -50% -50%;
  display: grid;
  justify-items: center;
}

.egg-coffee .cup {
  font-size: 80px;
  line-height: 1;
  grid-area: 1 / 1;
  align-self: end;
}

.egg-coffee .steam {
  grid-area: 1 / 1;
  width: 60px;
  translate: 0 -90px;
}

.egg-coffee .steam path {
  fill: none;
  stroke: rgba(123, 108, 89, 0.6);
  stroke-width: 3;
  stroke-linecap: round;
}

.egg-coffee .latte-heart {
  grid-area: 1 / 1;
  align-self: end;
  translate: 0 -24px;
  color: #fff;
  font-size: 28px;
  text-shadow: 0 0 6px rgba(120, 80, 40, 0.6);
}

/* bear */
.egg-night {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 70% 20%, rgba(70, 70, 140, 0.88), rgba(18, 16, 48, 0.94));
}

.egg-night .moon {
  position: absolute;
  top: 9%;
  right: 12%;
  font-size: 80px;
}

.egg-night .star {
  position: absolute;
  color: #fff6cf;
  font-style: normal;
  font-size: 14px;
  animation: twinkle 1.4s ease-in-out infinite;
}

@keyframes twinkle {
  50% {
    opacity: 0.2;
    transform: scale(0.6);
  }
}

.egg-night .bear {
  position: absolute;
  left: 50%;
  bottom: 18%;
  translate: -50% 0;
  font-size: clamp(110px, 14vw, 170px);
}

.egg-night .zz {
  position: absolute;
  left: 54%;
  bottom: 38%;
  font-family: var(--hand);
  font-size: 46px;
  color: #fff;
}

.egg-night .night-note {
  position: absolute;
  left: 50%;
  bottom: 10%;
  translate: -50% 0;
  font-family: var(--hand);
  font-size: 30px;
  color: #fff6cf;
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .sh-blob,
  .doodle {
    animation: none;
  }
}
