@property --winter { syntax: '<number>'; inherits: true; initial-value: 0.5; }
:root {
  --sky: #8f76a6;
  --bg: #33284a;
  --verge-c: #3d3454;
  --ink: #f3efe9;
  --muted: #cfc6d2;
  --accent: #9fc7b8;
  --accent-ink: #141a18;

  --copper: #6f8a7e;
  --copper-dk: #56705f;
  --stucco: #e3c2b0;
  --column: #f4ead9;
  --granite: #4a4a54;
  --limestone: #8d8779;
  --trim: #9c6a44;
  --ochre: #c9a35a;
  --glow: #f2c56a;
  --snow-c: #efe4e6;
  --car: #3f4d40;   /* Porsche Oak Green Metallic */
  --car-dk: #2c372e;
  --car-hi: #7d8f7c;
  --rim: #5d6468;
  --rim-hi: #b9bfc2;
  --mullion: #7a6650;
  --sun: #fff0c4;

  --skin-h: #f2d2bc;
  --skin-k: #f5d9c6;
  --hair-h: #8a623a;
  --hair-k: #b98a52;
  --suit: #2b2f45;
  --suit-dk: #20243a;
  --shirt: #f6f2ea;
  --tie: #8f3a24;
  --dress: #efe7dc;
  --dress-dk: #e2d6c6;
  --stole: #faf7f2;

  --step-small: 0.9375rem;
  --step-body: clamp(0.95rem, min(1.25vw, 2.1vh), 1.125rem);
  --step-lead: clamp(1.0625rem, min(1.7vw, 2.6vh), 1.5rem);
  --step-display: clamp(2.25rem, min(5.4vw, 7.4vh), 6rem);
  --step-date: clamp(1.625rem, min(3.4vw, 4.6vh), 3.25rem);
  --step-giant: min(15vw, 21vh);

  --m: clamp(16px, 2vw, 32px);
  --road: 27vh;

  --winter: 0.5;
  animation: snowfall-builds 150s linear 1s both;
  --snow: clamp(0, calc((var(--winter) - 0.15) * 2.4), 1);

  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; }
