/* ============================================================================
   AMANDA & MATTIA — WEDDING WEBSITE
   Design system: essentially monochromatic — warm ivory/cream backgrounds
   with a single deep burgundy carried through at different tonal values
   (dark, primary, muted, light, pale, whisper). No sage, no gold, no peach.
   Editorial, romantic, minimal. Mobile-first.
   ============================================================================ */

/* ---------- Fonts ----------------------------------------------------------
   Loaded via <link> tags in the <head> of templates/page.js (faster than an
   @import here, since the browser can start fetching the font CSS before it
   finishes downloading this stylesheet). See index.html <head> for the URL.
   ---------------------------------------------------------------------- */

/* ---------- Design tokens -------------------------------------------------
   Retuned to match the couple's printed wedding stationery (invitation,
   details card, save-the-date): a warmer blush-ivory paper tone, a slightly
   deeper "antique ink" burgundy, and a formal calligraphic script for
   headline moments in place of the earlier, more casual script.
   ---------------------------------------------------------------------- */
:root {
  /* One burgundy, six tonal steps — every accent, border, and secondary
     background on the site derives from this single hue rather than an
     independent color choice (no sage, no gold, no peach/tan/blush). */
  --color-burgundy-dark: #40121a;   /* darkest — solid backgrounds, hover/active fills */
  --color-burgundy-text: #7b4a57;   /* softer wine burgundy — headings & body text on cream */
  --color-burgundy: #6a1c28;        /* primary — buttons, kickers, links */
  --color-burgundy-mid: #8a3444;    /* medium muted — secondary/italic labels */
  --color-burgundy-light: #a9707a;  /* light — dividers, accents on dark bg */
  --color-burgundy-pale: #e9d6c8;   /* pale — alternate section backgrounds */
  --color-burgundy-whisper: #f2e8df; /* barely-there — subtle washes/hovers */
  --color-ivory: #f6ece2;
  --color-cream: #f0e0d0;
  --color-ink: #2a2018;
  --color-ink-soft: #55463c;
  --color-line: rgba(64, 18, 26, 0.16);
  --color-white: #fffdf9;

  --font-display: "Playfair Display", "Iowan Old Style", Georgia, serif;
  --font-body: "Cormorant Garamond", Georgia, serif;
  --font-script: "Mrs Saint Delafield", "Parisienne", cursive;

  --container-max: 1120px;
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;
  --space-6: 6rem;

  --radius: 2px;
  --shadow-card: 0 12px 32px -18px rgba(42, 20, 24, 0.35);
  --transition: 420ms cubic-bezier(0.22, 0.61, 0.36, 1);

  /* The fixed nav's tallest (non-scrolled) rendered height — used as the
     `top` offset for the scroll-stack sections further down, so a sticky
     section/cover settles just beneath the nav instead of tucking its top
     edge underneath it (the nav's own scrolled/"solid" state is a few
     pixels shorter, so this is deliberately the larger of the two). */
  --header-height: 78px;
}

/* ---------- Reset ---------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  background: var(--color-ivory);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 21px;
  line-height: 1.7;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
ul { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4, p { margin: 0; }

.container {
  width: 100%;
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 1.5rem;
}
@media (min-width: 640px) {
  .container { padding: 0 2.5rem; }
}

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

.skip-link {
  position: absolute; left: 1rem; top: -60px;
  background: var(--color-burgundy); color: var(--color-white);
  padding: 0.75rem 1.25rem; z-index: 200; transition: top var(--transition);
  font-family: var(--font-body); letter-spacing: 0.04em;
}
.skip-link:focus { top: 1rem; }

/* ---------- Photo framing ---------------------------------------------------
   Every photograph on the site gets the same thin, quiet burgundy hairline
   — `--photo-frame` — so photos read as deliberately presented (like a
   mounted print) rather than floating loose against the cream page. Always
   this one value: 1px, always this tone. Never thicker, never doubled,
   never ornamented — the photo stays the focus, this just gives it an
   edge. Applied per-component below (search "--photo-frame" or
   "var(--photo-frame)") rather than a blanket `img` selector, since a few
   images (the hero backdrop, the monogram) are deliberately borderless. */
:root { --photo-frame: 1px solid var(--color-burgundy-light); }

/* ---------- Typography ----------------------------------------------------- */
.kicker {
  display: block;
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  margin-bottom: 0.9rem;
}

.section-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2rem, 4.5vw, 2.9rem);
  color: var(--color-burgundy-text);
  letter-spacing: 0.01em;
}

.script-accent {
  font-family: var(--font-script);
  font-weight: 400;
  color: var(--color-burgundy);
  line-height: 1;
}

.section-intro {
  font-size: 1.2rem;
  color: var(--color-ink-soft);
  max-width: 46em;
  margin-top: 1rem;
}

.section-head {
  text-align: center;
  max-width: 640px;
  margin: 0 auto var(--space-4);
}

.divider {
  width: 64px;
  height: 1px;
  background: var(--color-burgundy-light);
  margin: 1.5rem auto;
  border: none;
}
.divider--left { margin-left: 0; }

/* Flourish divider (line–dot–diamond–dot–line), echoing the ornament under
   "Details" on the invitation suite. Used sparingly, under major headings. */
.flourish-divider {
  width: 170px;
  margin: 1.4rem auto;
  color: var(--color-burgundy);
}
.flourish-divider svg { width: 100%; height: auto; display: block; }
.section--dark .flourish-divider { color: var(--color-burgundy-light); }


/* ---------- Buttons ---------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.95rem 2.1rem;
  min-height: 48px;
  border: 1px solid var(--color-burgundy);
  background: transparent;
  color: var(--color-burgundy-text);
  font-family: var(--font-body);
  font-size: 1.05rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-radius: var(--radius);
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.btn:hover, .btn:focus-visible { background: var(--color-burgundy); color: var(--color-white); }

.btn--solid {
  background: var(--color-burgundy);
  color: var(--color-white);
}
.btn--solid:hover, .btn--solid:focus-visible {
  background: var(--color-burgundy-dark);
  border-color: var(--color-burgundy-dark);
}

.btn--ghost {
  border-color: rgba(250, 246, 238, 0.6);
  color: var(--color-white);
}
.btn--ghost:hover, .btn--ghost:focus-visible {
  background: var(--color-white);
  color: var(--color-burgundy-text);
}

.btn:disabled { opacity: 0.6; cursor: not-allowed; }

/* Quiet, text-only variant — used where a full outlined button would feel
   too prominent (e.g. "Add to Calendar" tucked under the Events intro). */
.btn--text {
  border: none;
  background: none;
  padding: 0.4rem 0.2rem;
  min-height: auto;
  color: var(--color-burgundy);
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-color: rgba(106, 28, 40, 0.4);
  margin-top: 1.5rem;
}
.btn--text:hover, .btn--text:focus-visible {
  background: none;
  color: var(--color-burgundy-text);
  text-decoration-color: currentColor;
}

/* Focus visibility for accessibility */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, summary:focus-visible {
  outline: 2px solid var(--color-burgundy);
  outline-offset: 3px;
}

/* ---------- Header / Nav ------------------------------------------------ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding: 1.1rem 0;
  transition: background var(--transition), box-shadow var(--transition), padding var(--transition);
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* The nav needs more breathing room than a reading-width content column
     (nine links, some long in Italian — "Le Nostre Famiglie", "Il Corteo
     Nuziale"), so the header alone is allowed a wider container. */
  max-width: 1400px;
}
.site-header.is-solid {
  /* Solid (not blurred) on purpose: backdrop-filter on this element would
     create a CSS containing block for the fixed-position .site-nav overlay
     inside it, breaking its full-viewport sizing. Keep filter/backdrop-filter
     off .site-header, or move .site-nav outside it, if revisiting this. */
  background: rgba(250, 246, 238, 0.97);
  box-shadow: 0 1px 0 var(--color-line);
  padding: 0.7rem 0;
}

.brand {
  font-family: var(--font-script);
  font-size: 1.6rem;
  color: var(--color-burgundy-text);
  transition: color var(--transition);
  white-space: nowrap;
}

.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  padding: 10px;
  margin: -10px;
  z-index: 110;
}
.nav-toggle span {
  width: 24px; height: 1.5px;
  background: var(--color-burgundy-dark);
  transition: background var(--transition), transform var(--transition), opacity var(--transition);
}
.site-header.nav-open .nav-toggle span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.site-header.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
.site-header.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.site-nav {
  position: fixed;
  inset: 0;
  background: var(--color-ivory);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2rem;
  transform: translateY(-100%);
  transition: transform var(--transition);
  z-index: 105;
}
.site-header.nav-open .site-nav { transform: translateY(0); }

.site-nav__links {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.6rem;
}
.site-nav__links a {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--color-burgundy-text);
  position: relative;
}
.site-nav__links a::after {
  content: "";
  position: absolute; left: 0; bottom: -4px; height: 1px; width: 0;
  background: var(--color-burgundy-mid);
  transition: width var(--transition);
}
.site-nav__links a:hover::after, .site-nav__links a:focus-visible::after { width: 100%; }

.lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-body);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
}
.lang-toggle a {
  padding: 0.3rem 0.55rem;
  color: var(--color-burgundy-text);
  opacity: 0.75;
  transition: opacity var(--transition), color var(--transition);
}
.lang-toggle a[aria-current="true"] { opacity: 1; font-weight: 600; text-decoration: underline; text-underline-offset: 4px; }
.lang-toggle a:not([aria-current="true"]):hover { opacity: 1; }
.lang-toggle span { color: var(--color-line); }

.header-right { display: flex; align-items: center; gap: 1.25rem; }

.lang-toggle--mobile { margin-top: 0.5rem; }
.lang-toggle--mobile a { color: var(--color-burgundy-text) !important; font-size: 1.15rem; }
.lang-toggle--mobile span { color: var(--color-line) !important; }

/* The guest-facing nav now carries nine links (Home, Our Story, Our
   Families, Wedding Party, Events, Stay, Travel, RSVP, FAQ) plus the
   EN·IT switch. Rather than compress that onto one crowded line at a
   modest width, the elegant full-screen mobile menu is kept all the way
   up to 1100px, and the inline row only appears once there is genuinely
   room for it to breathe. */
@media (min-width: 1100px) {
  .lang-toggle--mobile { display: none; }
  .nav-toggle { display: none; }
  .site-nav {
    position: static;
    inset: auto;
    background: none;
    transform: none;
    flex-direction: row;
    gap: 0;
  }
  .site-nav__links {
    flex-direction: row;
    flex-wrap: nowrap;
    gap: 0.85rem;
  }
  .site-nav__links a { font-size: 0.76rem; font-family: var(--font-body); letter-spacing: 0.015em; text-transform: uppercase; color: var(--color-ink); white-space: nowrap; }
}
@media (min-width: 1500px) {
  .site-nav__links { gap: 1.4rem; }
  .site-nav__links a { font-size: 0.9rem; letter-spacing: 0.03em; }
}

/* ---------- Hero --------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--color-ink);
  overflow: hidden;
  /* Luminous, light fallback in case the SVG art doesn't render — no
     burgundy wash, burgundy is reserved for the type and UI on top. */
  background: linear-gradient(180deg, #cdd8d8 0%, #e4d9ca 40%, #f2e7d7 72%, #f7ede0 100%);
}
.hero__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}
/* The couple's own commissioned Lake Como watercolor — used exactly as
   supplied, never recolored or reinterpreted. object-fit:cover only ever
   changes which *window* into the artwork is visible at a given screen
   size (via object-position below); the image file itself is untouched.
   Art-directed per breakpoint rather than one center-crop for every size:
   mobile keeps the villa + a slice of lake in frame (a portrait viewport
   would otherwise crop it out entirely), tablet eases toward center, and
   desktop shows most of the full composition — villa, lake, mountains,
   and the town across the water. */
.hero__art-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 34% 42%;
  display: block;
}
@media (min-width: 640px) {
  .hero__art-img { object-position: 28% 40%; }
}
@media (min-width: 1024px) {
  .hero__art-img { object-position: 50% 38%; }
}
.hero__scrim {
  /* A soft, warm cream glow behind the type for legibility over the light
     watercolor — not a dark overlay, so the artwork's own colors show
     through undimmed everywhere except immediately behind the type. */
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 62% 48% at 50% 42%, rgba(255,251,244,0.82) 0%, rgba(255,251,244,0.5) 42%, rgba(255,251,244,0) 74%);
  z-index: 1;
}
.hero__content {
  position: relative;
  z-index: 2;
  padding: 7rem 1.5rem 4rem;
  max-width: 760px;
}
.hero__eyebrow {
  font-family: var(--font-body);
  font-weight: 600;
  font-style: normal;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-size: 0.92rem;
  color: var(--color-burgundy);
  margin-bottom: 1.25rem;
}
.hero__names {
  font-family: var(--font-script);
  font-size: clamp(3.4rem, 13vw, 6.5rem);
  line-height: 1.05;
  color: var(--color-burgundy-text);
  margin-bottom: 1.25rem;
  text-shadow: 0 2px 28px rgba(255,253,249,0.5);
}
.hero__meta {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 2.4vw, 1.4rem);
  letter-spacing: 0.06em;
  color: var(--color-ink);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.hero__meta .sep { display: block; }

