/* ==========================================================================
   Nortjé Wedding 2027 — mockup design system
   Palette and type roles carried forward from the Canva v1 design.
   See output/planning/CONTENT_AUDIT.md §3 for where these values came from.
   ========================================================================== */

:root {
  /* --- colour ------------------------------------------------------------ */
  --sand:        #F6F5EE;   /* primary light surface                        */
  --cream:       #F3EBCF;   /* accent surface / display text on dark        */
  --paper:       #EEEDE7;   /* borders, subtle fills                        */
  --paper-warm:  #E8E2D2;
  --ink:         #5C4E3D;   /* body + display text  — 6.5:1 on sand         */
  --ink-deep:    #574737;   /* emphasis                                     */
  --terracotta:  #854D13;   /* accent, links, focus  — 6.9:1 on sand        */
  --sea:         #6B8BA3;   /* dividers, secondary fills                    */
  --sea-light:   #9EC3DE;
  --navy:        #304254;   /* dark surfaces                                */
  --navy-deep:   #26333F;

  /* --- type -------------------------------------------------------------- */
  --font-display: 'Cormorant Garamond', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --font-body:    'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

  /* --- rhythm ------------------------------------------------------------ */
  --section-y:  clamp(4.5rem, 9vw, 10rem);
  --gutter:     clamp(1.25rem, 5vw, 4rem);
  --measure:    68ch;
  --hairline:   rgba(92, 78, 61, 0.18);
  --hairline-light: rgba(246, 245, 238, 0.26);
  --ease:       cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ==========================================================================
   Base
   ========================================================================== */

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

html {
  scroll-behavior: smooth;
  /* clears the fixed header when jumping to an anchor */
  scroll-padding-top: 6rem;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background-color: var(--sand);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: clamp(1.0625rem, 0.35vw + 1rem, 1.25rem);
  line-height: 1.6;
  letter-spacing: 0.006em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Fine stationery grain. Sits above the background, below all content. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)' opacity='0.055'/%3E%3C/svg%3E");
}
body > * { position: relative; z-index: 1; }

img, svg, video { display: block; max-width: 100%; height: auto; }

/* Guard: an inline display (display:grid on a panel we toggle) otherwise beats
   the UA stylesheet's [hidden] rule and the element stays visible. */
[hidden] { display: none !important; }

/* Defined here rather than relying on the Tailwind utility, because the header
   and footer are injected by JS and must not depend on the CDN's scan timing. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Honeypot — off-screen, never announced, never tabbable. */
.hp { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; opacity: 0; }

::selection { background: var(--cream); color: var(--ink-deep); }

/* ==========================================================================
   Typography
   ========================================================================== */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 300;
  line-height: 1.02;
  letter-spacing: -0.004em;
  margin: 0;
  text-wrap: balance;
}

.display-hero   { font-size: clamp(3.6rem, 12vw, 9.5rem); }
.display-xl     { font-size: clamp(2.9rem, 8vw, 6.5rem); }
.display-lg     { font-size: clamp(2.4rem, 5.5vw, 4.25rem); }
.display-md     { font-size: clamp(1.9rem, 3.6vw, 3rem); }
.display-sm     { font-size: clamp(1.5rem, 2.4vw, 2.1rem); }

/* The oversized ampersand from the v1 hero, kept as a design moment. */
.ampersand {
  font-family: var(--font-display);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(3rem, 9vw, 7.5rem);
  line-height: 0.8;
}

/* Tracked-out uppercase sans — the v1 label voice. */
.label {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: clamp(0.66rem, 0.28vw + 0.6rem, 0.8rem);
  text-transform: uppercase;
  letter-spacing: 0.3em;
  line-height: 1.5;
}
.label-lg { font-size: clamp(0.75rem, 0.3vw + 0.7rem, 0.95rem); letter-spacing: 0.26em; }

