/* ═══════════════════════════════════════════════════════════════
   Deepika & Bharat
   Mobile first. Every value below is tuned for a 390px screen and
   only widens at 700px / 1024px. Palette sampled from the mandap
   photographs: golden hour, ivory marble, white roses, brass.
   ═══════════════════════════════════════════════════════════════ */

/* ── tokens ─────────────────────────────────────────────────── */
:root{
  /* light */
  --sun:      #FFE7BC;
  --sunset:   #F2A45E;
  --amber:    #E08A46;
  --coral:    #EBA189;
  --peach:    #F8D3AE;

  /* surface */
  --paper:    #FBF3E7;
  --paper-2:  #F4E7D4;
  --cream:    #FFFAF2;

  /* metal */
  --gold:     #C0913F;
  --gold-lt:  #E7C88A;
  --gold-dk:  #8E6A22;

  /* ink */
  --ink:      #45321F;
  --ink-2:    #7A6547;
  --ink-3:    #A38F72;

  /* type */
  --f-ser: "Cormorant Garamond", "Iowan Old Style", "Times New Roman", serif;
  --f-scr: "Italianno", "Snell Roundhand", cursive;
  --f-ui:  "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --f-dev: "Tiro Devanagari Hindi", var(--f-ser);

  /* rhythm */
  --pad:  clamp(1.25rem, 6vw, 3rem);
  --gap:  clamp(2.5rem, 9vw, 5rem);
  --sect: clamp(4.5rem, 16vw, 9rem);

  --ease: cubic-bezier(.22,.61,.36,1);

  /* Artwork is resolved by main.js, which tries .jpg .jpeg .png .webp
     for each name in turn. Nothing here hardcodes an extension, so a
     photo saved as a PNG still works. `none` is a valid image layer,
     so the gradients underneath survive if a file is missing. */
  --art-wide:   none;
  --art-couple: none;
  --art-seal:   none;
}

/* ── reset ──────────────────────────────────────────────────── */
*,*::before,*::after{ box-sizing:border-box; }
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  /* paper, not amber: if anything ever fails to reach an edge, a cream
     hairline is invisible where a saturated orange one is not */
  background:var(--paper);
  /* clip, not hidden: hidden on one axis forces the other to `auto` and
     turns the element into a scroll container, which breaks sticky */
  overflow-x:clip;
}
body{
  margin:0;
  width:100%;
  max-width:100%;
  overflow-x:clip;
  font-family:var(--f-ui);
  font-weight:300;
  color:var(--ink);
  background:transparent;
  overflow-wrap:break-word;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

/* Grid and flex children default to min-width:auto, which means a wide
   child can push its track past the screen and drag the whole document
   with it. This is the usual cause of a page that renders narrower than
   the phone with the background showing down one side. */
.count__list li,.seg label,.detail,.pic,.fld,.celeb,.fam{ min-width:0; }

img,svg,iframe,video,canvas{ display:block; max-width:100%; }
blockquote{ margin:0; }
button,input,textarea,select{ font:inherit; color:inherit; }
h1,h2,h3,p,figure,dl,dd,ol,ul,fieldset,legend{ margin:0; padding:0; }
[hidden]{ display:none !important; }
ol,ul{ list-style:none; }
fieldset{ border:0; min-width:0; }
a{ color:inherit; }

:focus-visible{
  outline:2px solid var(--gold-dk);
  outline-offset:3px;
  border-radius:2px;
}

/* ── shared type ────────────────────────────────────────────── */
.scr{
  font-family:var(--f-scr);
  font-weight:400;
  font-size:1.5em;
  line-height:.7;
  letter-spacing:.01em;
}
.eyebrow{
  font-family:var(--f-ui);
  font-size:.7rem;
  font-weight:300;
  letter-spacing:.34em;
  text-transform:uppercase;
  color:var(--gold-dk);
  margin-bottom:1rem;
}
.sect__title{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(2.2rem,9.5vw,4.4rem);
  line-height:1.12;
  letter-spacing:-.01em;
  color:var(--ink);
  margin-bottom:1.6rem;
  text-wrap:balance;
}
/* The .scr line-height of .7 is for a word sitting inline. In a heading
   that wraps, it drives two lines into each other — Italianno's
   descenders are long. Give it room, and less size on a phone. */
.sect__title .scr{
  color:var(--gold-dk);
  font-size:1.24em;
  line-height:.92;
}
@media (max-width:560px){
  .sect__title .scr{ font-size:1.14em; }
}

/* ── buttons ────────────────────────────────────────────────── */
.btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:50px;
  padding:0 1.6rem;
  border:0;
  border-radius:999px;
  font-family:var(--f-ui);
  font-size:.86rem;
  font-weight:400;
  letter-spacing:.16em;
  text-transform:uppercase;
  text-decoration:none;
  cursor:pointer;
  transition:transform .3s var(--ease), box-shadow .3s var(--ease), opacity .3s;
  -webkit-tap-highlight-color:transparent;
}
.btn:active{ transform:scale(.97); }

.btn--gold{
  color:#3B2A12;
  background:linear-gradient(145deg,#F0D79C 0%,#D3A954 42%,#B4863A 100%);
  box-shadow:0 6px 22px -8px rgba(142,106,34,.75), inset 0 1px 0 rgba(255,255,255,.55);
}
.btn--line{
  color:var(--ink);
  background:transparent;
  box-shadow:inset 0 0 0 1px rgba(142,106,34,.4);
}
.btn--wide{ width:100%; }

/* ═══════════════ THE TEASER ═══════════════ */
body.is-sealed{ overflow:hidden; height:100%; }

.seal{
  position:fixed;
  inset:0;
  z-index:100;
  display:grid;
  place-items:center;
  padding:calc(env(safe-area-inset-top) + 2rem) var(--pad)
          calc(env(safe-area-inset-bottom) + 2rem);
  text-align:center;
  color:var(--cream);
  transition:opacity 1s var(--ease), visibility 1s;
}
/* .seal is display:grid, which would otherwise beat the hidden attribute */
.seal[hidden]{ display:none; }
body.is-open .seal{ opacity:0; visibility:hidden; pointer-events:none; }

.seal__art{
  position:absolute;
  inset:0;
  background-image:var(--art-seal),linear-gradient(180deg,#E9A87C,#C98B58);
  background-position:center 34%;
  background-size:cover;
  background-repeat:no-repeat;
  transform:scale(1.06);
}
.seal__art::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(56,32,10,.58),rgba(56,32,10,.42) 42%,rgba(56,32,10,.68));
}
.seal__in{ position:relative; max-width:32rem; }

