/* ==========================================================================
   Atelier — Mubashir & Minha Mujeeb
   A luxury-stationery still life. The 3D object is the hero; the DOM carries
   only a quiet caption and the controls. Warm sand dominates, gold is the only
   accent, ivory is the neutral, bronze lives in the wax seal alone.
   ========================================================================== */

:root {
  /* The page is light beige, like good uncoated stock. */
  --sand-50:  #F2E8D8;
  --sand-100: #E7D9C1;
  --sand-200: #D6C3A2;

  /* Only the veil and the courtyard's own overlay are dark. */
  --night:    #0A1016;

  --gold:     #B08D4A;
  --gold-hi:  #D8BC7E;
  --gold-40:  rgba(176, 141, 74, .40);
  --gold-20:  rgba(176, 141, 74, .20);

  --ivory:    #F3ECDF;
  --ivory-70: rgba(243, 236, 223, .70);
  --ivory-50: rgba(243, 236, 223, .50);
  --ivory-14: rgba(243, 236, 223, .14);

  --ink:      #3B2C17;
  --ink-70:   rgba(59, 44, 23, .70);
  --ink-50:   rgba(59, 44, 23, .52);
  --ink-14:   rgba(59, 44, 23, .16);
  --ink-gold: #8A6A30;

  --serif:  "EB Garamond", Georgia, "Times New Roman", serif;
  --caps:   "Cinzel", "Trajan Pro", Georgia, serif;
  --script: "Pinyon Script", "EB Garamond", cursive;
  --ui:     "Jost", "Futura", "Avenir Next", sans-serif;
  --arabic: "Amiri", "Noto Naskh Arabic", serif;

  --ease:   cubic-bezier(.16, 1, .3, 1);
  --gutter: clamp(1.25rem, 5vw, 3.5rem);
  --header: 76px;                         /* mirrors HEADER_PX in scene.js */
  --safe-b: max(1.1rem, env(safe-area-inset-bottom));
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

/* A stage, not a page: every gesture belongs to the canvas, including
   paging through the open card on a phone. */
html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--sand-50);
  color: var(--ink);
  font-family: var(--ui);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

button { font: inherit; color: inherit; }
:focus-visible { outline: 1.5px solid var(--gold); outline-offset: 4px; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ── Stage layers ──────────────────────────────────────────────────────── */

/* Lit like seamless studio paper: brightest behind the object, falling off
   to near-black at the edges. */
.backdrop {
  position: fixed;
  inset: 0;
  background:
    radial-gradient(58% 46% at 50% 40%, rgba(255, 252, 245, .85) 0%, transparent 72%),
    radial-gradient(120% 92% at 50% 44%, var(--sand-50) 0%, var(--sand-100) 46%, var(--sand-200) 100%);
}

#stage {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;             /* the canvas owns every gesture */
  opacity: 0;
  transition: opacity .6s var(--ease);
}
body:not([data-state="loading"]) #stage { opacity: 1; }
/* Nothing is seen until the leaves part, so the canvas need not fade in. */
body[data-gate="open"] #stage { opacity: 1; transition: none; }

/* Dark veil for the move from the card into the courtyard: quick to fall,
   slow to lift, so the courtyard fades up out of the night. */
.veil {
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: var(--night);
  opacity: 0;
  transition: opacity 1.1s var(--ease);
}
/* Going in, nothing is covered: the room's own light goes down instead, and
   the paper dart carries the eye across. Coming back out, the veil still does
   the work, because there is no dart to hide the change behind. */
body[data-state="leaving"] .veil { opacity: 1; transition-duration: .5s; }

/* Dusk: the beige page darkens to night as the guest steps inside, so the
   courtyard is arrived at rather than cut to. */
body { transition: background-color 1.2s var(--ease); }
body[data-state="entering"],
body[data-state="courtyard"] { background: var(--night); }

.backdrop { transition: opacity 1s var(--ease); }
body[data-state="entering"] .backdrop,
body[data-state="courtyard"] .backdrop { opacity: 0; }

.grain {
  position: fixed;
  inset: -50%;
  pointer-events: none;
  opacity: .035;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/></filter><rect width='180' height='180' filter='url(%23n)'/></svg>");
}

/* ── Masthead ──────────────────────────────────────────────────────────── */

/* Its own band with a fade beneath, so the card can pass under it while the
   guest scrolls without the two ever colliding. */
