:root{
  /* Warmer/deeper than the site's original cream — closer to the printed
     invite. --cream-rgb exists so every rgba(cream, X) accent across the
     site (including rsvp.html, which locally overrides --cream itself to
     the inverted accent color) can share one source of truth instead of
     hardcoding this triplet in a dozen places. */
  --cream-rgb: 231, 218, 192;
  --cream: rgb(var(--cream-rgb));
  --accent-rgb: 161, 80, 60;
  --accent: #A1503C;
  --accent-ink: #5C3624;
  --accent-stripe-soft: #D9AE8E;
  --accent-hover-dark: #66220f;
  --accent-hover-light: #DCC7A3;

  --stripe: var(--accent);
  --stripe-soft: var(--accent-stripe-soft);
  --rust: var(--accent);
  --rust-deep: var(--accent);
  --rust-soft: var(--accent);
  --ink: var(--accent-ink);
}

html[data-theme="blue"]{
  --accent-rgb: 61, 107, 140;
  --accent: #3D6B8C;
  --accent-ink: #1E3648;
  --accent-stripe-soft: #B8CFDA;
  --accent-hover-dark: #1F3A4D;
  --accent-hover-light: #C9DCE5;
}

@view-transition {
  navigation: auto;
}

/* Tuned page-transition timing to match the site's .3s ease-in-out feel,
   plus a slight vertical drift instead of a flat cross-dissolve. Nav keeps
   the browser's default morph (it has a stable position via
   view-transition-name below) — only the root gets custom motion. */
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
  animation-duration: 0.38s;
  animation-timing-function: ease-in-out;
}

::view-transition-old(root) {
  animation-name: site-page-out;
}
::view-transition-new(root) {
  animation-name: site-page-in;
}

@keyframes site-page-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-8px); }
}
@keyframes site-page-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Used by rsvp.html to give the page you're leaving a more pronounced sink
   instead of the standard 8px drift, so that transition reads as a distinct
   moment from Home<->Details. Cross-document transition pseudo-elements are
   styled by the DESTINATION document, so this only takes effect when
   rsvp.html's own stylesheet (below) opts into it — never here. */
@keyframes site-page-sink {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(40px); }
}

/* Theme-toggle "bloom" reveal (theme.js adds/removes this class around the
   transition). Cancels every named region's own animation for this one
   instance — including page-navigation entrances like rsvp-card-in, which
   would otherwise replay (wrongly) on a same-document theme toggle, since
   those rules only key off the pseudo-element name, not the transition
   type. The `*` covers root, nav, card and content on every page, present
   or future, rather than enumerating each name by hand. The only motion
   left is the synced clip-path circle theme.js animates directly on each
   region's ::view-transition-new(name) — old stays fully visible
   underneath, revealed only where the growing circle hasn't reached yet. */
html.theme-bloom::view-transition-old(*),
html.theme-bloom::view-transition-new(*) {
  animation: none;
  mix-blend-mode: normal;
}

*{ box-sizing:border-box; }

html{
  /* Reserve scrollbar space on every page, scrollbar or not — RSVP is much
     shorter than Home/Details, so without this the centered content shifts
     sideways when a page that needs a scrollbar swaps for one that doesn't. */
  scrollbar-gutter: stable;
}

html,body{
  margin:0; padding:0;
  background:var(--cream);
  font-family:'Be Vietnam Pro', sans-serif;
  color:var(--rust-soft);
  min-height:100vh;
  /* Safety net: nothing on this page should ever be wider than the
     viewport, but if the bouncing icon's position ever computes past the
     edge (e.g. a stale viewport-width reading), this stops it from
     creating real horizontal scroll — which is what actually shifts the
     centered .wrap content off-screen, not just the icon itself. */
  overflow-x: hidden;
}

body{
  background-image: repeating-linear-gradient(
    90deg,
    var(--stripe-soft) 0px,
    var(--stripe-soft) 1px,
    transparent 1px,
    transparent 5px
  );
  background-attachment: scroll;
  padding: clamp(24px, 6vw, 48px) clamp(12px, 4vw, 16px) clamp(48px, 10vw, 80px);
}

.wrap{
  max-width: 620px;
  margin: 0 auto;
  container-type: inline-size;
}

.card{
  background: rgba(var(--cream-rgb), 0.95);
  border-radius: 50cqw;
  padding: clamp(68px, 19cqw, 100px) clamp(34px, 10cqw, 64px);
  position: relative;
  overflow: hidden;
  /* Named so Home<->Details morphs this pill's size/position directly
     instead of crossfading (see pill-transition.css, linked only by those
     two pages). rsvp.html overrides this to a different name locally, so
     its clover card is unaffected and never morphs with this shape. */
  view-transition-name: pill-card;
  /* Above the bouncing theme-toggle icon (z-index:1 on .toggle-orbit) so
     the icon is genuinely unhoverable/unclickable while passing underneath
     this shape — normal hit-testing handles that, no JS collision needed.
     rsvp.html's clover uses clip-path, so this also occludes precisely
     along the clover's actual outline there, not just its bounding box. */
  z-index: 2;
}

.content{
  position:relative;
  text-align:center;
  /* See .card above — named so its fade can be timed independently of the
     shape morph (in pill-transition.css). Also overridden locally on
     rsvp.html. */
  view-transition-name: page-content;
}

/* Simple site nav — repeated near the top of each page's content */
.nav-wrap{
  text-align: center;
  margin-bottom: 22px;
}

/* Fixed-position wrapper that bounce.js moves around the viewport (DVD
   screensaver style). inline-flex so the box shrink-wraps to the button's
   actual size — a plain block div here would stretch full-width and create
   an invisible hit-testable strip at whatever height it's translated to. */
.toggle-orbit{
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1;
  display: inline-flex;
  will-change: transform;
}

