/* ═══════════════════════════════════════════════════════════
   Imperial Pavilion · vowstory Shubharambh

   ⚠️ NEW DESIGN, added 11 September 2026. It is the sixth
   Shubharambh and the thirteenth in the range. The tokens, the
   typography and every section's treatment come from the
   co-founder's drop; what this repository added is the config
   pipeline, which in this file is the block at the very bottom
   marked "config-driven states".

   ⚠️ It is NOT a variant of Royale Pavilion despite the name. That
   design is marble and champagne with Prata; this one is marble and
   burgundy with Prata, Newsreader and Jost, a burgundy countdown and
   reply band, and arched niches for the two ceremonies. Both remain
   in the catalogue.

   ⚠️ Two things were corrected on the way in and are marked ⚠️ where
   they occur: the margin borders (fetched by phones that never show
   them) and the dress-code grid (a track held open for a cell that is
   not there). Both are in decision 0047 — they arrived on this new
   design exactly as they arrived on every redesigned one.
   ═══════════════════════════════════════════════════════════ */

/* ⚠️ SELF-HOSTED FONTS, as everywhere in the range. There is deliberately no
   Google Fonts <link> in index.html: an invitation is opened by a guest who
   never agreed to anything, and that stylesheet would make their browser
   announce itself to a third party before the first paint. 130 KB of woff2
   we serve ourselves instead.
   ⚠️ Every family named anywhere below must have a rule here. A family with
   no @font-face falls back to a system serif silently: the page looks
   slightly wrong rather than broken, which is how it survives review. */
@font-face {
  font-family: "Prata";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/prata-latin-400-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/newsreader-latin-300-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/newsreader-latin-400-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Newsreader";
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/newsreader-latin-300-italic.woff2) format("woff2");
}
@font-face {
  font-family: "Jost";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/jost-latin-300-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Jost";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/jost-latin-400-normal.woff2) format("woff2");
}

:root {
  --marble: #fbf3f1;
  --stone: #f5e7e4;
  --mist: #ebd9d6;
  --paper: #fdf8f6;
  --burgundy: #6e2233;
  --burgundy-deep: #511a28;
  --gold: #b58d50;
  --gold-deep: #8f6e38;
  --gold-dim: rgba(181, 141, 80, 0.45);
  --blush: #e7c3c0;
  --cream: #f7ede8;
  --cream-soft: #dbc4bc;
  --ink: #5a4642;
  --ink-soft: #9a857e;
  --col: 480px;
  --pad: 26px;
  --gap: 74px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --disp: "Prata", Georgia, serif;
  --label: "Jost", sans-serif;
  --body: "Newsreader", Georgia, serif;
}
* {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--stone);
  color: var(--ink);
  font-family: var(--body);
  font-weight: 300;
  font-size: 16.5px;
  line-height: 1.78;
  -webkit-font-smoothing: antialiased;
}
img {
  max-width: 100%;
  display: block;
}
sup {
  font-size: 0.58em;
  vertical-align: 0.5em;
}
body:not(.open) {
  overflow: hidden;
  height: 100%;
}

#page {
  max-width: var(--col);
  margin: 0 auto;
  background: var(--marble);
  overflow: clip;
  box-shadow: 0 0 80px rgba(110, 34, 51, 0.16);
  opacity: 0;
  transition: opacity 0.9s var(--ease);
  position: relative;
  z-index: 2;
}
body.open #page {
  opacity: 1;
}

/* ⚠️ Printed margin borders, shown only from 1180px up. These arrived as two
   <img> tags with display:none below that width. Every browser fetches a
   display:none image, so every phone — which never shows them — paid for
   1.4 MB. They are CSS background-images declared INSIDE the media query
   instead, which is fetched only when the query matches.
   The geometry is unchanged: height:100vh with background-size contain in a
   23vw box resolves to the same painted box as width:auto on an <img> did. */
.edge {
  display: none;
  position: fixed;
  top: 0;
  height: 100vh;
  width: 23vw;
  max-width: 23vw;
  opacity: 0.94;
  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/elements/border-l.webp);
  }
  .edge-r {
    background-image: url(assets/elements/border-r.webp);
  }
}

