/* ============ Sarah & Yves - 10.06.2028 ============
   Contemporary château: warm white, stone, muted sage, glass.
   Motion: scroll-driven story scrub, staggered reveals, soft parallax. */

:root {
  --bg: #faf8f4;
  --surface: #ffffff;
  --ink: #33312c;
  --muted: #8a8577;
  --line: #e6e1d5;
  --dash: #cfc9ba;
  --accent: #7c8b6c;
  --accent-dark: #5f6d52;
  --sand: #c4b28a;
  --blush: #cba89e;
  --serif: 'Cormorant Garamond', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }
html, body { overflow-x: clip; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; }
section { scroll-margin-top: 4rem; }

/* film-grain texture over everything, very faint */
.grain {
  position: fixed;
  inset: 0;
  z-index: 200;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

/* ---------- entrance & reveal system ---------- */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(28px); }
  to { opacity: 1; transform: none; }
}
.anim {
  animation: fadeUp 1s var(--ease-out) both;
  animation-delay: var(--ad, 0s);
}
.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity 0.8s ease var(--d, 0ms),
    transform 0.9s var(--ease-out) var(--d, 0ms);
}
.js [data-reveal].in { opacity: 1; transform: none; }

/* ---------- top bar ---------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.65rem 1rem;
  background: rgba(250, 248, 244, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.4s, box-shadow 0.4s;
}
.scrolled .topbar {
  border-bottom-color: var(--line);
  box-shadow: 0 1px 24px rgba(51, 49, 44, 0.06);
}
.brand {
  font-family: var(--serif);
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-decoration: none;
  white-space: nowrap;
}
.amp-sm { color: var(--accent); font-style: italic; }
.nav {
  display: flex;
  flex: 1;
  gap: 1.1rem;
  overflow-x: auto;
  font-size: 0.8rem;
  scrollbar-width: none;
}
.nav::-webkit-scrollbar { display: none; }
.nav a {
  position: relative;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  padding: 0.2rem 0;
  transition: color 0.25s;
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0;
  height: 1.5px;
  background: var(--accent);
  transition: right 0.35s var(--ease-out);
}
.nav a:hover, .nav a.active { color: var(--ink); }
.nav a.active::after { right: 0; }
.lang-toggle {
  display: flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface);
  flex-shrink: 0;
}
.lang-toggle button {
  border: none;
  background: none;
  padding: 0.32rem 0.7rem;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.25s, color 0.25s;
}
.lang-toggle button.active { background: var(--accent); color: #fff; }

/* ---------- hero ---------- */
.hero {
  position: relative;
  min-height: calc(100vh - 3.4rem);
  min-height: calc(100svh - 3.4rem);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3.5rem 1.25rem 5rem;
  overflow: clip;
}
.hero-bg {
  position: absolute;
  /* Extra height hangs off the BOTTOM, not the top: the parallax slides this
     box downward as you scroll, and it only ever moves by a fraction of the
     scroll distance, so its top edge stays at or above the viewport top and
     no gap can appear. Offsetting upward instead (the old `-20% 0 0`) hid
     the top of the photo — heads included — before you'd scrolled at all. */
  inset: 0 0 -20%;
  pointer-events: none;
  will-change: transform;
}
.blob {
  position: absolute;
  border-radius: 50%;
}
.blob-a {
  width: 60vw; height: 60vw;
  min-width: 420px; min-height: 420px;
  top: -5%; left: -12%;
  background: radial-gradient(circle at 38% 38%, rgba(124, 139, 108, 0.2), transparent 65%);
  animation: drift 26s ease-in-out infinite alternate;
}
.blob-b {
  width: 55vw; height: 55vw;
  min-width: 380px; min-height: 380px;
  top: 12%; right: -15%;
  background: radial-gradient(circle at 60% 40%, rgba(196, 178, 138, 0.2), transparent 65%);
  animation: drift 32s ease-in-out -9s infinite alternate-reverse;
}
.blob-c {
  width: 44vw; height: 44vw;
  min-width: 300px; min-height: 300px;
  bottom: -12%; left: 28%;
  background: radial-gradient(circle at 50% 50%, rgba(203, 168, 158, 0.13), transparent 65%);
  animation: drift 38s ease-in-out -18s infinite alternate;
}
@keyframes drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(4vw, 3vh, 0) scale(1.1); }
}
.hero-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* On wide/short viewports `cover` crops top and bottom; anchoring to the
     top keeps faces in frame rather than trimming the crown of a head. */
  object-position: center top;
  /* The photo sits under dark-ink text. Easing the saturation calms the red
     sweater, which otherwise fights the sage/sand palette, and the small
     brightness lift keeps the navy suit from swallowing the letterforms. */
  filter: saturate(0.82) brightness(1.05);
}
.hero-veil {
  position: absolute;
  inset: 0;
  /* Two layers. The radial is a soft oval sitting exactly where the text
     block does, carrying the veil to ~85% there so dark ink stays legible
     over the suit and sweater; the linear keeps the top and bottom edges
     settled. Between them the photo still reads at the left and right
     margins, which a single flat scrim would have washed out. */
  background:
    radial-gradient(
      92% 64% at 50% 47%,
      rgba(250, 248, 244, 0.74),
      rgba(250, 248, 244, 0) 74%
    ),
    linear-gradient(
      rgba(250, 248, 244, 0.78),
      rgba(250, 248, 244, 0.46) 45%,
      rgba(250, 248, 244, 0.9)
    );
}
.hero-inner { position: relative; text-align: center; width: 100%; max-width: 52rem; }
.kicker {
  font-size: 0.72rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1.4rem;
}
.names {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(3rem, 12vw, 5.6rem);
  line-height: 1.02;
  letter-spacing: 0.01em;
}
.names > span { display: inline-block; }
.amp {
  color: var(--accent);
  font-style: italic;
  font-weight: 400;
  padding: 0 0.06em;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  cursor: default;
}
.hero-rule {
  width: 1px;
  height: 2.2rem;
  background: linear-gradient(var(--accent), transparent);
  /* The gradient fades to nothing well before the bottom of the box, so the
     visible ink sits in the top half. The bottom margin is kept short
     deliberately - the fade itself already reads as space, and matching it
     to the top margin would push the date visually adrift from the names. */
  margin: 1rem auto 0.6rem;
}
.hero-date {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 2.9vw, 1.95rem);
  /* Sentence case rather than tracked caps: Cormorant sets figures as
     oldstyle, so "10" and "2028" sit into the lowercase instead of reading
     as intrusions the way they did between wide-tracked capitals. It also
     matches the countdown numerals directly below. */
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--accent-dark);
  margin-bottom: 0.45rem;
}
.hero-place { color: var(--muted); margin-bottom: 2.4rem; }
.countdown {
  display: flex;
  justify-content: center;
  gap: 0.9rem;
  margin-bottom: 2.4rem;
}
.cell {
  min-width: 5.4rem;
  padding: 0.95rem 1rem 0.8rem;
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.75);
  border-radius: 1.1rem;
  box-shadow: 0 12px 34px rgba(51, 49, 44, 0.07);
}
.cell .num {
  font-family: var(--serif);
  font-size: 2.3rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
@keyframes numTick {
  from { opacity: 0; transform: translateY(0.35em); filter: blur(3px); }
  to { opacity: 1; transform: none; filter: none; }
}
.cell .num.tick { animation: numTick 0.45s var(--ease-out); }
.cell .lab {
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 0.15rem;
}
@media (max-width: 540px) {
  .countdown { gap: 0.5rem; }
  .cell { min-width: 4.2rem; padding: 0.75rem 0.5rem 0.6rem; }
  .cell .num { font-size: 1.8rem; }
  .cell .lab { letter-spacing: 0.14em; }
}
.married { font-family: var(--serif); font-size: 1.7rem; color: var(--accent-dark); }
.welcome { max-width: 33rem; margin: 0 auto; color: var(--muted); font-size: 0.95rem; }
.beta-note {
  max-width: 29rem;
  margin: 1.3rem auto 0;
  padding: 0.6rem 1.2rem;
  border: 1px dashed var(--dash);
  border-radius: 1.1rem;
  background: rgba(124, 139, 108, 0.07);
  color: var(--accent-dark);
  font-size: 0.8rem;
  line-height: 1.55;
}
.scroll-cue {
  position: absolute;
  bottom: 1.9rem;
  left: 50%;
  transform: translateX(-50%);
  width: 1px;
  height: 52px;
  overflow: hidden;
  transition: opacity 0.5s;
}
.scroll-cue span {
  display: block;
  width: 1px;
  height: 100%;
  background: var(--accent);
  animation: cue 2s cubic-bezier(0.6, 0.05, 0.3, 0.95) infinite;
}
@keyframes cue {
  0% { transform: translateY(-100%); }
  55% { transform: translateY(0); }
  100% { transform: translateY(100%); }
}
.scrolled .scroll-cue { opacity: 0; }

/* ---------- sections ---------- */
.section { max-width: 44rem; margin: 0 auto; padding: 4.5rem 1.25rem; }
.section-title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.9rem, 5vw, 2.5rem);
  margin-bottom: 1.6rem;
}
.section-title::before {
  content: '';
  display: block;
  width: 2.4rem;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  margin-bottom: 1rem;
}
.js .section-title[data-reveal]::before {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.9s var(--ease-out) 0.25s;
}
.js .section-title[data-reveal].in::before { transform: scaleX(1); }
.notice { font-size: 0.85rem; color: var(--muted); }
.err { color: #a2543f; }

/* ---------- shared photo box ----------
   Same placeholder behaviour as the story cards: when the box carries
   .noimg (no photo set, or the file failed to load) the image is dropped
   and the caption panel shows in its place. */
.photo-media {
  position: relative;
  overflow: hidden;
  border-radius: 0.9rem;
  background: linear-gradient(145deg, #eceadf, #dcd8c7);
}
.photo-media img { width: 100%; height: 100%; object-fit: cover; }
.photo-media.noimg { display: flex; align-items: center; justify-content: center; }
.photo-media.noimg img { display: none; }
.photo-media.noimg .ph-fb {
  display: block;
  padding: 0.6rem;
  text-align: center;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- schedule ---------- */
.schedule {
  list-style: none;
  position: relative;
  padding-left: 1.9rem;
  margin-bottom: 1.25rem;
}
/* the container itself only draws its line - no fade of the whole list */
.js .schedule[data-reveal] { opacity: 1; transform: none; }
.schedule::before {
  content: '';
  position: absolute;
  left: 0.45rem;
  top: 0.4rem;
  bottom: 0.4rem;
  width: 1.5px;
  background: var(--line);
}
.js .schedule::before {
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 1.4s var(--ease-out) 0.15s;
}
.js .schedule.in::before { transform: scaleY(1); }
.schedule li { position: relative; padding-bottom: 2rem; }
.schedule li:last-child { padding-bottom: 0; }
.schedule li::before {
  content: '';
  position: absolute;
  left: calc(-1.45rem - 4.25px);
  top: 0.42rem;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--bg);
  box-shadow: 0 0 0 1px var(--line);
}
.js .schedule li[data-reveal]::before {
  transform: scale(0);
  transition: transform 0.5s var(--ease-out) calc(var(--d, 0ms) + 200ms);
}
.js .schedule li[data-reveal].in::before { transform: scale(1); }
.time {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-dark);
  margin-bottom: 0.15rem;
}
.event { font-family: var(--serif); font-size: 1.45rem; font-weight: 500; }
/* a row without a photo is just the text block, laid out exactly as before */
.sched-row { display: flex; align-items: center; gap: 1.2rem; }
.sched-text { flex: 1 1 auto; min-width: 0; }
.sched-photo {
  flex: 0 0 clamp(7rem, 24vw, 12rem);
  aspect-ratio: 4 / 3;
  box-shadow: 0 10px 28px rgba(51, 49, 44, 0.1);
}
.sched-photo img { transition: transform 0.9s var(--ease-out); }
.schedule li:hover .sched-photo img { transform: scale(1.05); }
@media (max-width: 600px) {
  .sched-row { flex-direction: column; align-items: stretch; gap: 0.85rem; }
  .sched-photo { flex: 0 0 auto; width: 100%; }
}

/* ---------- travel ---------- */
.travel-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.travel-block {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 1.1rem;
  padding: 1.5rem 1.4rem;
  transition: transform 0.35s var(--ease-out), box-shadow 0.35s;
}
.js .travel-block[data-reveal] {
  transition:
    opacity 0.8s ease var(--d, 0ms),
    transform 0.9s var(--ease-out) var(--d, 0ms),
    box-shadow 0.35s;
}
.travel-block:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 40px rgba(51, 49, 44, 0.08);
}
.t-icon {
  width: 26px;
  height: 26px;
  color: var(--accent);
  margin-bottom: 0.8rem;
}
.travel-block h3 {
  font-family: var(--serif);
  font-size: 1.3rem;
  font-weight: 500;
  margin-bottom: 0.35rem;
}
.travel-block p + .notice { margin-top: 0.5rem; }

