:root{
  --paper:#f6eedd;
  --paper-2:#efe4cd;
  --red:#a01322;
  --red-2:#870e1c;
  --red-deep:#650a13;
  --thread:#b31226;
  --gold:#b8923a;
  --gold-hi:#e6c465;
  --ink:#38220f;
  --ink-soft:#7c6248;

  --serif:'Fraunces',Georgia,serif;
  --sans:'Instrument Sans',system-ui,-apple-system,sans-serif;
  --pad:clamp(22px,6vw,110px);
  --ease:cubic-bezier(.22,.8,.24,1);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--sans); background:var(--paper); color:var(--ink); -webkit-font-smoothing:antialiased; overflow-x:clip}
::selection{background:var(--red); color:var(--paper)}
#page:focus{outline:none}

/* rice paper grain.
   NOTE: no mix-blend-mode here. A fixed full-screen multiply overlay forces the
   browser to re-blend the whole viewport against the scrolling content every
   frame, which tanks scroll performance. A plain low-opacity texture reads the
   same at 5% and composites for free. */
.grain{position:fixed; inset:0; z-index:4; pointer-events:none; opacity:.045;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");}

/* language toggle: a small gold pill, fixed above everything (incl. the gate).
   The translucent ink pill keeps the gold legible on cream, red, and deep red alike. */
.langtoggle{position:fixed; z-index:70; display:flex; align-items:center; gap:9px;
  top:calc(env(safe-area-inset-top,0px) + 12px); right:calc(env(safe-area-inset-right,0px) + 14px);
  padding:7px 13px; border-radius:999px; background:rgba(43,20,8,.5); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  font-family:var(--sans); font-size:11px; letter-spacing:.14em; box-shadow:0 3px 14px rgba(56,34,15,.2)}
.langtoggle button{background:none; border:none; padding:0; margin:0; cursor:pointer; color:var(--gold-hi);
  opacity:.5; font:inherit; letter-spacing:inherit; transition:opacity .25s}
.langtoggle button:hover{opacity:.85}
.langtoggle button.on{opacity:1; font-weight:600}
.langtoggle .sep{color:var(--gold-hi); opacity:.4}

/* the thread lives IN the document. It sits ABOVE section/band backgrounds (z-2)
   but BELOW all content (sections + the RSVP form at z-3), so it weaves behind
   photos and text yet stays visible where it crosses the solid red RSVP band.
   The band's red fill is painted by .rsvp::before at z-1, under the thread. */
#threadsvg{position:absolute; top:0; left:0; z-index:2; pointer-events:none; overflow:visible}
#threadsvg path{fill:none; stroke:url(#threadgrad) var(--thread); stroke-width:2; stroke-linecap:round}

main{position:relative}
section{position:relative; z-index:3; padding-left:var(--pad); padding-right:var(--pad)}

.label{font-family:var(--serif); font-style:italic; font-size:clamp(16px,2.2vw,21px); color:var(--gold); letter-spacing:.02em}
.seal{display:block}

/* ---------- GATE ---------- */
.gate{position:fixed; inset:0; z-index:60; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:24px; text-align:center; padding:34px;
  background:radial-gradient(130% 100% at 50% 20%, var(--red) 0%, var(--red-2) 55%, var(--red-deep) 100%);
  color:var(--paper); transition:opacity 1.1s var(--ease), visibility 1.1s}
.gate.open{opacity:0; visibility:hidden}
.gate .seal{width:clamp(96px,18vw,132px); filter:drop-shadow(0 8px 34px rgba(230,196,101,.32))}
.gate .who{font-family:var(--serif); font-size:clamp(22px,4vw,30px); font-weight:400; letter-spacing:.05em}
.gate p{max-width:33ch; color:#f0d9b5; font-size:15px; line-height:1.75; opacity:.92}
.gatebox{display:flex; gap:10px; width:min(370px,86vw); margin-top:4px}
/* font-size must stay >= 16px: iOS Safari auto-zooms the page in on focus of any
   smaller input, which left the hero scrolled with the seal clipped after unlock. */
.gatebox input{flex:1; background:rgba(255,255,255,.06); border:1px solid rgba(230,196,101,.5); color:var(--paper);
  padding:14px 16px; font-family:var(--sans); font-size:16px; border-radius:2px; outline:none; transition:border-color .3s}
.gatebox input::placeholder{color:#e6c46588}
.gatebox input:focus{border-color:var(--gold-hi)}
.gatebox button{background:var(--gold); color:var(--red-deep); border:none; padding:0 24px; cursor:pointer;
  font-family:var(--sans); font-weight:600; font-size:14px; border-radius:2px; transition:background .3s}
.gatebox button:hover{background:var(--gold-hi)}
.gate .err{color:#f6d2a0; font-size:13px; min-height:18px}
.gatebox.shake{animation:shake .4s var(--ease)}
@keyframes shake{20%{transform:translateX(-7px)}45%{transform:translateX(6px)}70%{transform:translateX(-4px)}90%{transform:translateX(2px)}}

/* ---------- entrance choreography ----------
   will-change promotes each rise element to its own compositor layer up front so
   the heavy first paint (esp. the huge variable-font names) happens once, and the
   transform/opacity transition is smooth from the first frame instead of stuttering
   while the gate fades. body.settled drops the hint once the entrance is over. */
.rise{opacity:0; transform:translateY(22px); transition:opacity 1s var(--ease), transform 1s var(--ease); will-change:transform, opacity}
body.settled .rise{will-change:auto}
body.in .rise{opacity:1; transform:none}
body.in .rise.d1{transition-delay:.15s} body.in .rise.d2{transition-delay:.3s}
body.in .rise.d3{transition-delay:.45s} body.in .rise.d4{transition-delay:.6s}
body.in .rise.d5{transition-delay:.8s}

/* scroll reveals */
.reveal{opacity:0; transform:translateY(26px); transition:opacity .9s var(--ease), transform .9s var(--ease)}
.reveal.on{opacity:1; transform:none}

/* ---------- HERO ---------- */
.hero{min-height:100svh; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center;
  padding-top:12vh; padding-bottom:10vh}
.hero .seal{width:clamp(66px,9vw,90px); margin-bottom:clamp(20px,4vh,38px)}
.hero .label{margin-bottom:clamp(16px,3vh,28px)}
.names{font-family:var(--serif); font-optical-sizing:auto; line-height:.96; color:var(--red)}
.names .n{display:block; font-weight:340; font-size:clamp(58px,14.5vw,172px); letter-spacing:0}
.names .amp{display:block; font-style:italic; font-weight:300; color:var(--gold); font-size:clamp(28px,5.6vw,68px); margin:clamp(2px,1vh,10px) 0}
.hero .meta{margin-top:clamp(28px,5vh,56px); font-family:var(--serif); font-weight:400; font-size:clamp(18px,2.6vw,26px); line-height:1.7}
.hero .meta .dot{color:var(--gold); padding:0 10px}
.hero .sub{margin-top:10px; font-size:13px; letter-spacing:.18em; text-transform:uppercase; color:var(--ink-soft)}
.scrollcue{margin-top:clamp(36px,7vh,80px); display:flex; align-items:center; gap:12px; color:var(--ink-soft); font-size:11px; letter-spacing:.22em; text-transform:uppercase}
.scrollcue .line{width:46px; height:1px; background:var(--gold); position:relative; overflow:hidden}
.scrollcue .line::after{content:""; position:absolute; inset:0; background:var(--red); animation:sweep 2.8s ease-in-out infinite}
@keyframes sweep{0%{transform:translateX(-100%)}60%,100%{transform:translateX(100%)}}

/* ---------- PHOTOS ---------- */
.frames{padding-top:clamp(60px,11vh,130px); padding-bottom:clamp(60px,11vh,130px)}
.hero + .frames{padding-top:clamp(14px,3vh,40px)}   /* tighten the gap under the scroll cue */
.frame{margin-bottom:clamp(76px,15vh,170px)}
.frame:last-child{margin-bottom:0}
.frame figure{overflow:hidden; border-radius:2px; background:var(--paper-2);
  box-shadow:0 26px 60px -30px rgba(56,34,15,.5); outline:1px solid rgba(184,146,58,.4); outline-offset:9px}
.frame img{width:100%; height:100%; object-fit:cover; display:block}
.frame.wide{max-width:900px; margin-left:auto; margin-right:auto}
.frame.wide figure{aspect-ratio:16/10}
.frame.portrait{max-width:520px; margin-left:auto; margin-right:auto}
.frame.portrait figure{aspect-ratio:4/5}
.frame.tall{max-width:500px; margin-left:auto}
.frame.tall figure{aspect-ratio:4/5}
.frame.offset{max-width:500px}
.frame.offset figure{aspect-ratio:4/5}
.frame figcaption{margin-top:16px; color:var(--ink-soft); font-family:var(--serif); font-style:italic; font-size:17px}

/* ---------- THE DETAILS (editorial rows: label in the margin, content beside it) ---------- */
.day{padding-top:clamp(74px,14vh,150px); padding-bottom:clamp(84px,16vh,170px)}
.day h2{font-family:var(--serif); font-weight:320; font-size:clamp(33px,5.8vw,66px); line-height:1.08;
  margin:0 auto clamp(46px,8vh,80px); max-width:16ch; text-align:center}
.day h2 em{font-style:italic; font-weight:340; color:var(--red)}

.details{max-width:780px; margin:0 auto}
.detail{display:grid; grid-template-columns:130px 1fr; gap:clamp(18px,4vw,48px);
  padding:clamp(30px,5vh,44px) 0; border-top:1px solid rgba(184,146,58,.28)}
.detail:first-child{border-top:none; padding-top:0}
.dk{text-transform:uppercase; letter-spacing:.2em; font-size:11px; color:var(--gold); padding-top:8px}
.dt{font-family:var(--serif); font-weight:400; font-size:clamp(22px,2.8vw,30px); line-height:1.15}
.dv p{margin-top:12px; color:var(--ink-soft); font-size:15px; line-height:1.75; max-width:44ch}
.dv a{color:var(--red); text-decoration:none; border-bottom:1px solid rgba(160,19,34,.3); white-space:nowrap}
.dv a:hover{border-bottom-color:var(--red)}

.sketch{display:block; height:auto}
.sketch.hotel{width:100%; aspect-ratio:5/3; margin-bottom:16px}

.hotels{display:grid; grid-template-columns:1fr 1fr; gap:clamp(22px,4vw,40px); margin-top:22px}
.hotel .hname{font-family:var(--serif); font-size:19px; line-height:1.2}
.hotel .hnote{margin-top:6px; color:var(--ink-soft); font-size:14px; line-height:1.65}
.hotel a{display:inline-block; margin-top:12px; color:var(--red); text-decoration:none; font-size:14px;
  letter-spacing:.02em; border-bottom:1px solid rgba(160,19,34,.3)}
.hotel a:hover{border-bottom-color:var(--red)}

/* ---------- RSVP ---------- */
/* No z-index here on purpose: .rsvp must NOT create a stacking context, so its
   ::before red fill (z-1) and its .rsvp-in content (a section, z-3) resolve in
   main's context with the thread (z-2) sliced between them. */
.rsvp{position:relative; color:var(--paper)}
.rsvp::before{content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:radial-gradient(120% 80% at 50% 0%, var(--red) 0%, var(--red-2) 55%, var(--red-deep) 100%)}
.rsvp-in{padding-top:clamp(52px,8vh,84px); padding-bottom:clamp(80px,15vh,150px); max-width:720px; margin:0 auto; text-align:center}
.knot{display:block; margin:0 auto clamp(10px,2vh,22px); width:clamp(104px,17vw,140px); height:auto;
  filter:drop-shadow(0 6px 26px rgba(230,196,101,.22))}
.knot .draw{stroke-dasharray:1; stroke-dashoffset:1; transition:stroke-dashoffset 1.1s var(--ease)}
.knot.tied .draw{stroke-dashoffset:0}
.knot.tied .draw.k2{transition-delay:.2s} .knot.tied .draw.k3{transition-delay:.4s}
.knot.tied .draw.k4{transition-delay:.6s} .knot.tied .draw.k5{transition-delay:.85s}
.knot .gem{opacity:0; transition:opacity .6s ease 1.1s}
.knot.tied .gem{opacity:1}
.rsvp .label{color:var(--gold-hi)}
.rsvp h2{font-family:var(--serif); font-weight:320; font-size:clamp(38px,7.6vw,84px); line-height:1.02; margin:6px 0 14px}
.rsvp h2 em{font-style:italic; color:var(--gold-hi)}
.rsvp .lede{color:#f0d9b5; max-width:46ch; margin:0 auto clamp(40px,7vh,60px); line-height:1.75; font-size:15px}
form{text-align:left}
.fieldrow{display:grid; grid-template-columns:1fr 1fr; gap:22px 26px}
.field{display:flex; flex-direction:column; gap:9px}
.field.full{grid-column:1/-1}
label{font-size:12px; letter-spacing:.13em; text-transform:uppercase; color:#e6c465bb}
input[type=text],input[type=tel],input[type=email],textarea,select{
  background:transparent; border:none; border-bottom:1px solid rgba(230,196,101,.4); color:var(--paper);
  padding:10px 2px; font-family:var(--sans); font-size:16px; outline:none; transition:border-color .3s; border-radius:0}
textarea{resize:vertical; min-height:64px}
select{appearance:none; cursor:pointer}
option{color:#38220f}
input:focus,textarea:focus,select:focus{border-color:var(--gold-hi)}

/* guest list */
.hint{font-size:12.5px; line-height:1.55; color:#e6c46599; text-transform:none; letter-spacing:0; margin-top:-2px}
.guests{display:flex; flex-direction:column; gap:14px}
.guestrow{display:flex; align-items:center; gap:12px}
.guestrow input{flex:1}
.guestrow .rm{flex:none; width:26px; height:26px; padding:0; border:1px solid rgba(230,196,101,.4); background:transparent;
  color:#e6c465bb; border-radius:50%; cursor:pointer; font-size:16px; line-height:1; transition:.25s; display:flex; align-items:center; justify-content:center}
.guestrow .rm:hover{border-color:var(--gold-hi); color:var(--gold-hi)}
.addguest{align-self:flex-start; margin-top:14px; background:transparent; border:none; color:var(--gold-hi);
  cursor:pointer; font-family:var(--sans); font-size:14px; letter-spacing:.02em; padding:2px 0; border-bottom:1px solid rgba(230,196,101,.4)}
.addguest:hover{border-bottom-color:var(--gold-hi)}

.attend{display:flex; gap:12px; flex-wrap:wrap}
.attend label{flex:1; min-width:170px; text-transform:none; letter-spacing:0; color:var(--paper);
  border:1px solid rgba(230,196,101,.4); padding:16px 18px; border-radius:2px; cursor:pointer; font-size:15px; transition:border-color .3s, background .3s}
.attend label:has(input:checked){border-color:var(--gold-hi); background:rgba(230,196,101,.08)}
.attend input{position:absolute; opacity:0; pointer-events:none}
.attend label span{display:flex; align-items:center; gap:12px}
.attend label .dot{width:11px; height:11px; border-radius:50%; border:1px solid #e6c46599; flex:none; transition:.25s}
.attend input:checked + span .dot{background:var(--gold-hi); border-color:var(--gold-hi); box-shadow:0 0 0 4px rgba(230,196,101,.18)}
.formerr{min-height:20px; margin-top:20px; text-align:center; color:#f6d2a0; font-size:14px; line-height:1.6}
.formerr a{color:var(--gold-hi)}
.submit{margin-top:clamp(20px,4vh,32px); width:100%; background:var(--gold); color:var(--red-deep); border:none;
  padding:19px; font-family:var(--sans); font-weight:600; font-size:15px; letter-spacing:.04em; border-radius:2px; cursor:pointer; transition:background .3s, transform .15s}
.submit:hover{background:var(--gold-hi)}
.submit:active{transform:translateY(1px)}
.submit:disabled{opacity:.7; cursor:default}
.already{margin-top:24px; text-align:center; color:#e6c465bb; font-size:14px}
.already a{color:var(--gold-hi); text-decoration:none; border-bottom:1px solid rgba(230,196,101,.4)}
.already a:hover{border-bottom-color:var(--gold-hi)}
.thanks{display:none; text-align:center; padding:clamp(20px,4vh,40px) 0}
.thanks.show{display:block; animation:riseIn .8s var(--ease)}
.thanks .mark{font-family:var(--serif); font-style:italic; color:var(--gold-hi); font-size:clamp(32px,6vw,50px); margin-bottom:14px}
.thanks p{color:#f0d9b5; max-width:40ch; margin:0 auto; line-height:1.75}
.thanks .cue{margin-top:22px; font-family:var(--serif); font-style:italic; color:var(--gold-hi); font-size:16px}
@keyframes riseIn{from{opacity:0; transform:translateY(16px)}to{opacity:1; transform:none}}

footer{position:relative; z-index:3; background:var(--red-deep); color:#e6c465cc; padding:clamp(40px,7vh,70px) var(--pad);
  display:flex; flex-wrap:wrap; gap:16px 40px; justify-content:space-between; align-items:center; font-size:13px}
footer .sig{display:flex; align-items:center; gap:14px; font-family:var(--serif); font-style:italic; font-size:20px; color:var(--paper)}
footer .sig .seal{width:34px}
footer a{color:var(--gold-hi); text-decoration:none}

:focus-visible{outline:2px solid var(--gold-hi); outline-offset:3px}
@media (max-width:640px){
  .fieldrow{grid-template-columns:1fr}
  #threadsvg path{stroke-width:1.6}
  .detail{grid-template-columns:1fr; gap:8px}
  .dk{padding-top:0}
  .hotels{grid-template-columns:1fr; gap:32px}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .scrollcue .line::after{animation:none}
  .rise,.reveal{opacity:1; transform:none; transition:none}
  .gatebox.shake{animation:none}
  .knot .draw{stroke-dashoffset:0; transition:none}
  .knot .gem{opacity:1; transition:none}
}
