/* Halloween template 1 (Halloween party invitation). All styles for index.html.
   The look is a stop-motion picture book: everything moves in held poses (steps(), never easing),
   and outlines "boil" because script.js cycles html.b0 / .b1 / .b2 at 8fps like redrawn frames. */

/* ── FONTS ───────────────────────────────────────────────
   block, not swap: the loader covers the block period, swap would re-flow the page. */
@font-face {
  font-family: "Dachi the Lynx";
  src: url("fonts/dachi-the-lynx.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
/* Latin display for the HALLOWEEN PARTY title: chunky, bouncy, hand-cut, sits beside Dachi's weight */
@font-face {
  font-family: "Chewy";
  src: url("fonts/chewy.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "Glaho";
  src: url("fonts/glaho-drunk.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

:root {
  --vh: 1vh; /* JS off = original value; the inline head script pins it */

  /* page = dark plum-black card stock; cards = cream cut paper laid on top of it */
  --night: #281d23;
  --night-dk: #1b1418;
  --chalk: #f1e6d3;       /* text straight on the dark stock */
  --chalk-soft: #c2ab9c;
  --ember: #e2445c;       /* red for text on dark (4.2:1, large type only) */

  --paper: #efe5d2;
  --paper-lt: #f8f1e3;
  --paper-dk: #e4d6bd;
  --ink: #3a2626;         /* text and outlines on cream cards */
  --ink-soft: #6c5250;
  --blood: #b3122e;
  --blood-dk: #8a0c22;
  --blush: #f19a92;

  --display: "Dachi the Lynx", "Glaho", sans-serif;
  --hand: "Glaho", "Dachi the Lynx", sans-serif;
  --latin: "Chewy", "Dachi the Lynx", sans-serif;

  /* three hand-cut outlines; the boil clock swaps between them so frames look redrawn */
  --wr0: 16px 22px 13px 20px / 20px 13px 22px 16px;
  --wr1: 20px 14px 21px 13px / 14px 21px 13px 20px;
  --wr2: 13px 20px 17px 22px / 22px 17px 20px 13px;
  --wr: var(--wr0);

  --cut-shadow: 3px 4px 0 rgba(0, 0, 0, 0.42);
  --card-shadow: 5px 7px 0 rgba(0, 0, 0, 0.45);
  --frame: 83ms; /* one frame at 12fps; every stepped delay is a multiple of it */
}
html.b1 { --wr: var(--wr1); }
html.b2 { --wr: var(--wr2); }

/* ── BASE ──────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html, body { overscroll-behavior-y: none; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background-color: var(--night); /* overscroll / rubber-band area matches the page */
  /* scrollbar starts invisible and fades in once the intro releases the page */
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
  transition: scrollbar-color 0.8s ease;
}
html.scroll-ready { scrollbar-color: var(--chalk-soft) var(--night-dk); }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background-color: var(--night-dk); }
::-webkit-scrollbar-thumb { background-color: transparent; border-radius: 8px; transition: background-color 0.8s ease; }
html.scroll-ready ::-webkit-scrollbar-thumb { background-color: var(--chalk-soft); }

body {
  margin: 0;
  background-color: var(--night);
  /* 1024px seamless tile drawn at 512px = 2x density, stays sharp on retina phones */
  background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-dark.webp");
  background-size: 512px 512px;
  color: var(--chalk);
  font-family: var(--hand);
  font-size: 19px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* clip, not hidden: no scroll container, so side doodles can't widen the page on phones */
main { overflow-x: clip; }

img { display: block; max-width: 100%; }
h1, h2, h3, p { margin: 0; font-weight: 400; }
a { color: inherit; }
button { font: inherit; color: inherit; }

/* Intro lock: never position:fixed / overflow:hidden on the document (Chrome iOS from a
   chat app freezes its viewport short). script.js traps touchmove + scroll instead. */
html.is-locked, html.is-locked body { overscroll-behavior: none; touch-action: none; }

/* ── BOIL ──────────────────────────────────────────────────
   Per-letter jitter. script.js writes --r0..2 / --x0..2 / --y0..2 on each .ch;
   the html boil class picks one set. --amp is raised while the monster is out. */
.ch {
  display: inline-block;
  --r: var(--r0); --x: var(--x0); --y: var(--y0);
  rotate: calc(var(--r) * var(--amp, 1));
  translate: calc(var(--x) * var(--amp, 1)) calc(var(--y) * var(--amp, 1));
}
html.b1 .ch { --r: var(--r1); --x: var(--x1); --y: var(--y1); }
html.b2 .ch { --r: var(--r2); --x: var(--x2); --y: var(--y2); }
/* letters are inline-blocks, so a line could break between any two; words keep them together */
.word { display: inline-block; white-space: nowrap; }

/* letters wait hidden, then pop in through four held poses */
[data-stop] .ch__in { display: inline-block; opacity: 0; }
[data-stop].is-typed .ch__in {
  animation: letter-pop calc(var(--frame) * 4) steps(1, end) forwards;
  animation-delay: calc(var(--i) * 66ms);
}
@keyframes letter-pop {
  0%   { opacity: 1; transform: translateY(0.35em) scale(0.3) rotate(-14deg); }
  25%  { opacity: 1; transform: translateY(-0.12em) scale(1.22) rotate(9deg); }
  50%  { opacity: 1; transform: translateY(0.04em) scale(0.92) rotate(-4deg); }
  75%, 100% { opacity: 1; transform: none; }
}

/* ── LOADER ──────────────────────────────────────────────── */
.loader {
  position: fixed;
  inset: 0;
  z-index: 10001; /* above every overlay, incl. popups */
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--night);
  background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-dark.webp");
  background-size: 512px 512px;
  transition: opacity 0.6s ease;
}
.loader.is-hidden { opacity: 0; pointer-events: none; }
.loader__spinner {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 4px solid rgba(241, 230, 211, 0.16);
  border-top-color: var(--ember);
  animation: spin 0.9s steps(8) infinite; /* ticks round like a stop-motion clock */
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── DESKTOP NOTICE ────────────────────────────────────── */
.mobile-prompt { display: none; }

/* ── SOUND TOGGLE ──────────────────────────────────────── */
.sound-toggle {
  position: fixed;
  top: calc(14px + env(safe-area-inset-top));
  left: 14px;
  z-index: 60;
  width: 54px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 0;
  background-color: var(--paper-lt);
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  box-shadow: var(--cut-shadow);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s ease, visibility 0.4s ease;
}
html.is-awake .sound-toggle { opacity: 1; visibility: visible; }
.sound-toggle__bar {
  width: 4px;
  height: 8px;
  border-radius: 2px;
  background-color: var(--ink-soft);
  opacity: 0.55;
}
/* muted: a resting equalizer, so it still reads as "sound" and invites a tap */
.sound-toggle__bar:nth-child(1) { height: 6px; }
.sound-toggle__bar:nth-child(2) { height: 11px; }
.sound-toggle__bar:nth-child(3) { height: 8px; }
.sound-toggle__bar:nth-child(4) { height: 12px; }
.sound-toggle.is-playing .sound-toggle__bar { opacity: 1; }
.sound-toggle.is-playing .sound-toggle__bar {
  background-color: var(--blood);
  animation: eq calc(var(--frame) * 8) steps(1, end) infinite;
}
.sound-toggle.is-playing .sound-toggle__bar:nth-child(2) { animation-delay: calc(var(--frame) * -3); }
.sound-toggle.is-playing .sound-toggle__bar:nth-child(3) { animation-delay: calc(var(--frame) * -5); }
.sound-toggle.is-playing .sound-toggle__bar:nth-child(4) { animation-delay: calc(var(--frame) * -2); }
@keyframes eq {
  0%   { height: 6px; }
  25%  { height: 15px; }
  50%  { height: 9px; }
  75%  { height: 13px; }
}

/* ── BUTTONS ────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 10px 26px 8px;
  font-family: var(--display);
  font-size: 18px;
  line-height: 1.1;
  white-space: nowrap;
  text-decoration: none;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  box-shadow: var(--cut-shadow);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.btn:active { translate: 1px 2px; box-shadow: 1px 2px 0 rgba(0, 0, 0, 0.42); }
.btn--blood { background-color: var(--blood); color: var(--paper-lt); }
.btn--blood:hover { background-color: var(--blood-dk); }
.btn--ink { background-color: var(--paper-lt); color: var(--ink); }
.btn--ink:hover { background-color: var(--paper-dk); }
.btn:focus-visible, .field__input:focus-visible, .bat:focus-visible {
  outline: 3px solid rgba(226, 68, 92, 0.6);
  outline-offset: 3px;
}

/* ── HERO ───────────────────────────────────────────────── */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
}
.vh-lock .hero { min-height: calc(var(--vh) * 100); }

/* A candle-warm pool behind the bat, falling off into near-black corners. It lives on its own
   layer so it can be masked out toward the bottom: painted on .hero itself, the dark corners
   stopped dead at the hero's edge and drew a hard seam above the party section. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(ellipse at 50% 64%, rgba(255, 214, 170, 0.1) 0%, rgba(255, 214, 170, 0) 50%, rgba(0, 0, 0, 0.42) 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}

/* red dread that floods in on held poses while the monster is out (no transition: stop motion) */
.hero__dread {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  background-image: radial-gradient(ellipse at 50% 62%, rgba(179, 18, 46, 0) 25%, rgba(179, 18, 46, 0.3) 70%, rgba(110, 8, 26, 0.55) 100%);
  /* same fade as the vignette, so the red never ends on a hard line either */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 70%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 70%, transparent 100%);
}
.hero[data-pose="t4"] .hero__dread { opacity: 0.35; }
.hero[data-pose="t5"] .hero__dread { opacity: 0.65; }
.hero[data-pose="t6"] .hero__dread { opacity: 1; }
.hero[data-pose="t5"] { --amp: 4; }
.hero[data-pose="t6"] { --amp: 7; }

.hero__copy {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  top: calc(var(--vh) * 6);
  padding: 0 16px;
  text-align: center;
  pointer-events: none;
}
.hero__hosts { font-size: 20px; color: var(--chalk-soft); }
.hero__title {
  margin: 6px 0 10px;
  font-family: var(--latin);
  font-size: 50px;
  line-height: 0.98;
  letter-spacing: 0.02em;
}
.hero__line { display: block; }
.hero__line--accent { color: var(--ember); font-size: 1.3em; }
.hero__date { font-size: 21px; }
.hero__cta {
  margin-top: 16px;
  pointer-events: auto;
  opacity: 0;
  visibility: hidden;
}
/* script.js adds .is-shown once the last copy line has typed itself in */
.hero__cta.is-shown {
  visibility: visible;
  animation: place calc(var(--frame) * 4) steps(1, end) forwards;
}

/* The stage box is the front pose; every other frame is placed in % of it (from extract.py),
   so the monster can spill far outside without moving the cute bat's head. */
.bat {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: calc(var(--vh) * 52);
  height: calc(var(--vh) * 33);
  width: calc(var(--vh) * 33.6);
  margin-left: calc(var(--vh) * -16.8);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  outline: none;
}
.bat__frames {
  position: absolute;
  inset: 0;
  rotate: 0deg;
}
html.b1 .bat__frames { rotate: 0.5deg; translate: 0 -1px; }
html.b2 .bat__frames { rotate: -0.4deg; translate: 1px 0; }

/* soft cast shadow, shrinks in held steps once the bat lifts off */
.bat::before {
  content: "";
  position: absolute;
  left: 20%;
  width: 60%;
  bottom: -3%;
  height: 7%;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.42);
}
.hero[data-pose="t3"] .bat::before, .hero[data-pose="t4"] .bat::before { left: 30%; width: 40%; opacity: 0.6; }
.hero[data-pose="t5"] .bat::before, .hero[data-pose="t6"] .bat::before { left: 36%; width: 28%; opacity: 0.4; }

.bat__f {
  position: absolute;
  max-width: none;
  visibility: hidden;
  user-select: none;
  -webkit-user-select: none;
  pointer-events: none;
}
.bat__f.is-on { visibility: visible; }
.f-front   { left: 0;      top: 0;        width: 99.93%;  height: 99.95%; }
.f-q34     { left: 1.04%;  top: -1.49%;   width: 95%;     height: 102.1%; }
.f-prof    { left: 2.71%;  top: -2.34%;   width: 91.72%;  height: 103.06%; }
.f-q34r    { left: 7.73%;  top: -1.49%;   width: 95%;     height: 102.1%; }
.f-profr   { left: 9.35%;  top: -2.34%;   width: 91.72%;  height: 103.06%; }
.f-startle { left: 2.2%;   top: -0.85%;   width: 96.64%;  height: 100.91%; }
.f-t2      { left: 10.57%; top: -17.59%;  width: 82.57%;  height: 124.53%; }
.f-t3      { left: 4.64%;  top: -45.28%;  width: 94.53%;  height: 149.1%; }
.f-t4      { left: 6.73%;  top: -64.82%;  width: 90.31%;  height: 178.92%; }
.f-t5      { left: 5.13%;  top: -82.41%;  width: 93.59%;  height: 200.63%; }
.f-t6      { left: -0.16%; top: -122.48%; width: 104.15%; height: 248.1%; }

/* startle = a little hop; the monster = a hand-held shake. Both use `translate`
   so they never fight the boil's `rotate`. */
.hero[data-pose="startle"] .bat__frames { animation: hop calc(var(--frame) * 5) steps(1, end) both; }
@keyframes hop {
  0%   { translate: 0 -9%; }
  20%  { translate: 0 -12%; }
  40%  { translate: 0 -5%; }
  60%  { translate: 0 1%; }
  80%, 100% { translate: 0 0; }
}
/* Coming at the camera: each transform pose is held a little bigger (no easing, it's stop
   motion), scaled around the face so the eyes come straight at the guest. Uses `scale`, so it
   stacks with the boil's rotate and the shake's translate. The same poses play back on the way
   down, so the bat steps back as it shrinks. */
.bat__frames { transform-origin: 50% 30%; }
.hero[data-pose="t2"] .bat__frames { scale: 1.06; }
.hero[data-pose="t3"] .bat__frames { scale: 1.14; }
.hero[data-pose="t4"] .bat__frames { scale: 1.25; }
.hero[data-pose="t5"] .bat__frames { scale: 1.38; }
.hero[data-pose="t6"] .bat__frames { scale: 1.52; }
/* once it's this close it passes in front of the copy */
.hero[data-pose="t4"] .bat, .hero[data-pose="t5"] .bat, .hero[data-pose="t6"] .bat { z-index: 5; }
.hero[data-pose="t6"] .bat__frames {
  animation:
    shake calc(var(--frame) * 4) steps(1, end) infinite,
    lunge calc(var(--frame) * 4) steps(1, end) forwards;
}
/* the monster lands too close, then settles back a hair */
@keyframes lunge {
  0%   { scale: 1.66; }
  25%  { scale: 1.6; }
  50%  { scale: 1.55; }
  75%, 100% { scale: 1.52; }
}
@keyframes shake {
  0%  { translate: -1.4% 0.6%; }
  25% { translate: 1.2% -0.8%; }
  50% { translate: -0.6% -1.2%; }
  75% { translate: 1.5% 0.9%; }
}

/* poof of paper dots when the monster shrinks back */
.bat__puff { position: absolute; left: 50%; top: 45%; width: 0; height: 0; }
.bat__puff i {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background-color: var(--paper-lt);
  opacity: 0;
}
.bat.is-poof .bat__puff i { animation: puff calc(var(--frame) * 5) steps(1, end) both; }
.bat__puff i:nth-child(1) { --px: -80px; --py: -40px; }
.bat__puff i:nth-child(2) { --px: 78px;  --py: -52px; }
.bat__puff i:nth-child(3) { --px: -96px; --py: 34px; }
.bat__puff i:nth-child(4) { --px: 92px;  --py: 30px; }
.bat__puff i:nth-child(5) { --px: 4px;   --py: -96px; }
@keyframes puff {
  0%   { opacity: 1; transform: translate(calc(var(--px) * 0.4), calc(var(--py) * 0.4)) scale(1.3); }
  25%  { opacity: 1; transform: translate(calc(var(--px) * 0.75), calc(var(--py) * 0.75)) scale(1); }
  50%  { opacity: 1; transform: translate(var(--px), var(--py)) scale(0.7); }
  75%  { opacity: 1; transform: translate(calc(var(--px) * 1.1), calc(var(--py) * 1.1)) scale(0.35); }
  100% { opacity: 0; transform: translate(calc(var(--px) * 1.1), calc(var(--py) * 1.1)) scale(0.2); }
}

/* touch hint, bottom centre: the only words on screen before the opening. Hidden on the tap. */
.tap-hint {
  position: absolute;
  z-index: 4;
  left: 50%;
  bottom: calc(var(--vh) * 2 + 24px + env(safe-area-inset-bottom));
  width: 260px;
  margin-left: -130px;
  text-align: center;
  font-size: 21px;
  color: var(--chalk);
  pointer-events: none;
  transition: opacity 0.3s ease;
}
.tap-hint.is-typed { animation: tap-bob calc(var(--frame) * 12) steps(1, end) infinite 1.2s; }
.tap-hint.is-gone { opacity: 0; }
/* "არ" in red: reverse psychology, the same joke as the brag video. The letters are split
   into .word spans by script.js, so the first word is the first element child. */
.tap-hint .word:first-child { color: var(--ember); }
@keyframes tap-bob {
  0%  { translate: 0 0; }
  33% { translate: 0 -4px; }
  66% { translate: 0 1px; }
}

/* scroll cue, bottom centre of the hero. Shown once the intro unlocks the page (script.js adds
   .is-shown), because during the locked intro there is nothing to scroll to yet. */
.scroll-hint {
  position: absolute;
  z-index: 4; /* above the monster's lower wing slashes */
  left: 50%;
  bottom: calc(var(--vh) * 2 + env(safe-area-inset-bottom));
  width: 180px;
  margin-left: -90px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 0;
  font-size: 18px;
  line-height: 1.2;
  color: var(--chalk-soft);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  visibility: hidden;
}
.scroll-hint.is-shown { visibility: visible; }
.scroll-hint__chev { position: relative; width: 22px; height: 26px; opacity: 0; }
.scroll-hint.is-shown .scroll-hint__chev {
  opacity: 1;
  animation: nudge calc(var(--frame) * 12) steps(1, end) infinite;
  animation-delay: 0.9s;
}
/* two chevrons drawn from a corner border, the lower one fainter */
.scroll-hint__chev i {
  position: absolute;
  left: 4px;
  width: 14px;
  height: 14px;
  border-right: 3px solid var(--chalk-soft);
  border-bottom: 3px solid var(--chalk-soft);
  border-radius: 0 0 3px 0;
  rotate: 45deg;
}
.scroll-hint__chev i:nth-child(1) { top: 0; }
.scroll-hint__chev i:nth-child(2) { top: 9px; opacity: 0.5; }
@keyframes nudge {
  0%  { translate: 0 0; }
  17% { translate: 0 4px; }
  33% { translate: 0 8px; }
  50% { translate: 0 3px; }
}

/* sparkles in the empty sky above the bat while it waits */
.hero .doodle { z-index: 1; }
/* kept clear of the copy block (6-42vh) so they never sit on the title once it types in */
.hero .s1 { left: 9%;  top: calc(var(--vh) * 46); }
.hero .s2 { left: 86%; top: calc(var(--vh) * 43); }
.hero .s3 { left: 6%;  top: calc(var(--vh) * 72); }
.hero .s4 { left: 90%; top: calc(var(--vh) * 68); }

/* ── SHARED SECTION TYPE ─────────────────────────────────── */
section:not(.hero) { padding: 72px 16px; }
.h2 {
  font-family: var(--display);
  font-size: 32px;
  line-height: 1.12;
  text-align: center;
  margin-bottom: 14px;
}
.body-text { font-size: 20px; color: var(--chalk-soft); max-width: 34ch; margin: 0 auto; text-align: center; }

/* scroll reveal: set down by hand in four held poses, then rest at a slight tilt */
.reveal { opacity: 0; }
.reveal.is-in { animation: place calc(var(--frame) * 4) steps(1, end) forwards; animation-delay: var(--d, 0ms); }
@keyframes place {
  0%   { opacity: 1; transform: translate(-12px, 26px) rotate(calc(var(--rest, 0deg) - 7deg)); }
  25%  { opacity: 1; transform: translate(-4px, 8px) rotate(calc(var(--rest, 0deg) - 2deg)); }
  50%  { opacity: 1; transform: translate(3px, -5px) rotate(calc(var(--rest, 0deg) + 2deg)); }
  75%, 100% { opacity: 1; transform: rotate(var(--rest, 0deg)); }
}

/* ── PARTY (bats.png) ───────────────────────────────────── */
.party { display: grid; gap: 34px; justify-items: center; }
.print {
  --rest: -1.6deg;
  position: relative;
  margin: 0;
  width: 100%;
  max-width: 560px;
  padding: 10px;
  color: var(--ink);
  background-color: var(--paper-lt);
  background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-light.webp");
  background-size: 512px 512px;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  box-shadow: var(--card-shadow);
}
.print__img { width: 100%; height: auto; border-radius: 10px; }
.print__tape {
  position: absolute;
  z-index: 2;
  top: -14px;
  width: 78px;
  height: 26px;
  background-color: rgba(241, 154, 146, 0.55);
  border-left: 2px dashed rgba(58, 38, 38, 0.18);
  border-right: 2px dashed rgba(58, 38, 38, 0.18);
}
.print__tape--l { left: 14px; rotate: -12deg; }
.print__tape--r { right: 14px; rotate: 9deg; }

/* doodles: CSS-only marks in the same ink as the art, animated on twos.
   They pause until the section is on screen (.is-in on .print). */
.doodle { position: absolute; z-index: 3; pointer-events: none; }
.doodle--spark { width: 20px; height: 20px; }
.doodle--spark::before, .doodle--spark::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  width: 3px;
  height: 100%;
  margin-left: -1.5px;
  border-radius: 3px;
  background-color: var(--ember);
}
.doodle--spark::after { rotate: 90deg; }
.doodle--bubble { width: 12px; height: 12px; border: 2px solid var(--chalk); border-radius: 50%; }
.doodle--dash { width: 30px; height: 30px; }
.doodle--dash i {
  position: absolute;
  left: 13px;
  top: 0;
  width: 4px;
  height: 11px;
  border-radius: 3px;
  background-color: var(--blush);
  transform-origin: 2px 26px;
}
.doodle--dash i:nth-child(1) { rotate: -40deg; }
.doodle--dash i:nth-child(3) { rotate: 40deg; }
.doodle--moon {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  box-shadow: 7px 5px 0 0 var(--chalk); /* crescent cut from an empty circle */
}