/* ---------- Sections ------------------------------------------------------ */
.section { padding: var(--space-6) 0; position: relative; }
.section--tint { background: var(--color-cream); }
.section--pale { background: var(--color-burgundy-pale); }
.section--dark {
  /* A dark charcoal-ink night, not a burgundy wash — burgundy stays an
     accent rather than a dominant field color, even for this one darker
     section (Wedding Transportation). */
  background: var(--color-ink);
  color: var(--color-ivory);
}
.section--dark .section-title { color: var(--color-white); }
.section--dark .kicker { color: var(--color-burgundy-light); }
.section--dark .section-intro { color: rgba(250,246,238,0.82); }

/* ---------- Scroll-stack effect (desktop, motion-safe only) ---------------
   Applied to four "chapter" sections — Our Families, Accommodations,
   Travel, RSVP — so each one feels like a page of an elegant wedding
   book: it holds in place as the next chapter's page rises and settles
   over it, rather than simply scrolling away underneath. Built with plain
   `position: sticky` + ascending `z-index` — no JS, no scroll-jacking.

   Each of these sections is short enough (well under ~1.5 screens) that
   making the entire section sticky and letting the *next* section's page
   slide up over it reads as a clean page-turn with no stuck-feeling pause.
   Applied to the section's own `.container` rather than the `<section>`
   element itself — a sticky element's release point is bounded by its
   *parent's* box, and `.container`'s parent is that one `<section>`
   alone, so it releases exactly at that section's own end rather than
   reaching toward the end of the whole page. The section's own vertical
   padding is transferred onto the sticky element too, so the solid "page"
   includes that breathing room instead of leaving a gap that lets the
   next layer show through early.

   Wedding Party and Events deliberately sit outside the stack (along with
   Welcome and Wedding Transportation) — both run to several screens of
   photos and portraits, and stacking them was found to feel like too long
   a pause, so they were reverted to plain scrolling. Our Story sits
   outside it too (redesigned 2026-08-27 into a centered kicker/title +
   the full, uncropped original photograph + a "Read Our Story" link that
   opens the complete narrative in its own full-screen overlay — see
   .our-story__photo and .story-overlay in this file): a viewport-height
   sticky container is exactly the kind of constraint that risks visually
   clipping "the entire photograph, uncropped," so this section stays
   plain, ordinary scrolling on principle, not just because of its height.
   The z-index ladder below is intentionally non-contiguous (2, 5, 6, 7)
   as a result — it only needs to stay ascending in document order, not
   consecutive.

   Gated behind `prefers-reduced-motion: no-preference` and a desktop-width
   check — this style of movement is skipped entirely (falling back to
   normal document scrolling) on touch/narrow viewports and for anyone who
   has asked their OS for less motion. */
@media (prefers-reduced-motion: no-preference) and (min-width: 900px) {
  #our-families > .container,
  #stay > .container,
  #travel > .container,
  #rsvp > .container {
    position: sticky;
    top: var(--header-height);
  }
  #our-families > .container {
    z-index: 2;
    background: var(--color-cream);
    padding-top: var(--space-6);
    padding-bottom: var(--space-6);
  }
  #stay > .container {
    z-index: 5;
    background: var(--color-burgundy-pale);
    padding-top: var(--space-6);
    padding-bottom: var(--space-6);
  }
  #travel > .container {
    z-index: 6;
    background: var(--color-ivory);
    padding-top: var(--space-6);
    padding-bottom: var(--space-6);
  }
  #rsvp > .container {
    z-index: 7;
    background: var(--color-cream);
    padding-top: var(--space-6);
    padding-bottom: var(--space-6);
  }
  /* The section's own padding is now redundant with the padding just added
     to its sticky `.container` above — dropped here so spacing isn't
     doubled. */
  #our-families,
  #stay,
  #travel,
  #rsvp {
    padding-top: 0;
    padding-bottom: 0;
  }
}

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 900ms ease, transform 900ms ease;
}
/* `transform: none` rather than `translateY(0)` once revealed — an active
   transform value (even a zero one) makes an ancestor a new containing
   block, which silently breaks `position: sticky` on any descendant. Any
   of the major sections below can be `position: sticky` (see the
   scroll-stack rules further down), so this matters sitewide, not just
   locally. Transitions between translateY(24px) and none interpolate
   exactly the same as translateY(0) in every browser. */
.reveal.is-visible { opacity: 1; transform: none; }

/* ---------- Welcome ------------------------------------------------------- */
.welcome { text-align: center; max-width: 720px; margin: 0 auto; }
.welcome p { font-size: 1.45rem; margin-bottom: 1.4rem; color: var(--color-ink-soft); }
.welcome .signature {
  font-family: var(--font-script);
  font-size: 2.4rem;
  color: var(--color-burgundy);
  margin-top: 1.5rem;
}

/* ---------- Events: photography-led venue features -------------------------
   Replaces the old white "information card" pattern. Each moment (Welcome
   Dinner, Ceremony, Reception) is real venue photography plus an oversized
   venue name and restrained typographic facts underneath — the photograph
   is part of the page composition, not something placed inside a box. */
.events-groups { display: flex; flex-direction: column; gap: var(--space-6); }

/* Each event day is its own "chapter," led by an oversized date rather
   than a small italic label — the two dates are meant to carry visual
   weight, not read as a generic "weekend" banner. */
.event-chapter__head { text-align: center; margin-bottom: var(--space-4); }
.event-chapter__day {
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  font-size: 1.05rem;
  color: var(--color-burgundy);
  margin-bottom: 0.5rem;
}
.event-chapter__date {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.4rem, 6vw, 3.6rem);
  color: var(--color-burgundy-text);
  letter-spacing: 0.02em;
}
.event-chapter__date-sep {
  display: inline-block;
  margin: 0 0.3em;
  color: var(--color-burgundy-light);
  font-size: 0.55em;
  vertical-align: middle;
}
/* The event's own title ("The Welcome Dinner" / "Wedding Day") — a step
   below the oversized date above it, but a clear "medium" tier of its
   own: serif display type (matching venue names/section titles rather
   than a small italic caption), not the sitewide small-caps `.kicker`
   treatment used for sub-labels like "The Ceremony"/"The Reception". */
.event-chapter__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.7rem, 3.4vw, 2.15rem);
  color: var(--color-burgundy-text);
  letter-spacing: 0.005em;
  margin-top: 0.7rem;
}

.event-chapter__followedby {
  text-align: center;
  font-family: var(--font-body);
  font-style: italic;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 1rem;
  color: var(--color-burgundy-mid);
  margin: var(--space-4) 0;
}
.event-chapter__followedby span { position: relative; display: inline-block; padding: 0 1.1rem; }
.event-chapter__followedby span::before,
.event-chapter__followedby span::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 26px;
  height: 1px;
  background: var(--color-line);
}
.event-chapter__followedby span::before { right: 100%; }
.event-chapter__followedby span::after { left: 100%; }

/* The venue name and details always introduce the photograph — content
   block first, photograph(s) beneath — rather than photos with text
   layered on or beside them. Every venue feature shares this shape;
   `--large` widens it, `--full` (Villa Erba) lets the photograph itself
   run nearly the full content width for one dramatic, cinematic moment
   while the text above stays at a comfortable reading width. */
.venue-feature {
  max-width: 620px;
  margin: 0 auto;
  text-align: center;
}
.venue-feature--large { max-width: 760px; }
.venue-feature--full { max-width: none; }
/* 700px rather than the standard 640px section-head width — at 640px the
   Welcome Dinner's description ("...as we welcome everyone to Lake
   Como.") wrapped its last word ("Como.") onto its own orphaned line;
   700px lets it sit on one full line instead, with no font-size change.
   Applies to all three venueFeature--full instances (Welcome Dinner,
   Ceremony, Reception) for consistency — the Ceremony/Reception
   descriptions already fit comfortably at this width too. */
.venue-feature--full .venue-feature__content { max-width: 700px; margin-left: auto; margin-right: auto; }
.venue-feature__content { margin-bottom: var(--space-4); }
.venue-feature__venue {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.9rem, 4vw, 2.6rem);
  color: var(--color-burgundy-text);
  margin: 0.4rem 0 0.2rem;
  letter-spacing: 0.005em;
}
.venue-feature--large .venue-feature__venue { font-size: clamp(2.2rem, 5vw, 3.1rem); }
.venue-feature__location { font-family: var(--font-body); font-style: italic; font-size: 1.35rem; color: var(--color-ink-soft); margin-bottom: 0.9rem; }
.venue-feature__facts {
  display: grid;
  gap: 0.55rem;
  max-width: 420px;
  margin: 0 auto 1.1rem;
  border-top: 1px solid var(--color-line);
  padding-top: 1rem;
  text-align: left;
}
.venue-feature__fact { display: flex; justify-content: space-between; gap: 1rem; font-size: 1.25rem; }
.venue-feature__fact span:first-child { color: var(--color-burgundy-mid); font-style: italic; }
.venue-feature__fact span:last-child { text-align: right; }
/* For a fact whose value is a full descriptive line rather than a short
   stat (e.g. "Men: Suits & Ties · Women: Long Dresses") — label above,
   value below, both left-aligned, instead of squeezing both onto one
   cramped two-column row. */
.venue-feature__fact--stacked { flex-direction: column; align-items: flex-start; gap: 0.3rem; }
.venue-feature__fact--stacked span:last-child { text-align: left; color: var(--color-ink); }
/* A short italic caveat directly beneath the facts row (e.g. "tuxedos
   should not be worn" under the Attire — Formal fact) — same small
   italic/burgundy-mid treatment used for callout notes elsewhere on the
   site (e.g. .info-card__note), pulled up close to the facts it clarifies
   rather than reading as a new, separate paragraph. */
.venue-feature__facts-note {
  max-width: 360px;
  margin: -0.6rem auto 1.1rem;
  font-size: 1.2rem;
  font-style: italic;
  color: var(--color-burgundy-mid);
  text-align: left;
}
.venue-feature__desc { color: var(--color-ink-soft); font-size: 1.35rem; }
.venue-feature__schedule-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  margin: 1rem 0 0.6rem;
}

.schedule-list { border-top: 1px solid var(--color-line); margin: 0.4rem auto 0; padding-top: 0.9rem; display: grid; gap: 0.6rem; max-width: 420px; text-align: left; }
.schedule-list__row { display: flex; justify-content: space-between; font-size: 1.25rem; }
.schedule-list__row span:first-child { color: var(--color-burgundy-mid); font-style: italic; }

/* Photographs: full width, own natural aspect ratio (never force-cropped —
   a vertical photo like the church exterior stays vertical), stacked with
   generous space between when there's more than one. No overlap, no inset,
   no collage treatment. */
.venue-feature__photos {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
}
.venue-feature__img { width: 100%; height: auto; display: block; border: var(--photo-frame); }
/* A second photograph (e.g. Villa Erba at dusk) is deliberately given a
   different, narrower size than the primary photo — its own quiet moment
   below the large dramatic one, not a matching pair, and never touching
   or overlapping it. */
.venue-feature__img--secondary { max-width: 640px; }

/* Villa Erba's photo series: the landscape frames are all cropped to the
   exact same width, height and aspect ratio as the first (facade) photo —
   nothing is displayed smaller than another. object-fit: cover crops each
   photo to that shared frame without ever stretching it; object-position
   is set per-photo (see content/en.js / content/it.js) so the important
   architectural detail in each stays visible. The ratio itself never
   changes across breakpoints, so mobile gets the same considered crop as
   desktop rather than a fresh, awkward one. Each frame keeps its own
   separate space — never inset, stacked, or overlapping another. */
.villa-gallery { gap: var(--space-5); }
.villa-gallery__frame {
  width: 100%;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border: var(--photo-frame);
}
/* The staircase hall's vertical columns, arches and steps get their own
   narrower, taller frame instead of being squeezed into the same 3:2
   landscape shape — an intentional portrait "detail shot" that still
   reads as a large, considered photograph, not an afterthought. */
.villa-gallery__frame--portrait {
  width: 100%;
  max-width: 620px;
  aspect-ratio: 3 / 4;
  margin: 0 auto;
}
.villa-gallery__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.venue-feature__placeholder {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: linear-gradient(160deg, var(--color-cream), var(--color-burgundy-pale));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  text-align: center;
  padding: 1.5rem;
}
.venue-feature__placeholder .sprig { width: 30%; color: var(--color-burgundy-mid); opacity: 0.75; }
.venue-feature__placeholder .sprig svg { width: 100%; height: auto; display: block; }
.venue-feature__placeholder span {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.25rem;
  color: var(--color-ink-soft);
}