/* ── cover ── */
#cover {
  position: fixed;
  inset: 0;
  z-index: 90;
  max-width: var(--col);
  margin: 0 auto;
  background: radial-gradient(120% 90% at 50% 32%, var(--stone), #e6d2ce);
  overflow: hidden;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  isolation: isolate;
}
.door {
  position: absolute;
  top: 0;
  height: 100%;
  width: 50.4%;
  background: radial-gradient(140% 120% at 50% 30%, var(--stone), #e6d2ce);
  transition: transform 1.35s var(--ease);
  will-change: transform;
}
.door-l {
  left: 0;
}
.door-r {
  right: 0;
}
.door .panel {
  position: absolute;
  inset: 26px 0;
  border-top: 1px solid var(--gold-dim);
  border-bottom: 1px solid var(--gold-dim);
}
.door-l .panel {
  left: 26px;
  right: 0;
  border-left: 1px solid var(--gold-dim);
}
.door-r .panel {
  right: 26px;
  left: 0;
  border-right: 1px solid var(--gold-dim);
}
.seam {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: linear-gradient(
    180deg,
    transparent,
    var(--gold-dim) 12%,
    var(--gold-dim) 88%,
    transparent
  );
  transform: translateX(-50%);
  transition: opacity 0.5s ease;
}
body.opening .door-l {
  transform: translateX(-101%);
}
body.opening .door-r {
  transform: translateX(101%);
}
body.opening .seam,
body.opening .cover-inner {
  opacity: 0;
}
body.opened #cover {
  display: none;
}
.cover-inner {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  transition: opacity 0.45s ease;
  padding: 20px;
}
.cover-frame {
  position: absolute;
  inset: 16px;
  border: 1px solid rgba(181, 141, 80, 0.6);
  box-shadow:
    inset 0 0 0 5px rgba(245, 231, 228, 0.5),
    inset 0 0 0 6px rgba(181, 141, 80, 0.34);
  z-index: 0;
}
.cover-frame::before,
.cover-frame::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 9px;
  height: 9px;
  background: var(--burgundy);
  transform: translateX(-50%) rotate(45deg);
}
.cover-frame::before {
  top: -5px;
}
.cover-frame::after {
  bottom: -5px;
}
.tap-open {
  position: relative;
  z-index: 1;
  font-family: var(--disp);
  font-size: clamp(25px, 7vw, 34px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: linear-gradient(
    100deg,
    #7a4a2a 0%,
    #b58d50 30%,
    #ebd9ae 48%,
    #cba968 56%,
    #8f6e38 74%,
    #7a4a2a 100%
  );
  background-size: 230% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 2px 7px rgba(110, 34, 51, 0.18));
  animation:
    shine 3.2s linear infinite,
    tapbob 2.1s var(--ease) infinite;
}
.tap-hint {
  position: relative;
  z-index: 1;
  color: var(--burgundy);
  animation: tapbob 2.1s var(--ease) infinite;
  animation-delay: 0.12s;
  opacity: 0.72;
}
.tap-hint svg {
  width: 24px;
  height: 24px;
  display: block;
}
@keyframes shine {
  to {
    background-position: 230% 0;
  }
}
@keyframes tapbob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-9px);
  }
}

