/* ===========================================================
   Anya & Shyam — Wedding Invitation
   =========================================================== */

:root {
  --burgundy-deep:  #3d0f18;
  --burgundy:       #5c1a26;
  --burgundy-light: #7a2536;
  --burgundy-soft:  #9c4a58;
  --gold:           #c9a45c;
  --gold-light:     #e8d4a0;
  --gold-dim:       #a8823f;
  --cream:          #fbf6eb;
  --cream-dark:     #f0e8d8;
  --ink:            #2b1810;
  --ink-soft:       #6b5548;

  /* couple's palette — woven in as accents */
  --bordeaux:       #610f16;
  --sage:           #a2ab8b;
  --sage-dark:      #7f885f;
  --pink:           #f1afba;
  --pink-soft:      #f8dce1;
  --sand:           #dfc3ad;
  --sand-soft:      #efe1d3;

  --font-display: "Playfair Display", serif;
  --font-body:    "EB Garamond", serif;
  --font-script:  "Parisienne", cursive;

  --container: 1080px;
  --gutter: clamp(1.25rem, 5vw, 3rem);

  /* THE knob for vertical rhythm between sections. Every .section pads top and
     bottom with this, so the gap between one section's end and the next one's
     title is exactly twice this value — change it here and nowhere else.
     Was clamp(4rem, 9vw, 7rem); now ~63% of that, which still leaves ~83px of
     air on a phone and ~144px on a wide desktop. */
  --section-y: clamp(2.5rem, 5.7vw, 4.4rem);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.94rem + 0.3vw, 1.15rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* body is locked while intro plays */
body.intro-active { overflow: hidden; height: 100vh; }

img, svg { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3 { font-family: var(--font-display); font-weight: 500; margin: 0; color: var(--burgundy-deep); }

.divider { width: 150px; height: 20px; color: var(--gold); margin: 0.9rem auto 0; }

.section {
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--section-y) var(--gutter);
}

.section-head { text-align: center; margin-bottom: clamp(2.5rem, 6vw, 4rem); }

.kicker {
  font-family: var(--font-script);
  font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  color: var(--gold-dim);
  margin: 0 0 0.2rem;
}

.section-head h2 {
  font-size: clamp(1.6rem, 1.3rem + 1.4vw, 2.4rem);
  letter-spacing: 0.02em;
}

.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.85em 2em;
  border-radius: 999px;
  border: 1.5px solid var(--burgundy);
  transition: background 0.25s ease, color 0.25s ease, transform 0.25s ease;
}
.btn-outline { background: transparent; color: var(--burgundy); }
.btn-outline:hover { background: var(--burgundy); color: var(--cream); transform: translateY(-2px); }
.btn-solid { background: var(--burgundy); color: var(--cream); border-color: var(--burgundy); }
.btn-solid:hover { background: var(--bordeaux); border-color: var(--bordeaux); transform: translateY(-2px); }

/* Full-bleed soft background for alternating sections */
.site { overflow-x: hidden; }
.alt-bg { position: relative; }
.alt-bg::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0; bottom: 0; left: 50%;
  width: 100vw;
  transform: translateX(-50vw);
  background: var(--sand-soft);
}

/* ===========================================================
   INTRO / ENVELOPE LOADER
   =========================================================== */

/* Every layer is silhouette-clipped to the envelope itself, so the intro
   sits directly on the website's cream background and the final zoom+fade
   melts into the page with no backdrop change. */
.intro-overlay {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  /* The scene backdrop: a faint wash of the SAME hero.jpg watercolour that
     anchors the real header — the envelope and card read as floating in
     front of a preview of the villa. The cream wash on top is deliberately
     kept near-opaque in aggregate (~99.6% effective coverage, same as the
     flat crema it replaces): a fully transparent overlay lets Chrome defer
     rasterizing the real page underneath, then pays that cost in one long
     stall mid-zoom. Layering the photo UNDER an opaque-ish cream tint keeps
     that guarantee while letting the villa show through faintly. */
  background:
    linear-gradient(rgba(251, 246, 235, 0.82), rgba(251, 246, 235, 0.82)),
    url("../assets/hero.jpg") center 32% / cover no-repeat,
    rgba(251, 246, 235, 0.996);
  cursor: pointer;
}

/* Long-lens perspective (~5x the flap length) so the flap barely changes
   apparent size while rotating — matching the reference video's distant
   camera — while keeping a believable 3D fold. */
.intro-stage {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 3200px;
  perspective: 340svh;
  overflow: hidden;
}

/* ---- Layered envelope built from the two real renders -----------------
   All geometry below is measured pixel-accurately from the artwork
   (1408x736). Closed render: body x 218-1174, hinge y=28, flap tip
   (700,528), seam traced point-by-point along its curve. Open render:
   body x 369-1011, fold y=272. Aligning the open render onto the closed
   one requires scaleX 1.4891 / scaleY 1.5648 anchored at the fold line —
   expressed as the oversized absolutely-positioned .env-open-layer. */

/* Sized so the WHOLE composition always fits on screen: the envelope
   spans 66.6% of the frame's width (must fit the viewport width), and
   once open, the standing flap extends the composition to 145.3% of the
   frame height (must fit the viewport height -> height <= ~66svh).
   intro.js adds a gentle downward camera drift while the flap rises so
   the closed envelope sits centered yet the full opening stays in frame. */
.envelope-frame {
  position: relative;
  width: auto;
  height: min(66vh, 66svh, 75vw);
  aspect-ratio: 1408 / 736;
  transform-style: preserve-3d;
}

/* Soft ground shadow replacing the renders' baked-in table shadow
   (which gets clipped away with their gray backdrops). */
.envelope-frame::before {
  content: "";
  position: absolute;
  left: 14%;
  right: 15%;
  bottom: 1.5%;
  height: 7%;
  z-index: 0;
  background: radial-gradient(ellipse at center,
    rgba(50, 18, 24, 0.4) 0%, rgba(50, 18, 24, 0.18) 55%, rgba(50, 18, 24, 0) 78%);
  filter: blur(6px);
}