/* ── the gate ───────────────────────────────────────────────
   One photograph, split down the middle. Each half is hinged on its
   OUTER edge and swings outward in 3D, so the invitation opens the way
   the gate in the picture would.

   The seam is hidden by overlapping the halves very slightly: each leaf
   is 50.2% wide and its image 199.2%, which lands the two crops on the
   same pixel column instead of leaving a hairline of background. */
.gate{
  position:absolute;
  inset:0;
  overflow:hidden;
  perspective:1500px;
  perspective-origin:50% 46%;
}
.gate__leaf{
  position:absolute;
  top:0;
  bottom:0;
  width:50.2%;
  overflow:hidden;
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
  transition:transform 1.9s cubic-bezier(.62,0,.18,1);
}
.gate__leaf--l{ left:0;  transform-origin:left center; }
.gate__leaf--r{ right:0; transform-origin:right center; }

.gate__leaf img{
  position:absolute;
  top:0;
  height:100%;
  width:199.2%;
  /* the global img cap would clamp this back to the leaf's own width and
     squeeze the whole picture into each half — the same trap the hero hit */
  max-width:none;
  object-fit:cover;
}
.gate__leaf--l img{ left:0; }
.gate__leaf--r img{ right:0; }

/* a door turning away from the light loses it */
.gate__shade{
  position:absolute;
  inset:0;
  background:#2A1607;
  opacity:0;
  transition:opacity 1.9s cubic-bezier(.62,0,.18,1);
  pointer-events:none;
}

body.is-open .gate__leaf--l{ transform:rotateY(-108deg); }
body.is-open .gate__leaf--r{ transform:rotateY(108deg); }
body.is-open .gate__shade{ opacity:.6; }

/* with a gate in place the photo backdrop and typeset names are
   redundant — the gate carries the monogram itself */
body.has-gate .seal__art,
body.has-gate .seal__names{ display:none; }

/* the seal must not fade; the doors are the transition. It only stops
   catching clicks once they have finished swinging. */
body.has-gate .seal{
  align-items:end;
  transition:visibility 0s linear 2s;
}
body.has-gate.is-open .seal{ opacity:1; visibility:hidden; }
body.has-gate .seal__in{
  padding-bottom:clamp(1rem,5vh,3rem);
  transition:opacity .55s var(--ease);
}
body.has-gate.is-open .seal__in{ opacity:0; }

/* the page behind settles forward as the doors part */
body.has-gate main,
body.has-gate .stage{
  transition:transform 2s cubic-bezier(.62,0,.18,1);
  transform:scale(1.06);
}
body.has-gate.is-open main,
body.has-gate.is-open .stage{ transform:none; }

@media (prefers-reduced-motion:reduce){
  .gate__leaf,.gate__shade{ transition:none; }
  body.has-gate main,body.has-gate .stage{ transition:none; transform:none; }
}

/* A supplied monogram, if there is one. Sized by height so a wide or a
   tall crest both land at the same optical weight. */
.seal__crest{
  display:block;
  width:auto;
  max-width:min(78vw,26rem);
  height:auto;
  max-height:min(42vh,20rem);
  margin:0 auto 2.6rem;
  filter:drop-shadow(0 4px 26px rgba(46,24,6,.5));
}
.seal__crest[hidden]{ display:none; }

/* Two names and a door. Nothing else — the date, the venue and the
   invitation itself all wait on the other side. */
.seal__names{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(3.2rem,16vw,6rem);
  line-height:1.02;
  margin-bottom:2.8rem;
  text-shadow:0 2px 28px rgba(46,24,6,.55);
}
.seal__names span{ display:block; }
.seal__names em{
  display:block;
  font-style:normal;
  font-size:.8em;
  line-height:.78;
  color:#F6DCA4;
  margin:.04em 0 .08em;
}

/* The music element. Kept at one pixel and fully transparent rather
   than display:none — a hidden media element can be deprioritised or
   refused playback outright, and this one has to keep running. */
.theme{
  position:fixed;
  left:0;
  bottom:0;
  width:1px;
  height:1px;
  opacity:.01;
  z-index:-1;
  pointer-events:none;
  border:0;
}

/* ═══════════════ THE STAGE ═══════════════ */
.stage{
  position:fixed;
  inset:0;
  z-index:0;
  overflow:hidden;
  background:#E7A55F;
}
.stage__plane{
  position:absolute;
  inset:0;
  overflow:hidden;
}
/* the optional hero video sits over the still, and fades in only once it
   is genuinely playing — so a slow file never shows a black rectangle */
.stage__video{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center 42%;
  opacity:0;
  transition:opacity 1.4s var(--ease);
  pointer-events:none;
}
.stage__video.is-on{ opacity:1; }

/* ── why the hero image is laid out oversized ────────────────
   Scaling a composited layer UP is what made this blurry: the browser
   rasterises the layer once and then stretches that texture, so a
   sharper source file changed nothing.

   So the image is laid out at twice its final size and scaled DOWN.
   scale(1) is the tight opening frame, rendered at natural resolution;
   scale(0.5) is the whole pavilion. Downscaling can never blur.

   Centring is done with left/top 50% plus translate(-50%,-50%) rather
   than negative offsets — negative offsets fought the inherited inset
   and tore the picture in half down the middle of the screen. */
