/* ═══ the three 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 that stylesheet made their browser announce itself to a third
   party before the first paint. Seven files, 164 KB, in assets/fonts/.

   ⚠️ `font-display: swap` on every face: the page paints in the fallback at
   once and reflows when the woff2 lands. `block` would hold 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. Amiri,
   Petrona and Allura are the complete set; a fourth named in a rule below
   would fall back to a system face with nothing to warn anybody. */
@font-face {
  font-family: "Amiri";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/amiri-latin-400-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Amiri";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(assets/fonts/amiri-latin-700-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Amiri";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/amiri-latin-400-italic.woff2) format("woff2");
}
@font-face {
  font-family: "Petrona";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/petrona-latin-300-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Petrona";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/petrona-latin-400-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Petrona";
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/petrona-latin-300-italic.woff2) format("woff2");
}
@font-face {
  font-family: "Allura";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/allura-latin-400-normal.woff2) format("woff2");
}

/* ═══════════════════════════════════════════════════════════
   Mayura · vowstory Utsav
   Mobile first. Both hero artworks arrived at 0.463 aspect with
   interiors at 229.9 (std 0.49) and 231.4 (std 0.40) — the first
   pair in the range needing neither a splice nor a veil.
   Signature: the reflecting pool.
   ═══════════════════════════════════════════════════════════ */

