/* ============================================================================
 *  Nicole Naledi Ng'ang'a — Graduation Invitation
 *  Design system: deep emerald + antique gold on ivory, botanical accents.
 *  No external image dependencies; every texture is generated in CSS/SVG so
 *  the page works offline and loads instantly.
 * ==========================================================================*/

/* --------------------------------------------------------------------------
 *  1. Tokens
 * ------------------------------------------------------------------------*/
:root {
  /* Emerald */
  --emerald-950: #041A13;
  --emerald-900: #07271D;
  --emerald-800: #0B3527;
  --emerald-700: #104733;
  --emerald-600: #165C43;
  --emerald-500: #1D7154;
  --emerald-100: #DCEAE2;

  /* Gold */
  --gold-600: #A8841B;
  --gold-500: #C9A227;
  --gold-400: #D9BA52;
  --gold-300: #E7CF86;
  --gold-200: #F2E3B4;
  --champagne: #F7EDD2;

  /* Neutrals */
  --ivory: #FCFAF4;
  --cream: #F4EDDF;
  --paper: #FBF7EF;
  --sage: #93A98F;
  --ink: #17211C;
  --ink-soft: #45514B;
  --ink-faint: #6C7A73;

  /* Type */
  --font-script: "Allura", "Great Vibes", "Segoe Script", "Brush Script MT", cursive;
  --font-serif: "EB Garamond", "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --font-sans: "Jost", "Helvetica Neue", Arial, sans-serif;

  /* Space & shape */
  --radius-card: 20px;
  --shadow-soft: 0 18px 50px -24px rgba(4, 26, 19, 0.45);
  --shadow-lift: 0 28px 70px -30px rgba(4, 26, 19, 0.55);
  --ring: 0 0 0 3px rgba(201, 162, 39, 0.35);

  --wrap: 1140px;
  --wrap-narrow: 860px;

  /* Generated textures */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
 *  2. Reset & base
 * ------------------------------------------------------------------------*/
*,
*::before,
*::after { box-sizing: border-box; }

/* The hidden attribute must always win. Several components set an explicit
   display (flex, grid), and that beats the browser's own [hidden] rule — so a
   "hidden" element stayed on screen until each one was patched individually. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-serif);
  font-size: clamp(1.02rem, 0.55vw + 0.92rem, 1.16rem);
  line-height: 1.7;
  color: var(--ink);
  background: var(--paper);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img, svg { max-width: 100%; display: block; }
a { color: var(--emerald-600); }

h1, h2, h3 {
  font-family: var(--font-serif);
  font-weight: 500;
  line-height: 1.15;
  margin: 0;
  letter-spacing: 0.01em;
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

:focus-visible {
  outline: 2px solid var(--gold-500);
  outline-offset: 3px;
  border-radius: 4px;
}

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

.skip-link {
  position: absolute;
  left: 50%; top: -100px;
  transform: translateX(-50%);
  z-index: 100;
  background: var(--gold-500);
  color: var(--emerald-950);
  padding: 0.7rem 1.4rem;
  border-radius: 0 0 10px 10px;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  transition: top 0.2s ease;
}
.skip-link:focus { top: 0; }

/* --------------------------------------------------------------------------
 *  3. Layout helpers
 * ------------------------------------------------------------------------*/
.wrap {
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}
/* Used standalone (not as `wrap wrap--narrow`), so it needs its own centring. */
.wrap--narrow {
  width: min(100% - 2.5rem, var(--wrap-narrow));
  margin-inline: auto;
}

.section { position: relative; padding: clamp(3.5rem, 8vw, 7rem) 0; }

.section--ivory { background: var(--ivory); }
.section--cream { background: var(--cream); }

/* Marble-ish veining for the light sections */
.texture-marble { position: relative; }
.texture-marble::before {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image:
    linear-gradient(112deg, transparent 42%, rgba(147, 169, 143, 0.18) 44%, transparent 46%),
    linear-gradient(96deg, transparent 66%, rgba(201, 162, 39, 0.12) 68%, transparent 71%),
    linear-gradient(154deg, transparent 22%, rgba(147, 169, 143, 0.12) 25%, transparent 28%),
    radial-gradient(120% 80% at 12% 8%, rgba(255, 255, 255, 0.42), transparent 62%);
}

/* --------------------------------------------------------------------------
 *  4. Typographic ornaments
 * ------------------------------------------------------------------------*/
.eyebrow {
  font-family: var(--font-sans);
  font-size: clamp(0.76rem, 0.4vw + 0.68rem, 0.9rem);
  font-weight: 400;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--gold-600);
  margin: 0;
}
.eyebrow--light { color: var(--gold-300); }

.script {
  font-family: var(--font-script);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: 0.02em;
}

/* Slim gold rule with a centred lozenge */
.rule {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.85rem;
  margin: 1rem auto 0.9rem;
  width: min(100%, 300px);
}
.rule::before,
.rule::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, currentColor 55%, currentColor);
  opacity: 0.55;
}
.rule::after { background: linear-gradient(270deg, transparent, currentColor 55%, currentColor); }
.rule__gem {
  width: 7px; height: 7px;
  transform: rotate(45deg);
  background: currentColor;
  opacity: 0.85;
  flex: none;
}
.rule--gold { color: var(--gold-500); }
.rule--light { color: var(--gold-300); }

/* Botanical divider sprig */
.sprig {
  width: min(240px, 62%);
  margin: 1.5rem auto;
  background: url("../img/sprig.svg") center / contain no-repeat;
  height: 44px;
  opacity: 0.9;
}

/* --------------------------------------------------------------------------
 *  5. Portrait — a tall figure that dissolves into the invitation
 *  She is a transparent cut-out running from the knees up. A vertical mask
 *  keeps her solid at the top and fades her out towards the bottom, and the
 *  welcome text is pulled up over that faded tail so she emerges from behind
 *  the words rather than sitting above them.
 *
 *  --portrait-w drives both her size and how far the text overlaps: the
 *  overlap is a fixed fraction of her width, so it scales at every size.
 * ------------------------------------------------------------------------*/
.hero__inner { --portrait-w: clamp(250px, 56vw, 310px); }

