/* ============================================================
   RUMBO A ANTIGUA — Sarah & Arturo — Wedding Website Styles
   Palette source: Monograma 3 floral moodboard (confirmed by couple)
   ============================================================ */

/* --- Custom fonts (licensed files, not on Google Fonts) --- */
@font-face {
  font-family: 'New Icon Serif';
  src: url('fonts/new-icon-serif-regular.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'New Icon Script';
  src: url('fonts/new-icon-script-regular.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  /* File is the italic-only cut of Venetian 301 — declared as normal
     style since it's the sole weight we have and needs to serve as
     the general body font (nav, buttons, labels, paragraphs). */
  font-family: 'Venetian 301';
  src: url('fonts/venetian-301.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* --- CSS Variables --- */
:root {
  /* Confirmed brand colors (Monograma 3, exact hex from couple's florist) */
  --marfil:      #fffbf2; /* base background — updated cream per new palette */
  --peonia:      #f1d5bd; /* Peonía Empolvada — card / soft surface */
  --miel:        #e9bf7a; /* Miel de Albaricoque — accent, CTA, gold */
  --olivo:       #a99c67; /* Olivo Imperial — decorative line / mid tone */
  --lino:        #8b894f; /* Lino Botánico — secondary accent */
  --dusty-pink:  #c88987; /* Requested pink accent (from the wedding-adaptation-brief palette) */

  /* Derived neutrals (not in the original 5 — needed for text contrast) */
  --ink:         #332c1f; /* main text, warm near-black */
  --ink-deep:    #251a15; /* footer / nav / dark sections — updated dark brown per new palette */
  --muted:       #8a7f63; /* secondary text */
  --border:      #e6d5c2; /* hairlines on marfil */
  --white:       #FFFFFF;

  --font-display: 'New Icon Serif', serif;
  --font-script:  'New Icon Script', cursive;
  --font-body:    'Venetian 301', serif;

  --max-width:   1200px;
  --margin-h:    clamp(24px, 6vw, 100px);
  --radius:      10px;
  --radius-sm:   4px;
  --section-gap: clamp(100px, 12vw, 180px);
}

/* --- Reset & Base --- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-feature-settings: "liga" 1, "kern" 1;
}

html { scroll-behavior: smooth; }

::placeholder { color: var(--muted); opacity: 0.6; font-size: 16px; }

:focus-visible {
  outline: 2px solid var(--lino);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: rgba(233, 191, 122, 0.35); color: var(--ink); }

@keyframes pageFadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.page-header, .hero-fullbleed { animation: pageFadeIn 0.6s ease both; }

body {
  background: var(--marfil);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* --- Typography --- */
h1 {
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(48px, 8.5vw, 96px);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--white);
}

h2 {
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(32px, 5vw, 54px);
  line-height: 1.15;
  color: var(--ink);
}

h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 21px;
  line-height: 1.35;
  color: var(--ink);
}

.script {
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(34px, 5.5vw, 58px);
  line-height: 1.2;
  color: var(--lino);
}

.label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 24px;
  line-height: 1;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  /* When .label lands on a <p> (e.g. the FAQ/Vestimenta CTAs) it was
     silently inheriting the base p{max-width:62ch} rule. With zero
     margin on the element itself, that made the box narrower than
     its container and left-aligned instead of centered — the eyebrow
     text just never needed a paragraph-length wrap limit to begin
     with. */
  max-width: none;
}

p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 29px;
  line-height: 1.5; /* 1.85 read as loose/floating lines in paragraphs like "Cómo llegar" and the concierge card */
  color: var(--muted);
  max-width: 62ch;
}

a { text-decoration: none; color: inherit; }
img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* --- Layout helpers --- */
.container { max-width: var(--max-width); margin: 0 auto; padding: 0 var(--margin-h); }
.center { text-align: center; margin-left: auto; margin-right: auto; }
.section { padding: var(--section-gap) 0; }
.divider {
  width: 48px; height: 1px; background: var(--olivo);
  margin: 20px auto;
}

/* --- Buttons --- */
.btn-primary {
  display: inline-block;
  background: var(--ink-deep);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 25px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 16px 34px;
  border-radius: 999px;
  transition: background 0.25s ease, transform 0.25s ease;
}
.btn-primary:hover { background: var(--lino); transform: translateY(-1px); }

.btn-outline {
  display: inline-block;
  border: 1px solid rgba(255,255,255,0.55);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 25px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 15px 32px;
  border-radius: 999px;
  transition: background 0.25s ease, border-color 0.25s ease;
}
.btn-outline:hover { background: rgba(255,255,255,0.12); border-color: #fff; }

/* --- Nav --- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  /* Above .nav-overlay (210) and .nav-mobile (211) — the bar (and the
     hamburger/X toggle inside it) has to stay visible and clickable
     while the panel is open, not get buried under it. Raised from the
     old 110 because per-page decorative art sitting in the 100-200
     range — Historia's corner ornaments (200), its chapter stickers
     (150), even Belarosa's own scroll photos (101) — was floating
     above the open mobile menu. Deliberately kept below 300, not
     pushed arbitrarily high: index.html's envelope intro (300),
     handoff clouds (310) and its floating badge (400) all need to
     stay above the nav during the homepage's intro/scroll sequence,
     same as before. */
  z-index: 212;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 28px var(--margin-h);
}
/* Applied by site.js once scrolled past the hero — keeps the (by
   default white, for hero-photo pages) hamburger legible once it's
   floating over cream page content instead of the photo. */
.nav-scrolled {
  background: var(--marfil);
  box-shadow: 0 2px 16px rgba(37,26,21,0.08);
}
.nav-scrolled .nav-hamburger-line { background: var(--ink-deep); }
.nav-scrolled .nav-links a { color: var(--ink); }
.nav-scrolled .nav-links a:hover, .nav-scrolled .nav-links a.active { color: var(--lino); border-color: var(--miel); text-shadow: none; }

.nav-mark {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: block;
  height: 34px;
}
.nav-mark img { display: block; height: 100%; width: auto; }
.nav-links { display: none; }
.nav-links a {
  font-family: var(--font-body);
  font-size: 24px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.85);
  padding-bottom: 4px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.nav-links a:hover, .nav-links a.active { color: #34432a; border-color: var(--miel); text-shadow: 0 1px 8px rgba(255,255,255,0.45); }
/* Hamburger — classic three lines. On open, the middle line fades out
   in place (no movement) while the top and bottom lines slide to
   center and rotate into an X — all via transform/opacity on the same
   three elements, never swapped for a separate icon. Color stays
   white in both states. Same easing/duration as the panel so the icon
   and the panel read as one synchronized motion. */
.nav-hamburger {
  display: block;
  width: 26px; height: 20px;
  position: relative;
  background: none; border: none; cursor: pointer; padding: 0;
}
.nav-hamburger-line {
  position: absolute; left: 0; width: 100%; height: 2px; background: var(--white);
  transition: transform 0.7s cubic-bezier(0.76, 0, 0.24, 1), opacity 0.7s cubic-bezier(0.76, 0, 0.24, 1);
}
.nav-hamburger-line:nth-child(1) { top: 0; }
.nav-hamburger-line:nth-child(2) { top: 9px; }
.nav-hamburger-line:nth-child(3) { top: 18px; }
.nav-hamburger.active .nav-hamburger-line:nth-child(1) { transform: translateY(9px) rotate(45deg); }
.nav-hamburger.active .nav-hamburger-line:nth-child(2) { opacity: 0; }
.nav-hamburger.active .nav-hamburger-line:nth-child(3) { transform: translateY(-9px) rotate(-45deg); }

/* Overlay behind the panel — fades in/out, never scales or moves the
   page itself. visibility is delayed on the way in / immediate on the
   way out so it's not clickable (or announced to a11y tools) while
   fully transparent, without adding a JS-timed class swap. */
.nav-overlay {
  position: fixed; inset: 0; z-index: 210;
  background: rgba(20, 18, 12, 0.45);
  opacity: 0; visibility: hidden;
  transition: opacity 0.7s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s linear 0.7s;
}
.nav-overlay.open {
  opacity: 1; visibility: visible;
  transition: opacity 0.7s cubic-bezier(0.76, 0, 0.24, 1), visibility 0s linear 0s;
}

/* Panel — slides in from the right edge only; the page underneath
   never scales or shifts, just the overlay + this panel move. */
.nav-mobile {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 211;
  width: min(420px, 82vw);
  background: var(--ink-deep);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 28px;
  transform: translateX(100%);
  transition: transform 0.7s cubic-bezier(0.76, 0, 0.24, 1);
  box-shadow: -20px 0 60px rgba(0,0,0,0.25);
}
.nav-mobile.open { transform: translateX(0); }
.nav-mobile-links {
  display: flex; flex-direction: column; align-items: center; gap: 22px;
}
.nav-mobile-links a {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--white);
}


/* --- Footer --- (correction #32: marfil/ink -> deep brown/dusty pink) */
.footer {
  background: var(--ink-deep);
  color: var(--dusty-pink);
  text-align: center;
  padding: 90px var(--margin-h) 50px;
}
.footer .script { color: var(--dusty-pink); } /* was var(--lino) — green, no longer used here */
.footer-meta {
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  margin-top: 18px; color: var(--dusty-pink);
}
.footer-links {
  display: flex; justify-content: center; gap: 28px; flex-wrap: wrap;
  margin-top: 40px; padding-top: 30px; border-top: 1px solid rgba(200, 137, 135, 0.35);
}
.footer-links a { font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--dusty-pink); }
.footer-links a:hover, .footer-links a:focus-visible { color: var(--white); }