/* Open render, scaled + positioned so its envelope body coincides exactly
   with the closed render's body. Revealed through the flap notch first,
   then fully as .env-base crossfades away mid-opening. */
.env-open-layer {
  position: absolute;
  left: -23.543%;
  top: -54.026%;
  width: 148.91%;
  height: 156.48%;
  z-index: 1;
}
.env-open-layer img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* The open render supplies only the BODY below its fold line (y=272/736 =
   36.96%), crossfaded in early so the flap's baked-in drop shadow on the
   closed body vanishes as soon as the flap lifts. The standing flap in
   the final open state is the SAME rotating flap object, resting at its
   132deg pose — one object start to finish, so its shape never changes.
   Clipped to the body rect so none of the render's gray backdrop shows. */
.open-body {
  clip-path: polygon(26.5% 36.85%, 71.55% 36.85%, 71.55% 95.35%, 26.5% 95.35%);
}

/* Closed render clipped to the envelope silhouette (no gray backdrop),
   with the flap kite cut out along its traced seam, so the rotating flap
   layer is the only copy of those pixels. Path: top-left corner, down the
   left seam to the tip, up the right seam to the top-right corner, then
   around the body's outer edges. */
.env-base {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  will-change: opacity;
  clip-path: polygon(
    16.05% 3.95%, 16.19% 8.15%, 18.11% 13.59%, 21.16% 19.02%, 24.08% 24.46%,
    26.7% 29.89%, 29.19% 35.33%, 31.61% 40.76%, 33.95% 46.2%, 37% 51.63%,
    39.77% 57.07%, 42.68% 62.5%, 45.74% 67.93%, 49.72% 71.74%,
    53.48% 67.93%, 56.46% 62.5%, 59.16% 57.07%, 62.07% 51.63%, 64.91% 46.2%,
    67.54% 40.76%, 69.89% 35.33%, 72.37% 29.89%, 74.86% 24.46%, 77.63% 19.02%,
    80.89% 13.59%, 82.46% 8.15%, 82.55% 3.95%,
    83.2% 95.3%, 15.75% 95.3%);
}

/* The real flap: same closed render, clipped to the seam (expanded a
   fraction outward so no antialiased sliver of the notch shows through),
   hinged on the fold line. GSAP drives rotationX for a true 3D opening. */
.env-flap {
  position: absolute;
  inset: 0;
  z-index: 3;
  transform-origin: 49.5% 3.8%;
  transform-style: preserve-3d;
  will-change: transform;
}
/* True two-sided card. The faces are pre-cut images with real alpha
   (assets/flap-front.webp, flap-back.webp — the kite region x 15.9-82.7%,
   y 3.95-72.15% of the render, silhouette baked in at export). No
   clip-path and no reliance on backface-visibility: browsers cull
   inconsistently (the flap vanished mid-rotation on some GPU paths), so
   intro.js toggles face visibility itself at the exact frame the real
   rotation angle crosses 90deg — the instant the flap is edge-on. */
.flap-front,
.flap-back {
  position: absolute;
  left: 15.9%;
  top: 3.95%;
  width: 66.8%;
  height: 68.2%;
}
/* Interior side: pre-flipped 180deg about its own center so that, while
   the parent is past 90deg, it reads upright; its silhouette and top-lit
   gradient are baked into the image mirrored, landing exactly on the
   kite. Hidden until the angle-driven toggle reveals it. */
.flap-back {
  transform: rotateX(180deg);
  visibility: hidden;
}

.intro-hint {
  position: absolute;
  bottom: max(1.5rem, env(safe-area-inset-bottom));
  z-index: 5;
  font-family: var(--font-body);
  font-size: 0.8rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-dim);
  opacity: 0.8;
  background: none;
  border: none;
  padding: 0.6em 1.2em;
  cursor: pointer;
}

/* The intro already played this session: kill it before first paint
   (class set by the inline <head> script). */
html.intro-seen .intro-overlay { display: none !important; }

/* ADDITIVE — the envelope's own rules above are untouched. This only gives
   intro.js a handle to dissolve the ground shadow together with the rest of
   the envelope's layers, once the card is on its way out. Fading the FRAME
   itself is not an option: the card now lives inside it and would fade too. */
.envelope-frame::before { opacity: var(--env-alpha, 1); }

/* ===========================================================
   INTRO — THE INVITATION CARD (rigid: it never folds)
   It sits INSIDE .envelope-frame, between the body (z2) and the flap (z3),
   so the flap really does paint over it and it really does ride the frame's
   drift. The front panels are painted pixels with no alpha window, so they
   cannot occlude it — intro.js clips the card to the V profile traced from
   the render instead.
   #cardFlip carries translate + scale (origin 0 0, so x/y ARE the top-left
   corner whatever the scale); .card-tilt carries only the paper-weight
   wobble, about its own centre. Keeping the two apart makes the closing FLIP
   exact: at scale 1, translated to the header's measured rect, the card IS
   the real .hero-inner — the text cannot jump.
   =========================================================== */

#introCard {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;          /* while seated: same as .env-base but later in the DOM,
                          so above the body and below the flap (z3). */
  pointer-events: none;
}

/* Where the card goes the moment it starts to climb: a flat sibling of
   .envelope-frame, so it paints over the entire envelope, flap included.
   .intro-stage only sets `perspective` (no preserve-3d), so it flattens its
   children and plain stacking decides between them again — which is the whole
   point: inside the frame, the rotateX'd flap is depth-sorted and would beat
   any z-index the card could claim. */
.card-layer {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}

#cardFlip {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  will-change: transform, clip-path;
}
.card-tilt {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
}

/* Warm ivory card stock. The deckled edge is a turbulence displacement of the
   sheet's own silhouette (#deckle) — safe here because this layer is flat: a
   CSS filter on a 3D-transformed element flattens its transform context. */