/* ---------- Ceremony: info above, exterior + interior side by side --------
   The ceremony details (kicker, venue name, location, time) always read
   first, as a normal centered section header — never beside or over the
   photography (the `full: true, skipPhotos: true` venueFeature call above
   renders just that text block). The two church photographs then sit
   directly beneath as one matched pair, not a photo-led editorial split:
   same displayed width and height, side by side on desktop, cleanly
   aligned with consistent spacing, never overlapping or staggered. Each
   is cropped (object-fit: cover, never stretched) into the shared 3:4
   frame — close to the exterior's own native proportions, so it needs
   almost no crop, while the square interior shot is trimmed evenly from
   both sides to the same frame, keeping the altar and nave centered.
   Stacks into one column on narrow screens, each photo still large. */
.ceremony-photos {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  max-width: 460px;
  margin: var(--space-5) auto 0;
}
@media (min-width: 640px) {
  .ceremony-photos { grid-template-columns: 1fr 1fr; max-width: none; gap: 1.75rem; }
}
.ceremony-photos__frame {
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border: var(--photo-frame);
}
.ceremony-photos__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- Hotel / stay cards --------------------------------------------- */
/* The Accommodations intro sentence ("These are our recommended places to
   stay... Tap or hover on a hotel for details.") wraps to two lines at the
   shared .section-head width (640px, used sitewide) even though there's
   comfortably enough room on desktop for it to sit on one — widening just
   this section's .section-head (same technique as #travel above) lets it
   settle onto a single line with no font-size change. Scoped to #stay
   only; gated to ≥900px so mobile keeps wrapping naturally exactly as
   before (this is a taller threshold than #travel's since this sentence
   is longer and needs more room to go from two lines to one). */
@media (min-width: 900px) {
  #stay .section-head { max-width: 900px; }
}


/* Three coordinated, identically-proportioned photographic cards rather than
   alternating rows. One row of three on desktop; stacked on mobile. Each
   card shows the hotel name overlaid on the photo (bottom, on a dark
   gradient scrim so it reads on any image); the address/distance/room-block
   details live in a burgundy info panel that reveals on hover (desktop) or
   tap (mobile/keyboard — see the click/keydown handling in main.js, since
   hover alone is unreliable on touch). Any field the couple hasn't supplied
   yet is simply omitted from the panel rather than padded with invented
   placeholder-shaped data. */
.hotel-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  max-width: 1100px;
  margin: 0 auto;
}
/* Two tiers rather than one jump straight to three columns: a mid-width
   two-column step gives each card meaningfully more width (and, via its
   aspect-ratio, more height) right where a cramped three-column row would
   otherwise force the larger supporting type in the hover/tap panel below
   to scroll internally more than necessary. Three columns only once the
   viewport is wide enough for that extra card width to comfortably fit
   the panel's content without scrolling on typical laptop screens. */
@media (min-width: 640px) {
  .hotel-cards { grid-template-columns: repeat(2, 1fr); gap: 1.75rem; }
}
@media (min-width: 1150px) {
  .hotel-cards { grid-template-columns: repeat(3, 1fr); gap: 1.75rem; }
}
.hotel-card {
  position: relative;
  border: var(--photo-frame);
  background: var(--color-burgundy-dark);
}
.hotel-card__photo {
  position: relative;
  /* Slightly taller than the original 3/4 — the hover/tap info panel
     below is an absolutely-positioned overlay sized to match this same
     box (see .hotel-card__panel, `inset: 0`), so this ratio sets its
     available height too. Increasing it gives the panel meaningfully
     more room for the larger supporting type sizes below without
     cropping the photo any more aggressively than a normal portrait
     frame — object-fit: cover on the photo still shows it uncropped
     left-to-right, just a touch more of it top-to-bottom. Any panel
     content that still doesn't fit at very narrow card widths falls back
     to .hotel-card__panel's existing internal scroll rather than
     overflowing the card. */
  aspect-ratio: 3 / 4.65;
  overflow: hidden;
  cursor: pointer;
  display: block;
  outline-offset: -3px;
}
.hotel-card__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  transition: transform 900ms ease;
}
.hotel-card__placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, var(--color-burgundy-pale), var(--color-cream));
}
.hotel-card__placeholder .sprig { width: 34%; color: var(--color-burgundy-mid); opacity: 0.75; }
.hotel-card__photo:hover img { transform: scale(1.045); }
/* Bottom scrim + name, always visible so the card reads elegantly at rest —
   the info panel is an additional reveal, not a replacement for this. */
.hotel-card__name-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 2.5rem 1.25rem 1.15rem;
  background: linear-gradient(to top, rgba(42, 15, 20, 0.82) 0%, rgba(42, 15, 20, 0.35) 60%, transparent 100%);
  text-align: center;
}
.hotel-card__name {
  font-family: var(--font-display);
  font-size: 1.35rem;
  color: var(--color-white);
  letter-spacing: 0.01em;
}
.hotel-card__hint {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--color-burgundy-pale);
  opacity: 0.9;
}
/* The info panel: an understated dark-burgundy overlay (never gray/black),
   revealed on hover, on keyboard focus, or via the .is-open class that
   main.js toggles on tap. Fades and lifts slightly rather than sliding or
   flipping, to stay in the site's quiet, editorial register. */
.hotel-card__panel {
  position: absolute;
  inset: 0;
  padding: 1.4rem 1.3rem 1.2rem;
  display: flex;
  flex-direction: column;
  background: rgba(64, 18, 26, 0.94);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 350ms ease, transform 350ms ease;
  pointer-events: none;
  text-align: left;
  overflow-y: auto;
}
/* Triggered off the whole card (:hover/:focus-within), not just the photo
   sibling — the panel exactly overlaps the photo, so a photo-only trigger
   would flicker the instant pointer-events switches to `auto`: the cursor
   "arrives" on the photo, the panel (now interactive but still fading in)
   sits above it in stacking order, and the browser's hover target jumps to
   the panel mid-transition. Keeping the trigger on the shared ancestor means
   moving from the photo onto the panel (e.g. to reach the Reserve button)
   never leaves `:hover`, so nothing flickers. */
.hotel-card:hover .hotel-card__panel,
.hotel-card:focus-within .hotel-card__panel,
.hotel-card.is-open .hotel-card__panel {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.hotel-card__panel-name {
  font-family: var(--font-display);
  font-size: 1.22rem;
  color: var(--color-white);
  margin-bottom: 0.4rem;
}
.hotel-card__desc {
  font-size: 1.2rem;
  font-style: italic;
  color: var(--color-burgundy-pale);
  margin-bottom: 0.5rem;
}
.hotel-card__facts { font-size: 1rem; }
.hotel-card__facts > div { border-top: 1px solid rgba(233, 214, 200, 0.25); padding: 0.4rem 0; }
.hotel-card__facts > div:first-child { border-top: none; padding-top: 0; }
.hotel-card__facts dt {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-burgundy-pale);
  opacity: 0.85;
  margin-bottom: 0.1rem;
}
.hotel-card__facts dd { color: var(--color-white); margin: 0; }
/* Up to two calls to action — "Visit Hotel Website" (always, every hotel
   has an official page) and "Reserve" (only once there's a real
   room-block link) — stacked with a small gap rather than crowded onto
   one row, so both stay easy to tap on mobile. */
.hotel-card__ctas {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  margin-top: 0.7rem;
  flex-shrink: 0;
}
.hotel-card__cta {
  align-self: stretch;
  justify-content: space-between;
  flex-shrink: 0;
  padding: 0.6rem 1.25rem;
  min-height: 40px;
  font-size: 1.05rem;
}
.hotel-card__cta-arrow { display: inline-block; transition: transform var(--transition); }
.hotel-card__cta:hover .hotel-card__cta-arrow,
.hotel-card__cta:focus-visible .hotel-card__cta-arrow { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .hotel-card__photo img,
  .hotel-card__panel { transition: none; }
}

/* A quiet titled callout explaining the hotels double as the wedding-
   shuttle pickup points — sits below the hotel cards. */
.stay-transport-note {
  max-width: 640px;
  margin: var(--space-4) auto 0;
  text-align: center;
  padding: 1.5rem 2rem;
  border: 1px solid var(--color-burgundy-light);
  background: var(--color-burgundy-pale);
}
.stay-transport-note__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy-text);
  margin-bottom: 0.5rem;
}
.stay-transport-note__body {
  font-style: italic;
  color: var(--color-burgundy-mid);
}
/* Travel section's "A Note on Transportation" reuses .stay-transport-note
   wholesale but needs a bit more breathing room — at the shared 640px/
   2rem-padding width, its longer paragraph left a lone "fare" orphaned
   on its own last line. Widening just this variant (via the `.travel-
   note` marker class added alongside .stay-transport-note in
   templates/page.js) settles the paragraph into a clean three lines
   without touching the Stay section's identical-looking box or shrinking
   the type. */
.stay-transport-note.travel-note {
  max-width: 760px;
  padding: 1.5rem 1.75rem;
}

/* A booking-urgency note, shown ABOVE the hotel cards (right after the
   section intro). Deliberately NOT the one-sided-burgundy-accent
   treatment used for other callouts on the site — a soft, all-around
   blush wash with no heavy border reads as noticeable-but-elegant
   rather than a warning banner. */
.stay-booking-note {
  max-width: 720px;
  margin: 0 auto var(--space-4);
  text-align: center;
  padding: 1.5rem 2rem;
  background: var(--color-burgundy-pale);
  border-radius: var(--radius);
}
.stay-booking-note__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  color: var(--color-burgundy-text);
  margin-bottom: 0.5rem;
}
.stay-booking-note__body {
  font-size: 1.17rem;
  color: var(--color-ink-soft);
}

/* ---------- Travel / info grid ---------------------------------------------- */
/* The Travel intro sentence is long enough that, at the shared
   .section-head width (640px, used sitewide for every section's kicker/
   title/intro), its last few words wrap onto their own short trailing
   line no matter the viewport ("under normal traffic conditions." / the
   Italian "condizioni di traffico normali." each ending up alone on the
   final line — an orphaned-looking fragment rather than a natural wrap).
   Widening just this section's .section-head lets the sentence settle
   into three more even lines instead of four, with no wording change and
   no font-size change (.section-intro's own size is untouched — only the
   box it wraps inside gets wider). Scoped to #travel only — every other
   section's kicker/title/intro keeps the standard 640px width. Gated to
   ≥700px; below that the narrower viewport itself already governs the
   wrap and mobile's own comfortable margins are untouched. */
@media (min-width: 700px) {
  #travel .section-head { max-width: 800px; }
}

/* Same fix, same reasoning, for two more section intros discovered during
   a final pass for orphaned last words: Wedding Transportation's intro
   ("...Wedding Ceremony, and Reception.") and Discover Milan's new
   second intro paragraph ("...countless moments together."), both of
   which left a single word alone on the final line at the standard
   640px .section-head width. */
@media (min-width: 700px) {
  #transportation .section-head { max-width: 850px; }
}
@media (min-width: 700px) {
  /* 720px settled the second intro paragraph's orphan; the third
     paragraph ("...the city they have come to know and love.") needed a
     little more room still — widened further so "and love." rejoins the
     line above it, no font-size change. */
  #discover-milan .section-head { max-width: 800px; }
}

.info-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.75rem;
  margin-top: var(--space-3);
}
@media (min-width: 700px) {
  .info-grid { grid-template-columns: repeat(2, 1fr); }
}
.info-card {
  padding: 1.75rem;
  border-left: 2px solid var(--color-burgundy-light);
  background: rgba(255,255,255,0.5);
}
.info-card__title {
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--color-burgundy-text);
  margin-bottom: 0.5rem;
}
.info-card__body { color: var(--color-ink-soft); }
.info-card__body + .info-card__body { margin-top: 0.9rem; }
.info-card__facts {
  display: grid;
  gap: 0.5rem;
  margin: 1rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--color-line);
}
.info-card__fact { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.98rem; }
.info-card__fact dt { color: var(--color-burgundy-mid); font-style: italic; }
.info-card__fact dd { margin: 0; text-align: right; color: var(--color-ink); }
.info-card__subsection { margin-top: 1.1rem; }
.info-card__subsection:first-of-type {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-line);
}
.info-card__subsection-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy-text);
  margin-bottom: 0.4rem;
}
.info-card__note {
  margin-top: 0.9rem;
  font-size: 1.07rem;
  font-style: italic;
  color: var(--color-burgundy-mid);
}
.info-card__cta { margin-top: 1.25rem; }

/* A titled callout at the top of the (dark) Transportation section,
   naming the three designated shuttle pickup hotels — lighter-on-dark
   version of the .discover-callout / .stay-transport-note treatment. */
.transport-callout {
  max-width: 640px;
  margin: var(--space-4) auto 0;
  padding: 1.3rem 1.5rem;
  border: 1px solid rgba(250, 246, 238, 0.25);
  background: rgba(250, 246, 238, 0.06);
  text-align: center;
}
.transport-callout__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy-light);
  margin-bottom: 0.6rem;
}
.transport-callout__intro { color: rgba(250, 246, 238, 0.85); margin-bottom: 0.5rem; }
.transport-callout__list {
  list-style: none;
  margin: 0 0 0.75rem;
  padding: 0;
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--color-white);
}
.transport-callout__list li { margin-bottom: 0.2rem; }
.transport-callout__body { color: rgba(250, 246, 238, 0.75); font-size: 1.1rem; font-style: italic; }
/* The no-parking-at-Villa-Erba note is a hard constraint, not a nice-
   to-know — set apart with a top rule and non-italic weight so it
   doesn't read as just another aside. */
