@font-face { font-family: Fredoka; src: url(../fonts/fredoka.woff2) format("woff2"); font-weight: 300 700; font-display: swap; }
@font-face { font-family: Nunito; src: url(../fonts/nunito.woff2) format("woff2"); font-weight: 200 1000; font-display: swap; }

/* The page's own styles. scrollcraft.css (loaded first, never edited) is the mechanism and the taste floor; this file
   themes it with tokens and styles our markup. It never restyles .sc-stage, .sc-copy or a [data-sc-*] selector. */
:root {
  --lilac: #C8A2C8; --lavender: #967BB6; --amethyst: #9966CC; --violet: #6F2DA8; --indigo: #4B0082;
  --paper: #FBF7FD; --dawn: #EEE3F6; --gold: #F4C95D; --dusk: #2D0868; --night: #1E0840;
  --pad-t: max(16px, env(safe-area-inset-top)); --pad-b: max(16px, env(safe-area-inset-bottom));
  --pad-l: max(20px, env(safe-area-inset-left)); --pad-r: max(20px, env(safe-area-inset-right));

  /* scroll-craft's six colour roles and two faces */
  --sc-canvas: var(--paper); --sc-surface: #fff;
  --sc-ink: var(--indigo); --sc-ink-soft: var(--violet);
  --sc-accent: var(--gold); --sc-accent-ink: var(--indigo);
  --sc-font-display: Fredoka, system-ui, sans-serif;
  --sc-font-text: Nunito, system-ui, sans-serif;
  --sc-shadow-color: 275 100% 15%;
}
html { background: var(--night); }
body { font-size: 18px; }
h1, h2, .btn, .two, dt, dd { font-family: var(--sc-font-display); font-weight: 700; line-height: 1.05; letter-spacing: -0.01em; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(44px, 12.5vw, 76px); }
h2 { font-size: clamp(30px, 8.5vw, 52px); }
p { margin: 0; }
.column { width: min(100%, 34rem); margin: 0 auto; padding: 0 var(--pad-r) 0 var(--pad-l); }

/* One story on one pinned stage (js/story.js places and moves everything on it, in px). It's laid out in the small
   viewport (svh, the phone browser's bars showing) but reaches down to the large one (lvh, bars hidden), so nothing
   shows below it when they hide; the negative margin keeps the page as long as the small viewport makes it. */
