/* ═══════════════════════════════════════════════════════════
   Raj Mahal · vowstory Utsav
   Mobile first. The first entirely pale template in the range —
   no dark section anywhere. Both hero artworks are cream inside
   (241.9 and 236.5), so no veil is used; the copy is held inside
   the arch instead. Sections separate by wash, hairline and
   ornament rather than by contrast.
   Signature: the palace horizon, a three-layer parallax diorama.
   ═══════════════════════════════════════════════════════════ */

/* ═══ the five families, served by us ═══
   Self-hosted since the 11 Sep 2026 redesign; index.html no longer links
   fonts.googleapis.com. A guest opening an invitation never agreed to
   anything, and the Google Fonts stylesheet made their browser announce
   itself to a third party before the first paint. Nine files, 151 KB total,
   in assets/fonts/.

   ⚠️ `font-display: swap` on every face: the page paints in the fallback
   immediately and re-flows when the woff2 lands. The alternative (`block`)
   holds the text invisible for up to three seconds, and this page opens on
   the couple's own names.

   ⚠️ Every family named anywhere in this file must appear here. Cinzel
   Decorative, Cinzel, Alegreya, Yesteryear and Noto Sans Gurmukhi are the
   complete set — Gurmukhi carries ੴ, which none of the others do. Naming a
   sixth family in a rule below would fall back silently to a system face. */
@font-face {
  font-family: "Cinzel Decorative";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/cinzeldeco-400.woff2) format("woff2");
}
@font-face {
  font-family: "Cinzel Decorative";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(assets/fonts/cinzeldeco-700.woff2) format("woff2");
}
@font-face {
  font-family: "Cinzel";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/cinzel-400.woff2) format("woff2");
}
@font-face {
  font-family: "Cinzel";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/cinzel-500.woff2) format("woff2");
}
@font-face {
  font-family: "Alegreya";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/alegreya-400.woff2) format("woff2");
}
@font-face {
  font-family: "Alegreya";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/alegreya-400i.woff2) format("woff2");
}
@font-face {
  font-family: "Yesteryear";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/yesteryear-400.woff2) format("woff2");
}
@font-face {
  font-family: "Noto Sans Gurmukhi";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/gurmukhi-400.woff2) format("woff2");
}
@font-face {
  font-family: "Noto Sans Gurmukhi";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/gurmukhi-500.woff2) format("woff2");
}

:root {
  --paper: #fdf6ea;
  --blush: #fbeadf;
  --blush-2: #f5dcce;
  --gold: #be8b2e;
  --gold-lt: #dcb158;
  --gold-pale: #f0dca8;
  --rose: #c4553f;
  --maroon: #1b2a4a;
  --indigo: #1b2a4a;
  --indigo-2: #111c33;
  --ink: #4a3427;
  --ink-2: #7a5f4a;
  --ink-3: #a38c74;
  --line: rgba(190, 139, 46, 0.3);

  --col: 480px;
  --pad: 24px;
  --gap: 78px;
  --es: cubic-bezier(0.22, 0.61, 0.36, 1);
  --eo: cubic-bezier(0.16, 1, 0.3, 1);
}

* {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--indigo-2);
  color: var(--ink);
  font-family: "Alegreya", Georgia, serif;
  font-size: 17px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
}
img {
  max-width: 100%;
  display: block;
}
sup {
  font-size: 0.56em;
  vertical-align: 0.5em;
}
body:not(.open) {
  overflow: hidden;
  height: 100%;
}
button {
  font: inherit;
  color: inherit;
}

#page {
  max-width: var(--col);
  margin: 0 auto;
  background: var(--paper);
  overflow: hidden;
  /* a faint grain so the flat cream reads as paper rather than a fill */
  background-image:
    repeating-linear-gradient(0deg, rgba(190, 139, 46, 0.014) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(190, 139, 46, 0.014) 0 1px, transparent 1px 3px);
  box-shadow: 0 0 80px rgba(74, 52, 39, 0.22);
  opacity: 0;
  transition: opacity 1s var(--es);
}
body.open #page {
  opacity: 1;
}

@media (min-width: 600px) {
  :root {
    --col: 640px;
    --pad: 42px;
    --gap: 96px;
  }
  body {
    font-size: 18px;
  }
}
@media (min-width: 960px) {
  :root {
    --col: 840px;
    --pad: 64px;
    --gap: 116px;
  }
  body {
    font-size: 19px;
  }
}
@media (min-width: 1400px) {
  :root {
    --col: 920px;
  }
}

/* ═══ COVER ═══ */
#cover {
  position: fixed;
  inset: 0;
  z-index: 100;
  max-width: var(--col);
  margin: 0 auto;
  background: var(--indigo-2);
  overflow: hidden;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    opacity 0.7s ease,
    transform 1.1s var(--eo);
}
.cv-panel {
  position: absolute;
  top: 0;
  height: 100%;
  width: 50.5%;
  overflow: hidden;
  transition: transform 1.25s var(--eo);
  will-change: transform;
}
.cv-panel::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100vw;
  background:
    radial-gradient(
      ellipse 58% 40% at 50% 42%,
      rgba(52, 74, 118, 0.85) 0%,
      rgba(27, 42, 74, 0) 72%
    ),
    linear-gradient(168deg, #22335a 0%, #1b2a4a 54%, #0e1830 100%);
}
.cv-l {
  left: 0;
}
.cv-r {
  right: 0;
}
.cv-l::before {
  left: 0;
}
.cv-r::before {
  right: 0;
}
.cv-edge {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  z-index: 2;
  background: linear-gradient(
    180deg,
    transparent,
    var(--gold) 22%,
    var(--gold) 78%,
    transparent
  );
  opacity: 0.55;
}
.cv-l .cv-edge {
  right: 0;
}
.cv-r .cv-edge {
  left: 0;
}

.cv-dust {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
}
.cv-dust i {
  position: absolute;
  border-radius: 50%;
  background: var(--gold-pale);
  filter: blur(0.4px);
  animation: rise linear infinite;
  opacity: 0;
}
@keyframes rise {
  0% {
    transform: translateY(0) scale(0.7);
    opacity: 0;
  }
  12% {
    opacity: 0.6;
  }
  85% {
    opacity: 0.35;
  }
  100% {
    transform: translateY(-92vh) scale(1.15);
    opacity: 0;
  }
}

.cv-stage {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition:
    opacity 0.55s ease,
    transform 1s var(--eo);
}

/* ── the phulkari bagh ──
   Real bagh is worked in slanted satin stitch, the whole ground covered. Each
   bar below is one stitch; they arrive in rows from the hem upward, the way
   the cloth is actually embroidered, then two gold rings close around it. */