.prose { max-width: var(--measure); margin-inline: auto; }
.prose p { margin: 0 0 1.35em; }
.prose p:last-child { margin-bottom: 0; }
.prose strong { font-weight: 500; color: var(--ink-deep); }

.script { font-family: var(--font-display); font-style: italic; font-weight: 300; }

a { color: inherit; }

.link {
  color: var(--terracotta);
  text-decoration: none;
  border-bottom: 1px solid rgba(133, 77, 19, 0.35);
  padding-bottom: 1px;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.link:hover { border-bottom-color: var(--terracotta); }
.on-dark .link { color: var(--cream); border-bottom-color: rgba(243, 235, 207, 0.4); }
.on-dark .link:hover { border-bottom-color: var(--cream); }

/* ==========================================================================
   Layout
   ========================================================================== */

.shell   { width: 100%; max-width: 1240px; margin-inline: auto; padding-inline: var(--gutter); }
.shell-narrow { width: 100%; max-width: 880px; margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-y); }
.section-tight { padding-block: clamp(3rem, 6vw, 6rem); }

.on-dark { background-color: var(--navy); color: var(--sand); }
.on-dark h1, .on-dark h2, .on-dark h3 { color: var(--sand); }
.on-cream { background-color: var(--cream); }
.on-paper { background-color: var(--paper); }

/* ==========================================================================
   Rules & ornament
   ========================================================================== */

.hr-hair { border: 0; border-top: 1px solid var(--hairline); margin: 0; }
.on-dark .hr-hair { border-top-color: var(--hairline-light); }

/* Hairline with a small centred diamond — the section divider. */
.ornament {
  display: flex;
  align-items: center;
  gap: 1.15rem;
  justify-content: center;
  color: var(--ink);
}
.ornament::before, .ornament::after {
  content: '';
  height: 1px;
  width: min(7rem, 18vw);
  background: currentColor;
  opacity: 0.28;
}
.ornament span {
  width: 5px; height: 5px;
  background: currentColor;
  transform: rotate(45deg);
  opacity: 0.55;
}
.on-dark .ornament { color: var(--cream); }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 3rem;
  padding: 0.85rem 2.1rem;
  border-radius: 999px;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(0.7rem, 0.25vw + 0.65rem, 0.82rem);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.24em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease),
              border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.btn:hover { background: var(--ink); color: var(--sand); }
.btn:active { transform: translateY(1px); }

.btn-solid { background: var(--terracotta); border-color: var(--terracotta); color: var(--sand); }
.btn-solid:hover { background: var(--ink-deep); border-color: var(--ink-deep); color: var(--sand); }

.btn-light { border-color: rgba(246, 245, 238, 0.65); color: var(--sand); }
.btn-light:hover { background: var(--sand); color: var(--ink); border-color: var(--sand); }

.btn-sm { min-height: 2.5rem; padding: 0.6rem 1.4rem; letter-spacing: 0.18em; }

/* Universal focus treatment — terracotta, always visible. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 3px;
  border-radius: 3px;
}
.on-dark :where(a, button, input, select, textarea, summary):focus-visible { outline-color: var(--cream); }

.skip-link {
  position: absolute; left: 0; top: 0;
  transform: translateY(-120%);
  z-index: 200;
  margin: 0.5rem;
  background: var(--ink);
  color: var(--sand);
  padding: 0.7rem 1.2rem;
  border-radius: 999px;
  text-decoration: none;
  transition: transform 0.2s var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* ==========================================================================
   Header / navigation
   ========================================================================== */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  transition: background-color 0.4s var(--ease), box-shadow 0.4s var(--ease),
              backdrop-filter 0.4s var(--ease);
}
.site-header.is-scrolled {
  background: rgba(246, 245, 238, 0.92);
  backdrop-filter: saturate(1.1) blur(12px);
  box-shadow: 0 1px 0 var(--hairline);
}
/* Over a dark hero the nav starts light, then inverts once scrolled. */
.site-header[data-over="dark"]:not(.is-scrolled) { color: var(--sand); }
.site-header[data-over="dark"]:not(.is-scrolled) .btn { border-color: rgba(246,245,238,0.6); color: var(--sand); }
.site-header[data-over="dark"]:not(.is-scrolled) .btn:hover { background: var(--sand); color: var(--ink); }