.story { position: relative; }
.stage { position: sticky; top: 0; height: 100lvh; margin-bottom: calc(100svh - 100lvh); overflow: clip; background: var(--dawn); }
.stage:not(.built) > * { visibility: hidden; } /* until js/story.js has placed it all: dawn, then the garden, nothing moving */
.svh { position: absolute; height: 100svh; } /* js/story.js measures the small viewport with it */
.stage > *, .world > * { position: absolute; }
.world, .words { inset: 0 auto auto 0; z-index: 0; }
.words { z-index: 5; } /* in front of the caterpillar: it crawls behind the paper tags */
.words > :not(.memory) { position: absolute; }
.world img { max-width: none; height: auto; }
.world > :is(.sky, .hills, .wisteria, .meadow, .blossoms) > img { display: block; width: 100%; }
.world .vine img { position: static; display: block; width: 100%; height: auto; }
.world .ground { background: linear-gradient(#2C0968, var(--dusk)); }
.world .meadow > img { -webkit-mask: linear-gradient(#000 55%, #0000); mask: linear-gradient(#000 55%, #0000); }
.world .blossoms > img { -webkit-mask: linear-gradient(#000 70%, #0000); mask: linear-gradient(#000 70%, #0000); }
.world .foliage { background: top / 100% auto repeat-y; } /* repeats without a seam (art.py tile) */
.world .foliage::before { content: ""; position: absolute; left: 0; bottom: 100%; width: 100%; aspect-ratio: 2 / 3; background: top / 100% auto no-repeat; } /* the first tile: the foliage starts here */
.later .world .foliage { background-image: url(../img/foliage.webp); } /* downloaded once the first screen has loaded (js/story.js) */
.later .world .foliage::before { background-image: url(../img/foliage-top.webp); }

/* On a wide screen the garden, the vine's foliage and the evening carry on past the column they were drawn for: each
   layer's sides (art.py widen) hang off its edges, 1.75 times its width, and overlap its outer quarter, where they
   blend into it; where Codex drew them taller, they reach above it by --up of its height (art.py prints it). Phones
   never load them, upright or turned sideways. */
@media (min-aspect-ratio: 2 / 3) and (min-height: 600px) {
  :is(.world > :is(.sky, .hills, .wisteria, .meadow, .blossoms), .world .sides, .evening .scene)::before,
  :is(.world > :is(.sky, .hills, .wisteria, .meadow, .blossoms), .world .sides, .evening .scene)::after {
    content: ""; position: absolute; z-index: 1; top: calc(-100% * var(--up, 0)); width: 174.96%; height: calc(100% * (1 + var(--up, 0)));
    background: top / 100% 100% no-repeat; } /* over the layer, even masked */
  :is(.world > :is(.sky, .hills, .wisteria, .meadow, .blossoms), .world .sides, .evening .scene)::before { right: 74.96%; }
  :is(.world > :is(.sky, .hills, .wisteria, .meadow, .blossoms), .world .sides, .evening .scene)::after { left: 74.96%; }
  .world .hills { --up: .0019; } .world .meadow { --up: .0025; } .world .blossoms { --up: .0149; }
  /* the layers' fading feet, at the same height */
  .world .meadow::before, .world .meadow::after {
    -webkit-mask: linear-gradient(#000 calc(100% * (var(--up, 0) + .55) / (1 + var(--up, 0))), #0000); mask: linear-gradient(#000 calc(100% * (var(--up, 0) + .55) / (1 + var(--up, 0))), #0000); }
  .world .blossoms::before, .world .blossoms::after {
    -webkit-mask: linear-gradient(#000 calc(100% * (var(--up, 0) + .7) / (1 + var(--up, 0))), #0000); mask: linear-gradient(#000 calc(100% * (var(--up, 0) + .7) / (1 + var(--up, 0))), #0000); }
  .world .sky::before { background-image: url(../img/wide/s1-sky-l.webp); }
  .world .sky::after { background-image: url(../img/wide/s1-sky-r.webp); }
  .world .hills::before { background-image: url(../img/wide/s1-hills-l.webp); }
  .world .hills::after { background-image: url(../img/wide/s1-hills-r.webp); }
  .world .wisteria::before { background-image: url(../img/wide/s1-wisteria-l.webp); }
  .world .wisteria::after { background-image: url(../img/wide/s1-wisteria-r.webp); }
  .world .meadow::before { background-image: url(../img/wide/s1-meadow-l.webp); }
  .world .meadow::after { background-image: url(../img/wide/s1-meadow-r.webp); }
  .world .blossoms::before { background-image: url(../img/wide/s1-blossoms-l.webp); }
  .world .blossoms::after { background-image: url(../img/wide/s1-blossoms-r.webp); }
  /* the foliage's start with its first tile, a frame (1.5 widths) above it, and grow in from the dark */
  .world .sides { position: absolute; inset: 0; margin-top: -150%; }
  .world .sides::before, .world .sides::after { background: top / 100% auto repeat-y; -webkit-mask: linear-gradient(#0000, #000 4%); mask: linear-gradient(#0000, #000 4%); }
  .later .world .sides::before { background-image: url(../img/wide/foliage-l.webp); }
  .later .world .sides::after { background-image: url(../img/wide/foliage-r.webp); }
  .later .evening .scene::before { background-image: url(../img/wide/evening-l.webp); }
  .later .evening .scene::after { background-image: url(../img/wide/evening-r.webp); }
}
.night { inset: 0; z-index: 2; background: var(--dusk); opacity: 0; pointer-events: none; }
.silk { z-index: 3; width: 2px; margin-left: -1px; background: rgb(200 162 200 / .8); }
.caterpillar { z-index: 4; left: 0; top: 0; }
.caterpillar img { position: absolute; max-width: none; height: auto; }
.film { z-index: 6; transform-origin: 50% 30%; }
.film > * { position: absolute; max-width: none; height: auto; }
/* drawings wait hidden and fully transparent, so fading one out never shows it (js/story.js shows one at a time) */
.change img { position: absolute; inset: 0 auto auto 0; width: 100%; height: auto; visibility: hidden; opacity: 0; }
.film .flyer img { display: block; width: 100%; height: auto; visibility: hidden; opacity: 0; }

/* words on the vine */
.words .scrim { background: radial-gradient(var(--rx, 60%) 50% at 50% 50%, rgb(251 247 253 / .82), rgb(251 247 253 / 0)); pointer-events: none; }
.words .title { text-align: center; }
.title h1 { max-width: 9em; margin: 0 auto; text-shadow: 0 2px 0 var(--paper), 0 4px 14px rgb(75 0 130 / .25); }
.greet { font-weight: 800; font-size: 19px; margin-bottom: 6px; }
.line { font: 700 clamp(21px, 5.8vw, 30px)/1.25 var(--sc-font-display); color: #fff; text-shadow: 0 2px 10px rgb(30 8 64 / .6); margin: 0; }
/* the words on the vine hang on paper tags, so they read over any leaf */
.words .intro, .memory figcaption { font: 700 clamp(17px, 4.6vw, 22px)/1.25 var(--sc-font-display); color: var(--indigo); background: var(--paper); padding: 10px 14px; border-radius: 14px; box-shadow: 0 2px 0 rgb(75 0 130 / .25), 0 8px 18px rgb(30 8 64 / .35); }
.memory { margin: 0; }
.memory .pic, .memory figcaption { position: absolute; }
/* her baby pictures, a paper medallion on each leaf */
.memory .pic { max-width: none; }
.hush { z-index: 7; left: 20px; right: 20px; bottom: calc(12svh + 100lvh - 100svh); text-align: center; }

/* her, the 2, and the words */
.her { z-index: 7; }
.her img { position: absolute; inset: 0; width: 100%; height: 100%; transform-origin: 50% 100%; }
.her .glow { inset: -20% -40% -10%; background: radial-gradient(closest-side, rgb(244 201 93 / .35), rgb(244 201 93 / 0)); }
.two { z-index: 8; right: max(5vw, calc(50% - 300px)); top: calc(var(--pad-t) + 6svh + 2.2 * clamp(30px, 8.5vw, 52px)); margin: 0; font-size: clamp(110px, 30vw, 190px); line-height: 1; color: var(--gold); -webkit-text-stroke: 5px var(--indigo); paint-order: stroke fill; text-shadow: 5px 7px 0 rgb(0 0 0 / .3); }
.burst { z-index: 6; /* bursts out from behind her */ left: 0; width: 100%; pointer-events: none; -webkit-mask: linear-gradient(transparent, #000 18%); mask: linear-gradient(transparent, #000 18%); }
.wings { z-index: 9; left: var(--pad-l); right: var(--pad-r); top: calc(var(--pad-t) + 4svh); text-align: center; color: #fff; text-shadow: 0 3px 0 var(--indigo); }

/* after the story: the garden at evening, ready for the party, behind the details and the close. Laid out in the small
   viewport like the story; its foot fades into its own colour, which carries on below it when the phone's bars hide */
.evening { inset: 0; z-index: 10; background: #3C1C73; }
.evening > .scene { position: absolute; } /* sized with the garden (js/story.js) */
.evening .scene > img { display: block; width: 100%; height: auto; }
.evening .scene > img, .evening .scene::before, .evening .scene::after { -webkit-mask: linear-gradient(#000 94%, #0000); mask: linear-gradient(#000 94%, #0000); }
.track { pointer-events: none; }

/* 4 · Clarity: the details on an invitation card, a paper one on a lilac one turned a little, with a gold frame and a
   paper butterfly on its top edge */
.details { position: relative; z-index: 1; color: #fff; padding: 8svh 0 8svh; overflow-x: clip; } /* she leaves as its first line arrives (js/story.js); the turned card never widens the page */
.details h2, .countdown { text-align: center; text-shadow: 0 3px 0 var(--indigo); }
.card { margin-top: calc(5svh + 40px); border-radius: 22px; background: linear-gradient(160deg, var(--lilac), var(--lavender)); rotate: -2.5deg; box-shadow: 0 16px 34px rgb(30 8 64 / .5); }
.card .paper { position: relative; rotate: 2.5deg; padding: 46px 26px 26px; border-radius: 20px; color: var(--indigo); background: radial-gradient(120% 80% at 30% 0%, #fff, var(--paper) 60%, #F3EAF8); box-shadow: 0 2px 0 rgb(75 0 130 / .2), 0 6px 14px rgb(30 8 64 / .25); }
.card .paper::before { content: ""; position: absolute; inset: 9px; border: 3px double var(--gold); border-radius: 14px; pointer-events: none; } /* the gold frame */
.card .ornament { position: absolute; left: 50%; top: -34px; /* within the card's top margin */ width: min(70%, 230px); translate: -50% 0; filter: drop-shadow(0 3px 3px rgb(30 8 64 / .3)); }
dl { margin: 0; display: grid; gap: 3svh; }
dt { display: flex; align-items: center; gap: 8px; font-size: 15px; letter-spacing: .1em; text-transform: uppercase; color: var(--violet); margin-bottom: 6px; }
dt img { width: auto; height: 30px; }
dd { margin: 0; font-size: clamp(20px, 5.4vw, 26px); line-height: 1.25; }
.swatches { display: flex; gap: 6px; margin-top: 10px; }
.swatches i { width: 30px; height: 14px; border-radius: 7px; box-shadow: 0 0 0 1px rgb(75 0 130 / .2); }
.swatches i:nth-child(1) { background: var(--lilac); } .swatches i:nth-child(2) { background: var(--lavender); }
.swatches i:nth-child(3) { background: var(--amethyst); } .swatches i:nth-child(4) { background: var(--violet); }
.swatches i:nth-child(5) { background: var(--indigo); }
.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4svh; }
.countdown { margin-top: 4svh; font: 700 22px var(--sc-font-display); color: var(--gold); }
.btn { display: inline-block; padding: 14px 24px; border-radius: 999px; background: var(--violet); color: #fff; font-size: 20px; text-decoration: none; border: 3px solid var(--gold); box-shadow: 0 4px 0 var(--indigo); transition: transform 120ms var(--sc-ease-out), box-shadow 120ms var(--sc-ease-out); }
.btn:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--indigo); }
.btn.gold { background: var(--gold); color: var(--indigo); border-color: var(--indigo); font-size: 22px; }

/* 5 · Warmth: the last screen of the page, over the evening garden */
.close { position: relative; z-index: 1; display: flex; flex-direction: column; min-height: 100svh; color: #fff; text-align: center; padding: 14svh 0 var(--pad-b); }
.close .column { display: grid; justify-items: center; gap: 18px; }
.close .coming { margin-block: 12px; } /* room for the butterflies that land on its edges */
.close .flock { z-index: 0; }
.close h2 { text-shadow: 0 3px 0 var(--indigo); }
.close .column p { font-weight: 800; text-shadow: 0 1px 4px var(--indigo); }
.close .cake { margin: auto auto 2svh; width: auto; height: 25svh; filter: drop-shadow(0 6px 10px rgb(30 8 64 / .5)); } /* at the foot of the screen, in the evening meadow */
.sign { text-align: center; font-size: 15px; font-weight: 700; }

/* small fluttering butterflies: two half-images flapping in CSS 3D, drifting on CSS keyframes (compositor only) */
.flock { position: absolute; inset: 0; overflow: clip; pointer-events: none; } /* one drifting off the edge flies out of view, never widens the page */
.bf { position: absolute; left: var(--x); top: var(--y); width: var(--s); aspect-ratio: 1024 / 779; perspective: 300px; animation: drift var(--d) ease-in-out var(--dl) infinite alternate; }
.bf i { position: absolute; top: 0; width: 50%; height: 100%; background: var(--img) no-repeat; background-size: 200% 100%; }
.bf .l { left: 0; transform-origin: 100% 50%; animation: flap-l var(--f) ease-in-out infinite alternate; }
.bf .r { right: 0; background-position: 100% 0; transform-origin: 0 50%; animation: flap-r var(--f) ease-in-out infinite alternate; }
@keyframes flap-l { from { transform: rotateY(5deg); } to { transform: rotateY(68deg); } }
@keyframes flap-r { from { transform: rotateY(-5deg); } to { transform: rotateY(-68deg); } }
/* the garden's butterflies: placed and turned by js/butterflies.js, frame by frame, in one of three layers */
.friends { inset: 0; pointer-events: none; }
.stage > .friends { z-index: 4; }
.close .friends { position: absolute; z-index: 1; overflow: clip; }
.bf.friend { left: 0; top: 0; animation: none; }
@keyframes drift { from { transform: translate(0, 0) rotate(var(--r0)); } to { transform: translate(var(--dx), var(--dy)) rotate(var(--r1)); } }

/* the engine never arrived: show what it would have revealed */
.no-sc [data-sc-cue], .no-sc [data-sc-in], .no-sc [data-sc-stagger] > * { opacity: 1; transform: none; }