.transport-callout__parking {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid rgba(250, 246, 238, 0.2);
  color: rgba(250, 246, 238, 0.9);
  font-size: 1.1rem;
  font-style: normal;
}

/* ---------- Transportation timeline ----------------------------------------- */
.timeline {
  margin-top: var(--space-4);
  position: relative;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}
.timeline::before {
  content: "";
  position: absolute;
  left: 11px;
  top: 6px;
  bottom: 6px;
  width: 1px;
  background: var(--color-burgundy-light);
}
@media (min-width: 640px) {
  .timeline::before { left: 50%; transform: translateX(-50%); }
}
.timeline__item {
  position: relative;
  padding-left: 2.5rem;
  padding-bottom: 2.25rem;
}
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item::before {
  content: "";
  position: absolute;
  left: 4px; top: 6px;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--color-ivory);
  border: 2px solid var(--color-burgundy);
}
/* This timeline only ever appears inside .section--dark (Wedding
   Transportation), so its type is tuned for legibility on that dark ink
   background rather than the light card colors used elsewhere. */
.timeline__label { font-family: var(--font-display); font-size: 1.15rem; color: var(--color-burgundy-light); margin-bottom: 0.2rem; }
.timeline__time { font-style: italic; color: rgba(250,246,238,0.78); margin-bottom: 0.2rem; }
.timeline__detail { color: rgba(250,246,238,0.62); font-size: 1.17rem; }

@media (min-width: 640px) {
  .timeline__item { width: 50%; padding-left: 0; }
  .timeline__item:nth-child(odd) { padding-right: 3rem; text-align: right; }
  .timeline__item:nth-child(even) { margin-left: 50%; padding-left: 3rem; }
  .timeline__item::before { left: auto; }
  .timeline__item:nth-child(odd)::before { right: -8px; left: auto; }
  .timeline__item:nth-child(even)::before { left: -8px; }
}

.transport-note {
  max-width: 640px;
  margin: var(--space-4) auto 0;
  text-align: center;
  font-style: italic;
  color: rgba(250,246,238,0.85);
}

/* ---------- Attire --------------------------------------------------------- */
.attire-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  max-width: 720px;
  margin: 0 auto;
}
@media (min-width: 600px) {
  .attire-grid { grid-template-columns: 1fr 1fr; }
}
.attire-card {
  text-align: center;
  padding: 2.25rem 1.5rem;
  border: 1px solid var(--color-line);
  background: var(--color-white);
}
.attire-card__title { font-family: var(--font-display); font-size: 1.3rem; color: var(--color-burgundy-text); margin-bottom: 0.6rem; }
.attire-card__value { font-style: italic; color: var(--color-ink-soft); font-size: 1.25rem; }
/* The richer breakdown (currently Wedding Day only) — a prominent
   dress-code word, then a couple of short men's/women's lines, then a
   small italic caveat. `.attire-card__value` above stays exactly as-is
   for a card that just needs one simple line (Welcome Dinner). */
.attire-card__dresscode {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.15rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  margin-bottom: 0.7rem;
}
.attire-card__details { display: grid; gap: 0.4rem; margin-bottom: 0.9rem; font-size: 1.25rem; font-style: italic; }
.attire-card__details li { color: var(--color-ink-soft); }
.attire-card__note { font-size: 1.2rem; font-style: italic; color: var(--color-burgundy-mid); }

/* Native "Color Inspiration" swatch palette (Welcome Dinner's Semi-Formal
   colors) — genuine rectangular color blocks built with plain CSS, not a
   small inserted image, so they render crisp and true at any size. Sits
   below the two attire cards but is intentionally NOT confined to
   .attire-grid's narrow 720px reading column — it uses most of the
   section's own standard 1120px container so eleven swatches have real
   room to breathe on desktop, per "large, elegant, appropriately scaled
   to the width of the website." A top divider echoes the same treatment
   used elsewhere on the site (e.g. .venue-feature__facts) to separate it
   visually from the two cards above. */
.color-palette {
  max-width: 1040px;
  margin: var(--space-6) auto 0;
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-line);
  text-align: center;
}
/* Above ~1000px, all 11 swatches are required to sit on one single
   horizontal line — never wrapping to a second row on desktop. That
   needs more width than the standard 1120px .container leaves for an
   11-across row plus labels, so #attire's own container (this section
   only — no other section is affected) widens the same way
   #wedding-party's did for its wide story text, and .color-palette
   grows to fill it. Below 1000px this reverts to the original
   flex-wrap behavior (see .color-palette__row below) so the palette
   still wraps elegantly on tablet/mobile instead of forcing swatches
   down to an unreadable size. */
@media (min-width: 1000px) {
  #attire .container { max-width: min(1700px, 94vw); }
  .color-palette { max-width: 100%; }
}
.color-palette__heading {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  margin-bottom: 0.6rem;
}
.color-palette__note {
  font-style: italic;
  font-size: 1.2rem;
  color: var(--color-ink-soft);
  max-width: 520px;
  margin: 0 auto 2.25rem;
}
/* flex + flex-wrap (not a fixed 11-column grid) so the row wraps into
   extra lines as room runs out — on tablets/phones the swatches keep
   their full size and simply flow onto more rows, rather than every
   swatch and its label being squeezed down to an unreadable size. */
.color-palette__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.75rem 1.35rem;
}
.color-palette__swatch {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.65rem;
  width: 92px;
}
.color-palette__block {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  border: 1px solid rgba(30, 16, 12, 0.14);
  box-shadow: 0 1px 3px rgba(64, 18, 26, 0.12);
}
.color-palette__name {
  font-family: var(--font-body);
  font-size: 0.98rem;
  color: var(--color-ink);
  line-height: 1.3;
}
@media (min-width: 700px) {
  .color-palette__swatch { width: 104px; }
}
/* ≥1000px: switch from wrapping flex to a strict 11-column grid so every
   swatch sits on one line, no matter the viewport within this range —
   grid columns (not flex-basis) are what guarantees exactly 11 tracks
   and never an 11th item overflowing onto its own row. Swatches give up
   their fixed pixel width here and simply fill their column, shrinking
   only as much as the available width forces and no more. */
@media (min-width: 1000px) {
  .color-palette__row {
    display: grid;
    grid-template-columns: repeat(11, 1fr);
    gap: 0.9rem 0.65rem;
  }
  .color-palette__swatch { width: 100%; gap: 0.5rem; }
  .color-palette__name { font-size: clamp(0.72rem, 0.85vw, 0.95rem); }
}

/* ---------- RSVP ------------------------------------------------------------
   Rebuilt as elegant, sentence-style prompts ("I, [name], [attend ▾] the
   celebration.") rather than a boxy questionnaire — see .rsvp-sentence and
   friends below. The panel itself is correspondingly quieter: a thin
   burgundy hairline instead of a drop-shadowed card. */
.rsvp-deadline {
  text-align: center;
  font-style: italic;
  color: var(--color-burgundy-mid);
  margin-top: 0.5rem;
}
.rsvp-panel {
  max-width: 680px;
  margin: var(--space-4) auto 0;
  background: var(--color-white);
  border: var(--photo-frame);
  padding: 2.25rem 1.75rem;
}
@media (min-width: 640px) { .rsvp-panel { padding: 3rem; } }

.field { margin-bottom: 1.5rem; }
.field label {
  display: block;
  font-family: var(--font-display);
  font-size: 0.95rem;
  letter-spacing: 0.03em;
  color: var(--color-burgundy-text);
  margin-bottom: 0.5rem;
}
/* Quiet underline fields rather than boxed inputs — a bottom hairline that
   deepens to solid burgundy on focus, echoing the sentence-style fields
   below without literally turning every field into a fill-in-the-blank. */
.field input[type="text"],
.field input[type="email"],
.field input[type="search"],
.field textarea {
  width: 100%;
  padding: 0.7rem 0.1rem;
  font-family: var(--font-body);
  font-size: 1.1rem;
  border: none;
  border-bottom: 1px solid var(--color-burgundy-light);
  background: transparent;
  border-radius: 0;
  color: var(--color-ink);
  transition: border-color var(--transition), background var(--transition);
}
.field input[type="text"]:focus,
.field input[type="email"]:focus,
.field input[type="search"]:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--color-burgundy);
  background: var(--color-burgundy-whisper);
}
.field textarea { min-height: 90px; resize: vertical; padding-top: 0.7rem; }
.field-help { font-size: 0.95rem; color: var(--color-ink-soft); margin-top: 0.4rem; }

.search-row { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: flex-end; }
.search-row .field { flex: 1 1 220px; margin-bottom: 0; }
.search-row .btn { flex: 0 0 auto; }

.rsvp-message { text-align: center; padding: 1.5rem 0; }
.rsvp-message__title { font-family: var(--font-display); font-size: 1.5rem; color: var(--color-burgundy-text); margin-bottom: 0.5rem; }
.rsvp-found-intro { text-align: center; font-style: italic; color: var(--color-ink-soft); margin-bottom: 2rem; }

/* ---- Sentence-style guest response --------------------------------------- */
.party-list { display: flex; flex-direction: column; margin-bottom: 2rem; }
.rsvp-guest {
  padding: 1.9rem 0;
  border-top: 1px solid var(--color-line);
}
.rsvp-guest:first-child { border-top: none; padding-top: 0; }

.rsvp-sentence {
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 2.1;
  color: var(--color-ink);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem;
  margin: 0;
}
/* The `hidden` attribute's default `display: none` has the same specificity
   as the class rule above, so without this override an author stylesheet
   loaded after the UA sheet wins and a "hidden" sentence (e.g. the entrée
   line before the reception is checked) would incorrectly stay visible. */
.rsvp-sentence[hidden] { display: none; }
.rsvp-sentence + .rsvp-sentence { margin-top: 0.6rem; }
.rsvp-sentence__text { white-space: pre-wrap; }
.rsvp-guest__name { color: var(--color-burgundy-text); font-weight: 600; }
@media (max-width: 480px) {
  .rsvp-sentence { font-size: 1.08rem; line-height: 1.9; }
}

/* Inline burgundy/cream dropdown — deliberately not the browser-default
   gray/black treatment. The closed control reads like an underlined phrase
   filled in by hand; the option list uses the same palette everywhere it's
   supported (native OS chrome may override the popover itself on some
   platforms, which is an acceptable, well-known limit of styling <select>). */
.rsvp-select-wrap { display: inline-flex; }
.rsvp-select {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.02rem;
  color: var(--color-white);
  background: var(--color-burgundy);
  border: none;
  border-radius: var(--radius);
  padding: 0.35rem 2rem 0.35rem 0.85rem;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M3.5 6l4.5 4.5L12.5 6' fill='none' stroke='%23f6ece2' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 11px;
  min-height: 40px;
  transition: background-color var(--transition);
}
.rsvp-select:hover,
.rsvp-select:focus-visible { background-color: var(--color-burgundy-dark); outline: none; }
.rsvp-select option { background: var(--color-burgundy); color: var(--color-white); font-style: normal; }
.rsvp-select:disabled { opacity: 0.6; cursor: not-allowed; }

/* Inline text field for song requests etc. — an underlined blank sitting
   directly in the sentence rather than a separate boxed input. */
.rsvp-inline-input {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--color-burgundy-text);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--color-burgundy);
  padding: 0.2rem 0.15rem;
  min-width: 12em;
  max-width: 100%;
}
@media (max-width: 480px) { .rsvp-inline-input { min-width: 9em; } }
.rsvp-inline-input:focus { outline: none; background: var(--color-burgundy-whisper); }
.rsvp-inline-input::placeholder { color: var(--color-burgundy-light); opacity: 1; }

.rsvp-guest__conditional { margin-top: 0.6rem; }

/* Events multi-select: a burgundy pill trigger ("0 Events ▾") that expands
   into a checkbox panel anchored beneath it — feels like a natural
   extension of the sentence rather than a generic browser dropdown. */
