/* Animation layer.
   Rule that keeps this safe: nothing is hidden unless html.js-anim is present,
   which JS only adds once it knows it can reveal things again. */

/* ---------- reveals ---------- */

[data-reveal] { transition: opacity .85s var(--ease-out), transform .85s var(--ease-out), clip-path 1s var(--ease-out); }

html.js-anim [data-reveal]:not(.is-revealed) { opacity: 0; }
html.js-anim [data-reveal="up"]:not(.is-revealed) { transform: translateY(38px); }
html.js-anim [data-reveal="down"]:not(.is-revealed) { transform: translateY(-28px); }
html.js-anim [data-reveal="left"]:not(.is-revealed) { transform: translateX(-44px); }
html.js-anim [data-reveal="right"]:not(.is-revealed) { transform: translateX(44px); }
html.js-anim [data-reveal="scale"]:not(.is-revealed) { transform: scale(.9); }
html.js-anim [data-reveal="rise"]:not(.is-revealed) { transform: translateY(60px) scale(.97); }
/* an arched curtain that wipes upward, like a jharokha opening */
html.js-anim [data-reveal="arch"]:not(.is-revealed) {
  clip-path: inset(100% 0 0 0);
  transform: translateY(20px);
}
html.js-anim [data-reveal="arch"].is-revealed { clip-path: inset(0 0 0 0); }
html.js-anim [data-reveal="blur"]:not(.is-revealed) { filter: blur(12px); transform: scale(1.04); }

/* ---------- split words ---------- */

.w-out { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .06em; }
.w-in { display: inline-block; will-change: transform; }
html.js-anim [data-split]:not(.is-revealed) .w-in { transform: translateY(105%) rotate(4deg); }
[data-split] .w-in {
  transition: transform .95s var(--ease-out);
  transition-delay: calc(var(--wi) * 55ms);
}
html.js-anim [data-split]:not(.is-revealed) { opacity: 1; }

/* ---------- split characters ----------
   Letters rise out of their own clipping box on a short stagger, so a heading
   assembles itself instead of sliding in as one block. Words stay unbreakable
   so a name never splits across two lines mid-letter. */

.c-word { display: inline-block; white-space: nowrap; }
.c-out { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .09em; }
.c-in { display: inline-block; will-change: transform; }
[data-split="chars"] .c-in {
  transition: transform 1s var(--ease-out);
  transition-delay: calc(var(--ci) * 28ms);
}
html.js-anim [data-split="chars"]:not(.is-revealed) .c-in {
  transform: translateY(110%) rotate(3deg);
}

/* ---------- ink wipe, for the script names ----------
   The script face joins its letters, so it is revealed by uncovering the word
   left to right — like it is being written — rather than by splitting it. */

[data-reveal="ink"] { transition: clip-path 1.6s var(--ease-out), opacity .6s linear; }
html.js-anim [data-reveal="ink"]:not(.is-revealed) {
  clip-path: inset(-18% 102% -18% -4%);
  opacity: 1;
}
html.js-anim [data-reveal="ink"].is-revealed { clip-path: inset(-18% -4% -18% -4%); }

/* ---------- the gate (jharokha doors) ---------- */

body.is-locked { overflow: hidden; }

/* Transparent, so the doors part onto the real invitation rather than a void.
   The two panels cover the viewport completely until they swing. */
.gate {
  position: fixed; inset: 0; z-index: 900;
  display: grid; place-items: center;
  perspective: 1800px; perspective-origin: 50% 45%;
  background: transparent;
}
.gate.is-done { display: none; }

/* A shaft of warm light widening between the doors as they open. */
.gate__glow {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 0;
  transform: translateX(-50%); pointer-events: none; z-index: 1;
  background: radial-gradient(ellipse at center,
    rgba(255, 246, 216, .5) 0%, rgba(240, 167, 42, .22) 45%, transparent 78%);
  opacity: 0;
  transition: width 1.9s cubic-bezier(.72, .02, .28, 1), opacity 1.9s ease;
}
.gate.is-open .gate__glow { width: 130%; opacity: 0; }
.gate.is-open .gate__glow { animation: glow-flare 1.9s ease forwards; }
@keyframes glow-flare {
  0% { opacity: 0; }
  35% { opacity: 1; }
  100% { opacity: 0; }
}