.print .d1  { left: -10px; top: 18%; }
.print .d2  { right: -14px; top: 6%; }
.print .d3  { right: 8%; bottom: -16px; }
.print .d4  { left: 32%; top: -24px; }
.print .d5  { left: 46%; top: 34%; }
.print .d6  { left: 70%; top: 30%; }
.print .d7  { left: 20%; top: 44%; }
.print .d8  { left: -12px; bottom: 22%; rotate: -90deg; }
.print .d9  { right: -12px; top: 40%; rotate: 90deg; }
.print .d10 { right: 16%; top: -40px; }

.doodle { animation-play-state: paused; }
.is-in .doodle, .hero .doodle { animation-play-state: running; }
.doodle--spark { animation: twinkle calc(var(--frame) * 12) steps(1, end) infinite; }
.d2, .s2 { animation-delay: calc(var(--frame) * -4); }
.d3, .s3 { animation-delay: calc(var(--frame) * -7); }
.d4, .s4 { animation-delay: calc(var(--frame) * -10); }
@keyframes twinkle {
  0%   { opacity: 0; transform: scale(0.3); }
  17%  { opacity: 1; transform: scale(1.15) rotate(10deg); }
  33%  { opacity: 1; transform: scale(0.85); }
  50%  { opacity: 1; transform: scale(1) rotate(-8deg); }
  67%  { opacity: 0; }
}
.doodle--bubble { animation: rise calc(var(--frame) * 16) steps(1, end) infinite; }
.d6 { animation-delay: calc(var(--frame) * -6); }
.d7 { animation-delay: calc(var(--frame) * -11); }
@keyframes rise {
  0%   { opacity: 0; transform: translateY(0) scale(0.5); }
  12%  { opacity: 1; transform: translateY(-6px) scale(0.8); }
  25%  { opacity: 1; transform: translateY(-16px) scale(1); }
  37%  { opacity: 1; transform: translateY(-26px) translateX(3px); }
  50%  { opacity: 1; transform: translateY(-38px) translateX(-2px); }
  62%  { opacity: 0.6; transform: translateY(-48px) scale(1.1); }
  75%, 100% { opacity: 0; transform: translateY(-48px) scale(1.4); }
}
.doodle--dash { animation: cheer calc(var(--frame) * 10) steps(1, end) infinite; }
.d9 { animation-delay: calc(var(--frame) * -5); }
@keyframes cheer {
  0%   { opacity: 1; scale: 1; }
  20%  { opacity: 1; scale: 1.2; }
  40%  { opacity: 0; }
  80%  { opacity: 0; }
}
.doodle--moon { animation: rock calc(var(--frame) * 16) steps(1, end) infinite; }
@keyframes rock {
  0%  { rotate: -10deg; }
  25% { rotate: -2deg; }
  50% { rotate: 8deg; }
  75% { rotate: 0deg; }
}

