/* ============================================================
   Sections — in scroll order, 01 → 10
   ============================================================ */

/* --- draft bar (delete when content is final) ---------------- */

.draftbar {
  background: var(--walnut);
  color: var(--paper);
  font-size: var(--t-xs);
  letter-spacing: var(--track-util);
  text-transform: uppercase;
  text-align: center;
  padding: 0.55rem var(--pad-r) 0.55rem var(--pad-l);
  position: relative;
  /* Below the nav (50) and the menu panel (45): the bar scrolls with
     the document, and opening the menu at page top must not leave it
     painting over either of them. */
  z-index: 10;
}

/* --- test reset (CONFIG.testMode; off before launch) --------- */

.testreset {
  position: fixed;
  left: calc(0.75rem + env(safe-area-inset-left, 0px));
  bottom: calc(0.75rem + var(--safe-b));
  /* Above the nav and menu, below the envelope (200). */
  z-index: 60;
  min-height: 44px;
  padding: 0.55rem 1rem;
  font: 400 var(--t-xs) var(--f-body);
  letter-spacing: var(--track-util);
  text-transform: uppercase;
  color: var(--paper);
  background: var(--walnut);
  border: 1px dashed var(--limewash);
  border-radius: 999px;
  box-shadow: 0 4px 14px var(--rule);
  cursor: pointer;
}

/* ============================================================
   00 — Envelope
   Shown only when the inline script has marked the page `.js` and
   this guest has not opened their envelope before (`.js-invited`).
   ============================================================ */

.envelope { display: none; }

.js .envelope {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  /* Flex + margin:auto on the stage, not place-items:center: when a
     short landscape screen can't fit it all, the top stays reachable
     by scrolling instead of being cut off. */
  overflow-y: auto;
  padding: calc(1.5rem + var(--safe-t)) var(--pad-r) calc(1.5rem + var(--safe-b)) var(--pad-l);
  background: radial-gradient(ellipse at 50% 30%, var(--forest) 0%, var(--forest-deep) 72%);
  color: var(--on-dark);
  transition: opacity 0.6s var(--ease), visibility 0s linear 0.6s;
}

.js-invited .envelope { display: none; }

.envelope__stage {
  margin: auto;
  width: min(100%, 30rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.6rem;
  text-align: center;
  transition: transform 0.6s var(--ease);
}

/* --- the envelope itself: back, card, front pocket, flap, seal -- */

.envelope__body {
  position: relative;
  width: min(100%, 24rem);
  aspect-ratio: 3 / 2;
  perspective: 1200px;
  margin-top: 1rem;
}

.envelope__body::before {           /* the inside back */
  content: "";
  position: absolute;
  inset: 0;
  background: var(--walnut-light);
  border-radius: 3px;
  box-shadow: 0 30px 60px -24px var(--forest-deep);
}

.envelope__body > * { position: absolute; }

.envelope__card {
  left: 6%;
  right: 6%;
  top: 6%;
  height: 88%;
  z-index: 1;
  display: grid;
  place-items: center;
  background: var(--surface);
  border-radius: 2px;
  transition: transform 1s var(--ease);
}

.envelope__card-names {
  font-family: var(--f-display);
  font-size: clamp(1.4rem, 6vw, 2rem);
  color: var(--ink);
}

.envelope__front {
  inset: 0;
  z-index: 2;
  background: linear-gradient(to bottom, var(--limewash-pale), var(--limewash));
  /* A pocket with a shallow V cut where the flap tucks in. */
  clip-path: polygon(0 0, 50% 52%, 100% 0, 100% 100%, 0 100%);
  border-radius: 3px;
}

.envelope__flap {
  left: 0;
  right: 0;
  top: 0;
  height: 58%;
  z-index: 3;
  background: var(--limewash);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: top;
  transition: transform 0.65s var(--ease);
}

.envelope__seal {
  left: 50%;
  top: 58%;
  translate: -50% -50%;
  z-index: 4;
  width: 3.4rem;
  height: 3.4rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--walnut);
  color: var(--limewash-pale);
  box-shadow: 0 3px 8px var(--forest-deep);
  transition: opacity 0.3s var(--ease);
}

.envelope__seal svg { width: 55%; height: 55%; }

/* --- address + controls -------------------------------------- */

.envelope__to {
  font-family: var(--f-display);
  font-size: clamp(1.9rem, 7vw, 2.6rem);
  line-height: 1.1;
  color: var(--on-dark);
  max-width: 100%;
  overflow-wrap: anywhere;
}