.nav-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 4.75rem; }

.monogram {
  font-family: var(--font-display);
  font-size: 1.35rem;
  letter-spacing: 0.16em;
  text-decoration: none;
  white-space: nowrap;
}

.nav-links { display: none; align-items: center; gap: clamp(1.1rem, 2.4vw, 2.4rem); }
@media (min-width: 62rem) { .nav-links { display: flex; } }

.nav-link {
  position: relative;
  text-decoration: none;
  font-size: 0.74rem;
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.26em;
  padding-block: 0.35rem;
}
.nav-link::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}
.nav-link:hover::after { transform: scaleX(1); }
.nav-link[aria-current="page"]::after { transform: scaleX(1); opacity: 0.55; }

.nav-toggle { display: inline-flex; }
@media (min-width: 62rem) { .nav-toggle { display: none; } }

/* Mobile drawer */
.nav-drawer {
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--sand);
  display: grid;
  place-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s var(--ease), visibility 0.35s;
}
.nav-drawer[data-open="true"] { opacity: 1; visibility: visible; }
.nav-drawer ol { list-style: none; margin: 0; padding: 0; text-align: center; }
.nav-drawer li { border-bottom: 1px solid var(--hairline); }
.nav-drawer li:last-child { border-bottom: 0; }
.nav-drawer a {
  display: block;
  padding: 1.1rem 2rem;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 7vw, 2.5rem);
  text-decoration: none;
}

/* Persistent mobile RSVP bar — the highest-value mobile pattern here. */
.rsvp-bar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 90;
  padding: 0.7rem var(--gutter) calc(0.7rem + env(safe-area-inset-bottom));
  background: rgba(246, 245, 238, 0.95);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--hairline);
  display: flex;
  transform: translateY(110%);
  transition: transform 0.4s var(--ease);
}
.rsvp-bar.is-visible { transform: translateY(0); }
.rsvp-bar .btn { flex: 1; }
@media (min-width: 62rem) { .rsvp-bar { display: none; } }

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  min-height: min(100svh, 60rem);
  display: grid;
  place-items: center;
  text-align: center;
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; }
.hero-media img,
.hero-media video { width: 100%; height: 100%; object-fit: cover; }
/* The footage is 1280x676; on a wide screen it is upscaled, so keep it slightly
   soft rather than letting the browser sharpen the noise. */
.hero-video { background: var(--navy); }

/* Never put body text straight over a photo — always a scrim. */
.scrim::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg,
    rgba(48, 66, 84, 0.52) 0%,
    rgba(48, 66, 84, 0.38) 34%,
    rgba(48, 66, 84, 0.62) 100%);
}
.scrim-soft::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(87,71,55,0.28) 0%, rgba(87,71,55,0.46) 100%);
}
/* Directional scrim for a left-aligned block over a bright photograph: darkens
   the text column and lets the image breathe on the other side. */
.scrim-editorial::after {
  content: '';
  position: absolute; inset: 0;
  background:
    linear-gradient(90deg,
      rgba(38, 51, 63, 0.78) 0%,
      rgba(38, 51, 63, 0.58) 34%,
      rgba(38, 51, 63, 0.22) 62%,
      rgba(38, 51, 63, 0.10) 100%),
    linear-gradient(180deg, rgba(38, 51, 63, 0.22), rgba(38, 51, 63, 0.30));
}

/* Scrim tuned for the hero footage. The wave clip runs to near-white foam,
   which the standard .scrim (built for a darker photograph) could not hold down
   - the date line and button measured 3.2:1 against it. Weighted towards the
   centre, where the type sits, so the corners of the frame stay open. */