/* The veil shares this geometry exactly — same size, same crop, same
   anchor — which is what makes the cut-out land on the building. */
.stage__plane--wide > img,
.veil > img{
  position:absolute;
  left:50%;
  top:50%;
  right:auto;
  bottom:auto;
  /* max-width:none is essential. The global reset caps images at
     max-width:100%, which quietly clamped this 200% width back down to
     100% and left the hero letterboxed in the middle of the screen. */
  max-width:none;
  /* Bigger layer = tighter opening frame. The closing frame is unaffected:
     the box is always ZOOM x viewport and lands at scale 1/ZOOM, so it
     resolves to exactly one viewport whatever ZOOM is. main.js reads the
     same numbers from zoomFor(). */
  width:250%;
  height:250%;
  /* the scale main.js lands on — OVERSCAN / ZOOM. Only the reduced-motion
     rule reads it, to park the picture at its resting framing. */
  --rest-scale:.416;
  object-fit:cover;
  /* The box always matches the viewport's aspect, which is taller than the
     photograph on every device — so cover only ever crops left and right,
     and the vertical half of object-position does nothing. Vertical framing
     is done by the animated lift in main.js instead. */
  object-position:center center;
  /* top is 50%, not 56%. At 56% the picture's centre sat below the stage
     centre, and at the end of the scroll — where the layer is exactly one
     viewport tall — that left a 6% strip of bare stage across the top of
     the screen. */
  transform:translate(-50%,-50%) scale(1);
}
/* above the names (z-index 4), below the front flowers (8) */
.veil{
  position:fixed;
  inset:0;
  z-index:6;
  overflow:hidden;
  pointer-events:none;
  opacity:0;
}

.stage__bloom{
  position:absolute;
  left:50%; top:44%;
  width:min(150vw,900px);
  aspect-ratio:1;
  transform:translate(-50%,-50%);
  background:radial-gradient(circle,rgba(255,232,190,.62) 0%,rgba(255,206,140,.28) 34%,transparent 68%);
  mix-blend-mode:screen;
  pointer-events:none;
}
/* keeps hero type legible over a busy photograph */
.stage__wash{
  position:absolute;
  inset:0;
  /* Warm amber, not brown, and much lighter at the top than it was. The
     old .34 of rgba(74,46,18) read as a grey-black band laid across the
     sunset — obvious on a phone, where the sky fills the upper third. The
     names carry their own scrim now, so this no longer has to do that job
     on its own. The foot stays a little stronger: it is what keeps the
     "Our story" cue legible over bright marble. */
  background:
    linear-gradient(180deg,rgba(150,86,34,.15) 0%,rgba(150,86,34,.04) 30%,rgba(150,86,34,0) 50%),
    linear-gradient(0deg,rgba(96,56,20,.36) 0%,rgba(96,56,20,.08) 26%,rgba(96,56,20,0) 52%);
}