.masthead {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 5;
  height: calc(var(--header) + env(safe-area-inset-top));
  display: flex;
  align-items: center;
  padding: env(safe-area-inset-top) var(--gutter) 0;
  pointer-events: none;                    /* except the switch, which opts in */
  background: linear-gradient(to bottom, rgba(242, 232, 216, .96) 0%, rgba(242, 232, 216, .8) 55%, rgba(242, 232, 216, 0) 100%);
  transition: opacity .5s var(--ease), visibility .5s;
}

/* The courtyard is its own world at night: a band of daylight beige across
   the top of it would break the illusion, so the masthead steps aside. */
body[data-state="entering"] .masthead,
body[data-state="leaving"] .masthead,
body[data-state="courtyard"] .masthead {
  opacity: 0;
  visibility: hidden;
}

.masthead__mark {
  font-family: var(--script);
  font-size: 1.85rem;
  line-height: 1;
  color: var(--ink-gold);
}
.masthead__mark i { font-family: var(--serif); font-style: italic; font-size: .5em; margin: 0 .3em; color: var(--gold); }

.masthead__title {
  margin-left: auto;                       /* the mark left, the rest right */
  font-size: .66rem;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--ink-50);
}

/* Portrait: the masthead sits in a shorter band than the 3D reserves for it
   (HEADER_PX in scene.js stays 76), so the card clears the type instead of
   arriving right under it. */
@media (max-aspect-ratio: 9/10) {
  :root { --header: 58px; }
  .masthead { align-items: center; }
  .masthead__mark { font-size: 1.5rem; }
  .masthead__title { font-size: .58rem; letter-spacing: .28em; }
}

/* ── Captions ──────────────────────────────────────────────────────────── */

.copy {
  position: fixed;
  z-index: 5;
  left: 0;
  right: 0;
  bottom: var(--safe-b);
  padding: 0 var(--gutter);
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .5s var(--ease), transform .5s var(--ease), visibility .5s;
}

/* Wide screens: a compact caption centred directly beneath the object
   (the 3D framing reserves WIDE_CAPTION_PX for it), in one quiet line of
   hint and action under a small title. */
@media (min-aspect-ratio: 9/10) {
  .copy { bottom: clamp(1.4rem, 3.5vh, 2.4rem); }
  .copy .eyebrow { margin-bottom: .45rem; font-size: .6rem; }
  .copy .copy__title { font-size: 1.35rem; }
  .copy__row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.1rem;
    margin-top: .7rem;
  }
  .copy__row .copy__hint { margin: 0; font-size: .74rem; }
  .copy__row .btn { min-height: 36px; padding: 0 1.2rem; font-size: .6rem; }
}

body[data-state="closed"] .copy--closed,
body[data-state="card-open"][data-layout="book"] .copy--open {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: .1s;
}

.eyebrow {
  margin: 0 0 .7rem;
  font-size: .64rem;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--gold);
}

.copy__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.7rem, 1.3rem + 1.4vw, 2.4rem);
  line-height: 1.1;
}

.copy__hint {
  margin: .55rem 0 1.1rem;
  font-size: .8rem;
  letter-spacing: .04em;
  color: var(--ink-50);
}

.btn {
  min-height: 44px;
  padding: 0 1.6rem;
  border: 1px solid var(--gold-40);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-gold);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .24em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color .25s var(--ease), color .25s var(--ease), transform .2s var(--ease);
}
.btn:hover { border-color: var(--gold); }
.btn:active { transform: scale(.97); }

.btn--gold { background: var(--gold); border-color: var(--gold); color: var(--sand-50); }
.btn--gold:hover { background: var(--ink-gold); border-color: var(--ink-gold); }

/* "Step inside" only exists once the courtyard has finished building. */
.btn--enter { display: none; }
body[data-court="ready"] .btn--enter { display: inline-flex; align-items: center; justify-content: center; gap: .55rem; }

/* The arrow says there is more below, and keeps nudging that way. */
.btn__arrow {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: nudge-on 1.9s var(--ease) infinite;
}
@keyframes nudge-on {
  0%, 100% { transform: translateY(-1px); }
  50%      { transform: translateY(3px); }
}

/* ── The entrance ──────────────────────────────────────────────────────── */

/* Two leaves of blind-embossed paper, closed over the stage and joined by a
   hairline of gold, with a pressed seal between them. They also hide the
   printing, which is why this page has no loader: the wait is spent looking
   at something finished rather than at a progress ring. */
.gate {
  position: fixed;
  inset: 0;
  z-index: 7;
  visibility: visible;
  transition: visibility 0s linear 1.3s;
  --px: 0px;                                /* the seal leans with the pointer */
  --py: 0px;
}
body[data-gate="open"] .gate { visibility: hidden; }
body[data-state="fallback"] .gate { display: none; }