.scrim-video::after {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(135% 105% at 50% 44%,
      rgba(38, 51, 63, 0.76) 0%,
      rgba(38, 51, 63, 0.68) 55%,
      rgba(38, 51, 63, 0.46) 100%);
}

.scrim-strong::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(38,51,63,0.62) 0%, rgba(38,51,63,0.74) 100%);
}

.hero-inner { position: relative; z-index: 2; padding-block: 6.5rem 4.5rem; }

/* ==========================================================================
   Watercolour seal — the v1 illustration, given a soft painted edge
   ========================================================================== */

.seal {
  width: clamp(7rem, 16vw, 11rem);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 58%, transparent 78%);
          mask-image: radial-gradient(circle at 50% 50%, #000 58%, transparent 78%);
  mix-blend-mode: multiply;
}
.seal img { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   Invitation scene — the v1 composition: couple full-bleed, stationery card
   offset to the left, envelope and wax seal breaking out of the bottom edge.
   Proportions are taken from the original; sizes are fluid so the card is
   driven by its own type rather than by a fixed canvas.
   ========================================================================== */

.invite-scene {
  position: relative;
  overflow: hidden;            /* the envelope is meant to run off the bottom */
  background: var(--navy-deep);
}
.invite-scene-media { position: absolute; inset: 0; }
.invite-scene-media img { width: 100%; height: 100%; object-fit: cover; }
/* A whisper of shade so the card lifts off the photograph. */
.invite-scene-media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(38,51,63,.28) 0%, rgba(38,51,63,.10) 45%, rgba(38,51,63,.20) 100%);
}

.invite-stage {
  position: relative;
  z-index: 1;
  /* the bottom pad decides how much envelope shows below the card */
  padding-block: clamp(3rem, 6vw, 5.5rem) clamp(6rem, 11vw, 10rem);
}

/* Sized to the card, so the envelope can be placed as a percentage of it. */
.invite-group {
  position: relative;
  width: min(31rem, 100%);
}

/* ---- the card ----------------------------------------------------------
   Its own class, not .invite-card: that one is the bordered panel used on
   details.html and thank-you.html, and this scene wants a plain sheet. */
.invite-paper {
  position: relative;
  z-index: 3;
  width: 100%;
  background: var(--sand);
  padding: clamp(2.5rem, 4.5vw, 3.75rem) clamp(1.75rem, 3.2vw, 2.75rem) clamp(3rem, 5.5vw, 4.5rem);
  box-shadow: 0 30px 70px -30px rgba(26, 34, 42, 0.55);
  text-align: center;
}

.invite-shell {
  width: clamp(4.25rem, 7vw, 5.5rem);
  height: auto;
  margin: 0 auto clamp(1.5rem, 3vw, 2.25rem);
}

.invite-names {
  margin: 0;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 300;
  /* sized to hold one line inside the card at every width */
  font-size: clamp(2.05rem, 4.6vw, 3.4rem);
  line-height: 1.1;
  color: var(--ink-deep);
  text-align: center;
}
.invite-names .amp { font-size: 0.86em; }

/* ---- framed button, squared off like the original ---------------------- */
.btn-frame {
  display: inline-block;
  padding: 0.85rem 1.9rem;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(0.68rem, 0.24vw + 0.63rem, 0.8rem);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  text-decoration: none;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease);
}
.btn-frame:hover { background: var(--ink); color: var(--sand); }

/* ---- envelope + seal --------------------------------------------------- */
.invite-envelope {
  position: absolute;
  z-index: 2;
  /* offsets taken from the original: a fifth across the card, two thirds down
     it, and 138% of its width so it breaks out to the right */
  left: 20%;
  top: 65%;
  width: 138%;
  pointer-events: none;
}
.invite-envelope > img { width: 100%; height: auto; filter: drop-shadow(0 24px 40px rgba(26,34,42,.35)); }