/* --- Scroll reveal --- */
.reveal, .reveal-left, .reveal-right {
  opacity: 0; transition: opacity 0.9s ease, transform 0.9s ease;
}
.reveal { transform: translateY(24px); }
.reveal-left { transform: translateX(-24px); }
.reveal-right { transform: translateX(24px); }
.reveal.visible, .reveal-left.visible, .reveal-right.visible {
  opacity: 1; transform: none;
}

/* ============================================================
   INVITATION INTRO — full-screen click-to-open envelope. Isolated
   from the rest of the site's styles; see invitation-intro.js for
   the GSAP timeline that drives all of the transform/opacity work
   below. Layout only lives here — no animation states are defined
   in CSS except the two end-states (closed markup default, and the
   .reduced-motion fallback), so there's exactly one source of truth
   for "what does open actually look like."
   ============================================================ */
#invitation-intro {
  position: fixed; inset: 0; z-index: 300;
  overflow: hidden;
  /* Matches home.css's .atmosphere-sky gradient — as the envelope
     photo (.hero-background) fades out over the scroll-exit, this is
     what shows through underneath, so it should already read as the
     incoming sky, not a dark brown gap (correction: envelope -> sky
     handoff). */
  background: linear-gradient(180deg, #cfe3ef 0%, #aecbdd 45%, #8fb2c9 100%);
}
#invitation-intro.intro-hidden { display: none; }

.hero-background {
  position: absolute; inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Only what's needed for the overlaid white text to read — the photo
   itself stays fully visible, no heavy scrim. */
.hero-background::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,18,12,0.32) 0%, rgba(20,18,12,0.08) 30%, rgba(20,18,12,0.4) 100%);
}

.hero-copy {
  position: absolute; top: 9vh; left: 0; right: 0;
  text-align: center; color: var(--white); z-index: 2;
  padding: 0 var(--margin-h);
}
.invite-eyebrow {
  font-family: var(--font-body);
  font-size: 16.1px; /* 14px + 15% */ letter-spacing: 0.3em; text-transform: uppercase;
  color: rgba(255,255,255,0.88);
  text-shadow: 0 2px 14px rgba(0,0,0,0.4);
}
.invite-names {
  font-family: var(--font-script);
  font-size: clamp(40px, 8vw, 84px);
  font-weight: 400;
  color: var(--white);
  margin: 10px 0 0;
  text-shadow: 0 4px 30px rgba(0,0,0,0.45);
}
.invite-names .script { color: var(--miel); }

/* Envelope + hint used to be positioned independently (trigger centered
   via top:52%, hint pinned to bottom:9vh) — that made "put the hint
   right under the envelope" unreliable, since the envelope's own
   rendered height depends on its width clamp() and can't be predicted
   from the hint's fixed vh offset. Wrapping both in one flex column
   and centering THAT as a unit means the hint always sits directly
   under the envelope, at any viewport size, with no separate math to
   keep in sync. */
.envelope-stage {
  position: absolute; left: 50%;
  /* Was top:52% on the trigger alone — brought up 40px per request. */
  top: calc(52% - 40px);
  transform: translate(-50%, -50%);
  z-index: 2;
  display: flex; flex-direction: column; align-items: center;
}

.envelope-trigger {
  position: static;
  background: none; border: none; padding: 0; margin: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.envelope-trigger[aria-disabled="true"] { cursor: default; }

.envelope {
  position: relative;
  /* 25% smaller than the original clamp(340px,40vw,650px) — the couple
     in the background photo were getting covered. Every part (body,
     flap, seal, reveal) is sized as a % of this box, so shrinking just
     this one value scales the whole envelope proportionally. */
  width: clamp(255px, 30vw, 488px);
  /* Aspect ratio of the body artwork (945:628) — the flap/seal layers
     are sized off this box, not the other way around. */
  aspect-ratio: 945 / 628;
  filter: drop-shadow(0 26px 46px rgba(20,18,12,0.38));
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), filter 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  /* Viewing context for the flap's rotateX hinge below — without this,
     rotateX just squashes the layer flat instead of reading as a
     plane tilting away in 3D space. */
  perspective: 1400px;
}
@media (hover: hover) {
  .envelope-trigger:not([aria-disabled="true"]):hover .envelope {
    transform: translateY(-4px) scale(1.012);
    filter: drop-shadow(0 34px 56px rgba(20,18,12,0.44));
  }
}

.envelope-layer {
  position: absolute; top: 0; left: 0; width: 100%; height: auto;
  /* The site-wide base img{} rule forces width/height:100% + object-fit:
     cover — fine for a photo, but it was stretching/cropping every one
     of these (especially the seal, squashed into a tall sliver at
     15% width x 100% of the envelope's height). object-fit only
     matters when a box's declared size doesn't match the image's own
     aspect ratio, but setting it defensively here means no future
     layer in this stack can silently inherit the stretch bug. */
  object-fit: contain;
  pointer-events: none; user-select: none;
  -webkit-user-drag: none;
}
/* Explicit stacking, not left to DOM order — the flap layers each get
   their own rotateX transform below, and any non-none transform opens
   a new stacking context, which makes relying on plain source order
   fragile. Bottom to top, now that the card is physically sandwiched
   inside the envelope rather than just masked by one body layer:
   open flap (back structure) < envelope-body-img (back/base body,
   the original asset) < the card < envelope-body-front (the new
   front-pocket art, with its own alpha "mouth" cut into it) < closed
   flap < wax seal. The front pocket sits above the card at all times,
   static — never animated mid-reveal — so however much of the card
   is behind its opaque area stays hidden and whatever aligns with its
   cut-out mouth (or rises above the envelope entirely) shows through.
   No clip-path, no mid-animation z-index swap, just correct static
   stacking doing the masking for free. */
.envelope-flap-open { z-index: 1; opacity: 0; }
.envelope-body-img { z-index: 2; height: 100%; }
.card-clip-stage { z-index: 3; }
.envelope-body-front { z-index: 4; height: 100%; }
.envelope-flap-closed { z-index: 5; }
.wax-seal { z-index: 6; }

/* Flap art is a taller/wider canvas (1619:971) than the body — sized
   off its OWN aspect ratio via height:auto rather than stretched to
   the body's box, so the lace never distorts. backface-visibility:
   hidden is a defensive guard against a mirrored flash right at the
   exact 90deg edge-on frame in some browsers.

   The two flap PNGs are NOT interchangeable positionally, even though
   they share canvas dimensions: the closed flap's artwork is wide at
   its own top (the hinge) tapering to a tip near its own bottom (the
   seal), so top:0 (matching the envelope's own top edge = the real
   hinge) is correct for it as-is. The open flap's artwork is a
   vertical mirror of that — tip near its own top, wide/hinge-looking
   base near its own bottom — because it depicts the flap AFTER it has
   folded back past edge-on: the hinge is still the envelope's top
   edge, but on this asset that hinge line is the BOTTOM of the image,
   with the rest of the art (the visible lace) extending upward past
   it. envelope-body.png is a ~99%-opaque rectangle covering the whole
   envelope box top-to-bottom, so anything positioned inside that same
   box (as the old shared top:0 rule put the open flap) sits entirely
   behind it and is invisible, regardless of z-index. Anchoring the
   open flap by bottom:100% instead puts its own hinge line exactly at
   the envelope's top edge and lets the rest of the art extend upward,
   OUTSIDE the body's box, where z-index:1 (below the card and body)
   is still visible because nothing opaque overlaps it there. */
.envelope-flap-closed, .envelope-flap-open {
  height: auto; width: 108%; left: -4%;
  backface-visibility: hidden;
}
.envelope-flap-closed {
  top: 0;
  transform-origin: top center;
}
.envelope-flap-open {
  top: auto;
  bottom: 100%;
  transform-origin: bottom center;
}

.wax-seal {
  /* Sits at the closed flap's tip: at matched width the flap's own
     1619:971 aspect covers ~90.25% of the body-aspect (945:628)
     envelope box; scaled 108% for the resized flap, that's 97.47%,
     then nudged up 25px (~7.35% at the current rendered envelope
     height of ~340px) per request: 97.47% - 7.35% = 90.12%.
     Width itself is 15% * 1.25 = 18.75%, per the later "25% bigger"
     request — top/transform stay as-is since they anchor the seal by
     its own center. */
  width: 18.75%;
  left: 50%; top: 90.12%;
  /* Base centering (-50%,-50%) plus a literal 4px-left/13px-up nudge
     (5px + a later +15px request, then -7px down) — kept as calc() so
     the request stays visible rather than baked into a recomputed %
     that would hide where it came from. */
  transform: translate(calc(-50% - 4px), calc(-50% - 13px));
  filter: drop-shadow(0 6px 14px rgba(20,18,12,0.3));
}