.portrait-wrap {
  position: relative;
  z-index: 1;
  width: var(--portrait-w);
  margin: 0 auto;
}

/* The veil: page-coloured, heaviest where the words sit and easing away as it
   rises, so her face and shoulders stay clear while the text stays legible.
   It runs wider than the photograph and is feathered left and right — confined
   to the image width its side edges showed as hard vertical lines. */
/* Her graduation cap: beside her and clear of her silhouette, but held right
   back — no movement, and faint enough to read as an impression in the paper
   rather than an object in the scene. */
.portrait__cap {
  position: absolute;
  top: 30%;
  /* Anchored to the portrait's left edge rather than offset from it by a
     percentage. right:100% pins the cap's right edge to her edge, and the
     margin is then a real gap in pixels — the same clearance at every width,
     instead of one that shrinks as the screen narrows. */
  right: 100%;
  margin-right: 10px;
  z-index: 1;
  width: clamp(92px, 20vw, 132px);
  height: auto;
  color: var(--gold-600);
  opacity: 0.18;
  pointer-events: none;
  transform: rotate(-13deg);
}

/* Phones have less room beside her, so the cap is nudged left of her edge
   rather than pinned outside it. It stays a proper size — the subtlety is the
   opacity, not the scale — and keeps clear of her body. */
@media (max-width: 620px) {
  .portrait__cap {
    right: auto;
    left: -16%;
    width: clamp(76px, 23vw, 110px);
  }
}