.rsvp-multiselect { position: relative; display: inline-flex; vertical-align: middle; }
.rsvp-multiselect__trigger {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.02rem;
  color: var(--color-white);
  background: var(--color-burgundy);
  border: none;
  border-radius: var(--radius);
  padding: 0.35rem 0.9rem;
  min-height: 40px;
  cursor: pointer;
  transition: background-color var(--transition);
}
.rsvp-multiselect__trigger:hover,
.rsvp-multiselect__trigger[aria-expanded="true"] { background-color: var(--color-burgundy-dark); }
.rsvp-multiselect__panel {
  position: absolute;
  top: calc(100% + 0.6rem);
  left: 0;
  z-index: 5;
  width: max-content;
  max-width: min(360px, 84vw);
  background: var(--color-burgundy-dark);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  box-shadow: 0 18px 40px -16px rgba(42, 15, 20, 0.45);
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  pointer-events: none;
  transition: opacity 250ms ease, transform 250ms ease, visibility 250ms;
}
.rsvp-multiselect__panel.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}
.rsvp-multiselect__option {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.55rem 0.2rem;
  font-family: var(--font-body);
  font-size: 1rem;
  font-style: normal;
  color: var(--color-white);
  cursor: pointer;
  white-space: normal;
}
.rsvp-multiselect__option input {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  accent-color: var(--color-burgundy-pale);
  cursor: pointer;
}
.rsvp-multiselect__done {
  display: block;
  margin: 0.5rem 0 0 auto;
  background: transparent;
  border: none;
  color: var(--color-burgundy-pale);
  font-family: var(--font-body);
  font-style: italic;
  font-size: 0.9rem;
  letter-spacing: 0.05em;
  cursor: pointer;
  padding: 0.3rem 0.2rem;
}
/* Below ~600px the trigger can sit anywhere within a wrapped sentence line,
   so anchoring the panel to the trigger itself (as on desktop) risks
   pushing it past the right edge of the screen. Anchor to the whole
   sentence instead — guaranteed to stay within the page's own padding. */
@media (max-width: 600px) {
  .rsvp-sentence--events { position: relative; }
  .rsvp-multiselect { position: static; }
  .rsvp-multiselect__panel {
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
  }
}
.rsvp-multiselect__done:hover { color: var(--color-white); }

.rsvp-sentence--accommodation { margin-bottom: 1.5rem; }
.rsvp-accommodation-other { margin-top: -0.5rem; }

.rsvp-actions { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-top: 1.5rem; }

/* Household-level song request line, sitting between the party list and
   the accommodation sentence — same treatment as .rsvp-sentence--accommodation. */
.rsvp-sentence--song { margin-bottom: 1.5rem; }

/* Per-guest dietary line, rendered inside each guest's conditional block. */
.rsvp-sentence--dietary { margin-top: 0.6rem; }

/* Editable plus-one name field — sits where a fixed guest name normally
   would, so it needs the same weight/color as .rsvp-guest__name while
   still reading as an editable blank. */
.rsvp-guest__name-input {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1em;
  color: var(--color-burgundy-text);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--color-burgundy);
  padding: 0.1rem 0.05rem;
  min-width: 10em;
  max-width: 100%;
}
.rsvp-guest__name-input:focus { outline: none; background: var(--color-burgundy-whisper); }
.rsvp-guest__name-input::placeholder { color: var(--color-burgundy-light); opacity: 1; font-weight: 400; }

/* A returning guest's "you already responded" note, shown above the party
   list once a household with a prior submission is found. */
.rsvp-previous-note {
  text-align: center;
  font-style: italic;
  font-size: 0.95rem;
  color: var(--color-burgundy-mid);
  background: var(--color-burgundy-whisper);
  border: 1px solid var(--color-line);
  padding: 0.85rem 1.25rem;
  margin: -0.75rem 0 2rem;
}

.rsvp-success-note {
  margin-top: 0.75rem;
  font-size: 0.95rem;
  font-style: italic;
  color: var(--color-ink-soft);
}

/* Error step — same quiet .rsvp-message treatment, with a thin burgundy
   top rule instead of an alarming red, so a failed submission still reads
   as "elegant wedding site" rather than a generic system error. */
.rsvp-message--error {
  border-top: 2px solid var(--color-burgundy);
  padding-top: 1.75rem;
}

/* ---------- FAQ -------------------------------------------------------------- */
.faq-list { max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; gap: 0.1rem; }
.faq-item {
  border-bottom: 1px solid var(--color-line);
  padding: 1.25rem 0;
}
.faq-item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--color-burgundy-text);
  padding: 0.25rem 0.25rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  font-size: 1.6rem;
  line-height: 1;
  color: var(--color-burgundy-mid);
  flex-shrink: 0;
  transition: transform var(--transition);
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p {
  margin-top: 0.85rem;
  padding: 0 0.25rem;
  color: var(--color-ink-soft);
  font-size: 1.25rem;
  max-width: 62em;
}

/* ---------- Contact ------------------------------------------------------------ */
.contact-card {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
}
.contact-card__row { margin-top: 1rem; font-size: 1.3rem; }
.contact-card__row a { text-decoration: underline; text-underline-offset: 4px; color: var(--color-burgundy); }

/* Wedding travel advisor (e.g. A La Luna) — a small named-contact card
   sitting beneath the general Travel Assistance intro. Separated visually
   from the plain .contact-card__row lines above it (name/title/company
   need their own hierarchy) with a top border and extra spacing so it
   reads as "here's who to contact," not just more body text. */
.contact-card__advisor {
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-burgundy-light);
}
.contact-card__advisor-name {
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--color-burgundy-text);
}
.contact-card__advisor-role {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.17rem;
  color: var(--color-burgundy-mid);
  margin-top: 0.2rem;
}
.contact-card__advisor-company {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.13rem;
  color: var(--color-ink-soft);
  margin-top: 0.15rem;
}
.contact-card__cta-wrap { margin-top: 2rem; }

/* ---------- Footer ------------------------------------------------------------- */
.site-footer {
  background: var(--color-ivory);
  color: var(--color-ink);
  text-align: center;
  padding: var(--space-5) 0 var(--space-3);
  border-top: 1px solid var(--color-line);
}
.site-footer .script-accent { font-size: 2rem; color: var(--color-burgundy-text); margin-bottom: 0.5rem; }
.site-footer__tagline { letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.9rem; color: var(--color-ink-soft); opacity: 0.85; }
.site-footer .lang-toggle { justify-content: center; margin: 1.5rem 0; }
.site-footer .lang-toggle a { color: var(--color-burgundy-text); }
.site-footer .lang-toggle span { color: var(--color-line); }
.site-footer__credit { font-size: 0.8rem; color: var(--color-ink-soft); opacity: 0.6; margin-top: 1.5rem; }

/* ---------- Decorative sprig ----------------------------------------------------- */
.sprig { display: block; margin: 0 auto var(--space-3); width: 46px; height: auto; color: var(--color-burgundy-light); }

/* ---------- Monogram --------------------------------------------------------------
   The couple's real floral "A & M" artwork, extracted from their printed
   stationery and used here as an image asset — never redrawn or
   approximated with fonts/icons. Used sparingly by design: the entrance
   (password) screen, the homepage hero, and one small, quiet mark in the
   footer. It is never repeated between sections and never used as a
   background pattern. */
.monogram {
  display: block;
  width: 132px;
  height: auto;
  margin: 0 auto 1.5rem;
}
.gate__monogram { width: 188px; margin: 0 auto 1.5rem; }
.hero__monogram { width: 104px; margin: 0 auto 1.35rem; }
.site-footer .monogram { width: 88px; margin-bottom: 1rem; opacity: 0.92; }

/* ---------- Our Story ----------------------------------------------------------------
   Redesigned 2026-08-27 into a calm, centered, photo-first feature —
   kicker + script title, then the photograph, then a quiet "Read Our
   Story" link. The full narrative itself now lives only in
   .story-overlay further below, opened by that link. */
.our-story {
  padding: var(--space-6) 0;
  background: var(--color-white);
}
.our-story .section-head { margin-bottom: var(--space-4); }
.our-story__title {
  font-family: var(--font-script);
  font-size: clamp(2.2rem, 4vw, 3rem);
  color: var(--color-burgundy-text);
  line-height: 1.15;
  margin-top: 0.3rem;
}
/* The photograph: no `object-fit`, no forced container height/aspect
   ratio — width is capped, height is `auto`, so the image renders at its
   own natural aspect ratio in full, never cropped, zoomed, stretched, or
   cut off. `max-width` alone controls its size; on a narrow viewport it
   simply shrinks with the container instead. */
.our-story__photo {
  max-width: 620px;
  margin: 0 auto;
  border: var(--photo-frame);
  background: var(--color-ink);
}
.our-story__photo img {
  width: 100%;
  height: auto;
  display: block;
}
.our-story__cta-wrap {
  text-align: center;
  margin: var(--space-4) 0 0;
}
/* Same quiet, editorial "text link with an arrow" language as
   .proposal-photos__watch elsewhere in Our Story — deliberately not a
   filled button, per the brief ("not like a large conventional website
   button"). Kept as its own rule set (rather than sharing a class)
   so the two CTAs can be edited independently later. */
.our-story__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: none;
  border: none;
  padding: 0.4rem 0.2rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-color: var(--color-burgundy-light);
  cursor: pointer;
  transition: text-decoration-color var(--transition), color var(--transition);
}
.our-story__cta:hover, .our-story__cta:focus-visible {
  color: var(--color-burgundy-text);
  text-decoration-color: var(--color-burgundy-text);
}
.our-story__cta-arrow { display: inline-block; transition: transform var(--transition); }
.our-story__cta:hover .our-story__cta-arrow,
.our-story__cta:focus-visible .our-story__cta-arrow { transform: translateX(4px); }

/* ---------- Our Story: full-story overlay ----------------------------------
   Opened by "Read Our Story" above; closed by either close control here.
   Same [hidden]-toggling show/hide idiom as proposal-lightbox (see
   main.js), but deliberately NOT that lightbox's dark cinematic
   treatment — this is plain long-form body copy, not a video stage, so it
   stays inside the site's own cream/ivory + burgundy palette and simply
   gives the same story a full-width page to read on, with substantially
   more horizontal room than the old side-by-side layout ever offered. */
.story-overlay {
  position: fixed;
  inset: 0;
  z-index: 400;
  background: var(--color-ivory);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.story-overlay[hidden] { display: none; }
.story-overlay__close {
  position: fixed;
  top: 1.25rem;
  right: 1.5rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--color-ivory);
  border: 1px solid var(--color-burgundy-light);
  border-radius: 999px;
  padding: 0.55rem 1.1rem 0.55rem 0.9rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.story-overlay__close:hover, .story-overlay__close:focus-visible {
  background: var(--color-burgundy-pale);
  border-color: var(--color-burgundy);
  color: var(--color-burgundy-text);
}
.story-overlay__close-x { font-size: 1.2rem; line-height: 1; }
.story-overlay__scroll {
  min-height: 100%;
  padding: calc(var(--space-6) + 1rem) 1.5rem var(--space-6);
}
.story-overlay__content {
  max-width: 720px;
  margin: 0 auto;
}
@media (min-width: 900px) {
  /* Substantially wider reading column on desktop — roughly 80-85% of
     the available width, per the brief, rather than the site's usual
     comfortable-measure "article" column. Matches the identical 82% /
     1400px formula used by .party-shared-story--wide (the Proposal
     Story, Maids of Honor, and Best Men stories) so all four long-form
     narratives on the site share one consistent reading width, not just
     a similar one. Font size and line-height are set on
     .story-overlay__content p below, also matching those three. Mobile
     (no media query here) keeps its own narrower, comfortable margins
     untouched. */
  .story-overlay__content { width: 82%; max-width: 1400px; }
}
.story-overlay__content > .kicker { text-align: center; }
.story-overlay__title {
  font-family: var(--font-script);
  font-size: clamp(2.2rem, 4vw, 3rem);
  color: var(--color-burgundy-text);
  line-height: 1.15;
  text-align: center;
  margin: 0.3rem 0 var(--space-5);
}
/* Comfortable long-form reading rhythm for the full story — a touch more
   line-height and paragraph spacing than the site's base body copy, in
   the same spirit as `.party-shared-story` elsewhere on the site. */
.story-overlay__content p {
  font-family: var(--font-body);
  font-size: 1.3rem;
  line-height: 1.75;
  color: var(--color-ink-soft);
  margin-bottom: 1.3rem;
  /* Modern browsers avoid leaving a single short word alone on the final
     line of a paragraph; older browsers simply ignore this and wrap
     normally, so it's a safe, no-downside addition on top of the
     width/margin sizing above (which does the real work everywhere). */
  text-wrap: pretty;
}
.story-overlay__close-text {
  display: block;
  margin: var(--space-4) auto 0;
  background: none;
  border: none;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-color: var(--color-burgundy-light);
  cursor: pointer;
  transition: text-decoration-color var(--transition), color var(--transition);
}
.story-overlay__close-text:hover, .story-overlay__close-text:focus-visible {
  color: var(--color-burgundy-text);
  text-decoration-color: var(--color-burgundy-text);
}

/* ---------- The Proposal ----------------------------------------------------
   An editorial triptych, not a collage: three photographs from the
   proposal evening sit on the same line at nearly the same height, the
   center (the actual on-one-knee moment) only modestly larger. Title/
   location read as an ordinary section header above the photos — capped
   at the normal .section-head reading width — but the photography itself
   is deliberately given a much wider stage than the site's standard
   1120px container, so the triptych reads as a large, dramatic editorial
   spread (in the spirit of the large Villa Erba photography) rather than
   three small cards adrift in cream space. Nothing is overlaid on the
   photography itself. ------------------- */
.proposal-photos .container,
#wedding-party > .container {
  /* Wider than --container-max on purpose — see the note above. Clamped
     to the viewport so small margins remain on very large screens without
     the row ever going edge-to-edge. Also applied to #wedding-party's
     container (see the .party-shared-story--wide comment further down)
     so the Maids of Honor / Best Men shared stories can reach the same
     ~70-75%-of-viewport reading width as The Proposal Story. */
  max-width: min(1800px, 94vw);
}
.proposal-photos__location {
  font-family: var(--font-body);
  font-style: italic;
  color: var(--color-ink-soft);
  margin-top: 0.4rem;
}
.proposal-triptych {
  display: flex;
  gap: 1.1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0.6rem 0.2rem 1rem;
  margin: 0 -0.2rem;
}
.proposal-triptych::-webkit-scrollbar { display: none; }
.proposal-triptych__frame {
  flex: 0 0 78%;
  scroll-snap-align: center;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: var(--photo-frame);
}
.proposal-triptych__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.proposal-triptych__placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  text-align: center;
  padding: 1.5rem;
  background: linear-gradient(160deg, var(--color-cream), var(--color-burgundy-pale));
}
.proposal-triptych__placeholder .sprig { width: 22%; color: var(--color-burgundy-mid); opacity: 0.75; }
.proposal-triptych__placeholder span {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.02rem;
  color: var(--color-ink-soft);
}
/* Desktop: all three side by side, no scrolling — equal-width columns so
   the photographs read as balanced and coordinated at a glance. The
   center frame gets a taller `aspect-ratio` only (never a wider column),
   so with all three vertically centered on the row it bleeds a few
   percent above and below the outer two — proud, not dominant: ~7%
   more area, comfortably inside the requested 5-10%. */