/* The card-rise effect relies on TWO independent occlusion systems that
   each do a different job:

   1) envelope-body-front's own opaque art (z-index:4, above the card)
      creates the realistic pocket shape — it hides the card behind the
      olive paper and lets it show through the cut-out "mouth" at the
      top. That's what makes the reveal look like a real envelope mouth
      instead of a straight-edged mask.

   2) .card-clip-stage (this element) is a separate, purely geometric
      backstop: nothing belonging to the card may EVER render below the
      envelope's own physical bottom edge, no matter how far down the
      card's hidden resting position sits or how tall .intro-reveal's
      own box is. envelope-body-front only occludes where its PNG
      actually has opaque pixels — it has no artwork at all below the
      envelope's bottom, so without this wrapper the card's lower
      portion would show as a bare rectangle hanging beneath the
      envelope while rising.

   This box is therefore positioned TALLER than the envelope and
   shifted up (top:-120%, well past the card's max rise, which peaks
   around -84% of the envelope's height) so the card can freely rise
   through it, but pinned with bottom:0 so its own bottom edge is
   EXACTLY the envelope's bottom edge — never higher, never lower —
   and overflow:hidden turns that into a hard boundary. It must not be
   envelope { overflow:hidden } directly: that would also clip the
   flap art, which deliberately extends outside the envelope's box
   (see .envelope-flap-open above). This wrapper is scoped to just the
   card. It never moves and never changes z-index — only .intro-reveal,
   positioned inset:0 within it, moves (see invitation-intro.js). */
.card-clip-stage {
  position: absolute; left: 8%; right: 8%;
  top: -120%;
  /* 3px of intentional overscan, not 0 — envelope-body-front's own
     bottom edge has a few px of anti-aliased/transparent pixels rather
     than being 100% opaque right to the last row, so a mask that ends
     exactly at the mathematical bottom of the container let a hairline
     of the card's own cream fill show through underneath the visible
     artwork. Pulling the clip boundary up those few px hides it — the
     overlap itself is invisible since the (still fully opaque a few px
     up) front-pocket art covers it. */
  bottom: 3px;
  overflow: hidden;
  /* overflow:clip (progressive enhancement — unsupported browsers just
     keep the overflow:hidden above) + contain:paint force this box into
     its own paint-containment context. Verified working with plain
     overflow:hidden alone in this codebase's testing, but Safari/WebKit
     has a known history of failing to clip a GPU-composited descendant
     (which .intro-reveal is, since GSAP moves it via `transform`) against
     an ancestor's overflow:hidden — this closes that gap defensively. */
  overflow: clip;
  contain: paint;
  pointer-events: none;
}
.intro-reveal {
  /* top:29.55% is relative to .card-clip-stage's own box (which spans
     -120% to ~0% of the ENVELOPE's height, i.e. 220% tall) and puts
     this element's natural top edge at envelope-relative -55% — same
     derivation as before. Height is no longer a fixed % of that
     taller parent, though: aspect-ratio drives it directly off this
     element's own width instead, which is the actual fix for the
     "long ticket" proportion — the old fixed-% height had no relation
     to how wide the card actually renders at a given envelope size. */
  position: absolute; left: 0; right: 0;
  top: 29.55%;
  aspect-ratio: 4 / 5;
  border-radius: 2px;
  /* Keeps content inside THIS card's own rounded rect. card-clip-stage
     only clips the BOTTOM edge against the envelope — this is a
     separate, smaller concern. */
  overflow: hidden;
  /* A physical card, not a UI surface: warm cream/ivory stock (the
     project's existing --marfil token) with a faint tonal gradient
     for a hint of paper variation, not a flat single color. Square-
     ish corners and a soft, low paper shadow — not a modal shadow.
     This background is the shared backdrop behind EVERY card state
     below — both are transparent and just show it through. */
  background: linear-gradient(165deg, #fffdf8 0%, var(--marfil) 55%, #f4ecdb 100%);
  box-shadow: 0 4px 14px rgba(35, 28, 16, 0.16);
  opacity: 0;
}

/* ----------------------------------------------------------
   CARD CONTENT — sits inset:0 inside .intro-reveal, is-active by
   default so it's part of the card's very first visible frame
   (printed on the paper, not faded in after the fact). Position,
   size and the card's own footprint never change once the click
   timeline hands off.
---------------------------------------------------------- */
.card-state {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  opacity: 0;
  pointer-events: none;
}
.card-state.is-active { opacity: 1; pointer-events: auto; }

.card-state--final { gap: 8%; padding: 8% 12%; }
/* Card typography — small editorial kicker (now the couple's names,
   set in --font-body/Venetian 301 per request), the tagline as the
   dominant focal element (--font-script, the same romantic treatment
   the site already uses for the couple's names elsewhere), small
   supporting date line. Sized in clamp() against the card's own
   compact width (it's ~84% of the clamp(255px,30vw,488px) envelope,
   not a full-viewport hero), not the larger scale used by the site's
   full-page headlines. */
.invitation-card-kicker {
  font-family: var(--font-body);
  font-style: italic;
  /* 75% bigger than the original clamp(11px, 3.4vw, 15px) per request. */
  font-size: clamp(19.25px, 5.95vw, 26.25px);
  color: var(--ink-deep);
}
.invitation-card-kicker .amp { color: #34432a; } /* site's established dark green accent (nav hover, RSVP theme, monogram) */
.invitation-card-names {
  font-family: var(--font-script);
  font-weight: 400;
  font-size: clamp(24px, 9vw, 42px);
  line-height: 1.1;
  color: var(--ink);
}
.invitation-card-date {
  font-family: var(--font-body);
  font-size: clamp(10px, 2.6vw, 13px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.invite-hint {
  /* Now a static flex child of .envelope-stage, right under the
     envelope — position/bottom no longer needed. */
  margin-top: 22px;
  text-align: center; z-index: 2;
  font-family: var(--font-body);
  /* 13px was reading too small — bumped by the requested 12pt
     (=16px at the standard 96dpi CSS reference) to 29px, then dialed
     back 5% off THAT size per the next request (29px * 0.95). */
  font-size: 27.55px; letter-spacing: 0.24em; text-transform: uppercase;
  color: rgba(255,255,255,0.85);
  text-shadow: 0 2px 10px rgba(0,0,0,0.35);
}
.invite-hint.pulse { animation: invite-hint-pulse 2.6s ease-in-out infinite; }
@keyframes invite-hint-pulse { 0%, 100% { opacity: 0.85; } 50% { opacity: 0.45; } }

@media (max-width: 640px) {
  .hero-copy { top: 8vh; }
  .envelope { width: 64vw; } /* 85vw - 25% */
}

/* ============================================================
   HERO
   ============================================================ */
.hero-fullbleed {
  position: relative;
  min-height: 100vh;
  display: flex; align-items: flex-end;
  background: linear-gradient(180deg, rgba(42,36,23,0.15), rgba(42,36,23,0.72)), var(--lino);
  color: var(--white);
}
.hero-inner {
  width: 100%;
  padding: 0 var(--margin-h) 90px;
  text-align: center;
}
.hero-eyebrow {
  font-family: var(--font-body);
  font-size: 24px; letter-spacing: 0.2em; text-transform: uppercase;
  color: rgba(255,255,255,0.8);
  margin-bottom: 18px;
}
.hero-fullbleed h1 { margin: 4px 0; }
.hero-fullbleed .script { color: var(--miel); }

/* ============================================================
   PHOTO HERO — full-bleed photograph, transparent nav on top,
   flush to the very top of the page
   ============================================================ */
.photo-hero { position: relative; width: 100%; height: 82vh; overflow: hidden; }
.photo-hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-hero-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,20,10,0.28) 0%, rgba(20,20,10,0.1) 35%, rgba(20,20,10,0.6) 100%);
}
.photo-hero-content {
  position: absolute; left: 0; right: 0; bottom: 0;
  text-align: center; padding: 0 var(--margin-h) 56px;
}
@media (max-width: 720px) {
  .photo-hero { height: 62vh; }
}
.hero-sub {
  font-family: var(--font-body);
  font-size: 25px; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.8);
  margin: 18px 0 34px;
}
.hero-scroll-hint {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
  color: rgba(255,255,255,0.6);
  animation: bob 2.2s ease-in-out infinite;
}
@keyframes bob { 0%,100% { transform: translate(-50%,0);} 50% { transform: translate(-50%,8px);} }

/* --- Poppy wreath / crest accents (interim illustration identity) --- */
.crest {
  width: clamp(140px, 20vw, 220px);
  margin: 0 auto 18px;
  opacity: 0.92;
}
.crest img { object-fit: contain; }

/* ============================================================
   COUNTDOWN
   ============================================================ */
.countdown {
  display: flex; justify-content: center; gap: clamp(18px, 4vw, 44px);
  margin: 30px 0;
}
.countdown-unit { text-align: center; }
.countdown-num {
  font-family: var(--font-body);
  font-size: clamp(34px, 6vw, 54px);
  color: var(--white);
  line-height: 1;
}
.countdown-label {
  font-family: var(--font-body);
  font-size: 22px; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255,255,255,0.65);
  margin-top: 6px;
}

/* ============================================================
   CARDS — itinerary / hotel / faq (shared across inner pages)
   ============================================================ */
.card {
  background: var(--peonia);
  border-radius: var(--radius);
  padding: clamp(28px, 4vw, 48px);
}

