/* =====================================================================
   लग्नपत्रिका — six 9:16 pages with live Marathi text over the artwork.
   All sizes inside a page use cqw (1% of the page width), so every page
   keeps the same composition on any screen.
   ===================================================================== */

:root {
  --maroon: #7A1F2B;
  --burgundy: #541820;
  --night: #2A0D10;
  --cream: #F3E2C2;
  --gold: #B68A45;
  --gold-light: #D8BD80;
  --gold-hi: #F3DFA6;
  --ink: #3A2618;
  --ink-soft: #4E3626;
  --halo: 0 0 2.4cqw rgba(255, 247, 228, .95), 0 0 .7cqw rgba(255, 247, 228, .9);
  --font-display: "Rozha One", "Noto Serif Devanagari", "Kohinoor Devanagari", "Nirmala UI", "Mangal", serif;
  --font-body: "Noto Serif Devanagari", "Kohinoor Devanagari", "Nirmala UI", "Mangal", serif;
  --book: min(100vw, 480px);
  --ease: cubic-bezier(.22, .61, .36, 1);
}

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

html {
  background: var(--cream);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  overflow-x: hidden;
  font-family: var(--font-body);
  color: var(--ink);
}

h1, h2, p, ul { margin: 0; }

:focus-visible { outline: 3px solid var(--maroon); outline-offset: 3px; }

/* =====================================================================
   Pages
   All six pages are stacked into one continuous page that scrolls freely,
   like a feed. Each page fills the screen height.
   ===================================================================== */

.slide { position: relative; }

.slide__frame {
  position: relative;
  width: var(--book);
  margin: 0 auto;
  aspect-ratio: 941 / 1672;
  overflow: hidden;
  container-type: inline-size;
  background: #F4DDB0;
}


/* the painting and anything that must stay glued to it (page 1's sun rays) */
.slide__art,
.art-fx {
  position: absolute;
  inset: 0;
}
.art-fx { overflow: visible; pointer-events: none; }

.slide__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* page size: fill the screen height; on tall phones crop a little off the
   sides (at most ~9% each), never more */
.js {
  --fw: min(100vh * .5628, 100vw * 1.22);
}
@supports (height: 100svh) {
  .js { --fw: min(100svh * .5628, 100vw * 1.22); }
}

/* the feed: pages stacked into one continuous, freely scrolling page */
.js .stage { overflow-x: hidden; }
/* the page's height comes from the picture itself (9:16), so the page box
   and its artwork can never differ; on tall phones the picture is a little
   wider than the screen and is centred, with the sides trimmed */
.js .slide { overflow: hidden; }
.js .slide__frame {
  width: var(--fw);
  margin-left: calc(50% - var(--fw) / 2);
}
/* 3D depth: the painting sits at the back and tilts / shifts a little,
   the glow and sparkles sit in the middle, the text floats in front.
   main.js sets --tx/--ty (tilt, -1..1) and --sp (scroll position). */
.js .slide__frame { perspective: 1100px; }
.js .slide__art {
  scale: 1.1; /* room so the edges never show while it moves */
  translate: calc(var(--tx, 0) * -1.6%) calc(var(--ty, 0) * -1.2% + var(--sp, 0) * -4%);
  rotate: var(--rot, none);
}
.js .fx { translate: calc(var(--tx, 0) * -.6%) calc(var(--ty, 0) * -.5%); }
.js .slide__text { translate: var(--text-x, 0) var(--text-y, 0); } /* whole pixels, set by main.js */
/* pages overlap a little and blend into each other, so the feed reads as one page */
.js .slide + .slide {
  margin-top: calc(var(--fw) * -0.0711); /* 4% of the page height */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 4%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 4%);
}

/* on wide screens one soft, blurred copy of the opening artwork sits behind
   the whole invitation, so the space beside the pages is warm and seamless */
@media (min-aspect-ratio: 3/4) {
  .js body::before {
    content: "";
    position: fixed;
    inset: -6%;
    z-index: -1;
    background: url("../assets/bg/page-1.webp") center 40% / cover no-repeat;
    filter: blur(34px) brightness(1.04) saturate(1.05);
    opacity: .85;
  }
  .js .slide__frame { box-shadow: 0 0 50px rgba(120, 70, 30, .25); }
}

@media (prefers-reduced-motion: no-preference) {
  .js .slide.is-in .slide__art { animation: drift 26s ease-in-out infinite alternate; }
  /* stepping through the door: the first page eases back into place */
  .js.door-opening .slide--1 .slide__art { animation: step-in 5.4s cubic-bezier(.3, .1, .2, 1) both, drift 26s ease-in-out 5.4s infinite alternate; }
}


/* =====================================================================
   Heritage door (opening)
   Two thick wooden leaves: unlatch, pause, then a slow heavy swing
   towards the guest while the view moves forward through the doorway.
   ===================================================================== */