/* painted stand-in, used until the photographs are dropped in */
.stage__paint{ position:absolute; inset:0; display:none;
  background:linear-gradient(180deg,
    #D9968E 0%, #E9A87C 16%, #F4C089 34%, #FBD9A2 52%,
    #FFE6B4 60%, #E3A868 62%, #CE9059 72%, #B77F50 79%,
    #EFE0CB 80%, #F8EEDF 100%);
}
.no-art .stage__paint{ display:block; }
.no-art .stage__plane{ display:none; }
.paint__sun{
  position:absolute; left:50%; top:57%;
  width:min(46vw,230px); aspect-ratio:1;
  transform:translate(-50%,-50%);
  border-radius:50%;
  background:radial-gradient(circle,#FFF6DE 0%,#FFE7AE 38%,rgba(255,214,140,.5) 60%,transparent 72%);
}
.paint__sea{
  position:absolute; left:0; right:0; top:62%; height:18%;
  background:
    repeating-linear-gradient(180deg,rgba(255,255,255,.10) 0 1px,transparent 1px 7px),
    radial-gradient(ellipse 26% 90% at 50% 0%,rgba(255,236,190,.85),transparent 70%);
}
.paint__deck{
  position:absolute; left:0; right:0; bottom:0; height:22%;
  background:
    radial-gradient(ellipse 60% 90% at 50% 100%,rgba(255,240,214,.9),transparent 70%),
    linear-gradient(180deg,#EFE0CB,#FAF2E5);
}

/* ── particle canvases + grain ──────────────────────────────── */
.petals{
  position:fixed;
  inset:0;
  width:100%;
  height:100%;
  pointer-events:none;
}
.petals--back{ z-index:2; }
.petals--front{ z-index:8; }

.grain{
  position:fixed;
  inset:0;
  z-index:9;
  pointer-events:none;
  opacity:.30;
  mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='.5'/></svg>");
}

/* ── skip link ──────────────────────────────────────────────── */
.skip{
  position:fixed;
  z-index:110;
  top:.5rem; left:.5rem;
  padding:.7rem 1rem;
  background:var(--ink);
  color:var(--cream);
  font-size:.8rem;
  border-radius:8px;
  text-decoration:none;
  transform:translateY(-160%);
  transition:transform .25s var(--ease);
}
.skip:focus{ transform:none; }

/* ═══════════════ HERO ═══════════════ */
main{ position:relative; z-index:4; }

/* The hero's HEIGHT is the length of the camera move. 230svh gives the
   pull-back about a screen and a half of scrolling — long enough to feel
   deliberate, short enough that nobody wonders if the page is stuck. */
.hero{
  position:relative;
  height:210vh;
  height:210svh;
}
/* holds the type still while the photograph opens out behind it.
   svh, not dvh: iOS then does not reflow every time the URL bar hides. */
.hero__pin{
  position:sticky;
  top:0;
  height:100vh;
  height:100svh;
  display:flex;
  flex-direction:column;
  /* The names ride high, in the open sky above the dome. They used to be
     centred, which put them straight over the couple — the one part of
     the photograph nobody wants covered. */
  justify-content:flex-start;
  align-items:center;
  padding:calc(env(safe-area-inset-top) + 3rem) var(--pad)
          calc(env(safe-area-inset-bottom) + 2rem);
  text-align:center;
  color:var(--cream);
}
.hero__type{
  position:relative;
  will-change:transform,opacity;
}
/* A scrim that travels with the type instead of sitting on the whole
   photograph. Cream lettering over a lit sunset has almost no contrast;
   this puts a soft warm shadow behind the words only, so the picture
   stays bright everywhere else. */
.hero__type::before{
  content:"";
  position:absolute;
  left:50%;
  top:50%;
  /* Sized to the words now that they sit at the top. At the old 116vh it
     reached most of the way down the picture, dimming the couple — which
     is exactly what this frame is meant to show off. */
  width:min(150vw,72rem);
  height:min(80vh,42rem);
  transform:translate(-50%,-50%);
  z-index:-1;
  pointer-events:none;
  /* `ellipse 50% 50%` — an EXPLICIT radius of half the box, not the
     default farthest-corner. Farthest-corner scales the ellipse out to the
     box corners, which leaves the left and right edge midpoints at only
     70.7% of the radius: still ~5% opaque when the box ends, so the scrim
     cut off in a hard vertical line down each side of a wide screen.
     Sized this way the gradient is fully transparent well inside its own
     edge, and there is nothing to see a seam at. */
  background:radial-gradient(ellipse 50% 50% at center,
    rgba(52,28,8,.58) 0%,
    rgba(52,28,8,.44) 34%,
    rgba(52,28,8,.20) 60%,
    rgba(52,28,8,0)   82%);
}
.hero__eyebrow{
  font-size:.66rem;
  font-weight:300;
  letter-spacing:.36em;
  text-transform:uppercase;
  color:rgba(255,250,242,.78);
  margin-bottom:1.1rem;
  text-shadow:0 1px 2px rgba(46,24,6,.9), 0 2px 16px rgba(46,24,6,.8);
}
.hero__names{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(3rem,17.5vw,7rem);
  line-height:.96;
  letter-spacing:.005em;
  text-shadow:0 1px 3px rgba(46,24,6,.42), 0 4px 30px rgba(46,24,6,.6);
}
.hero__name{ display:block; }
/* The ampersand is set in Italianno, whose glyphs sit small inside their
   em box — at .48em it all but vanished between two large names. It
   needs roughly two thirds of the name size to read as a peer. */
.hero__weds{
  display:block;
  font-size:.78em;
  line-height:.78;
  color:#F6DCA4;
  margin:.04em 0 .06em;
  /* Nudged down to sit centred between the two names. position:relative
     rather than margin on purpose — it moves the glyph alone and leaves
     Deepika and Bharat exactly where they were. Increase to drop it
     further; it cannot push the names apart. */
  position:relative;
  top:.22em;
  text-shadow:0 1px 3px rgba(46,24,6,.5), 0 3px 24px rgba(46,24,6,.55);
}
.flourish{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:.8rem;
  margin:1.5rem auto 1.2rem;
  max-width:15rem;
}
.flourish i{
  flex:1;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--gold-lt),transparent);
}
.flourish b{ font-size:.6rem; color:var(--gold-lt); }

.hero__meta{
  font-size:.78rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:rgba(255,250,242,.92);
  text-shadow:0 1px 2px rgba(46,24,6,.92), 0 2px 18px rgba(46,24,6,.85);
}
.hero__place{
  margin-top:.55rem;
  font-family:var(--f-ser);
  font-size:1.05rem;
  font-style:italic;
  color:rgba(255,250,242,.8);
  text-shadow:0 1px 2px rgba(46,24,6,.92), 0 2px 18px rgba(46,24,6,.85);
}

.cue{
  position:absolute;
  left:50%;
  bottom:calc(env(safe-area-inset-bottom) + 1.4rem);
  transform:translateX(-50%);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.6rem;
  font-size:.62rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:rgba(255,250,242,.75);
  text-decoration:none;
}
.cue__line{
  width:1px; height:34px;
  background:linear-gradient(180deg,var(--gold-lt),transparent);
  animation:drop 2.2s var(--ease) infinite;
  transform-origin:top;
}
@keyframes drop{ 0%{transform:scaleY(0);opacity:0} 40%{transform:scaleY(1);opacity:1} 100%{transform:scaleY(1) translateY(34px);opacity:0} }

/* ═══════════════ PAPER ═══════════════ */
main{ width:100%; max-width:100%; }
/* No hard edge between the photograph and the page. The paper has NO
   background colour — only gradients — so its first 46vh is transparent
   and the sunset shows straight through it, thickening into solid paper
   as you read on. A linear-gradient holds its final colour forever, so
   everything past 46vh is opaque without needing a colour underneath. */
.paper{
  position:relative;
  background-color:transparent;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='p'><feTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='4'/><feColorMatrix type='saturate' values='0'/></filter><rect width='180' height='180' filter='url(%23p)' opacity='.055'/></svg>"),
    radial-gradient(ellipse 130% 46vh at 50% 0%,rgba(240,199,138,.5),transparent 70%),
    linear-gradient(180deg,
      rgba(251,243,231,0)    0,
      rgba(251,243,231,.30) 14vh,
      rgba(251,243,231,.80) 30vh,
      rgba(251,243,231,1)   48vh);
}
/* the first section needs room to clear the dissolve before it is read */
.paper > .sect:first-child{ padding-top:calc(var(--sect) + 26vh); }

.sect{
  padding:var(--sect) var(--pad);
  max-width:44rem;
  margin-inline:auto;
  text-align:center;
}
/* centred text needs a tighter measure than ragged-left text, or the
   eye loses the start of each line */
.prose p{ max-width:34rem; margin-inline:auto; }
.place__acts{ justify-content:center; }
.fld label,.fld legend{ text-align:center; }
.step{ margin-inline:auto; }

/* ── story ──────────────────────────────────────────────────── */
.prose p{
  font-family:var(--f-ser);
  font-size:1.2rem;
  line-height:1.62;
  color:var(--ink-2);
  margin-bottom:1.4rem;
}
.prose__close{
  font-size:1.35rem !important;
  color:var(--ink) !important;
  font-style:italic;
  padding-top:.8rem;
  border-top:1px solid rgba(192,145,63,.28);
}

/* ── the card ───────────────────────────────────────────────── */
.card{
  position:relative;
  background:var(--cream);
  padding:2px;
  box-shadow:
    0 30px 60px -30px rgba(120,74,20,.5),
    0 2px 0 rgba(255,255,255,.7) inset;
  background-image:linear-gradient(150deg,var(--gold-lt),var(--gold) 30%,var(--gold-dk) 55%,var(--gold-lt) 100%);
}
.card__in{
  background:var(--cream);
  padding:clamp(1.8rem,7vw,3.4rem) clamp(1.2rem,5.5vw,2.8rem);
  text-align:center;
  outline:1px solid rgba(192,145,63,.3);
  outline-offset:-9px;
}
.card__deva{
  font-family:var(--f-dev);
  font-size:.9rem;
  line-height:1.7;
  color:var(--gold-dk);
}
.card__gloss{
  margin-top:.7rem;
  font-family:var(--f-ser);
  font-style:italic;
  font-size:1rem;
  color:var(--ink-2);
}
.card__gloss span{
  display:block;
  margin-top:.5rem;
  font-family:var(--f-ui);
  font-style:normal;
  font-size:.62rem;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.rule{
  display:flex;
  align-items:center;
  gap:.75rem;
  margin:2rem auto;
  max-width:14rem;
}
.rule i{ flex:1; height:1px; background:linear-gradient(90deg,transparent,var(--gold),transparent); }
.rule b{ font-size:.55rem; color:var(--gold); }
.rule--sm{ margin:1.6rem auto; max-width:9rem; }

.card__fam{
  font-family:var(--f-ser);
  font-size:1.1rem;
  line-height:1.7;
  color:var(--ink);
}
.card__fam em{ font-style:normal; color:var(--gold-dk); font-size:1.35rem; }
.card__ask{
  margin:1.1rem auto 0;
  max-width:22rem;
  font-size:.76rem;
  line-height:1.9;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.card__names{
  margin:1.4rem 0 1.8rem;
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(2.3rem,12vw,3.6rem);
  line-height:1.02;
  color:var(--ink);
}
.card__names span{ display:block; }
.card__names em{
  display:block;
  font-style:normal;
  font-size:.5em;
  color:var(--gold-dk);
  margin:.04em 0;
}

.stamp{
  display:inline-block;
  padding:.9rem 1.6rem;
  border-top:1px solid rgba(192,145,63,.45);
  border-bottom:1px solid rgba(192,145,63,.45);
}
.stamp__day,.stamp__time{
  font-size:.68rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.stamp__date{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:.5rem;
  margin:.5rem 0;
  font-family:var(--f-ser);
  font-size:clamp(1.7rem,8vw,2.5rem);
  color:var(--gold-dk);
}
.stamp__date i{ width:4px; height:4px; border-radius:50%; background:var(--gold); }

.card__venue{
  margin-top:1.5rem;
  font-family:var(--f-ser);
  font-size:1.12rem;
  line-height:1.6;
  color:var(--ink);
}
.card__venue strong{ font-weight:500; }

.run{
  display:grid;
  gap:.55rem;
  max-width:22rem;
  margin-inline:auto;
  text-align:left;
}
.run li{ display:grid; grid-template-columns:5.2rem 1fr; align-items:baseline; gap:.6rem; }
.run span{
  font-size:.7rem;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--gold-dk);
}
.run b{
  font-family:var(--f-ser);
  font-weight:400;
  font-size:1.02rem;
  color:var(--ink-2);
}
.card__wear{
  margin-top:1.7rem;
  font-family:var(--f-ser);
  font-style:italic;
  font-size:.98rem;
  color:var(--ink-3);
}

/* ── countdown ──────────────────────────────────────────────── */
.count{ margin-top:var(--gap); text-align:center; }
.count__lede{
  font-size:.68rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--ink-3);
  margin-bottom:1.1rem;
}
.count__list{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:.5rem;
  margin-bottom:1.8rem;
}
.count__list li{
  padding:.9rem .2rem;
  background:linear-gradient(180deg,rgba(255,255,255,.75),rgba(244,231,212,.5));
  border:1px solid rgba(192,145,63,.26);
  border-radius:12px;
}
.count__list b{
  display:block;
  font-family:var(--f-ser);
  font-weight:400;
  font-size:clamp(1.5rem,8vw,2.2rem);
  line-height:1;
  color:var(--gold-dk);
  font-variant-numeric:tabular-nums;
}
.count__list span{
  display:block;
  margin-top:.35rem;
  font-size:.58rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--ink-3);
}

/* ── portraits ──────────────────────────────────────────────── */
.couple__grid{ display:grid; gap:2.4rem; justify-items:center; }
.port{ max-width:22rem; text-align:center; will-change:transform; }
.port__arch{
  position:relative;
  width:min(72vw,17rem);
  aspect-ratio:3/4.1;
  margin:0 auto 1.4rem;
  padding:9px;
  background:linear-gradient(150deg,var(--gold-lt),var(--gold) 40%,var(--gold-dk) 70%,var(--gold-lt));
  /* a cusped arch: rounded top, square foot */
  border-radius:50% 50% 10px 10px / 34% 34% 10px 10px;
  box-shadow:0 26px 50px -26px rgba(120,74,20,.6);
}
.port__img{
  width:100%; height:100%;
  border-radius:50% 50% 6px 6px / 34% 34% 6px 6px;
  background:linear-gradient(160deg,var(--peach),var(--sunset));
  background-size:cover;
  background-position:center 28%;
}
.port__img[data-loaded]{ background-blend-mode:normal; }
.port__name{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:2.2rem;
  color:var(--ink);
}
.port__rel{
  margin:.3rem 0 .8rem;
  font-size:.66rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--gold-dk);
}
.port__line{
  font-family:var(--f-ser);
  font-size:1.05rem;
  line-height:1.6;
  color:var(--ink-2);
}
.couple__amp{
  font-size:3.4rem;
  color:var(--gold);
  line-height:.5;
}