.envelope__to .amp { color: var(--limewash); }

.envelope__to.is-addressed {
  font-family: var(--f-script);
  font-size: clamp(2.1rem, 8vw, 2.9rem);
  color: var(--limewash);
}

.envelope__to.is-addressed.is-long { font-size: clamp(1.7rem, 6vw, 2.3rem); }

.envelope__find {
  width: 100%;
  display: grid;
  gap: 0.8rem;
}

.envelope__find label {
  font-size: var(--t-xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-dark-soft);
}

.envelope__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
}

.envelope__row input {
  flex: 1 1 14rem;
  min-width: 0;
  /* 16px or iOS zooms the page on focus. */
  font: 300 1rem var(--f-body);
  text-align: center;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 0.85rem 1.2rem;
}

.envelope__row input:focus-visible { outline: 2px solid var(--limewash); outline-offset: 2px; }

.envelope__status {
  min-height: 1.4em;
  font-size: var(--t-sm);
  color: var(--on-dark);
  text-wrap: balance;
}

.envelope__status:empty { min-height: 0; }

.envelope__hint {
  font-size: var(--t-sm);
  font-style: italic;
  color: var(--on-dark-soft);
}

.envelope__ready {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  transition: opacity 0.3s var(--ease);
}

.envelope__notme,
.rsvp__notme {
  font: inherit;
  font-size: var(--t-sm);
  background: none;
  border: 0;
  padding: 0.5rem;
  min-height: 44px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.envelope__notme { color: var(--on-dark-soft); }

/* --- opening: flap lifts, card rises, the page appears ------- */

.envelope.is-opening .envelope__flap { transform: rotateX(180deg); }
.envelope.is-opening .envelope__seal,
.envelope.is-opening .envelope__ready { opacity: 0; }
.envelope.is-rising .envelope__flap { z-index: 0; }
.envelope.is-rising .envelope__card { transform: translateY(-58%); }
.envelope.is-leaving { opacity: 0; visibility: hidden; }
.envelope.is-leaving .envelope__stage { transform: scale(1.04); }

/* Landscape phones: a 375px-tall screen can't hold a full-size
   envelope and the form. */
@media (max-height: 500px) and (orientation: landscape) {
  .envelope__stage { gap: 0.9rem; }
  .envelope__body { width: min(100%, 14rem); margin-top: 0.5rem; }
  .envelope__to { font-size: 1.7rem; }
  .envelope__to.is-addressed { font-size: 2rem; }
}

/* --- site nav ------------------------------------------------ */

.nav {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: calc(1rem + var(--safe-t)) var(--pad-r) 1rem var(--pad-l);
  background: transparent;
  color: var(--on-dark);
  transform: translateY(-100%);
  transition: transform 0.5s var(--ease), background 0.4s var(--ease),
              color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}

.nav.is-stuck {
  transform: translateY(0);
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 1px 0 var(--rule);
}

/* Must follow .nav.is-stuck — same specificity, so source order wins.
   Over the open panel the bar rides on the green, not on paper. */
.nav.is-open {
  transform: translateY(0);
  background: transparent;
  color: var(--on-dark);
  box-shadow: none;
}

.nav__mark {
  font-family: var(--f-display);
  font-size: 1.0625rem;
  letter-spacing: 0.06em;
  text-decoration: none;
  white-space: nowrap;
}

.nav__links {
  display: none;
  gap: 1.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

@media (min-width: 860px) {
  .nav__links { display: flex; }
}

.nav__links a {
  font-size: var(--t-xs);
  letter-spacing: var(--track-util);
  text-transform: uppercase;
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease);
}

.nav__links a:focus-visible { border-bottom-color: currentColor; }
@media (hover: hover) {
  .nav__links a:hover { border-bottom-color: currentColor; }
}

.nav__rsvp {
  padding: 0.6rem 1.5rem;
  min-height: 40px;
  font-size: 0.625rem;
  border-color: currentColor;
  color: inherit;
}

.nav__end {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

/* --- mobile menu -------------------------------------------- */

.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  background: none;
  border: 0;
  /* 10px type on its own is a ~22px tap target. Pad the hit area out
     to 44px without changing how it looks. */
  padding: 0.7rem 0 0.7rem 0.5rem;
  min-height: 44px;
  margin-right: -0.25rem;
  cursor: pointer;
  color: inherit;
  font-family: var(--f-body);
  font-weight: 400;
  font-size: 0.625rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

@media (min-width: 860px) {
  .nav__toggle { display: none; }
}

.nav__bars {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 17px;
}

.nav__bars i {
  display: block;
  height: 1px;
  background: currentColor;
  transition: transform 0.3s var(--ease), opacity 0.3s var(--ease);
}

.nav.is-open .nav__bars i:first-child { transform: translateY(2.5px) rotate(45deg); }
.nav.is-open .nav__bars i:last-child  { transform: translateY(-2.5px) rotate(-45deg); }

.navpanel {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: var(--forest);
  color: var(--on-dark);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--gap-lg);
  padding: 6rem var(--pad-r) calc(3rem + var(--safe-b)) var(--pad-l);
  overflow-y: auto;
}

.navpanel__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.navpanel__links a {
  display: block;
  font-family: var(--f-display);
  font-size: clamp(1.6rem, 8vw, 2.4rem);
  line-height: 1.35;
  text-decoration: none;
  color: var(--on-dark);
}

.navpanel__links a:focus-visible { color: var(--limewash); }
@media (hover: hover) {
  .navpanel__links a:hover { color: var(--limewash); }
}

.navpanel__foot {
  font-size: var(--t-xs);
  letter-spacing: var(--track-util);
  text-transform: uppercase;
  color: var(--on-dark-soft);
}

/* Short viewports — landscape phones. Seven links at full size would
   outgrow the panel, and centred flex content that overflows clips at
   the top where it cannot be scrolled back to. Shrinking to fit avoids
   the trap rather than fighting it. */
@media (max-height: 560px) {
  .navpanel {
    justify-content: flex-start;
    gap: var(--gap);
    padding: 4.5rem var(--pad-r) calc(2rem + var(--safe-b)) var(--pad-l);
  }
  .navpanel__links a { font-size: 1.25rem; line-height: 1.3; }
}

/* ============================================================
   01 — Invitation (hero)
   ============================================================ */

/* Focus lands here when the envelope opens; the hero itself is not a
   control, so no ring. */
.hero:focus { outline: none; }

.hero {
  position: relative;
  /* vh first as the fallback: svh lands ~2022, and without it an older
     browser gets min-height:auto and a collapsed hero. svh then wins
     where supported, so mobile toolbars don't crop the names. */
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--forest-deep);
  color: var(--on-dark);
  text-align: center;
  /* Fluid so a landscape phone (~390px tall) isn't spending 160px of
     its viewport on padding alone. */
  padding: clamp(3.5rem, 12vh, 6rem) var(--pad-r) clamp(2.5rem, 8vh, 4rem) var(--pad-l);
  isolation: isolate;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: hero-settle 9s var(--ease) forwards;
}