.card-sheet {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #F0EAD9;
  border-radius: 2px;
  filter: url(#deckle);
  box-shadow: 0 14px 40px rgba(61, 15, 24, 0.30);
}

/* Embossed linen: a fine turbulence tile plus a whisper of weave. Kept low
   enough to read as paper tooth rather than as digital noise. */
.card-grain {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0.06;
  background-image:
    repeating-linear-gradient(90deg, rgba(0,0,0,0.5) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(0deg, rgba(0,0,0,0.35) 0 1px, transparent 1px 3px),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* The cloned header text. Same padding and text-align as .hero-inner, and
   #cardFlip is sized to .hero-inner's measured rect — so at FLIP identity the
   clone's layout IS the header's layout, line for line.
   The z-index is load-bearing: the sheet and grain are POSITIONED while the
   cloned text is static, and static descendants paint first — without it the
   paper would bury the names. */
.card-text {
  position: absolute;
  inset: 0;
  z-index: 2;
  padding: clamp(0.8rem, 1.6vw, 1.1rem) clamp(1.2rem, 3vw, 2rem);
  /* .hero-inner has a 1px border and border-box sizing, so it eats 2px of
     content width. Without a matching invisible border the clone would be 2px
     wider inside and the tagline could break to a different line. */
  border: 1px solid transparent;
  text-align: center;
}

/* ===========================================================
   NAV
   =========================================================== */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem clamp(1.25rem, 5vw, 3rem);
  background: rgba(251, 246, 235, 0.85);
  border-bottom: 1px solid rgba(92, 26, 38, 0.1);
}
/* Frosted blur lives on a pseudo-element ON PURPOSE: backdrop-filter on
   .nav itself would make it the containing block for fixed descendants,
   trapping the mobile fullscreen menu inside the 64px bar. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.nav-monogram {
  display: inline-flex;
  align-items: center;
}
.nav-monogram img {
  height: clamp(2rem, 1.6rem + 1.4vw, 2.75rem);
  width: auto;
  display: block;
}

.nav-toggle {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 28px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.3rem;
  z-index: 101;
}
.nav-toggle span {
  display: block;
  height: 2px;
  background: var(--burgundy);
  border-radius: 2px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav-menu {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  font-family: var(--font-display);
  font-size: 1.4rem;
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform 0.4s cubic-bezier(0.6, 0, 0.2, 1),
              visibility 0s linear 0.4s;
}
.nav-menu.open {
  transform: translateY(0);
  visibility: visible;
  transition: transform 0.4s cubic-bezier(0.6, 0, 0.2, 1);
}
.nav-menu a { color: var(--burgundy-deep); }
.nav-menu a:hover { color: var(--gold-dim); }

@media (min-width: 768px) {
  .nav-toggle { display: none; }
  .nav-menu {
    position: static;
    transform: none;
    visibility: visible;
    flex-direction: row;
    background: none;
    gap: clamp(1.2rem, 3vw, 2.2rem);
    font-family: var(--font-body);
    font-size: 1rem;
    letter-spacing: 0.04em;
  }
  .nav-menu a { position: relative; }
  .nav-menu a::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: -4px;
    height: 1px;
    background: var(--gold-dim);
    transform: scaleX(0);
    transition: transform 0.25s ease;
  }
  .nav-menu a:hover::after { transform: scaleX(1); }
  .nav-menu a.nav-cta {
    padding: 0.4em 1.2em;
    border: 1.5px solid var(--burgundy);
    border-radius: 999px;
    color: var(--burgundy);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-size: 0.85rem;
    transition: background 0.25s ease, color 0.25s ease;
  }
  .nav-menu a.nav-cta::after { display: none; }
  .nav-menu a.nav-cta:hover { background: var(--burgundy); color: var(--cream); }
}

/* ===========================================================
   HERO
   =========================================================== */

.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  /* panel anchored low so the villa (upper-center of the painting)
     stays fully in view above it */
  align-items: flex-end;
  justify-content: center;
  text-align: center;
  padding: 6rem var(--gutter) clamp(0.8rem, 1.8vh, 1.4rem);
  background:
    radial-gradient(ellipse at 50% 0%, var(--cream-dark) 0%, var(--cream) 60%);
  position: relative;
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 12% 20%, rgba(201,164,92,0.14), transparent 40%),
    radial-gradient(circle at 88% 78%, rgba(92,26,38,0.10), transparent 40%);
  pointer-events: none;
}

/* Header illustration (watercolour of the villa), FULL-BLEED cover.
   Readability per UX: two guarantees layered on top of the painting —
   (1) a vertical cream scrim, strongest at the top (fixed nav) and the
   bottom (scroll cue / transition into the page), lighter mid-frame so
   the artwork breathes; (2) a frosted cream panel behind the hero text
   (below), keeping the burgundy type >7:1 contrast over any brushwork.
   `multiply` melts the watercolour paper into the cream page.
   Missing file → nothing shows and the cream gradient stands alone. */
.hero-media {
  position: absolute;
  inset: 0;
  background-image: url("../assets/hero.jpg");
  background-size: cover;
  background-position: center 32%;
  background-repeat: no-repeat;
  mix-blend-mode: multiply;
  z-index: 0;
  pointer-events: none;
}
/* The painting's top 75% (the villa) stays FREE: only a whisper of cream
   up top (the fixed nav has its own frosted bar) and nothing over the
   mid-frame. The readability scrim is concentrated in the bottom quarter,
   where the text panel now lives. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(251, 246, 235, 0.45) 0%,
    rgba(251, 246, 235, 0.05) 12%,
    rgba(251, 246, 235, 0.00) 45%,
    rgba(251, 246, 235, 0.00) 60%,
    rgba(251, 246, 235, 0.30) 78%,
    rgba(251, 246, 235, 0.75) 100%);
}

/* Panel confined to the photo's BOTTOM 40%: the villa runs free in the
   upper 60%, while the panel gets enough width for a balanced type scale
   (names → countdown → cue all inside the band). */