.day-card { background: var(--peonia); border-radius: var(--radius); padding: clamp(28px, 4vw, 44px); margin-top: 40px; }
.day-card-eyebrow { font-family: var(--font-body); font-size: 15px; letter-spacing: 0.16em; text-transform: uppercase; color: #34432a; }
.event-row { display: flex; gap: 24px; padding: 22px 0; border-top: 1px solid rgba(139,137,79,0.2); }
.event-row:first-of-type { border-top: none; }
.event-time { flex: 0 0 90px; font-family: var(--font-body); font-weight: 500; color: var(--lino); font-size: 26px; letter-spacing: 0.04em; }
.event-detail p { color: var(--ink); max-width: none; }
.event-detail strong { color: var(--ink); font-weight: 600; }

.hotel-card {
  display: block;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}
a.hotel-card:hover { border-color: var(--miel); box-shadow: 0 8px 24px rgba(42,36,23,0.1); transform: translateY(-2px); }
.hotel-card-img { aspect-ratio: 16/10; background: var(--peonia); }
.hotel-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hotel-card-body { padding: 26px; }
.stars { color: var(--miel); letter-spacing: 2px; font-size: 14px; }

.cards-grid { display: grid; grid-template-columns: repeat(var(--cols, 3), 1fr); gap: 28px; }
@media (max-width: 900px) { .cards-grid { grid-template-columns: 1fr; } }

.rec-list { list-style: none; padding: 0; margin: 0; }
.rec-list li { padding: 10px 0; border-top: 1px solid var(--border); color: var(--ink); font-size: 18px; }
.rec-list li:first-child { border-top: none; }
.rec-list strong { color: var(--lino); font-weight: 500; }
/* Guía local cards only — 10% bigger than the shared .around-card/
   .rec-list defaults above (18px * 1.1, 15px * 1.1), scoped to
   #panel-guia so the Tours y experiencias cards elsewhere keep their
   own sizing untouched. */
#panel-guia .around-card .label { font-size: 16.5px; }
#panel-guia .rec-list li { font-size: 19.8px; }

/* ============================================================
   NAV — ON LIGHT — the default nav chrome (white hamburger bars)
   is built to sit over a dark photo-hero. Pages without one
   (Viaje / Hospedaje) need a dark-on-light variant instead.
   ============================================================ */
.nav--on-light .nav-hamburger-line { background: var(--ink); }
.nav--on-light .nav-links a { color: var(--muted); }
.nav--on-light .nav-links a:hover, .nav--on-light .nav-links a.active { color: var(--lino); border-color: var(--miel); }

/* ============================================================
   PAGE HEADER — no-photo inner-page header (Viaje / Hospedaje,
   layout borrowed from Theresa & Juanma's stay/travel pages)
   ============================================================ */
.page-header { padding: 90px var(--margin-h) 50px; text-align: center; }
.page-header .label { display: block; margin-bottom: 14px; }
.page-header p { margin: 14px auto 0; max-width: 520px; color: var(--muted); }

/* ============================================================
   TAB SWITCHER (Viaje — "Cómo llegar" / "Tours y experiencias")
   ============================================================ */
.travel-tabs-nav {
  display: flex; gap: 0; justify-content: center;
  padding: 0 var(--margin-h);
  border-bottom: 1px solid var(--border);
  overflow-x: auto; scrollbar-width: none;
}
.travel-tabs-nav::-webkit-scrollbar { display: none; }
@media (max-width: 640px) {
  /* Centered + overflow clips both edge tabs with no scroll hint on
     narrow screens — left-align so the first tab is always visible
     and "there's more to scroll" reads naturally. Snapping makes the
     drag land cleanly on a tab instead of stopping mid-label, and the
     mask-image fades whichever edge still has tabs hidden past it, so
     a tab visibly gets cut off instead of just clipping flush with
     the screen edge — the fade lives on the container (not a
     pseudo-element) specifically so it stays pinned to the viewport
     edge as the row scrolls underneath it, rather than scrolling away
     with the tabs. site.js toggles .is-at-start/.is-at-end as you
     scroll so the fade never implies there's more in a direction
     that's already fully in view. */
  .travel-tabs-nav {
    justify-content: flex-start;
    scroll-snap-type: x proximity;
    /* Without this, snapping the first tab's start edge to the
       scrollport ignores the container's own left padding and quietly
       scrolls it away on load (scrollLeft lands on ~24px instead of
       0) — scroll-padding tells snap to treat the padding box as the
       real edge, so the tab row opens flush against the page margin
       like every other element instead of scroll-snapping past it. */
    scroll-padding-inline: var(--margin-h);
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 32px), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 24px, #000 calc(100% - 32px), transparent 100%);
  }
  .travel-tabs-nav.is-at-start {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent 100%);
  }
  .travel-tabs-nav.is-at-end {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 24px);
    mask-image: linear-gradient(to right, transparent 0, #000 24px);
  }
  .travel-tabs-nav.is-at-start.is-at-end { -webkit-mask-image: none; mask-image: none; }
}
.travel-tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 18px 22px; margin-bottom: -1px;
  font-family: var(--font-body); font-size: 23px; letter-spacing: 0.15em; text-transform: uppercase;
  color: var(--muted); cursor: pointer; white-space: nowrap; transition: all 0.2s ease;
}
@media (max-width: 640px) {
  /* Smaller than desktop so the next tab peeks further into view
     (another passive hint there's more), and so the active tab isn't
     the loudest thing on the page at this width. */
  .travel-tab { font-size: 18px; padding: 16px 16px; scroll-snap-align: start; }
}
.travel-tab.active { color: var(--lino); border-bottom-color: var(--miel); }
.travel-tab:hover { color: var(--lino); }

.travel-panels { padding: 56px var(--margin-h) 0; }
.travel-panel { display: none; }
.travel-panel.active { display: block; }

.travel-steps { display: flex; flex-direction: column; gap: 30px; max-width: 640px; margin: 0 auto; }
.travel-step { display: flex; gap: 22px; align-items: flex-start; }
.step-circle {
  width: 38px; height: 38px; min-width: 38px; border-radius: 50%;
  background: var(--peonia); display: flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-style: italic; font-size: 29px; color: var(--lino);
}
.step-content .label { display: block; margin-bottom: 6px; }
.step-content p { max-width: none; color: var(--ink); }

.around-cards { display: grid; grid-template-columns: repeat(var(--cols, 3), 1fr); gap: 20px; }
.around-card {
  background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 24px; text-decoration: none; color: inherit; display: block;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
a.around-card:hover { border-color: var(--miel); box-shadow: 0 4px 16px rgba(42,36,23,0.06); }
/* Illustration sits above the label/heading/body, one consistent
   height across the row regardless of each piece's own aspect ratio
   (the volcano/lake/umbrella art aren't cropped to match each other —
   they're painted at very different proportions) — bottom-aligned so
   the landscape pieces read as sitting on a shared ground line. */
.around-card-illustration {
  height: 130px;
  margin-bottom: 18px;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
}
.around-card-illustration img { max-width: 100%; max-height: 100%; width: auto; height: auto; }
/* Price/tag eyebrow (e.g. "Desde $525 USD/persona") reads as a small
   badge, not competing with the card title below it — the site-wide
   .label bump (12->24px) had made it the loudest text in the card. */
.around-card .label,
.theme-earth .around-card .label { display: block; margin-bottom: 8px; font-size: 15px; color: var(--ink); text-transform: none; }
.around-card h3 { font-family: var(--font-display); font-size: 25px; color: var(--ink); margin-bottom: 8px; }
.around-card p { font-size: 22px; line-height: 1.55; max-width: none; color: var(--muted); }

.contact-card {
  position: relative; background: var(--white); border: 1.5px solid var(--miel); border-radius: var(--radius);
  padding: 30px 34px; max-width: 620px; margin: 40px auto 0; text-align: center;
}
.contact-card .contact-phone { font-family: var(--font-display); font-style: italic; font-size: 19px; color: var(--lino); }
/* The card is narrow (max-width:620px, often much less), so the base
   29px/1.5 wraps this short paragraph into many tall-spaced lines —
   shrink it to match .contact-phone and tighten the ratio further. */
.contact-card p { font-size: 19px; line-height: 1.4; color: var(--ink); }

@media (max-width: 720px) { .around-cards { grid-template-columns: 1fr; } }

/* ============================================================
   HOTEL CARD — header/tags additions (Hospedaje)
   ============================================================ */
.hotel-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.hotel-header h3 { font-family: var(--font-display); font-size: 20px; color: var(--ink); margin: 0; }
.hotel-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 4px; }
.hotel-tag {
  /* Was a small location pill ("Antigua Guatemala") — now a real
     "Reserva ahora" call-to-action, styled as a button so it reads
     as clickable (the whole card is already the link). */
  font-family: var(--font-body); font-weight: 600; font-size: 16px; letter-spacing: 0.08em; text-transform: uppercase;
  background: #34432a; border-radius: 100px; padding: 10px 22px; color: var(--white);
}

/* ============================================================
   FLOATING STICKER — scrapbook travel ephemera (stamps, postmark,
   map) scattered around Viaje's hero and cards. The base class holds
   what's shared; each instance below gets its own class for desktop
   position/size plus a mobile override, instead of the old per-image
   inline `style` (inline styles can't be overridden from a media
   query without !important, so mobile-specific placement needs its
   own selector). Every sticker keeps a spot at every width — none are
   display:none'd away — sized down and pulled toward the nearest
   gutter (24px on the smallest phones this site supports) so nothing
   clips past the viewport edge, same approach as .corner-ornament
   above.
   ============================================================ */