@keyframes hero-settle {
  from { transform: scale(1.07); }
  to   { transform: scale(1); }
}

.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    var(--scrim-top) 0%,
    var(--scrim-mid) 45%,
    var(--scrim-bottom) 100%
  );
}

.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
  /* Wide enough to keep the names on one line at every width —
     they stack badly around the ampersand otherwise. */
  max-width: min(100%, 44rem);
}

.hero__eyebrow {
  font-size: var(--t-xs);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
}

.hero__names {
  font-size: clamp(2.6rem, 9vw, 5.5rem);
  line-height: 0.95;
  letter-spacing: -0.015em;
  color: var(--on-dark);
}

.hero__names .amp { color: var(--limewash); }

.hero__date {
  font-size: var(--t-sm);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
}

.hero__venue {
  font-family: var(--f-script);
  font-size: 2.1rem;
  color: var(--limewash);
  line-height: 1;
}

/* Personal greeting from an invite link — script, like the venue line,
   so it reads as handwritten on the card. */
.hero__guest {
  font-family: var(--f-script);
  font-size: clamp(1.9rem, 6vw, 2.6rem);
  line-height: 1;
  color: var(--limewash);
  max-width: 100%;
  overflow-wrap: anywhere;
}

.hero__guest.is-long { font-size: clamp(1.55rem, 4.6vw, 2.2rem); }

.hero__countdown {
  font-size: var(--t-xs);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
  padding-top: 1rem;
  border-top: 1px solid var(--rule-on-dark);
}

.hero__scroll {
  position: absolute;
  bottom: calc(2rem + var(--safe-b));
  left: 50%;
  translate: -50% 0;
  width: 1px;
  height: 3.5rem;
  background: linear-gradient(
    to bottom, transparent, var(--on-dark-soft)
  );
}