/* "Open in Maps", under the address. Sized as a proper tap target rather
   than a text link - on a phone this is the one thing in the Travel section
   anyone actually presses. */
.map-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.9rem;
  padding: 0.5rem 0.9rem;
  min-height: 44px;
  border: 1px solid var(--line);
  border-radius: 2rem;
  color: var(--accent-dark);
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  transition: border-color 0.25s, background 0.25s, transform 0.25s var(--ease-out);
}
.map-link svg { width: 17px; height: 17px; flex: none; }
.map-link:hover {
  background: var(--bg);
  border-color: var(--accent);
  transform: translateY(-1px);
}
.map-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- accommodations ---------- */
.stay-prompt { margin-bottom: 1rem; }
.stay-card { margin-bottom: 0.25rem; }
.stay-note { font-family: var(--serif); font-size: 1.25rem; margin-bottom: 0.5rem; }
/* the château shot, above the on-site note - a wide banner across the
   card, at the source photo's own 2:1 so nothing is cropped away */
.stay-photo {
  aspect-ratio: 2 / 1;
  margin-bottom: 1.3rem;
  box-shadow: 0 10px 28px rgba(51, 49, 44, 0.1);
}
/* two across, one on narrow screens - same surface as .card */
.hotel-cards {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.1rem;
  margin-bottom: 1rem;
}
.hotel-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 1.2rem;
  overflow: hidden;
  box-shadow: 0 16px 44px rgba(51, 49, 44, 0.05);
  transition: transform 0.4s var(--ease-out), box-shadow 0.4s ease;
}
.hotel-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 22px 54px rgba(51, 49, 44, 0.12);
}
.hotel-photo { aspect-ratio: 4 / 3; border-radius: 0; }
.hotel-photo img { transition: transform 0.9s var(--ease-out); }
.hotel-card:hover .hotel-photo img { transform: scale(1.05); }
.hotel-card-body { padding: 0.95rem 1.15rem 1.15rem; }
.hotel-name { display: block; font-weight: 500; }
.hotel-dist { display: block; color: var(--muted); font-size: 0.9rem; }
@media (max-width: 600px) {
  .hotel-cards { grid-template-columns: 1fr; }
}