.cv-phul {
  width: min(280px, 72%);
  height: auto;
}
.cv-phul rect {
  opacity: 0;
  animation: stitch 0.42s var(--eo) forwards;
}
.cv-phul .ph-ring {
  fill: none;
  stroke: var(--gold-lt);
  stroke-width: 1.1;
  stroke-dasharray: 760;
  stroke-dashoffset: 760;
  animation: draw 2s var(--eo) 1.5s forwards;
}
.cv-phul .ph-ring2 {
  stroke-width: 0.6;
  opacity: 0.55;
  animation-delay: 1.75s;
}
@keyframes stitch {
  from {
    opacity: 0;
    transform: translateY(7px) scaleY(0.3);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

/* ── kalire ──
   The golden danglers tied to a Punjabi bride's bangles. They hang from the
   very top edge and swing on their own cords. */
.kalire {
  position: absolute;
  top: 0;
  z-index: 4;
  width: clamp(38px, 10vw, 64px);
  height: auto;
  transform-origin: 50% 0;
  opacity: 0;
  animation:
    klIn 1.1s var(--eo) 0.5s forwards,
    klSway 6.5s ease-in-out 1.6s infinite;
}
.kalire-l {
  left: 9%;
}
.kalire-r {
  right: 9%;
  animation-delay: 0.68s, 1.9s;
  animation-duration: 1.1s, 7.8s;
}
@keyframes klIn {
  from {
    opacity: 0;
    transform: translateY(-70px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes klSway {
  0%,
  100% {
    transform: rotate(-3.4deg);
  }
  50% {
    transform: rotate(3.4deg);
  }
}
.kalire path,
.kalire circle {
  fill: none;
  stroke: var(--gold-lt);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.kl-cord {
  stroke: var(--gold);
  stroke-width: 1.4;
  opacity: 0.7;
}
.kl-dome {
  fill: rgba(240, 220, 168, 0.16);
}
.kl-dome2 {
  opacity: 0.7;
}
.kl-drops path {
  stroke-width: 1.2;
  opacity: 0.75;
}
.kl-drops circle {
  fill: rgba(240, 220, 168, 0.28);
  stroke-width: 1.4;
}

.cv-corner {
  position: absolute;
  width: 24px;
  height: 24px;
  opacity: 0;
  animation: fadeUp 0.9s var(--eo) 1.7s forwards;
}
.cv-corner::before,
.cv-corner::after {
  content: "";
  position: absolute;
  background: var(--gold);
}
.cv-corner::before {
  width: 100%;
  height: 1px;
}
.cv-corner::after {
  width: 1px;
  height: 100%;
}
.c-tl {
  top: 10%;
  left: 12%;
}
.c-tl::before {
  top: 0;
  left: 0;
}
.c-tl::after {
  top: 0;
  left: 0;
}
.c-tr {
  top: 10%;
  right: 12%;
}
.c-tr::before {
  top: 0;
  right: 0;
}
.c-tr::after {
  top: 0;
  right: 0;
}
.c-bl {
  bottom: 10%;
  left: 12%;
}
.c-bl::before {
  bottom: 0;
  left: 0;
}
.c-bl::after {
  bottom: 0;
  left: 0;
}
.c-br {
  bottom: 10%;
  right: 12%;
}
.c-br::before {
  bottom: 0;
  right: 0;
}
.c-br::after {
  bottom: 0;
  right: 0;
}
@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(9px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.cv-tap {
  position: absolute;
  bottom: min(13vh, 104px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  opacity: 0;
  animation: tapIn 1.1s var(--eo) 2.2s forwards;
}
@keyframes tapIn {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.cv-ring {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 1px solid rgba(240, 220, 168, 0.55);
  position: relative;
  animation: breathe 3s ease-in-out infinite;
}
.cv-ring::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(220, 177, 88, 0.5);
  animation: halo 3s ease-out infinite;
}
@keyframes breathe {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(0.9);
  }
}
@keyframes halo {
  0% {
    transform: scale(1);
    opacity: 0.7;
  }
  70%,
  100% {
    transform: scale(2);
    opacity: 0;
  }
}
/* "Tap to open" is now gold LEAF rather than flat gold: a five-stop gradient
   slid across the glyphs forever, so the letters catch light the way foil
   does. `background-clip: text` paints the gradient through the letterforms
   and `text-fill-color: transparent` lets it show; the `color: transparent`
   after it is the fallback for anything that has the clip but not the
   prefixed fill property. ⚠️ This is the ONE piece of text on the cover, so
   if both properties were unsupported the words would vanish — every engine
   we ship to has had `background-clip: text` since 2016. */
.cv-word {
  font-family: "Cinzel", serif;
  font-size: 12.5px;
  letter-spacing: 0.48em;
  text-transform: uppercase;
  text-indent: 0.48em;
  background: linear-gradient(
    100deg,
    #8a6e36 0%,
    #c8a961 26%,
    #f4e4b6 48%,
    #dec488 56%,
    #8a6e36 82%
  );
  background-size: 230% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: cvShine 3.4s linear infinite;
}
@keyframes cvShine {
  to {
    background-position: 230% 0;
  }
}

#flash {
  position: fixed;
  inset: 0;
  z-index: 99;
  pointer-events: none;
  opacity: 0;
  max-width: var(--col);
  margin: 0 auto;
}
#flash.run {
  opacity: 1;
}
#flash .ray {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  transform: translateX(-50%) scaleY(0);
  background: linear-gradient(180deg, transparent, #fff8ec, transparent);
  box-shadow: 0 0 30px 8px rgba(255, 248, 236, 0.8);
}
#flash.run .ray {
  animation: rayUp 0.6s var(--eo) forwards;
}
@keyframes rayUp {
  0% {
    transform: translateX(-50%) scaleY(0);
    opacity: 0;
  }
  40% {
    opacity: 1;
  }
  100% {
    transform: translateX(-50%) scaleY(1);
    opacity: 0;
  }
}
#flash .bloom {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 180vmax;
  height: 180vmax;
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  background: radial-gradient(
    circle,
    rgba(255, 248, 236, 0.85) 0%,
    rgba(235, 211, 166, 0.35) 30%,
    rgba(245, 228, 216, 0) 60%
  );
}
#flash.run .bloom {
  animation: bloom 1.4s var(--eo) forwards;
}
@keyframes bloom {
  0% {
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
  }
  22% {
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0;
  }
}

body.opening #cover {
  transform: scale(1.06);
  opacity: 0;
}
body.opening .cv-l {
  transform: translateX(-102%) rotate(-1.4deg);
}
body.opening .cv-r {
  transform: translateX(102%) rotate(1.4deg);
}
body.opening .cv-stage {
  opacity: 0;
  transform: translateY(-22px) scale(0.94);
}
body.opened #cover {
  display: none;
}