@media (min-width: 760px) {
  .proposal-triptych {
    overflow: visible;
    padding: 0.6rem 0 1rem;
    margin: 0;
    align-items: center;
    /* No max-width here — the row fills the .proposal-photos .container
       above (already widened, see the note there), so the photos
       themselves grow with it rather than staying capped at 1120px. */
  }
  .proposal-triptych__frame { flex: 1 1 0; aspect-ratio: 3 / 4; }
  .proposal-triptych__frame--center { aspect-ratio: 3 / 4.3; }
}
.proposal-photos__cta { text-align: center; margin-top: var(--space-3); }
.proposal-photos__watch {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: none;
  border: none;
  padding: 0.4rem 0.2rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-color: var(--color-burgundy-light);
  cursor: pointer;
  transition: text-decoration-color var(--transition), color var(--transition);
}
.proposal-photos__watch:hover, .proposal-photos__watch:focus-visible {
  color: var(--color-burgundy-text);
  text-decoration-color: var(--color-burgundy-text);
}
.proposal-photos__watch-arrow { display: inline-block; transition: transform var(--transition); }
.proposal-photos__watch:hover .proposal-photos__watch-arrow,
.proposal-photos__watch:focus-visible .proposal-photos__watch-arrow { transform: translateX(4px); }

/* ---------- Proposal video lightbox -----------------------------------------
   Same show/hide idiom as the password gate (`[hidden]` + JS toggling the
   attribute). No native <video controls> and no volume/mute control by
   design — see the note above proposalLightbox() in templates/page.js:
   the published video files carry no audio track at all. ------------- */
.proposal-lightbox {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.proposal-lightbox[hidden] { display: none; }
/* A sophisticated deep-burgundy cinematic backdrop (not black) for the
   space either side of the video — derived from the site's own darkest
   burgundy token rather than an independent color choice. */
.proposal-lightbox__backdrop { position: absolute; inset: 0; background: rgba(56, 15, 21, 0.97); }
/* The panel itself is now the sizing driver (height + aspect-ratio), with
   the topbar and controls overlaid ON TOP of the video via `position:
   absolute` rather than stacked above/below it in normal flow. That's
   the whole point: the old layout reserved a fixed chunk of vertical
   space (topbar + controls + margins) OUTSIDE the video, which ate into
   the 85-90vh budget and left the actual <video> noticeably short of it
   on ordinary laptop-height windows. Overlaying them means every pixel
   of the 85-90vh target belongs to the video itself. */
.proposal-lightbox__panel {
  position: relative;
  z-index: 1;
  /* Height IS the target: 90vh is the top of the requested 85-90vh
     range; `calc(100vh - 2rem)` matches this element's own 1rem/1rem
     padding on .proposal-lightbox so the panel never overflows the
     viewport; `calc(94vw * 16 / 9)` is the tallest a 94vw-wide 9:16 box
     could be, guarding extreme wide-but-short viewports. Whichever is
     smallest wins, and — since 90vh <= 100vh - 2rem on any realistic
     viewport — that's normally the full 90vh itself. */
  height: min(90vh, calc(100vh - 2rem), calc(94vw * 16 / 9));
  aspect-ratio: 9 / 16;
  max-width: 94vw;
}
.proposal-lightbox__topbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem;
  background: linear-gradient(to bottom, rgba(56, 15, 21, 0.65), transparent);
}
.proposal-lightbox__chapter {
  font-family: var(--font-body);
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(246,236,226,0.75);
}
.proposal-lightbox__close {
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid rgba(246,236,226,0.45);
  border-radius: 50%;
  color: var(--color-white);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.proposal-lightbox__close:hover, .proposal-lightbox__close:focus-visible {
  background: rgba(246,236,226,0.14);
  border-color: var(--color-white);
}
/* The stage now simply fills the panel (which carries the 85-90vh sizing
   above) — it no longer sets its own height/aspect-ratio, so there's a
   single source of truth for the video's size and zero risk of the two
   drifting out of sync. `object-fit: contain` on the <video> itself is
   what actually guarantees the full vertical frame is preserved with
   zero crop/stretch/distortion within that box. */
.proposal-lightbox__stage {
  position: absolute;
  inset: 0;
  background: #000;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 30px 70px -20px rgba(0,0,0,0.6);
}
.proposal-lightbox__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
  display: block;
}
.proposal-lightbox__video[hidden] { display: none; }
.proposal-lightbox__fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem;
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.05rem;
  color: rgba(246,236,226,0.85);
}
.proposal-lightbox__fallback[hidden] { display: none; }
.proposal-lightbox__controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1.1rem 1rem 0.9rem;
  background: linear-gradient(to top, rgba(56, 15, 21, 0.7), transparent);
}
/* Same [hidden]-vs-class-display cascade tie as .rsvp-sentence[hidden]
   elsewhere on the site (author `display: flex` above and the UA
   `[hidden] { display: none }` rule have equal specificity, and the
   later-loaded author rule wins) — needs an explicit override. */
.proposal-lightbox__controls[hidden] { display: none; }
.proposal-lightbox__playpause {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(246,236,226,0.45);
  background: none;
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.proposal-lightbox__playpause:hover, .proposal-lightbox__playpause:focus-visible {
  background: rgba(246,236,226,0.14);
  border-color: var(--color-white);
}
.proposal-lightbox__playpause .icon-play { display: none; }
.proposal-lightbox.is-paused .proposal-lightbox__playpause .icon-pause { display: none; }
.proposal-lightbox.is-paused .proposal-lightbox__playpause .icon-play { display: block; }
.proposal-lightbox__progress {
  flex: 1;
  height: 2px;
  background: rgba(246,236,226,0.25);
  border-radius: 2px;
  overflow: hidden;
}
.proposal-lightbox__progress-fill {
  height: 100%;
  width: 0%;
  background: var(--color-burgundy-light);
}

/* Mobile: nearly the full screen — topbar/controls already overlay the
   video rather than taking their own space, so this just relaxes the
   padding/max-width a little further than desktop. */
@media (max-width: 640px) {
  .proposal-lightbox { padding: 0.5rem; }
  .proposal-lightbox__panel {
    height: min(95vh, calc(100vh - 1rem), calc(97vw * 16 / 9));
    max-width: 97vw;
  }
}

/* ---------- Our Families -----------------------------------------------------------
   Quiet recognition of both sets of parents. Deliberately not laid out as
   matching employee-directory cards — just generous whitespace and
   centered editorial type, echoed on both sides. */
.families-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
  max-width: 780px;
  margin: 0 auto;
}
@media (min-width: 700px) {
  .families-grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-6); }
}
.family-block { text-align: center; }
.family-block__side {
  font-family: var(--font-body);
  font-style: italic;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 0.95rem;
  color: var(--color-burgundy-mid);
  margin-bottom: 0.75rem;
}
.family-block__names {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--color-burgundy-text);
  line-height: 1.4;
}
/* Keeps each person's first/last name together; when a couple's combined
   names don't fit on one line, this is the only place it may wrap. */
.names-nowrap { white-space: nowrap; }
.family-block__desc { color: var(--color-ink-soft); font-size: 1.2rem; margin-top: 0.6rem; }

/* ---------- Wedding Party -----------------------------------------------------------
   Built specifically for a pair on each side (two bridesmaids, two
   groomsmen) — large, generously sized editorial portraits with plenty of
   negative space, not a three-slot grid with an empty third position. The
   second portrait in each pair sits slightly lower for a quiet asymmetry. */
/* No max-width of its own (beyond the widened #wedding-party > .container,
   see the .party-shared-story--wide comment below) — .party-pair (980px)
   and .party-group__label/.section-head (centered, their own caps) each
   already constrain themselves, so a wider .party-group only gives the
   .party-shared-story--wide text block below room to actually reach its
   ~70-75%-of-viewport width; it doesn't stretch the portraits or label. */
.party-group { margin: 0 auto; }
.party-group + .party-group { margin-top: var(--space-6); }
.party-group__label {
  text-align: center;
  font-family: var(--font-body);
  font-style: italic;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 1rem;
  color: var(--color-burgundy-mid);
  margin-bottom: var(--space-4);
}
.party-pair {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
  max-width: 520px;
  margin: 0 auto;
}
@media (min-width: 700px) {
  .party-pair {
    grid-template-columns: repeat(2, 1fr);
    gap: 3.5rem;
    max-width: 980px;
    align-items: start;
  }
}
/* Both portraits in a pair (Maids of Honor, Best Men) share this exact
   frame — same aspect ratio, same background, same spacing — and neither
   is staggered/offset from the other, so names, roles and story text both
   begin at identical vertical positions across the two columns. */
.party-pair__portrait { text-align: center; }
.party-pair__frame {
  aspect-ratio: 3 / 4;
  background: linear-gradient(160deg, var(--color-cream), var(--color-burgundy-pale));
  overflow: hidden;
  margin-bottom: 1.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: var(--photo-frame);
}
.party-pair__frame img { width: 100%; height: 100%; object-fit: cover; }
.party-pair__mark { width: 26%; color: var(--color-burgundy-mid); opacity: 0.7; }
.party-pair__mark svg { width: 100%; height: auto; display: block; }
.party-pair__name { font-family: var(--font-display); font-size: 1.6rem; color: var(--color-burgundy-text); }
.party-pair__role { font-family: var(--font-body); font-style: italic; font-size: 1.08rem; color: var(--color-burgundy-mid); margin-top: 0.25rem; }
.party-pair__desc { font-size: 1.05rem; color: var(--color-ink-soft); margin-top: 0.7rem; max-width: 30em; margin-left: auto; margin-right: auto; }

/* One joint story shared by a pair (currently the Maids of Honor),
   centered beneath both portraits — a comfortable reading-width column,
   not a full-bleed block, so long-form text stays easy to read. No box,
   border or background of its own (just the section's own cream/ivory
   ground) and no decorative flourish/sprig — burgundy serif type only. */
.party-shared-story {
  max-width: 640px;
  margin: 3rem auto 0;
  padding: 0 1rem;
}
.party-shared-story__title {
  font-family: var(--font-display);
  font-size: 1.55rem;
  color: var(--color-burgundy-text);
  text-align: center;
  margin-bottom: 1.6rem;
}
.party-shared-story p:not(.party-shared-story__title) {
  font-family: var(--font-body);
  font-size: 1.3rem;
  line-height: 1.75;
  color: var(--color-burgundy-text);
  margin-bottom: 1.3rem;
  text-wrap: pretty;
}
.party-shared-story p:last-child { margin-bottom: 0; }

/* Used by all three long-form "shared story" blocks (weddingPartySharedStory(
   story, {wide: true}) in templates/page.js): The Proposal Story, the
   Maids of Honor story, and the Best Men story — a substantially wider
   desktop reading column than the default .party-shared-story above,
   since the old ~640px column left large unused margins either side and
   caused excessive vertical scrolling. The Proposal Story sits inside its
   own wider `.proposal-photos .container` (max-width: min(1800px, 94vw));
   the Maids of Honor / Best Men stories sit inside `#wedding-party`'s
   container, which gets the identical max-width override just below so
   both land on the same formula and the same resulting width. Either way,
   82% of that container's available width (container max-width minus its
   own 2.5rem side padding) tracks out to ~70-75% of the actual viewport
   at ordinary desktop and laptop sizes (measured ~72-73% at 1400px/1920px
   viewports), only falling short of that range on very wide/ultrawide
   monitors once the 1400px cap engages — an intentional guard so lines
   never stretch further than comfortable. Font-size/line-height are
   unchanged (the shared `.party-shared-story p` rule above still applies
   to every variant); paragraph text stays left-aligned (only the title
   and the block itself are centered). Mobile is untouched — the base
   `.party-shared-story` rule keeps its own narrower margins below 900px. */