.portrait-wrap::after {
  content: "";
  position: absolute;
  left: -20%;
  right: -20%;
  top: 0;
  bottom: 0;
  z-index: 0; /* above the photograph, below the words */
  pointer-events: none;
  /* The ramp starts higher and builds sooner, because the invite line sits at
     66-82% of her image and the name just below it. The top fifth stays clear
     so her head and shoulders still read through. */
  background: linear-gradient(to bottom,
    rgba(251, 247, 238, 0) 22%,
    rgba(251, 247, 238, 0.07) 32%,
    rgba(251, 247, 238, 0.20) 42%,
    rgba(251, 247, 238, 0.38) 52%,
    rgba(251, 247, 238, 0.58) 63%,
    rgba(251, 247, 238, 0.78) 75%,
    rgba(251, 247, 238, 0.90) 88%,
    rgba(251, 247, 238, 0.96) 100%);
  -webkit-mask-image: linear-gradient(to right,
    transparent 0%, #000 26%, #000 74%, transparent 100%);
  mask-image: linear-gradient(to right,
    transparent 0%, #000 26%, #000 74%, transparent 100%);
}

.portrait__img {
  width: 100%;
  height: auto;
  display: block;
  /* Solid through the figure, dissolving through the skirt. */
  -webkit-mask-image: linear-gradient(to bottom,
    #000 0%, #000 88%, rgba(0, 0, 0, 0.45) 95%, transparent 100%);
  mask-image: linear-gradient(to bottom,
    #000 0%, #000 88%, rgba(0, 0, 0, 0.45) 95%, transparent 100%);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  /* Her outstretched arm pulls the cut-out's bounding box to the right, which
     leaves her head and body sitting ~12% left of centre. Shift the image so
     her body reads centred; the arm simply extends further right. */
  transform: translateX(12%);
}

/* Pulled up so the opening text sits in her faded tail. */
.hero__text {
  position: relative;
  z-index: 2;
  margin-top: calc(var(--portrait-w) * -0.51);
}


/* --------------------------------------------------------------------------
 *  6. Hero
 * ------------------------------------------------------------------------*/
.hero {
  position: relative;
  isolation: isolate;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: clamp(1.6rem, 4vh, 2.4rem) 0 clamp(2.4rem, 5vh, 3.2rem);
  /* Starts clearly warmer than the Details section and resolves into its exact
     ivory (#FCFAF4) at the bottom, so the two sections meet with no seam. */
  background:
    radial-gradient(120% 62% at 50% 4%, rgba(231, 207, 134, 0.26), transparent 64%),
    linear-gradient(180deg, #F8F1E4 0%, #FBF6EC 46%, var(--ivory) 100%);
  overflow: hidden;
}
/* Soft emerald halo behind the portrait and a warm gold glow through the
   middle. Deliberately nothing at the very bottom: a glow there tinted the
   last few pixels and stopped the hero meeting the Details section cleanly. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(34% 24% at 50% 22%, rgba(16, 71, 51, 0.10), transparent 72%),
    radial-gradient(58% 38% at 50% 44%, rgba(231, 207, 134, 0.16), transparent 70%);
  pointer-events: none;
}

.hero__corners { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.hero__corner {
  position: absolute;
  width: clamp(150px, 26vw, 330px);
  aspect-ratio: 1;
  /* The light-background variant, since the hero is no longer dark. */
  background: url("../img/floral-corner-soft.svg") top left / contain no-repeat;
  opacity: 0.7;
}
.hero__corner--tl { top: 0; left: 0; }
.hero__corner--tr { top: 0; right: 0; transform: scaleX(-1); }
.hero__corner--bl { bottom: 0; left: 0; transform: scaleY(-1); opacity: 0.45; }
.hero__corner--br { bottom: 0; right: 0; transform: scale(-1, -1); opacity: 0.45; }

/* Gold glitter confetti. It used to sit in the corners of the invitation card;
   with the card gone it decorates the hero corners directly. */
.hero__sparkle {
  position: absolute;
  width: clamp(104px, 23vw, 200px);
  aspect-ratio: 1;
  background: url("../img/sparkle-corner.svg") top left / contain no-repeat;
  opacity: 0.72;
}
.hero__sparkle--tl { top: 0; left: 0; }
.hero__sparkle--tr { top: 0; right: 0; transform: scaleX(-1); }
.hero__sparkle--bl { bottom: 0; left: 0; transform: scaleY(-1); }
.hero__sparkle--br { bottom: 0; right: 0; transform: scale(-1, -1); }
@media (max-width: 700px) {
  .hero__corner { width: 140px; opacity: 0.5; }
  .hero__sparkle { width: 120px; opacity: 0.6; }
  /* Drop the top sprays clear of the monogram and nav on small screens. */
  .hero__corner--tl, .hero__corner--tr { top: 2.75rem; }
  .hero__corner--bl, .hero__corner--br { display: none; }
}

.hero__inner {
  position: relative;
  z-index: 2;
  width: min(100% - 2rem, 620px);
  text-align: center;
}

.hero__invite {
  /* Script now, not small caps: the two lines that frame her name are set in
     the hand, and the name itself is set in capitals. */
  font-family: var(--font-script);
  /* Allura runs small for its size, so this is larger than the Great Vibes
     value it replaced — matching apparent weight, not the number. */
  font-size: clamp(1.62rem, 3.05vw, 2.28rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.2;
  text-transform: none;
  text-wrap: balance;
  /* Matches the message below, so the two script lines read as one voice
     framing the name. */
  color: var(--ink-soft);
  max-width: 33rem;
  margin: 0 auto 1.05rem;
}

/* Sits directly under her name, quieter than it but still part of the title
   block rather than the logistics below. */
.hero__class {
  margin: 0 0 1.15rem;
  font-family: var(--font-sans);
  font-size: clamp(0.72rem, 1.05vw, 0.84rem);
  font-weight: 400;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--gold-600);
}

/* Her name carries the invitation, so it is set in capitals with wide
   tracking — the counterweight to the script above and below it. */
.hero__name {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(1.5rem, 4vw, 2.3rem);
  line-height: 1.24;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-wrap: balance;
  /* Flat gold is the fallback; the gradient below replaces it wherever
     background-clip: text is supported. Never leave this transparent without
     the clip, or the name would vanish. */
  color: var(--gold-600);
  margin: 0 0 1rem;
}

/* Gold leaf rather than a flat fill: the sweep runs light-dark-light across
   the capitals so they catch light the way the metal does elsewhere. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero__name {
    background-image: linear-gradient(168deg,
      #F2E4AC 0%,
      #DCC068 24%,
      #C09A25 54%,
      #9E7C13 84%,
      #8A6C14 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}

/* The invitation message. Slightly larger and airier than the logistics. */
.hero__message {
  font-family: var(--font-script);
  font-size: clamp(1.36rem, 2.45vw, 1.86rem);
  line-height: 1.28;
  text-wrap: balance;
  color: var(--ink-soft);
  /* Full column: at 27rem Allura broke this to three lines, which made the
     hero taller than the screen and pushed the RSVP button off it. */
  max-width: 39rem;
  margin: 0 auto;
}

/* On narrow phones her name is the focal point, so it runs wider than the text column — out
     towards the edges of the screen — rather than shrinking to fit.
     Measured: the name is 8.485px wide per 1px of font-size. 10vw leaves a
     clear margin at the screen edges while staying much larger than a
     one-line-fit-at-any-cost size would allow. */
@media (max-width: 430px) {
  .hero__name {
    font-size: 10vw;
    margin-left: -0.9rem;
    margin-right: -0.9rem;
  }

  /* A single button now, so it keeps its natural width and stays centred —
     it should not stretch the full width of the screen. */
  .hero__actions { flex-wrap: nowrap; }
}

/* Countdown */
.countdown {
  display: flex;
  justify-content: center;
  gap: clamp(0.4rem, 1.6vw, 0.9rem);
  margin-top: 0.65rem;
}
.countdown__unit {
  min-width: clamp(54px, 15vw, 68px);
  padding: 0.5rem 0.35rem;
  border: 1px solid rgba(201, 162, 39, 0.45);
  border-radius: 12px;
  background: #FFFFFF;
  box-shadow: 0 6px 16px -12px rgba(4, 26, 19, 0.5);
}
.countdown__num {
  display: block;
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 4.2vw, 2rem);
  font-weight: 600;
  color: var(--emerald-800);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.countdown__label {
  display: block;
  font-family: var(--font-sans);
  font-size: clamp(0.68rem, 0.95vw, 0.78rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem;
  margin-top: 1.7rem;
  margin-bottom: 1rem;
}

/* The hero's single call to action: a gilded pill with an engraved inner
   hairline and a soft outer lift, so it reads as a piece of jewellery rather
   than a flat button. */
.hero__actions .btn,
.details__actions .btn {
  padding: 1.15rem 3.1rem;
  font-size: 0.85rem;
  letter-spacing: 0.24em;
  background: linear-gradient(165deg, #EBCF80 0%, #DBBC55 45%, #C29C22 100%);
  color: #241A08;
  box-shadow:
    inset 0 0 0 1px rgba(255, 252, 240, 0.42),
    inset 0 1px 0 rgba(255, 255, 255, 0.75),
    0 0 0 1px rgba(168, 132, 27, 0.55),
    0 16px 32px -16px rgba(4, 26, 19, 0.65);
}
.hero__actions .btn:hover,
.details__actions .btn:hover {
  background: linear-gradient(165deg, #F2DE9E 0%, #E4C766 45%, #CFA92A 100%);
  transform: translateY(-3px);
  box-shadow:
    inset 0 0 0 1px rgba(255, 252, 240, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    0 0 0 1px rgba(168, 132, 27, 0.62),
    0 22px 42px -18px rgba(4, 26, 19, 0.72);
}


/* --------------------------------------------------------------------------
 *  8. Buttons
 * ------------------------------------------------------------------------*/
.btn {
  --btn-bg: var(--gold-500);
  --btn-fg: var(--emerald-950);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.95rem 2rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 0.84rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  background: var(--btn-bg);
  color: var(--btn-fg);
  transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease, color 0.18s ease;
  box-shadow: 0 10px 26px -14px rgba(4, 26, 19, 0.6);
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 16px 34px -16px rgba(4, 26, 19, 0.7); }
.btn:active { transform: translateY(0); }

.btn--gold { background: linear-gradient(135deg, var(--gold-400), var(--gold-500)); color: #23180A; }
.btn--gold:hover { background: linear-gradient(135deg, var(--gold-300), var(--gold-400)); }

.btn--outline {
  background: transparent;
  border-color: rgba(201, 162, 39, 0.65);
  color: var(--emerald-800);
}
.btn--outline:hover { background: rgba(201, 162, 39, 0.12); }

.btn--outline-light {
  background: rgba(4, 26, 19, 0.25);
  border-color: rgba(217, 186, 82, 0.6);
  color: var(--gold-200);
}
.btn--outline-light:hover { background: rgba(217, 186, 82, 0.16); color: var(--gold-200); }

.btn--wide { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; transform: none; }

/* --------------------------------------------------------------------------
 *  9. Section headings
 * ------------------------------------------------------------------------*/
.section__head { text-align: center; margin-bottom: clamp(2rem, 5vw, 3.25rem); }
.section__title {
  font-size: clamp(1.9rem, 4.6vw, 2.9rem);
  color: var(--emerald-900);
}
.section__title .script { color: var(--gold-600); font-size: 1.15em; }
.section__lead {
  max-width: 56ch;
  margin: 0.9rem auto 0;
  color: var(--ink-soft);
  font-size: clamp(1.1rem, 1.2vw, 1.24rem);
}

/* --------------------------------------------------------------------------
 * 10. Detail cards
 * ------------------------------------------------------------------------*/
.details-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: clamp(1rem, 2.4vw, 1.6rem);
}
.detail {
  position: relative;
  padding: 2rem 1.5rem 1.75rem;
  background: var(--paper);
  border: 1px solid rgba(201, 162, 39, 0.28);
  border-radius: 16px;
  text-align: center;
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.detail::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 46px; height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold-500), transparent);
}
.detail:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-soft);
  border-color: rgba(201, 162, 39, 0.55);
}
.detail__icon {
  width: 34px; height: 34px;
  margin: 0 auto 0.9rem;
  color: var(--gold-600);
}
.detail__label {
  font-family: var(--font-sans);
  font-size: 0.74rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 0.5rem;
}
.detail__value {
  font-size: 1.28rem;
  /* Stops a single word (the year) being orphaned onto its own line now that
     the type is larger. */
  text-wrap: balance;
  font-weight: 600;
  color: var(--emerald-800);
  margin: 0;
  line-height: 1.35;
}
.detail__sub {
  margin: 0.3rem 0 0;
  font-size: 1.02rem;
  color: var(--ink-soft);
  font-style: italic;
}
.detail a { color: var(--emerald-600); text-decoration-color: rgba(201, 162, 39, 0.6); }

/* Labelled rows inside a detail card — used by the dress code. */
.detail__rows { display: grid; gap: 0.6rem; }
.detail__row { margin: 0; }
.detail__row b {
  display: block;
  margin-bottom: 0.15rem;
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-600);
}
.detail__row span {
  display: block;
  font-size: 1.14rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--emerald-800);
}

/* --------------------------------------------------------------------------
 * 11. RSVP form
 * ------------------------------------------------------------------------*/
.rsvp { position: relative; overflow: hidden; }

.rsvp__card {
  background: var(--ivory);
  border-radius: var(--radius-card);
  border: 1px solid rgba(201, 162, 39, 0.35);
  box-shadow: var(--shadow-lift);
  padding: clamp(1.5rem, 4.5vw, 3.25rem);
  position: relative;
}
/* engraved inner gold frame */
.rsvp__card::before {
  content: "";
  position: absolute;
  inset: 9px;
  border: 1px solid rgba(201, 162, 39, 0.32);
  border-radius: calc(var(--radius-card) - 6px);
  pointer-events: none;
}

/* Faint glassware across the whole section, behind the card rather than
   trapped inside the form. */
.rsvp::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.2;
  background-image: url("../img/bar-motifs.svg");
  background-size: 340px 340px;
  background-repeat: repeat;
  background-position: center;
}

.rsvp__corners { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
/* Keep the RSVP card above the backdrop. */
.rsvp > .wrap--narrow { position: relative; z-index: 2; }
.rsvp__corner {
  position: absolute;
  width: clamp(120px, 20vw, 240px);
  aspect-ratio: 1;
  background: url("../img/floral-corner-soft.svg") top left / contain no-repeat;
  opacity: 0.35;
}
.rsvp__corner--tl { top: 0; left: 0; }
.rsvp__corner--tr { top: 0; right: 0; transform: scaleX(-1); }
.rsvp__corner--bl { bottom: 0; left: 0; transform: scaleY(-1); }
.rsvp__corner--br { bottom: 0; right: 0; transform: scale(-1, -1); }
@media (max-width: 780px) { .rsvp__corner { display: none; } }

.fieldset {
  position: relative;
  z-index: 1;
  border: 0;
  margin: 0 0 2rem;
  padding: 0;
}
.fieldset:last-of-type { margin-bottom: 1.25rem; }

/* Sections below the attendance question, before the guest has answered:
   visible so they know what is coming, but greyed and unclickable. */
.is-gated {
  opacity: 0.4;
  pointer-events: none;
  user-select: none;
  transition: opacity 0.3s ease;
}

.fieldset__legend {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
  padding: 0 0 0.9rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid rgba(201, 162, 39, 0.32);
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--emerald-700);
}
.fieldset__num {
  flex: none;
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--emerald-800);
  color: var(--gold-200);
  font-size: 0.76rem;
  letter-spacing: 0;
}
.fieldset__optional {
  margin-left: auto;
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  color: var(--ink-faint);
  text-transform: none;
  font-style: italic;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.1rem 1.25rem;
}