/* ═══ ambient ═══ */
/* ⚠️ z-index 6, raised from 2 in the 11 Sep 2026 redesign. The printed
   border edges introduced then sit at z-index 1 and #page at 2, so the
   drifting motes at 2 were being painted level with the page content and
   were lost against it. 6 puts them over everything except the cover, the
   flash and the music button. Still pointer-events:none, so nothing they
   float across becomes unclickable. */
.amb {
  position: fixed;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s ease;
}
body.open .amb {
  opacity: 1;
}
.amb i {
  position: absolute;
  display: block;
  will-change: transform;
}
.amb .mote {
  border-radius: 50%;
  background: radial-gradient(circle, #fff6e4 0%, #d6ae6b 42%, rgba(184, 137, 63, 0) 72%);
  animation: rise2 linear infinite;
}
@keyframes rise2 {
  0% {
    transform: translate3d(0, 12vh, 0) scale(0.6);
    opacity: 0;
  }
  14% {
    opacity: var(--o);
  }
  86% {
    opacity: calc(var(--o) * 0.55);
  }
  100% {
    transform: translate3d(var(--dx), -108vh, 0) scale(1.1);
    opacity: 0;
  }
}
.amb .petal {
  border-radius: 62% 38% 60% 40%/50% 58% 42% 50%;
  background: linear-gradient(140deg, #f6d9ce, #c0766a);
  animation: fall linear infinite;
}
@keyframes fall {
  0% {
    transform: translate3d(0, -14vh, 0) rotate(0deg);
    opacity: 0;
  }
  12% {
    opacity: var(--o);
  }
  88% {
    opacity: calc(var(--o) * 0.5);
  }
  100% {
    transform: translate3d(var(--dx), 112vh, 0) rotate(var(--rot));
    opacity: 0;
  }
}

/* ═══ music ═══ */
.music {
  position: fixed;
  top: 18px;
  z-index: 90;
  right: max(16px, calc(50vw - var(--col) / 2 + 16px));
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(251, 242, 231, 0.86);
  border: 1px solid var(--line);
  backdrop-filter: blur(8px);
  display: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  color: var(--maroon);
  transition: transform 0.3s var(--es);
}
body.open .music {
  display: flex;
  animation: fadein 1s 0.9s backwards;
}
.music:hover {
  transform: scale(1.08);
}
.music svg {
  width: 20px;
  height: 20px;
  fill: currentColor;
  stroke: currentColor;
  position: relative;
  z-index: 2;
}
.music .ic-off {
  display: none;
}
.music[aria-pressed="false"] .ic-on {
  display: none;
}
.music[aria-pressed="false"] .ic-off {
  display: block;
}
.mu-ring {
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  opacity: 0;
}
.music[aria-pressed="true"] .mu-ring {
  animation: pulse 2.6s ease-out infinite;
}
@keyframes pulse {
  0% {
    opacity: 0.6;
    transform: scale(1);
  }
  70%,
  100% {
    opacity: 0;
    transform: scale(1.5);
  }
}
@keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* ═══ HERO ═══ */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: var(--paper);
}
/* ⚠️ The hero artwork is anchored to its TOP and sized to the full column
   width, not cropped to cover (11 Sep 2026 redesign). `cover` scaled the
   painting until it filled the box on both axes, which on a tall phone meant
   cutting the arch's crown off — the one part of the artwork the whole
   composition points at. `100% auto` from `center top` keeps the crown and
   lets the foot run past the bottom edge instead, where there is nothing but
   ground. The bleed shrank with it: -7% each way rather than -14%, because a
   width-fitted image has far less spare height to pan through. */
.hero-art {
  position: absolute;
  inset: -7% 0 -7%;
  background: url(assets/hero.webp) center top / 100% auto no-repeat;
  will-change: transform;
  animation: kb 18s var(--eo) forwards;
}
/* The slow push-in. Narrower now (107% → 100%, was 116% → 104%) so it ends
   exactly at the width the rule above declares, rather than 4% past it. */
@keyframes kb {
  from {
    background-size: 107% auto;
  }
  to {
    background-size: 100% auto;
  }
}
.hero-in {
  position: relative;
  z-index: 2;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 12vh 30px 16vh;
}
/* held inside the arch: at 390 the interior is 74% of the column, 56% above 600 */
.hero-in > * {
  max-width: min(72%, 32rem);
  margin-left: auto;
  margin-right: auto;
}
@media (min-width: 600px) {
  .hero-in {
    padding: 13vh 56px 15vh;
  }
  .hero-in > * {
    max-width: min(54%, 32rem);
  }
}

/* Half again as large as it was (was clamp(74px, 18vw, 108px)). The deity is
   the first thing on the invitation and the couple chose it; at 74px on a
   phone it read as a watermark. */
.deity {
  width: clamp(104px, 25vw, 150px);
  margin: 0 auto 14px;
  filter: drop-shadow(0 6px 18px rgba(74, 52, 39, 0.2));
  animation: glow 6s ease-in-out infinite;
}
@keyframes glow {
  0%,
  100% {
    filter: drop-shadow(0 6px 16px rgba(74, 52, 39, 0.18));
  }
  50% {
    filter: drop-shadow(0 8px 28px rgba(184, 137, 63, 0.4));
  }
}
/* Gurmukhi is not in Cinzel or Alegreya, so the invocation names a stack
   that carries the script rather than falling back to a default */
.invocation {
  margin: 0 0 16px;
  font-size: 17px;
  letter-spacing: 0.06em;
  color: var(--gold);
  font-family: "Noto Sans Gurmukhi", "Gurmukhi MN", "Raavi", sans-serif;
}
.eyebrow {
  margin: 0 0 12px;
  font-family: "Cinzel", serif;
  font-size: 10.5px;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--gold);
}
.hero-names {
  margin: 0;
  font-family: "Cinzel Decorative", serif;
  font-weight: 400;
  font-size: clamp(27px, 7vw, 46px);
  line-height: 1.24;
  letter-spacing: 0.045em;
  color: var(--indigo);
}
.hero-names .ln {
  display: block;
}
.hero-names .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(24px);
  animation: chIn 0.9s var(--eo) forwards;
}
@keyframes chIn {
  to {
    opacity: 1;
    transform: none;
  }
}
.hero-names em {
  display: block;
  font-family: "Yesteryear", cursive;
  font-style: normal;
  font-size: 0.9em;
  color: var(--gold);
  margin: 0;
  line-height: 1.15;
  opacity: 0;
  animation: chIn 1s var(--eo) 1.1s forwards;
}
.hair {
  display: block;
  width: min(200px, 54%);
  height: 1px;
  margin: 18px auto;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.hero-date {
  margin: 0 0 10px;
  font-family: "Cinzel", serif;
  font-size: clamp(12px, 3vw, 15px);
  letter-spacing: 0.2em;
  color: var(--ink);
  text-transform: uppercase;
}
.hero-venue {
  margin: 0;
  font-size: clamp(15px, 3.2vw, 17px);
  font-style: italic;
  color: var(--ink-2);
  line-height: 1.55;
}
.hero-venue span {
  font-style: normal;
  font-size: 0.84em;
  letter-spacing: 0.07em;
  color: var(--ink-3);
}

.hang {
  position: absolute;
  top: 0;
  z-index: 3;
  pointer-events: none;
  transform-origin: 50% 0;
  opacity: 0;
}
body.open .hang {
  animation:
    hangIn 1.1s var(--eo) forwards,
    sway 7s ease-in-out 1.1s infinite;
}
body.open .hang-b {
  animation:
    hangIn 1.1s var(--eo) 0.18s forwards,
    sway 8.6s ease-in-out 1.28s infinite;
}
@keyframes hangIn {
  from {
    opacity: 0;
    transform: translateY(-56px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes sway {
  0%,
  100% {
    transform: rotate(-2deg);
  }
  50% {
    transform: rotate(2deg);
  }
}
.hang img {
  width: 100%;
}
.hang-a {
  left: 6%;
  width: clamp(22px, 6vw, 40px);
}
.hang-b {
  right: 7%;
  width: clamp(20px, 5.4vw, 36px);
}
@media (min-width: 960px) {
  .hang-a {
    left: 13%;
  }
  .hang-b {
    right: 14%;
  }
}

.cue {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 26px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition:
    opacity 0.5s ease,
    transform 0.5s ease;
}
.cue span:first-child {
  font-family: "Cinzel", serif;
  font-size: 10px;
  letter-spacing: 0.38em;
  text-transform: uppercase;
  color: var(--gold);
}
.cue-line {
  width: 1px;
  height: 40px;
  background: linear-gradient(180deg, var(--gold), transparent);
  animation: drop 2.4s ease-in-out infinite;
}
@keyframes drop {
  0% {
    transform: scaleY(0.2);
    transform-origin: top;
  }
  55% {
    transform: scaleY(1);
    transform-origin: top;
  }
  56% {
    transform-origin: bottom;
  }
  100% {
    transform: scaleY(0);
    transform-origin: bottom;
  }
}
.cue.gone {
  opacity: 0;
  transform: translateY(14px);
}

/* ═══ sections ═══ */
.sec {
  position: relative;
  padding: var(--gap) var(--pad);
  overflow: hidden;
  text-align: center;
  background: var(--paper);
}
.sec-blush {
  background: var(--indigo);
  color: #efe4d4;
  box-shadow:
    inset 0 1px 0 rgba(240, 220, 168, 0.22),
    inset 0 -1px 0 rgba(240, 220, 168, 0.22);
}
.sec-blush .h2 {
  color: var(--gold-pale);
}
.sec-blush .eyebrow {
  color: var(--gold-lt);
}
.sec-blush .prose,
.sec-blush .rv-lead {
  color: #dccdb8;
}
.sec-blush::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse 72% 50% at 50% 24%,
    rgba(240, 220, 168, 0.1),
    transparent 72%
  );
}
.inner {
  position: relative;
  z-index: 2;
  max-width: 620px;
  margin: 0 auto;
}
.h2 {
  margin: 0 0 20px;
  font-family: "Cinzel", serif;
  font-weight: 400;
  font-size: clamp(24px, 5.4vw, 36px);
  line-height: 1.26;
  color: var(--indigo);
  letter-spacing: 0.05em;
}
/* the flourish draws itself once the heading lands — new to this template */
.h2 .ul {
  display: block;
  width: min(200px, 64%);
  height: auto;
  margin: 14px auto 0;
}
.h2 .ul path,
.h2 .ul circle {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.3;
  stroke-linecap: round;
}
.h2 .ul path {
  stroke-dasharray: 210;
  stroke-dashoffset: 210;
  transition: stroke-dashoffset 1.5s var(--eo) 0.25s;
}
.h2 .ul circle {
  opacity: 0;
  transition: opacity 0.5s ease 1.3s;
}
.h2.in .ul path {
  stroke-dashoffset: 0;
}
.h2.in .ul circle {
  opacity: 1;
}
.sec-blush .h2 .ul path,
.sec-blush .h2 .ul circle {
  stroke: var(--gold-lt);
}
.prose {
  margin: 0 auto 16px;
  max-width: 36ch;
  color: var(--ink-2);
}
.tag {
  margin: 26px 0 0;
  font-family: "Cinzel", serif;
  font-size: clamp(12px, 2.4vw, 14px);
  letter-spacing: 0.24em;
  color: var(--gold);
}
.tag-sm {
  font-size: 11.5px;
  letter-spacing: 0.28em;
  margin-top: 14px;
}
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity 1.05s var(--eo),
    transform 1.05s var(--eo);
}
.reveal.in {
  opacity: 1;
  transform: none;
}

.deco {
  position: absolute;
  z-index: 1;
  pointer-events: none;
}
/* rendered height always stays inside the section padding, so it cannot reach text */
.deco-lantern {
  width: clamp(15px, 3vw, 19px);
  right: 16px;
  top: 0;
  opacity: 0.6;
  animation: sway 8s ease-in-out infinite;
  transform-origin: 50% 0;
}

/* the same slanted satin stitch as the cover, as a section divider */
.stitch {
  display: block;
  height: 14px;
  background: var(--paper);
  background-image:
    repeating-linear-gradient(58deg, var(--rose) 0 2px, transparent 2px 11px),
    repeating-linear-gradient(58deg, var(--gold) 5px 7px, transparent 7px 16px);
  background-size: auto 100%;
  opacity: 0.5;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* ═══ THE BARAAT — the signature ═══
   Three lanes of ornaments, each translated horizontally at its own rate by
   the scroll handler, so the procession gains depth. Purely decorative: no
   text sits on it, so nothing can collide. */
.baraat {
  position: relative;
  height: clamp(140px, 32vw, 230px);
  overflow: hidden;
  background: var(--paper);
  isolation: isolate;
}
.baraat-sm {
  height: clamp(96px, 21vw, 150px);
}
.br-sky {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, var(--paper) 0%, #fbeadf 62%, #f5dcce 100%);
}
.br-lane {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  gap: clamp(30px, 8vw, 80px);
  padding: 0 4vw;
  white-space: nowrap;
  will-change: transform;
}
.br-lane img {
  flex: none;
}
.br-far {
  bottom: 26%;
  opacity: 0.34;
}
.br-far img {
  width: clamp(120px, 30vw, 230px);
}
.br-mid {
  bottom: 20%;
  opacity: 0.55;
}
.br-mid img {
  width: clamp(60px, 15vw, 116px);
}
.br-near {
  bottom: 9%;
  opacity: 0.95;
}
.br-near img {
  width: clamp(52px, 13vw, 104px);
}
.baraat-sm .br-mid img {
  width: clamp(44px, 11vw, 80px);
}
.baraat-sm .br-near img {
  width: clamp(38px, 9vw, 68px);
}
.br-floor {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 9%;
  background: linear-gradient(180deg, rgba(245, 220, 206, 0), rgba(238, 206, 186, 0.95));
  border-top: 1px solid var(--line);
}

/* ═══ FAMILIES — page two, on Hero_2 ═══
   Not a three-slice plate: Hero_2's lanterns and garland strands all end at
   different heights, so no horizontal band of it is vertically uniform (worst
   column spread 166 at every candidate). A tiling strip would have produced a
   dashed line down the sides. It is used full-bleed with `cover` instead — the
   interior is uniform, so cropping is harmless and the copy stays safe. */
.sec-fam {
  padding: var(--gap) var(--pad);
  /* Anchored to the top since 11 Sep 2026, for the same reason as .hero-art:
     the lantern chains hang from the upper edge and centring the crop cut
     their tops off on a tall viewport. */
  background: url(assets/fam.webp) center top/cover no-repeat;
  min-height: clamp(760px, 132vw, 900px);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* The copy sits on its own paper plate rather than on the artwork. Hero_2's
   interior is only clean between y25-72%, and the section height is
   content-driven, so no column width could guarantee the lower family block
   cleared the pavilions. At .955 alpha the plate reads 235+ over even the
   darkest element, so the collision is impossible by construction. */
.fam-in {
  width: 100%;
  max-width: min(84%, 30rem);
  text-align: center;
  position: relative;
  z-index: 2;
  margin: 0 auto;
  padding: clamp(30px, 7vw, 52px) clamp(22px, 6vw, 44px);
  background: rgba(253, 246, 234, 0.955);
  box-shadow:
    0 20px 60px rgba(27, 42, 74, 0.22),
    0 0 0 1px rgba(190, 139, 46, 0.28);
  backdrop-filter: blur(2px);
}
@media (min-width: 600px) {
  .fam-in {
    max-width: min(70%, 32rem);
  }
}
/* drawn corner brackets, so the plate reads as a card rather than a box */
.fam-corner {
  position: absolute;
  width: 16px;
  height: 16px;
  pointer-events: none;
}
.fam-corner::before,
.fam-corner::after {
  content: "";
  position: absolute;
  background: var(--gold);
}
.fam-corner::before {
  width: 100%;
  height: 1px;
}
.fam-corner::after {
  width: 1px;
  height: 100%;
}
.fc-tl {
  top: 9px;
  left: 9px;
}
.fc-tl::before {
  top: 0;
  left: 0;
}
.fc-tl::after {
  top: 0;
  left: 0;
}
.fc-tr {
  top: 9px;
  right: 9px;
}
.fc-tr::before {
  top: 0;
  right: 0;
}
.fc-tr::after {
  top: 0;
  right: 0;
}
.fc-bl {
  bottom: 9px;
  left: 9px;
}
.fc-bl::before {
  bottom: 0;
  left: 0;
}
.fc-bl::after {
  bottom: 0;
  left: 0;
}
.fc-br {
  bottom: 9px;
  right: 9px;
}
.fc-br::before {
  bottom: 0;
  right: 0;
}
.fc-br::after {
  bottom: 0;
  right: 0;
}
.fam-garland {
  position: absolute;
  top: -9%;
  right: -9%;
  width: clamp(18px, 4.4vw, 32px);
  z-index: 1;
  opacity: 0.7;
  transform-origin: 50% 0;
  animation: sway 9s ease-in-out infinite;
}

.seal {
  width: min(104px, 27%);
  margin: 0 auto 18px;
  border-radius: 50%;
  box-shadow:
    0 0 0 1px var(--line),
    0 0 0 6px var(--paper),
    0 0 0 7px rgba(184, 137, 63, 0.22);
}
.weds {
  margin: 32px 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: "Cinzel", serif;
  font-size: clamp(15px, 3.5vw, 20px);
  line-height: 1.4;
  color: var(--indigo);
}
.weds em {
  font-family: "Yesteryear", cursive;
  font-style: normal;
  font-size: 1.5em;
  color: var(--gold);
  display: flex;
  align-items: center;
  gap: 14px;
  line-height: 1;
}
.weds em::before,
.weds em::after {
  content: "";
  width: 30px;
  height: 1px;
  background: var(--line);
}
.side {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.side-name {
  margin: 0 0 8px;
  line-height: 1.2;
}
.side-role {
  margin: 0 0 6px;
  font-family: "Cinzel", serif;
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold);
}
.side-parents {
  margin: 0;
  font-family: "Alegreya", serif;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 26ch;
}

/* ═══ countdown ═══ */
.sec-count {
  padding-top: calc(var(--gap) * 0.45);
}
.chand {
  display: block;
  width: clamp(96px, 24vw, 168px);
  margin: 0 auto 22px;
  opacity: 0.9;
}
.clock {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  max-width: 400px;
  margin: 26px auto 0;
}
.unit {
  padding: 20px 4px 15px;
  position: relative;
  border: 1px solid var(--line);
  background: linear-gradient(
    180deg,
    rgba(240, 220, 168, 0.12),
    rgba(253, 246, 234, 0.03)
  );
}
.unit::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -1px;
  width: 26px;
  height: 1px;
  transform: translateX(-50%);
  background: var(--gold-lt);
}
.unit b {
  display: block;
  font-family: "Cinzel", serif;
  font-size: clamp(24px, 6.4vw, 34px);
  color: var(--gold-pale);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.unit i {
  display: block;
  margin-top: 10px;
  font-style: normal;
  font-family: "Cinzel", serif;
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(240, 220, 168, 0.6);
}

/* ═══ EVENTS — read as a programme, one after another ═══ */
.sec-events {
  padding-bottom: calc(var(--gap) + 10px);
}
.rail {
  margin-top: 30px;
}
.ev {
  position: relative;
  margin-bottom: 44px;
  text-align: center;
}
.ev:last-child {
  margin-bottom: 0;
}
/* the separator is in normal flow, so it can never land on text */
.ev-orn {
  display: block;
  width: min(180px, 46%);
  height: 1px;
  margin: 0 auto 30px;
  position: relative;
  background: linear-gradient(90deg, transparent, var(--line), transparent);
}
.ev-orn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -3px;
  width: 7px;
  height: 7px;
  transform: translateX(-50%) rotate(45deg);
  border: 1px solid var(--gold);
  background: var(--paper);
}
.ev:first-child .ev-orn {
  display: none;
}
.ev-art {
  margin: 0 auto 20px;
  overflow: hidden;
  border-radius: 0 0 46% 46%/0 0 14% 14%;
  border-bottom: 1px solid var(--line);
}
.ev-art img {
  width: 100%;
  transition: transform 1.5s var(--eo);
}
.ev:hover .ev-art img {
  transform: scale(1.04);
}
.ev-name {
  margin: 0 0 8px;
  font-family: "Cinzel", serif;
  letter-spacing: 0.06em;
  font-size: clamp(22px, 5.2vw, 30px);
  color: var(--indigo);
  line-height: 1.1;
}
.ev-when {
  margin: 0 0 2px;
  font-family: "Cinzel", serif;
  font-size: clamp(11px, 2.6vw, 13px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}
.ev-time {
  margin: 0 0 12px;
  font-style: italic;
  color: var(--ink-2);
}
.ev-venue {
  margin: 0 0 16px;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.ev-venue span {
  font-size: 0.86em;
  color: var(--ink-3);
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 22px;
  border: 1px solid var(--gold);
  font-family: "Cinzel", serif;
  font-size: 10.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--indigo);
  text-decoration: none;
  background: transparent;
  transition:
    background 0.35s ease,
    color 0.35s ease;
}
.btn:hover {
  background: var(--indigo);
  color: var(--gold-pale);
  border-color: var(--indigo);
}

@media (min-width: 760px) {
  .rail {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 44px 34px;
  }
  .ev {
    margin-bottom: 0;
  }
  .ev:nth-child(even) {
    margin-top: 46px;
  }
  .ev-orn {
    display: none;
  }
}

/* ═══ gallery ═══ */
.sec-gal {
  padding-left: 0;
  padding-right: 0;
}
.sec-gal .inner {
  padding: 0 var(--pad);
}
.car {
  margin-top: 28px;
  overflow: hidden;
}
.car-track {
  display: flex;
  gap: 14px;
  padding: 0 var(--pad);
  will-change: transform;
}
.ph {
  margin: 0;
  flex: 0 0 clamp(210px, 62vw, 260px);
  position: relative;
  border: 1px solid var(--line);
  background: var(--paper);
  padding: 14px;
}
.ph img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
}
.ph-tag {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  font-family: "Cinzel", serif;
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--indigo);
  background: var(--gold-pale);
  padding: 4px 11px;
  white-space: nowrap;
}
.ph-wide {
  flex: 0 0 clamp(230px, 68vw, 300px);
  background: rgba(253, 246, 234, 0.06);
  border-style: dashed;
}
.ph-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  aspect-ratio: 1;
  text-align: center;
  padding: 16px;
}
.ph-empty svg {
  width: 34px;
  height: 34px;
  fill: none;
  stroke: var(--gold-lt);
  stroke-width: 1.1;
  opacity: 0.8;
}
.ph-empty b {
  font-family: "Cinzel", serif;
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold-pale);
}
.dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-top: 20px;
}
.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  padding: 0;
  border: 1px solid var(--gold);
  background: transparent;
  cursor: pointer;
  transition: background 0.3s;
}
.dot[aria-current="true"] {
  background: var(--gold);
}