.floating-sticker {
  position: absolute; height: auto; pointer-events: none; z-index: 2;
  filter: drop-shadow(0 6px 14px rgba(42,36,23,0.22));
}

/* --- Hero (page-header) trio --- */
.stamp-hero-diamond { top: 4%; left: 2%; width: 158px; opacity: 0.5; transform: rotate(-9deg); }
.stamp-hero-postmark { top: 6%; right: calc(2% + 100px); width: 244px; opacity: 0.5; transform: rotate(6deg); }
.stamp-hero-bienvenido { top: 150px; right: 6%; width: 139px; opacity: 0.5; transform: rotate(5deg); }

/* --- Contact card (Cómo llegar) — Sarah & Arturo --- */
.stamp-contact-sarah { top: -46px; right: -24px; width: 92px; transform: rotate(10deg); }
.stamp-contact-arturo { bottom: -40px; left: -24px; width: 92px; transform: rotate(-9deg); }

/* --- Hospedaje day-card --- */
.stamp-hospedaje-map { top: -40px; right: -30px; width: 180px; opacity: 0.9; transform: rotate(6deg); }

@media (max-width: 640px) {
  /* Header padding-top is 90px, clearing the fixed nav (76px tall) —
     the trio sits in that band, above the "Antigua Guatemala" label,
     instead of the desktop's percentage-based placement which would
     otherwise land them under the nav or over the headline. */
  .stamp-hero-diamond { top: 18px; left: 6px; width: 110px; opacity: 0.55; }
  /* Nav is 76px tall and its hamburger sits in the top-right corner
     (fixed, no opaque background until scrolled) — push the postmark
     below it instead of behind it, or the two visually collide. */
  .stamp-hero-postmark { top: 88px; right: 6px; width: 141px; opacity: 0.5; }
  .stamp-hero-bienvenido { top: auto; bottom: 6px; left: 10px; width: 106px; opacity: 0.5; }

  /* The card's text runs nearly edge-to-edge at this width (327px
     card, ~259px content), so a corner stamp has to clear the first/
     last text line entirely rather than just nudge past it — sized
     and offset so each stamp hangs mostly outside the card, the way
     both already do on desktop. */
  .stamp-contact-sarah { top: -58px; right: -8px; width: 66px; }
  .stamp-contact-arturo { bottom: -58px; left: -8px; width: 66px; }

  .stamp-hospedaje-map { top: -20px; right: -10px; width: 144px; }
}

.faq-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-top: 3px solid #34432a; /* site's established dark green accent (RSVP theme, nav hover) */
  border-radius: var(--radius-sm);
  padding: 22px 26px;
  margin-bottom: 14px;
}
.faq-question {
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
  cursor: pointer;
  font-family: var(--font-display); font-size: 19px; color: var(--ink);
}
.faq-question::after {
  content: '+'; flex-shrink: 0; font-family: var(--font-body); font-size: 20px; color: var(--lino);
  transition: transform 0.3s ease;
}
.faq-card.open .faq-question::after { transform: rotate(135deg); }
.faq-answer {
  max-height: 0; overflow: hidden;
  transition: max-height 0.35s ease;
}
.faq-card.open .faq-answer { max-height: 400px; margin-top: 14px; }
.faq-answer p { color: var(--muted); }

/* Two-column editorial layout: questions left, sticky photo right
   (layout borrowed from Theresa & Juanma's faq.html) */
.faq-layout { display: grid; grid-template-columns: 1fr 380px; gap: 56px; max-width: var(--max-width); margin: 0 auto; align-items: start; }
/* FAQ.png is a self-framed illustration (decorative lace oval baked
   into the transparent PNG, not a plain rectangular photo) — no
   border-radius/overflow:hidden clipping or object-fit:cover crop
   here, either would cut off the frame's own scalloped edges. */
.faq-photo { position: sticky; top: 100px; }
.faq-photo img { width: 100%; height: auto; display: block; }
@media (max-width: 900px) {
  .faq-layout { grid-template-columns: 1fr; gap: 40px; }
  .faq-photo { position: static; }
}

/* ============================================================
   AUDIO TOGGLE
   ============================================================ */
.audio-toggle {
  position: fixed; bottom: 24px; right: 24px; z-index: 60;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--ink-deep); color: var(--white);
  border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px;
  box-shadow: 0 8px 20px rgba(42,36,23,0.25);
  transition: transform 0.2s ease;
}
.audio-toggle:hover { transform: scale(1.06); }

/* --- Section eyebrow/heading rhythm (reused every inner page) --- */
.section-head { text-align: center; margin-bottom: 50px; }
.section-head .label { margin-bottom: 14px; }
.section-head p { margin: 18px auto 0; }

/* ============================================================
   ORNAMENT DIVIDER (pattern from Regi & Gian's shared.css)
   ============================================================ */
.ornament {
  display: flex; align-items: center; justify-content: center;
  margin: 28px auto; max-width: 280px;
  color: var(--olivo); opacity: 0.7;
}
.ornament.light { color: rgba(255,255,255,0.55); }
.ornament.narrow { max-width: 180px; margin: 20px auto; }
.ornament-line { flex: 1; height: 1px; background: currentColor; }
.ornament-dot { width: 3px; height: 3px; border-radius: 50%; background: currentColor; margin: 0 6px; flex-shrink: 0; }
.ornament-diamond { width: 6px; height: 6px; border: 1px solid currentColor; transform: rotate(45deg); margin: 0 10px; flex-shrink: 0; }

/* ============================================================
   PROGRAMA — two-column schedule grid (time left, events right)
   ============================================================ */
.schedule-grid { max-width: 820px; margin: 0 auto; }
.schedule-day {
  display: grid; grid-template-columns: 170px 1fr; gap: 0 40px;
  margin-bottom: 56px;
}
.schedule-day:last-child { margin-bottom: 0; }
.schedule-date-label {
  font-family: var(--font-body); font-style: italic; font-weight: 400;
  font-size: 33px; color: var(--ink); line-height: 1.25;
}
.schedule-events-col { border-left: 1px solid var(--border); padding-left: 40px; }
.schedule-event { margin-bottom: 38px; padding-bottom: 38px; border-bottom: 1px solid var(--border); }
.schedule-event:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; }
.schedule-event .event-title {
  font-family: var(--font-display); font-size: clamp(21px, 2.6vw, 27px);
  color: var(--ink); margin-bottom: 8px; line-height: 1.2;
}
.schedule-event .event-detail { font-family: var(--font-body); font-size: 28px; color: var(--muted); line-height: 1.7; margin-bottom: 10px; max-width: none; }
.schedule-event .event-meta { display: flex; align-items: flex-start; gap: 6px; margin-top: 8px; }
.schedule-event .event-meta-icon { flex-shrink: 0; margin-top: 2px; opacity: 0.55; }
.schedule-event .event-meta-text { font-family: var(--font-body); font-size: 27px; font-style: italic; color: var(--lino); }

@media (max-width: 720px) {
  .schedule-day { grid-template-columns: 1fr; gap: 18px 0; }
  .schedule-date-label { border-top: 1px solid var(--border); padding-top: 20px; }
  .schedule-events-col { border-left: none; padding-left: 0; }
}

@media (max-width: 640px) {
  /* Scoped to this one CTA (not .btn-primary, which is shared across
     every page) so the shrink stays local to Programa's mobile view.
     The element also carries inline padding, which always wins over
     an external stylesheet regardless of selector specificity — the
     !important on padding is what actually overrides it here; the
     font-size doesn't need one since nothing inline sets it. */
  .programa-confirmar-btn {
    font-size: 15px;
    padding: 12px 26px !important;
  }
}

/* ============================================================
   EDITORIAL SPLIT — photo left (sticky) / content right (Historia)
   ============================================================ */
.editorial-split { display: grid; grid-template-columns: 1fr 1fr; gap: 0; align-items: start; min-height: 100vh; }
.editorial-split.reverse .editorial-photo { order: 2; }
.editorial-split.reverse .editorial-content { order: 1; }
.editorial-photo { position: sticky; top: 0; align-self: start; height: 100vh; overflow: hidden; }
.editorial-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.editorial-content { padding: 100px 72px; display: flex; flex-direction: column; justify-content: center; }
.chapter-label { font-family: var(--font-display); font-size: clamp(24px, 3vw, 32px); font-style: italic; color: var(--lino); margin-bottom: 24px; }
.chapter-quote { font-family: var(--font-script); font-size: clamp(26px, 3.4vw, 36px); color: var(--olivo); margin-top: 8px; line-height: 1.3; }
@media (max-width: 900px) {
  .editorial-split { grid-template-columns: 1fr; min-height: 0; }
  .editorial-split.reverse .editorial-photo,
  .editorial-split.reverse .editorial-content { order: 0; }
  .editorial-photo { position: static; height: auto; }
  .editorial-photo img { aspect-ratio: 4/3; max-height: 480px; }
  .editorial-content { padding: 52px 24px 72px; }
}

/* ============================================================
   REGISTRY — Zola/cash cards (Registro, layout borrowed from
   Regina & Gianmarco's registry.html, reuses .editorial-split)
   ============================================================ */