/* ── the invitation line ────────────────────────────────────── */
.lede{
  font-family:var(--f-ser);
  font-size:clamp(1.35rem,5.4vw,1.9rem);
  font-weight:300;
  line-height:1.5;
  color:var(--ink);
  text-align:center;
  max-width:30rem;
  margin-inline:auto;
}
.stamp--solo{
  display:block;
  width:fit-content;
  margin:2.6rem auto 0;
  padding:1rem 2rem;
  text-align:center;
}
.stamp--solo .stamp__date{ margin:0; }

/* ── the families ───────────────────────────────────────────
   The formal half of the invitation. Set quieter and more upright than
   the couple's own sections — this is the parents speaking, not them. */
/* Each name leads, with its parentage underneath — the reading order of a
   printed invitation. Before, the name sat at the FOOT of its block behind
   a role label, the parents' names and a line of invitation wording, with
   a rule between the two: Bharat and Deepika ended up the better part of a
   phone screen apart. The script "and" now carries the join, and the two
   names sit close enough to read as one pair. */
.fam{ padding:0; }
.fam__who{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(2.4rem,10vw,3.4rem);
  line-height:1.05;
  color:var(--gold-dk);
}
.fam__of{
  margin-top:.75rem;
  font-size:.72rem;
  line-height:1.95;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--ink-3);
}
/* The hinge. Italianno sits small and high inside its em box, so it needs
   a generous size and a tight line-height to read as a peer of the names
   rather than a stray word floating between them. */