body {
  background: var(--sky);
  background-image: radial-gradient(95vw 75vh at 48vw calc(100% - var(--road)), #ffe2a6 0%, #f8c48e 30%, #eca59a 58%, #b98fb0 82%, #8f76a6 100%); /* taste-skill-ignore */
  color: var(--ink);
  font-family: "Clash Grotesk", "Helvetica Neue", Arial, sans-serif;
  font-weight: 400;
  font-size: var(--step-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
p, h1 { margin: 0; }
a { color: inherit; }
::selection { background: var(--accent); color: var(--accent-ink); }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 4px; }
.defs { position: absolute; width: 0; height: 0; }
.phone-br { display: none; }

.stage { position: fixed; inset: 0; overflow: hidden; }

/* ---------- the scene ----------
   One drawing on a 1440 x 900 stage. --u is one stage unit; every element is placed in units, so the
   composition scales with the viewport width like a single vector picture. Portrait views zoom into
   the right-hand 940 units of the same stage. */
:root {
  --u: min(calc(100vw / 1440), calc(100vh / 900));
  /* the exploded view: how far the depth layers slide apart from the villa; zero at 1440 wide,
     positive when wider (apart), negative when narrower (together) */
  --spread: clamp(-130px, calc((100vw - 1440px) * 0.45), 340px);
}
.scene { position: absolute; inset: 0; }
.scene-inner {
  position: absolute; right: 0; bottom: var(--road);
  width: calc(1440 * var(--u)); height: calc(900 * var(--u));
}
.scene svg, .scene div { position: absolute; }
.scene-inner > * { transition: translate .8s cubic-bezier(.2, .8, .2, 1); }
.sun { translate: calc(-1 * var(--spread)) 0; }
.skyline { translate: calc(-1 * var(--spread)) 0; }
.maple { translate: calc(-0.55 * var(--spread)) 0; }
.lamp { translate: calc(-0.55 * var(--spread)) 0; }
.car-wrap { translate: calc(-0.18 * var(--spread)) 0; }
.couple { translate: calc(-0.06 * var(--spread)) 0; }
.oak { translate: calc(0.22 * var(--spread)) 0; }
.rowan { translate: calc(0.28 * var(--spread)) 0; }

.sun { left: calc(560 * var(--u)); bottom: calc(120 * var(--u)); width: calc(140 * var(--u)); }
.skyline { left: calc(490 * var(--u)); bottom: calc(18 * var(--u)); height: calc(270 * var(--u)); width: auto; aspect-ratio: 1600 / 812.1; }
.villa { right: calc(72 * var(--u)); bottom: calc(18 * var(--u)); height: calc(558 * var(--u)); aspect-ratio: 620 / 560; overflow: visible; }
.lamp { right: calc(985 * var(--u)); bottom: calc(9 * var(--u)); height: calc(324 * var(--u)); aspect-ratio: 60 / 320; }
.tree { aspect-ratio: 400 / 500; overflow: visible; transform-origin: 50% 100%; will-change: transform; animation: sway var(--sway, 7s) ease-in-out infinite alternate; }
.oak { right: calc(-216 * var(--u)); bottom: calc(18 * var(--u)); height: calc(522 * var(--u)); }
.maple { left: calc(533 * var(--u)); bottom: calc(9 * var(--u)); height: calc(450 * var(--u)); }
.rowan { right: calc(-58 * var(--u)); bottom: calc(4 * var(--u)); height: calc(342 * var(--u)); }
.verge { left: 0; width: 100%; bottom: calc(var(--road) - 2 * var(--u)); height: calc(36 * var(--u)); overflow: visible; z-index: -1; }
/* the car is always the front-most thing on the page: above the people, the settled snow and the falling weather */
.car-wrap { z-index: 50; left: calc(468 * var(--u)); bottom: calc(-23 * var(--u)); width: calc(302 * var(--u)); }
.car { position: static !important; display: block; width: 100%; height: auto; overflow: visible; }
.guests { left: calc(760 * var(--u)); bottom: calc(-6 * var(--u)); height: calc(118 * var(--u)); aspect-ratio: 340 / 150; overflow: visible; animation: fadein 1s ease 2.6s both; }
.couple { left: calc(835 * var(--u)); bottom: calc(-16 * var(--u)); height: calc(144 * var(--u)); aspect-ratio: 160 / 200; }
.kerb { left: 0; right: 0; bottom: var(--road); height: 2px; background: #4a4060; z-index: -1; }
.road { position: absolute; left: 0; right: 0; bottom: 0; height: var(--road); background: var(--bg); z-index: -1; }
/* the bog below the road: Heinsoo, literally hay-bog. Hummocks recede toward the road; one pool mirrors the sky */
.asphalt { position: absolute; left: 0; right: 0; bottom: calc(var(--road) - 30 * var(--u)); height: calc(30 * var(--u)); background: #d6c3d1; z-index: -1; }
.bog { position: absolute; left: 0; bottom: 0; width: 100%; height: calc(var(--road) - 30 * var(--u)); z-index: -1; }
/* the red carpet starts under the couple, wherever they stand (scene.js sets --carpet-x) */
.carpet { position: absolute; top: calc(100% - var(--road) + 30 * var(--u)); left: calc(var(--carpet-x, 62vw) - var(--carpet-w) / 2); --carpet-w: calc((var(--road) - 30 * var(--u)) * 640 / 210); width: var(--carpet-w); height: calc(var(--road) - 30 * var(--u)); z-index: -1; }

.snow { fill: var(--snow-c); opacity: var(--snow); transition: opacity .8s; }
.tree .snow { fill: none; }
.ice { fill: #d6e4ec; opacity: calc(var(--snow) * .92); transition: opacity .8s; }
.ice-hi { fill: none; stroke: #fff; stroke-width: .9; stroke-linecap: round; opacity: calc(var(--snow) * .7); }
.win { fill: var(--glow); }
.win > * { stroke: var(--mullion); stroke-width: 2; }

/* ---------- the words ---------- */
.weather, .settled { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

.bar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  display: flex; justify-content: space-between; align-items: center;
  padding: calc(var(--m) * 0.9) var(--m);
  font-size: 0.9375rem;
}
.bar a { text-decoration: none; }
.bar nav { display: flex; gap: 28px; }
.bar a { position: relative; padding: 6px 0; }
.bar a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 2px; height: 2px; background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform .35s var(--ease-out); }
.bar a:hover::after, .bar a:focus-visible::after { transform: scaleX(1); }

.invite {
  position: absolute; left: var(--m); top: 13vh; z-index: 2;
  width: min(40vw, 620px);
}
h1 {
  font-size: var(--step-display);
  font-weight: 400;
  line-height: 0.98;
  letter-spacing: -0.03em;
}
.surname { display: block; font-size: 1.32em; line-height: .9; letter-spacing: -.035em; }
.given { display: block; margin-top: .22em; font-size: .5em; line-height: 1.1; letter-spacing: -.015em; white-space: nowrap; }
.lead { margin-top: 2.4vh; font-size: var(--step-lead); line-height: 1.35; max-width: 30ch; }
.date { margin-top: 3.6vh; font-size: var(--step-date); font-weight: 500; line-height: 1; letter-spacing: -0.02em; }
.where { margin-top: 1.4vh; font-size: var(--step-lead); line-height: 1.3; }
.act { margin-top: 3vh; display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.act span { color: var(--ink); }
.button {
  display: inline-flex; align-items: center; height: 52px; padding: 0 26px;
  background: var(--accent); color: var(--accent-ink);
  font-weight: 500; text-decoration: none;
  transition: background-color .2s, transform .15s;
}
.button:hover { background: #b6d6ca; }
.button:active { transform: translateY(1px) scale(.98); }

.road-text {
  z-index: 2;
  position: absolute; left: 0; right: 0; bottom: 0; height: var(--road);
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--m);
  padding: 0 var(--m) calc(var(--m) * 0.8);
}
.family {
  color: #d9d2d6;
  font-size: var(--step-giant);
  line-height: 0.74;
  letter-spacing: -0.045em;
  margin-left: -0.04em;
  white-space: nowrap;
}
.family span { display: block; }
.dial { width: min(30vw, 420px); padding-bottom: 0.4vh; }
.count { font-size: var(--step-body); line-height: 1.4; }
.credit { margin-top: 12px; font-size: var(--step-small); color: var(--muted); }
.hint-phone { display: none; }


/* ---------- motion ----------
   The opening is a build in depth order, each layer arriving with a strong ease-out and overlapping the
   next: sun and Old Town, the villa settling onto the ground, the trees growing back to front, the lamp,
   then the car driving in and braking, the windows flickering on, the headlights switching off once
   parked, and the two of them stepping out. Text arrives early so the message reads at once. */
:root { --ease-expo: cubic-bezier(.16, 1, .3, 1); --ease-travel: cubic-bezier(.1, .8, .2, 1); }

@keyframes rise { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes arrive { from { opacity: 0; transform: translateY(calc(28 * var(--u))); } to { opacity: 1; transform: none; } }
@keyframes grow { from { opacity: 0; transform: translateY(calc(10 * var(--u))) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes drive { from { transform: translateX(-330%); } to { transform: none; } }
@keyframes roll { from { transform: rotate(2110deg); } to { transform: none; } }
@keyframes nosedip { 0%, 84% { transform: none; } 92% { transform: rotate(.8deg); } 100% { transform: none; } }
@keyframes brake { 0%, 100% { filter: none; } 20%, 70% { filter: brightness(2.2) saturate(1.3); } }
@keyframes lightson { 0% { opacity: .12; } 45% { opacity: .9; } 60% { opacity: .4; } 100% { opacity: 1; } }
@keyframes lampon { 0% { opacity: 0; } 40% { opacity: .22; } 55% { opacity: .08; } 100% { opacity: .2; } }
@keyframes beamoff { to { opacity: 0; } }
@keyframes dim { to { opacity: .35; } }
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
@keyframes dogrun { from { transform: translateX(calc(100vw - var(--carpet-x, 62vw))); } to { transform: none; } }
@keyframes gallop { 0% { opacity: 1; } 16.667% { opacity: 0; } }
@keyframes appear { to { opacity: 1; } }
@keyframes standwin { 0%, 88% { opacity: 1; } 100% { opacity: 0; } }
@keyframes sitin { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
@keyframes bump { from { transform: scaleX(.3); } to { transform: none; } }
@keyframes rollout { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
}
}
@keyframes twinkle { from { opacity: .55; } to { opacity: 1; } }
@keyframes glint { from { opacity: .25; } to { opacity: .9; } }
@keyframes toss { 0% { transform: translate(0, 0); opacity: 0; } 15% { opacity: 1; } 100% { transform: translate(14px, 26px); opacity: 0; } }
@keyframes snowfall-builds { from { --winter: 0.36; } to { --winter: 0.72; } }
@keyframes icicle { from { transform: scaleY(.12); } to { transform: none; } }
@keyframes sway { from { transform: rotate(-0.9deg); } to { transform: rotate(0.9deg); } }
@keyframes breathe { from { opacity: .10; } to { opacity: .22; } }

.rise { animation: rise .8s var(--ease-out) both; animation-delay: calc(.1s + var(--d) * 70ms); }
.sun { animation: arrive 1.4s var(--ease-expo) 0s both; }
.skyline { animation: arrive 1.2s var(--ease-expo) .25s both; }
.villa { transform-origin: 50% 100%; animation: grow 1.2s var(--ease-expo) .5s both; }
.tree image { transform-box: fill-box; transform-origin: 50% 100%; animation: grow 1.1s var(--ease-expo) both; }
.oak image { animation-delay: .7s; }
.maple image { animation-delay: .9s; }
.rowan image { animation-delay: 1.1s; }
.lamp { animation: arrive .9s var(--ease-expo) 1s both; }
.halo { animation: lampon .6s ease 2.3s both, breathe 3.5s ease-in-out 3s infinite alternate; }
.car-wrap { animation: drive 3s var(--ease-travel) 1.4s both; }
.spin { transform-box: fill-box; transform-origin: center; animation: roll 3s var(--ease-travel) 1.4s both; }
.car { transform-origin: 78% 92%; animation: nosedip 3s linear 1.4s both; }
.tl { animation: brake 1.2s ease 3.9s both; }
.beam { animation: beamoff 1s ease 5.6s both; }
.hl { animation: dim 1s ease 5.6s both; }
.win { animation: lightson .7s ease both; animation-delay: calc(1.6s + var(--i) * 90ms); }
.couple { animation: fadein 1s ease 2.4s both; }
/* the carpet rolls out from the couple's feet toward the viewer, revealing the lanterns as it goes */
.beagle { position: absolute; z-index: 0; width: calc(46 * var(--u)); left: calc(var(--carpet-x, 62vw) + 14 * var(--u)); bottom: calc(var(--road) - 24 * var(--u)); animation: dogrun 1.8s cubic-bezier(.2, .55, .3, 1) 4s both; }
.beagle .gf, .beagle .stand, .beagle .sit { opacity: 0; }
/* six-frame gallop: each frame is shown for one sixth of a 0.36 s stride, in turn, until the dog sits */
.beagle .gf0 { animation: gallop 0.36s step-end 4.00s 4.167, gallop .6s step-end 5.5s 1; }
.beagle .gf1 { animation: gallop 0.36s step-end 4.06s 4.000, gallop .6s step-end 5.6s 1; }
.beagle .gf2 { animation: gallop 0.36s step-end 4.12s 3.833, gallop .6s step-end 5.7s 1; }
.beagle .gf3 { animation: gallop 0.36s step-end 4.18s 3.667, gallop .6s step-end 5.8s 1; }
.beagle .gf4 { animation: gallop 0.36s step-end 4.24s 3.500, gallop .6s step-end 5.9s 1; }
.beagle .gf5 { animation: gallop 0.36s step-end 4.30s 3.333, gallop .6s step-end 6.0s 1; }
.beagle .stand { animation: standwin .75s linear 6.1s forwards; }
.beagle .sit { animation: sitin .35s ease-out 6.7s forwards; }
.bump { transform-box: fill-box; transform-origin: 100% 50%; animation: bump 4.5s cubic-bezier(.45, 0, .25, 1) 2.4s both; }
.carpet { animation: rollout 1.5s var(--ease-expo) 2.5s both; }
.toss { animation: toss 2.6s ease-out 6s infinite; }
.icicle { transform-box: fill-box; transform-origin: 50% 0; animation: icicle 9s cubic-bezier(.3, 0, .3, 1) calc(3s + var(--g) * 70s) both; }
.bulb { animation: twinkle 1.6s ease-in-out infinite alternate; animation-delay: calc(var(--k) * -1.6s); }
.tree use, .tree circle, .verge use { transition: opacity .7s; }
.scene .off { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  :root { animation: none; }
  .rise, .sun, .skyline, .villa, .tree image, .lamp, .halo, .car-wrap, .spin, .car, .tl, .beam, .hl, .win, .icicle, .couple, .guests, .carpet, .beagle, .beagle g, .bump, .toss, .tree, .bulb, .glint rect { animation: none; }
  .scene-inner > * { transition: none; }
  .beagle .sit { opacity: 1; }
}

/* ---------- portrait: phones and tall tablets ---------- */
@media (max-aspect-ratio: 1/1) {
  :root {
    --road: 22vh;
    --u: calc(100vw / 940); --spread: 0px;
    --step-display: clamp(2.25rem, min(11vw, 5.8vh), 4.5rem);
    --step-giant: min(20vw, 10vh);
    --step-date: clamp(1.5rem, 7vw, 2.5rem);
    --step-lead: clamp(1rem, 0.9rem + 0.8vw, 1.375rem);
  }
  .bar .cal { display: none; }
  .maple, .lamp { display: none; }
  /* the Old Town runs from the viewport's left edge, in front of nothing */
  .skyline { translate: calc(950 * var(--u) - 100vw) 0; }
  .sun { translate: calc(-120 * var(--u)) calc(-110 * var(--u)); }
  .invite { top: 7vh; width: auto; right: var(--m); }
  .lead { max-width: 34ch; margin-top: 1.8vh; }
  .date { margin-top: 2.6vh; }
  .act { margin-top: 2.4vh; gap: 12px 18px; }
  .road-text { flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 1.2vh; padding-top: 1.6vh; }
  .dial { width: auto; padding: 0; }
  .count { font-size: var(--step-small); }
}

@media (max-aspect-ratio: 1/1) and (max-width: 600px) {
  :root { --step-display: clamp(2rem, 9.5vw, 2.75rem); --u: calc(100vw / 1000); --road: 20vh; }
  .invite { top: 6vh; }
  .hint-phone { display: block; margin-top: 4px; }
  .given { font-size: .56em; }
  .act { flex-direction: column; align-items: flex-start; gap: 10px; }
  .credit { display: none; }
}