.door { display: none; }

.js.door-closed,
.js.door-closed body { overflow: hidden; } /* no scrolling while the door is shut */

@media (prefers-reduced-motion: no-preference) {
  .js .door {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 40;
    background: var(--night);
    --open: 5.4s;
  }
  .js .door.is-missing { opacity: 0; transition: opacity .8s ease; pointer-events: none; }
  .js .door.is-gone { display: none; }

  /* soft, blurred copy of the door fills the screen around it on wide screens */
  .door__backdrop {
    position: absolute;
    inset: -6%;
    background: url("../assets/door.webp") center / cover no-repeat;
    filter: blur(30px) brightness(.4);
  }

  .door__frame {
    position: absolute;
    left: 50%;
    top: 50%;
    width: var(--fw);
    aspect-ratio: 941 / 1672;
    translate: -50% -50%;
    perspective: calc(var(--fw) * 2.2);
    perspective-origin: 50% 50%;
    container-type: inline-size;
  }

  .door__leaf {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    transform-style: preserve-3d;
    background: #3B2414 url("../assets/door.webp") 0 0 / 200% 100% no-repeat;
  }
  .door__leaf--l { left: 0; transform-origin: 0 50%; }
  .door__leaf--r { right: 0; transform-origin: 100% 50%; background-position: 100% 0; }

  /* the leaf's thickness: a carved wooden edge along the meeting side */
  .door__edge {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 7cqw;
    backface-visibility: hidden;
    background:
      repeating-linear-gradient(0deg, rgba(0, 0, 0, .18) 0 3px, transparent 3px 9px),
      repeating-linear-gradient(0deg, transparent 0 18%, #C9A055 18% 19%, transparent 19% 33.3%),
      linear-gradient(90deg, #5A3418, #7A4A22 45%, #4A2A12);
  }
  .door__leaf--l .door__edge { left: 100%; transform-origin: 0 50%; transform: rotateY(90deg); }
  .door__leaf--r .door__edge { right: 100%; transform-origin: 100% 50%; transform: rotateY(-90deg); }

  /* shading that deepens towards the hinge as the leaf turns */
  .door__shade {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
  }
  .door__leaf--l .door__shade { background: linear-gradient(90deg, rgba(10, 4, 2, .85), rgba(10, 4, 2, .25) 70%, rgba(255, 220, 160, .12)); }
  .door__leaf--r .door__shade { background: linear-gradient(270deg, rgba(10, 4, 2, .85), rgba(10, 4, 2, .25) 70%, rgba(255, 220, 160, .12)); }

  /* warm light spilling through the gap */
  .door__light {
    position: absolute;
    left: 50%;
    top: 0;
    bottom: 0;
    width: 2px;
    translate: -50% 0;
    background: linear-gradient(to bottom, rgba(255, 236, 190, 0), rgba(255, 236, 190, .95) 25%, rgba(255, 236, 190, .95) 75%, rgba(255, 236, 190, 0));
    box-shadow: 0 0 50px 18px rgba(255, 214, 140, .55);
    opacity: 0;
  }

  .js .door { cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .js .door:focus-visible { outline: 3px solid var(--gold-hi); outline-offset: -6px; }

  /* glowing circle on the seam where the two leaves meet, shown once the
     door art has loaded: it invites the tap without any words */
  .door__hint {
    position: absolute;
    left: 50%;
    top: 50%;
    translate: -50% -50%;
    opacity: 0;
    transition: opacity .8s ease;
    pointer-events: none;
  }
  .door__tap {
    position: relative;
    display: block;
    width: 8cqw;
    height: 8cqw;
    border-radius: 50%;
    background: radial-gradient(circle, #FFF3C8 0, #E9C46A 45%, rgba(233, 196, 106, 0) 70%);
  }
  .door__tap::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid rgba(246, 227, 170, .9);
    animation: tap-ring 1.8s ease-out infinite;
  }
  .door.is-ready .door__hint { opacity: 1; }
  .door.is-ready .door__tap { animation: hint-breathe 2.4s ease-in-out .8s infinite alternate; }
  /* a thin line of warm light already peeks through the seam */
  .door.is-ready:not(.is-opening) .door__light { opacity: .35; width: 3px; transition: opacity 1.2s ease; }
  .door.is-opening .door__hint { opacity: 0; animation: none; transition: opacity .3s ease; }

  .door.is-opening { animation: door-bg var(--open) linear forwards; pointer-events: none; }
  .door.is-opening .door__frame { animation: door-push var(--open) cubic-bezier(.5, 0, .3, 1) forwards; }
  .door.is-opening .door__backdrop { animation: door-backdrop var(--open) ease-out forwards; }
  .door.is-opening .door__leaf--l { animation: leaf-l var(--open) linear forwards; }
  .door.is-opening .door__leaf--r { animation: leaf-r var(--open) linear forwards; }
  .door.is-opening .door__shade { animation: door-shade var(--open) ease-in forwards; }
  .door.is-opening .door__light { animation: door-light var(--open) ease-out forwards; }
}

@keyframes leaf-l {
  0%   { transform: rotateY(0); animation-timing-function: ease-out; }
  7%   { transform: rotateY(-2.5deg); animation-timing-function: ease-in-out; }   /* unlatch */
  15%  { transform: rotateY(-1.8deg); animation-timing-function: cubic-bezier(.45, .02, .25, 1); } /* settle, gather weight */
  92%  { transform: rotateY(-84deg); animation-timing-function: ease-out; }
  100% { transform: rotateY(-82deg); }
}
@keyframes leaf-r {
  0%   { transform: rotateY(0); animation-timing-function: ease-out; }
  7%   { transform: rotateY(2.5deg); animation-timing-function: ease-in-out; }
  15%  { transform: rotateY(1.8deg); animation-timing-function: cubic-bezier(.45, .02, .25, 1); }
  92%  { transform: rotateY(84deg); animation-timing-function: ease-out; }
  100% { transform: rotateY(82deg); }
}
@keyframes door-push {
  0%, 15% { transform: scale(1); }
  100%    { transform: scale(1.32); }
}
@keyframes door-backdrop { 0%, 10% { opacity: 1; } 26%, 100% { opacity: 0; } }
@keyframes tap-ring { from { transform: scale(1); opacity: 1; } to { transform: scale(2.4); opacity: 0; } }
@keyframes hint-breathe { from { box-shadow: 0 0 2cqw 1cqw rgba(255, 210, 130, .25); } to { box-shadow: 0 0 6cqw 2.4cqw rgba(255, 210, 130, .6); } }
@keyframes door-shade { 0%, 12% { opacity: 0; } 100% { opacity: 1; } }
@keyframes door-light {
  0%, 6% { opacity: 0; width: 2px; }
  14%    { opacity: 1; width: 4px; }
  32%    { opacity: .85; width: 10%; }
  50%    { opacity: 0; width: 16%; }
  100%   { opacity: 0; width: 16%; }
}
@keyframes door-bg {
  0%, 12% { background-color: rgba(42, 13, 16, 1); opacity: 1; }
  28%     { background-color: rgba(42, 13, 16, 0); }
  86%     { opacity: 1; }
  100%    { background-color: rgba(42, 13, 16, 0); opacity: 0; }
}

/* =====================================================================
   Text layer
   ===================================================================== */

.slide__text {
  position: absolute;
  z-index: 3;
  left: 14%;
  right: 14%;
  text-align: center;
  text-shadow: var(--halo);
}

.line { display: block; }

.ornament { display: block; margin: 0 auto; filter: drop-shadow(0 0 1.5cqw rgba(255, 247, 228, .95)); }
.ganesha { width: 17cqw; height: auto; margin-bottom: .6cqw; }

.sacred,
.kuldaivat {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 3.7cqw;
  line-height: 1.8;
  color: #6A2422;
}
/* both blessings on one line, with a wide gap between them */
.kuldaivat {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  gap: 0 4.5cqw;
}
.kuldaivat span { white-space: nowrap; }


.name, .event {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.45;
  color: var(--maroon);
}
.name { font-size: 10.5cqw; }
.event { font-size: 9.6cqw; }
.event--small { font-size: 8.4cqw; }

.rule {
  display: block;
  width: 48cqw;
  height: 3.6cqw;
  margin: 1cqw auto 2.4cqw;
  background: url("../assets/ornaments/divider.svg") center / contain no-repeat;
  filter: drop-shadow(0 0 1cqw rgba(255, 247, 228, .9));
}

.family { font-size: 4.4cqw; font-weight: 500; line-height: 1.75; text-wrap: balance; }
.address { margin-top: 2.6cqw; font-size: 4.2cqw; font-weight: 500; line-height: 1.75; color: var(--ink-soft); text-wrap: balance; }

.when { line-height: 1.7; }
.when .tithi { font-size: 4.7cqw; font-weight: 500; color: var(--ink-soft); }
.when .date { font-size: 5.1cqw; font-weight: 600; }
.when .time { font-size: 5.7cqw; font-weight: 700; color: var(--maroon); }
.when .place { font-size: 4.7cqw; font-weight: 500; color: var(--ink-soft); margin-top: .8cqw; }

.venue { line-height: 1.7; font-size: 4.4cqw; font-weight: 500; }
.venue__name { font-size: 5.8cqw; font-weight: 700; color: var(--maroon); }

/* map button: maroon velvet pill with gold rings and a gold pin medallion */
.map {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 2.6cqw;
  min-height: max(46px, 12.5cqw);
  margin: 3cqw auto 1cqw;
  padding: 1.2cqw 5cqw 1.2cqw 1.4cqw;
  border-radius: 999px;
  overflow: hidden;
  font-size: 4.6cqw;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: .02em;
  color: #F6E3AA;
  text-decoration: none;
  text-shadow: 0 1px 1px rgba(40, 8, 10, .6);
  background: radial-gradient(120% 140% at 50% 0%, #A3343E, #7A1F2B 55%, #4E1219);
  border: 1px solid #E2C27A;
  box-shadow:
    inset 0 1px 0 rgba(255, 220, 190, .35),
    inset 0 -2px 4px rgba(30, 5, 8, .45),
    0 0 0 .7cqw rgba(251, 243, 226, .92),
    0 0 0 1.1cqw #B68A45,
    0 2.6cqw 5cqw -2cqw rgba(60, 12, 16, .75);
  transition: transform .3s var(--ease), filter .3s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.map__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 9cqw;
  height: 9cqw;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #FFF1C8, #E2BE6A 45%, #A97C34);
  box-shadow: inset 0 -1px 2px rgba(80, 40, 10, .5), 0 0 0 1px rgba(255, 236, 190, .6);
}
.map__icon svg { width: 5.4cqw; height: 5.4cqw; fill: var(--maroon); }
.map__arrow { width: 4.2cqw; height: 4.2cqw; flex: none; fill: none; stroke: #E9CB86; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; transition: transform .3s var(--ease); }
/* a soft sheen that glides across every few seconds */
.map::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 30%;
  background: linear-gradient(100deg, transparent, rgba(255, 240, 200, .35), transparent);
  transform: skewX(-20deg) translateX(0);
  animation: map-sheen 4.5s ease-in-out 2.5s infinite;
  pointer-events: none;
}
.map:hover { transform: translateY(-2px); filter: brightness(1.08); }
.map:hover .map__arrow { transform: translateX(3px); }
.map:active { transform: translateY(1px); filter: brightness(.95); }

.hosts { list-style: none; padding: 0; font-size: 4.3cqw; font-weight: 500; line-height: 1.75; }

/* per-page placement (percent of the page) */
/* opening page: taller picture (941 x 2036) holding blessings + both families */
.slide--1 .slide__frame { aspect-ratio: 941 / 2036; }
@supports (height: 100svh) { .slide--1 .slide__text { top: 7%; left: 5%; right: 5%; }
.slide--1 .ganesha { width: 9cqw; margin-bottom: 0; }
.slide--1 .sacred, .slide--1 .kuldaivat { font-size: 3.4cqw; line-height: 1.6; }
.person { margin-top: 3.6cqw; }
.person--bride { margin-top: 3.4cqw; }
.slide--1 .name {
  font-family: "Amita", var(--font-display);
  font-weight: 700;
  font-size: 5.8cqw;
  line-height: 1.45;
}
.slide--1 .rule { width: 32cqw; height: 2.4cqw; margin: .2cqw auto .8cqw; }
.slide--1 .family { font-size: 3.5cqw; line-height: 1.5; }
.slide--1 .address { font-size: 3.3cqw; line-height: 1.5; margin-top: .8cqw; }
.slide--4 .slide__text { top: 19.5%; left: 18%; right: 18%; }
.slide--4 .event { font-size: 8.6cqw; }
.slide--4 .when .tithi { font-size: 4.4cqw; }
.slide--4 .when .date { font-size: 4.5cqw; }
.slide--4 .when .time { font-size: 5.2cqw; }
.slide--5 .slide__text { top: 16%; left: 19%; right: 19%; }
.slide--5 .countdown { margin-top: 3.4cqw; }
.slide--6 .slide__text { top: 5.2%; left: 12%; right: 12%; }
.slide--6 .event { font-size: 8.8cqw; }
.slide--6 .event--small { font-size: 7.6cqw; }
.slide--6 .venue { font-size: 4.2cqw; line-height: 1.6; }
.slide--6 .venue__name { font-size: 5.4cqw; }
.slide--6 .map { margin: 2.4cqw auto 1.4cqw; }
.slide--6 .rule { margin: .6cqw auto .6cqw; }
.slide--6 .hosts { font-size: 4.1cqw; line-height: 1.55; }

/* =====================================================================
   Countdown
   ===================================================================== */

.countdown {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2.2cqw;
  margin: 4cqw 0 0;
  text-shadow: none;
}
.countdown__unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 1.4cqw 0 1cqw;
  border-radius: 3cqw 3cqw 2cqw 2cqw;
  background: linear-gradient(170deg, #8A2C34, var(--burgundy));
  border: 1px solid var(--gold);
  box-shadow: 0 0 0 .8cqw rgba(251, 243, 226, .85), 0 0 0 1.1cqw rgba(182, 138, 69, .6), 0 2.4cqw 4cqw -2cqw rgba(84, 24, 32, .7);
}
.countdown__num {
  display: block;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 6.4cqw;
  line-height: 1.3;
  color: var(--gold-hi);
}
.countdown__num.tick { animation: tick .45s var(--ease); }
.countdown__label { font-size: max(10px, 3.1cqw); line-height: 1.5; color: #EBD3A4; }

/* =====================================================================
   Animated overlays
   ===================================================================== */

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

.glow {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 18cqw;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 214, 130, .8), rgba(255, 190, 90, .25) 55%, transparent);
  mix-blend-mode: screen;
  animation: flicker 2.6s ease-in-out infinite alternate;
}
.glow--lamp:nth-of-type(2n) { animation-duration: 3.1s; animation-delay: -1s; }
.glow--fire { width: 30cqw; animation-duration: 2.1s; }
.glow--sun {
  width: 80cqw;
  background: radial-gradient(closest-side, rgba(255, 236, 180, .6), rgba(255, 220, 150, .15) 60%, transparent);
  animation: breathe 7s ease-in-out infinite alternate;
}
.glow--soft {
  width: 90cqw;
  background: radial-gradient(closest-side, rgba(255, 228, 170, .45), transparent);
  animation: breathe 8s ease-in-out infinite alternate;
}
.glow--sparkle {
  width: 22cqw;
  background:
    radial-gradient(closest-side, rgba(255, 250, 225, .95), transparent 20%),
    radial-gradient(closest-side, rgba(255, 220, 140, .35), transparent);
  animation: twinkle 3.6s ease-in-out infinite;
}

.petals i {
  position: absolute;
  top: var(--t, 0);
  left: var(--l, 50%);
  width: 2.6cqw;
  height: 1.8cqw;
  border-radius: 70% 0 70% 0;
  background: #B5372A;
  opacity: 0;
  animation: fall 13s linear infinite;
}
.petals i:nth-child(1) { --l: 14%; --t: -2%; animation-delay: 0s; }
.petals i:nth-child(2) { --l: 76%; --t: -2%; animation-delay: -4s;  animation-duration: 15s; background: #D9772A; }
.petals i:nth-child(3) { --l: 40%; --t: 10%; animation-delay: -8s;  animation-duration: 17s; }
.petals i:nth-child(4) { --l: 88%; --t: 20%; animation-delay: -2s;  animation-duration: 14s; background: #E39A3B; }
.petals i:nth-child(5) { --l: 24%; --t: 28%; animation-delay: -10s; animation-duration: 16s; background: #8E2420; }
.petals i:nth-child(6) { --l: 60%; --t: 6%;  animation-delay: -6s;  animation-duration: 18s; }
.petals i:nth-child(7) { --l: 6%;  --t: 36%; animation-delay: -12s; animation-duration: 15s; background: #D9772A; }
.petals i:nth-child(8) { --l: 52%; --t: 30%; animation-delay: -3s;  animation-duration: 19s; background: #E39A3B; }

/* sun rays: soft beams from the setting sun that slowly turn and shimmer */
.rays {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 150cqw;
  aspect-ratio: 1;
  translate: -50% -50%;
  /* fade out with distance, and stop at the horizon so rays only fan
     out across the sky around the sun, not over the mountains */
  -webkit-mask-image:
    radial-gradient(closest-side, #000 6%, rgba(0, 0, 0, .55) 30%, transparent 66%),
    linear-gradient(to bottom, #000 47%, transparent 52.5%);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(closest-side, #000 6%, rgba(0, 0, 0, .55) 30%, transparent 66%),
    linear-gradient(to bottom, #000 47%, transparent 52.5%);
  mask-composite: intersect;
  mix-blend-mode: screen;
  opacity: .55;
  animation: rays-breathe 7s ease-in-out infinite alternate;
}
.rays::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-conic-gradient(from 0deg,
    rgba(255, 238, 196, 0) 0deg 6deg,
    rgba(255, 238, 196, .6) 9deg 11deg,
    rgba(255, 238, 196, 0) 14deg 21deg);
  animation: rays-turn 90s linear infinite;
}

/* living painting: a copy of a region of the painting, exactly over the
   original, gently displaced by an animated SVG filter (index.html). The
   edges are feathered so it melts into the still painting around it. */
.filters { position: absolute; width: 0; height: 0; overflow: hidden; }
.live { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .js .live {
    display: block;
    position: absolute;
    background-repeat: no-repeat;
    pointer-events: none;
    -webkit-mask-image:
      linear-gradient(to right, transparent, #000 14%, #000 86%, transparent),
      linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
    -webkit-mask-composite: source-in;
    mask-image:
      linear-gradient(to right, transparent, #000 14%, #000 86%, transparent),
      linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
    mask-composite: intersect;
  }
  /* the toran band touches the top and both sides: feather only its lower edge */
  .js .live--breeze {
    -webkit-mask-image: linear-gradient(to bottom, #000 80%, transparent);
    mask-image: linear-gradient(to bottom, #000 80%, transparent);
  }
  /* only pages on screen run the filters, to keep phones smooth */
  .js .slide.is-in .live--water  { filter: url(#f-water); }
  .js .slide.is-in .live--breeze { filter: url(#f-breeze); }
  .js .slide.is-in .live--cloth  { filter: url(#f-cloth); }
  .js .slide.is-in .live--heat   { filter: url(#f-heat); }
}

/* havan embers rising from the agni kund */
.embers { position: absolute; left: var(--x); top: var(--y); width: 16cqw; height: 0; translate: -50% 0; }
.embers i {
  position: absolute;
  bottom: 0;
  left: var(--l);
  width: .9cqw;
  height: .9cqw;
  border-radius: 50%;
  background: radial-gradient(circle, #FFF3C4 0, #FFB347 45%, rgba(255, 120, 40, 0) 72%);
  box-shadow: 0 0 1.4cqw .3cqw rgba(255, 150, 60, .6);
  opacity: 0;
  animation: ember var(--d, 2.6s) ease-out var(--w, 0s) infinite;
}
.embers i:nth-child(1)  { --l: 44%; --d: 2.4s; --w: 0s;    --dx: -2cqw; }
.embers i:nth-child(2)  { --l: 52%; --d: 2.9s; --w: -.6s;  --dx: 1.5cqw; }
.embers i:nth-child(3)  { --l: 38%; --d: 2.2s; --w: -1.3s; --dx: -3cqw; }
.embers i:nth-child(4)  { --l: 58%; --d: 3.1s; --w: -1.9s; --dx: 3cqw; }
.embers i:nth-child(5)  { --l: 48%; --d: 2.6s; --w: -.3s;  --dx: .5cqw; }
.embers i:nth-child(6)  { --l: 62%; --d: 2.3s; --w: -2.2s; --dx: 2cqw; width: .6cqw; height: .6cqw; }
.embers i:nth-child(7)  { --l: 34%; --d: 2.8s; --w: -1s;   --dx: -1.5cqw; width: .7cqw; height: .7cqw; }
.embers i:nth-child(8)  { --l: 54%; --d: 3.3s; --w: -2.6s; --dx: -1cqw; }
.embers i:nth-child(9)  { --l: 42%; --d: 2.5s; --w: -1.6s; --dx: 2.5cqw; width: .6cqw; height: .6cqw; }
.embers i:nth-child(10) { --l: 50%; --d: 3s;   --w: -.9s;  --dx: -2.5cqw; width: .7cqw; height: .7cqw; }

/* akshata shower on reaching the muhurat page (grains are made by main.js) */
.akshata i {
  position: absolute;
  top: -2%;
  left: var(--l);
  width: 1.7cqw;
  height: .8cqw;
  border-radius: 50%;
  background: linear-gradient(160deg, #FFE27A, #E0A21C 60%, #B87A0E);
  box-shadow: 0 .25cqw .5cqw rgba(110, 55, 5, .45), inset 0 0 0 .08cqw rgba(140, 80, 10, .5);
  opacity: 0;
  animation: grain var(--d) cubic-bezier(.35, .1, .65, 1) var(--w) forwards;
}
.akshata i.kumkum { background: radial-gradient(circle at 35% 35%, #F0444C, #A3141E); width: 1.1cqw; height: 1.1cqw; }

/* names written in gold: a soft-edged mask sweeps left to right while a
   glowing pen tip travels along the writing edge (main.js positions it) */
.write { width: fit-content; margin-inline: auto; }
.hosts { position: relative; }
.hosts li { --shim: var(--ink); }
.person { position: relative; }
.pen { display: none; }

/* golden sparkles: tiny motes of gold that drift up and twinkle */
.sparks i {
  position: absolute;
  left: var(--l);
  top: var(--t);
  width: 1cqw;
  height: 1cqw;
  border-radius: 50%;
  background: radial-gradient(circle, #FFF6D6 0, #F3D27A 45%, rgba(243, 210, 122, 0) 70%);
  box-shadow: 0 0 1.6cqw .4cqw rgba(255, 214, 120, .55);
  opacity: 0;
  animation: spark var(--d, 9s) ease-in-out var(--w, 0s) infinite;
}
.sparks i:nth-child(1) { --l: 18%; --t: 40%; --d: 9s;  --w: -1s; }
.sparks i:nth-child(2) { --l: 72%; --t: 30%; --d: 11s; --w: -6s; }
.sparks i:nth-child(3) { --l: 40%; --t: 62%; --d: 8s;  --w: -3s; }
.sparks i:nth-child(4) { --l: 86%; --t: 55%; --d: 12s; --w: -8s; }
.sparks i:nth-child(5) { --l: 8%;  --t: 72%; --d: 10s; --w: -2s; }
.sparks i:nth-child(6) { --l: 58%; --t: 80%; --d: 9s;  --w: -5s; }
.sparks i:nth-child(7) { --l: 30%; --t: 22%; --d: 13s; --w: -10s; width: .7cqw; height: .7cqw; }
.sparks i:nth-child(8) { --l: 64%; --t: 48%; --d: 11s; --w: -7s;  width: .8cqw; height: .8cqw; }


/* =====================================================================
   Scroll hint (first page): three thin gold chevrons that light up one
   after another, top to bottom. Sits at the bottom of the first screen,
   fades in after the text and fades out once the guest scrolls.
   ===================================================================== */

.scroll-hint {
  position: absolute;
  z-index: 6;
  left: 50%;
  top: calc(min(100vh, var(--fw, 100vw) / .5628) - 19cqw);
  translate: -50% 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: max(44px, 12cqw);
  padding: 1cqw 0 2cqw;
  -webkit-tap-highlight-color: transparent;
  transition: opacity .6s ease;
}
@supports (height: 100svh) {
  .scroll-hint { top: calc(min(100svh, var(--fw, 100vw) / .5628) - 19cqw); }
}
.scroll-hint i {
  display: block;
  width: 5.6cqw;
  height: 5.6cqw;
  margin-top: -2cqw;
  border-right: 3px solid #FFE7A6;
  border-bottom: 3px solid #FFE7A6;
  border-radius: 0 0 2px 0;
  rotate: 45deg;
  opacity: .5;
  /* dark outline first so the gold reads on the saree, then a warm glow */
  filter: drop-shadow(0 0 1px rgba(45, 12, 6, .95)) drop-shadow(0 0 2px rgba(45, 12, 6, .7)) drop-shadow(0 0 1.6cqw rgba(255, 210, 110, .9));
}
.scroll-hint.is-hidden { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: no-preference) {
  .js .scroll-hint { opacity: 0; }
  .js .slide--1.is-in .scroll-hint:not(.is-hidden) { opacity: 1; transition: opacity 1s ease 3s; }
  .scroll-hint i { opacity: .2; animation: chevron 1.8s ease-in-out infinite; }
  .scroll-hint i:nth-child(2) { animation-delay: .22s; }
  .scroll-hint i:nth-child(3) { animation-delay: .44s; }
}
@keyframes chevron {
  0%, 100% { opacity: .2; }
  30%      { opacity: 1; }
  65%      { opacity: .2; }
}

/* =====================================================================
   Text motion — only when JS is running and motion is allowed.
   main.js gives each animated piece an order (--i) within its page.
   ===================================================================== */

@media (prefers-reduced-motion: no-preference) {
  .js .a,
  .js .a .line,
  .js .countdown__unit,
  .js .hosts li {
    opacity: 0;
  }
  /* Fill mode is "backwards", never "both": once an animation ends nothing
     (blur, transform, mask) stays attached, so Safari draws the text crisply
     instead of keeping it in a softened, filtered layer. */
  .js .slide.is-in .a,
  .js .slide.is-in .a .line,
  .js .slide.is-in .hosts li,
  .js .slide.is-in .countdown__unit {
    opacity: 1;
    animation: rise 1.1s var(--ease) backwards;
    animation-delay: calc(.25s + var(--i, 0) * .16s);
  }
  /* containers that stagger their own lines show immediately */
  .js .slide.is-in .a:has(.line),
  .js .slide.is-in .hosts,
  .js .slide.is-in .countdown { animation: none; opacity: 1; }

  .js .slide.is-in .rule { animation: draw 1.2s var(--ease) backwards; animation-delay: calc(.25s + var(--i, 0) * .16s); }
  .js .slide.is-in .ganesha { animation: bloom 1.6s var(--ease) backwards; animation-delay: .5s; }
  .js .slide.is-in .countdown__unit { animation-name: pop; }
  .js .slide.is-in .map { animation: rise 1.1s var(--ease) backwards; animation-delay: calc(.25s + var(--i, 0) * .16s); }

  /* the mask itself is only set inside @keyframes write (see below) */
  .js .write {
    -webkit-mask-size: 220% 100%;
    mask-size: 220% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
  }
  .js .pen {
    display: block;
    position: absolute;
    left: var(--x0, 0);
    top: var(--py, 0);
    width: 2.6cqw;
    height: 2.6cqw;
    translate: -50% -50%;
    border-radius: 50%;
    background: radial-gradient(circle, #FFFBE6 0, #F6D47A 35%, rgba(246, 212, 122, 0) 70%);
    box-shadow: 0 0 2.4cqw .8cqw rgba(255, 214, 120, .65);
    opacity: 0;
    pointer-events: none;
  }
  .js .slide.is-in .pen { animation: pen 2.2s cubic-bezier(.45, .05, .4, 1) backwards; animation-delay: var(--wd, calc(.25s + var(--i, 0) * .16s)); }

  /* a gold sheen that passes through headings every few seconds */
  @supports ((-webkit-background-clip: text) or (background-clip: text)) {
    .shimmer {
      background: linear-gradient(100deg, var(--shim, var(--maroon)) 42%, #E2B864 50%, var(--shim, var(--maroon)) 58%) 0 0 / 300% 100%;
      -webkit-background-clip: text;
      background-clip: text;
      -webkit-text-fill-color: transparent;
      text-shadow: none;
      filter: drop-shadow(0 0 1.2cqw rgba(255, 247, 228, .95));
    }
    .js .slide.is-in .shimmer {
      animation: rise 1.1s var(--ease) backwards, shine 6.5s ease-in-out infinite;
      animation-delay: calc(.25s + var(--i, 0) * .16s), 2.2s;
    }
  }
}

/* =====================================================================
   Keyframes
   ===================================================================== */

@media (prefers-reduced-motion: no-preference) {
  .js .slide.is-in .write,
  .js .slide.is-in .hosts li.write {
    animation: write 2.2s cubic-bezier(.45, .05, .4, 1) backwards, shine 6.5s ease-in-out infinite;
    animation-delay: var(--wd, calc(.25s + var(--i, 0) * .16s)), calc(var(--wd, 0s) + 3.2s);
  }
}
/* the mask lives only inside the animation, so it is gone once written */
@keyframes write {
  from {
    opacity: 1;
    -webkit-mask-image: linear-gradient(90deg, #000 45%, transparent 55%);
    mask-image: linear-gradient(90deg, #000 45%, transparent 55%);
    -webkit-mask-position: 100% 0;
    mask-position: 100% 0;
  }
  to {
    opacity: 1;
    -webkit-mask-image: linear-gradient(90deg, #000 45%, transparent 55%);
    mask-image: linear-gradient(90deg, #000 45%, transparent 55%);
    -webkit-mask-position: 0 0;
    mask-position: 0 0;
  }
}
@keyframes pen {
  0%   { opacity: 0; transform: translateX(0); }
  10%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(var(--dx-pen, 0)); }
}
@keyframes ember {
  0%   { opacity: 0; transform: translate(0, 0) scale(1); }
  12%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx, 0), -24cqw) scale(.35); }
}
@keyframes grain {
  0%   { opacity: 0; transform: translate(0, 0) rotate(0deg); }
  6%   { opacity: 1; }
  85%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx, 0), var(--fall, 120cqw)) rotate(var(--r, 360deg)); }
}
@keyframes rise { from { opacity: 0; transform: translateY(3.5cqw); filter: blur(4px); } to { opacity: 1; transform: none; filter: none; } }
@keyframes pop { from { opacity: 0; transform: translateY(3cqw) scale(.85); } to { opacity: 1; transform: none; } }
@keyframes draw { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: none; } }
@keyframes bloom { from { opacity: 0; transform: scale(.6) rotate(-10deg); } to { opacity: 1; transform: none; } }
@keyframes shine { 0%, 55% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@keyframes tick { from { transform: translateY(-30%); opacity: .3; } to { transform: none; opacity: 1; } }
@keyframes map-sheen { 0% { transform: skewX(-20deg) translateX(0); } 45%, 100% { transform: skewX(-20deg) translateX(560%); } }
@keyframes glow-pulse { 0%, 100% { box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 0 0 0 rgba(255, 232, 170, .0); } 50% { box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 0 0 1.6cqw rgba(255, 232, 170, .45); } }
@keyframes step-in { from { transform: scale(1.14); filter: brightness(.7); } to { transform: none; filter: none; } }
@keyframes drift { from { transform: scale(1); } to { transform: scale(1.05); } }
@keyframes sweep { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
@keyframes flicker { from { opacity: .5; transform: scale(.92); } to { opacity: 1; transform: scale(1.05); } }
@keyframes breathe { from { opacity: .4; } to { opacity: 1; } }
@keyframes twinkle { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
@keyframes rays-turn { to { rotate: 360deg; } }
@keyframes rays-breathe { from { opacity: .35; } to { opacity: .65; } }
@keyframes spark {
  0%   { opacity: 0; transform: translate(0, 0) scale(.6); }
  20%  { opacity: 1; transform: translate(.6cqw, -4cqw) scale(1); }
  45%  { opacity: .25; }
  60%  { opacity: .95; transform: translate(-.8cqw, -10cqw) scale(.9); }
  100% { opacity: 0; transform: translate(.4cqw, -16cqw) scale(.5); }
}
@keyframes fall {
  0%   { opacity: 0; transform: translate(0, 0) rotate(0deg); }
  10%  { opacity: .9; }
  50%  { transform: translate(6cqw, 45cqw) rotate(190deg); }
  90%  { opacity: .8; }
  100% { opacity: 0; transform: translate(-3cqw, 95cqw) rotate(400deg); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .petals, .sparks, .embers, .akshata, .slide__frame::before { display: none; }
}