.hero-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 600px;
  padding: clamp(0.8rem, 1.6vw, 1.1rem) clamp(1.2rem, 3vw, 2rem);
  border-radius: 14px;
  background: rgba(251, 246, 235, 0.68);
  border: 1px solid rgba(255, 253, 246, 0.85);
  box-shadow: 0 16px 50px rgba(61, 15, 24, 0.10);
}
/* Type scale for the bottom-40% panel. line-height pinned on the small
   lines: the body's 1.6 would silently add ~40px of dead space.
   :is(.hero, #introCard) — the intro's card clones this same text (split
   across .fold-top / .card-text-lower) OUTSIDE the .hero section, so it
   must share this exact scale for the closing FLIP zoom to land pixel-
   perfect on the real header. Keep both branches in sync. */
:is(.hero, #introCard) .eyebrow { font-size: 0.68rem; margin-bottom: 0.45rem; letter-spacing: 0.28em; line-height: 1.3; }
:is(.hero, #introCard) .hero-names { font-size: clamp(1.9rem, 1.35rem + 2.1vw, 2.7rem); line-height: 1.05; }
:is(.hero, #introCard) .divider { width: 104px; height: 16px; margin-top: 0.4rem; }
:is(.hero, #introCard) .hero-date { margin-top: 0.6rem; font-size: clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem); line-height: 1.3; }
:is(.hero, #introCard) .hero-location { margin-top: 0.2rem; font-size: 0.92rem; line-height: 1.3; }
:is(.hero, #introCard) .hero-tagline { margin-top: 0.55rem; font-size: 0.88rem; max-width: 470px; line-height: 1.45; }
:is(.hero, #introCard) .cd-num { font-size: clamp(1.35rem, 1.1rem + 0.9vw, 1.75rem); }
:is(.hero, #introCard) .cd-lbl { font-size: 0.62rem; margin-top: 0.25rem; }
:is(.hero, #introCard) .cd-unit { min-width: 2.8rem; }
:is(.hero, #introCard) .countdown { margin-top: 0.6rem; gap: clamp(0.9rem, 2.4vw, 1.6rem); }
:is(.hero, #introCard) .scroll-cue { margin-top: 0.5rem; width: 22px; height: 34px; padding-top: 6px; }
/* Short viewports: the 40% band shrinks below ~310px — trim the two
   decorative extras so names, date and countdown keep breathing. */
@media (max-height: 780px) {
  :is(.hero, #introCard) .divider { display: none; }
  :is(.hero, #introCard) .hero-tagline { display: none; }
  :is(.hero, #introCard) .hero-names { font-size: clamp(1.7rem, 1.2rem + 1.8vw, 2.2rem); }
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .hero-inner {
    background: rgba(251, 246, 235, 0.46);
    -webkit-backdrop-filter: blur(9px) saturate(1.05);
    backdrop-filter: blur(9px) saturate(1.05);
  }
}

.hero-location {
  margin: 0.35rem 0 0;
  font-family: var(--font-body);
  font-size: clamp(0.95rem, 0.88rem + 0.35vw, 1.15rem);
  letter-spacing: 0.06em;
  color: var(--sage-dark);
}

/* Countdown */
.countdown {
  display: flex;
  justify-content: center;
  gap: clamp(0.9rem, 3vw, 2rem);
  margin: clamp(1.6rem, 4vw, 2.4rem) auto 0;
}
.cd-unit { display: flex; flex-direction: column; align-items: center; min-width: 3.2rem; }
.cd-num {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 1.4rem + 2.2vw, 3rem);
  line-height: 1;
  color: var(--bordeaux);
  font-variant-numeric: tabular-nums;
}
.cd-lbl {
  margin-top: 0.4rem;
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-dim);
}
.cd-unit + .cd-unit { position: relative; }
.cd-unit + .cd-unit::before {
  content: "·";
  position: absolute;
  left: calc(-1 * clamp(0.9rem, 3vw, 2rem) / 2);
  top: 0.1em;
  transform: translateX(-50%);
  color: var(--gold-dim);
  opacity: 0.5;
}

.eyebrow {
  font-size: 0.8rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold-dim);
  margin: 0 0 1rem;
}
/* Small type over the hero artwork: darkened for WCAG-safe contrast
   (gold-dim/sage-dark fall below 4.5:1 on the frosted cream panel). */
:is(.hero, #introCard) .eyebrow { color: #7d5f28; }
:is(.hero, #introCard) .hero-location { color: #62693f; }

.hero-names {
  font-size: clamp(2.6rem, 1.6rem + 6.5vw, 5.5rem);
  color: var(--burgundy-deep);
  line-height: 1.05;
}
.hero-names .amp {
  font-family: var(--font-script);
  color: var(--gold-dim);
  padding: 0 0.15em;
  font-size: 0.85em;
}

.hero-date {
  margin: 1.4rem 0 0;
  font-size: clamp(1rem, 0.9rem + 0.4vw, 1.25rem);
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

.hero-tagline {
  margin: 1.1rem auto 0;
  max-width: 520px;
  color: var(--ink-soft);
}

.scroll-cue {
  display: inline-flex;
  margin-top: clamp(2.5rem, 6vw, 4rem);
  width: 26px; height: 42px;
  border: 1.5px solid var(--gold-dim);
  border-radius: 999px;
  align-items: flex-start;
  justify-content: center;
  padding-top: 8px;
}
.scroll-cue span {
  width: 4px; height: 8px;
  border-radius: 999px;
  background: var(--gold-dim);
  animation: scrollcue 1.8s ease-in-out infinite;
}
@keyframes scrollcue {
  0% { transform: translateY(0); opacity: 1; }
  70% { transform: translateY(10px); opacity: 0; }
  100% { opacity: 0; }
}

/* ===========================================================
   REVEAL ANIMATION (scroll)
   =========================================================== */

.reveal { opacity: 0; transform: translateY(28px); }
.reveal.is-visible {
  animation: revealUp 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}
@keyframes revealUp {
  to { opacity: 1; transform: translateY(0); }
}

/* ===========================================================
   STORY
   =========================================================== */

/* The photos moved out to the rail above, so the prose runs full width —
   centred and measure-capped rather than stretched across the container. */
.story-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
  max-width: 760px;
  margin: clamp(2rem, 5vw, 3rem) auto 0;
}

.story-text p { margin: 0 0 1.1em; color: var(--ink-soft); }
.story-text p:last-child { margin-bottom: 0; }

/* ---- Horizontal photo rail (portrait shots) ----------------------------
   Native scroll + scroll-snap: touch swipe, trackpad and keyboard all work
   with no JS at all. main.js only adds pointer-drag and the arrow buttons,
   for mouse users who have neither. */
.photo-rail {
  position: relative;
  margin-bottom: clamp(0.5rem, 2vw, 1rem);
}
.rail-track {
  display: flex;
  gap: clamp(0.6rem, 1.6vw, 1rem);
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* old Edge */
}
.rail-track::-webkit-scrollbar { display: none; }
.rail-track.is-dragging { cursor: grabbing; scroll-behavior: auto; }
@media (hover: hover) { .rail-track { cursor: grab; } }

/* Portrait frames. The flex-basis is what decides how many are in view — the
   partial one at the edge is the point: it says "there is more". */
.rail-item {
  position: relative;
  flex: 0 0 62%;                  /* mobile: one and a half in view */
  scroll-snap-align: center;
  aspect-ratio: 3 / 4;
  border-radius: 6px;
  overflow: hidden;
  background: linear-gradient(155deg, var(--cream-dark), #e4d7bf);
  border: 1px solid rgba(92, 26, 38, 0.15);
}
@media (min-width: 640px) { .rail-item { flex-basis: 38%; } }
@media (min-width: 900px) { .rail-item { flex-basis: 27%; } }   /* ~3.5 in view */
@media (min-width: 1100px) { .rail-item { flex-basis: 25%; } }  /* ~4 in view */

/* The photo sits ON TOP of the placeholder: it is a static child while the
   placeholder is absolutely positioned, and positioned boxes paint last — so
   without this the caption would be stamped over the real photograph. */
.rail-item img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Seen only while the real file is missing: main.js drops the broken <img>,
   so no torn-image icon ever shows. */
.rail-ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--gold-dim);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
}
.rail-ph::before {
  content: "✿";
  margin-right: 0.45em;
  font-size: 1.4rem;
  color: var(--sage-dark);
}

/* Arrows reuse the carousel's own buttons — same design system, no new one.
   Pointer-only: on touch the swipe is the control.
   z-index is required, not decorative: .rail-item img carries z-index:1 (to
   win over the placeholder caption underneath it — see above), and the base
   .carousel-btn rule sets no z-index of its own (position:absolute defaults
   to z-index:auto). An explicit z-index:1 on an image with no intervening
   stacking-context ancestor wins over ANY z-index:auto sibling regardless of
   DOM order — so once real photos loaded, the buttons were painted first and
   then buried under every image in the strip. Anything meant to float above
   the rail needs a z-index that actually beats the images'. */
.photo-rail .carousel-btn {
  z-index: 2;
}
/* Sitting just outside the strip (in the page's own cream margin) was the
   real remaining bug, not distance: the button's fill is
   rgba(251,246,235,0.9) — the exact value of --cream — so out there it was
   cream-on-cream, invisible regardless of how far out it sat. Over a photo
   (like the venue carousel's buttons, 0.7rem in from its own edge) that same
   fill reads as a clear frosted disc against real colour. */
.photo-rail .carousel-btn.prev { left: 0.6rem; }
.photo-rail .carousel-btn.next { right: 0.6rem; }
@media (hover: none) {
  .photo-rail .carousel-btn { display: none; }
}

.photo-placeholder {
  aspect-ratio: 4 / 5;
  border-radius: 6px;
  background: linear-gradient(155deg, var(--cream-dark), #e4d7bf);
  border: 1px solid rgba(92,26,38,0.15);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  color: var(--gold-dim);
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.photo-placeholder .cam-icon { font-size: 1.8rem; color: var(--burgundy-soft); }

/* ===========================================================
   GALLERY
   =========================================================== */

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.8rem, 2vw, 1.4rem);
}
@media (min-width: 640px) { .gallery-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .gallery-grid { grid-template-columns: repeat(4, 1fr); } }
.gallery-grid .photo-placeholder { aspect-ratio: 1 / 1; }

/* ===========================================================
   SCHEDULE / TIMELINE
   =========================================================== */

.timeline {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: 640px;
  position: relative;
}
.timeline::before {
  content: "";
  position: absolute;
  left: 7px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: linear-gradient(var(--gold-dim), var(--gold-dim)) ;
  opacity: 0.35;
}
.timeline-item {
  position: relative;
  padding-left: 2.2rem;
  padding-bottom: clamp(1.8rem, 4vw, 2.6rem);
}
.timeline-item:last-child { padding-bottom: 0; }
.timeline-dot {
  position: absolute;
  left: 0; top: 6px;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--cream);
  border: 2px solid var(--gold-dim);
}
.timeline-time {
  display: block;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  color: var(--gold-dim);
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}
.timeline-content h3 { font-size: 1.25rem; margin-bottom: 0.35rem; }
.timeline-content p { margin: 0; color: var(--ink-soft); }

/* The ceremony's inner running order — a compact, time-labelled sub-list. */
.sub-flow {
  list-style: none;
  margin: 0.85rem 0 0;
  padding: 0.85rem 0 0;
  border-top: 1px solid rgba(168, 130, 63, 0.25);
  display: grid;
  gap: 0.55rem;
}
.sub-flow li {
  position: relative;
  padding-left: 4rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.4;
}
.sub-time {
  position: absolute;
  left: 0;
  top: 0.1em;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--gold-dim);
  font-variant-numeric: tabular-nums;
}

@media (min-width: 700px) {
  .timeline { max-width: 720px; }
  .timeline-item { padding-left: 2.6rem; }
}

/* ===========================================================
   VENUE
   =========================================================== */

.venue-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 4vw, 2.5rem);
}
@media (min-width: 768px) {
  .venue-grid { grid-template-columns: 1fr 1.2fr; align-items: stretch; }
}
.venue-info h3 { font-size: 1.5rem; margin-bottom: 0.6rem; }
.venue-info p { color: var(--ink-soft); margin: 0 0 0.6rem; }
.venue-note { font-style: italic; }
.venue-info .btn { margin-top: 1rem; }

.venue-map {
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid rgba(92,26,38,0.15);
  min-height: 280px;
}
.venue-map iframe { width: 100%; height: 100%; min-height: 280px; border: 0; }

/* ===========================================================
   TRAVEL
   =========================================================== */

.travel-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.2rem;
}
@media (min-width: 700px) { .travel-grid { grid-template-columns: repeat(3, 1fr); } }

.travel-card {
  background: var(--cream-dark);
  border: 1px solid rgba(92,26,38,0.12);
  border-radius: 8px;
  padding: 1.8rem 1.5rem;
  text-align: center;
}
.travel-card h3 { font-size: 1.15rem; margin-bottom: 0.6rem; color: var(--burgundy); }
.travel-card p { margin: 0; color: var(--ink-soft); font-size: 0.95rem; }

/* ===========================================================
   DRESS CODE
   =========================================================== */

.dresscode-intro {
  max-width: 680px;
  margin: 0 auto clamp(2rem, 5vw, 3rem);
  text-align: center;
  color: var(--ink-soft);
}

/* Two moments side by side (stacked on mobile), each its own card. */
.dresscode-moments {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.4rem, 4vw, 2.2rem);
  align-items: start;
}
@media (min-width: 768px) { .dresscode-moments { grid-template-columns: 1fr 1fr; } }

.dc-moment {
  background: var(--cream-dark);
  border: 1px solid rgba(92, 26, 38, 0.12);
  border-radius: 12px;
  padding: clamp(1.6rem, 3.5vw, 2.2rem);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
}
.dc-moment-day {
  font-family: var(--font-script);
  font-size: 1.4rem;
  color: var(--gold-dim);
  margin: 0 0 0.1rem;
}
.dc-moment-title { font-size: 1.45rem; margin-bottom: 0.9rem; }
.dc-moment-desc { color: var(--ink-soft); margin: 0 0 1.2rem; }

.dc-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.dc-chip {
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--burgundy);
  background: rgba(251, 246, 235, 0.7);
  border: 1px solid rgba(92, 26, 38, 0.2);
  border-radius: 999px;
  padding: 0.35em 1em;
}
.dresscode-moments .dresscode-sides { width: 100%; }

/* Single Pinterest button, centred beneath both moments. */
.dresscode-pin {
  margin-top: clamp(1.8rem, 4vw, 2.6rem);
  text-align: center;
}

.dresscode-palette {
  background: var(--cream-dark);
  border-radius: 10px;
  padding: 2rem 1.5rem;
  text-align: center;
}
.palette-label {
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-dim);
  margin: 0 0 1.1rem;
}
.swatches { display: flex; justify-content: center; gap: 0.7rem; flex-wrap: wrap; }
.swatch {
  width: 42px; height: 42px;
  border-radius: 50%;
  background: var(--sw);
  border: 3px solid var(--cream);
  box-shadow: 0 0 0 1px rgba(92,26,38,0.2), 0 4px 8px rgba(0,0,0,0.12);
}

/* ===========================================================
   FOOTER
   =========================================================== */

.footer {
  background: var(--burgundy-deep);
  color: var(--cream-dark);
  text-align: center;
  padding: clamp(3.5rem, 8vw, 5.5rem) var(--gutter) clamp(2.5rem, 5vw, 3.5rem);
}
.footer-names { font-family: var(--font-script); font-size: clamp(1.8rem, 1.4rem + 2vw, 2.6rem); margin: 0; color: var(--cream); }
.footer-date { margin: 0.3rem 0 1.6rem; letter-spacing: 0.08em; opacity: 0.8; }
.footer-rsvp { margin: 0 0 0.3rem; opacity: 0.9; }
.footer-contact { margin: 0 0 2rem; color: var(--gold-light); letter-spacing: 0.03em; }
.footer-credit { font-size: 0.8rem; opacity: 0.55; margin: 0; }

/* Agency credit — set apart from the couple's message by a hairline rule so
   it reads as a business signature, not part of the wedding copy. */
.footer-company {
  margin-top: clamp(2rem, 5vw, 3rem);
  padding-top: clamp(1.4rem, 3vw, 2rem);
  border-top: 1px solid rgba(251, 246, 235, 0.15);
}
.footer-brand {
  margin: 0;
  font-size: 0.9rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-light);
}
.footer-brand .tm { font-size: 0.62em; vertical-align: super; letter-spacing: 0; }
.footer-email { margin: 0.4rem 0 0; font-size: 0.82rem; opacity: 0.75; }
.footer-email a { color: inherit; border-bottom: 1px solid rgba(232, 212, 160, 0.4); }
.footer-email a:hover { color: var(--cream); }

/* ===========================================================
   PHOTO SLOTS (drop-in image fallback)
   =========================================================== */

.photo-slot {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: 6px;
  background: linear-gradient(155deg, var(--cream-dark), #e4d7bf);
  border: 1px solid rgba(92,26,38,0.15);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: var(--gold-dim);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: lowercase;
  overflow: hidden;
}
.photo-slot .cam-icon { font-size: 1.6rem; color: var(--sage-dark); }
.photo-slot.has-img {
  background-size: cover;
  background-position: center;
  border-color: rgba(92,26,38,0.18);
}
.photo-slot.has-img .cam-icon,
.photo-slot.has-img span { display: none; }

/* ===========================================================
   VENUE
   =========================================================== */

.venue-lede {
  max-width: 720px;
  margin: 0 auto clamp(2rem, 5vw, 3rem);
  text-align: center;
  color: var(--ink-soft);
  font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem);
}
.venue-foot { text-align: center; margin-top: clamp(1.8rem, 4vw, 2.5rem); }
.venue-address { color: var(--ink-soft); margin: 0 0 1.1rem; letter-spacing: 0.02em; }

/* ===========================================================
   CAROUSEL
   =========================================================== */

.carousel { position: relative; max-width: 860px; margin: 0 auto; }
.carousel-viewport { overflow: hidden; border-radius: 8px; border: 1px solid rgba(92,26,38,0.15); }
.carousel-track {
  list-style: none;
  margin: 0; padding: 0;
  display: flex;
  transition: transform 0.55s cubic-bezier(0.6, 0, 0.2, 1);
}
.carousel-slide { flex: 0 0 100%; }
.carousel-slide .photo-slot {
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: 0;
}
.carousel-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px; height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(251, 246, 235, 0.9);
  color: var(--burgundy);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(61,15,24,0.18);
  transition: background 0.2s ease, transform 0.2s ease;
  display: flex; align-items: center; justify-content: center;
  padding-bottom: 3px;
}
.carousel-btn:hover { background: var(--cream); transform: translateY(-50%) scale(1.06); }
.carousel-btn.prev { left: 0.7rem; }
.carousel-btn.next { right: 0.7rem; }
.carousel-dots { display: flex; justify-content: center; gap: 0.5rem; margin-top: 1rem; }
.carousel-dots button {
  width: 9px; height: 9px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: var(--sand);
  cursor: pointer;
  transition: background 0.2s ease, transform 0.2s ease;
}
.carousel-dots button.is-active { background: var(--sage-dark); transform: scale(1.25); }

/* ===========================================================
   ACCOMMODATIONS
   =========================================================== */

.stay-lede {
  max-width: 680px;
  margin: 0 auto clamp(1.6rem, 4vw, 2.2rem);
  text-align: center;
  color: var(--ink-soft);
}
.deadline-callout {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  max-width: 340px;
  margin: 0 auto clamp(2rem, 5vw, 3rem);
  padding: 1.1rem 1.5rem;
  border: 1.5px solid var(--sage);
  border-radius: 10px;
  background: rgba(162, 171, 139, 0.12);
  text-align: center;
}
.deadline-label {
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage-dark);
}
.deadline-date {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 1.1rem + 1vw, 1.7rem);
  color: var(--bordeaux);
}
/* One card now, so it is centred on its own rather than sitting left as if a
   second one had gone missing. */