/* ═══ venue ═══ */
.mandap {
  width: min(330px, 86%);
  margin: 6px auto 18px;
  opacity: 0.92;
}
.v-name {
  margin: 0 0 6px;
  font-family: "Cinzel", serif;
  font-size: clamp(14px, 3.2vw, 18px);
  color: var(--indigo);
  letter-spacing: 0.04em;
}
.v-addr {
  margin: 0 0 24px;
  color: var(--ink-2);
}
.mapcard {
  display: flex;
  align-items: center;
  gap: 16px;
  text-decoration: none;
  color: var(--ink);
  padding: 18px 20px;
  background: var(--blush);
  border: 1px solid var(--line);
  max-width: 460px;
  margin: 0 auto;
  text-align: left;
  transition:
    border-color 0.3s,
    transform 0.3s var(--es);
}
.mapcard:hover {
  border-color: var(--gold);
  transform: translateY(-2px);
}
.mc-pin {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
}
.mc-pin svg {
  width: 21px;
  height: 21px;
  stroke: var(--gold);
}
.mc-txt {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  color: var(--ink-3);
}
.mc-txt b {
  display: block;
  font-family: "Cinzel", serif;
  font-size: 16px;
  letter-spacing: 0.04em;
  color: var(--indigo);
  margin-bottom: 2px;
}
.mc-go {
  flex: none;
}
.mc-go svg {
  width: 20px;
  height: 20px;
  stroke: var(--gold);
}