/* ── music ── */
.music {
  position: fixed;
  top: 16px;
  z-index: 80;
  right: max(16px, calc(50vw - var(--col) / 2 + 16px));
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: rgba(253, 248, 246, 0.9);
  border: 1px solid rgba(181, 141, 80, 0.5);
  backdrop-filter: blur(6px);
  display: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  color: var(--burgundy);
  transition: transform 0.25s var(--ease);
}
body.open .music {
  display: flex;
  animation: fadein 0.8s 0.5s backwards;
}
.music:hover {
  transform: scale(1.07);
}
.music svg {
  width: 20px;
  height: 20px;
  fill: currentColor;
  stroke: currentColor;
}
.music .ic-off {
  display: none;
}
.music[aria-pressed="false"] .ic-on {
  display: none;
}
.music[aria-pressed="false"] .ic-off {
  display: block;
}
@keyframes fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* ── hero (Hero 1, light) ── */
.hero {
  position: relative;
  background: var(--marble);
}
.hero-art {
  position: relative;
  min-height: 100svh;
  background: url(assets/hero.webp) center top/cover no-repeat;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 34px 22vh;
  overflow: clip;
}
.hero-art::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(
      ellipse 92% 66% at 50% 44%,
      rgba(251, 243, 241, 0.9) 0%,
      rgba(251, 243, 241, 0.66) 42%,
      rgba(251, 243, 241, 0.28) 70%,
      rgba(251, 243, 241, 0) 88%
    ),
    linear-gradient(
      180deg,
      rgba(251, 243, 241, 0.25) 2%,
      rgba(251, 243, 241, 0) 24%,
      rgba(251, 243, 241, 0) 74%,
      rgba(251, 243, 241, 0.55) 94%
    );
}
.hero-body {
  position: relative;
  text-align: center;
  width: 100%;
  max-width: 520px;
  z-index: 2;
}
.ganesh {
  width: clamp(112px, 30%, 158px);
  margin: 0 auto 6px;
  filter: drop-shadow(0 6px 16px rgba(110, 34, 51, 0.16));
}
.invocation {
  margin: 0 0 14px;
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--gold-deep);
}
.hero-eyebrow {
  margin: 0 0 12px;
  font-family: var(--label);
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: 0.38em;
  text-transform: uppercase;
  color: var(--burgundy);
}
.hero-names {
  margin: 0;
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(40px, 11.5vw, 74px);
  line-height: 1.08;
  letter-spacing: 0.005em;
}
.hero-names span {
  display: block;
  background: linear-gradient(
    96deg,
    var(--burgundy) 24%,
    var(--gold) 50%,
    var(--burgundy) 76%
  );
  background-size: 230% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: shine 6.5s linear infinite;
}
.hero-names em {
  display: block;
  font-family: var(--label);
  font-weight: 300;
  font-style: normal;
  font-size: 0.2em;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold-deep);
  margin: 10px 0 8px;
  text-indent: 0.42em;
}
.hair {
  display: block;
  width: min(200px, 54%);
  height: 1px;
  margin: 18px auto;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.hair-sm {
  display: block;
  width: min(120px, 44%);
  height: 1px;
  margin: 10px auto 14px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.hero-date {
  margin: 0 0 10px;
  font-family: var(--label);
  font-weight: 400;
  font-size: clamp(13px, 3.2vw, 17px);
  letter-spacing: 0.18em;
  color: var(--burgundy);
  text-transform: uppercase;
}
.hero-venue {
  margin: 0;
  font-size: clamp(15px, 3.3vw, 18px);
  font-style: italic;
  color: var(--ink);
  line-height: 1.5;
}
.hero-venue span {
  display: inline-block;
  font-style: normal;
  font-size: 0.82em;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  margin-top: 2px;
}
body.open .hero-body > * {
  animation: heroIn 1.1s var(--ease) backwards;
}
body.open .hero-body > *:nth-child(1) {
  animation-delay: 0.45s;
}
body.open .hero-body > *:nth-child(2) {
  animation-delay: 0.57s;
}
body.open .hero-body > *:nth-child(3) {
  animation-delay: 0.69s;
}
body.open .hero-body > *:nth-child(4) {
  animation-delay: 0.81s;
}
body.open .hero-body > *:nth-child(5) {
  animation-delay: 0.93s;
}
body.open .hero-body > *:nth-child(6) {
  animation-delay: 1.05s;
}
body.open .hero-body > *:nth-child(7) {
  animation-delay: 1.17s;
}
@keyframes heroIn {
  from {
    opacity: 0;
    transform: translateY(24px);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

.scroll-cue {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 24px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  transition:
    opacity 0.5s ease,
    transform 0.5s ease;
  pointer-events: none;
}
.cue-word {
  font-family: var(--label);
  font-size: 10px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--burgundy);
}
.cue-chev {
  color: var(--gold-deep);
  animation: bob 1.6s ease-in-out infinite;
}
.cue-chev svg {
  width: 28px;
  height: 28px;
  display: block;
}
@keyframes bob {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.55;
  }
  50% {
    transform: translateY(7px);
    opacity: 1;
  }
}
.scroll-cue.gone {
  opacity: 0;
  transform: translateY(10px);
}

/* ── shared ── */
.sec {
  padding: var(--gap) var(--pad);
  position: relative;
  overflow: clip;
  isolation: isolate;
  background: var(--marble);
  text-align: center;
}
.sec > *:not(.deco),
.foot > *:not(.deco) {
  position: relative;
  z-index: 1;
}
.eyebrow {
  margin: 0 0 12px;
  font-family: var(--label);
  font-weight: 400;
  font-size: 10.5px;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--gold-deep);
}
.h2 {
  margin: 0 0 20px;
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(27px, 6.6vw, 44px);
  line-height: 1.2;
  color: var(--burgundy);
}
.h2-sm {
  font-size: clamp(24px, 5.4vw, 34px);
}
.prose {
  margin: 0 auto 16px;
  max-width: 38ch;
  color: var(--ink);
}
.tag {
  margin: 26px 0 0;
  font-family: var(--label);
  font-size: clamp(12px, 2.4vw, 15px);
  letter-spacing: 0.24em;
  color: var(--gold-deep);
}
.tag-sm {
  font-size: 11px;
  letter-spacing: 0.3em;
  margin-top: 14px;
}
.eyebrow-on {
  color: var(--gold);
}
.h2-on {
  color: var(--cream);
}

.reveal {
  opacity: 0;
  transform: translateY(28px) scale(0.99);
  filter: blur(6px);
  transition:
    opacity 1.05s var(--ease),
    transform 1.05s var(--ease),
    filter 1.05s var(--ease);
}
.reveal.in {
  opacity: 1;
  transform: none;
  filter: none;
}
.deco {
  position: absolute;
  pointer-events: none;
  z-index: 0;
}

/* ── plate (Hero 2 invite, light) ── */
.plate {
  position: relative;
  isolation: isolate;
}
.plate-invite {
  background: url(assets/hero2.webp) center/cover no-repeat;
}
/* ⚠️ THE VEIL IS THE ONLY THING HOLDING THIS SECTION'S COPY ABOVE
   THRESHOLD, and these are not the stops the redesign shipped. Those peaked
   low and fell away fast — measured on the two family columns at 834px, where
   they sit at the outer edges of the plate and the veil has almost run out,
   the parents' line came back well under the 4.5:1 small text needs.
   ⚠️ Widening a veil is not the same as strengthening it: peak opacity is the
   limit, not extent. These stops were set by measurement and still reach zero
   at the edge so the painted border reads.
   ⚠️ Re-export the artwork and they have to be measured again. */
.plate-invite::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse 106% 96% at 50% 48%,
    rgba(251, 243, 241, 0.95) 0%,
    rgba(251, 243, 241, 0.9) 44%,
    rgba(251, 243, 241, 0.72) 72%,
    rgba(251, 243, 241, 0.26) 88%,
    rgba(251, 243, 241, 0) 100%
  );
}
.plate-body {
  position: relative;
  padding: calc(var(--gap) + 6px) var(--pad);
  text-align: center;
  min-height: clamp(480px, 80vw, 600px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.seal-wrap {
  position: relative;
  width: min(122px, 32%);
  margin: 0 auto 20px;
  aspect-ratio: 1;
}
.seal-ring {
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  border: 1px solid rgba(181, 141, 80, 0.6);
  box-shadow:
    0 0 0 5px var(--marble),
    0 0 0 6px var(--gold-dim);
  z-index: 1;
}
.seal {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 10px 26px rgba(110, 34, 51, 0.16);
}

/* ── countdown (burgundy panel) ── */
.sec-count {
  background: var(--burgundy);
}
.deco-candles {
  width: clamp(96px, 26vw, 160px);
  right: -18px;
  bottom: -14px;
  opacity: 0.95;
}
.sec-count .tag {
  color: var(--gold);
}
.clock {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  max-width: 400px;
  margin: 26px auto 0;
}
.unit {
  padding: 18px 4px 14px;
  background: var(--burgundy-deep);
  border: 1px solid rgba(181, 141, 80, 0.4);
}
.unit b {
  display: block;
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(23px, 6vw, 34px);
  color: var(--gold);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.unit i {
  display: block;
  margin-top: 9px;
  font-style: normal;
  font-size: 9.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cream-soft);
  font-family: var(--label);
}

/* ── union block ── */
.weds {
  margin: 34px auto 0;
  max-width: 560px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  font-family: var(--disp);
  font-size: clamp(20px, 4.6vw, 28px);
  line-height: 1.25;
  color: var(--burgundy);
  text-align: center;
}
.weds em {
  font-family: var(--label);
  font-style: normal;
  font-size: 0.44em;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--gold-deep);
  display: flex;
  align-items: center;
  gap: 12px;
  text-indent: 0.34em;
}
.weds em::before,
.weds em::after {
  content: "";
  width: 32px;
  height: 1px;
  background: var(--gold-dim);
}
.side {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.side-name {
  margin: 0 0 9px;
  line-height: 1.2;
}
.side-role {
  margin: 0 0 6px;
  font-family: var(--label);
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--burgundy);
}
.side-parents {
  margin: 0;
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  max-width: 26ch;
}
@media (min-width: 640px) {
  .weds {
    flex-direction: row;
    justify-content: center;
    gap: clamp(20px, 4vw, 38px);
    align-items: flex-start;
  }
  .side {
    flex: 1;
    max-width: 300px;
  }
  .weds em {
    margin-top: 10px;
    flex: none;
  }
}

/* ── events (niche cards) ── */
.sec-events {
  background: var(--stone);
}
.head {
  margin-bottom: 4px;
}
.cards {
  display: grid;
  gap: 26px;
  margin-top: 30px;
}
.niche.card {
  background: var(--marble);
  border: 1px solid var(--gold-dim);
  border-radius: 150px 150px 8px 8px;
  padding: 14px 20px 26px;
  overflow: hidden;
}
.card-art {
  margin: 0 0 18px;
  overflow: hidden;
  border-radius: 140px 140px 6px 6px;
  aspect-ratio: 4/5;
}
.card-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.card-title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(26px, 5.6vw, 36px);
  color: var(--burgundy);
  line-height: 1;
}
.card-when {
  margin: 0 0 3px;
  font-family: var(--label);
  font-size: clamp(12.5px, 2.8vw, 15px);
  letter-spacing: 0.14em;
  color: var(--gold-deep);
  text-transform: uppercase;
}
.card-time {
  margin: 0 0 12px;
  font-style: italic;
  color: var(--ink-soft);
}
.card-venue {
  margin: 0 0 16px;
  line-height: 1.5;
  color: var(--ink);
}
.card-venue span {
  font-size: 0.85em;
  color: var(--ink-soft);
}
/* Dress code and note, two labelled cells under an event. New with the
   redesign; there was one italic line before it.
   ⚠️ The columns are generated per cell, NOT declared as `1fr 1fr` as they
   arrived. Most couples fill in one of the two, and a declared pair of tracks
   stays open whether or not anything is in it — the lone cell would sit at
   half width beside a hole. `grid-auto-flow: column` with
   `grid-auto-columns: 1fr` makes one track per cell that exists. */