.stay-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.4rem;
  max-width: 460px;
  margin: 0 auto;
}
.stay-card {
  background: var(--cream);
  border: 1px solid rgba(92,26,38,0.14);
  border-radius: 10px;
  padding: 1.8rem 1.6rem;
  text-align: center;
}
.stay-card h3 { font-size: 1.25rem; margin-bottom: 0.6rem; color: var(--burgundy); }
.stay-card p { color: var(--ink-soft); margin: 0 0 1.3rem; font-size: 0.95rem; }
.stay-note { text-align: center; margin: 1.6rem 0 0; font-style: italic; color: var(--ink-soft); font-size: 0.92rem; }

/* ===========================================================
   SCHEDULE DAY TABS
   =========================================================== */

.day-tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin: 0 auto clamp(2.2rem, 5vw, 3.2rem);
}
.day-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.7rem 1.4rem;
  background: transparent;
  border: 1.5px solid rgba(92,26,38,0.2);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
  color: var(--ink-soft);
  font-family: var(--font-body);
}
.day-tab .day-num { font-family: var(--font-display); font-size: 1.05rem; color: var(--burgundy); }
.day-tab .day-name { font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; }
.day-tab:hover { border-color: var(--sage); }
.day-tab.is-active { background: var(--burgundy); border-color: var(--burgundy); }
.day-tab.is-active .day-num, .day-tab.is-active .day-name { color: var(--cream); }