.registry-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; max-width: 560px; margin: 32px 0; }
.registry-card {
  /* flex column + the arrow's margin-top:auto below keeps "Próximamente"
     and "Con cariño" pinned to the same baseline across both cards
     even when one description is longer than the other — grid's own
     row-stretch already equalizes the cards' outer height, this just
     makes the inner content use that extra space instead of the arrow
     floating right under the shorter description. */
  border: 1px solid var(--border); padding: 40px 28px 32px; text-align: center;
  text-decoration: none; display: flex; flex-direction: column; background: var(--white);
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
a.registry-card:hover { border-color: var(--lino); box-shadow: 0 8px 32px rgba(42,36,23,0.1); }
.registry-card-eyebrow { font-family: var(--font-body); font-size: 23px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; display: block; }
.registry-card-divider { width: 32px; height: 1px; background: var(--border); margin: 0 auto 22px; }
.registry-card-name { font-family: var(--font-display); font-size: clamp(24px, 3vw, 30px); font-style: italic; color: var(--ink); margin-bottom: 12px; }
.registry-card-desc { font-family: var(--font-body); font-size: 26px; color: var(--muted); line-height: 1.6; margin-bottom: 22px; }
.registry-arrow { display: inline-block; margin-top: auto; align-self: center; font-family: var(--font-body); font-size: 23px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--lino); border-bottom: 1px solid var(--miel); padding-bottom: 2px; }
@media (max-width: 600px) { .registry-grid { grid-template-columns: 1fr; max-width: 340px; } }

/* ============================================================
   STORY CHAPTER — compact, corrected against Belarosa's actual
   vision.html proportions (verified from screen recording, not
   guessed from class names): small photo, eyebrow+heading+short
   paragraph, generous whitespace, NOT a full-100vh sticky split.
   ============================================================ */
.story-chapter {
  display: grid; grid-template-columns: 42% 1fr; gap: 64px; align-items: center;
  max-width: 1160px; margin: 0 auto; padding: 90px var(--margin-h);
}
.story-chapter.reverse { grid-template-columns: 1fr 42%; }
.story-chapter.reverse .story-photo { order: 2; }
.story-chapter.reverse .story-text { order: 1; }
.story-photo { position: relative; }
.story-photo-backdrop {
  position: absolute; inset: 24px -24px -24px 24px;
  background: var(--peonia); border-radius: 2px; z-index: 0;
}
.story-chapter.reverse .story-photo-backdrop { inset: 24px 24px -24px -24px; }
.story-photo img {
  position: relative; z-index: 1;
  width: 100%; height: 480px; object-fit: cover; display: block;
  box-shadow: 0 24px 50px rgba(42,36,23,0.2);
}
.story-eyebrow { font-family: var(--font-body); font-size: 24px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--lino); margin-bottom: 14px; }
.story-heading { font-family: var(--font-display); font-size: clamp(28px, 3.2vw, 38px); font-weight: 500; color: var(--ink); line-height: 1.2; margin-bottom: 20px; }
.story-text p { max-width: 46ch; margin-bottom: 14px; }
.story-quote { font-family: var(--font-display); font-style: italic; font-size: clamp(19px, 2vw, 22px); color: var(--lino); margin-top: 12px; }

@media (max-width: 860px) {
  .story-chapter, .story-chapter.reverse { grid-template-columns: 1fr; gap: 32px; padding: 56px 24px; }
  .story-chapter.reverse .story-photo, .story-chapter.reverse .story-text { order: 0; }
  .story-photo img { height: 340px; }
}

/* ============================================================
   RSVP — conversational step flow (pattern from Regi & Gian)
   ============================================================ */
.rsvp-split { display: flex; min-height: calc(100vh - 92px); padding-top: 92px; }

/* --- Left panel: plain green, postcard + photobooth strip + stamp collage --- */
.rsvp-photo-col {
  flex: 0 0 46%; position: sticky; top: 0; align-self: flex-start; height: 100vh;
  background: var(--lino);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; padding: 40px;
}
.rsvp-collage { position: relative; width: min(440px, 88%); aspect-ratio: 1748 / 1240; }

.rsvp-postcard {
  position: absolute; left: 8%; top: 10%; width: 108%;
  transform: rotate(3deg);
  box-shadow: 0 18px 40px rgba(0,0,0,0.32);
  border-radius: 3px; overflow: hidden;
  transition: transform 0.9s cubic-bezier(.4,1.8,.6,1);
  z-index: 1;
}
.rsvp-postcard img { display: block; width: 100%; height: auto; }

.rsvp-stamp {
  position: absolute; left: 24%; top: -9%; width: 52%;
  transform: rotate(-4deg);
  transition: transform 0.9s cubic-bezier(.4,1.8,.6,1);
  z-index: 2;
  filter: drop-shadow(0 6px 12px rgba(0,0,0,0.3));
}
.rsvp-stamp img { display: block; width: 100%; height: auto; }

.rsvp-photostrip {
  position: absolute; left: -8%; top: -6%; width: 34%;
  transform: rotate(-7deg);
  box-shadow: 0 14px 30px rgba(0,0,0,0.32);
  transition: transform 0.9s cubic-bezier(.4,1.8,.6,1);
  z-index: 3;
}
.rsvp-photostrip img { display: block; width: 100%; height: auto; }

@keyframes jiggle {
  0%, 100% { transform: rotate(var(--jr, 0deg)) scale(1.03); }
  30% { transform: rotate(calc(var(--jr, 0deg) + 3deg)) scale(1.03); }
  60% { transform: rotate(calc(var(--jr, 0deg) - 2deg)) scale(1.03); }
  80% { transform: rotate(calc(var(--jr, 0deg) + 1deg)) scale(1.03); }
}
.rsvp-postcard:hover { animation: jiggle 1.4s ease-in-out; --jr: 3deg; }
.rsvp-photostrip:hover { animation: jiggle 1.4s ease-in-out; --jr: -7deg; }

.rsvp-form-col { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 60px 64px; }
.rsvp-header-block { width: fit-content; margin: 0 auto; text-align: center; }
.rsvp-monogram { width: clamp(56px, 8vw, 76px); margin: 0 auto 6px; }
.rsvp-monogram img { display: block; width: 100%; height: auto; }
/* Header ornaments read as one formal heading block — spacing only,
   the ornament shapes/colors themselves are untouched. */
.rsvp-header-block .ornament.narrow { margin: 10px auto; }
.rsvp-header-block .ornament:not(.narrow) { margin: 14px auto; }
.rsvp-deadline { font-size: 19px; font-weight: 500; color: var(--ink); font-style: italic; letter-spacing: 0.01em; margin-bottom: 0; text-align: center; font-family: var(--font-body); }
/* "Confirmación de asistencia" — keep the site-wide .label uppercase
   treatment everywhere else, just not here where it read too shouty
   next to the softer copy around it. Reads as the section's main
   title: comfortably large, tracking eased off so it isn't shouty
   at this size. */
.rsvp-header-block .label { text-transform: none; font-size: 33px; letter-spacing: 0.1em; line-height: 1.2; }

.step-dots { display: flex; justify-content: center; align-items: center; gap: 7px; margin: 28px auto 34px; }
.step-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border); transition: background 0.3s; }
.step-dot.active { background: var(--lino); }

.step { max-width: 560px; width: 100%; margin: 0 auto; display: none; opacity: 0; transition: opacity 0.4s ease; }
.step.visible { display: block; }
.step.faded-in { opacity: 1; }
.step-question { font-style: italic; font-size: clamp(26px, 2.4vw, 32px); color: var(--ink); line-height: 1.5; margin-bottom: 34px; text-align: center; font-family: var(--font-body); }
.step-guest-name { font-size: 25px; letter-spacing: 0.2em; color: var(--muted); text-transform: uppercase; margin-bottom: 6px; text-align: center; font-family: var(--font-body); }

.field-label { display: block; font-size: 16px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; font-family: var(--font-body); }
.field-input { width: 100%; padding: 16px 20px; border: 1px solid var(--border); background: var(--white); font-family: var(--font-body); font-size: 19px; color: var(--ink); outline: none; transition: border-color 0.25s; border-radius: 0; margin-bottom: 22px; }
.field-input:focus { border-color: var(--lino); }

/* ============================================================
   EARTH THEME — all text/ornaments in black-brown, for pages on
   the dusty-pink background (no olive/tan tones — not readable there)
   ============================================================ */
.theme-earth .ornament { color: var(--ink-deep); opacity: 0.7; }
.theme-earth .label { color: var(--ink-deep); }
.theme-earth .schedule-date-label { color: var(--ink-deep); }
.theme-earth .schedule-event { border-bottom-color: rgba(42,36,23,0.4); }
.theme-earth .schedule-date-label { border-top-color: rgba(42,36,23,0.4); }
.theme-earth .schedule-events-col { border-left-color: rgba(42,36,23,0.4); }
.theme-earth .event-title { color: var(--ink-deep); }
.theme-earth .event-detail { color: var(--ink-deep); opacity: 0.82; }
.theme-earth .event-meta-text { color: var(--ink-deep); }
.theme-earth .event-meta-icon { color: var(--ink-deep); opacity: 0.7; }
.theme-earth p { color: var(--ink-deep); }
.theme-earth .label, .theme-earth p.label { color: var(--ink-deep); }

/* ============================================================
   RSVP — dark green theme (both panels), pink/white text
   ============================================================ */