.gate__doors {
  position: absolute; inset: 0;
  display: flex; transform-style: preserve-3d;
}
.gate__door {
  position: relative; width: 50%; height: 100%;
  transform-style: preserve-3d;
  transition: transform 1.9s cubic-bezier(.72, .02, .28, 1), filter 1.9s ease;
  backface-visibility: hidden;
  overflow: hidden;
  background: var(--grad-door);
  box-shadow: 0 0 80px rgba(0, 0, 0, .5);
}
.gate__door--l { transform-origin: left center; }
.gate__door--r { transform-origin: right center; }

/* The gold frame follows the door edges, so CSS draws it — a stretched SVG
   border would thin out on one axis. */
.gate__door::after {
  content: ''; position: absolute; inset: clamp(8px, 1.4vmin, 18px);
  border: 2px solid rgba(216, 180, 90, .9);
  box-shadow: inset 0 0 0 1px rgba(216, 180, 90, 0), inset 0 0 0 7px rgba(216, 180, 90, .3);
  pointer-events: none;
}

/* Tiled lattice: a fixed tile size means the circles stay round however wide
   or short the door gets. */
.door__jaali {
  position: absolute; inset: 0; opacity: .3;
  background-image: var(--jaali-tile);
  background-size: 30px 30px;
}

/* Both carvings keep their aspect ratio; the arch hangs from the top of the
   door and the medallion sits on the bottom rail. */
.gate__door .door__arch,
.gate__door .door__medal {
  position: absolute; left: 0; right: 0; display: block;
  width: 100%; overflow: visible;
}
.gate__door .door__arch { top: 3%; height: 62%; }
.gate__door .door__medal { bottom: 4%; height: 25%; }

/* soft highlight down the edge where the two doors meet */
.door__edge {
  position: absolute; top: 0; bottom: 0; width: 10px;
  background: linear-gradient(90deg, transparent, rgba(255, 246, 216, .42), transparent);
  pointer-events: none;
}
.door__edge--l { right: -5px; }
.door__edge--r { left: -5px; }

.gate.is-open .gate__door--l { transform: rotateY(-105deg); filter: brightness(.55); }
.gate.is-open .gate__door--r { transform: rotateY(105deg); filter: brightness(.55); }

/* seam glow down the middle */
.gate__seam {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 3px;
  transform: translateX(-50%);
  background: linear-gradient(180deg, transparent, rgba(255, 246, 216, .75), transparent);
  opacity: .8; transition: opacity .6s ease;
}
.gate.is-open .gate__seam { opacity: 0; }

/* the latch / knocker the guest taps */
.gate__latch {
  position: relative; z-index: 3; text-align: center;
  transition: opacity .5s ease, transform .7s var(--ease-out);
  padding: 20px;
}
/* the jaali behind is busy — sink a soft scrim so the text reads */
.gate__latch::before {
  content: ''; position: absolute; z-index: -1;
  left: 50%; top: 50%; width: 220%; height: 250%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side,
    rgba(30, 6, 12, .95) 0%, rgba(30, 6, 12, .9) 38%,
    rgba(30, 6, 12, .6) 68%, rgba(30, 6, 12, 0) 100%);
}
.gate.is-open .gate__latch { opacity: 0; transform: scale(.86); pointer-events: none; }

.gate__ring {
  width: 108px; height: 108px; margin: 0 auto 22px; border-radius: 50%;
  border: 2px solid var(--gold); display: grid; place-items: center;
  background: radial-gradient(circle at 40% 34%, rgba(232, 200, 106, .3), rgba(0, 0, 0, .35));
  color: var(--gold-lit); font-family: var(--deva); font-size: 40px; line-height: 1;
  cursor: pointer; position: relative;
  box-shadow: 0 0 0 0 rgba(201, 162, 39, .5), inset 0 2px 14px rgba(0, 0, 0, .4);
  animation: knock 3s ease-in-out infinite;
  transition: transform .3s var(--ease-back);
}
.gate__ring:hover { transform: scale(1.07); }
.gate__ring:active { transform: scale(.95); }
@keyframes knock {
  0%, 100% { box-shadow: 0 0 0 0 rgba(201, 162, 39, .45), inset 0 2px 14px rgba(0, 0, 0, .4); }
  55% { box-shadow: 0 0 0 22px rgba(201, 162, 39, 0), inset 0 2px 14px rgba(0, 0, 0, .4); }
}