:root {
  /* ⚠️ THE WHOLE PALETTE MOVED IN THE 11 SEP 2026 REDESIGN — this is not a
     tweak, it is a different colour scheme, and it is the only one of the
     twelve designs where a redesign changed the tokens rather than the
     layout. Mayura was peacock: a near-black teal ground (#023646) with a
     brass gold. It is now sage and olive on warm stone.

     ⚠️ THE CONSEQUENCE TO KNOW ABOUT IS `--deep`. It is BOTH the dark band
     background (.sec-deep — light text on it) AND the colour of the couple's
     names over the hero artwork. Moving it from #023646 to #59604A raises its
     luminance a long way, which cuts the contrast of everything light sitting
     on it. That was measured rather than assumed; the numbers are in
     README.md under "Verified again", and `--deep-2` was NOT lightened by as
     much precisely so the dark bands still hold their text.

     ⚠️ index.html's `theme-color` meta follows `--deep` and was moved with it.
     ⚠️ `--sage` is new and has no counterpart in the old palette. */
  --paper: #f4efe3;
  --paper-2: #e9e0cb;
  --teal: #2c5d52;
  /* ⚠️ DARKER THAN THE REDESIGN SHIPPED (#59604A), AND THE NUMBERS ARE THE
     REASON. `--deep` is the dark band's background AND the colour of seven
     pieces of dark-on-light text, so it is the one token whose luminance sets
     the contrast on both polarities at once. At #59604A the countdown band
     measured light text at 3.80:1 (the digits), 3.70:1 (the hashtag) and
     2.62:1 (the unit labels) against 4.5 for small text — where the old
     peacock #023646 gave 6.95, 6.92 and 5.09. Darkening it inside the same
     olive hue fixes the band and, because the other seven uses are dark text
     on paper, improves every one of them too. Re-measured; see README.md. */
  --deep: #474d38;
  --deep-2: #3b4032;
  --gold: #b69a62;
  --gold-lt: #d6c08c;
  --leaf: #6e7a54;
  --sage: #858a70;
  --coral: #c68a5e;
  --ink: #292a24;
  --ink-2: #585a48;
  --ink-3: #8a8770;
  --line: rgba(182, 154, 98, 0.32);

  --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(--deep-2);
  color: var(--ink);
  font-family: "Petrona", Georgia, serif;
  font-size: 17px;
  font-weight: 300;
  line-height: 1.78;
  -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;
  box-shadow: 0 0 80px rgba(59, 64, 50, 0.34);
  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(--deep-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% 42% at 50% 44%,
      rgba(44, 93, 82, 0.85) 0%,
      rgba(71, 77, 56, 0) 72%
    ),
    linear-gradient(170deg, #5a6349 0%, #474d38 56%, #2c3025 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-lt) 22%,
    var(--gold-lt) 78%,
    transparent
  );
  opacity: 0.6;
}
.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-lt);
  filter: blur(0.4px);
  animation: rise linear infinite;
  opacity: 0;
}
@keyframes rise {
  0% {
    transform: translateY(0) scale(0.7);
    opacity: 0;
  }
  12% {
    opacity: 0.7;
  }
  85% {
    opacity: 0.4;
  }
  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 plume fans open, eye by eye */
.cv-plume {
  width: min(280px, 72%);
  height: auto;
}
.pl-fan path {
  fill: none;
  stroke: var(--gold-lt);
  stroke-width: 1.1;
  stroke-linecap: round;
  opacity: 0;
  animation: quill 0.8s var(--eo) forwards;
}
.pl-fan circle {
  fill: none;
  stroke-width: 1.3;
  opacity: 0;
  animation: eye 0.7s var(--eo) forwards;
}
.pl-fan .eye-o {
  stroke: #2f8e93;
}
.pl-fan .eye-i {
  stroke: var(--gold-lt);
}
@keyframes quill {
  from {
    opacity: 0;
    stroke-dasharray: 200;
    stroke-dashoffset: 200;
  }
  to {
    opacity: 0.9;
    stroke-dasharray: 200;
    stroke-dashoffset: 0;
  }
}
@keyframes eye {
  from {
    opacity: 0;
    transform: scale(0.3);
  }
  to {
    opacity: 0.95;
    transform: none;
  }
}
.pl-ring {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1;
  opacity: 0.5;
  stroke-dasharray: 760;
  stroke-dashoffset: 760;
  animation: draw 2s var(--eo) 1.5s forwards;
}
.pl-ring2 {
  stroke-width: 0.6;
  opacity: 0.35;
  animation-delay: 1.75s;
}
@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

.cv-corner {
  position: absolute;
  width: 24px;
  height: 24px;
  opacity: 0;
  animation: fadeUp 0.9s var(--eo) 1.9s forwards;
}
.cv-corner::before,
.cv-corner::after {
  content: "";
  position: absolute;
  background: var(--gold-lt);
}
.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(12vh, 96px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  opacity: 0;
  animation: tapIn 1.1s var(--eo) 2.3s 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(214, 192, 140, 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(47, 142, 147, 0.6);
  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 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. ⚠️ 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. ⚠️ It works here and does NOT work on a transformed descendant; see
   the note on the hero names below. */
.cv-word {
  font-family: "Amiri", serif;
  font-size: 12.5px;
  letter-spacing: 0.48em;
  text-transform: uppercase;
  text-indent: 0.48em;
  background: linear-gradient(
    100deg,
    #8a6e36 0%,
    #b69a62 28%,
    #f1e4be 48%,
    #d6c08c 56%,
    #8a6e36 82%
  );
  background-size: 230% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: wordShine 3.4s linear infinite;
}
@keyframes wordShine {
  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, #fbf0d6, transparent);
  box-shadow: 0 0 30px 8px rgba(251, 240, 214, 0.7);
}
#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(251, 240, 214, 0.8) 0%,
    rgba(47, 142, 147, 0.28) 32%,
    rgba(71, 77, 56, 0) 62%
  );
}
#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 added then sit at 1 and #page at 2, so motes at 2 were painted level
   with the page content and lost against it. Still pointer-events:none. */
.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, #fff6de 0%, #d6c08c 42%, rgba(182, 154, 98, 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%;
  /* ⚠️ Both stops were the OLD palette's coral (#D07A55 and a white-mixed
     tint of it), left behind when the tokens moved. Same construction on
     the current coral: the token, and the same mix toward white. */
  background: linear-gradient(140deg, #e5cab7, var(--coral));
  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(244, 239, 227, 0.9);
  border: 1px solid var(--line);
  backdrop-filter: blur(8px);
  display: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  color: var(--teal);
  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(--teal);
  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;
  aspect-ratio: 853/1844;
  overflow: hidden;
  background: var(--paper);
}
/* inset 0 and a matching aspect, so `cover` shows the plate whole — peacock
   included — at every width. The zoom moves background-size, which can only
   crop inward; the parallax moves background-position, which cannot expose an
   edge either. Neither uses transform, so they never fight. */
.hero-art {
  position: absolute;
  inset: 0;
  background: url(assets/hero.webp) center top/100% auto no-repeat;
  animation: kb 20s var(--eo) forwards;
}
@keyframes kb {
  from {
    background-size: 108% auto;
  }
  to {
    background-size: 100% auto;
  }
}
.hero-in {
  position: relative;
  z-index: 2;
  height: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 13vh 30px 16vh;
}
/* held inside the arch interior — measured, see README */
.hero-in > * {
  max-width: min(66%, 32rem);
  margin-left: auto;
  margin-right: auto;
}
@media (min-width: 600px) {
  .hero-in {
    padding: 14vh 56px 15vh;
  }
  .hero-in > * {
    max-width: min(50%, 32rem);
  }
}

.deity {
  width: clamp(74px, 18vw, 110px);
  margin: 0 auto 14px;
  filter: drop-shadow(0 6px 18px rgba(41, 42, 36, 0.2));
  animation: glow 6s ease-in-out infinite;
}
@keyframes glow {
  0%,
  100% {
    filter: drop-shadow(0 6px 16px rgba(41, 42, 36, 0.18));
  }
  50% {
    filter: drop-shadow(0 8px 28px rgba(47, 142, 147, 0.36));
  }
}
.invocation {
  margin: 0 0 16px;
  font-size: 14px;
  letter-spacing: 0.09em;
  color: var(--gold);
}
.eyebrow {
  margin: 0 0 12px;
  font-family: "Amiri", serif;
  font-size: 10.5px;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--gold);
}
.hero-names {
  margin: 0;
  font-family: "Amiri", serif;
  font-weight: 400;
  font-size: clamp(32px, 8.4vw, 56px);
  line-height: 1.18;
  letter-spacing: 0.02em;
  color: var(--deep);
}
.hero-names .ln {
  display: block;
  position: relative;
}
/* A band of light crossing the couple's names. ⚠️ It is an ::after OVERLAY
   with a blend mode, not `background-clip: text` — the letters are wrapped in
   per-character spans that are transformed as they rise in, and in Blink and
   WebKit a transformed descendant gets its own compositing layer that the
   parent's text-clipped background never paints over. The cover's "Tap to
   open" can use the clip because nothing inside it is transformed.
   ⚠️ `soft-light` rather than `overlay` since the 11 Sep 2026 redesign: the
   names moved to a much lighter `--deep`, and `overlay` on a light colour
   blows out to near-white instead of reading as a sheen. */