/* ── TIMETABLE ───────────────────────────────────────────── */
.slips {
  list-style: none;
  margin: 28px auto 0;
  padding: 0;
  max-width: 520px;
  display: grid;
  gap: 16px;
}
.slip {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 16px;
  align-items: baseline;
  padding: 14px 18px 12px;
  color: var(--ink);
  background-color: var(--paper-lt);
  background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-light.webp");
  background-size: 512px 512px;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  box-shadow: var(--cut-shadow);
}
/* uneven tilts and offsets: slips set down by hand, not laid on a grid */
.slip:nth-child(1) { --rest: -1.4deg; margin-right: 18px; --d: 0ms; }
.slip:nth-child(2) { --rest: 1.1deg;  margin-left: 22px;  --d: 166ms; }
.slip:nth-child(3) { --rest: -0.6deg; margin-right: 8px;  --d: 332ms; }
.slip:nth-child(4) { --rest: 1.5deg;  margin-left: 12px;  --d: 498ms; }
.slip:nth-child(5) { --rest: -1deg;   margin-right: 24px; --d: 664ms; }
.slip__time {
  grid-row: span 2;
  font-family: var(--display);
  font-size: 30px;
  line-height: 1;
  color: var(--blood);
}
.slip__what { font-size: 22px; line-height: 1.25; }
.slip__note { font-size: 18px; line-height: 1.3; color: var(--ink-soft); }