/* ═══ RSVP ═══ */
.rv-lead {
  margin: 0 auto 26px;
  max-width: 34ch;
  color: var(--ink-2);
}
.rv-choices {
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 400px;
  margin: 0 auto 26px;
}
.rv-ch {
  border: 1px solid var(--line);
  padding: 22px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  background: rgba(253, 246, 234, 0.06);
  transition:
    border-color 0.3s,
    background 0.3s,
    transform 0.2s var(--es);
}
.rv-ch:active {
  transform: scale(0.98);
}
.rv-ch.sy {
  border-color: var(--gold);
  background: rgba(214, 174, 107, 0.16);
}
.rv-ch.sn {
  border-color: var(--rose);
  background: rgba(192, 118, 106, 0.1);
}
.rv-ico {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(240, 220, 168, 0.1);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    background 0.3s,
    border-color 0.3s;
}
.rv-ico svg {
  width: 22px;
  height: 22px;
  stroke: var(--ink-3);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke 0.3s;
}
.rv-ch.sy .rv-ico {
  background: rgba(214, 174, 107, 0.28);
  border-color: var(--gold);
}
.rv-ch.sy .rv-ico svg {
  stroke: var(--gold);
}
.rv-ch.sn .rv-ico {
  background: rgba(192, 118, 106, 0.18);
  border-color: var(--rose);
}
.rv-ch.sn .rv-ico svg {
  stroke: var(--rose);
}
.rv-lbl {
  font-family: "Cinzel", serif;
  font-size: 16px;
  letter-spacing: 0.05em;
  color: #efe4d4;
  transition: color 0.3s;
}
.rv-ch.sn .rv-lbl {
  color: var(--rose);
}