.hero-names.lit .ln::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    102deg,
    transparent 34%,
    rgba(214, 192, 140, 0.55) 46%,
    rgba(255, 251, 238, 0.95) 50%,
    rgba(214, 192, 140, 0.55) 54%,
    transparent 66%
  );
  background-size: 260% 100%;
  mix-blend-mode: soft-light;
  animation: sweep 5.5s ease-in-out infinite;
}
.hero-names.lit .ln {
  text-shadow: 0 0 22px rgba(214, 192, 140, 0.28);
}
@keyframes sweep {
  0% {
    background-position: 180% 0;
  }
  55%,
  100% {
    background-position: -80% 0;
  }
}
.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: "Allura", cursive;
  font-style: normal;
  font-size: 0.86em;
  color: var(--teal);
  margin: -2px 0;
  line-height: 1.2;
  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: "Amiri", 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: 5%;
  width: clamp(20px, 5.4vw, 36px);
}
.hang-b {
  right: 6%;
  width: clamp(30px, 8vw, 54px);
}
@media (min-width: 960px) {
  .hang-a {
    left: 12%;
  }
  .hang-b {
    right: 13%;
  }
}

.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: "Amiri", 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);
}

/* ═══ THE REFLECTING POOL — the signature ═══
   The ornaments stand on a bank; below it the same ornaments are mirrored,
   masked into water and slowly skewed so the reflection wavers. Purely
   decorative: no text sits on it, so nothing can collide. */
.pool {
  position: relative;
  height: clamp(190px, 44vw, 320px);
  overflow: hidden;
  background: var(--paper);
}
.pl-stage,
.pl-mirror {
  position: absolute;
  left: 0;
  right: 0;
  height: 100%;
}
.pl-stage {
  bottom: 34%;
}
.pl-item {
  position: absolute;
  bottom: 0;
  will-change: transform;
}
.pl-1 {
  left: 5%;
  width: clamp(26px, 6.4vw, 50px);
}
.pl-2 {
  left: 24%;
  width: clamp(56px, 14vw, 110px);
}
.pl-3 {
  right: 26%;
  width: clamp(64px, 16vw, 124px);
}
.pl-4 {
  right: 4%;
  width: clamp(50px, 12vw, 96px);
}
.pl-bank {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 34%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line), transparent);
  z-index: 2;
}
.pl-water {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 34%;
  overflow: hidden;
  background: linear-gradient(180deg, #dce9e2 0%, #c9ddda 42%, #b7d0d0 100%);
}
.pl-mirror {
  top: 0;
  transform: scaleY(-1);
  transform-origin: top;
  opacity: 0.34;
  -webkit-mask-image: linear-gradient(
    180deg,
    #000 0%,
    rgba(0, 0, 0, 0.45) 46%,
    transparent 86%
  );
  mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.45) 46%, transparent 86%);
  animation: waver 7s ease-in-out infinite;
}
@keyframes waver {
  0%,
  100% {
    transform: scaleY(-1) skewX(-1.1deg);
  }
  50% {
    transform: scaleY(-1) skewX(1.1deg);
  }
}
.pl-ripple {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.34) 0 1px,
    transparent 1px 9px
  );
  animation: ripple 5.5s ease-in-out infinite;
}
@keyframes ripple {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.5;
  }
  50% {
    transform: translateY(4px);
    opacity: 0.85;
  }
}
.pl-lotus {
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: clamp(90px, 24vw, 190px);
  opacity: 0.9;
  z-index: 3;
  animation: bob 6.5s ease-in-out infinite;
}
@keyframes bob {
  0%,
  100% {
    transform: translateX(-50%) translateY(0) rotate(-0.6deg);
  }
  50% {
    transform: translateX(-50%) translateY(-4px) rotate(0.6deg);
  }
}