@media (min-width: 900px) {
  .party-shared-story--wide {
    width: 82%;
    max-width: 1400px;
  }
}

/* ---------- Password gate ------------------------------------------------------------ */
.gate {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: var(--color-ivory);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  text-align: center;
}
.gate[hidden] { display: none; }
.gate__panel { max-width: 380px; width: 100%; }
.gate__names {
  font-family: var(--font-script);
  font-size: 2.6rem;
  color: var(--color-burgundy);
  margin-bottom: 0.5rem;
}
.gate__body { color: var(--color-ink-soft); font-size: 1.1rem; margin-bottom: 1.75rem; }
.gate__form { display: flex; flex-direction: column; gap: 1rem; }
.gate__input {
  width: 100%;
  padding: 0.9rem 1rem;
  text-align: center;
  font-family: var(--font-body);
  font-size: 1.2rem;
  letter-spacing: 0.04em;
  border: 1px solid var(--color-line);
  background: var(--color-white);
  border-radius: var(--radius);
  color: var(--color-ink);
}
.gate__error {
  color: var(--color-burgundy);
  font-size: 0.98rem;
  font-style: italic;
  min-height: 1.4em;
}
html:not(.gate-unlocked) body { overflow: hidden; }
html:not(.gate-unlocked) .site-header,
html:not(.gate-unlocked) main,
html:not(.gate-unlocked) .site-footer {
  visibility: hidden;
}

/* ---------- Couple photo moment ---------------------------------------------------
   One quiet, large editorial photograph — the transition beat between the
   wedding-logistics half of the site and the Discover guides. Generous
   cream space around it, no caption/text overlapping the image. */
.couple-photo__frame {
  /* Fills the standard container (--container-max, 1120px) rather than
     capping itself narrower — large and prominent, with the container's
     own side padding providing the generous cream margin around it on
     wide screens. The <img> below only ever sets width/height:auto (no
     object-fit, no fixed aspect-ratio), so the frame simply follows the
     photo's real proportions — no cropping or distortion regardless of
     whether the photo is portrait or landscape. */
  position: relative;
  margin: 0 auto;
  border: var(--photo-frame);
}
.couple-photo__frame img {
  width: 100%;
  height: auto;
  display: block;
}
/* Two-line text overlay, positioned in the open sky near the top of this
   particular photo (not a general-purpose photo-caption pattern — just
   this one image, which happens to have open, subject-free sky up top).
   White with a soft dark shadow for legibility against a bright blue-sky
   background; sized with clamp()/vw so both lines keep to one row each
   at any viewport width, since the photo itself scales fluidly with the
   container rather than sitting at a fixed pixel size. */
.couple-photo__overlay {
  position: absolute;
  top: 7%;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 0 1rem;
  text-align: center;
  pointer-events: none;
}
.couple-photo__overlay-line {
  display: block;
  white-space: nowrap;
  color: var(--color-white);
  text-shadow: 0 2px 14px rgba(20, 20, 30, 0.55), 0 1px 3px rgba(20, 20, 30, 0.5);
}
.couple-photo__overlay-line--title {
  font-family: var(--font-display);
  font-weight: 600;
  /* Lower bound tuned so the longer Italian line ("La Nostra Prima
     Vacanza sulle Alpi Italiane") still fits within the photo frame at
     narrow mobile widths without wrapping or bleeding past the edge —
     verified for both languages down to a 320px viewport. */
  font-size: clamp(0.68rem, 3.2vw, 2rem);
  letter-spacing: 0.02em;
}
.couple-photo__overlay-line:not(.couple-photo__overlay-line--title) {
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(0.62rem, 1.8vw, 1.15rem);
  letter-spacing: 0.01em;
}
.couple-photo__placeholder {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: linear-gradient(160deg, var(--color-cream), var(--color-burgundy-pale));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  text-align: center;
  padding: 1.5rem;
}
.couple-photo__placeholder .sprig { width: 22%; color: var(--color-burgundy-mid); opacity: 0.75; }
.couple-photo__placeholder span {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.2rem;
  color: var(--color-ink-soft);
}

/* ---------- Couple triptych (Welcome → Events) --------------------------------------
   Three Amanda & Mattia photos in one row, between the Welcome message and
   The Celebration. Deliberately modeled on the Proposal triptych below —
   same wide stage well beyond the standard 1120px container, same small
   elegant gap, same swipeable snap-scroll carousel on mobile — but with
   NO larger center frame: all three columns share one identical size, no
   photo more visually important than another. No heading/kicker (a quiet
   photo-only transition, like the single Couple Photo moment above), no
   overlay, no caption text on the photography itself. */
.couple-triptych__container {
  max-width: min(1800px, 94vw);
}
.couple-triptych__row {
  display: flex;
  gap: 1.1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0.6rem 0.2rem 1rem;
  margin: 0 -0.2rem;
}
.couple-triptych__row::-webkit-scrollbar { display: none; }
.couple-triptych__frame {
  flex: 0 0 78%;
  scroll-snap-align: center;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: var(--photo-frame);
}
.couple-triptych__frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
.couple-triptych__placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  text-align: center;
  padding: 1.5rem;
  background: linear-gradient(160deg, var(--color-cream), var(--color-burgundy-pale));
}
.couple-triptych__placeholder .sprig { width: 22%; color: var(--color-burgundy-mid); opacity: 0.75; }
.couple-triptych__placeholder span {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--color-ink-soft);
}
/* Desktop: all three side by side, no scrolling, equal-width columns —
   note the absence of anything like Proposal's `--center` variant. */
@media (min-width: 760px) {
  .couple-triptych__row {
    overflow: visible;
    padding: 0.6rem 0 1rem;
    margin: 0;
    align-items: center;
  }
  .couple-triptych__frame { flex: 1 1 0; aspect-ratio: 3 / 4; }
}
/* One shared, subtle caption for the whole group of three photos — not
   printed over any individual photo, just a quiet line underneath the
   row, centered. */
.couple-triptych__caption {
  margin-top: 0.9rem;
  text-align: center;
  font-style: italic;
  font-size: 1.2rem;
  color: var(--color-ink-soft);
}

/* ---------- Discover Lake Como / Discover Milan --------------------------------------
   A reusable recommendation-guide system — see templates/discover.js for the
   full design rationale. Every category (Sip/Dine/Do/Shop/Nightlife) is a
   card: a burgundy-washed header (photo optional) and a plain list of
   clickable names below it. Clicking/tapping a name opens the one shared
   detail modal (.discover-modal, styled further down) rather than growing
   its own bespoke markup per item — this is what keeps the whole system
   infinitely expandable from content data alone. */
.discover-categories {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.25rem;
  margin-top: var(--space-4);
  align-items: start;
}
@media (min-width: 780px) {
  .discover-categories { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; }
}
/* Discover Milan only: a fixed 3-column, 2-row grid — Sip / Dine — Casual /
   Dine — Elevated on the first row, Do / Shop / Nightlife on the second —
   rather than Como's auto-fit layout. All six cards share the same width,
   photo-header proportions and padding, including Dine — Elevated's
   photo-less placeholder header (reserved at the identical footprint, see
   .discover-category__header--empty below) and the shared dress-code note
   (.discover-category--note further down), which spans the full row. */
@media (min-width: 780px) and (max-width: 1229.98px) {
  /* Milan's own tablet-width step: pinned to exactly 2 columns (rather
     than left to the auto-fit rule above, which — once the container
     clears roughly 940px — starts auto-packing a 3rd 300px+ column on
     its own) so a card's width never shrinks back down into the same
     "too narrow for one line" zone the 1230px breakpoint below is
     specifically avoiding. */
  #discover-milan .discover-categories { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1230px) {
  /* Gated to 1230px, not the 780px auto-fit breakpoint above: a 3-up row
     needs each card to hold its widest content — the Italian nightlife
     feature title, "Un Ultimo Brindisi di Nozze," measured wider than
     the English "One Last Wedding Toast" — on one line. Below this
     width, even combined with the wider .container below, three equal
     columns leave cards too narrow and the title wraps to two lines
     (confirmed by measurement across 900–1200px). Below 1230px, Milan
     uses a pinned 2-column step instead (see above); the fixed
     3-column grid only takes over once there's genuinely enough room
     for it — the .container widening here (beyond the sitewide 1120px
     cap) is what supplies that room once the viewport allows. */
  #discover-milan .discover-categories { grid-template-columns: repeat(3, 1fr); }
  #discover-milan .container { max-width: 1320px; }
}
/* Standardize every Milan category photo on the same aspect ratio — the
   existing Sip/Dine/Do photos' own natural proportions (~3:4 portrait) —
   so all six header images line up edge to edge. object-fit: cover crops
   to fill without ever stretching or distorting the photo; Sip/Dine/Do
   are already almost exactly 3:4 so this is a no-visible-op for them, it
   only affects the wider Shop/Nightlife photos. */
#discover-milan .discover-category__photo {
  aspect-ratio: 3 / 4;
  object-fit: cover;
}
#discover-milan .discover-category__header--empty { aspect-ratio: 3 / 4; }
.discover-category {
  border: var(--photo-frame);
  background: var(--color-white);
}
/* The header shows the category photo exactly as supplied — full
   original file, full original size, no dark/burgundy wash and no text
   over the image. Height simply follows the image's natural aspect
   ratio (see .discover-category__photo below), whatever that photo's
   own proportions call for — nothing is force-cropped or resized to
   match the others (Discover Milan overrides this to a fixed 3:4 ratio
   for all six cards, see above). The category word always runs as a
   normal heading directly below the header, never on top of it — the
   empty (no-photo) state is just a fixed-ratio solid-burgundy block
   reserving a photo's footprint, with the title as its own heading
   underneath, same as every photo card. */
.discover-category__header {
  position: relative;
}
/* The no-photo placeholder is now purely a reserved-space visual (solid
   burgundy wash, same footprint a photo would occupy) — the category
   title used to be centered on top of it, but it now always renders as
   its own heading below the header instead (see .discover-category__label
   below), so this no longer needs to center/pad any inner content. */
.discover-category__header--empty {
  aspect-ratio: 4 / 3;
  background-color: var(--color-burgundy);
}
.discover-category__photo {
  display: block;
  width: 100%;
  height: auto;
}
/* Always a normal heading sitting directly below the header — photo or
   empty placeholder alike — never overlaid on top of either, so every
   category shares one consistent [header][title][listings] structure. */
.discover-category__label {
  display: block;
  font-family: var(--font-display);
  font-size: 1.4rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-burgundy-text);
  padding: 0.85rem 1.35rem 0.6rem;
  border-bottom: 1px solid var(--color-line);
}
.discover-category__list { padding: 1.1rem 1.35rem 1.35rem; }
/* Optional sub-heading (see the `groupLabel` support in
   templates/discover.js) splitting one category's items into clearly
   labeled sections — currently used only by Milan's Dine category
   ("Fancy Restaurants" / "Casual / Less Expensive"). Sits directly above
   the `<ul>` it introduces; a category with no grouped items never
   renders one. */
.discover-category__group-label {
  padding: 1.3rem 1.35rem 0;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-burgundy);
}
.discover-category__group-label + .discover-category__list { padding-top: 0.6rem; }
.discover-category__item {
  padding: 0.7rem 0;
  border-top: 1px solid var(--color-line);
}
.discover-category__item:first-child { border-top: none; }
.discover-category__link {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.55rem;
  background: none;
  border: none;
  padding: 0;
  text-align: left;
  font-family: var(--font-body);
  font-size: 1.08rem;
  color: var(--color-burgundy-text);
  text-decoration: underline;
  text-decoration-color: rgba(106, 28, 40, 0.35);
  text-underline-offset: 4px;
  transition: color var(--transition), text-decoration-color var(--transition);
}
.discover-category__link:hover, .discover-category__link:focus-visible {
  color: var(--color-burgundy);
  text-decoration-color: currentColor;
}
.discover-category__location {
  display: block;
  font-size: 1rem;
  font-style: italic;
  color: var(--color-ink-soft);
  margin-top: 0.15rem;
}
.discover-category__soon {
  padding: 0 1.35rem 1.35rem;
  font-size: 1.1rem;
  font-style: italic;
  color: var(--color-ink-soft);
}
/* Shared badge — used both inline in a category list (next to a name) and
   inside the detail modal — for the small set of personal-connection
   recommendations flagged `ourStory: true`. */
.discover-badge, .discover-modal__badge {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-white);
  background: var(--color-burgundy);
  padding: 0.2rem 0.55rem;
  border-radius: 20px;
  white-space: nowrap;
}
.discover-modal__badge { margin-bottom: 0.6rem; }
.discover-modal__badge[hidden] { display: none; }