.invite-seal {
  position: absolute;
  left: 50%;
  top: 44%;                     /* the point of the envelope flap */
  transform: translate(-50%, -50%);
  width: 16%;
  display: block;
}
.invite-seal > img { width: 100%; height: auto; }
/* flex, not grid: as a grid the bare "I" text node and the <i> became two rows
   and the monogram stacked vertically instead of interlocking */
.invite-monogram {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(1.05rem, 1.9vw, 1.6rem);
  line-height: 1;
  color: rgba(246, 245, 238, 0.95);
  text-shadow: 0 1px 2px rgba(38, 51, 63, 0.35);
}
.invite-monogram i { font-style: italic; margin-left: -0.18em; }

@media (min-width: 62rem) {
  .invite-group { margin-left: clamp(0rem, 3vw, 3rem); }
}

/* Narrow screens: the card takes the width and the envelope tucks in behind
   its lower edge rather than running across it. */
@media (max-width: 48rem) {
  .invite-stage { padding-bottom: clamp(6rem, 30vw, 10rem); }
  .invite-group { width: 100%; }
  .invite-envelope { left: 10%; top: 74%; width: 108%; }
}

/* Invitation card — bordered stationery panel */
.invite-card {
  position: relative;
  background: var(--sand);
  border: 1px solid var(--hairline);
  padding: clamp(2.25rem, 6vw, 5rem) clamp(1.5rem, 5vw, 4rem);
  box-shadow: 0 24px 60px -32px rgba(87, 71, 55, 0.28);
}
.invite-card::after {
  content: '';
  position: absolute;
  inset: 9px;
  border: 1px solid var(--hairline);
  pointer-events: none;
}

/* ==========================================================================
   Quick-facts strip
   ========================================================================== */

.facts {
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--hairline);
  border-left: 1px solid var(--hairline);
}
@media (min-width: 40rem)  { .facts { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem)  { .facts { grid-template-columns: repeat(4, 1fr); } }
.fact {
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 2.5vw, 2rem);
  text-align: center;
}
.fact dt { margin-bottom: 0.85rem; opacity: 0.7; }
.fact dd { margin: 0; font-family: var(--font-display); font-size: clamp(1.35rem, 2.2vw, 1.85rem); line-height: 1.15; }
.fact small { display: block; margin-top: 0.5rem; font-size: 0.82rem; opacity: 0.72; letter-spacing: 0.02em; }

/* ==========================================================================
   Countdown
   ========================================================================== */

.countdown { display: grid; grid-template-columns: repeat(4, 1fr); max-width: 44rem; margin-inline: auto; }
.countdown > div { padding: 0.75rem 0.35rem; border-left: 1px solid var(--hairline-light); }
.countdown > div:first-child { border-left: 0; }
.countdown .num {
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 6.5vw, 4rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  display: block;
}
.countdown .unit { display: block; margin-top: 0.7rem; opacity: 0.75; }

/* ==========================================================================
   Order of events — semantic timeline
   ========================================================================== */

.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.timeline::before {
  content: '';
  position: absolute;
  left: 0; top: 0.75rem; bottom: 0.75rem;
  width: 1px;
  background: var(--hairline-light);
}
@media (min-width: 48rem) {
  .timeline::before { left: 8.5rem; }
}
.timeline > li {
  position: relative;
  padding: 0 0 clamp(2rem, 4vw, 3rem) 2rem;
  display: grid;
  gap: 0.3rem 2rem;
}
@media (min-width: 48rem) {
  .timeline > li { grid-template-columns: 8.5rem 1fr; padding-left: 0; align-items: center; }
  .timeline > li::before { top: 50%; margin-top: -3.5px; }
  .timeline-body { padding-left: 0.75rem; }
  .timeline > li > * { grid-column: 2; }
  .timeline > li > time { grid-column: 1; text-align: right; padding-right: 2rem; }
}
.timeline > li:last-child { padding-bottom: 0; }
.timeline > li::before {
  content: '';
  position: absolute;
  left: -3px; top: 0.85rem;
  width: 7px; height: 7px;
  background: var(--cream);
  transform: rotate(45deg);
}
@media (min-width: 48rem) { .timeline > li::before { left: calc(8.5rem - 3px); } }
/* Each entry carries the line-art icon the original uses for it. The icon and
   the text sit side by side inside the content column, so the time column and
   the marker on the rule are untouched. */