/* Landscape phones: the scroll cue collides with the venue line, and a
   70px nav is a fifth of the screen. */
@media (max-height: 500px) and (orientation: landscape) {
  .hero__scroll { display: none; }
  .nav { padding-top: calc(0.5rem + var(--safe-t)); padding-bottom: 0.5rem; }
  .hero__inner { gap: 0.85rem; }
  .hero__venue { font-size: 1.7rem; }
}

/* ============================================================
   02 — The Note
   ============================================================ */

.note__grid {
  display: grid;
  gap: var(--gap-lg);
  align-items: center;
}

@media (min-width: 820px) {
  .note__grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--gap-xl);
  }
}

.note__figure { margin: 0; }

.note__figure img { aspect-ratio: 3 / 4; object-fit: cover; }

.note__figure figcaption {
  font-size: var(--t-sm);
  color: var(--muted);
  margin-top: 0.75rem;
  font-style: italic;
}

.note__body {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  align-items: flex-start;
}

.note__headline {
  font-size: clamp(1.75rem, 4.2vw, 2.6rem);
  line-height: 1.16;
  font-style: italic;
  max-width: 16ch;
}

.note__facts {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  width: 100%;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.note__fact {
  background: var(--paper);
  padding: 1rem 1.15rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.note__fact dt {
  font-size: 0.625rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
}

.note__fact dd {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.45;
}

.note__cal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}

.note__cal .label { width: 100%; }

/* Two pills side by side don't fit a 320px phone at full padding. */
.note__cal .btn { padding-inline: 1.6rem; }

/* ============================================================
   03 — Our Story
   ============================================================ */

.story__grid {
  display: grid;
  gap: var(--gap-lg);
}

@media (min-width: 900px) {
  .story__grid {
    grid-template-columns: repeat(12, 1fr);
    align-items: end;
    gap: var(--gap);
  }
  .story__fig--a { grid-column: 1 / span 5; }
  .story__fig--b { grid-column: 6 / span 3; margin-bottom: 3.5rem; }
  .story__text   { grid-column: 9 / span 4; margin-bottom: 1rem; }
}

.story__grid figure { margin: 0; }

.story__fig--a img { aspect-ratio: 4 / 5; object-fit: cover; }
.story__fig--b img { aspect-ratio: 3 / 4; object-fit: cover; }

.story__text {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  align-items: flex-start;
}

.story__text p { font-size: 0.9375rem; color: var(--ink-soft); }

/* ============================================================
   04 — The Day (schedule, forest ground)
   ============================================================ */

.schedule__head {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-xs);
  margin-bottom: var(--gap-xl);
}

.schedule__head h2 { font-size: clamp(1.9rem, 4.5vw, 2.6rem); }

.schedule__list {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: 640px;
  display: flex;
  flex-direction: column;
}

.schedule__item {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: 1.5rem;
  padding: 1.6rem 0;
  border-top: 1px solid var(--rule-on-dark);
  align-items: baseline;
}

.schedule__item:last-child { border-bottom: 1px solid var(--rule-on-dark); }

.schedule__time {
  font-size: var(--t-sm);
  letter-spacing: var(--track-util);
  font-variant-numeric: tabular-nums;
  color: var(--limewash);
  white-space: nowrap;
  /* Otherwise the grid stretches the span and a .tbd underline
     reads as a rule across the whole column. */
  justify-self: start;
}

.schedule__what h3 {
  font-size: 1.3125rem;
  font-style: italic;
  line-height: 1.25;
}

.schedule__what p {
  font-size: var(--t-sm);
  color: var(--on-dark-soft);
  margin-top: 0.3rem;
  max-width: 44ch;
}

.schedule__foot {
  display: flex;
  justify-content: center;
  margin-top: var(--gap-lg);
}

/* ============================================================
   05 — The Venue
   ============================================================ */

.venue__grid {
  display: grid;
  gap: var(--gap-lg);
}

@media (min-width: 900px) {
  .venue__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--gap-xl);
    align-items: start;
  }
}

.venue__figure { margin: 0; }

.venue__figure img {
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--limewash-pale);
}

.venue__figure figcaption {
  font-size: var(--t-sm);
  color: var(--muted);
  margin-top: 0.75rem;
  font-style: italic;
}

.venue__side {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  align-items: flex-start;
}