.fam__join{
  margin:.45rem 0 .3rem;
  font-family:var(--f-scr);
  font-weight:400;
  font-size:clamp(2.2rem,9vw,3rem);
  line-height:.9;
  color:var(--gold);
}
.fam__bless{
  margin-top:1.9rem;
  padding-top:1.5rem;
  border-top:1px solid rgba(192,145,63,.3);
  font-size:.68rem;
  line-height:1.95;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--ink-3);
}
.fam__bless strong{ font-weight:400; color:var(--ink-2); }

/* ── scripture ──────────────────────────────────────────────── */
.verse{
  position:relative;
  margin-top:3rem;
  padding:2rem 0 0;
  border-top:1px solid rgba(192,145,63,.3);
  text-align:center;
}
.verse blockquote p{
  font-family:var(--f-ser);
  font-style:italic;
  font-size:clamp(1.15rem,4.6vw,1.4rem);
  line-height:1.6;
  color:var(--ink);
  max-width:32rem;
  margin-inline:auto;
}
.verse figcaption{
  margin-top:1.1rem;
  font-size:.66rem;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--gold-dk);
}

/* ── celebrations ───────────────────────────────────────────── */
.celebs__list{ display:grid; gap:1rem; }
.celeb{
  position:relative;
  padding:2rem 1.5rem;
  text-align:center;
  background:linear-gradient(180deg,rgba(255,255,255,.72),rgba(244,231,212,.44));
  border:1px solid rgba(192,145,63,.26);
  border-radius:16px;
}
/* the ceremony itself carries the gold edge; the rest are quieter */
.celeb--main{
  border-color:transparent;
  background:
    linear-gradient(var(--cream),var(--cream)) padding-box,
    linear-gradient(150deg,var(--gold-lt),var(--gold) 45%,var(--gold-dk) 75%,var(--gold-lt)) border-box;
  border:2px solid transparent;
  box-shadow:0 22px 44px -28px rgba(120,74,20,.55);
}
.celeb__mark{
  display:block;
  font-size:.62rem;
  color:var(--gold);
  margin-bottom:.9rem;
}
.celeb__name{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(1.8rem,7vw,2.4rem);
  line-height:1.1;
  color:var(--ink);
}
.celeb__when{
  margin:.55rem 0 1rem;
  font-size:.66rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--gold-dk);
}
.celeb__note{
  font-family:var(--f-ser);
  font-size:1.05rem;
  line-height:1.6;
  color:var(--ink-2);
  max-width:26rem;
  margin-inline:auto;
}
/* the single event carries the invitation itself, so it gets the size */
.celeb__note--lead{
  font-size:clamp(1.15rem,4.6vw,1.35rem);
  line-height:1.62;
  color:var(--ink);
  max-width:30rem;
}
/* ── the three facts ────────────────────────────────────────
   When, what time, where. Given room and an icon each, so a guest
   glancing at the page on a phone finds all three without reading. */
.details{
  display:grid;
  gap:2.4rem;
  margin-top:.6rem;
}
.detail{ display:grid; justify-items:center; }
.detail__icon{
  display:grid;
  place-items:center;
  width:56px;
  height:56px;
  margin-bottom:1rem;
  border-radius:50%;
  background:linear-gradient(180deg,rgba(255,255,255,.9),rgba(244,231,212,.6));
  box-shadow:inset 0 0 0 1px rgba(192,145,63,.34);
}
.detail__icon svg{
  width:26px;
  height:26px;
  fill:none;
  stroke:var(--gold-dk);
  stroke-width:1.3;
  stroke-linecap:round;
  stroke-linejoin:round;
}
.detail__k{
  font-family:var(--f-ser);
  font-weight:400;
  font-size:clamp(1.6rem,6.4vw,2.1rem);
  line-height:1.15;
  color:var(--ink);
}
.detail__v{
  margin-top:.35rem;
  font-family:var(--f-ui);
  font-size:.82rem;
  font-weight:300;
  letter-spacing:.14em;
  line-height:1.7;
  text-transform:uppercase;
  color:var(--ink-2);
}