/* ── DETAILS ─────────────────────────────────────────────── */
.details { max-width: 920px; margin: 0 auto; }
.countdown { text-align: center; }
.countdown__label { font-size: 20px; color: var(--chalk-soft); }
.countdown__row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  max-width: 400px;
  margin: 10px auto 0;
}
.countdown__cell { display: grid; justify-items: center; }
.countdown__num {
  font-family: var(--display);
  font-size: 44px;
  line-height: 1;
  color: var(--ember);
  font-variant-numeric: tabular-nums;
}
.countdown__num.tick { animation: tick calc(var(--frame) * 3) steps(1, end); }
@keyframes tick {
  0%   { transform: scale(0.8, 1.15); }
  33%  { transform: scale(1.1, 0.92); }
  66%, 100% { transform: none; }
}
.countdown__unit { font-size: 17px; color: var(--chalk-soft); }

.info { display: grid; gap: 0; margin-top: 44px; }
.info__block { padding: 30px 4px; text-align: center; }
.info__block + .info__block { border-top: 2px dashed rgba(241, 230, 211, 0.22); }
.info__title { font-family: var(--display); font-size: 26px; margin-bottom: 6px; }
.info__main { font-size: 24px; }
.info__sub { font-size: 19px; color: var(--chalk-soft); max-width: 30ch; margin: 2px auto 18px; }
.info__block:nth-child(1) { --rest: -0.8deg; }
.info__block:nth-child(2) { --rest: 0.6deg; --d: 166ms; }