.gate__leaf {
  position: absolute;
  top: -1px;
  bottom: -1px;
  width: calc(50% + 1px);
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='128' height='128' viewBox='0 0 128 128'><g fill='none' stroke='%23ffffff' stroke-opacity='.38' stroke-width='1'><rect x='40' y='40' width='48' height='48'/><rect x='40' y='40' width='48' height='48' transform='rotate(45 64 64)'/><circle cx='64' cy='64' r='33.9'/></g><g fill='none' stroke='%236b5326' stroke-opacity='.045' stroke-width='1' transform='translate(0 1.2)'><rect x='40' y='40' width='48' height='48'/><rect x='40' y='40' width='48' height='48' transform='rotate(45 64 64)'/><circle cx='64' cy='64' r='33.9'/></g></svg>"),
    linear-gradient(180deg, #EFE4D0 0%, #E3D4B9 52%, #D6C4A4 100%);
  background-size: 148px 148px, auto;
  transition: transform 1.25s cubic-bezier(.58, .02, .2, 1);
  will-change: transform;
}
.gate__leaf--left  { left: 0; }
.gate__leaf--right { right: 0; background-position: right top, right top; }

/* One pool of light, centred on the join: each leaf carries its own half of
   it, anchored to its inner edge, so the two make a single glow. */
.gate__leaf::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.gate__leaf--left::before {
  background: radial-gradient(170% 105% at 100% 45%, rgba(255, 253, 247, .95) 0%, rgba(255, 253, 247, 0) 56%);
}
.gate__leaf--right::before {
  background: radial-gradient(170% 105% at 0% 45%, rgba(255, 253, 247, .95) 0%, rgba(255, 253, 247, 0) 56%);
}

/* The printed frame: one rule around the pair, which parts with them. */
.gate__leaf::after {
  content: "";
  position: absolute;
  inset: clamp(14px, 3.4vmin, 30px);
  border: 1px solid rgba(176, 141, 74, .26);
}
.gate__leaf--left::after  { border-right: 0; }
.gate__leaf--right::after { border-left: 0; }

/* And the shadow each leaf casts into the join, so the two read as paper
   lying over something rather than as one flat field. */
.gate__leaf--left  { box-shadow: inset -18px 0 26px -20px rgba(92, 68, 30, .55); }
.gate__leaf--right { box-shadow: inset 18px 0 26px -20px rgba(92, 68, 30, .55); }

body[data-gate="open"] .gate__leaf--left  { transform: translate3d(-100.5%, 0, 0); }
body[data-gate="open"] .gate__leaf--right { transform: translate3d(100.5%, 0, 0); }

/* The join: a hairline of gold that fades as the leaves part. */
.gate__seam {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  margin-left: -.5px;
  background: linear-gradient(180deg,
    transparent 0%, var(--gold-40) 16%, var(--gold-hi) 50%, var(--gold-40) 84%, transparent 100%);
  opacity: .55;
  transform: scaleY(.9);
  transform-origin: 50% 50%;
  transition: opacity .45s var(--ease), transform .9s var(--ease);
}
body[data-gate="open"] .gate__seam { opacity: 0; transform: scaleY(1); transition-duration: .4s, .4s; }

/* The seal: pressed into the paper, ringed twice in gold, with light moving
   slowly across its face as foil does. */
.gate__seal {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(calc(-50% + var(--px)), calc(-50% + var(--py)));
  display: grid;
  place-items: center;
  align-content: center;
  gap: .4rem;
  width: clamp(152px, 22vmin, 192px);
  height: clamp(152px, 22vmin, 192px);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background:
    radial-gradient(120% 120% at 50% 26%, #FEFBF4 0%, #F6EEDF 58%, #EADCC3 100%);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .95) inset,
    0 -10px 22px -14px rgba(120, 92, 44, .5) inset,
    0 18px 44px rgba(94, 72, 40, .22),
    0 3px 10px rgba(94, 72, 40, .12);
  cursor: pointer;
  transition: transform .5s var(--ease), opacity .6s var(--ease), box-shadow .35s var(--ease);
}
.gate__seal::after {                        /* the fine rule pressed inside */
  content: "";
  position: absolute;
  inset: 9px;
  border: 1px solid rgba(176, 141, 74, .42);
  border-radius: 50%;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .7);
}
/* Light travelling across the foil. It is clipped to the disc by a layer of
   its own, so nothing else on the seal is cut off with it — the script M has
   a swash that reaches past the edge of the type. */
.gate__sheen {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  pointer-events: none;
}
.gate__sheen::after {
  content: "";
  position: absolute;
  inset: -45%;
  background: linear-gradient(74deg,
    transparent 36%,
    rgba(255, 255, 255, .5) 45%,
    rgba(255, 252, 244, .95) 50%,
    rgba(255, 244, 218, .5) 55%,
    transparent 64%);
  transform: translateX(-70%);
  animation: gate-sheen 6.5s ease-in-out .45s infinite;
}
/* The sweep comes first, so it happens as the page arrives rather than four
   seconds after the guest has stopped looking. */
@keyframes gate-sheen {
  0%        { transform: translateX(-70%); }
  26%, 100% { transform: translateX(70%); }
}
.gate__seal:hover { box-shadow:
  0 1px 0 rgba(255, 255, 255, .95) inset,
  0 -10px 22px -14px rgba(120, 92, 44, .5) inset,
  0 22px 52px rgba(94, 72, 40, .26),
  0 3px 10px rgba(94, 72, 40, .12); }
.gate__seal:active { transform: translate(calc(-50% + var(--px)), calc(-50% + var(--py))) scale(.985); }

/* Two rings drifting outward, one behind the other. */
.gate__ring {
  position: absolute;
  inset: -6px;
  border: 1px solid var(--gold-40);
  border-radius: 50%;
  opacity: 0;
  animation: gate-ring 4.4s var(--ease) infinite;
}
.gate__ring--late { animation-delay: 2.2s; }
@keyframes gate-ring {
  0%   { transform: scale(.95); opacity: 0; }
  18%  { opacity: .6; }
  100% { transform: scale(1.62); opacity: 0; }
}

.gate__mark {
  font-family: var(--script);
  font-size: clamp(1.95rem, 4vmin, 2.45rem);
  line-height: 1.24;                        /* the swash sits below the baseline */
  padding: 0 .35rem;
  color: var(--ink-gold);
  /* Foil: the gold turns as the light crosses it. */
  background: linear-gradient(118deg, #A87F33 0%, #E9CE93 30%, #96702A 48%, #EFD69F 70%, #A87F33 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.gate__mark i {
  font-family: var(--serif);
  font-style: italic;
  font-size: .44em;
  margin: 0 .2em;
}

.gate__rule {
  width: 34px;
  height: 1px;
  margin: .1rem 0 .05rem;
  background: linear-gradient(90deg, transparent, var(--gold-40) 30%, var(--gold) 50%, var(--gold-40) 70%, transparent);
}

.gate__label {
  font-size: .55rem;
  font-weight: 500;
  letter-spacing: .28em;
  text-indent: .28em;
  text-transform: uppercase;
  color: rgba(59, 44, 23, .58);
}

/* The seal is gone before the leaves are, so nothing is seen sliding away. */
body[data-gate="open"] .gate__seal {
  opacity: 0;
  transform: translate(calc(-50% + var(--px)), calc(-50% + var(--py))) scale(1.16);
  transition-duration: .45s, .38s;
  pointer-events: none;
}
body[data-gate="open"] .gate__ring { animation: none; opacity: 0; }

/* ── Reading UI (phones, card open) ────────────────────────────────────── */

.reading-ui {
  position: fixed;
  z-index: 5;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(96px + env(safe-area-inset-bottom));   /* mirrors READING_FOOTER_PX */
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  padding: 0 var(--gutter) var(--safe-b);
  pointer-events: none;
  background: linear-gradient(to top, rgba(242, 232, 216, .95) 0%, rgba(242, 232, 216, .72) 50%, rgba(242, 232, 216, 0) 100%);
  opacity: 0;
  visibility: hidden;
  transition: opacity .7s var(--ease), visibility .7s;
}

body[data-state="card-open"][data-layout="vertical"] .reading-ui {
  opacity: 1;
  visibility: visible;
  transition-delay: .2s;
}

/* Page cue: two dots (which page) and where the other page is. Also a
   button, for anyone who would rather tap than swipe. */
.page-cue {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: .75rem;
  min-height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-70);
  font-size: .62rem;
  font-weight: 400;
  letter-spacing: .2em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}

.page-cue__dots { display: grid; gap: 5px; }
.page-cue__dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ink-14);
  transition: background .4s var(--ease), transform .4s var(--ease);
}
.page-cue[data-page="0"] .page-cue__dots i:first-child,
.page-cue[data-page="1"] .page-cue__dots i:last-child {
  background: var(--gold);
  transform: scale(1.25);
}