/* ═══ sections ═══ */
.sec {
  position: relative;
  padding: var(--gap) var(--pad);
  overflow: hidden;
  text-align: center;
  background: var(--paper);
}
.sec-deep {
  background: var(--deep);
  color: #e9e0cc;
}
.sec-deep .h2 {
  color: #f1e2be;
}
.sec-deep .eyebrow {
  color: var(--gold-lt);
}
.sec-deep .prose,
.sec-deep .rv-lead {
  color: #d6cbb2;
}
.sec-deep::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse 72% 50% at 50% 24%,
    rgba(47, 142, 147, 0.16),
    transparent 72%
  );
}
.inner {
  position: relative;
  z-index: 2;
  max-width: 620px;
  margin: 0 auto;
}
.h2 {
  margin: 0 0 20px;
  font-family: "Amiri", serif;
  font-weight: 400;
  font-size: clamp(26px, 5.8vw, 38px);
  line-height: 1.28;
  color: var(--deep);
  letter-spacing: 0.02em;
}
/* a feather-eye is drawn under every heading */
.h2 .ul {
  display: block;
  width: min(170px, 56%);
  height: auto;
  margin: 14px auto 0;
}
.h2 .ul path,
.h2 .ul ellipse {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.2;
  stroke-linecap: round;
}
.h2 .ul path {
  stroke-dasharray: 190;
  stroke-dashoffset: 190;
  transition: stroke-dashoffset 1.5s var(--eo) 0.25s;
}
.h2 .ul ellipse {
  opacity: 0;
  transition: opacity 0.5s ease 1.25s;
}
.h2.in .ul path {
  stroke-dashoffset: 0;
}
.h2.in .ul ellipse {
  opacity: 1;
}
.sec-deep .h2 .ul path {
  stroke: var(--gold-lt);
}
.sec-deep .h2 .ul ellipse {
  stroke: #2f8e93;
}
.prose {
  margin: 0 auto 16px;
  max-width: 36ch;
  color: var(--ink-2);
}
.tag {
  margin: 26px 0 0;
  font-family: "Amiri", serif;
  font-size: clamp(12px, 2.4vw, 14px);
  letter-spacing: 0.24em;
  color: var(--gold);
}
.sec-deep .tag {
  color: var(--gold-lt);
}
.tag-sm {
  font-size: 11.5px;
  letter-spacing: 0.28em;
  margin-top: 14px;
}
.reveal {
  opacity: 0;
  transform: translateY(28px) scale(0.985);
  transition:
    opacity 1.05s var(--eo),
    transform 1.05s var(--eo);
}
.reveal.in {
  opacity: 1;
  transform: none;
}
/* the two sides of the family arrive one after the other */
.weds.in .side:first-of-type {
  animation: sideIn 0.9s var(--eo) 0.1s backwards;
}
.weds.in em {
  animation: sideIn 0.9s var(--eo) 0.3s backwards;
}
.weds.in .side:last-of-type {
  animation: sideIn 0.9s var(--eo) 0.5s backwards;
}
@keyframes sideIn {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.deco {
  position: absolute;
  z-index: 1;
  pointer-events: none;
}
/* sized so its rendered height is always less than the section padding */
.deco-feather {
  width: clamp(14px, 3vw, 20px);
  right: 18px;
  top: 0;
  opacity: 0.55;
  animation: sway 9s ease-in-out infinite;
  transform-origin: 50% 0;
}

/* ═══ FAMILIES — page two, on Hero_2 ═══
   ⚠️ THIS SECTION USED TO BE SIZED TO THE ARTWORK; IT IS NOW SIZED TO ITS
   CONTENT (11 Sep 2026 redesign), and that is what let the two family
   sections become one.

   Hero_2 arrived at 0.463 aspect with a flat interior covering only the
   middle 45%. The section therefore took the plate's own `aspect-ratio` and
   anchored the copy to the foot of the arch, with width-relative padding
   computed so the baseline landed at 74.1% of the plate — inside the flat
   interior at every viewport. It worked, and it could only hold the
   invitation heading; the two families had to go in a section of their own
   below, on plain paper.

   The artwork was re-exported in this drop, and the section now takes normal
   padding, places the artwork with `cover`, and lays a veil over it. The
   interior is whatever the content needs, `cover` crops the surplus, and both
   blocks fit. #sec-kin is gone.

   ⚠️ The veil is a ::before on the section rather than a `.fam-veil` div, so
   there is no extra element for `.fam-in`'s sibling selectors to trip over.
   `isolation: isolate` keeps its stacking context inside the section.
   ⚠️ The linear layer on top of the radial is doing real work: it holds the
   BOTTOM of the section light. `cover` on a tall block crops to the artwork's
   middle, which is darker than the crown, and the "Hosted by" line is the
   last thing on the page here — it was measured, see README.md. */
.sec-fam {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: url(assets/hero2.webp) center/cover no-repeat;
  padding: clamp(70px, 17vw, 140px) var(--pad) clamp(64px, 15vw, 120px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.sec-fam::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(
      ellipse 90% 72% at 50% 44%,
      rgba(244, 239, 227, 0.84) 0%,
      rgba(244, 239, 227, 0.6) 46%,
      rgba(244, 239, 227, 0.22) 78%,
      rgba(244, 239, 227, 0) 92%
    ),
    linear-gradient(
      180deg,
      rgba(244, 239, 227, 0) 56%,
      rgba(244, 239, 227, 0.5) 80%,
      rgba(244, 239, 227, 0.7) 100%
    );
}
/* The copy column. Wider than it was, because it now carries the families as
   well as the heading and the old 64%/52% would have wrapped every parent
   line. */
.fam-in {
  width: 100%;
  max-width: min(90%, 30rem);
  text-align: center;
  position: relative;
  z-index: 2;
  margin: 0 auto;
}
@media (min-width: 600px) {
  .fam-in {
    max-width: min(74%, 30rem);
  }
}
/* On a wide screen the block scales with the artwork rather than sitting as a
   small island in the middle — that is what read as empty. ⚠️ The veil is
   redeclared here without its linear layer: a wide section is short relative
   to its width, so `cover` keeps more of the crown and the foot never gets
   dark enough to need it. */
@media (min-width: 960px) {
  .sec-fam::before {
    background: radial-gradient(
      ellipse 84% 64% at 50% 46%,
      rgba(244, 239, 227, 0.78) 0%,
      rgba(244, 239, 227, 0.5) 48%,
      rgba(244, 239, 227, 0.1) 80%,
      rgba(244, 239, 227, 0) 92%
    );
  }
  .fam-in {
    max-width: min(60%, 34rem);
  }
  .fam-in .seal {
    width: min(150px, 26%);
    margin-bottom: 22px;
  }
  .fam-in .eyebrow {
    font-size: 13px;
    margin-bottom: 16px;
  }
  .fam-in .h2 {
    font-size: clamp(36px, 3.4vw, 48px);
    margin-bottom: 22px;
  }
  .fam-in .h2 .ul {
    width: min(210px, 60%);
    margin-top: 20px;
  }
  .fam-in .prose {
    font-size: 1.08rem;
    line-height: 1.85;
    max-width: 34ch;
  }
}
.fam-in .h2 {
  margin-bottom: 18px;
  font-size: clamp(28px, 6.4vw, 42px);
}
.fam-in .prose {
  margin-bottom: 0;
  max-width: 32ch;
}
/* The hairline between the invitation and the families, now that they share a
   section. script.js removes it when there is no family to divide from. */
.fam-div {
  display: block;
  width: 44px;
  height: 1px;
  margin: 26px auto;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.fam-in .weds {
  margin-top: 0;
}
.fam-in .hosted {
  margin-top: 26px;
}

/* ⚠️ `.sec-kin` and `.kin-orn` were deleted here. They styled the families'
   own section, which no longer exists; the cartouche they used is still in
   assets/ornaments/ because the countdown's `.chand` uses it. */

.seal {
  width: min(112px, 30%);
  margin: 0 auto 16px;
  border-radius: 50%;
  box-shadow:
    0 0 0 1px var(--line),
    0 0 0 6px var(--paper),
    0 0 0 7px rgba(182, 154, 98, 0.24);
}
.weds {
  margin: 30px 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: "Amiri", serif;
  font-size: clamp(17px, 4vw, 22px);
  line-height: 1.36;
  color: var(--deep);
}
.weds em {
  font-family: "Allura", cursive;
  font-style: normal;
  font-size: 1.5em;
  color: var(--teal);
  display: flex;
  align-items: center;
  gap: 14px;
  line-height: 1;
}
.weds em::before,
.weds em::after {
  content: "";
  width: 28px;
  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.26;
}
.side-role {
  margin: 0 0 6px;
  font-family: "Amiri", serif;
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold);
}
.side-parents {
  margin: 0;
  font-family: "Petrona", serif;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 25ch;
}

/* ═══ countdown ═══ */
.sec-count {
  padding-top: calc(var(--gap) * 0.5);
}
.chand {
  display: block;
  width: clamp(120px, 30vw, 210px);
  margin: 0 auto 22px;
  opacity: 0.92;
  animation: float 9s ease-in-out infinite;
}
@keyframes float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-6px);
  }
}
.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;
  background: rgba(244, 239, 227, 0.07);
  border: 1px solid var(--line);
  position: relative;
  overflow: hidden;
}
.unit::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    115deg,
    transparent 40%,
    rgba(214, 192, 140, 0.16) 50%,
    transparent 60%
  );
  background-size: 260% 100%;
  animation: sweep 9s ease-in-out infinite;
}
.unit:nth-child(2)::after {
  animation-delay: 0.7s;
}
.unit:nth-child(3)::after {
  animation-delay: 1.4s;
}
.unit b {
  display: block;
  font-family: "Amiri", serif;
  font-size: clamp(26px, 6.8vw, 36px);
  color: #f1e2be;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.unit i {
  display: block;
  margin-top: 10px;
  font-style: normal;
  font-family: "Amiri", serif;
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  /* ⚠️ Was rgba(216, 177, 107, .65) — a 65%-opacity copy of the OLD palette's
     --gold-lt (#D8B16B), left behind when the tokens moved. It was the
     weakest text on the page at 2.62:1.
     ⚠️ Not `var(--gold-lt)` either: these labels sit on `.unit`'s own pale
     tint rather than on the band, so their background is lighter than the
     heading's and the token measured 3.77:1. This is the least-bright warm
     gold that clears 4.5 on that tint — measured at 4.84:1. If `.unit`'s
     background changes, re-measure this. */
  color: #e8dab4;
}