.field { margin-bottom: 1.25rem; }
.field:last-child { margin-bottom: 0; }

.field__label {
  display: block;
  margin-bottom: 0.45rem;
  font-family: var(--font-sans);
  font-size: 0.84rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--emerald-800);
}
.field__req { color: var(--gold-600); margin-left: 0.2rem; }
.field__hint {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.93rem;
  font-style: italic;
  color: var(--ink-faint);
  letter-spacing: 0;
  text-transform: none;
  font-family: var(--font-serif);
}

.input,
.select,
.textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  font-family: var(--font-serif);
  font-size: 1.12rem;
  color: var(--ink);
  background: #FFFFFF;
  border: 1px solid rgba(23, 33, 28, 0.18);
  border-radius: 10px;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
  appearance: none;
}
.textarea { min-height: 112px; resize: vertical; line-height: 1.6; }

.input::placeholder, .textarea::placeholder { color: #9AA6A0; font-style: italic; }

.input:hover, .select:hover, .textarea:hover { border-color: rgba(201, 162, 39, 0.55); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--gold-500);
  box-shadow: var(--ring);
  background: #FFFFFF;
}

.select {
  padding-right: 2.9rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23C9A227' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1.05rem center;
  cursor: pointer;
}
.select:disabled, .input:disabled, .textarea:disabled {
  background: #F1EFE9;
  color: var(--ink-faint);
  cursor: not-allowed;
  border-color: rgba(23, 33, 28, 0.1);
}
.select optgroup {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--emerald-700);
  background: var(--cream);
}
/* Options inside a group are indented by the browser already; keep them
   optically comfortable under the emerald group heading. */