.rv-form {
  max-width: 400px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  opacity: 0.3;
  pointer-events: none;
  transition: opacity 0.55s ease;
}
.rv-form.act {
  opacity: 1;
  pointer-events: all;
}
.f-lbl {
  font-family: "Cinzel", serif;
  font-size: 9.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(240, 220, 168, 0.8);
  display: block;
  margin-bottom: 8px;
  text-align: left;
}
.f-opt {
  opacity: 0.6;
  letter-spacing: 0.1em;
}
.f-in,
.f-ta {
  width: 100%;
  background: rgba(17, 28, 51, 0.55);
  border: 1px solid var(--line);
  padding: 14px 16px;
  font-family: "Alegreya", serif;
  font-size: 16px;
  color: #efe4d4;
  outline: none;
  transition:
    border-color 0.25s,
    box-shadow 0.25s;
  -webkit-appearance: none;
  appearance: none;
}
.f-in::placeholder,
.f-ta::placeholder {
  color: rgba(240, 220, 168, 0.42);
}
.f-in:focus,
.f-ta:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(184, 137, 63, 0.14);
}
.f-ta {
  resize: none;
  min-height: 88px;
}
.ff.hide {
  display: none;
}
.btn-sub {
  width: 100%;
  padding: 16px;
  background: linear-gradient(135deg, var(--gold-lt), #9c6f1c);
  color: var(--indigo-2);
  border: none;
  border-radius: 50px;
  font-family: "Cinzel", serif;
  font-size: 10px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
  transition:
    transform 0.2s var(--es),
    opacity 0.2s;
  margin-top: 4px;
}
.btn-sub:active {
  transform: scale(0.97);
}
.btn-sub:disabled {
  opacity: 0.6;
  pointer-events: none;
}

.rv-contact {
  max-width: 400px;
  margin: 28px auto 0;
  text-align: center;
  padding: 22px;
  background: rgba(253, 246, 234, 0.06);
  border: 1px solid var(--line);
}
.rc-lbl {
  font-family: "Cinzel", serif;
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(240, 220, 168, 0.55);
  margin: 0 0 8px;
}
.rc-name {
  font-family: "Cinzel", serif;
  font-size: 17px;
  letter-spacing: 0.04em;
  color: #efe4d4;
  margin: 0 0 6px;
}
.rc-ph {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "Cinzel", serif;
  font-size: 13.5px;
  color: var(--gold);
  text-decoration: none;
  letter-spacing: 0.05em;
}
.rc-ph svg {
  width: 15px;
  height: 15px;
  stroke: var(--gold);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
}

.rv-ok {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
  padding: 40px 20px;
  max-width: 400px;
  margin: 0 auto;
}
.rv-ok.show {
  display: flex;
}

/* The refused-reply line under the form (pack 0011 T8) — the form's body
   size, in a deep wine so it reads as a warning without a new colour token. */
.rv-err {
  margin: 12px 0 0;
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  color: #7c3040;
}
.ok-r {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--gold-pale), var(--gold));
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ok-r svg {
  width: 28px;
  height: 28px;
  stroke: var(--indigo-2);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
}
.ok-t {
  font-family: "Cinzel", serif;
  font-size: 24px;
  letter-spacing: 0.03em;
  color: var(--gold-pale);
  margin: 0;
}
.ok-x {
  font-family: "Alegreya", serif;
  font-size: 15px;
  color: #dccdb8;
  line-height: 1.75;
  margin: 0;
}