.card-meta {
  margin: 0 auto 20px;
  max-width: 340px;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 10px;
}
.card-meta > div {
  background: var(--stone);
  border: 1px solid rgba(181, 141, 80, 0.3);
  padding: 8px 12px;
  min-width: 0;
}
.card-meta dt {
  font-family: var(--label);
  font-size: 9px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-deep);
}
.card-meta dd {
  margin: 3px 0 0;
  font-size: 14px;
  color: var(--ink);
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 24px;
  border: 1px solid rgba(181, 141, 80, 0.6);
  font-family: var(--label);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--burgundy);
  text-decoration: none;
  background: var(--marble);
  transition:
    background 0.3s ease,
    color 0.3s ease,
    border-color 0.3s ease;
}
.btn:hover {
  background: var(--burgundy);
  color: var(--cream);
  border-color: var(--burgundy);
}
.btn svg {
  width: 15px;
  height: 15px;
  stroke: currentColor;
  fill: none;
}

/* ── gallery ── */
.sec-gallery {
  background: var(--marble);
}
.frame-wrap {
  position: relative;
  width: min(430px, 96%);
  margin: 28px auto 0;
  aspect-ratio: 1;
}
.photo-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 3;
  filter: drop-shadow(0 12px 26px rgba(110, 34, 51, 0.16));
}
.slides {
  position: absolute;
  inset: 22.4% 20.4% 22% 24%;
  overflow: hidden;
  z-index: 1;
  background: var(--stone);
  border-radius: 3px;
}
.slide-track {
  display: flex;
  height: 100%;
  transition: transform 0.6s var(--ease);
}
.slide {
  margin: 0;
  flex: 0 0 100%;
  height: 100%;
  position: relative;
}
.slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ph {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--label);
  font-size: 9px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold-deep);
  border: 1px solid rgba(181, 141, 80, 0.45);
  padding: 3px 10px;
  background: rgba(253, 248, 246, 0.9);
  white-space: nowrap;
  z-index: 2;
}
.nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  background: rgba(253, 248, 246, 0.94);
  border: 1px solid rgba(181, 141, 80, 0.45);
  color: var(--burgundy);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 4;
}
.nav svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  fill: none;
}
.prev {
  left: calc(24% - 16px);
}
.next {
  right: calc(20.4% - 16px);
}
.dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-top: 20px;
}
.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  background: transparent;
  border: 1px solid var(--gold);
  transition: background 0.3s ease;
}
.dot[aria-current="true"] {
  background: var(--gold);
}