.pill {
  pointer-events: auto;
  min-height: 40px;
  padding: 0 1.1rem;
  border: 1px solid var(--gold-40);
  border-radius: 999px;
  background: rgba(255, 252, 246, .78);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 1px 10px rgba(59, 44, 23, .07);
  color: var(--ink-70);
  font-size: .62rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: transform .2s var(--ease), color .25s var(--ease);
}
.pill:active { transform: scale(.97); }

.pill--gold {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--sand-50);
  box-shadow: none;
}

/* Phones: on the verse page, once the courtyard is ready, Step inside takes
   the cue's place; on the details page the cue stays. */
body[data-court="ready"][data-page="1"] .page-cue { display: none; }
body:not([data-page="1"]) .reading-ui .btn--enter { display: none; }

/* ── Text version ──────────────────────────────────────────────────────── */

.text-version {
  width: min(92vw, 34rem);
  max-height: 86dvh;
  padding: 3rem clamp(1.4rem, 5vw, 2.8rem) 2.4rem;
  border: 1px solid var(--gold-20);
  border-radius: 4px;
  background: #F4EDE0;
  color: var(--ink);
  text-align: center;
  font-family: var(--serif);
}
.text-version::backdrop { background: rgba(59, 44, 23, .52); backdrop-filter: blur(6px); }