.select optgroup option { padding-left: 1.1rem; }
.select option {
  font-family: var(--font-serif);
  font-size: 1.04rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  background: #FFFFFF;
  /* Roomy rows: browsers that honour padding give a tidier list. */
  padding: 0.45rem 0.8rem;
  line-height: 1.5;
}
.select option:checked {
  background: var(--champagne) linear-gradient(0deg, var(--champagne), var(--champagne));
  color: var(--emerald-900);
  font-weight: 600;
}

/* Inline validation */
.field__error {
  display: none;
  margin-top: 0.4rem;
  font-family: var(--font-sans);
  font-size: 0.86rem;
  letter-spacing: 0.02em;
  color: #A3311F;
}
.field.is-invalid .field__error { display: block; }
.field.is-invalid .input,
.field.is-invalid .select,
.field.is-invalid .textarea,
.field.is-invalid .choice { border-color: #C2482F; }
.field.is-invalid .input:focus,
.field.is-invalid .select:focus,
.field.is-invalid .textarea:focus {
  box-shadow: 0 0 0 3px rgba(194, 72, 47, 0.28);
}

/* Attendance radio cards */
.choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 0.85rem; }

.choice {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 1.05rem 1.15rem;
  background: #FFFFFF;
  border: 1px solid rgba(23, 33, 28, 0.16);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.choice:hover { border-color: rgba(201, 162, 39, 0.7); transform: translateY(-2px); }
.choice input {
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
}
.choice__box {
  flex: none;
  width: 20px; height: 20px;
  margin-top: 0.15rem;
  border: 1.5px solid rgba(23, 33, 28, 0.34);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: border-color 0.18s ease, background 0.18s ease;
}
.choice__box::after {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--gold-500);
  transform: scale(0);
  transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.choice__body { display: grid; gap: 0.12rem; }
.choice__title {
  font-family: var(--font-serif);
  font-size: 1.18rem;
  font-weight: 600;
  color: var(--emerald-800);
  line-height: 1.3;
}
.choice__desc { font-size: 0.95rem; color: var(--ink-soft); font-style: italic; line-height: 1.45; }

.choice:has(input:checked) {
  border-color: var(--gold-500);
  background: linear-gradient(180deg, #FFFDF7, var(--champagne));
  box-shadow: 0 0 0 1px var(--gold-500), 0 12px 28px -18px rgba(4, 26, 19, 0.5);
}
.choice:has(input:checked) .choice__box { border-color: var(--gold-600); }
.choice:has(input:checked) .choice__box::after { transform: scale(1); }
.choice:has(input:focus-visible) { box-shadow: var(--ring); }

/* ---- Signature mocktails & cocktails ---- */


/* ---- Drink picker ---- */
.drinks {
  position: relative;
  z-index: 1;
  margin-top: 0.35rem;
  padding: clamp(1.1rem, 3vw, 1.6rem);
  /* Plain white, matching the other form surfaces. */
  background-color: #FFFFFF;
  border: 1px solid rgba(201, 162, 39, 0.32);
  border-radius: 14px;
}
.drinks__title {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--emerald-700);
  /* The intro line used to provide this gap; without it the title sat right
     on top of "First choice". */
  margin: 0 0 1.05rem;
}
/* Quiet text rather than a floating pill — it was reading as a button. */
.drinks__count {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  transition: color 0.2s ease;
}
.drinks__count[data-full="true"] { color: var(--gold-600); font-weight: 500; }

/* Progress and selection share one ruled footer. */
.drinks__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1.25rem;
  margin-top: 1.15rem;
  padding-top: 0.85rem;
  border-top: 1px dashed rgba(201, 162, 39, 0.45);
}
.drink-row { display: grid; gap: 0.4rem; margin-bottom: 0.95rem; }
.drink-row:last-of-type { margin-bottom: 0; }
.drink-row__label {
  font-family: var(--font-sans);
  font-size: 0.76rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-600);
}

/* ---- Styled drink dropdown -------------------------------------------
   The native select stays in the DOM as the value holder (it posts with the
   form), but the guest sees this control instead: grouped headings, a hover
   highlight and no wrapped option text. */
.pick { position: relative; }
/* The native select is the value holder only — both sections use the same
   class now, so this hides it for the day and evening pickers alike. */
.pick .pick__native { display: none; }