/* ── venue ── */
.deco-vase {
  width: clamp(96px, 24vw, 150px);
  left: -20px;
  bottom: -14px;
  opacity: 0.9;
}
.venue-name {
  margin: 0 0 6px;
  font-family: var(--label);
  font-size: clamp(15px, 3.2vw, 19px);
  color: var(--burgundy);
  letter-spacing: 0.04em;
}
.venue-addr {
  margin: 0 0 24px;
  color: var(--ink-soft);
}
.mapcard {
  display: flex;
  align-items: center;
  gap: 16px;
  text-decoration: none;
  color: var(--ink);
  padding: 18px 20px;
  background: var(--paper);
  border: 1px solid rgba(181, 141, 80, 0.45);
  max-width: 520px;
  margin: 6px auto 0;
  text-align: left;
  transition:
    border-color 0.3s ease,
    transform 0.3s var(--ease);
}
.mapcard:hover {
  border-color: var(--gold);
  transform: translateY(-2px);
}
.mapcard-pin,
.mapcard-go {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gold-deep);
}
.mapcard-pin svg {
  width: 26px;
  height: 26px;
  stroke: currentColor;
  fill: none;
}
.mapcard-go svg {
  width: 17px;
  height: 17px;
  stroke: currentColor;
  fill: none;
}
.mapcard-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  font-family: var(--body);
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.5;
}
.mapcard-text b {
  font-family: var(--label);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--burgundy);
  margin-bottom: 3px;
}
.route {
  margin: 30px auto 2px;
  width: min(330px, 86%);
}
.route-svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