/* ═══ footer ═══ */
.foot {
  background: var(--indigo-2);
  color: #efe4d4;
  padding: var(--gap) var(--pad) 34px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.foot-orn {
  width: min(250px, 62%);
  margin: 0 auto 24px;
  opacity: 0.9;
}
.foot-line {
  margin: 0 0 6px;
  font-style: italic;
  color: rgba(239, 228, 212, 0.72);
}
.foot-names {
  margin: 0;
  font-family: "Cinzel Decorative", serif;
  font-size: clamp(23px, 5.4vw, 33px);
  letter-spacing: 0.03em;
  color: var(--gold-pale);
}
.ig {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
  text-decoration: none;
  color: rgba(239, 228, 212, 0.7);
  font-size: 14px;
  transition: color 0.3s;
}
.ig:hover {
  color: var(--gold-pale);
}
.ig svg {
  width: 19px;
  height: 19px;
  stroke: currentColor;
  fill: currentColor;
}
.foot-rule {
  display: block;
  width: min(180px, 50%);
  height: 1px;
  margin: 42px auto 26px;
  background: linear-gradient(90deg, transparent, var(--line), transparent);
}
.made {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-decoration: none;
  opacity: 0.85;
  transition: opacity 0.3s;
}
.made:hover {
  opacity: 1;
}
.made span {
  font-family: "Cinzel", serif;
  font-size: 9.5px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(239, 228, 212, 0.55);
}
.made img {
  width: 126px;
}

@media (min-width: 600px) {
  .weds {
    flex-direction: row;
    align-items: flex-start;
    justify-content: center;
    gap: 24px;
  }
  .weds .side {
    flex: 1;
    max-width: 260px;
  }
  .weds em {
    margin-top: 8px;
    flex: none;
  }
  .car-track {
    gap: 18px;
  }
}
@media (min-width: 960px) {
  .music {
    width: 48px;
    height: 48px;
    top: 24px;
  }
  .ph {
    flex-basis: 290px;
  }
  .ph-wide {
    flex-basis: 340px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal {
    opacity: 1;
    transform: none;
  }
  .amb {
    display: none;
  }
  .hero-names .ch,
  .hero-names em {
    opacity: 1;
    transform: none;
  }
  .cv-draw {
    stroke-dashoffset: 0;
  }
  .cv-phul rect {
    opacity: 0.85;
    transform: none;
  }
  .ph-ring {
    stroke-dashoffset: 0;
  }
  .h2 .ul path {
    stroke-dashoffset: 0;
  }
  .h2 .ul circle {
    opacity: 1;
  }
  .cv-corner,
  .cv-tap {
    opacity: 1;
  }
  .hang {
    opacity: 1;
  }
}
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* ═══ printed borders down the margins ═══
   A wide screen leaves two empty columns either side of the reading column,
   and a paper invitation would have a printed border there. Shown only from
   1180px up, where those columns exist.

   ⚠️ They are BACKGROUNDS on empty divs, not <img> tags. The original
   redesign used <img class="edge">, and a `display: none` image is still
   fetched by every browser — 870 KB downloaded on every phone, which never
   shows them. A background-image inside a media query is fetched only when
   the query matches.

   ⚠️ position: fixed and z-index 1, one below #page, with pointer-events
   off. Nothing on the page can end up behind them and nothing they cover can
   become unclickable. */
#page {
  position: relative;
  z-index: 2;
}
.edge {
  display: none;
  position: fixed;
  top: 0;
  height: 100vh;
  width: 22vw;
  max-width: 22vw;
  opacity: 0.9;
  pointer-events: none;
  z-index: 1;
  background-repeat: no-repeat;
  background-size: contain;
}
.edge-l {
  left: 0;
  background-position: left center;
}
.edge-r {
  right: 0;
  background-position: right center;
}
@media (min-width: 1180px) {
  .edge {
    display: block;
  }
  .edge-l {
    background-image: url(assets/border-l.webp);
  }
  .edge-r {
    background-image: url(assets/border-r.webp);
  }
}

/* ═══ the gallery photo frame ═══
   Each carousel photo is matted into a painted frame that overhangs the
   image by 3% on every side. ⚠️ The frame is an ::after over the photo, not
   a border: it is artwork with corner detail, which no border can draw.
   Overflow has to stay visible for the overhang, so the photo itself takes
   the radius. The square aspect-ratio is what makes one frame fit them all —
   without it a portrait photo would stretch the frame out of proportion.
   ⚠️ .ph-wide is the dashed "your photo here" slot and is deliberately
   excluded: an empty slot in a painted frame reads as a mistake. */
.ph:not(.ph-wide) {
  position: relative;
  aspect-ratio: 1;
  overflow: visible;
  background: transparent;
}
.ph:not(.ph-wide) img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 2px;
}
.ph:not(.ph-wide)::after {
  content: "";
  position: absolute;
  inset: -3%;
  background: url(assets/couple-frame.webp) center/100% 100% no-repeat;
  pointer-events: none;
  z-index: 3;
  filter: drop-shadow(0 8px 20px rgba(74, 52, 39, 0.18));
}
/* Above the frame, or the caption would be printed under the matting. */
.ph:not(.ph-wide) .ph-tag {
  z-index: 4;
}