.venue__address {
  font-family: var(--f-display);
  font-size: 1.375rem;
  line-height: 1.4;
}

.venue__notes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 100%;
}

.venue__notes li {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule-soft);
  font-size: 0.9375rem;
  color: var(--ink-soft);
  line-height: 1.6;
}

.venue__notes strong {
  font-weight: 400;
  color: var(--ink);
  font-size: var(--t-xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

.venue__go {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* Two or three pills must share a 320px row. */
.venue__go .btn { padding-inline: 1.5rem; }

.venue__map {
  margin-top: var(--gap-lg);
  aspect-ratio: 4 / 3;
  max-width: 100%;
  border: 1px solid var(--rule);
  background: var(--limewash-pale);
}

@media (min-width: 700px) {
  .venue__map { aspect-ratio: 16 / 7; }
}

.venue__map iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Until a guest asks for it: grid paper with a pin, not a grey box. */
.venue__map-load {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font: inherit;
  color: var(--ink);
  border: 0;
  cursor: pointer;
  background:
    radial-gradient(circle at 50% 46%, var(--limewash-pale) 0 5.5rem, transparent 5.6rem),
    repeating-linear-gradient(0deg, var(--rule-soft) 0 1px, transparent 1px 32px),
    repeating-linear-gradient(90deg, var(--rule-soft) 0 1px, transparent 1px 32px),
    var(--limewash-pale);
}

.venue__map-cta {
  font-family: var(--f-display);
  font-size: 1.5rem;
  font-style: italic;
  border-bottom: 1px solid currentColor;
}

.venue__map-note { font-size: var(--t-sm); color: var(--muted); }

@media (hover: hover) {
  .venue__map-load:hover .venue__map-cta { color: var(--walnut); }
}

/* ============================================================
   06 — The Entourage
   ============================================================ */

/* Six groups. Column counts are fixed to divisors of six so no row
   is ever left half-empty. */
.entourage__cols {
  display: grid;
  gap: var(--gap-lg) var(--gap);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 560px) {
  .entourage__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .entourage__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.entourage__group {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  border-top: 1px solid var(--rule);
  padding-top: 1.1rem;
}

.entourage__group h3 {
  font-family: var(--f-body);
  font-weight: 400;
  font-size: var(--t-xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--moss);
}

.entourage__group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.entourage__group li {
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* ============================================================
   07 — What to Wear
   ============================================================ */

.dress__grid {
  display: grid;
  gap: var(--gap-lg);
}

@media (min-width: 860px) {
  .dress__grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
    gap: var(--gap-xl);
    align-items: start;
  }
}

.dress__copy {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  align-items: flex-start;
}

.dress__copy p { font-size: 0.9375rem; color: var(--ink-soft); max-width: 34ch; }

/* Five materials, always on one line — the palette reads as a strip,
   and auto-fit would orphan the fifth chip onto its own row. */
.dress__swatches {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.5rem;
}

@media (min-width: 560px) {
  .dress__swatches { gap: 0.75rem; }
}

.swatch {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--rule);
}

.swatch__chip {
  aspect-ratio: 4 / 5;
  border-bottom: 1px solid var(--rule);
}

/* Five chips share the row, so each is ~48px wide on a 320px phone.
   "LIMEWASH" is a single unbreakable word — size and tracking have to
   scale with the viewport or it gets clipped. */
.swatch__name {
  padding: 0.6rem 0.3rem 0.65rem;
  font-size: clamp(0.5rem, 2.2vw, 0.625rem);
  letter-spacing: clamp(0.01em, 0.35vw, 0.08em);
  text-align: center;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.4;
  background: var(--surface);
}

.dress__note {
  font-size: var(--t-sm);
  color: var(--muted);
  font-style: italic;
  margin-top: 1.25rem;
  max-width: 48ch;
}

/* ============================================================
   08 — RSVP
   ============================================================ */

.rsvp {
  background: var(--limewash-pale);
}

.rsvp__grid {
  display: grid;
  gap: var(--gap-lg);
}

@media (min-width: 900px) {
  .rsvp__grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
    gap: var(--gap-xl);
    align-items: start;
  }
}

.rsvp__intro {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
}

.rsvp__intro p { font-size: 0.9375rem; color: var(--ink-soft); max-width: 34ch; }

.rsvp__held {
  font-family: var(--f-display);
  font-size: 1.25rem;
  color: var(--forest);
}

.rsvp__notme {
  justify-self: start;
  align-self: flex-start;
  margin-top: -0.75rem;
  padding-inline: 0;
  color: var(--muted);
}

.rsvp__deadline {
  font-family: var(--f-display);
  font-size: 1.25rem;
  font-style: italic;
  color: var(--walnut);
}

.form {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.field--wide { grid-column: 1 / -1; }

.field label {
  font-size: 0.625rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--muted);
}

.field input,
.field select,
.field textarea {
  font-family: var(--f-body);
  font-weight: 300;
  /* Must be at least 16px. Below that, iOS Safari zooms the whole page
     in when a field is focused and leaves it there — the single most
     common mobile form complaint, and it hits the RSVP form directly. */
  font-size: 1rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 0;
  padding: 0.8rem 0.9rem;
  width: 100%;
  transition: border-color 0.3s var(--ease);
}

.field textarea { resize: vertical; min-height: 5.5rem; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--moss);
  outline: none;
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--moss);
  outline-offset: 1px;
}