.pick__control {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1rem;
  font-family: var(--font-serif);
  font-size: 1.12rem;
  color: var(--ink);
  text-align: left;
  background: #FFFFFF;
  border: 1px solid rgba(23, 33, 28, 0.18);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.pick__control:hover { border-color: rgba(201, 162, 39, 0.55); }
.pick.is-open .pick__control { border-color: var(--gold-500); box-shadow: var(--ring); }
.pick__control:focus-visible { outline: none; border-color: var(--gold-500); box-shadow: var(--ring); }

/* One line, ellipsised — never wrapped. */
/* min-width:0 is what actually lets this shrink. As a flex item its default
   min-width is auto, so a long drink name pushed the control wider than the
   field instead of ellipsising inside it. */
.pick__value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pick__value.is-empty { color: #9AA6A0; font-style: italic; }

/* On a phone, "Moët & Chandon Brut Imp…" is not enough to confirm a choice —
   the full name matters more than a tidy single line, so let it wrap and let
   the field grow to fit it. */
@media (max-width: 560px) {
  .pick__control {
    gap: 0.7rem;
    padding: 0.8rem 0.9rem;
    font-size: 1.04rem;
  }
  .pick__value {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: 1.32;
  }
}

.pick__chevron {
  flex: none;
  width: 13px; height: 8px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1l6 6 6-6' fill='none' stroke='%23C9A227' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.2s ease;
}
.pick.is-open .pick__chevron { transform: rotate(180deg); }

.pick__list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 6px);
  left: 0; right: 0;
  /* 75 options in a 19rem window hid the wines entirely — they sit at the very
     bottom, and nothing said the list scrolled. Taller now, with a scrollbar
     that is always visible rather than an overlay that fades away. */
  max-height: min(26rem, 58vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 162, 39, 0.65) rgba(201, 162, 39, 0.1);
  margin: 0;
  padding: 0.4rem;
  list-style: none;
  background: #FFFFFF;
  border: 1px solid rgba(201, 162, 39, 0.45);
  border-radius: 12px;
  box-shadow: 0 26px 50px -22px rgba(4, 26, 19, 0.5);
}
.pick__list::-webkit-scrollbar { width: 11px; }
.pick__list::-webkit-scrollbar-track {
  background: rgba(201, 162, 39, 0.1);
  border-radius: 0 12px 12px 0;
}
.pick__list::-webkit-scrollbar-thumb {
  background: rgba(201, 162, 39, 0.6);
  border: 3px solid #FFFFFF;
  border-radius: 999px;
}
.pick__list::-webkit-scrollbar-thumb:hover { background: rgba(168, 132, 27, 0.8); }

.pick__group {
  margin: 0.35rem 0 0.15rem;
  padding: 0.45rem 0.7rem;
  border-radius: 7px;
  background: var(--cream);
  font-family: var(--font-sans);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--emerald-700);
}

.pick__option {
  padding: 0.5rem 0.85rem;
  border-radius: 8px;
  font-size: 1.08rem;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pick__option.is-active { background: var(--champagne); }
.pick__option.is-selected {
  background: linear-gradient(180deg, var(--gold-400), var(--gold-500));
  color: #23180A;
  font-weight: 600;
}

/* A section holding an open list must sit above the sections after it. */
.fieldset:has(.pick.is-open) { z-index: 5; }

.picks-summary {
  margin: 0;
  font-size: 1.02rem;
  color: var(--ink-soft);
  text-align: right;
}
.picks-summary strong { color: var(--emerald-800); }
.picks-summary__label {
  font-family: var(--font-sans);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-right: 0.55rem;
}

/* Stack once there is no room for two columns. This has to sit *after* the
   rules above: they are the same specificity, so source order decides — from
   further up the file the old text-align:right won and left the summary
   ragged against the counter. */
@media (max-width: 560px) {
  .drinks__foot {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
  }
  .picks-summary { text-align: left; }
  .picks-summary__label { display: block; margin: 0 0 0.1rem; }
}

/* Other-drink reveal */
.reveal { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 0.28s ease; }

/* Submit area */
.rsvp__submit {
  position: relative;
  z-index: 1;
  margin-top: 2rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgba(201, 162, 39, 0.32);
  text-align: center;
}

.linkbtn {
  background: none;
  border: 0;
  padding: 0.2rem 0;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--emerald-600);
  border-bottom: 1px solid rgba(201, 162, 39, 0.55);
  cursor: pointer;
  text-decoration: none;
}
.linkbtn:hover { color: var(--gold-600); border-bottom-color: var(--gold-500); }

.form-status {
  position: relative;
  z-index: 1;
  margin-top: 1.25rem;
  padding: 1rem 1.2rem;
  border-radius: 12px;
  font-size: 1.02rem;
  display: none;
}
.form-status[data-state] { display: block; }
.form-status[data-state="error"] {
  background: #FCEFEC;
  border: 1px solid #E2B4A9;
  color: #8C2C18;
}
.form-status[data-state="info"] {
  background: var(--champagne);
  border: 1px solid rgba(201, 162, 39, 0.5);
  color: #6B5210;
}