/* ---------- forms & buttons ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 1.2rem;
  padding: 1.7rem 1.5rem;
  box-shadow: 0 16px 44px rgba(51, 49, 44, 0.05);
}
input[type='text'], input[type='email'], input[type='tel'], textarea {
  width: 100%;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface);
  font: inherit;
  color: inherit;
  transition: border-color 0.25s, box-shadow 0.25s;
}
input[type='text']:focus, input[type='email']:focus, input[type='tel']:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(124, 139, 108, 0.18);
}
textarea { resize: vertical; }
.inline-form { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.inline-form input { flex: 1; min-width: 200px; }

/* ---------- guest-name autocomplete ---------- */
.ac-wrap { position: relative; flex: 1; min-width: 200px; }
.ac-wrap input { width: 100%; }
.ac-list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 0.35rem);
  left: 0;
  right: 0;
  list-style: none;
  padding: 0.3rem;
  max-height: 14.5rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  box-shadow: 0 18px 44px rgba(51, 49, 44, 0.14);
  animation: acIn 0.22s var(--ease-out);
}
@keyframes acIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}
.ac-list li {
  padding: 0.5rem 0.7rem;
  border-radius: 0.6rem;
  font-size: 0.92rem;
  cursor: pointer;
  transition: background 0.15s;
}
.ac-list li:hover, .ac-list li.on { background: rgba(124, 139, 108, 0.14); }
.btn {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 0.7rem 1.5rem;
  font-family: var(--sans);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.25s, transform 0.25s var(--ease-out), box-shadow 0.25s;
}
.btn:hover {
  background: var(--accent-dark);
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(95, 109, 82, 0.25);
}
.btn:active { transform: none; }
.btn:disabled { opacity: 0.5; cursor: default; transform: none; box-shadow: none; }
.btn:focus-visible, .linklike:focus-visible, .lang-toggle button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.linklike {
  background: none;
  border: none;
  color: var(--muted);
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  padding: 0;
  margin-top: 0.9rem;
}