/* ── rsvp (burgundy panel) ── */
.sec-rsvp {
  background: var(--burgundy);
}
.deco-bowls {
  width: clamp(110px, 28vw, 180px);
  right: -16px;
  bottom: -14px;
  opacity: 0.95;
}
.rsvp {
  display: grid;
  gap: 12px;
  margin-top: 24px;
  max-width: 520px;
  margin-inline: auto;
  width: 100%;
}
.chip {
  display: flex;
  align-items: center;
  gap: 14px;
  text-align: left;
  padding: 14px 20px;
  background: rgba(253, 248, 246, 0.95);
  border: 1px solid rgba(181, 141, 80, 0.4);
  text-decoration: none;
  color: var(--ink);
  transition:
    border-color 0.3s ease,
    transform 0.3s var(--ease);
}
.chip:hover {
  border-color: var(--gold);
  transform: translateY(-2px);
}
.chip svg {
  width: 23px;
  height: 23px;
  flex: none;
  stroke: var(--burgundy);
  fill: var(--burgundy);
}
.chip span {
  display: flex;
  flex-direction: column;
  font-size: 0.85em;
  color: var(--ink-soft);
}
.chip b {
  font-family: var(--label);
  font-weight: 400;
  font-size: 1.1em;
  color: var(--burgundy);
}