/* ═══ EVENTS — feather-eye medallions ═══ */
.sec-events {
  padding-bottom: calc(var(--gap) + 10px);
}
.rail {
  margin-top: 32px;
}
.ev {
  position: relative;
  margin-bottom: 46px;
  text-align: center;
}
.ev:last-child {
  margin-bottom: 0;
}
.ev-art {
  position: relative;
  margin: 0 auto 20px;
  width: min(260px, 70%);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  box-shadow:
    0 0 0 1px var(--line),
    0 0 0 8px var(--paper),
    0 0 0 9px rgba(47, 142, 147, 0.4),
    0 14px 34px rgba(71, 77, 56, 0.14);
}
.ev-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.5s var(--eo);
}
.ev:hover .ev-art img {
  transform: scale(1.05);
}
/* the eye ring, drawn rather than cropped from the sheet */
.ev-eye {
  position: absolute;
  inset: -9px;
  border-radius: 50%;
  pointer-events: none;
  border: 1px solid rgba(182, 154, 98, 0.55);
  transform: scale(0.86);
  opacity: 0;
  transition:
    transform 1.1s var(--eo) 0.2s,
    opacity 0.8s ease 0.2s;
}
.ev.in .ev-eye {
  transform: none;
  opacity: 1;
}
.ev-art::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(
    circle at 32% 26%,
    rgba(255, 250, 235, 0.42),
    transparent 54%
  );
  opacity: 0;
  transition: opacity 0.7s ease;
}
.ev:hover .ev-art::after {
  opacity: 1;
}
.ev-name {
  margin: 0 0 8px;
  font-family: "Amiri", serif;
  font-size: clamp(23px, 5.4vw, 31px);
  color: var(--deep);
  line-height: 1.1;
}
.ev-when {
  margin: 0 0 2px;
  font-family: "Amiri", 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: "Amiri", serif;
  font-size: 10.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--deep);
  text-decoration: none;
  background: transparent;
  transition:
    background 0.35s ease,
    color 0.35s ease;
}
.btn:hover {
  background: var(--teal);
  color: var(--paper);
  border-color: var(--teal);
}

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