/* for screen readers only — the icons carry no text otherwise */
.vh{
  position:absolute;
  width:1px; height:1px;
  padding:0; margin:-1px;
  overflow:hidden;
  clip:rect(0 0 0 0);
  white-space:nowrap;
  border:0;
}
.celebs .mapbox{ margin-top:2rem; }
.celebs .place__acts{ margin-top:1.6rem; }

/* ── gallery ────────────────────────────────────────────────
   Scroll-driven, not clicked. Each photograph is overscanned inside its
   frame — 128% tall, hung 14% above — so main.js can slide it against
   the scroll without ever exposing an edge. That counter-motion is what
   reads as depth: the frame moves with the page, the picture lags.

   Frames alternate width and alignment so the column has a rhythm
   rather than being a stack of identical rectangles. */
.gallery{
  display:grid;
  gap:clamp(2.6rem,9vw,4.5rem);
  margin-top:1rem;
}
.pic{ position:relative; width:100%; }
.pic__frame{
  position:relative;
  overflow:hidden;
  aspect-ratio:3/4;
  border-radius:14px;
  background:linear-gradient(160deg,var(--peach),var(--sunset));
  box-shadow:0 26px 50px -30px rgba(120,74,20,.6);
}
.pic__frame img{
  position:absolute;
  left:0;
  top:-14%;
  width:100%;
  height:128%;
  max-width:none;
  object-fit:cover;
  transform:translate3d(0,var(--shift,0px),0);
}
.pic__cap{
  margin-top:.85rem;
  font-family:var(--f-ser);
  font-style:italic;
  font-size:1rem;
  color:var(--ink-2);
}

/* the rhythm: wide-left, narrow-right, and a landscape crop every third */
.pic:nth-child(odd){  width:min(100%,30rem); margin-right:auto; margin-left:0; }
.pic:nth-child(even){ width:min(76%,24rem);  margin-left:auto;  margin-right:0; }
.pic:nth-child(3n) .pic__frame{ aspect-ratio:4/5; }
.pic:nth-child(4n) .pic__frame{ aspect-ratio:1/1; }

/* the caption follows its frame's alignment */
.pic:nth-child(odd)  .pic__cap{ text-align:left; }
.pic:nth-child(even) .pic__cap{ text-align:right; }

@media (prefers-reduced-motion:reduce){
  /* no counter-motion, so centre the picture in its frame */
  .pic__frame img{ top:0; height:100%; transform:none; }
}

/* ── map ────────────────────────────────────────────────────── */
.mapbox{
  position:relative;
  aspect-ratio:4/3.4;
  border-radius:16px;
  overflow:hidden;
  border:1px solid rgba(192,145,63,.35);
  box-shadow:0 24px 44px -26px rgba(120,74,20,.5);
  background:var(--paper-2);
}
.mapbox iframe{ width:100%; height:100%; border:0; filter:sepia(.24) saturate(1.05); }
.place__addr{
  margin:1.5rem 0;
  font-family:var(--f-ser);
  font-size:1.2rem;
  line-height:1.6;
  color:var(--ink);
}
.place__acts{ display:grid; gap:.7rem; margin-bottom:2.4rem; }
.facts{ display:grid; gap:1.1rem; }
.facts dt{
  font-size:.64rem;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--gold-dk);
  margin-bottom:.3rem;
}
.facts dd{
  font-family:var(--f-ser);
  font-size:1.05rem;
  line-height:1.55;
  color:var(--ink-2);
}