.theme-toggle{
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  padding: 12px;
  margin: 0;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity .25s ease-in-out, transform .2s ease-in-out;
}
.theme-toggle:hover{ opacity: 1; }
.theme-toggle:active{ transform: scale(0.9); }
.theme-toggle svg{
  /* Same size as the .bloom flower between the couple's names above. */
  width: clamp(26px, 6cqw, 40px);
  height: clamp(26px, 6cqw, 40px);
  display: block;
}
.theme-toggle .swatch-path{
  fill: var(--accent);
}

.site-nav{
  display:inline-flex;
  justify-content:center;
  gap: 22px;
  flex-wrap: wrap;
  font-family: 'Imbue', serif;
  /* Sized to match .details h3 (Ceremony/Reception), capping at its fixed
     22px. Lighter than that heading's own 500 weight — nav is persistent
     chrome on every page, not a moment that should compete with in-content
     headings for attention. */
  font-size: clamp(18px, 4cqw, 22px);
  font-weight: 400;
  background: rgba(var(--cream-rgb), 0.95);
  padding: 12px 28px;
  border-radius: 999px;
  view-transition-name: site-nav;
  /* position:relative so z-index takes effect at all (static elements
     ignore it) — needed to occlude the bouncing theme-toggle icon
     (z-index:1) the same way .card does. */
  position: relative;
  z-index: 2;
}
.site-nav a{
  color: var(--rust-soft);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color .25s ease-in-out, color .25s ease-in-out;
}
.site-nav a:hover{ border-color: var(--rust-soft); }
.site-nav .current{
  color: var(--rust-deep);
  border-bottom: 1px solid var(--rust-deep);
  padding-bottom: 2px;
}

.eyebrow{
  font-size: 14px;
  font-weight: 300;
  letter-spacing: 0.02em;
  line-height: 1.7;
  color: var(--rust-soft);
  margin-bottom: 22px;
}
.eyebrow .vn{ font-size: 13px; }
.eyebrow .family{ margin-bottom: 14px; }

.announce{
  font-size: 15px;
  font-weight: 300;
  max-width: 380px;
  margin: 26px auto;
  line-height: 1.6;
  color: var(--rust-soft);
}
.announce .vn{ display:block; margin-top: 8px; font-size: 14px; }

.rule{
  width: 90px;
  height: 1px;
  background: var(--stripe);
  margin: 30px auto;
}

.names{
  font-family: 'Imbue', serif;
  color: var(--rust-deep);
  /* Matched to the printed invite's lighter, more delicate display weight
     (Imbue is embedded as a variable font, full 100-900 range) — 500 read
     noticeably bolder than the invite's actual strokes. Sized up since the
     lighter weight reads smaller at the same font-size. */
  font-size: clamp(46px, 12cqw, 80px);
  line-height: 1.15;
  font-weight: 300;
}
/* Per-letter reveal (index.html only — see its inline script). inline-block
   so each letter can move independently; the animation itself supplies the
   initial hidden state (opacity/translateY in its first keyframe), so if
   the script never runs, the plain text underneath is already visible and
   nothing is ever stuck hidden. */
.names .letter{ display: inline-block; }

.bloom{
  margin: 32px 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bloom svg{
  width: clamp(26px, 6cqw, 40px);
  height: clamp(26px, 6cqw, 40px);
  display: block;
}

.date-row{
  display:flex;
  align-items:center;
  justify-content:center;
  gap: 16px;
  margin: 30px 0 40px;
  font-family: 'Imbue', serif;
  font-size: clamp(19px, 4.2cqw, 24px);
  color: var(--rust-deep);
}
.date-row .dash{ width: 30px; height: 1px; background: var(--stripe); }

.details{
  display:flex;
  gap: 28px;
  justify-content:center;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.details .col{ min-width: 190px; }

.details h3{
  font-family:'Imbue', serif;
  font-weight: 500;
  font-size: 22px;
  color: var(--rust-deep);
  margin: 0 0 10px;
}
.details p{
  margin: 0;
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.65;
  color: var(--rust-soft);
}

.divider-full{
  width: 90px;
  height:1px;
  background: var(--stripe);
  margin: 46px auto 38px;
  opacity: 0.6;
}

/* Page-level heading, used by Details and RSVP pages */
.page-heading{
  font-family:'Imbue', serif;
  font-size: clamp(28px, 7cqw, 34px);
  color: var(--rust-deep);
  margin: 0 0 6px;
}
.page-sub{
  font-size: 14px;
  color: var(--rust-soft);
  margin: 0 0 12px;
}

/* Shared pill-shaped link/button used for nav CTAs (e.g. home page's "View Details" / "RSVP") */
.pill-btn{
  display:inline-block;
  padding: 13px 26px;
  border-radius: 999px;
  background: var(--rust-deep);
  color: var(--cream);
  font-family: 'Imbue', serif;
  font-size: 16px;
  letter-spacing: 0.02em;
  text-decoration: none;
  transition: background-color .3s ease-in-out, transform .2s ease-in-out;
}
.pill-btn:hover{ background: var(--accent-hover-dark); }
.pill-btn:active{ transform: scale(0.98); }
.pill-btn.outline{
  background: transparent;
  border: 1px solid var(--stripe);
  color: var(--rust-deep);
}
.pill-btn.outline:hover{ background: rgba(var(--accent-rgb), 0.08); }

.cta-row{
  display:flex;
  gap: 18px;
  justify-content:center;
  flex-wrap: wrap;
  margin-top: 12px;
}

@media (max-width: 480px){
  .details{ gap: 20px; }
  .details .col{ min-width: 150px; }
}

@media (prefers-reduced-motion: reduce){
  *{ transition:none !important; }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*){
    animation: none !important;
  }
}

.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;
}