/* ═══ 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;
  transition:
    transform 0.6s var(--eo),
    box-shadow 0.6s var(--eo);
}
.ph:hover {
  transform: translateY(-5px) rotate(-0.7deg);
  box-shadow: 0 16px 34px rgba(71, 77, 56, 0.16);
}
.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: "Amiri", serif;
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--teal);
  padding: 4px 11px;
  white-space: nowrap;
}
.ph-wide {
  flex: 0 0 clamp(230px, 68vw, 300px);
  background: rgba(244, 239, 227, 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: "Amiri", serif;
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold-lt);
}
.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-lt);
  background: transparent;
  cursor: pointer;
  transition: background 0.3s;
}
.dot[aria-current="true"] {
  background: var(--gold-lt);
}

/* ═══ venue ═══ */
.mandap {
  width: min(300px, 80%);
  margin: 6px auto 18px;
  opacity: 0.94;
}
.v-name {
  margin: 0 0 6px;
  font-family: "Amiri", serif;
  font-size: clamp(13px, 3vw, 17px);
  color: var(--deep);
  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(--paper-2);
  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(--teal);
}
.mc-txt {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  color: var(--ink-3);
}
.mc-txt b {
  display: block;
  font-family: "Amiri", serif;
  font-size: 17px;
  color: var(--deep);
  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;
}
.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(244, 239, 227, 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-lt);
  background: rgba(214, 192, 140, 0.14);
}
.rv-ch.sn {
  border-color: var(--coral);
  background: rgba(198, 138, 94, 0.12);
}
.rv-ico {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(47, 142, 147, 0.16);
  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: rgba(214, 192, 140, 0.6);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke 0.3s;
}
.rv-ch.sy .rv-ico {
  background: rgba(214, 192, 140, 0.22);
  border-color: var(--gold-lt);
}
.rv-ch.sy .rv-ico svg {
  stroke: #f1e2be;
}
.rv-ch.sn .rv-ico {
  background: rgba(198, 138, 94, 0.18);
  border-color: var(--coral);
}
.rv-ch.sn .rv-ico svg {
  stroke: #eda184;
}
.rv-lbl {
  font-family: "Amiri", serif;
  font-size: 18px;
  color: #e9e0cc;
  transition: color 0.3s;
}
.rv-ch.sy .rv-lbl {
  color: #f1e2be;
}
.rv-ch.sn .rv-lbl {
  color: #eda184;
}