/* ── form ───────────────────────────────────────────────────── */
.rsvp__lede{
  font-family:var(--f-ser);
  font-size:1.15rem;
  line-height:1.6;
  color:var(--ink-2);
  margin-bottom:2.4rem;
}
.form{ display:grid; gap:1.4rem; }
.fld{ display:grid; gap:.5rem; }
.fld label,.fld legend{
  font-size:.66rem;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--gold-dk);
}
.fld__opt{ letter-spacing:.1em; color:var(--ink-3); text-transform:none; }
.fld input[type=text],
.fld input[type=tel],
.fld textarea{
  width:100%;
  min-height:52px;
  padding:.85rem 1rem;
  background:var(--cream);
  border:1px solid rgba(192,145,63,.34);
  border-radius:12px;
  font-family:var(--f-ser);
  font-size:1.05rem;
  transition:border-color .25s, box-shadow .25s;
}
.fld textarea{ min-height:auto; resize:vertical; line-height:1.5; }
.fld input:focus,.fld textarea:focus{
  outline:0;
  border-color:var(--gold);
  box-shadow:0 0 0 3px rgba(192,145,63,.16);
}
.fld.is-bad input,.fld.is-bad textarea{ border-color:#B4482E; }
.fld__err{ font-size:.76rem; color:#B4482E; min-height:0; }

.seg{ display:grid; grid-template-columns:repeat(3,1fr); gap:.5rem; }
.seg input{ position:absolute; opacity:0; width:0; height:0; }
.seg label{
  display:flex;
  align-items:center;
  justify-content:center;
  min-height:50px;
  border:1px solid rgba(192,145,63,.34);
  border-radius:12px;
  background:var(--cream);
  font-family:var(--f-ui);
  font-size:.8rem;
  letter-spacing:.1em;
  text-transform:none;
  color:var(--ink-2);
  cursor:pointer;
  transition:.25s var(--ease);
  -webkit-tap-highlight-color:transparent;
}
.seg input:checked + label{
  background:linear-gradient(145deg,#F0D79C,#D3A954);
  border-color:transparent;
  color:#3B2A12;
}
.seg input:focus-visible + label{ outline:2px solid var(--gold-dk); outline-offset:2px; }

.step{ display:grid; grid-template-columns:52px 1fr 52px; gap:.5rem; max-width:14rem; }
.step__b{
  height:52px;
  border:1px solid rgba(192,145,63,.34);
  border-radius:12px;
  background:var(--cream);
  font-size:1.4rem;
  line-height:1;
  color:var(--gold-dk);
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.step__b:active{ background:var(--paper-2); }
.step input{
  width:100%; height:52px;
  text-align:center;
  border:1px solid rgba(192,145,63,.34);
  border-radius:12px;
  background:var(--cream);
  font-family:var(--f-ser);
  font-size:1.3rem;
  -moz-appearance:textfield;
}
.step input::-webkit-outer-spin-button,
.step input::-webkit-inner-spin-button{ -webkit-appearance:none; margin:0; }

.fld--go{ gap:.9rem; margin-top:.4rem; }
.form__note{ font-size:.74rem; color:var(--ink-3); text-align:center; }
.form__status{ font-size:.88rem; text-align:center; color:var(--gold-dk); min-height:1.2em; }

/* ── foot ───────────────────────────────────────────────────── */
.foot{
  position:relative;
  padding:var(--sect) var(--pad) calc(env(safe-area-inset-bottom) + 3rem);
  text-align:center;
  color:var(--cream);
  overflow:hidden;
}
.foot__art{
  position:absolute;
  inset:0;
  background-image:var(--art-wide),linear-gradient(180deg,#E9A87C,#B77F50);
  background-position:center 30%;
  background-size:cover;
  background-repeat:no-repeat;
}
.foot__art::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(58,34,12,.72),rgba(58,34,12,.86));
}
.foot__in{ position:relative; max-width:34rem; margin-inline:auto; }
.foot__eyebrow{
  font-size:.66rem;
  letter-spacing:.34em;
  text-transform:uppercase;
  color:var(--gold-lt);
  margin-bottom:1.8rem;
}
.foot__line{
  font-family:var(--f-ser);
  font-size:clamp(1.1rem,4.4vw,1.3rem);
  line-height:1.65;
  color:rgba(255,250,242,.9);
  margin-bottom:.9rem;
}
.flourish--foot{ margin:2.2rem auto 1.8rem; max-width:12rem; }
.flourish--foot i{ background:linear-gradient(90deg,transparent,var(--gold-lt),transparent); }

.foot__sign{
  font-size:.66rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:rgba(255,250,242,.6);
  margin-bottom:.7rem;
}
.foot__tag{
  font-family:var(--f-ser);
  font-weight:300;
  font-size:clamp(1.8rem,9vw,2.8rem);
  line-height:1.1;
  color:var(--cream);
}

/* ── reveal ─────────────────────────────────────────────────── */
/* Parallax writes to --par rather than to transform, so an element can
   be both revealed and parallaxed without the two fighting over the
   same property. */
[data-reveal]{
  opacity:0;
  transform:translate3d(0,26px,0);
  transition:opacity .9s var(--ease), transform .9s var(--ease);
}
[data-reveal].is-in{
  opacity:1;
  transform:translate3d(0,var(--par,0px),0);
}
[data-par]{ transform:translate3d(0,var(--par,0px),0); }
/* an element that is both revealed and parallaxed fades only — a
   transition on transform would make every parallax frame lag .9s */
[data-reveal][data-par],
[data-reveal][data-par].is-in{
  transform:translate3d(0,var(--par,0px),0);
  transition:opacity .9s var(--ease);
}

/* ═══════════════ WIDER SCREENS ═══════════════ */
/* A 200%-of-viewport layer costs four times the GPU memory of a normal
   one. On a phone that is the difference between smooth and stuttering,
   so narrow screens get a 170% layer and a correspondingly gentler
   zoom — main.js reads the same numbers. */
@media (max-width:699px){
  .stage__plane--wide > img,
  .veil > img{
    width:190%;
    height:190%;
    --rest-scale:.547;
  }
}

@media (min-width:700px){
  /* a wide screen already shows the flower beds, so crop in less */
  .stage__plane--fore > img{ transform:scale(1.28); }
  .hero__pin{ padding-top:4rem; padding-bottom:var(--pad); }

  .place__acts{ grid-auto-flow:column; justify-content:center; }
  .facts{ grid-template-columns:repeat(3,1fr); gap:2rem; }
  .celebs__list{ grid-template-columns:1fr 1fr; gap:1.2rem; }
  .celeb--main{ grid-column:1/-1; }
  /* the three facts sit side by side once there is room */
  .details{ grid-template-columns:repeat(3,1fr); gap:1.6rem; align-items:start; }
  .form{ grid-template-columns:1fr 1fr; }
  .fld--seg,.fld:has(textarea),.fld--go{ grid-column:1/-1; }
  .count__list{ max-width:30rem; margin-inline:auto; }
}

@media (min-width:1024px){
  .sect{ max-width:52rem; }
  .couple__grid{
    grid-template-columns:1fr auto 1fr;
    align-items:center;
    gap:2rem;
  }
  .couple__amp{ font-size:5rem; }
  .card__in{ padding:4rem 3.6rem; }
  .mapbox{ aspect-ratio:16/8; }
}

/* ═══════════════ REDUCED MOTION ═══════════════ */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  [data-reveal]{ opacity:1; transform:none; }
  .cue__line{ opacity:.6; }
  /* main.js never runs its scroll loop here, so park the hero at its
     resting state instead of leaving it frozen mid-zoom */
  .stage__plane--wide > img{
    transform:translate(-50%,-50%) scale(var(--rest-scale));
  }
}