.day-panel { display: none; }
.day-panel.is-active { display: block; animation: revealUp 0.6s cubic-bezier(0.2,0.7,0.2,1) both; }

/* ===========================================================
   TRAVEL — TIPS & MAP
   =========================================================== */

.travel-lower {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  margin-top: clamp(2rem, 5vw, 3rem);
  align-items: start;
}
@media (min-width: 860px) { .travel-lower { grid-template-columns: 1.1fr 1fr; } }
.tips {
  background: var(--cream-dark);
  border: 1px solid rgba(92,26,38,0.12);
  border-radius: 10px;
  padding: 1.8rem 1.8rem;
}
.tips-title { font-size: 1.25rem; margin-bottom: 1rem; color: var(--burgundy); }
.tips-list { list-style: none; margin: 0; padding: 0; }
.tips-list li { position: relative; padding-left: 1.4rem; margin-bottom: 0.9rem; color: var(--ink-soft); font-size: 0.96rem; }
.tips-list li:last-child { margin-bottom: 0; }
.tips-list li::before { content: "✿"; position: absolute; left: 0; top: 0.05em; color: var(--sage-dark); font-size: 0.85rem; }
.tips-list strong { color: var(--ink); }
.map-caption { margin: 0.7rem 0 0; text-align: center; font-size: 0.85rem; color: var(--ink-soft); }