.timeline-body {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2vw, 1.6rem);
}
.timeline-icon {
  flex: 0 0 auto;
  width: clamp(3.5rem, 5.8vw, 5rem);
  height: auto;
  opacity: 0.92;
}

.timeline time {
  font-family: var(--font-body);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  opacity: 0.72;
  font-variant-numeric: tabular-nums;
}
.timeline h3 { font-size: clamp(1.45rem, 2.6vw, 2rem); }
.timeline p { margin: 0.35rem 0 0; font-size: 0.95rem; opacity: 0.78; max-width: 46ch; }
/* Light-background variant — the cream marker disappears on sand. */
.timeline-light::before { background: var(--hairline); }
.timeline-light > li::before { background: var(--ink); opacity: 0.55; }
.timeline-light time { opacity: 0.65; }

/* Highlighted on the day itself, driven by site.js */
.timeline > li[data-now="true"] h3 { color: var(--cream); }
.timeline > li[data-now="true"]::before { background: var(--terracotta); box-shadow: 0 0 0 5px rgba(133,77,19,0.25); }

/* ==========================================================================
   Cards
   ========================================================================== */

.card {
  background: var(--sand);
  border: 1px solid var(--hairline);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.card-body { padding: clamp(1.35rem, 2.6vw, 2rem); display: flex; flex-direction: column; gap: 0.75rem; flex: 1; }
.card-media { aspect-ratio: 3 / 2; overflow: hidden; }
.card-media img { width: 100%; height: 100%; object-fit: cover; }
.on-dark .card { background: rgba(246,245,238,0.05); border-color: var(--hairline-light); }

/* ==========================================================================
   Gallery
   ========================================================================== */

/* A real grid, not CSS columns: multi-column flows top-to-bottom per column,
   which puts a chronological gallery in the wrong reading order and leaves
   ragged gaps at the foot of each column. */
.gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(0.6rem, 1.4vw, 1.1rem);
}
@media (min-width: 48rem) { .gallery { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 72rem) { .gallery { grid-template-columns: repeat(4, 1fr); } }

.gallery figure { margin: 0; display: flex; flex-direction: column; }
.gallery button {
  display: block; width: 100%; padding: 0; border: 0; background: none;
  cursor: zoom-in; overflow: hidden;
  aspect-ratio: 4 / 5;
  border: 1px solid var(--hairline);
}
.gallery img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease);
}
.gallery button:hover img { transform: scale(1.04); }
.gallery figcaption { margin-top: 0.6rem; opacity: 0.65; }

.lightbox {
  position: fixed; inset: 0; z-index: 200;
  display: none; place-items: center;
  background: rgba(38, 51, 63, 0.94);
  padding: clamp(1rem, 4vw, 3rem);
}
.lightbox[data-open="true"] { display: grid; }
.lightbox img { max-height: 82vh; width: auto; margin-inline: auto; }
.lightbox figcaption { color: var(--cream); text-align: center; margin-top: 1.25rem; }
.lightbox-close, .lightbox-prev, .lightbox-next {
  position: absolute;
  background: transparent;
  border: 1px solid rgba(246,245,238,0.4);
  color: var(--sand);
  width: 3rem; height: 3rem;
  border-radius: 999px;
  cursor: pointer;
  display: grid; place-items: center;
  font-size: 1.1rem;
  transition: background 0.25s var(--ease);
}
.lightbox-close:hover, .lightbox-prev:hover, .lightbox-next:hover { background: rgba(246,245,238,0.16); }
.lightbox-close { top: 1.25rem; right: 1.25rem; }
.lightbox-prev  { left: 1.25rem;  top: 50%; transform: translateY(-50%); }
.lightbox-next  { right: 1.25rem; top: 50%; transform: translateY(-50%); }