/* The vowstory mark in the footer is a round badge now, so it needs a width
   of its own; the old wordmark sized itself. */
.made img {
  width: 88px;
  height: auto;
}

/* ═══ the venue route ═══
   Decorative only — see the comment on .route in index.html. The SVG's own
   overflow is visible so the pulsing ring around the destination pin is not
   clipped by the viewBox. */
.route {
  margin: 26px auto 2px;
  width: min(330px, 86%);
}
.route-svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

/* ═══ config-driven additions ═══
   Everything below exists because the page is painted from
   script#wedding-config: elements the couple left empty are hidden rather
   than deleted, and a few slots have no counterpart in the shipped demo. */

/* Outranks the flex/grid/inline-flex display rules on .rc-ph, .mapcard,
   .ig, .btn and the name spans, so `hidden` always wins. */
[hidden] {
  display: none !important;
}

/* The deity when the couple's blessing has no artwork of its own. Set in the
   same Gurmukhi-capable stack as the invocation, so ੴ and ॐ both render. */
.glyph {
  margin: 0 auto 14px;
  font-size: clamp(38px, 9vw, 54px);
  line-height: 1;
  color: var(--gold);
  font-family: "Noto Sans Gurmukhi", "Cinzel", serif;
  text-shadow: 0 6px 18px rgba(74, 52, 39, 0.18);
}

/* "Hosted by …" — for when an uncle or a brother is the official host.
   ⚠️ Rebuilt as a three-part block in the 11 Sep 2026 redesign: a short gold
   rule, a small-caps label, then the names. It used to be a single line
   reading "Hosted by Shri Mohan Malhotra", set in Cinzel at the same weight
   as everything around it, and it disappeared into the family copy above.
   The label and the names now differ in family, size and colour, so the eye
   reads it as a separate note rather than as a third family. */
.hosted {
  margin: 26px auto 0;
  text-align: center;
  max-width: 440px;
}
.hosted-rule {
  display: block;
  width: 44px;
  height: 1px;
  margin: 0 auto 13px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.hosted-label {
  margin: 0 0 6px;
  font-family: "Cinzel", serif;
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold);
}
.hosted-names {
  margin: 0;
  font-family: "Alegreya", Georgia, serif;
  font-size: 15px;
  line-height: 1.62;
  color: var(--ink-2);
}

/* Dress code and note, two labelled cells under an event's time.
   ⚠️ Was one italic run-on line ("Dress code: Marigold & ivory · Breakfast
   from 10:30") until the 11 Sep 2026 redesign.
   ⚠️ The columns are generated per cell, NOT declared as `1fr 1fr`. Most
   couples fill in one of the two, and a declared pair of tracks keeps both
   open whether or not anything is in them — the lone cell would sit at half
   width with an empty 136px beside it. `grid-auto-flow: column` with
   `grid-auto-columns: 1fr` makes one track per child that actually exists,
   so one cell fills the 280px and two split it. Measured: 280 alone, 136
   each in a pair.
   ⚠️ The body face here is Alegreya, NOT the Cardo the redesign shipped:
   Cardo is Raj Mahal's and Vaikuntha Mahal's body face and is not one of the
   five @font-face families at the top of this file, so it would have fallen
   back to a system serif with nothing to warn anybody. */
.ev-meta {
  margin: 12px auto 16px;
  max-width: 280px;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 9px;
}
.ev-meta > div {
  background: rgba(74, 52, 39, 0.05);
  border: 1px solid var(--line);
  padding: 7px 11px;
  min-width: 0;
}
.ev-meta dt {
  font-family: "Cinzel", serif;
  font-size: 8.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}
.ev-meta dd {
  margin: 3px 0 0;
  font-family: "Alegreya", Georgia, serif;
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.4;
}

/* A second query contact, when the couple gives one. */
.rc-ph + .rc-name {
  margin-top: 18px;
}

/* A lone event has no pair to sit beside in the two-column rail, so it keeps
   the reading column instead of hugging the left half of the page. */
@media (min-width: 760px) {
  .rail.one {
    grid-template-columns: minmax(0, 1fr);
    max-width: 430px;
    margin-left: auto;
    margin-right: auto;
  }
  .rail.one .ev:nth-child(even) {
    margin-top: 0;
  }
}