.text-version__close { position: absolute; top: .9rem; right: .9rem; }
.btn--ink { color: var(--ink); border-color: rgba(59, 44, 23, .22); min-height: 38px; padding: 0 1rem; }
.btn--ink:hover { border-color: var(--ink); }

.tv-arabic { font-family: var(--arabic); font-size: 1.6rem; line-height: 2; color: var(--ink); margin: 0; }
.tv-arabic:first-of-type { color: var(--ink-gold); }
.tv-eyebrow {
  margin: 1rem 0 0;
  font-family: var(--caps);
  font-weight: 600;
  font-size: .72rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink);
}
.tv-names {
  font-family: var(--script);
  font-weight: 400;
  font-size: clamp(2.1rem, 4vw, 3.2rem);
  line-height: 1.1;
  margin: .2rem 0;
  color: var(--ink-gold);
  word-break: break-word;
  overflow-wrap: anywhere;
}
.tv-names i { font-family: var(--serif); font-size: .45em; }
.tv-small { font-style: italic; font-size: 1.05rem; line-height: 1.5; color: #6B5A42; margin: .4rem 0 0; }

.tv-events {
  display: grid;
  /* One event fills the width; two sit side by side. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: 1.4rem;
  margin: 1.8rem 0;
  padding: 1.6rem 0;
  /* border-block: 1px solid rgba(138, 106, 48, .28); */
}
.tv-events h3 {
  margin: 0 0 .6rem;
  font-family: var(--caps);
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-gold);
}
.tv-events p { margin: 0 0 .7rem; font-size: 1.08rem; line-height: 1.45; }
.tv-events span { font-style: italic; font-size: .98rem; color: #6B5A42; }

.tv-verse { margin: 0 0 1.4rem; }
.tv-verse p:not(.tv-arabic) { font-style: italic; font-size: 1.08rem; line-height: 1.6; color: #4A3A22; }
.tv-verse cite {
  font-family: var(--caps);
  font-style: normal;
  font-weight: 600;
  font-size: .72rem;
  letter-spacing: .14em;
  color: var(--ink-gold);
}

/* ── No WebGL: the text version becomes the page ───────────────────────── */

body[data-state="fallback"] { overflow: auto; }
html:has(body[data-state="fallback"]) { overflow: auto; }
body[data-state="fallback"] .text-version {
  position: static;
  display: block;
  margin: calc(var(--header) + 1.5rem) auto 3rem;
  max-height: none;
}
body[data-state="fallback"] .text-version__close { display: none; }

/* ── Courtyard ─────────────────────────────────────────────────────────── */

.court-ui {
  position: fixed;
  z-index: 5;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.6rem var(--gutter) var(--safe-b);
  text-align: center;
  pointer-events: none;
  /* Just enough to hold the type, not a black band across the courtyard. */
  background: linear-gradient(to top, rgba(6, 12, 18, .66) 0%, rgba(6, 12, 18, .3) 48%, rgba(6, 12, 18, 0) 100%);
  opacity: 0;
  visibility: hidden;
  transition: opacity .9s var(--ease), visibility .9s;
}
body[data-stop="3"] .court-ui,
body[data-stop="4"] .court-ui,
body[data-stop="5"] .court-ui {
  background: linear-gradient(to top, rgba(6, 12, 18, .5) 0%, rgba(6, 12, 18, .16) 42%, rgba(6, 12, 18, 0) 100%);
}

body[data-state="courtyard"] .court-ui {
  opacity: 1;
  visibility: visible;
  transition-delay: .9s;       /* after the veil has begun to lift */
}

/* Passages stack in one grid cell and cross-fade. */
.court-ui { display: grid; justify-items: center; }
.court-stop {
  grid-area: 1 / 1;
  max-width: 30rem;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}
body[data-stop="0"] .court-stop[data-court-stop="0"],
body[data-stop="1"] .court-stop[data-court-stop="1"],
body[data-stop="2"] .court-stop[data-court-stop="2"],
body[data-stop="3"] .court-stop[data-court-stop="3"] {
  opacity: 1;
  transform: none;
  transition-delay: .35s;
}

.court-arabic {
  margin: 0;
  font-family: var(--arabic);
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.2rem);
  line-height: 1.8;
  color: var(--gold-hi);
}
.court-title {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.6rem, 1.3rem + 1.2vw, 2.2rem);
  line-height: 1.15;
}
.court-line {
  margin: .5rem auto 0;
  max-width: 26rem;
  font-family: var(--serif);
  font-size: clamp(1rem, .95rem + .3vw, 1.15rem);
  line-height: 1.45;
  color: var(--ivory-70);
}
.court-cite {
  margin: .6rem 0 0;
  font-size: .62rem;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--gold);
}