/* ==========================================================================
   Sticky sub-navigation (details page)
   ========================================================================== */

.subnav {
  position: sticky;
  top: 4.75rem;
  z-index: 60;
  background: rgba(246, 245, 238, 0.94);
  backdrop-filter: blur(10px);
  border-block: 1px solid var(--hairline);
}
.subnav ol {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: clamp(1rem, 3vw, 2.5rem);
  overflow-x: auto;
  scrollbar-width: none;
  justify-content: flex-start;
  -webkit-overflow-scrolling: touch;
}
.subnav ol::-webkit-scrollbar { display: none; }
@media (min-width: 62rem) { .subnav ol { justify-content: center; } }
.subnav a {
  display: block;
  padding: 1.1rem 0;
  text-decoration: none;
  white-space: nowrap;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  opacity: 0.6;
  border-bottom: 1px solid transparent;
  transition: opacity 0.25s var(--ease), border-color 0.25s var(--ease);
}
.subnav a:hover { opacity: 1; }
.subnav a.is-active { opacity: 1; border-bottom-color: var(--terracotta); }

/* ==========================================================================
   Accordion (FAQ)
   ========================================================================== */

.accordion { border-top: 1px solid var(--hairline); }
.accordion details { border-bottom: 1px solid var(--hairline); }
.accordion summary {
  cursor: pointer;
  list-style: none;
  padding: clamp(1.1rem, 2.2vw, 1.6rem) 3rem clamp(1.1rem, 2.2vw, 1.6rem) 0;
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 1.9vw, 1.5rem);
  line-height: 1.3;
  transition: color 0.25s var(--ease);
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary:hover { color: var(--terracotta); }
.accordion summary::after {
  content: '';
  position: absolute; right: 0.5rem; top: 50%;
  width: 11px; height: 11px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-70%) rotate(45deg);
  transition: transform 0.3s var(--ease);
  opacity: 0.6;
}
.accordion details[open] summary::after { transform: translateY(-30%) rotate(-135deg); }
.accordion .answer { padding: 0 0 clamp(1.25rem, 2.4vw, 1.9rem); max-width: 62ch; }
.accordion .answer p { margin: 0 0 0.9em; }
.accordion .answer p:last-child { margin-bottom: 0; }

/* ==========================================================================
   Forms
   ========================================================================== */

.field { display: grid; gap: 0.5rem; }
.field > label, .fieldset-legend {
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  opacity: 0.8;
}
.field .hint { font-size: 0.86rem; opacity: 0.65; letter-spacing: 0.01em; }
.req { color: var(--terracotta); }

input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
input[type="date"], select, textarea {
  width: 100%;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 1rem;
  color: var(--ink);
  background: var(--sand);
  border: 1px solid var(--hairline);
  border-radius: 2px;
  padding: 0.85rem 1rem;
  min-height: 3rem;
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease);
  appearance: none;
}
textarea { min-height: 7.5rem; resize: vertical; line-height: 1.55; }
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%235C4E3D' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.6rem;
}
input:hover, select:hover, textarea:hover { border-color: rgba(92,78,61,0.4); }
input::placeholder, textarea::placeholder { color: rgba(92,78,61,0.45); }

[aria-invalid="true"] { border-color: #A33B1F !important; background: rgba(163,59,31,0.04); }
.error-text { color: #8E3319; font-size: 0.86rem; display: flex; gap: 0.4rem; align-items: flex-start; }

/* Yes / No segmented control */
.segmented { display: inline-grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--hairline); border-radius: 999px; overflow: hidden; }
.segmented label {
  position: relative;
  padding: 0.7rem 1.5rem;
  text-align: center;
  cursor: pointer;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease);
  min-height: 2.9rem;
  display: grid;
  place-items: center;
}
.segmented input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.segmented label:has(input:checked) { background: var(--ink); color: var(--sand); }
.segmented label:has(input:focus-visible) { outline: 2px solid var(--terracotta); outline-offset: 2px; }