/* Success panel */
.success {
  position: relative;
  z-index: 1;
  text-align: center;
  padding: clamp(1rem, 3vw, 2rem) 0;
}
.success__mark {
  width: 74px; height: 74px;
  margin: 0 auto 1.4rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(201, 162, 39, 0.6);
  background: linear-gradient(160deg, var(--champagne), #FFFFFF);
  color: var(--gold-600);
}
.success__title { font-size: clamp(1.6rem, 4.2vw, 2.25rem); color: var(--emerald-900); }
.success__title .script { color: var(--gold-600); }
.success__body { max-width: 46ch; margin: 0.9rem auto 0; color: var(--ink-soft); }
.success__recap {
  margin: 1.5rem auto 0;
  max-width: 460px;
  text-align: left;
  background: var(--cream);
  border: 1px solid rgba(201, 162, 39, 0.35);
  border-radius: 12px;
  padding: 1.15rem 1.35rem;
  font-size: 1.02rem;
}
.success__recap dl { display: grid; grid-template-columns: auto 1fr; gap: 0.4rem 1rem; margin: 0; }
.success__recap dt {
  font-family: var(--font-sans);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-top: 0.2rem;
}
.success__recap dd { margin: 0; color: var(--emerald-800); font-weight: 600; }
.success__actions { margin-top: 1.75rem; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.8rem; }

/* --------------------------------------------------------------------------
 * 12. Footer
 * ------------------------------------------------------------------------*/
.footer {
  position: relative;
  isolation: isolate;
  background: linear-gradient(180deg, var(--emerald-900), var(--emerald-950));
  color: rgba(252, 250, 244, 0.82);
  text-align: center;
  /* One line now, so the deep top padding that carried the script line and
     the fine print is no longer needed — keep the name optically centred. */
  padding: clamp(2.2rem, 5vw, 3rem) 0;
  overflow: hidden;
}
.footer::after {
  content: "";
  position: absolute; inset: 0;
  background-image: var(--grain);
  opacity: 0.05;
  mix-blend-mode: overlay;
  pointer-events: none;
}
.footer__line { font-size: 0.98rem; margin: 0; }

/* --------------------------------------------------------------------------
 * 13. Motion & print
 * ------------------------------------------------------------------------*/
/* Scroll-reveal. The hidden state is gated behind `html.reveal-ready`, which
 * only JavaScript adds — so with JS disabled, or in a print/PDF render, the
 * content is always visible instead of being stuck at opacity 0. */
@media (prefers-reduced-motion: no-preference) {
  html.reveal-ready .reveal-up {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  }
  html.reveal-ready .reveal-up.is-visible { opacity: 1; transform: none; }
}

@media print {
  .hero__corners, .rsvp__corners, .hero__actions, .btn { display: none !important; }
  body { background: #fff; font-size: 11pt; }
  .hero {
    min-height: auto;
    background: #fff !important;
    color: #000;
    padding: 1.5rem 0;
  }
  .section { padding: 1rem 0; page-break-inside: avoid; }
  /* A printed invitation must never inherit the scroll-reveal hidden state. */
  .reveal-up { opacity: 1 !important; transform: none !important; }
  .rsvp__card { box-shadow: none; }
  .footer { background: #fff !important; color: #000; }
}

/* ======================================================================
   THE SEALED INVITATION (gate.html)

   Shown to anyone without the invitation link. Everything above is the
   hero's own styling reused verbatim, so the teaser and the real thing
   are the same picture — the difference is that the guard never reaches
   the rest of the page.
   ====================================================================== */

.gate-body { background: var(--ivory); }

/* The hero fills the screen on the invitation; here it has to share the
   screen with the envelope, so the padding comes in a little. */
.hero--gate { padding-bottom: clamp(1.5rem, 4vh, 2.5rem); }

/* The message dissolves mid-sentence. */
.gate__teaser {
  -webkit-mask-image: linear-gradient(to bottom,
    #000 0%, #000 30%, rgba(0, 0, 0, 0.55) 62%, rgba(0, 0, 0, 0.15) 82%, transparent 100%);
  mask-image: linear-gradient(to bottom,
    #000 0%, #000 30%, rgba(0, 0, 0, 0.55) 62%, rgba(0, 0, 0, 0.15) 82%, transparent 100%);
}

.gate__lock {
  display: grid;
  justify-items: center;
  gap: 1.1rem;
  margin-top: 1.9rem;
  padding-bottom: 0.5rem;
}

.gate__note {
  max-width: 34ch;
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.74rem;
  line-height: 1.85;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-faint);
  transition: color 0.3s ease;
}
.gate__note.is-emphasised { color: var(--gold-600); }

/* ---------------------------------------------------------- the envelope */

.envelope {
  --env-w: 210px;
  --env-h: 138px;
  position: relative;
  display: block;
  width: var(--env-w);
  height: var(--env-h);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  perspective: 900px;
  -webkit-tap-highlight-color: transparent;
}
.envelope:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 8px; border-radius: 8px; }

.envelope__body {
  position: absolute;
  inset: 0;
  display: block;
  transform-style: preserve-3d;
  filter: drop-shadow(0 16px 26px rgba(4, 26, 19, 0.28));
}

/* Outline the envelope once, above every layer, so the silhouette is clean. */
.envelope::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 5px;
  box-shadow: inset 0 0 0 1px rgba(168, 132, 27, 0.45);
  pointer-events: none;
}

/* The paper showing through, with the cream interior behind the flap. */
.envelope__letter {
  position: absolute;
  inset: 8% 5% 6%;
  display: block;
  border-radius: 3px;
  background: linear-gradient(170deg, #FFFFFF 0%, #FBF6EC 100%);
  box-shadow: inset 0 0 0 1px rgba(201, 162, 39, 0.35);
}

/* The pocket, drawn as the two side folds meeting at the middle. */
.envelope__front {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: 5px;
  background:
    linear-gradient(200deg, #F1E3C4 0%, #E7D5AC 54%, #DBC596 100%);
  clip-path: polygon(0 0, 50% 46%, 100% 0, 100% 100%, 0 100%);
  box-shadow: inset 0 0 0 1px rgba(168, 132, 27, 0.5);
}

/* The flap: a triangle hinged along the top edge. */
.envelope__flap {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 52%;
  display: block;
  background: linear-gradient(180deg, #FEFBF3 0%, #F7EDD6 62%, #EFE0BC 100%);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  filter: drop-shadow(0 3px 4px rgba(122, 96, 32, 0.22));
  transform-origin: top center;
  transform: rotateX(0deg);
  transition: transform 0.75s cubic-bezier(0.6, 0.04, 0.3, 1);
  backface-visibility: hidden;
}
.envelope.is-open .envelope__flap { transform: rotateX(-180deg); }

/* The wax seal. */
.envelope__seal {
  position: absolute;
  left: 50%;
  top: 46%;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #E7CF86, #C9A227 58%, #A8841B 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 4px 10px -3px rgba(4, 26, 19, 0.5);
  font-family: var(--font-serif);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: #2A1E07;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.envelope.is-open .envelope__seal { opacity: 0; transform: scale(1.5); }

/* A polite refusal rather than a dead image. */
@keyframes envelope-denied {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  18% { transform: translateX(-6px) rotate(-1.4deg); }
  38% { transform: translateX(5px) rotate(1.1deg); }
  58% { transform: translateX(-4px) rotate(-0.8deg); }
  78% { transform: translateX(3px) rotate(0.5deg); }
}
.envelope.is-denied { animation: envelope-denied 0.55s ease; }

.envelope.is-denied .envelope__seal { animation: envelope-denied 0.55s ease; }

@media (prefers-reduced-motion: reduce) {
  .envelope__flap { transition: none; }
  .envelope.is-denied,
  .envelope.is-denied .envelope__seal { animation: none; }
}

/* ======================================================================
   THE SEALED ENVELOPE (on the invitation itself)

   Seen once per session by a guest who arrived on the invitation link.
   It lifts away to hand over the invitation rather than just loading it.
   ====================================================================== */

body.is-sealed { overflow: hidden; }

.reveal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  background:
    radial-gradient(120% 62% at 50% 4%, rgba(231, 207, 134, 0.3), transparent 66%),
    linear-gradient(180deg, #F8F1E4 0%, #FBF6EC 46%, var(--ivory) 100%);
  transition: opacity 0.9s ease, visibility 0.9s ease;
}
.reveal.is-lifting { opacity: 0; visibility: hidden; pointer-events: none; }

.reveal__inner {
  display: grid;
  justify-items: center;
  gap: 1.5rem;
  padding: 2rem;
  text-align: center;
  animation: reveal-arrive 0.9s ease both;
}
@keyframes reveal-arrive {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.reveal__eyebrow {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.76rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold-600);
}

.reveal__hint {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The larger envelope used for the reveal. */
.envelope--lg { --env-w: 264px; --env-h: 174px; }
.envelope--lg .envelope__seal { width: 54px; height: 54px; margin: -27px 0 0 -27px; font-size: 0.94rem; }

@media (prefers-reduced-motion: reduce) {
  .reveal__inner { animation: none; }
}

/* ======================================================================
   INNER PAGES (details.html, rsvp.html)

   Each is its own document now, so they need their own bottom actions and
   a way back up the flow.
   ====================================================================== */

.details__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  margin-top: clamp(2rem, 5vw, 3rem);
  text-align: center;
}

.details__actions .btn { min-width: min(100%, 260px); }

/* A quiet way back to the previous step. */
.backlink {
  margin-top: 1.5rem;
  text-align: center;
}

/* The day refreshment ingredients, shown under the dropdown for whichever
   drink is chosen. */

/* The old radio-card markup is gone, so its layout rules go with it. */

/* ======================================================================
   THE ENVELOPE, IN THREE ACTS

   1. the seal breaks, with gold motes thrown up from it
   2. the flap lifts and light spills out of the envelope
   3. the envelope drops away, leaving the invitation

   Everything is driven by .is-open, which the reveal script adds on click.
   ====================================================================== */

/* --- the light inside ------------------------------------------------- */
.envelope__glow {
  position: absolute;
  left: 50%;
  top: 46%;
  width: 150%;
  height: 120%;
  margin: -60% 0 0 -75%;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle,
    rgba(255, 243, 205, 0.95) 0%,
    rgba(231, 207, 134, 0.55) 38%,
    rgba(231, 207, 134, 0) 70%);
  transform: scale(0.5);
  transition: opacity 0.5s ease 0.1s, transform 0.9s cubic-bezier(0.3, 0, 0.2, 1) 0.1s;
}
.envelope.is-open .envelope__glow { opacity: 1; transform: scale(1); }

/* --- the seal breaks -------------------------------------------------- */
.envelope .envelope__seal { transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.3, 1.4, 0.5, 1); }
.envelope.is-open .envelope__seal {
  opacity: 0;
  transform: scale(1.7) rotate(18deg);
}

/* --- the flap lifts --------------------------------------------------- */
.envelope .envelope__flap { transition: transform 0.85s cubic-bezier(0.62, 0.02, 0.28, 1) 0.28s; }

/* --- the letter rises, then the envelope drops away ------------------- */
.envelope .envelope__letter {
  transition: transform 0.7s cubic-bezier(0.3, 0.9, 0.3, 1) 0.85s;
}
.envelope.is-open .envelope__letter { transform: translateY(-38%); }

.envelope { transition: transform 0.9s cubic-bezier(0.5, 0, 0.7, 0.2) 1.15s, opacity 0.7s ease 1.35s; }
.envelope.is-open { transform: translateY(26px) scale(0.94); opacity: 0; }

/* --- the gold motes --------------------------------------------------- */
.envelope__sparks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.envelope__sparks i {
  position: absolute;
  left: 50%;
  top: 46%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #FFF6DA, #D9BA52 60%, #A8841B);
  opacity: 0;
  transform: translate(0, 0) scale(0.4);
}
.envelope.is-open .envelope__sparks i {
  animation: spark-fly 0.95s cubic-bezier(0.2, 0.7, 0.4, 1) 0.12s forwards;
}
/* Fanned out so the burst reads as a scatter rather than a star. */
.envelope__sparks i:nth-child(1) { --dx: -78px; --dy: -54px; }
.envelope__sparks i:nth-child(2) { --dx: -46px; --dy: -80px; }
.envelope__sparks i:nth-child(3) { --dx:  -8px; --dy: -92px; }
.envelope__sparks i:nth-child(4) { --dx:  38px; --dy: -76px; }
.envelope__sparks i:nth-child(5) { --dx:  72px; --dy: -46px; }
.envelope__sparks i:nth-child(6) { --dx: -62px; --dy:  18px; }
.envelope__sparks i:nth-child(7) { --dx:  16px; --dy:  26px; }
.envelope__sparks i:nth-child(8) { --dx:  64px; --dy:  10px; }

@keyframes spark-fly {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.3); }
  18%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1.05); }
}