/* ===========================================================
   THE MENU
   =========================================================== */

.menu-card {
  max-width: 720px;
  margin: 0 auto;
  background: var(--cream);
  border: 1px solid rgba(92,26,38,0.14);
  border-radius: 12px;
  padding: clamp(1.8rem, 4vw, 2.6rem);
  text-align: center;
}
.menu-card > p { color: var(--ink-soft); margin: 0 0 1.4rem; }
.menu-points { list-style: none; margin: 0 0 1.4rem; padding: 0; display: grid; gap: 0.9rem; text-align: left; }
.menu-points li { color: var(--ink-soft); font-size: 0.96rem; display: flex; gap: 0.7rem; align-items: baseline; flex-wrap: wrap; }
.menu-badge {
  flex: none;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sage-dark);
  background: rgba(162,171,139,0.16);
  border: 1px solid rgba(162,171,139,0.5);
  border-radius: 999px;
  padding: 0.2em 0.8em;
}
.menu-note { margin: 0; font-style: italic; color: var(--ink-soft); font-size: 0.92rem; }

/* ===========================================================
   DRESS CODE — SIDES
   =========================================================== */

.dresscode-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.side-card {
  border-radius: 10px;
  padding: 1.8rem 1rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
/* Palette swapped: bride's side now green, groom's side now pink. */
.side-bride { background: rgba(162,171,139,0.22); }
.side-groom { background: var(--pink-soft); }
.side-swatch {
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--sw);
  border: 3px solid var(--cream);
  box-shadow: 0 0 0 1px rgba(92,26,38,0.15), 0 4px 8px rgba(0,0,0,0.1);
}
.side-label { font-family: var(--font-display); font-size: 1.05rem; color: var(--burgundy-deep); }
.side-color { font-size: 0.78rem; letter-spacing: 0.08em; color: var(--ink-soft); text-transform: uppercase; }