/* Chip checkboxes (dietary) */
.chips { display: flex; flex-wrap: wrap; gap: 0.55rem; }
.chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.55rem 1.1rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.88rem;
  min-height: 2.5rem;
  transition: background-color 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.chip input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.chip:has(input:checked) { background: var(--cream); border-color: var(--ink); color: var(--ink-deep); }
.chip:has(input:focus-visible) { outline: 2px solid var(--terracotta); outline-offset: 2px; }

/* Display lives here, not in an inline style, so the declined-guest rule below
   can actually win. */
.when-attending { display: grid; gap: 1.25rem; }

/* Guest block */
.guest-card {
  border: 1px solid var(--hairline);
  background: rgba(246,245,238,0.6);
  padding: clamp(1.25rem, 2.6vw, 2rem);
  display: grid;
  gap: 1.5rem;
}
.guest-card[data-attending="no"] { opacity: 0.72; background: rgba(238,237,231,0.5); }
.guest-card[data-attending="no"] .when-attending { display: none; }

/* Copy-to-clipboard row (bank details) */
.copy-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--hairline);
}
.copy-row:last-of-type { border-bottom: 0; }
.copy-row dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.18em; opacity: 0.7; }
.copy-row dd { margin: 0; font-family: var(--font-body); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   TBC flag — marks content the couple still owes us (plan §9)
   ========================================================================== */

.tbc {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px dashed rgba(133, 77, 19, 0.6);
  color: var(--terracotta);
  background: rgba(133, 77, 19, 0.06);
  border-radius: 3px;
  padding: 0.15rem 0.55rem;
  font-family: var(--font-body);
  font-size: 0.62rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  vertical-align: middle;
  white-space: nowrap;
}
.on-dark .tbc { border-color: rgba(243,235,207,0.6); color: var(--cream); background: rgba(243,235,207,0.1); }
.tbc-block {
  border: 1px dashed rgba(133, 77, 19, 0.5);
  background: rgba(133, 77, 19, 0.045);
  padding: clamp(1rem, 2.2vw, 1.5rem);
  border-radius: 3px;
}
.on-dark .tbc-block { border-color: rgba(243,235,207,0.4); background: rgba(243,235,207,0.07); }

/* Mockup notice — sits at the foot of each page, above the footer. */
.mock-note {
  border: 1px dashed rgba(133, 77, 19, 0.45);
  background: rgba(133, 77, 19, 0.05);
  border-radius: 3px;
  padding: clamp(1rem, 2.2vw, 1.5rem) clamp(1.1rem, 2.4vw, 1.75rem);
  font-size: 0.88rem;
  line-height: 1.55;
}
.mock-note p { margin: 0 0 0.6em; }
.mock-note p:last-child { margin-bottom: 0; }
.mock-note code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86em;
  background: rgba(92, 78, 61, 0.08);
  padding: 0.1em 0.4em;
  border-radius: 2px;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer { background: var(--navy-deep); color: var(--sand); }
.site-footer a { color: var(--cream); }

/* ==========================================================================
   Reveal on scroll
   ========================================================================== */

.reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: 0.08s; }
.reveal-d2 { transition-delay: 0.16s; }
.reveal-d3 { transition-delay: 0.24s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   Print — guests do print the details page
   ========================================================================== */

@media print {
  body::before, .site-header, .rsvp-bar, .subnav, .mock-banner, .nav-drawer, .lightbox { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .on-dark, .site-footer { background: #fff !important; color: #000 !important; }
  .on-dark h1, .on-dark h2, .on-dark h3 { color: #000 !important; }
  .section { padding-block: 1.5rem; }
  a[href^="http"]::after { content: ' (' attr(href) ')'; font-size: 9pt; }
}
