/* Guest portal — styled after the printed invite: ivory and champagne, antique
   gold, sage and leaf green, a pointed arch frame. Mobile first. */

:root {
  --ivory: #fbf6ec;
  --surround: #f0e2c6;
  --gold: #b0893f;
  --gold-deep: #86672a;
  --gold-soft: #d9c08a;
  --gold-text: linear-gradient(180deg, #c49c4e 0%, #9b772f 55%, #7e5f22 100%);
  --sage: #5f7350;
  --leaf: #2f4a2c;
  --ink: #3f3222;
  --ink-soft: #6a5840;
  --error: #9a3b2b;

  --display: 'Cormorant Garamond', 'Cormorant', Garamond, 'Times New Roman', serif;
  --body: 'EB Garamond', Garamond, Georgia, 'Times New Roman', serif;
  /* The couple's names. */
  --script: 'Great Vibes', 'Apple Chancery', 'URW Chancery L', cursive;

  /* Overwritten by js/frame.js from the viewport; sensible values for first paint. */
  --vw: 100vw;
  --vh: 100vh;
  --arch-left: 4vw;
  --arch-width: 92vw;
  --arch-bottom: calc(100vh - 14px);
  --arch-bottom-gap: 14px;
  --header-bottom: 200px;
  --content-left: 10vw;
  --content-width: 80vw;
  --mono-h: 98px;
  --mono-top: 105px;
  --garland-left: 0px;
  --garland-width: 100vw;
  --greet-cy: 190px;

  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--ivory);
  scroll-padding-top: calc(var(--header-bottom) + 24px);
  scroll-padding-bottom: calc(var(--arch-bottom-gap) + 64px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  /* Never shorter than the viewport at its tallest, for the same reason. */
  min-height: 100lvh;
  background: var(--ivory);
  color: var(--ink);
  font: 400 1.0625rem/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* `clip` where it exists (it keeps position: fixed working); `hidden` as the
   fallback for older iOS. Either way the intro's scaled-up layers can't make
   the page wider, which would make a phone zoom the whole page out. */
html, body { overflow-x: hidden; overflow-x: clip; }

html.intro-locked,
html.intro-locked body { overflow: hidden; }

img { max-width: 100%; display: block; }
p { margin: 0; }

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

:focus-visible { outline: 2px solid var(--leaf); outline-offset: 3px; }

.gold-text,
.person-name, .event-title, .date-day, .closing-title, .state-title {
  color: var(--gold-deep);
}
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .person-name, .event-title, .date-day, .closing-title, .state-title {
    background: var(--gold-text);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* Cormorant defaults to old-style figures, where 1 reads as I. */
.date-block, .stepper-value, .seal-detail, .closing-deadline-date, .rsvp-places, .button { font-variant-numeric: lining-nums; }

/* ---- Fixed frame ------------------------------------------------------- */

/* Everything below is positioned absolutely inside this box, never fixed
   itself. Mobile browsers disagree about which viewport a fixed box gets —
   iOS gives it the tall one whether or not the URL bar is showing, and the
   bar can sit at either end — so the box is NOT clipped, and the layers
   inside deliberately paint well past it in both directions. Horizontal
   overflow is held in by `overflow-x: clip` on html and body instead. */
.frame {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.arch-layer {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  will-change: transform, opacity;
}

.arch-svg { position: absolute; left: 0; top: 0; overflow: visible; }

/* The surround and the covers swallow taps meant for content they hide. */
.surround { fill: var(--surround); pointer-events: auto; }
.surround-pattern { opacity: 0.22; }
.arch-line { fill: none; stroke: var(--gold); }
.arch-outer { stroke-width: 1.6; }
.arch-inner { stroke-width: 0.8; stroke: var(--gold-soft); }

.arch-cover { position: absolute; left: var(--arch-left); width: var(--arch-width); pointer-events: auto; }
.arch-cover-top { top: -40vh; height: calc(var(--header-bottom) + 40vh); background: var(--ivory); }
.arch-cover-top::after {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 3rem;
  background: linear-gradient(var(--ivory), rgba(251, 246, 236, 0));
  pointer-events: none;
}
.arch-cover-bottom {
  top: calc(var(--arch-bottom) - 3rem);
  /* Runs past the arch's foot, so a URL bar collapsing mid-scroll can't
     reveal a gap under it. */
  height: calc(var(--arch-bottom-gap) + 3rem + 40vh);
  background: linear-gradient(rgba(251, 246, 236, 0), var(--ivory) 3rem);
  pointer-events: none;
}

.corners { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.corner {
  --corner-out: clamp(26px, 8vw, 80px);
  position: absolute;
  bottom: calc(var(--arch-bottom-gap) - 8px);
  width: var(--corner-w);
  will-change: transform, opacity;
}
/* Left: the table scene (w/h ≈ 0.85). Right: a wide, low garden (≈ 1.87) that trails inward along the base. */
.corner-left { --corner-w: clamp(100px, 27vw, 300px); height: calc(var(--corner-w) / 0.845); }
.corner-right { --corner-w: clamp(170px, 50vw, 500px); height: calc(var(--corner-w) / 1.87); }
@media (min-width: 760px) {
  /* Wide screens have room beside the arch: let the foliage sit mostly outside it. */
  .corner-left { --corner-out: calc(var(--corner-w) * 0.62); }
  .corner-right { --corner-out: calc(var(--corner-w) * 0.45); }
}
.corner-left { left: calc(var(--arch-left) - var(--corner-out)); }
.corner-right { left: calc(var(--arch-left) + var(--arch-width) + var(--corner-out) - var(--corner-w)); }
.corner-florals { position: absolute; bottom: 0; width: 100%; }
.corner-left .corner-florals { left: 0; }
.corner-right .corner-florals { right: 0; }

.garland {
  position: absolute;
  z-index: 3;
  top: 0;
  left: var(--garland-left);
  width: var(--garland-width);
  pointer-events: none;
  will-change: transform, opacity;
}
.garland-img { width: 100%; }

.brand { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
/* Shrink-wrapped and centred with auto margins, so a scaled intro state stays narrow. */
.brand-monogram {
  position: absolute;
  left: 0; right: 0;
  width: fit-content;
  margin: 0 auto;
  top: var(--mono-top);
  height: var(--mono-h);
  will-change: transform;
}
.brand-monogram-img { height: 100%; width: auto; }
.brand-greeting {
  position: absolute;
  left: 0; right: 0;
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
  top: var(--greet-cy);
  height: 2em;
  margin-top: -1em;
  line-height: 2em;
  text-align: center;
  font: italic 500 clamp(1.05rem, calc(var(--mono-h) * 0.18), 1.6rem) var(--display);
  letter-spacing: 0.02em;
  color: var(--gold-deep);
  will-change: transform;
}
.brand-greeting-text { display: inline-block; white-space: nowrap; }

/* ---- Intro (only while motion is on) --------------------------------- */

.intro-spacer, .intro-stage { display: none; }
html.motion .intro-spacer { display: block; height: var(--vh); }
html.motion.intro-done .intro-spacer { display: none; }

html.motion .intro-stage { display: block; position: absolute; inset: 0; z-index: 5; pointer-events: none; }
.intro-logo, .intro-greeting { display: none; }
html.reduced .intro-logo {
  display: flex;
  justify-content: center;
  position: absolute;
  left: 0; right: 0;
  /* The tall logo, sized by height and kept within 70% of the width (0.7 / 0.56 aspect = 125vw). */
  --size: clamp(180px, min(46vh, 125vw), 440px);
  top: calc(var(--vh) * 0.4 - var(--size) / 2);
  height: var(--size);
}
html.reduced .intro-logo img { height: 100%; width: auto; }
html.reduced .intro-greeting {
  display: block;
  position: absolute;
  left: 0; right: 0;
  top: calc(var(--vh) * 0.4 + clamp(180px, min(46vh, 125vw), 440px) / 2 + 18px);
  text-align: center;
  font: italic 500 clamp(1.4rem, 6vw, 2rem) var(--display);
  color: var(--gold-deep);
}

.intro-status {
  position: absolute;
  left: 0; right: 0;
  /* Anchored from the top in small-viewport units: the frame around it is as
     tall as the viewport gets, so anything hung off its bottom disappears
     under a browser's toolbar. */
  top: 78vh;
  top: calc(78svh - env(safe-area-inset-bottom, 0px));
  height: 5rem;
  text-align: center;
  color: var(--gold-deep);
}
.intro-loading, .scroll-hint { position: absolute; left: 0; right: 0; bottom: 0; opacity: 0; }
.intro-loading { font: italic 400 1.1rem var(--display); color: var(--ink-soft); }
.scroll-hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  font: 600 0.72rem/1 var(--display);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  padding-left: 0.32em;
}
.scroll-hint-line {
  width: 1px;
  height: 40px;
  background: linear-gradient(var(--gold), rgba(176, 137, 63, 0));
  transform-origin: top;
  animation: hint-line 2.4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
@keyframes hint-line {
  0% { transform: scaleY(0); opacity: 1; }
  55% { transform: scaleY(1); opacity: 1; }
  100% { transform: translateY(14px) scaleY(1); opacity: 0; }
}

/* ---- Content column (scrolls inside the arch) ------------------------ */

.content {
  position: relative;
  z-index: 1;
  margin-left: var(--content-left);
  width: var(--content-width);
  min-height: var(--vh);
  padding-top: calc(var(--header-bottom) + 3.5rem);
  padding-bottom: calc(var(--vh) * 0.1 + var(--arch-bottom-gap));
  text-align: center;
}

.loading { font: italic 400 1.15rem var(--display); color: var(--ink-soft); padding-top: 2rem; }

.divider {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  max-width: 15rem;
  margin: 1.75rem auto;
}
.divider-rule { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(217, 192, 138, 0), var(--gold-soft)); }
.divider-rule:last-child { background: linear-gradient(90deg, var(--gold-soft), rgba(217, 192, 138, 0)); }
.divider-diamond { width: 0.5rem; height: 0.5rem; background: var(--gold); transform: rotate(45deg); flex: none; }

/* Hero */
.hero { padding-bottom: 1rem; }
.rsvp-heading, .closing-deadline-label {
  font: 600 0.74rem/1.3 var(--display);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  padding-left: 0.3em;
}
.guest-greeting {
  font: italic 500 clamp(1.9rem, 8.5vw, 2.7rem)/1.15 var(--display);
  color: var(--gold-deep);
  overflow-wrap: anywhere;
}
.invitation-line {
  font: italic 400 1.22rem/1.5 var(--display);
  color: var(--ink-soft);
  max-width: 23rem;
  margin: 0 auto 2rem;
}
.couple { display: grid; gap: 0.25rem; }
.person-name {
  font: 400 clamp(2.3rem, 10.5vw, 3.1rem)/1.45 var(--script);
  /* The gold gradient is clipped to this box, so the script's tall swashes
     need room inside it or their tops are cut off. */
  padding: 0.22em 0.2em 0.12em;
  margin-bottom: 0.2rem;
}
.lineage { font-size: 0.9rem; line-height: 1.55; color: var(--ink-soft); }
.ampersand { font: italic 300 3.4rem/1 var(--display); color: var(--gold); margin: 0.9rem 0 0.5rem; }
.events-lead { font: italic 400 1.2rem/1.5 var(--display); color: var(--ink-soft); max-width: 22rem; margin: 0 auto; }


/* Event */
.event {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--arch-bottom) - var(--header-bottom));
  padding: 4rem 0 3rem;
}
.event-title {
  font: italic 500 clamp(2.7rem, 12.5vw, 3.8rem)/1.1 var(--display);
  margin: 0 0 1.5rem;
  padding: 0 0.1em;
}
.date-block { width: 100%; max-width: 21rem; margin: 0 auto 1.5rem; }
.date-month { font: 500 1.4rem/1.2 var(--display); color: var(--ink-soft); margin-bottom: 0.35rem; }
.date-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; }
.date-side { display: flex; flex-direction: column; gap: 0.45rem; }
.date-rule { display: block; height: 1px; background: var(--gold-soft); }
.date-label { font: 500 1.2rem/1.2 var(--display); color: var(--ink); }
.date-day { font: 500 clamp(3.6rem, 17vw, 4.6rem)/1 var(--display); padding: 0 0.05em; }
.date-year { font: 500 1.35rem/1.2 var(--display); color: var(--ink-soft); margin-top: 0.3rem; }

.venue-name { font: italic 500 1.5rem/1.3 var(--display); color: var(--gold-deep); }
.venue-address { font-size: 0.98rem; color: var(--ink-soft); margin-top: 0.15rem; }
.event-description {
  font: italic 400 1.12rem/1.5 var(--display);
  color: var(--ink-soft);
  max-width: 23rem;
  margin: 1rem auto 0;
}

/* RSVP card — an arch-topped panel echoing the frame. */
.rsvp-card {
  position: relative;
  width: 100%;
  max-width: 24rem;
  margin: 0.25rem auto 0;
  padding: 2.4rem 1.25rem 1.6rem;
  background: rgba(255, 252, 246, 0.8);
  border: 1px solid var(--gold-soft);
  border-radius: 12rem 12rem 1.1rem 1.1rem / 4.5rem 4.5rem 1.1rem 1.1rem;
  box-shadow:
    inset 0 0 0 5px rgba(255, 252, 246, 0.9),
    inset 0 0 0 6px rgba(217, 192, 138, 0.55),
    0 18px 40px -28px rgba(134, 103, 42, 0.45);
}
.rsvp-heading { color: var(--sage); margin-bottom: 0.35rem; }
.rsvp-places { font: italic 400 1.1rem/1.4 var(--display); color: var(--ink-soft); margin-bottom: 1.25rem; }
.rsvp-choices, .rsvp-actions { display: grid; gap: 0.7rem; }

.button {
  font: 600 1.08rem/1.2 var(--display);
  letter-spacing: 0.05em;
  min-height: 48px;
  padding: 0.7rem 1.4rem;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}
.button-primary {
  color: #fffaf0;
  background: linear-gradient(180deg, #c29b4d, #9a7631);
  border-color: #86672a;
  box-shadow: 0 2px 12px -4px rgba(134, 103, 42, 0.55), inset 0 1px 0 rgba(255, 240, 200, 0.35);
}
.button-primary:hover:not(:disabled) { background: linear-gradient(180deg, #b58f42, #86672a); }
.button-secondary { color: var(--gold-deep); background: rgba(255, 252, 246, 0.6); border-color: var(--gold-soft); }
.button-secondary:hover:not(:disabled) { border-color: var(--gold); background: #fffaf0; }
.button-link {
  background: none;
  color: var(--gold-deep);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--gold-soft);
  text-underline-offset: 4px;
  min-height: 44px;
  margin-top: 0.35rem;
}
.button:disabled { opacity: 0.6; cursor: default; }
.button[aria-busy='true'] { opacity: 1; }

.stepper { margin-bottom: 1.1rem; }
.stepper-label { font: italic 400 1.12rem/1.3 var(--display); color: var(--ink); margin-bottom: 0.7rem; }
.stepper-controls { display: flex; align-items: center; justify-content: center; gap: 1.25rem; }
.stepper-button {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  background: #fffaf0;
  color: var(--gold-deep);
  font: 400 1.7rem/1 var(--display);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.stepper-button:disabled { opacity: 0.35; cursor: default; }
.stepper-value { min-width: 4.5rem; display: flex; flex-direction: column; align-items: center; }
.stepper-count { font: 500 2.7rem/1 var(--display); color: var(--gold-deep); }
.stepper-of { font: 600 0.7rem/1.4 var(--display); letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-soft); }

.seal { display: flex; flex-direction: column; align-items: center; outline: none; }
.seal-mark {
  position: relative;
  width: 3.5rem;
  height: 3.5rem;
  margin-bottom: 0.6rem;
  border-radius: 50%;
  border: 1px solid var(--gold);
  background: radial-gradient(circle, #fffaf0 55%, #f4e7cc);
  box-shadow: inset 0 0 0 4px #fffaf0, inset 0 0 0 5px var(--gold-soft);
}
.seal-mark::after { content: ''; position: absolute; left: 50%; top: 50%; }
.seal-attending .seal-mark::after {
  width: 0.62rem;
  height: 1.15rem;
  border: solid var(--gold-deep);
  border-width: 0 2px 2px 0;
  transform: translate(-50%, -62%) rotate(45deg);
}
.seal-declined .seal-mark::after {
  width: 0.55rem;
  height: 0.55rem;
  background: var(--sage);
  transform: translate(-50%, -50%) rotate(45deg);
}
.seal-title { font: italic 500 1.6rem/1.2 var(--display); color: var(--gold-deep); }
.seal-declined .seal-title { color: var(--sage); }
.seal-detail { color: var(--ink-soft); font-size: 1rem; }
.rsvp-calendar {
  display: grid;
  justify-items: center;
  gap: 0.15rem;
  margin-top: 1.1rem;
}
.rsvp-calendar .button-secondary { min-width: 12rem; }
.rsvp-calendar .button-link { font-size: 0.95rem; }

.rsvp-thanks { font: italic 500 1.08rem/1.45 var(--display); color: var(--leaf); margin-top: 0.9rem; }
.rsvp-received { font: 400 0.82rem/1.4 var(--body); color: var(--ink-soft); }
.rsvp-note, .rsvp-closed { font: italic 400 1.08rem/1.45 var(--display); color: var(--ink-soft); }
.rsvp-closed { margin-top: 0.8rem; }
.rsvp-error { margin-top: 1rem; color: var(--error); font-size: 0.95rem; line-height: 1.45; outline: none; }

/* Closing */
.closing {
  position: relative;
  display: grid;
  place-items: center;
  min-height: calc((var(--arch-bottom) - var(--header-bottom)) * 0.7);
  padding: 3rem 0 2rem;
}
.mandala {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(125%, 34rem);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  opacity: 0.2;
  pointer-events: none;
}
.mandala img { width: 100%; height: 100%; }
.closing-inner { position: relative; }
.closing-title { font: italic 500 clamp(2.3rem, 10vw, 3.1rem)/1.15 var(--display); margin-bottom: 1rem; }
.closing-body { color: var(--ink-soft); max-width: 22rem; margin: 0 auto 1.6rem; }
.closing-deadline-label { display: block; color: var(--sage); margin-bottom: 0.2rem; }
.closing-deadline-date { display: block; font: italic 500 1.45rem/1.3 var(--display); color: var(--gold-deep); }
.closing-closed { font: italic 400 1.15rem/1.45 var(--display); color: var(--ink-soft); max-width: 22rem; margin: 0 auto; }
.closing-note { font: italic 400 1.02rem/1.45 var(--display); color: var(--ink-soft); margin-top: 0.4rem; }

/* Whole-page states */
.state { padding: 1rem 0 2rem; }
.state-title { font: italic 500 clamp(2rem, 9vw, 2.8rem)/1.15 var(--display); margin-bottom: 0.5rem; }
.state-body { color: var(--ink-soft); max-width: 22rem; margin: 0 auto 1.5rem; }
.state .button { min-width: 12rem; }

noscript p { max-width: 24rem; margin: 30vh auto 0; text-align: center; font: italic 1.2rem var(--display); color: var(--ink-soft); }

@media (prefers-reduced-motion: reduce) {
  .scroll-hint-line { animation: none; }
  .button { transition: none; }
}