.court-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .8rem;
  margin-top: 1.4rem;
  font-size: .62rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ivory-50);
  white-space: nowrap;
}
.court-dots { display: flex; gap: 6px; }
.court-dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ivory-14);
  transition: background .4s var(--ease), transform .4s var(--ease);
}
body[data-stop="0"] .court-dots i:nth-child(1),
body[data-stop="1"] .court-dots i:nth-child(2),
body[data-stop="2"] .court-dots i:nth-child(3),
body[data-stop="3"] .court-dots i:nth-child(4),
body[data-stop="4"] .court-dots i:nth-child(5),
body[data-stop="5"] .court-dots i:nth-child(6) {
  background: var(--gold-hi);
  transform: scale(1.3);
}

/* ── Sound ─────────────────────────────────────────────────────────────── */

/* The same control twice: once in the masthead, where the page is light, and
   once as a chip in the courtyard, where the masthead is hidden and the night
   wants dark glass. Both are bound to the same switch. */
.sound {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--ink-14);
  border-radius: 50%;
  background: rgba(255, 252, 246, .5);
  color: var(--ink-gold);
  cursor: pointer;
  pointer-events: auto;
  transition: border-color .25s var(--ease), background-color .25s var(--ease), opacity .4s var(--ease);
}
.sound svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.sound__off { opacity: 0; transition: opacity .2s var(--ease); }
.sound[data-muted] { color: var(--ink-50); }
.sound[data-muted] .sound__bars { opacity: .5; }
.sound[data-muted] .sound__off { opacity: 1; }
.sound:hover { border-color: var(--gold-40); }

.masthead .sound { margin-left: .85rem; }

/* In the courtyard it stands on its own, opposite the way back. */
.sound--court {
  position: fixed;
  z-index: 7;
  top: calc(env(safe-area-inset-top) + .9rem);
  right: var(--gutter);
  width: 40px;
  height: 40px;
  border-color: rgba(233, 208, 152, .34);
  background: rgba(26, 20, 13, .58);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 26px rgba(12, 7, 2, .38);
  color: #F2E2BC;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .5s var(--ease), visibility .5s;
}
.sound--court[data-muted] { color: rgba(242, 226, 188, .6); }
body[data-state="courtyard"] .sound--court {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition-delay: .5s;
}
/* And the one in the masthead steps aside while the courtyard has its own. */
body[data-state="entering"] .masthead .sound,
body[data-state="leaving"] .masthead .sound,
body[data-state="courtyard"] .masthead .sound { opacity: 0; }

/* ── The way back out of the hall ──────────────────────────────────────── */

/* The reply covers the screen, so the swipe that walks the guest back has
   nothing to land on. This sits clear of the card, in the corner the masthead
   leaves empty inside the courtyard. */