.gate__names {
  font-family: var(--script); font-size: clamp(46px, 11vw, 96px);
  line-height: .95; margin: 0 0 10px;
  filter: drop-shadow(0 3px 18px rgba(0, 0, 0, .7));
}
.gate__sub {
  font-family: var(--sans); font-size: 11px; letter-spacing: .38em;
  text-transform: uppercase; color: var(--gold-pale); opacity: .9;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .9);
}
.gate__hint {
  margin-top: 26px; font-size: 11px; letter-spacing: .26em;
  text-transform: uppercase; color: var(--gold-pale); opacity: .55;
  animation: pulse-dim 2.6s ease-in-out infinite;
}
@keyframes pulse-dim { 0%, 100% { opacity: .3; } 50% { opacity: .75; } }

/* The hero behind eases forward as the doors part. */
html.gate-open .hero .card-invite {
  animation: gate-settle 1.9s var(--ease-out);
}
@keyframes gate-settle {
  0% { transform: scale(.9) translateY(20px); opacity: .2; }
  100% { transform: none; opacity: 1; }
}

/* ---------- hanging garland strands ---------- */

.garland {
  position: absolute; top: 0; left: 0; right: 0; height: 0;
  pointer-events: none; z-index: 4;
}
.garland .strand {
  position: absolute; top: 0; transform-origin: 50% 0;
  transform: translateX(-50%);
  animation: sway var(--sway, 3.4s) ease-in-out infinite alternate;
  animation-delay: calc(var(--i) * -.34s);
}
@keyframes sway {
  from { transform: translateX(-50%) rotate(-2.2deg); }
  to { transform: translateX(-50%) rotate(2.2deg); }
}

/* ---------- parallax ---------- */

[data-parallax] { transform: translate3d(0, var(--py, 0px), 0); will-change: transform; }

/* ---------- tilt cards ---------- */

[data-tilt] { transition: transform .5s var(--ease-out), box-shadow .4s ease; transform-style: preserve-3d; }
[data-tilt].is-tilting { transition: transform .08s linear, box-shadow .4s ease; }
[data-tilt] .tilt-sheen {
  position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: radial-gradient(320px circle at var(--gx, 50%) var(--gy, 50%),
    rgba(255, 246, 216, .16), transparent 62%);
  opacity: 0; transition: opacity .35s ease;
}
[data-tilt].is-tilting .tilt-sheen { opacity: 1; }

/* ---------- scroll progress thread ---------- */

.thread {
  position: fixed; top: 0; bottom: 0; left: 14px; width: 2px; z-index: 30;
  background: rgba(201, 162, 39, .16); pointer-events: none;
}
.thread::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0;
  height: calc(var(--p, 0) * 100%);
  background: linear-gradient(180deg, var(--gold-lit), var(--marigold));
}
.thread::after {
  content: ''; position: absolute; left: 50%; top: calc(var(--p, 0) * 100%);
  width: 9px; height: 9px; margin: -4px 0 0 -4.5px; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #ffe08a, var(--marigold));
  box-shadow: 0 0 10px rgba(240, 167, 42, .8);
}
@media (max-width: 900px) { .thread { display: none; } }

/* ---------- floating rotation ---------- */

.spin-slow { animation: spin 90s linear infinite; }
.spin-slow-rev { animation: spin 120s linear infinite reverse; }
@keyframes spin { to { transform: rotate(360deg); } }

.float { animation: float 7s ease-in-out infinite; }
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-12px); }
}

/* ---------- petal canvas ---------- */

.petals {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 2;
}
.petals--fixed { position: fixed; z-index: 1; }

/* ---------- shimmer sweep on cards ---------- */

.sweep { position: relative; overflow: hidden; }
.sweep::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 246, 216, .18), transparent);
  transform: skewX(-18deg); opacity: 0;
}
.sweep:hover::after { animation: sweep 1.1s ease; }
@keyframes sweep {
  0% { left: -60%; opacity: 1; }
  100% { left: 120%; opacity: 0; }
}

/* ---------- reduced motion: strip everything kinetic ---------- */

@media (prefers-reduced-motion: reduce) {
  html.js-anim [data-reveal]:not(.is-revealed) {
    opacity: 1 !important; transform: none !important;
    clip-path: none !important; filter: none !important;
  }
  html.js-anim [data-split]:not(.is-revealed) .w-in { transform: none !important; }
  html.js-anim [data-split="chars"]:not(.is-revealed) .c-in { transform: none !important; }
  .gate__door, [data-reveal], [data-tilt], .c-in { transition: none !important; }
  .spin-slow, .spin-slow-rev, .float, .garland .strand,
  .gate__ring, .gate__hint, .gold-shimmer { animation: none !important; }
  .sweep:hover::after { animation: none !important; }
}