@media (prefers-reduced-motion: reduce) {
  .envelope,
  .envelope__glow,
  .envelope__seal,
  .envelope__flap,
  .envelope__letter { transition-duration: 0.01ms !important; }
  .envelope.is-open .envelope__sparks i { animation: none; }
}


/* Cloudflare Turnstile sits with the form fields, above the send button.
   Its iframe carries inline sizing, so it is capped here as well — a widget
   wider than the card is the one thing that must never happen. */
.turnstile-field { margin-top: 1.6rem; max-width: 100%; }
#turnstileSlot { max-width: 100%; }
#turnstileSlot > div,
#turnstileSlot iframe { max-width: 100% !important; }
.turnstile-note {
  margin: 0.6rem 0 0;
  font-size: 0.82rem;
  color: var(--ink-faint);
}

/* A note that must be read, not skimmed — set apart from the lead line
   without shouting. Used for the adults-only line on the details page. */
.section__note {
  display: inline-block;
  margin: 0.9rem 0 0;
  padding: 0.5rem 1.05rem;
  border: 1px solid rgba(201, 162, 39, 0.42);
  border-radius: 999px;
  background: rgba(201, 162, 39, 0.07);
  font-family: var(--font-sans);
  font-size: 0.78rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--emerald-800);
}

/* The thank-you shown in place of the form once the RSVP closes. */
.success--closed .success__title { margin-top: 0.2rem; }
.success--closed .success__body { max-width: 30rem; margin-inline: auto; }