/* ===========================================================
   RSVP
   =========================================================== */

.rsvp { text-align: center; }
.rsvp-inner { max-width: 620px; margin: 0 auto; }
.rsvp-inner h2 { font-size: clamp(1.8rem, 1.4rem + 1.6vw, 2.6rem); margin-bottom: 1rem; }
.rsvp-text { color: var(--ink-soft); margin: 0 auto 2rem; max-width: 520px; }
.rsvp-btn { font-size: 1.05rem; padding: 1em 2.6em; }
.rsvp-deadline { margin: 1.6rem 0 2rem; letter-spacing: 0.04em; color: var(--bordeaux); }
.rsvp-fallback { margin: 1.8rem 0 0; font-size: 0.92rem; color: var(--ink-soft); }
.rsvp-fallback a { color: var(--sage-dark); border-bottom: 1px solid currentColor; }

/* ---- RSVP collapsible panel ---- */
.rsvp-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s ease;
}

/* ---- RSVP form ---- */
.rsvp-form {
  text-align: left;
  max-width: 640px;
  margin: clamp(2rem, 5vw, 2.8rem) auto 0;
}
.rsvp-bot-field { position: absolute; left: -9999px; }
.rsvp-form fieldset { border: none; margin: 0 0 clamp(2rem, 5vw, 2.6rem); padding: 0; }
.rsvp-form legend {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--burgundy);
  margin: 0 0 1.1rem;
  padding: 0;
  width: 100%;
  text-align: center;
}
.req { color: var(--bordeaux); margin-left: 0.15em; }
.field-question { margin: 0 0 0.9rem; text-align: center; color: var(--ink); }

.field-grid { display: grid; grid-template-columns: 1fr; gap: 1.1rem; }
@media (min-width: 640px) { .field-grid.cols-2 { grid-template-columns: 1fr 1fr; } }

.field { display: flex; flex-direction: column; gap: 0.4rem; }
.field label {
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sage-dark);
}
.field input[type="text"],
.field input[type="email"],
.field input[type="tel"] {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  padding: 0.75em 1em;
  border: 1.5px solid rgba(92, 26, 38, 0.2);
  border-radius: 8px;
  background: var(--cream);
  transition: border-color 0.25s ease;
}
.field input:focus { outline: none; border-color: var(--burgundy); }
.field-hint { margin: 0; font-size: 0.78rem; font-style: italic; color: var(--ink-soft); text-transform: none; letter-spacing: normal; }
.field-other { max-width: 360px; margin: 1.2rem auto 0; }

.choice-group { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
.choice-group input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.65em 1.4em;
  border: 1.5px solid rgba(92, 26, 38, 0.2);
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.92rem;
  color: var(--ink-soft);
  transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.choice-pill:hover { border-color: var(--sage); }
.choice-group input:checked + .choice-pill { background: var(--burgundy); border-color: var(--burgundy); color: var(--cream); }
.choice-group input:focus-visible + .choice-pill { outline: 2px solid var(--gold); outline-offset: 2px; }

.rsvp-declined-note { text-align: center; font-style: italic; color: var(--ink-soft); margin: 0 0 2rem; }
.rsvp-error { text-align: center; color: var(--bordeaux); font-weight: 600; font-size: 0.95rem; margin: 0 0 1.2rem; }

.rsvp-form .rsvp-btn { display: block; margin: 0 auto; }

.rsvp-success {
  max-width: 480px;
  margin: clamp(2rem, 5vw, 2.8rem) auto 0;
  padding: 1.6rem;
  border: 1.5px solid var(--sage);
  border-radius: 10px;
  background: rgba(162, 171, 139, 0.12);
  text-align: center;
}
.rsvp-success p { margin: 0; font-family: var(--font-display); font-size: 1.15rem; color: var(--burgundy-deep); }

/* ===========================================================
   FAQ
   =========================================================== */

.faq-list { list-style: none; margin: 0 auto; padding: 0; max-width: 760px; }
.faq-item { border-bottom: 1px solid rgba(92,26,38,0.15); }
.faq-q {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
  padding: 1.2rem 2.4rem 1.2rem 0;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem);
  color: var(--burgundy-deep);
  position: relative;
}
.faq-mark { position: absolute; right: 0.2rem; top: 50%; width: 14px; height: 14px; transform: translateY(-50%); }
.faq-mark::before, .faq-mark::after {
  content: ""; position: absolute; background: var(--gold-dim); border-radius: 2px;
  left: 50%; top: 50%;
}
.faq-mark::before { width: 14px; height: 2px; transform: translate(-50%, -50%); }
.faq-mark::after { width: 2px; height: 14px; transform: translate(-50%, -50%); transition: transform 0.3s ease, opacity 0.3s ease; }
.faq-q[aria-expanded="true"] .faq-mark::after { transform: translate(-50%, -50%) scaleY(0); opacity: 0; }
.faq-a {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.35s ease;
}
.faq-a p { margin: 0 0 1.2rem; color: var(--ink-soft); }
.faq-a a { color: var(--sage-dark); border-bottom: 1px solid currentColor; }

.footer-btn { margin: 0.4rem 0 1.8rem; border-color: var(--cream-dark); color: var(--cream-dark); }
.footer-btn:hover { background: var(--cream); color: var(--burgundy-deep); border-color: var(--cream); }

/* ===========================================================
   REDUCED MOTION
   =========================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { animation: none !important; opacity: 1 !important; transform: none !important; }
  .scroll-cue span { animation: none; }
  .carousel-track { transition: none; }
  .day-panel.is-active { animation: none; }
}