.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: "Amiri", serif;
  font-size: 9.5px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(214, 192, 140, 0.85);
  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(59, 64, 50, 0.55);
  border: 1px solid var(--line);
  padding: 14px 16px;
  font-family: "Petrona", serif;
  font-size: 16px;
  color: #e9e0cc;
  outline: none;
  transition:
    border-color 0.25s,
    box-shadow 0.25s;
  -webkit-appearance: none;
  appearance: none;
}
.f-in::placeholder,
.f-ta::placeholder {
  color: rgba(214, 192, 140, 0.42);
}
.f-in:focus,
.f-ta:focus {
  border-color: var(--gold-lt);
  box-shadow: 0 0 0 3px rgba(47, 142, 147, 0.22);
}
.f-ta {
  resize: none;
  min-height: 88px;
}
.ff.hide {
  display: none;
}
.btn-sub {
  width: 100%;
  padding: 16px;
  background: linear-gradient(135deg, var(--gold-lt), #96701f);
  color: var(--deep-2);
  border: none;
  border-radius: 50px;
  font-family: "Amiri", 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(244, 239, 227, 0.06);
  border: 1px solid var(--line);
}
.rc-lbl {
  font-family: "Amiri", serif;
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(214, 192, 140, 0.6);
  margin: 0 0 8px;
}
.rc-name {
  font-family: "Amiri", serif;
  font-size: 18px;
  color: #e9e0cc;
  margin: 0 0 6px;
}
.rc-ph {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "Amiri", serif;
  font-size: 13.5px;
  color: var(--gold-lt);
  text-decoration: none;
  letter-spacing: 0.05em;
}
.rc-ph svg {
  width: 15px;
  height: 15px;
  stroke: var(--gold-lt);
  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, #f1e2be, var(--gold));
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ok-r svg {
  width: 28px;
  height: 28px;
  stroke: var(--deep-2);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
}
.ok-t {
  font-family: "Amiri", serif;
  font-size: 26px;
  color: #f1e2be;
  margin: 0;
}
.ok-x {
  font-family: "Petrona", serif;
  font-size: 15px;
  color: #d6cbb2;
  line-height: 1.75;
  margin: 0;
}

/* ═══ footer ═══ */
.foot {
  background: var(--deep-2);
  color: #e9e0cc;
  padding: var(--gap) var(--pad) 34px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.foot-orn {
  width: min(280px, 72%);
  margin: 0 auto 24px;
  opacity: 0.9;
}
.foot-line {
  margin: 0 0 6px;
  font-style: italic;
  color: rgba(233, 224, 204, 0.72);
}
.foot-names {
  margin: 0;
  font-family: "Amiri", serif;
  font-size: clamp(25px, 5.8vw, 35px);
  color: #f1e2be;
}
.ig {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
  text-decoration: none;
  color: rgba(233, 224, 204, 0.7);
  font-size: 14px;
  transition: color 0.3s;
}
.ig:hover {
  color: #f1e2be;
}
.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: "Amiri", serif;
  font-size: 9.5px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(233, 224, 204, 0.55);
}
/* The vowstory mark is a round badge now rather than a wordmark. */
.made img {
  width: 92px;
}

@media (min-width: 600px) {
  .weds {
    flex-direction: row;
    align-items: flex-start;
    justify-content: center;
    gap: 22px;
  }
  .weds .side {
    flex: 1;
    max-width: 240px;
  }
  .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;
  }
  .pl-fan path,
  .pl-fan circle {
    opacity: 0.9;
  }
  .pl-ring {
    stroke-dashoffset: 0;
  }
  .h2 .ul path {
    stroke-dashoffset: 0;
  }
  .h2 .ul ellipse {
    opacity: 1;
  }
  .cv-corner,
  .cv-tap {
    opacity: 1;
  }
  .hang {
    opacity: 1;
  }
  .pl-mirror {
    transform: scaleY(-1);
  }
  .pl-lotus {
    transform: translateX(-50%);
  }
  .hero-names.lit .ln::after {
    display: none;
  }
  .ev-eye {
    transform: none;
    opacity: 1;
  }
}
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* ═══ printed borders down the margins ═══
   #page is capped at --col, so a wide screen leaves two empty columns either
   side of it. A paper invitation would have a printed border there. Shown
   only from 1180px up, where those columns exist.

   ⚠️ BACKGROUNDS ON EMPTY DIVS, NOT <img> TAGS. The redesign used
   <img class="edge"> hidden with `display: none` below 1180px, and a hidden
   image is still FETCHED by every browser. These two files are 717 KB EACH —
   the heaviest of the three designs merged so far — so that was 1.4 MB
   downloaded on every phone, which never shows them. A background-image
   inside a media query is fetched only when the query matches.

   ⚠️ The geometry matches the <img> version at every width: `contain` in a
   22vw x 100vh box resolves as `height: 100vh; width: auto; max-width: 22vw`
   with `object-fit: contain` did.

   ⚠️ The source files live at assets/border-*.webp here. The redesign shipped
   them under assets/elements/; they were moved so all twelve designs keep one
   convention. Nothing else in any design uses an `elements/` folder. */
#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 venue route ═══
   Decorative only — see the comment on .route in index.html. The SVG's own
   overflow stays 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
   display face over the hero. */
.glyph {
  margin: 0 auto 14px;
  font-family: "Amiri", serif;
  line-height: 1;
  font-size: clamp(42px, 10vw, 62px);
  color: var(--gold-lt);
  text-shadow: 0 0 30px rgba(182, 154, 98, 0.45);
}

/* "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 Amiri line
   at the same weight as the family copy and disappeared into it.
   ⚠️ It is now INSIDE the arch, which the old comment here said it never
   was — the families moved in with it when #sec-kin was folded into
   .sec-fam. It is the last line on that artwork, which is why .sec-fam::before
   carries a linear layer to keep the foot of the section light. */
.hosted {
  margin: 30px 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: "Amiri", serif;
  font-size: 10px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold);
}
.hosted-names {
  margin: 0;
  font-family: "Petrona", serif;
  font-weight: 400;
  font-size: 15px;
  line-height: 1.66;
  color: var(--ink);
}

/* Dress code and note, two labelled cells under an event's venue.
   ⚠️ 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 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.
   ⚠️ The events rail can sit in a paper band or a dark one. The .sec-deep
   overrides are what keep the cells legible on the dark one — check both if
   these colours change. */
.ev-meta {
  margin: 14px auto 18px;
  max-width: 300px;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 9px;
}
.ev-meta > div {
  background: var(--paper-2);
  border: 1px solid var(--line);
  padding: 7px 11px;
  min-width: 0;
}
.ev-meta dt {
  font-family: "Amiri", serif;
  font-size: 8.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}
.ev-meta dd {
  margin: 3px 0 0;
  font-family: "Petrona", serif;
  font-weight: 300;
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.4;
}
.sec-deep .ev-meta > div {
  background: rgba(255, 255, 255, 0.05);
}
.sec-deep .ev-meta dd {
  color: #e9e0cc;
}

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

/* A lone medallion 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;
  }
}