/* Informational callouts inside a category (e.g. the VAT refund note in
   Milan Shop) or at the end of a whole region (e.g. the Lake Como boat
   rental placeholder) — a quiet bordered panel, never a garish alert box. */
.discover-callout {
  margin: 1.1rem 1.35rem 1.35rem;
  padding: 1.1rem 1.2rem;
  background: var(--color-burgundy-whisper);
  border-left: 3px solid var(--color-burgundy);
}
.discover-callout--practical {
  margin: 2.5rem auto 0;
  max-width: 760px;
  padding: 1.3rem 1.5rem;
}
/* A shared note card that can sit *inside* the categories grid, between
   two category cards, rather than only at the very end of a region (see
   discoverNoteCard() in templates/discover.js) — e.g. Milan's one dress-
   code note placed once under both Dine cards. Spans the full grid row
   and drops the plain white card frame other categories use, since it's
   not a photo/list card — just the quiet callout panel itself. */
.discover-category--note {
  grid-column: 1 / -1;
  border: none;
  background: none;
}
.discover-category--note .discover-callout--practical {
  margin-top: 0;
  /* This note sits inside a full-width grid row (see
     .discover-category--note above), not the narrower single-column
     flow .discover-callout--practical was originally written for — so
     it can safely use much more of that row's width to settle the body
     copy onto two clean lines instead of shrinking the type. */
  max-width: 1100px;
}
.discover-callout__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy-text);
  margin-bottom: 0.5rem;
}
.discover-callout__body { font-size: 1.1rem; color: var(--color-ink-soft); }
.discover-callout__list {
  list-style: disc;
  margin: 0.6rem 0 0;
  padding-left: 1.15rem;
}
.discover-callout__list li { font-size: 1.1rem; color: var(--color-ink-soft); margin-bottom: 0.3rem; }
.discover-callout__note {
  margin-top: 0.65rem;
  font-size: 1rem;
  font-style: italic;
  color: var(--color-burgundy-mid);
}

/* A single, personal "special feature" within a category — e.g. "One Last
   Wedding Toast" in Milan Nightlife for The Club Milano. This is meant to
   read as a heartfelt invitation from Amanda & Mattia themselves rather
   than a plain clickable recommendation, but the card it lives in must
   still look like every other Discover category card (Sip/Dine/Do/Shop)
   sitting beside it — same bordered white card, same photo-header-on-top
   treatment (the feature's own photo is set as the category's `photo`, so
   it renders in the shared, uncropped .discover-category__photo header,
   never a second nested photo below it), and the same content padding as
   the plain items list it replaces. No separate border/background/margin
   of its own — it's simply this category's content, not a card-in-a-card. */
.discover-feature { padding: 1.1rem 1.35rem 1.35rem; }
.discover-feature__kicker {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-burgundy-mid);
  margin-bottom: 0.6rem;
}
.discover-feature__title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--color-burgundy-text);
}
@media (max-width: 819px) {
  .discover-feature { padding-left: 1rem; padding-right: 1rem; }
  .discover-feature__title { font-size: 1.42rem; }
}
.discover-feature__meta {
  margin-top: 0.35rem;
  font-size: 1.05rem;
  font-style: italic;
  color: var(--color-burgundy-mid);
}
.discover-feature__text {
  margin-top: 1rem;
  font-size: 1.25rem;
  line-height: 1.75;
  color: var(--color-burgundy-text);
}
.discover-feature__note {
  margin-top: 1.4rem;
  padding: 1.05rem 1.2rem;
  background: var(--color-burgundy-whisper);
  border-left: 3px solid var(--color-burgundy);
}
.discover-feature__note-label {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-burgundy-text);
  margin-bottom: 0.4rem;
}
.discover-feature__note-body { margin: 0; font-size: 1.1rem; color: var(--color-ink-soft); }

/* ---------- Discover detail modal -----------------------------------------------------
   The one shared panel every recommendation opens into — populated at
   click time from window.DISCOVER_DATA by main.js. Same [hidden]-toggle
   idiom as .gate/.proposal-lightbox, but a cream card rather than a
   full-bleed dark stage, since this is a reference/detail read rather
   than a cinematic moment. */
.discover-modal {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}
.discover-modal[hidden] { display: none; }
.discover-modal__backdrop { position: absolute; inset: 0; background: rgba(42, 20, 24, 0.6); }
.discover-modal__panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 560px;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--color-ivory);
  border: var(--photo-frame);
  box-shadow: var(--shadow-card);
}
.discover-modal__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 2;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--color-line);
  background: var(--color-white);
  color: var(--color-burgundy-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  line-height: 1;
  transition: background var(--transition);
}
.discover-modal__close:hover, .discover-modal__close:focus-visible { background: var(--color-burgundy-whisper); }
.discover-modal__photo-wrap { width: 100%; aspect-ratio: 4 / 3; overflow: hidden; }
.discover-modal__photo-wrap[hidden] { display: none; }
.discover-modal__photo { width: 100%; height: 100%; object-fit: cover; display: block; }
.discover-modal__body { padding: 1.9rem 1.75rem 2.1rem; }
.discover-modal__name { font-family: var(--font-display); font-size: 1.5rem; color: var(--color-burgundy-text); }
.discover-modal__location {
  margin-top: 0.3rem;
  font-size: 1.1rem;
  font-style: italic;
  color: var(--color-burgundy-mid);
}
.discover-modal__location[hidden] { display: none; }
/* A brief first-person recollection shown near the TOP of the card, right
   under the name/location — distinct from `.discover-modal__why` (a short
   curatorial aside shown further down, after the factual description).
   Currently used only by Il Sereno Al Lago, the one Como Dine
   recommendation the couple has personally visited; every other
   recommendation stays a curated (not personal) suggestion. Same quiet
   whisper-background treatment as `.discover-modal__why`, but set in
   normal (non-italic) type — this reads as a genuine short recollection,
   not an aside. */
.discover-modal__personal-note {
  margin-top: 0.9rem;
  padding: 0.85rem 1rem;
  background: var(--color-burgundy-whisper);
  font-size: 1.1rem;
  font-style: normal;
  color: var(--color-ink-soft);
}
.discover-modal__personal-note[hidden] { display: none; }
/* A short evocative hook line for a personal-connection item's story
   (e.g. "Where we knew there was something special") — quiet, italic,
   script-adjacent emphasis without reaching for the site's script
   typeface. Optional: only items with `storyIntro` show it. */
.discover-modal__story-intro {
  margin-top: 0.9rem;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: 1.25rem;
  color: var(--color-burgundy);
}
.discover-modal__story-intro[hidden] { display: none; }
/* `white-space: pre-line` lets a longer personal story (written with
   blank lines between short paragraphs in content/en.js / content/it.js)
   render as real paragraph breaks instead of collapsing to one dense
   block — every other, shorter `description` in the site is a single
   line anyway, so this is invisible to them. */
.discover-modal__desc { margin-top: 0.95rem; font-size: 1.2rem; color: var(--color-ink-soft); white-space: pre-line; }
.discover-modal__desc[hidden] { display: none; }
.discover-modal__why {
  margin-top: 0.85rem;
  padding: 0.85rem 1rem;
  background: var(--color-burgundy-whisper);
  font-size: 1.1rem;
  font-style: italic;
  color: var(--color-ink-soft);
}
.discover-modal__why[hidden] { display: none; }
.discover-modal__field-label {
  display: block;
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 600;
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-burgundy);
  margin-bottom: 0.25rem;
}
.discover-modal__facts { margin-top: 1.1rem; font-size: 0.94rem; }
.discover-modal__facts > div { border-top: 1px solid var(--color-line); padding: 0.55rem 0; }
.discover-modal__facts > div:first-child { border-top: none; padding-top: 0; }
.discover-modal__facts dt {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-burgundy-mid);
  margin-bottom: 0.15rem;
}
.discover-modal__facts dd { margin: 0; color: var(--color-ink); }
.discover-modal__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
}
.discover-modal__links:empty { display: none; }
.discover-modal__link { margin-top: 1.1rem; }

/* ---------- Photo gallery — "Through the Years" carousel -----------------------------
   A horizontal, slide-through carousel rather than a vertical wall: three
   photos visible side by side on desktop, one prominent photo at a time
   on mobile. Every photo frame is a fixed box (aspect-ratio: 4/5, the
   same portrait-leaning ratio used elsewhere on the site for framed
   photos) but the photo itself never gets object-fit: cover cropping —
   it's `object-fit: contain`, so the full photograph is always visible,
   letterboxed/pillarboxed against a soft cream-to-burgundy wash rather
   than cropped or stretched to fill the box. Desktop arrows/mobile swipe
   both just scroll `.gallery-carousel__viewport` natively (scroll-snap
   makes it settle cleanly on a photo either way) — no JS position math,
   no risk of the two getting out of sync. */
.gallery-empty-note {
  margin-top: 1.25rem;
  text-align: center;
  font-style: italic;
  font-size: 1.15rem;
  color: var(--color-ink-soft);
}
.gallery-carousel {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: var(--space-4);
  max-width: min(1400px, 94vw);
  margin-left: auto;
  margin-right: auto;
}
.gallery-carousel__viewport {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0.3rem 0.1rem 0.6rem;
}
.gallery-carousel__viewport::-webkit-scrollbar { display: none; }
.gallery-carousel__track {
  display: flex;
  gap: 1.25rem;
}
.gallery-carousel__slide {
  flex: 0 0 82%;
  scroll-snap-align: center;
}
@media (min-width: 700px) {
  .gallery-carousel__slide { flex-basis: calc((100% - 2 * 1.25rem) / 3); scroll-snap-align: start; }
}
.gallery-carousel__slide-btn {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  border: var(--photo-frame);
  background: linear-gradient(160deg, var(--color-cream), var(--color-burgundy-pale));
  overflow: hidden;
  cursor: zoom-in;
  padding: 0;
}
.gallery-carousel__slide-btn img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: transform 500ms ease;
}
.gallery-carousel__slide-btn:hover img,
.gallery-carousel__slide-btn:focus-visible img { transform: scale(1.03); }
/* Arrows sit beside the viewport as ordinary flex siblings on desktop
   (plenty of side margin to hold them); on mobile they'd eat into the
   "one photo prominent" width, so they move to small overlaid circles at
   the edges of the photo itself instead — same buttons, no markup
   change, just repositioned. */
.gallery-carousel__arrow {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border: 1px solid var(--color-burgundy);
  border-radius: 50%;
  background: var(--color-cream);
  color: var(--color-burgundy-text);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.gallery-carousel__arrow svg { width: 20px; height: 20px; }
.gallery-carousel__arrow:hover, .gallery-carousel__arrow:focus-visible {
  background: var(--color-burgundy);
  color: var(--color-white);
}
@media (max-width: 699px) {
  .gallery-carousel { gap: 0; }
  .gallery-carousel__arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 40px;
    height: 40px;
    background: rgba(250, 246, 238, 0.88);
    box-shadow: 0 2px 10px rgba(56, 15, 21, 0.18);
  }
  .gallery-carousel__arrow--prev { left: 0.4rem; }
  .gallery-carousel__arrow--next { right: 0.4rem; }
}

/* ---------- Photo gallery lightbox --------------------------------------------------- */
.gallery-lightbox {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.gallery-lightbox[hidden] { display: none; }
.gallery-lightbox__backdrop { position: absolute; inset: 0; background: rgba(56, 15, 21, 0.97); }
.gallery-lightbox__panel {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.gallery-lightbox__stage {
  position: relative;
  max-width: min(92vw, 1300px);
  max-height: calc(100vh - 2rem);
}
.gallery-lightbox__img {
  display: block;
  max-width: min(92vw, 1300px);
  max-height: calc(100vh - 2rem);
  width: auto;
  height: auto;
  object-fit: contain;
  box-shadow: 0 30px 70px -20px rgba(0,0,0,0.6);
}
.gallery-lightbox__close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 2;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid rgba(246,236,226,0.45);
  border-radius: 50%;
  color: var(--color-white);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.gallery-lightbox__close:hover, .gallery-lightbox__close:focus-visible {
  background: rgba(246,236,226,0.14);
  border-color: var(--color-white);
}
.gallery-lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 46px;
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid rgba(246,236,226,0.45);
  border-radius: 50%;
  color: var(--color-white);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.gallery-lightbox__nav svg { width: 22px; height: 22px; }
.gallery-lightbox__nav:hover, .gallery-lightbox__nav:focus-visible {
  background: rgba(246,236,226,0.14);
  border-color: var(--color-white);
}
.gallery-lightbox__nav--prev { left: 0.75rem; }
.gallery-lightbox__nav--next { right: 0.75rem; }
@media (max-width: 640px) {
  .gallery-lightbox { padding: 0.4rem; }
  .gallery-lightbox__nav { width: 38px; height: 38px; }
  .gallery-lightbox__nav--prev { left: 0.25rem; }
  .gallery-lightbox__nav--next { right: 0.25rem; }
}

/* ---------- Utility ---------------------------------------------------------------- */
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