.court-back {
  position: fixed;
  z-index: 7;
  top: calc(env(safe-area-inset-top) + .9rem);
  left: var(--gutter);
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  min-height: 40px;
  padding: 0 .95rem 0 .7rem;
  border: 1px solid rgba(233, 208, 152, .34);
  border-radius: 999px;
  background: rgba(26, 20, 13, .58);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 26px rgba(12, 7, 2, .38);
  color: #F2E2BC;
  font-size: .58rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(-6px);
  transition: opacity .5s var(--ease), transform .5s var(--ease), visibility .5s;
}
body[data-state="courtyard"][data-stop="5"] .court-back {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition-delay: .5s;
}
.court-back:active { transform: scale(.97); }
.court-back svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── The reply ─────────────────────────────────────────────────────────── */

/* A card of the same paper as everything else, held up in the hall. It is a
   real form: the 3D behind it is scenery, and this is the one thing on the
   page a guest is asked to do. */
.rsvp {
  position: fixed;
  z-index: 6;
  left: 50%;
  top: 50%;
  width: min(93vw, 25.5rem);
  max-height: calc(100dvh - var(--header) - 5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translate(-50%, -46%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .7s var(--ease), transform .7s var(--ease), visibility .7s;
}
body[data-state="courtyard"][data-stop="5"] .rsvp {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translate(-50%, -50%);
  transition-delay: .45s;
}

.rsvp__card {
  position: relative;
  padding: 1.7rem clamp(1.2rem, 4.5vw, 1.9rem) 1.5rem;
  border-radius: 8px;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(255, 253, 247, 1) 0%, rgba(249, 244, 235, .97) 60%),
    rgba(249, 244, 235, .97);
  box-shadow:
    0 0 0 1px rgba(176, 141, 74, .3),
    0 26px 70px rgba(0, 0, 0, .5);
  color: var(--ink);
  text-align: center;
}
.rsvp__card::after {                        /* the printed rule inside, as on the boards */
  content: "";
  position: absolute;
  inset: 7px;
  border: 1px solid rgba(176, 141, 74, .2);
  border-radius: 4px;
  pointer-events: none;
}

.rsvp__star {
  display: block;
  width: 17px;
  height: 17px;
  margin: 0 auto .6rem;
  fill: none;
  stroke: var(--gold);
  stroke-width: 1;
  opacity: .85;
}

.rsvp__title {
  margin: .1rem 0 1.25rem;
  font-family: var(--serif);
  font-weight: 400;
  font-style: italic;
  font-size: clamp(1.3rem, 1.15rem + .8vw, 1.6rem);
  line-height: 1.2;
}

/* Yes or no, as one control with a gold marker that slides between them. */
.seg {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-bottom: 1.35rem;
  padding: 4px;
  border: 1px solid var(--ink-14);
  border-radius: 999px;
  background: rgba(255, 255, 255, .55);
}
.seg__slider {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  border-radius: 999px;
  background: linear-gradient(180deg, #C9A65E 0%, #AF8A44 100%);
  box-shadow: 0 2px 8px rgba(120, 92, 44, .3);
  opacity: 0;
  transform: translateX(0);
  transition: transform .42s var(--ease), opacity .3s var(--ease);
}
.seg[data-on] .seg__slider { opacity: 1; }
.seg[data-on="No"] .seg__slider { transform: translateX(100%); }

.seg__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.seg__opt span {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 .5rem;
  border-radius: 999px;
  font-family: var(--serif);
  font-size: .95rem;
  line-height: 1.2;
  color: var(--ink-70);
  cursor: pointer;
  transition: color .3s var(--ease);
}
.seg__opt input:checked + span { color: #FFF9EE; }
.seg__opt input:focus-visible + span { outline: 1.5px solid var(--gold-hi); outline-offset: 2px; }

/* Written on a ruled line, the way a name is written on paper. */
.field {
  position: relative;
  margin-bottom: 1.35rem;
  text-align: left;
}
.field input {
  width: 100%;
  min-height: 44px;
  padding: 1.05rem .1rem .35rem;
  border: 0;
  border-bottom: 1px solid var(--ink-14);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1.05rem;
  transition: border-color .25s var(--ease);
}
.field input:focus { outline: none; border-bottom-color: var(--gold); }
.field label {
  position: absolute;
  left: .1rem;
  top: .95rem;
  transform-origin: 0 0;
  font-family: var(--ui);
  font-size: .82rem;
  letter-spacing: .02em;
  color: rgba(59, 44, 23, .5);
  pointer-events: none;
  transition: transform .28s var(--ease), color .28s var(--ease);
}
.field input:focus + label,
.field input:not(:placeholder-shown) + label {
  transform: translateY(-.95rem) scale(.7);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-gold);
}

/* How many are coming: a counter, not a spinner nobody can hit. */
.count {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
  text-align: left;
}
.count__label {
  font-size: .58rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-50);
}
.count__box {
  display: flex;
  align-items: center;
  gap: .1rem;
  padding: 3px;
  border: 1px solid var(--ink-14);
  border-radius: 999px;
  background: rgba(255, 255, 255, .55);
}
.count__btn {
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-gold);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.count__btn:hover { background: rgba(176, 141, 74, .12); }
.count__btn:active { background: rgba(176, 141, 74, .2); }
.count__box input {
  width: 2.4rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1.15rem;
  text-align: center;
  -moz-appearance: textfield;
}
.count__box input::-webkit-outer-spin-button,
.count__box input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.count__box input:focus { outline: none; }

.rsvp__send {
  position: relative;
  overflow: hidden;
  width: 100%;
  min-height: 50px;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(180deg, #C9A65E 0%, #AF8A44 100%);
  box-shadow: 0 6px 18px rgba(120, 92, 44, .28), inset 0 1px 0 rgba(255, 246, 224, .4);
  color: #FFF9EE;
  font-size: .64rem;
  font-weight: 500;
  letter-spacing: .26em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform .15s var(--ease), box-shadow .25s var(--ease);
}
.rsvp__send span { position: relative; }
.rsvp__send::after {                        /* light crossing the gold */
  content: "";
  position: absolute;
  inset: -50%;
  background: linear-gradient(72deg, transparent 40%, rgba(255, 255, 255, .45) 50%, transparent 60%);
  transform: translateX(-70%);
  animation: gate-sheen 6s ease-in-out infinite;
}
.rsvp__send:hover { box-shadow: 0 10px 24px rgba(120, 92, 44, .34), inset 0 1px 0 rgba(255, 246, 224, .4); }
.rsvp__send:active { transform: scale(.985); }
.rsvp__send[disabled] { opacity: .65; cursor: default; }

.rsvp__note {
  min-height: 1.1rem;
  margin: .95rem 0 0;
  font-family: var(--serif);
  font-size: .92rem;
  line-height: 1.45;
  color: var(--ink-70);
}
.rsvp__note[data-bad] { color: #8C3A2A; }

/* Once it is sent, the form steps aside and only the thanks remain. */
.rsvp__card[data-sent] .seg,
.rsvp__card[data-sent] .field,
.rsvp__card[data-sent] .count,
.rsvp__card[data-sent] .rsvp__send { display: none; }
.rsvp__card[data-sent] .rsvp__title { margin-bottom: .3rem; }

/* The burst of gold. Above everything, in the way of nothing. */
.celebrate {
  position: fixed;
  inset: 0;
  z-index: 8;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity .4s var(--ease);
}
.celebrate[data-on] { opacity: 1; }

/* ── The directions plate ──────────────────────────────────────────────── */

/* A floating pill, held at the foot of the venue board by scene.js. Dark
   glass against bright paper: it reads instantly as the one thing here that
   can be pressed, without pretending to be printed on the board. */
.plate {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 5;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .66rem 1.15rem;
  border-radius: 999px;
  border: 1px solid rgba(233, 208, 152, .38);
  background: rgba(26, 20, 13, .62);
  backdrop-filter: blur(12px) saturate(1.15);
  -webkit-backdrop-filter: blur(12px) saturate(1.15);
  box-shadow:
    inset 0 1px 0 rgba(255, 246, 224, .22),
    0 2px 6px rgba(12, 7, 2, .3),
    0 14px 34px rgba(12, 7, 2, .45);
  color: #F2E2BC;
  font-size: .6rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(.9) translateY(6px);
  transform-origin: 50% 50%;
  transition:
    opacity .5s var(--ease),
    transform .5s var(--ease),
    visibility .5s,
    background-color .25s var(--ease),
    border-color .25s var(--ease);
}
.plate[data-show] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
  transition-delay: .35s;
}
.plate:hover {
  background: rgba(38, 29, 18, .74);
  border-color: rgba(233, 208, 152, .62);
}
.plate:active { transform: translate(-50%, -50%) scale(.97); }

/* The arrow leans out of the pill: this leaves the page. */
.plate__out {
  width: 11px;
  height: 11px;
  margin-left: -.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .72;
}

.plate__pin {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (prefers-reduced-motion: reduce) {
  .gate__ring { animation: none; opacity: .5; }
  .gate__seal::before { animation: none; opacity: .35; }
  .gate__leaf, .gate__seal, .gate__seam { transition-duration: .01ms; }
  .copy, #stage, .reading-ui { transition-duration: .01ms; }
}