/* ── RSVP ────────────────────────────────────────────────── */
.rsvp__deadline { margin-bottom: 28px; }
.rsvp__form {
  --rest: 0.5deg;
  max-width: 460px;
  margin: 0 auto;
  padding: 26px 20px 24px;
  display: grid;
  gap: 18px;
  color: var(--ink);
  background-color: var(--paper-lt);
  background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-light.webp");
  background-size: 512px 512px;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  box-shadow: var(--card-shadow);
}
.field { display: grid; gap: 6px; margin: 0; padding: 0; border: 0; min-width: 0; }
.field__label { font-size: 19px; padding: 0; }
.field__input {
  width: 100%;
  min-height: 50px;
  padding: 10px 14px 8px;
  font-family: var(--hand);
  font-size: 20px;
  color: var(--ink);
  background-color: #fffaf1;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  -webkit-appearance: none;
  appearance: none;
}
.field--count.is-hidden { display: none; }

.choice { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.choice__opt, .pill { position: relative; cursor: pointer; }
.choice__opt input, .pill input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice__card, .pill__face {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 8px 10px 6px;
  font-size: 20px;
  text-align: center;
  background-color: #fffaf1;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.choice__opt input:checked + .choice__card,
.pill input:checked + .pill__face {
  background-color: var(--blood);
  color: var(--paper-lt);
  animation: tick calc(var(--frame) * 3) steps(1, end);
}
.choice__opt input:focus-visible + .choice__card,
.pill input:focus-visible + .pill__face { outline: 3px solid rgba(179, 18, 46, 0.45); outline-offset: 2px; }
.pills { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.pill__face { font-family: var(--display); font-size: 22px; }
.form-error { min-height: 1.4em; font-size: 18px; color: var(--blood-dk); text-align: center; }
.rsvp__submit { justify-self: center; min-width: 180px; }

/* ── FOOTER ──────────────────────────────────────────────── */
.footer {
  padding: 56px 16px calc(36px + env(safe-area-inset-bottom));
  text-align: center;
  border-top: 2px dashed rgba(241, 230, 211, 0.18);
}
.footer__names { font-family: var(--latin); font-size: 32px; letter-spacing: 0.02em; color: var(--ember); }
.footer__date { font-size: 19px; color: var(--chalk-soft); margin-bottom: 26px; }
.footer-credit {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "Segoe UI", system-ui, sans-serif; /* real latin text, keep it off the georgian faces */
  font-size: 13px;
  text-decoration: none;
  color: var(--chalk);
  opacity: 0.3;
  transition: opacity 0.3s ease;
}
.footer-credit:hover { opacity: 0.65; }
.footer-credit img { width: 20px; height: 20px; }

/* ── POPUPS ──────────────────────────────────────────────── */
.popup {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background-color: rgba(12, 7, 10, 0.72);
}
.popup[hidden] { display: none; }
.popup__box {
  --rest: -0.8deg;
  position: relative;
  width: 100%;
  max-width: 360px;
  padding: 22px 22px 24px;
  text-align: center;
  color: var(--ink);
  background-color: var(--paper-lt);
  background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-light.webp");
  background-size: 512px 512px;
  border: 2px solid var(--ink);
  border-radius: var(--wr);
  box-shadow: 6px 8px 0 rgba(0, 0, 0, 0.5);
  animation: place calc(var(--frame) * 4) steps(1, end) both;
}
.popup__close {
  position: absolute;
  top: 8px;
  right: 10px;
  padding: 6px 8px;
  background: none;
  border: 0;
  font-size: 16px;
  color: var(--ink-soft);
  cursor: pointer;
}
.popup__art { position: relative; width: 150px; height: 150px; margin: 14px auto 6px; }
.popup__art img { width: 100%; height: 100%; object-fit: contain; }
.popup__title { font-family: var(--display); font-size: 28px; line-height: 1.15; margin-bottom: 6px; }
.popup__text { font-size: 20px; color: var(--ink-soft); margin-bottom: 18px; }

/* yes: the bat hops for joy and hearts pop around it */
.popup__art--yes img { animation: joy calc(var(--frame) * 8) steps(1, end) infinite; }
@keyframes joy {
  0%  { translate: 0 0; }
  25% { translate: 0 -14px; rotate: -3deg; }
  50% { translate: 0 -4px; rotate: 2deg; }
  75% { translate: 0 0; }
}
.heart {
  position: absolute;
  width: 16px;
  height: 16px;
  background-color: var(--blood);
  rotate: 45deg;
  border-radius: 2px;
  animation: heart calc(var(--frame) * 12) steps(1, end) infinite;
}
.heart::before, .heart::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: var(--blood);
}
.heart::before { left: -8px; top: 0; }
.heart::after { left: 0; top: -8px; }
.heart.h1 { left: 4px; top: 30px; }
.heart.h2 { right: 2px; top: 12px; scale: 0.7; animation-delay: calc(var(--frame) * -4); }
.heart.h3 { right: 16px; top: 88px; scale: 0.55; animation-delay: calc(var(--frame) * -8); }
@keyframes heart {
  0%   { opacity: 0; translate: 0 6px; }
  17%  { opacity: 1; translate: 0 0; }
  33%  { opacity: 1; translate: 0 -8px; }
  50%  { opacity: 1; translate: 0 -14px; }
  67%  { opacity: 0; }
}

/* no: the bat turns away to sulk under its own little cloud */
.popup__art--no img { animation: sulk calc(var(--frame) * 16) steps(1, end) infinite; }
@keyframes sulk {
  0%  { translate: 0 0; rotate: 0deg; }
  50% { translate: 0 3px; rotate: -2deg; }
}
.cloud { position: absolute; z-index: 2; left: 52px; top: -26px; width: 56px; height: 24px; }
.cloud::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 14px;
  background-color: var(--ink-soft);
  box-shadow: 12px -9px 0 -2px var(--ink-soft), -2px -6px 0 -4px var(--ink-soft);
}
.cloud i {
  position: absolute;
  top: 28px;
  width: 3px;
  height: 9px;
  border-radius: 3px;
  background-color: #7a9bb5;
  opacity: 0;
  animation: drip calc(var(--frame) * 9) steps(1, end) infinite;
}
.cloud i:nth-child(1) { left: 12px; }
.cloud i:nth-child(2) { left: 26px; animation-delay: calc(var(--frame) * -3); }
.cloud i:nth-child(3) { left: 40px; animation-delay: calc(var(--frame) * -6); }
@keyframes drip {
  0%  { opacity: 1; translate: 0 0; }
  33% { opacity: 1; translate: 0 8px; }
  66% { opacity: 0; translate: 0 14px; }
}

/* ── BREAKPOINTS (mobile-first) ─────────────────────────── */
@media (min-width: 481px) {
  .hero__title { font-size: 60px; }
  .h2 { font-size: 38px; }
  .rsvp__form { padding: 30px 28px 28px; }
}

@media (min-width: 769px) {
  section:not(.hero) { padding: 100px 32px; }
  .hero__title { font-size: 72px; }
  .h2 { font-size: 44px; }
  .info { grid-template-columns: 1fr 1fr; gap: 40px; }
  .info__block + .info__block { border-top: 0; border-left: 2px dashed rgba(241, 230, 211, 0.22); }
  .countdown__num { font-size: 58px; }
  .countdown__row { max-width: 520px; }

  .mobile-prompt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9999;
    width: 340px;
    padding: 22px 20px 20px;
    color: var(--ink);
    background-color: var(--paper-lt);
    background-image: url("https://weddsite.b-cdn.net/showcase/halloween-1/paper-light.webp");
    background-size: 512px 512px;
    border: 2px solid var(--ink);
    border-radius: var(--wr);
    text-align: center;
    box-shadow: var(--card-shadow);
    transition: opacity 0.35s ease, transform 0.35s ease;
  }
  .mobile-prompt.hidden { opacity: 0; transform: translateX(-50%) translateY(16px); pointer-events: none; }
  .mobile-prompt__icon { width: 52px; height: 52px; opacity: 0.8; }
  .mobile-prompt__text { font-size: 18px; line-height: 1.5; }
  .mobile-prompt__close {
    position: absolute;
    top: 8px;
    right: 10px;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 14px;
    color: var(--ink-soft);
    padding: 4px 6px;
  }
}

@media (min-width: 1025px) {
  /* split hero: copy left, bat right, so the monster has its own column to grow in */
  .hero__copy {
    left: 8vw;
    right: auto;
    width: 44vw;
    top: calc(var(--vh) * 50);
    transform: translateY(-50%);
    text-align: left;
    padding: 0;
  }
  .hero__title { font-size: 88px; }
  .bat { left: 68%; top: calc(var(--vh) * 50); height: calc(var(--vh) * 34); width: calc(var(--vh) * 34.6); margin-left: calc(var(--vh) * -17.3); }
  .party {
    grid-template-columns: 1fr 1.15fr;
    align-items: center;
    max-width: 1180px;
    margin: 0 auto;
    gap: 64px;
  }
  .party .h2, .party .body-text { text-align: left; margin-left: 0; }
  .print { max-width: 640px; }
}

/* ── REDUCED MOTION: everything rests in its final pose ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; }
  .ch { rotate: none !important; translate: none !important; }
  [data-stop] .ch__in, .reveal, .hero__cta, .scroll-hint__chev { opacity: 1 !important; visibility: visible !important; }
  .tap-hint { display: none; }
  .doodle { display: none; }
  html { scroll-behavior: auto; }
}