.form__actions {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-sm);
}

.form__status {
  font-size: var(--t-sm);
  color: var(--muted);
  min-height: 1.4em;
}

.form__status[data-state="ok"]   { color: var(--forest); }
.form__status[data-state="err"]  { color: var(--walnut); }

/* ============================================================
   09 — Useful Info
   ============================================================ */

.faq {
  max-width: var(--page-narrow);
  margin-inline: auto;
  border-top: 1px solid var(--rule);
}

.faq details {
  border-bottom: 1px solid var(--rule-soft);
}

.faq summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap-sm);
  padding: 1.35rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--f-display);
  font-size: 1.1875rem;
  line-height: 1.35;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "+";
  font-family: var(--f-body);
  font-weight: 300;
  font-size: 1.25rem;
  color: var(--moss);
  flex: none;
  transition: transform 0.3s var(--ease);
}

.faq details[open] summary::after {
  transform: rotate(45deg);
}

.faq__answer {
  padding: 0 0 1.5rem;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  max-width: 58ch;
  line-height: 1.7;
}

/* ============================================================
   10 — After / footer
   ============================================================ */

.after {
  background: var(--forest);
  color: var(--on-dark);
  text-align: center;
}

.after__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-sm);
}

.after__script {
  font-family: var(--f-script);
  font-size: clamp(2.5rem, 7vw, 4rem);
  color: var(--limewash);
  line-height: 1;
}

.after__note {
  font-size: 0.9375rem;
  color: var(--on-dark-soft);
  max-width: 44ch;
}

.footer {
  background: var(--forest-deep);
  color: var(--on-dark-soft);
  padding-block: 2.5rem;
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm) var(--gap);
  font-size: var(--t-xs);
  letter-spacing: var(--track-util);
  text-transform: uppercase;
}

.footer__mark {
  width: 22px;
  height: auto;
  color: var(--limewash);
  flex: none;
}

/* --- the anthurium mark -------------------------------------- */

.anthurium {
  width: 42px;
  height: auto;
  color: var(--moss);
  flex: none;
}

.anthurium--on-dark { color: var(--limewash); }

/* --- placeholder image block --------------------------------- */

.ph {
  display: grid;
  place-items: center;
  background:
    repeating-linear-gradient(
      45deg,
      var(--limewash-pale) 0 12px,
      var(--limewash) 12px 24px
    );
  color: var(--muted);
  font-size: var(--t-xs);
  letter-spacing: var(--track-util);
  text-transform: uppercase;
  text-align: center;
  padding: 1rem;
}

.ph--3x4 { aspect-ratio: 3 / 4; }
.ph--4x5 { aspect-ratio: 4 / 5; }

/* ============================================================
   Colophon — the last bar on the page
   ============================================================ */

.colophon {
  background: var(--paper-2);
  border-top: 1px solid var(--rule-soft);
  /* Last thing on the page, so it's what sits behind the iPhone home
     indicator. Extra bottom padding keeps the credit above it. */
  padding: 0.4rem 0 calc(0.4rem + var(--safe-b));
}

.colophon__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
}

.colophon__label,
.colophon__name {
  font-family: var(--f-body);
  font-weight: 400;
  font-size: 0.5625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  color: var(--muted);
}

.colophon__name { color: var(--ink); }

/* The mark is the tallest thing in the bar, so it sets the bar's
   height. Keep it just above the cap-height of the labels. */
.colophon__mark {
  width: auto;
  height: 13px;
  display: block;
}