/* ── footer ── */
.foot {
  background: var(--marble);
  padding: calc(var(--gap) - 8px) var(--pad) 34px;
  text-align: center;
  position: relative;
  overflow: clip;
  border-top: 1px solid var(--gold-dim);
}
.foot-orn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: min(216px, 58%);
  margin: 0 auto 18px;
}
.foot-orn i {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.foot-orn i:last-child {
  background: linear-gradient(90deg, var(--gold), transparent);
}
.foot-orn b {
  width: 7px;
  height: 7px;
  transform: rotate(45deg);
  background: var(--burgundy);
  flex: none;
}
.foot-candles {
  width: min(196px, 54%);
  margin: 6px auto 18px;
  display: block;
  filter: drop-shadow(0 6px 20px rgba(110, 34, 51, 0.18));
}
.foot-line {
  margin: 0 0 6px;
  font-style: italic;
  color: var(--ink-soft);
}
.foot-names {
  margin: 0;
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(30px, 7vw, 44px);
  color: var(--burgundy);
}
.ig {
  display: flex;
  width: max-content;
  align-items: center;
  gap: 8px;
  margin: 20px auto 0;
  text-decoration: none;
  color: var(--ink-soft);
  font-size: 0.85em;
  letter-spacing: 0.04em;
  transition: color 0.3s ease;
}
.ig:hover {
  color: var(--burgundy);
}
.ig svg {
  width: 19px;
  height: 19px;
  stroke: currentColor;
  fill: currentColor;
}
.made {
  display: flex;
  width: max-content;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 38px auto 0;
  text-decoration: none;
  opacity: 0.9;
  transition: opacity 0.3s ease;
}
.made:hover {
  opacity: 1;
}
.made span {
  font-family: var(--label);
  font-size: 9.5px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.made img {
  width: 98px;
}

/* ── scale up ── */
@media (min-width: 600px) {
  :root {
    --col: 620px;
    --pad: 46px;
    --gap: 92px;
  }
  body {
    font-size: 17.5px;
  }
  .hero-art {
    padding: 12vh 58px 20vh;
  }
  .cards {
    grid-template-columns: 1fr 1fr;
    gap: 24px;
  }
}
@media (min-width: 960px) {
  :root {
    --col: 800px;
    --pad: 66px;
    --gap: 110px;
  }
  body {
    font-size: 18.5px;
  }
  .music {
    width: 46px;
    height: 46px;
    top: 22px;
  }
  .hero-art {
    background-position: center 14%;
  }
}
@media (min-width: 1400px) {
  :root {
    --col: 880px;
  }
}

@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;
    filter: none;
  }
  .hero-names span,
  .tap-open {
    -webkit-text-fill-color: var(--burgundy);
    color: var(--burgundy);
  }
}
:focus-visible {
  outline: 2px solid var(--burgundy);
  outline-offset: 3px;
}

/* ── hosted by ── */
.hosted {
  margin: 32px auto 0;
  text-align: center;
  max-width: 440px;
}
.hosted-rule {
  display: block;
  width: 46px;
  height: 1px;
  margin: 0 auto 14px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.hosted-label {
  margin: 0 0 6px;
  font-family: var(--label);
  font-weight: 400;
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold-deep);
}
.hosted-names {
  margin: 0;
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink);
}

/* ══ config-driven states ══════════════════════════════════════════════════
   Everything below this line belongs to the repository's rendering pipeline,
   not to the design. It is what has to be re-applied whenever a redesign
   replaces this sheet. */

/* Slots the config left empty are hidden with [hidden]; several of them are
   flex or grid, so the attribute needs to win over the class. */
[hidden] {
  display: none !important;
}

/* Blessings with no artwork of their own fall back to their glyph, set at the
   same weight as the Ganesha crop it replaces.
   ⚠️ Since 11 September 2026 (decision 0048) every blessing in the catalogue
   ships its own drawing, so the config sends `symbol: null` and NOTHING lands
   here any more. The rule stays as the fallback for a blessing added later
   with no artwork drawn for it yet — without it that one would print at the
   browser's default size in a system serif. */
.glyph {
  margin: 0 0 8px;
  font-family: var(--disp);
  font-size: clamp(40px, 10vw, 58px);
  line-height: 1;
  color: var(--gold-deep);
}

/* The reply chip's second line is an <i> because the blueprint has two text
   slots and only one of them is ever a name. */
.chip i {
  font-style: normal;
}

/* A single event keeps the card at reading width instead of being dealt into
   the left half of a two-column grid with nothing beside it. Shubharambh sells
   two events, so one is an ordinary thing for a couple to enter.
   ⚠️ script.js ALREADY adds this class ("if (events.length === 1)"); this
   design inherited that half of the pipeline from Neelam on 11 September 2026
   without the rule that reads it. Check both halves together. */
.cards.one {
  max-width: 460px;
  margin-inline: auto;
}
@media (min-width: 960px) {
  .cards.one {
    grid-template-columns: 1fr;
  }
}