/* Hand-off from "here's your room" to "so are you coming?". Identifying
   yourself in this section already unlocks the RSVP form below, so this is
   the next thing to do rather than a second name to type. */
.stay-cta {
  display: inline-block;
  margin-top: 1.1rem;
  padding: 0.7rem 1.3rem;
  min-height: 44px;
  border-radius: 2rem;
  background: var(--accent);
  color: #fff;
  font-size: 0.88rem;
  font-weight: 500;
  text-decoration: none;
  transition: background 0.25s, transform 0.25s var(--ease-out);
}
.stay-cta:hover { background: var(--accent-dark); transform: translateY(-1px); }
.stay-cta:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.stay-cta + .linklike { display: block; }

/* ---------- RSVP ---------- */
/* The by-when, above the name field. Tinted rather than boxed in red: it's a
   nudge, not a warning, and it sits inside the RSVP card already. */
.rsvp-deadline {
  margin-bottom: 1.3rem;
  padding: 0.85rem 1rem;
  border-left: 2px solid var(--accent);
  border-radius: 0 0.6rem 0.6rem 0;
  background: var(--bg);
  color: var(--ink);
  font-size: 0.88rem;
  line-height: 1.55;
}
.rsvp-head { margin-bottom: 1.4rem; }
.rsvp-head .linklike { margin-top: 0.25rem; }
.rsvp-greeting { font-family: var(--serif); font-size: 1.45rem; }
.field { border: none; margin-bottom: 1.3rem; }
.field-label, legend {
  display: block;
  font-size: 0.85rem;
  font-weight: 500;
  margin-bottom: 0.5rem;
}
.pills { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.pills input { position: absolute; opacity: 0; pointer-events: none; }
.pills label {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.55rem 1.1rem;
  background: var(--surface);
  font-size: 0.9rem;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, color 0.2s, transform 0.2s var(--ease-out);
}
.pills label:hover { transform: translateY(-1px); border-color: var(--dash); }
.pills input:checked + label {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.pills input:focus-visible + label {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.checkline {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.28rem 0;
  font-size: 0.95rem;
  cursor: pointer;
}
input[type='checkbox'] {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: var(--accent);
}
.field .field-label { margin-top: 0.6rem; }
.contact-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.9rem; }
.contact-row .field-label { margin-top: 0; }
.contact-hint { margin-top: 0.55rem; }
@media (max-width: 540px) {
  .contact-row { grid-template-columns: 1fr; gap: 0.8rem; }
}
.rsvp-confirm { text-align: center; padding: 1rem 0; }
.check {
  width: 3.4rem;
  height: 3.4rem;
  margin: 0 auto 1rem;
  stroke: var(--accent);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.check-circle {
  stroke-dasharray: 151;
  stroke-dashoffset: 151;
  animation: checkDraw 0.8s var(--ease-out) forwards;
}
.check-mark {
  stroke-dasharray: 36;
  stroke-dashoffset: 36;
  animation: checkDraw 0.4s var(--ease-out) 0.6s forwards;
}
@keyframes checkDraw { to { stroke-dashoffset: 0; } }

/* ---------- FAQ ---------- */
.faq-item { border-bottom: 1px solid var(--line); padding: 1.05rem 0; }
.faq-item summary {
  cursor: pointer;
  font-weight: 500;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '+';
  font-family: var(--serif);
  font-size: 1.4rem;
  color: var(--accent);
  flex-shrink: 0;
  transition: transform 0.35s var(--ease-out);
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { margin-top: 0.6rem; color: var(--muted); }
/* optional example photos inside an answer (e.g. dress code) */
.faq-photos {
  display: grid;
  /* auto-fit counts tracks using the UPPER bound when it's a fixed length,
     so the old `minmax(10rem, 14rem)` sized every track as if it were 14rem
     wide just to decide how many fit - on a ~23rem-wide phone that only
     ever cleared one track, and that lone track then sat pinned at 14rem
     instead of growing, leaving roughly half the row empty. Making the
     upper bound `1fr` switches the count to the (still 14rem) lower bound
     while letting whichever tracks *do* fit stretch and split the leftover
     width evenly, so a single photo goes full-width and a pair fills the
     row edge to edge at every size in between. */
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: 1rem;
  margin-top: 1rem;
}
.faq-photos figure { margin: 0; }
.faq-photo { aspect-ratio: 3 / 4; box-shadow: 0 10px 28px rgba(51, 49, 44, 0.1); }
.faq-photos figcaption {
  margin-top: 0.45rem;
  font-size: 0.85rem;
  color: var(--muted);
}
@keyframes faqIn {
  from { opacity: 0; transform: translateY(-5px); }
  to { opacity: 1; transform: none; }
}
.faq-item[open] p { animation: faqIn 0.4s var(--ease-out); }

/* ---------- footer ---------- */
.footer {
  text-align: center;
  padding: 4rem 1rem 3rem;
  color: var(--muted);
}
.foot-mono {
  font-family: var(--serif);
  font-size: 1.5rem;
  color: var(--ink);
  letter-spacing: 0.14em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  margin-bottom: 0.4rem;
}
.foot-rule { display: inline-block; width: 44px; height: 1px; background: var(--line); }
.footer p { font-family: var(--serif); font-size: 1rem; }
.footer .foot-contact { font-family: var(--sans); font-size: 0.83rem; margin-top: 0.7rem; }
.foot-contact a {
  color: var(--accent-dark);
  text-decoration: underline;
  text-decoration-color: var(--dash);
  text-underline-offset: 0.2em;
  transition: text-decoration-color 0.2s;
}
.foot-contact a:hover { text-decoration-color: var(--accent-dark); }

/* ---------- modal (hidden surprise) ---------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 1.5rem;
  background: rgba(43, 41, 35, 0.5);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.modal[hidden] { display: none; }
@keyframes popIn {
  from { opacity: 0; transform: translateY(18px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
.modal-card {
  background: var(--surface);
  border-radius: 1.2rem;
  padding: 2.25rem 1.75rem;
  max-width: 24rem;
  text-align: center;
  box-shadow: 0 25px 60px rgba(0, 0, 0, 0.18);
  animation: popIn 0.5s var(--ease-out);
}
.egg-emoji { font-size: 2.5rem; margin-bottom: 0.75rem; }
.modal-card h3 { font-family: var(--serif); font-size: 1.55rem; margin-bottom: 0.6rem; }
.modal-card p { color: var(--muted); margin-bottom: 1.4rem; }
.modal-card-egg { max-width: 28rem; }
.egg-photos { display: flex; gap: 0.9rem; justify-content: center; margin-bottom: 1.4rem; }
.egg-photos figure { flex: 1; min-width: 0; margin: 0; }
.egg-photos img {
  display: block; width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: 0.8rem; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
}
.egg-photos figure:first-child { transform: rotate(-2.5deg); }
.egg-photos figure:last-child { transform: rotate(2.5deg); }
.egg-photos figcaption { font-size: 0.78rem; color: var(--muted); margin-top: 0.4rem; }
.confetti-canvas { position: fixed; inset: 0; z-index: 110; pointer-events: none; }

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .anim, .blob, .scroll-cue span, .cell .num.tick,
  .check-circle, .check-mark, .modal-card, .faq-item[open] p, .ac-list { animation: none; }
  .check-circle, .check-mark { stroke-dashoffset: 0; }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .js .schedule::before, .js .schedule li[data-reveal]::before,
  .js .section-title[data-reveal]::before { transform: none; transition: none; }
  .hero-bg { transform: none !important; }
  .venue-figure img { transform: none !important; transition: none !important; }
  .hotel-card, .hotel-photo img, .sched-photo img {
    transform: none !important;
    transition: none !important;
  }
}


/* ---------- the château, under "The Day" ----------
   Deliberately not a veiled background: shown at full strength, nothing
   written over it, and no parallax - the hero keeps that to itself. */
.venue-band {
  max-width: 82rem;
  margin: 0 auto;
  padding: 0 1.25rem 1rem;
}
.venue-band[hidden] { display: none; }
.venue-figure {
  overflow: hidden;
  border-radius: 1.4rem;
  aspect-ratio: 16 / 9;
  background: linear-gradient(145deg, #eceadf, #dcd8c7);
  box-shadow: 0 26px 60px rgba(51, 49, 44, 0.16);
}
.venue-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.venue-cap {
  margin-top: 0.85rem;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--muted);
}
/* settle out of a slight zoom instead of sliding up like the other reveals */
.js .venue-band[data-reveal] { opacity: 0; transform: none; transition: opacity 1.1s ease; }
.js .venue-band[data-reveal].in { opacity: 1; }
.js .venue-band[data-reveal] .venue-figure img { transform: scale(1.07); }
.js .venue-band[data-reveal].in .venue-figure img {
  transform: scale(1);
  transition: transform 1.8s var(--ease-out);
}
@media (max-width: 700px) {
  .venue-figure { aspect-ratio: 4 / 3; border-radius: 1.1rem; }
}

/* ---------- Our Story: film strip ----------
   Drag / swipe / arrow through the stops; the card nearest the centre
   is highlighted, and captions expand with more detail on hover
   (tap on touch screens). */
.section-wide { max-width: 76rem; }
.tl-hint { margin: -0.8rem 0 1.6rem; }
.tl-date {
  font-size: 0.66rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.tlC-scroller {
  /* position:relative is load-bearing: it makes the scroller the cards'
     offsetParent, so the JS can use card.offsetLeft as a scroll-content
     coordinate (transform-immune, unlike getBoundingClientRect). Without
     it offsetLeft is measured from <body> and includes the section's
     centering margin, skewing every glide target on wide screens. */
  position: relative;
  display: flex;
  gap: 1.1rem;
  overflow-x: auto;
  padding: 0.6rem 0.25rem 1.2rem;
  /* no native scroll-snap here on purpose - it fights the JS-eased glide
     below (native momentum + native snap settle at different rates, so the
     two visibly fought and produced a last-instant jump). Settling on a
     card is done entirely in JS instead, see stripGlideTo/scheduleSettle
     in app.js, so there is exactly one thing moving scrollLeft at a time. */
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  cursor: grab;
}
.tlC-scroller::-webkit-scrollbar { display: none; }
.tlC-scroller.drag { cursor: grabbing; }
.tlC-scroller.drag .cardC,
.tlC-scroller.gliding .cardC { pointer-events: none; }

.cardC {
  position: relative;
  flex: 0 0 min(23rem, 78vw);
  aspect-ratio: 3 / 4;
  border-radius: 1.25rem;
  overflow: hidden;
  outline-offset: 3px;
  transform: scale(0.95);
  box-shadow: 0 10px 28px rgba(51, 49, 44, 0.1);
  transition: transform 0.8s var(--ease-out), box-shadow 0.8s ease;
}
.cardC.is-active {
  transform: scale(1);
  box-shadow: 0 22px 54px rgba(51, 49, 44, 0.16);
}

.cardC-media { position: absolute; inset: 0; }
/* the wrapper is a little wider than the card and slides sideways as the
   strip scrolls - a soft parallax done with compositor-only transforms */
.cardC-para { position: absolute; inset: 0 -7%; will-change: transform; }
.cardC-para img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.7) brightness(0.95);
  transition: transform 0.9s var(--ease-out), filter 0.8s ease;
}
.cardC.is-active .cardC-para img { filter: none; }
.cardC:hover .cardC-para img,
.cardC:focus-visible .cardC-para img,
.cardC.show .cardC-para img { transform: scale(1.06); filter: none; }

.ph-fb { display: none; }
.cardC-media.noimg {
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(145deg, #eceadf, #dcd8c7);
}
.cardC-media.noimg .cardC-para { display: none; }
.cardC-media.noimg .ph-fb {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.cardC-idx {
  position: absolute;
  top: 0.85rem;
  right: 0.95rem;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  color: #fff;
  background: rgba(22, 24, 18, 0.38);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: 0.28rem 0.65rem;
  border-radius: 2rem;
}

.cardC-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 3.4rem 1.35rem 1.2rem;
  background: linear-gradient(rgba(22, 24, 18, 0) 0%, rgba(22, 24, 18, 0.72) 62%);
  color: #fff;
}
.cardC-cap .tl-date { color: rgba(255, 255, 255, 0.78); }
.cardC-cap h3 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 1.55rem;
  line-height: 1.12;
  margin: 0.25rem 0 0.4rem;
}
/* the note expands from 0 to its natural height (grid-rows trick) */
.cardC-note {
  display: grid;
  grid-template-rows: 0fr;
  overflow: hidden;
  transition: grid-template-rows 0.65s var(--ease-out);
}
.cardC-note p {
  min-height: 0;
  overflow: hidden;
  font-size: 0.85rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.9);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.45s ease 0.08s, transform 0.6s var(--ease-out) 0.08s;
}
.cardC:hover .cardC-note,
.cardC:focus-visible .cardC-note,
.cardC.show .cardC-note { grid-template-rows: 1fr; }
.cardC:hover .cardC-note p,
.cardC:focus-visible .cardC-note p,
.cardC.show .cardC-note p { opacity: 1; transform: none; }

.tlC-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.5rem;
}
.tlC-btn {
  width: 2.7rem;
  height: 2.7rem;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 1rem;
  cursor: pointer;
  transition:
    background 0.35s, border-color 0.35s, color 0.35s,
    opacity 0.35s, transform 0.35s var(--ease-out);
}
.tlC-btn:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  transform: translateY(-2px);
}
.tlC-btn:active { transform: translateY(0) scale(0.94); }
.tlC-btn.dim { opacity: 0.35; pointer-events: none; }
.tlC-progress {
  flex: 1;
  height: 2px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
#tlC-fill {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

@media (prefers-reduced-motion: reduce) {
  .cardC, .cardC-para img, .cardC-note, .cardC-note p, .tlC-btn {
    transition: none !important;
  }
  .cardC { transform: none; }
  .cardC-para { transform: none !important; }
}