.theme-dark-green .rsvp-photo-col,
.theme-dark-green .rsvp-form-col { background: #34432a; }
.theme-dark-green .rsvp-monogram { color: #eab8ae; }
.theme-dark-green .label { color: rgba(255,255,255,0.65); }
.theme-dark-green .rsvp-deadline { color: #fff; }
.theme-dark-green .ornament { color: rgba(255,255,255,0.45); }
.theme-dark-green .step-question { color: #fff; }
.theme-dark-green .step-guest-name { color: rgba(255,255,255,0.6); }
.theme-dark-green .field-label { color: rgba(255,255,255,0.55); }
.theme-dark-green .field-input { border-color: rgba(255,255,255,0.35); }
.theme-dark-green .step-dot { background: rgba(255,255,255,0.18); }
.theme-dark-green .step-dot.active { background: #eab8ae; }
.theme-dark-green .btn-primary { background: #eab8ae; color: #34432a; }
.theme-dark-green .btn-primary:hover:not(:disabled) { background: #f2cec6; }
.theme-dark-green .btn-outline { color: #fff; border-color: rgba(255,255,255,0.55); }
.theme-dark-green .btn-outline:hover:not(:disabled) { background: rgba(255,255,255,0.12); color: #fff; }
.theme-dark-green .confirm-title { color: #eab8ae; }
.theme-dark-green .confirm-sub { color: rgba(255,255,255,0.8); }
.theme-dark-green .confirm-divider { background: rgba(255,255,255,0.2); }
.theme-dark-green .confirm-registry-label { color: rgba(255,255,255,0.75); }
.theme-dark-green .registry-buttons a { border-color: rgba(255,255,255,0.55); color: #fff; }
.theme-dark-green .registry-buttons a:hover { background: rgba(255,255,255,0.15); }
.theme-dark-green .already-confirmed { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.2); }
.theme-dark-green .already-confirmed p { color: rgba(255,255,255,0.8); }
.theme-dark-green .already-confirmed a { color: #eab8ae; }
.theme-dark-green .inline-error { color: #ffb4b4; }

.textarea-wrap { position: relative; margin-bottom: 22px; }
.field-textarea { width: 100%; min-height: 140px; padding: 18px; border: none; background: var(--marfil); font-family: var(--font-script); font-size: 26px; color: var(--ink); resize: vertical; outline: none; line-height: 1.5; box-shadow: inset 0 1px 6px rgba(0,0,0,0.06); }

.btn { display: block; width: 100%; padding: 16px 26px; font-family: var(--font-body); font-size: 19px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; cursor: pointer; border: none; border-radius: 16px; transition: background 0.2s, color 0.2s, opacity 0.2s; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-primary { background: var(--ink-deep); color: var(--white); margin-bottom: 12px; }
.btn-primary:hover:not(:disabled) { background: var(--lino); }
.btn-outline { background: transparent; color: var(--ink-deep); border: 1px solid var(--ink-deep); margin-bottom: 12px; }
.btn-outline:hover:not(:disabled) { background: var(--ink-deep); color: var(--white); }

.inline-error { display: none; font-size: 15px; color: #a13b3b; margin-top: 10px; line-height: 1.5; font-style: italic; }
.inline-error.visible { display: block; }
.already-confirmed { display: none; background: var(--peonia); border: 1px solid var(--border); padding: 18px; margin-bottom: 22px; text-align: center; }
.already-confirmed.visible { display: block; }
.already-confirmed p { font-size: 17px; color: var(--muted); margin-bottom: 8px; max-width: none; }
.already-confirmed a { font-size: 15px; color: var(--ink-deep); cursor: pointer; text-decoration: underline; }

.confirm-title { font-family: var(--font-script); font-size: clamp(28px, 3.6vw, 40px); text-align: center; color: var(--lino); margin-bottom: 14px; line-height: 1.2; }
.confirm-sub { font-style: italic; color: var(--muted); text-align: center; font-size: 28px; margin-bottom: 22px; font-family: var(--font-body); }
.confirm-divider { width: 100%; height: 1px; background: var(--border); margin: 22px 0; }
.confirm-registry-label { font-size: 17px; color: var(--muted); margin-bottom: 14px; font-family: var(--font-display); font-style: italic; text-align: center; }
.registry-buttons { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 20px; justify-content: center; }
.registry-buttons a { flex: 1 1 160px; display: block; text-align: center; padding: 12px 18px; border: 1px solid var(--ink-deep); color: var(--ink-deep); font-family: var(--font-body); font-size: 22px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; transition: background 0.2s, color 0.2s; }
.registry-buttons a:hover { background: var(--ink-deep); color: var(--white); }

@media (max-width: 900px) {
  .rsvp-split { flex-direction: column; }
  .rsvp-photo-col { position: static; height: auto; flex: none; width: 100%; padding: 40px 24px; }
  .rsvp-collage { width: min(420px, 100%); }
  .rsvp-form-col { padding: 44px 24px 56px; }
}

/* ============================================================
   DRESS CODE PAGE (Vestimenta)
   Two-day comparison: Friday (Welcome Party / Sunset Colors) and
   Saturday (Ceremonia + Recepción / Etiqueta Formal) need to read as
   two distinct, equally-important events from the first screenful —
   never "scroll far enough and eventually discover day two".

   Structure: .dresscode-tabs (mobile/tablet day selector, up to
   1024px) + .dresscode-events, which holds both .dresscode-event
   panels. On mobile only the .active panel is shown (tabs control
   which); from 1025px up, .dresscode-tabs hides and both panels
   render side by side in a 2-col grid — the tablist markup stays in
   the DOM (harmless — display:none removes it from the a11y tree
   too) so no separate desktop/mobile markup is needed.

   Placeholder classes .moodboard-placeholder / .ornament-diamond
   above are shared site-wide (reused as-is); every selector below
   this point is scoped to the dress-code page only.
   ============================================================ */

/* No forced aspect-ratio/crop on desktop — Vestimenta.webp is close to
   square, and the point of this strip is to show the whole moodboard
   image, not crop into it. On mobile (below) it's cropped to a wide
   banner instead, so it doesn't push the day selector too far down. */
.dress-photo-strip { max-width: 697px; margin: 0 auto 48px; border-radius: var(--radius); overflow: hidden; }
.dress-photo-strip img { width: 100%; height: auto; display: block; }

/* --- Header intro copy --- */
.dresscode-intro-main {
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: clamp(21px, 2.6vw, 26px); line-height: 1.4;
  color: var(--ink); max-width: 420px; margin: 16px auto 0;
}
.dresscode-intro-sub {
  font-family: var(--font-body); font-size: 16px; letter-spacing: 0.04em;
  color: var(--muted); max-width: 420px; margin: 8px auto 0;
}

/* --- Mobile/tablet day selector --- */
.dresscode-tabs {
  display: flex; gap: 10px;
  position: sticky; z-index: 20;
  /* Clears the fixed .nav (28px padding + 20px hamburger ≈ 76px tall)
     with a small buffer so the sticky bar never rides under it. */
  top: 84px;
  background: var(--marfil);
  padding: 10px 0 14px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--border);
}
.dresscode-tab {
  flex: 1 1 0;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 12px 8px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 2px;
  cursor: pointer;
  transition: background 0.22s ease, border-color 0.22s ease;
}
.dresscode-tab-date {
  font-family: var(--font-body); font-weight: 600; font-size: 14px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink);
}
.dresscode-tab-name {
  font-family: var(--font-body); font-size: 11.5px; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted);
}
.dresscode-tab.active { background: var(--ink-deep); border-color: var(--ink-deep); }
.dresscode-tab.active .dresscode-tab-date,
.dresscode-tab.active .dresscode-tab-name { color: var(--white); }
.dresscode-tab:not(.active):hover { border-color: var(--miel); }

/* --- Event panels (mobile/tablet: one visible at a time) --- */
.dresscode-event { display: none; }
.dresscode-event.active {
  display: block;
  animation: dresscodeFadeIn 0.28s ease both;
}
@keyframes dresscodeFadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .dresscode-event.active { animation: none; }
}

.dresscode-event {
  padding: 30px clamp(20px, 4.5vw, 44px) 38px;
  border-radius: 2px;
  border: 1px solid var(--border);
}
/* Event surfaces borrow only existing brand tokens — Friday leans
   warm (marfil/miel), Saturday leans refined (peonia/dusty-pink) —
   distinct from each other and from the plain --marfil page
   background, without introducing new UI colors. */
.dresscode-event--friday {
  background: var(--marfil);
  background: color-mix(in srgb, var(--marfil) 86%, var(--miel) 14%);
}
.dresscode-event--saturday {
  background: var(--peonia);
  background: color-mix(in srgb, var(--peonia) 84%, var(--dusty-pink) 16%);
}

/* --- Editorial date badge — printed-ticket language, not a UI pill --- */
.dresscode-badge {
  display: inline-flex; flex-direction: column; align-items: flex-start;
  position: relative;
  padding: 14px 22px 14px 18px;
  background: var(--white);
  border: 1px solid var(--olivo);
  border-radius: 2px;
  margin-bottom: 24px;
}
.dresscode-badge::after {
  content: ''; position: absolute; top: 12px; right: 12px;
  width: 6px; height: 6px; border: 1px solid var(--olivo);
  transform: rotate(45deg);
}
.dresscode-badge-day {
  font-family: var(--font-body); font-size: 12.5px; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--muted);
}
.dresscode-badge-date {
  font-family: var(--font-display); font-style: italic; font-size: 32px;
  line-height: 1; color: var(--ink); margin: 5px 0 8px;
  display: flex; align-items: baseline; gap: 7px;
}
.dresscode-badge-date small {
  font-family: var(--font-body); font-style: normal; font-size: 12px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--lino);
}
.dresscode-badge-event {
  font-family: var(--font-body); font-size: 14px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--lino);
  border-top: 1px dashed var(--border);
  padding-top: 8px; margin-top: 2px;
  width: 100%; white-space: nowrap;
}

.dresscode-title { margin: 4px 0 10px; }
.dresscode-desc { font-size: 19px; line-height: 1.6; color: var(--ink); max-width: 44ch; }

/* --- Suggested color palette — organic chips, not a color picker --- */
.dresscode-palette { margin-top: 26px; }
.dresscode-palette-label {
  font-family: var(--font-body); font-size: 13px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 12px;
}
.dresscode-swatches { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.dresscode-swatch {
  width: 34px; height: 34px; flex-shrink: 0;
  border-radius: 42% 58% 55% 45% / 45% 42% 58% 55%;
  box-shadow: 0 2px 6px rgba(37,26,21,0.18), inset 0 0 0 1px rgba(255,255,255,0.4);
}
.dresscode-swatch:nth-child(2n) { border-radius: 55% 45% 48% 52% / 52% 55% 45% 48%; transform: translateY(3px); }
.dresscode-swatch:nth-child(3n) { border-radius: 48% 52% 42% 58% / 58% 48% 52% 42%; transform: translateY(-2px); }
.dresscode-swatch:nth-child(1) { background: var(--swatch-1); }
.dresscode-swatch:nth-child(2) { background: var(--swatch-2); }
.dresscode-swatch:nth-child(3) { background: var(--swatch-3); }
.dresscode-swatch:nth-child(4) { background: var(--swatch-4); }
.dresscode-swatch:nth-child(5) { background: var(--swatch-5); }
.dresscode-swatch:nth-child(6) { background: var(--swatch-6); }
.dresscode-swatch:nth-child(7) { background: var(--swatch-7); }

/* Replace with client-approved Friday dress code palette */
.dresscode-event--friday {
  --swatch-1: #e2704a;
  --swatch-2: #f2a541;
  --swatch-3: #d94f4f;
  --swatch-4: #f6c667;
  --swatch-5: #b6592f;
  --swatch-6: #8a9a5b;
  --swatch-7: #e8916b;
}
/* Client-approved Saturday (Ceremonia + Recepción) dress code palette */
.dresscode-event--saturday {
  --swatch-1: #8bc2f4;
  --swatch-2: #a37ecd;
  --swatch-3: #b3b057;
  --swatch-4: #e69d90;
  --swatch-5: #f0bab9;
  --swatch-6: #ffdc75;
}

/* "Evitar: negro y blanco" — sits right under the Saturday palette,
   not buried in the paragraph copy. */
.dresscode-avoid {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 14px;
  padding: 8px 16px;
  background: var(--white);
  border: 1px solid var(--ink-deep);
  border-radius: 2px;
  font-family: var(--font-body); font-size: 13.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-deep); max-width: none;
}
.dresscode-avoid-label { font-weight: 700; }

/* --- Para Ellas / Para Ellos — compact two-up grid, palette-first --- */
.dresscode-moodboards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 32px; }
.dresscode-moodboard { text-align: center; }
.dresscode-moodboard-label {
  font-family: var(--font-body); font-size: 12.5px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 8px;
}
.dresscode-moodboard-img {
  width: 100%;
  background: var(--white); border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.dresscode-moodboard-img img { width: 100%; height: auto; display: block; }
.dresscode-moodboard-img .moodboard-placeholder { padding: 14px; }
.dresscode-moodboard-img .moodboard-placeholder p { font-size: 11px; }
.dresscode-moodboard-caption {
  margin-top: 8px; font-family: var(--font-display); font-size: 13px;
  font-style: italic; color: var(--lino); max-width: none;
}

@media (max-width: 340px) {
  .dresscode-moodboards { grid-template-columns: 1fr; max-width: 260px; margin-left: auto; margin-right: auto; }
}

/* Photo strip: full image at every size — no crop — just tighter
   surrounding spacing on mobile. */
@media (max-width: 640px) {
  .dress-photo-strip { margin: 0 auto 28px; max-width: 100%; }
}

/* --- Desktop / wide tablet: both days visible side by side --- */
@media (min-width: 1025px) {
  .dresscode-tabs { display: none; }
  .dresscode-events {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: clamp(28px, 3vw, 52px);
    align-items: start;
  }
  .dresscode-event { display: block; animation: none; }
}

/* ============================================================
   MENSAJES — private guestbook feed (unlisted page for the couple)
   ============================================================ */
.message-card { background: var(--white); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 26px 30px; margin-bottom: 16px; }
.message-card .message-text { font-family: var(--font-display); font-size: 18px; font-style: italic; color: var(--ink); line-height: 1.6; }
.message-card .message-meta { font-family: var(--font-body); font-size: 23px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--lino); margin-top: 14px; }
.messages-empty { text-align: center; color: var(--muted); font-family: var(--font-display); font-style: italic; font-size: 19px; padding: 60px 0; }
.messages-list { max-width: 700px; margin: 0 auto; }

/* ============================================================
   MOMENTOS — video hero slide + masonry photo gallery + lightbox
   ============================================================ */
.video-hero { padding: 0 var(--margin-h) clamp(60px, 8vw, 100px); }
.video-hero-frame {
  max-width: 720px;
  margin: 0 auto;
  box-shadow: 0 24px 60px rgba(37,26,21,0.2);
}
/* Inset border: box-sizing:border-box means the 7px border eats into
   the video's own box instead of adding extra width/height around it,
   so it reads as a border painted inward on the video, not a white
   mat framing it from the outside. */
.video-hero-frame video {
  display: block; width: 100%; height: auto;
  box-sizing: border-box;
  border: 7px solid var(--white);
}

/* Scrapbook corner ornaments — same asset/technique as Historia's
   photo frames (there defined inline per-page; shared here since
   Momentos needs them too). No overflow:hidden on the frame itself,
   so the corners can overhang the edges instead of being clipped. */
.photo-frame-corners { position: relative; width: 100%; height: 100%; }
.corner-ornament {
  /* Low z-index on purpose — this only needs to sit above the video/img
     it shares .photo-frame-corners with. Historia's own page (where this
     class originated) overrides this locally at z-index:200 to clear
     Belarosa's overlapping picture holders there, but that page-specific
     need doesn't apply here — and 200 was clobbering the mobile nav menu
     (z-index:100), making the corners float above the open hamburger menu. */
  position: absolute; z-index: 2; pointer-events: none; width: 30px; height: auto;
}
.corner-tl { top: -4px; left: -4px; }
.corner-tr { top: -4px; right: -4px; transform: scaleX(-1); }
.corner-bl { bottom: -4px; left: -4px; transform: scaleY(-1); }
.corner-br { bottom: -4px; right: -4px; transform: scale(-1,-1); }
@media (min-width: 761px) {
  .corner-ornament { width: 42px; }
  .corner-tl, .corner-tr { top: -7px; }
  .corner-bl, .corner-br { bottom: -7px; }
  .corner-tl, .corner-bl { left: -7px; }
  .corner-tr, .corner-br { right: -7px; }
}

.gallery-section { padding: 0 var(--margin-h) var(--section-gap); }
.gallery-grid {
  columns: 3;
  column-gap: 16px;
  max-width: var(--max-width);
  margin: 0 auto;
}
@media (max-width: 900px) { .gallery-grid { columns: 2; } }
@media (max-width: 560px) { .gallery-grid { columns: 1; } }

.gallery-item {
  break-inside: avoid;
  margin-bottom: 16px;
  background: var(--white);
  padding: 8px;
  box-shadow: 0 6px 18px rgba(37,26,21,0.14);
  cursor: pointer;
  transition: transform 0.3s ease;
}
.gallery-item:hover { transform: scale(1.01); }
.gallery-item img { display: block; width: 100%; height: auto; }

/* Lightbox */
dialog#lightbox {
  border: none; padding: 0; background: transparent;
  max-width: 100vw; max-height: 100vh; width: 100vw; height: 100vh;
}
dialog#lightbox[open] { display: flex; align-items: center; justify-content: center; }
dialog#lightbox::backdrop { background: rgba(37,26,21,0.94); }
.lightbox-img { max-width: 90vw; max-height: 90vh; width: auto; height: auto; object-fit: contain; display: block; border-radius: var(--radius-sm); }
.lightbox-close, .lightbox-prev, .lightbox-next {
  position: fixed;
  background: rgba(255,255,255,0.1);
  color: var(--white);
  border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  font-size: 18px;
  transition: background 0.2s ease;
}
.lightbox-close:hover, .lightbox-prev:hover, .lightbox-next:hover { background: rgba(255,255,255,0.22); }
.lightbox-close { top: 24px; right: 24px; width: 44px; height: 44px; }
.lightbox-prev, .lightbox-next { top: 50%; transform: translateY(-50%); width: 52px; height: 52px; }
.lightbox-prev { left: 24px; }
.lightbox-next { right: 24px; }
@media (max-width: 640px) {
  .lightbox-prev, .lightbox-next { width: 42px; height: 42px; font-size: 15px; }
  .lightbox-prev { left: 10px; }
  .lightbox-next { right: 10px; }
  .lightbox-close { top: 14px; right: 14px; }
}
