:root{
  --ink: #f6f1ff;
  --ink-dim: #a08fc8;
  --accent: #8fd62f;   /* lime, from the coral tips */
  --warm:   #ff7c1a;   /* hot orange, from the ring */
  --bg: #0d0620;       /* deep violet, from the ground */
  --text: #ddd4f0;     /* everything you read */

  /* the type scale: apart from the headings, the hero and the story's short
     versions, every piece of text uses one of these two sizes */
  --fs-body: clamp(17px, 1.55vw, 21px);   /* reading text: paragraphs and both lists */
  --fs-ui:   clamp(14px, 1.2vw, 17px);    /* labels, buttons, small print */

  /* Questrial is a single-weight face — there is no bold. Emphasis is done
     with size, letter-spacing and colour instead. If you ever want real bold
     headlines, swap this line for one of:
       'Quicksand'  — rounder, 300-700            'Nunito'   — soft, 200-1000
       'Comfortaa'  — very round, 300-700         'Poppins'  — geometric, 100-900
     and update the <link> in index.html to match. */
  --font: "Questrial", ui-rounded, "Avenir Next", system-ui, sans-serif;
}

*{ box-sizing: border-box; }

html{ scroll-behavior: smooth; }

body{
  margin:0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---------- the art layer ---------- */

#art{
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
  display: block;
}

.grain{
  position: fixed;
  inset: -50%;
  z-index: 1;
  pointer-events: none;
  opacity: .035;
  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='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: drift 7s steps(6) infinite;
}
@keyframes drift{
  0%{transform:translate(0,0)} 20%{transform:translate(-3%,2%)}
  40%{transform:translate(2%,-3%)} 60%{transform:translate(-2%,-2%)}
  80%{transform:translate(3%,1%)} 100%{transform:translate(0,0)}
}

.vignette{
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%, transparent 35%, rgba(9,4,22,.58) 100%);
}

/* ---------- fixed chrome ---------- */

/* the language switch, top left: the language you're reading is bright and
   underlined in lime, the others soft */
.lang{
  position: fixed;
  top: 24px; left: 28px;
  z-index: 5;
  display: flex; gap: 0;
  padding: 2px 6px;
  font-family: var(--font);
  background: rgba(28,14,58,.62);            /* the same soft backing as the music buttons */
  border: 1px solid rgba(160,143,200,.3);
  border-radius: 999px;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.lang button{
  font: inherit; font-size: 12px; letter-spacing: .10em;
  color: var(--ink-dim);
  background: none; border: 0;
  padding: 7px 7px 5px;
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
.lang button:hover{ color: var(--ink); }
.lang button[aria-pressed="true"]{ color: var(--ink); border-bottom-color: var(--accent); }
.lang button:focus-visible{ outline: 1px solid var(--accent); outline-offset: 2px; }

.hint{
  position: fixed;
  bottom: 30px; left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  font-family: var(--font);
  font-size: 11px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-dim);
  transition: opacity .5s ease;
}
.hint svg{ animation: nudge 2.4s ease-in-out infinite; }
@keyframes nudge{ 0%,100%{transform:translateY(0);opacity:.5} 50%{transform:translateY(5px);opacity:1} }

/* ---------- content ---------- */

main{
  position: relative;
  z-index: 3;
}

.sec{
  position: relative;
  min-height: 118vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 16vh clamp(24px, 9vw, 160px);
  max-width: 1200px;
  will-change: opacity, transform;
}

.inner{
  position: relative;
  width: 100%;
}

.inner > *{ max-width: 46ch; }

.kicker{
  font-family: var(--font);
  font-size: 13px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--warm);             /* labels are orange; lime is for things you tap */
  margin: 0 0 22px;
  text-shadow: 0 1px 2px rgba(9,4,22,.95), 0 1px 10px rgba(9,4,22,.85);
}

h1{
  font-size: clamp(62px, 14.5vw, 168px);
  line-height: .9;
  font-weight: 400;
  letter-spacing: -.028em;
  margin: 0 0 30px;
  text-shadow: 0 2px 4px rgba(9,4,22,.55), 0 6px 40px rgba(9,4,22,.6);
}

h2{
  font-size: clamp(34px, 6vw, 70px);
  line-height: 1.08;
  font-weight: 400;
  letter-spacing: -.018em;
  margin: 0 0 26px;
  text-shadow: 0 1px 3px rgba(9,4,22,.7), 0 4px 28px rgba(9,4,22,.6);
}

p{
  font-size: var(--fs-body);
  line-height: 1.72;
  color: var(--text);
  margin: 0 0 18px;
  text-shadow: 0 1px 2px rgba(9,4,22,.95), 0 1px 10px rgba(9,4,22,.8);
}

.lede{ font-size: clamp(18px, 2vw, 26px); color: var(--ink); }

em{ font-style: normal; font-weight: 400; color: var(--warm); }

.meta{
  font-family: var(--font);
  font-size: var(--fs-ui);
  letter-spacing: .01em;
  color: var(--ink-dim);
}

.links{ display: flex; gap: 26px; margin-top: 8px; }
/* wider screens: sections alternate sides so the art stays visible. A block on
   the right keeps its heading and every line on one left edge — easier to read
   than right-aligned text, and the art still frames it. */
@media (min-width: 721px){
  .sec:nth-child(even){ margin-left: auto; }
  .sec:nth-child(even) .inner{
    display: flex; flex-direction: column; align-items: flex-start;
    width: min(31em, 100%); margin-left: auto; text-align: left;
  }
}

a{
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid rgba(255,124,26,.55);
  padding-bottom: 3px;
  transition: color .25s, border-color .25s;
}
a:hover{ color: var(--warm); border-color: var(--warm); }

.hero{ min-height: 100vh; }

@media (max-width: 720px){
  .sec{ min-height: 110vh; }
  .sec:nth-child(even) .inner{ align-items: flex-start; }
  .sec:nth-child(even){ align-items: flex-start; text-align: left; margin-left: 0; }
  .sec:nth-child(even) .links{ justify-content: flex-start; }
  .lang{ top: 16px; left: 14px; }
}

@media (prefers-reduced-motion: reduce){
  .grain, .hint svg{ animation: none; }
  html{ scroll-behavior: auto; }
}

/* ---------- contact form ---------- */

.contact{
  width: 100%;
  max-width: 46ch;
  margin: 2px 0 26px;
}

.bot-field{ position: absolute; left: -9999px; }

.contact .row{
  display: flex;
  gap: 14px;
}
.contact .row .field{ flex: 1 1 0; min-width: 0; }

.field{
  display: block;
  margin-bottom: 11px;
}
.field > span{
  display: block;
  font-size: var(--fs-ui);
  letter-spacing: .02em;
  color: var(--warm);
  margin-bottom: 7px;
  text-shadow: 0 2px 18px rgba(9,4,22,.95);
}

.contact input,
.contact textarea{
  width: 100%;
  font: inherit;
  font-size: 16px;                 /* 16px keeps iOS from zooming on focus */
  color: var(--ink);
  background: rgba(28,14,58,.72);
  border: 1px solid rgba(160,143,200,.30);
  border-radius: 14px;
  padding: 11px 15px;
  transition: border-color .2s, background .2s, box-shadow .2s;
  -webkit-appearance: none;
  appearance: none;
}
.contact textarea{
  resize: vertical;
  min-height: 88px;
  line-height: 1.6;
}
.contact input::placeholder,
.contact textarea::placeholder{ color: rgba(160,143,200,.55); }

.contact input:focus,
.contact textarea:focus{
  outline: none;
  border-color: var(--accent);
  background: rgba(34,18,70,.85);
  box-shadow: 0 0 0 3px rgba(143,214,47,.18);
}

.contact button{
  font: inherit;
  font-size: 16px;
  color: #15240a;
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  padding: 12px 30px;
  cursor: pointer;
  transition: transform .15s, background .2s, box-shadow .2s;
  box-shadow: 0 6px 24px rgba(143,214,47,.22);
}
.contact button:hover{
  background: #a3e64a;
}
.contact button:active{ transform: translateY(1px); }
.contact button:disabled{ opacity: .55; cursor: default; }

.form-status{
  font-size: var(--fs-ui);
  margin: 12px 0 0;
  min-height: 1.2em;
  color: var(--ink-dim);
}
.form-status.is-good{ color: var(--accent); }
.form-status.is-bad{ color: #ff8f8f; }

.links{ flex-wrap: wrap; row-gap: 12px; margin-bottom: 30px; }

@media (max-width: 560px){
  .contact .row{ flex-direction: column; gap: 0; }
}

/* The contact block is the tallest on the page. Keep the final section to one
   screen so scrolling to the bottom shows all of it, and tighten the form on
   short viewports. */
.sec:last-child{
  min-height: 100vh;
  padding-top: 10vh;
  padding-bottom: 10vh;
}

@media (max-height: 800px){
  .contact textarea{ min-height: 72px; }
  .contact{ margin-bottom: 18px; }
  .links{ margin-bottom: 22px; }
  .sec:last-child{ padding-top: 7vh; padding-bottom: 7vh; }
}

/* ---------- wedding content ---------- */

.amp{
  color: var(--warm);
  font-size: .62em;
  vertical-align: .08em;
  margin: 0 .06em;
}

/* placeholders still to fill in: a dashed underline (orange is for labels) */
.todo{ color: var(--ink-dim); border-bottom: 1px dashed currentColor; }

/* the lists — the day's facts (when / where / dress…) and the weekend's days —
   share one layout: an orange label, the words beside it at reading size, and
   a hairline between rows. On phones the label sits above its words. */
.facts, .schedule{
  margin: 26px 0 24px;
  padding: 0;
  list-style: none;
  font-size: var(--fs-body);      /* so their width matches the paragraphs */
  max-width: 46ch;
}
.facts > div, .schedule li{
  display: flex;
  align-items: baseline;
  gap: 20px;
  padding: 14px 0;
  border-top: 1px solid rgba(160,143,200,.22);
}
.facts > div:last-child, .schedule li:last-child{ border-bottom: 1px solid rgba(160,143,200,.22); }
.facts dt, .schedule .time{
  flex: 0 0 7em;                  /* room for the longer labels, e.g. "Places to stay" */
  font-size: var(--fs-ui);
  color: var(--warm);
}
.facts dd, .schedule .what{
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text);
}
.schedule .what em{ color: var(--ink); }   /* each day's name, a touch brighter */

/* collapsible groups (Getting there): a row per group, with the same hairlines
   as the lists; tap to open its own little list underneath */
.accordion{ margin: 26px 0 24px; font-size: var(--fs-body); max-width: 46ch; }
.acc{ border-top: 1px solid rgba(160,143,200,.22); }
.acc:last-child{ border-bottom: 1px solid rgba(160,143,200,.22); }
.acc > summary{
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 0;
  list-style: none;
  cursor: pointer;
  font-size: var(--fs-body);
  color: var(--ink);
  text-shadow: 0 1px 2px rgba(9,4,22,.95), 0 1px 10px rgba(9,4,22,.8);
}
.acc > summary::-webkit-details-marker{ display: none; }
/* the open/close mark: a plus in a small circle that turns into a cross */
.acc > summary::after{
  content: "+";
  flex: none;
  display: grid; place-items: center;
  width: 30px; height: 30px;
  border: 1px solid rgba(160,143,200,.4);
  border-radius: 50%;
  background: rgba(28,14,58,.62);
  font-size: 20px; line-height: 1;
  color: var(--ink);
  -webkit-text-stroke: 0;
  transition: transform .42s cubic-bezier(.22,.61,.36,1), border-color .2s;
}
.acc > summary:hover::after, .acc > summary:focus-visible::after{ border-color: var(--accent); }
.acc > summary:focus-visible{ outline: none; }
.acc[open] > summary::after{ transform: rotate(45deg); }
.acc.is-closing > summary::after{ transform: none; }   /* turns back as soon as it starts closing (layout.js) */
/* inside a group: the list sits flush, without its own outer lines */
.acc .facts{ margin: 0 0 14px; }
.acc .facts > div:first-child{ border-top: 0; padding-top: 2px; }
.acc .facts > div:last-child{ border-bottom: 0; }
.acc > p{ margin: 0 0 18px; }

/* the RSVP select needs to match the text inputs */
.contact select{
  width: 100%;
  font: inherit;
  font-size: 16px;
  color: var(--ink);
  background: rgba(28,14,58,.72);
  border: 1px solid rgba(160,143,200,.30);
  border-radius: 14px;
  padding: 11px 15px;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  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='%23a08fc8' stroke-width='1.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 15px center;
  padding-right: 38px;
  transition: border-color .2s, background-color .2s, box-shadow .2s;
}
.contact select:focus{
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(143,214,47,.18);
}
.contact select option{ background: #1c0e3a; color: var(--ink); }


@media (max-width: 560px){
  .facts > div, .schedule li{ flex-direction: column; gap: 4px; }
  .facts dt, .schedule .time{ flex: none; }
}


/* ---------- opening photograph ---------- */

.hint{ text-shadow: 0 1px 10px rgba(9,4,22,.9); }

/* ---------- RSVP card ---------- */

.rsvp-open{
  font: inherit;
  font-size: 18px;
  color: #15240a;
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  padding: 14px 40px;
  margin: 10px 0 34px;
  cursor: pointer;
  box-shadow: 0 8px 30px rgba(143,214,47,.25);
  transition: transform .15s, background .2s, box-shadow .2s;
}
.rsvp-open:hover{ background: #a3e64a; box-shadow: 0 10px 36px rgba(143,214,47,.35); }
.rsvp-open:active{ transform: translateY(1px); }

.rsvp-card{
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100dvh - 40px);
  padding: 0;
  border: 1px solid rgba(160,143,200,.26);
  border-radius: 26px;
  background: rgba(19,9,42,.95);
  color: var(--ink);
  box-shadow: 0 30px 90px rgba(0,0,0,.6);
  overflow: auto;
  overscroll-behavior: contain;
}
.rsvp-card::backdrop{
  background: rgba(9,4,22,.58);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.rsvp-card[open]{ animation: card-in .38s cubic-bezier(.2,.8,.2,1); }
@keyframes card-in{
  from{ opacity: 0; transform: translateY(22px) scale(.98); }
}

.rsvp-body{
  position: relative;
  padding: 34px clamp(22px, 5vw, 40px) 26px;
}
.rsvp-body h2{
  font-size: clamp(30px, 6vw, 42px);
  margin-bottom: 22px;
  text-shadow: none;
}
.rsvp-body .kicker{ margin-bottom: 12px; text-shadow: none; }
.rsvp-body .contact{ max-width: none; margin-bottom: 0; }
.rsvp-body .field > span{ text-shadow: none; }

.rsvp-close{
  position: absolute;
  top: 16px; right: 16px;
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(160,143,200,.28);
  background: rgba(40,22,80,.6);
  color: var(--ink);
  font: inherit;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  transition: background .2s, border-color .2s;
}
.rsvp-close:hover{ background: rgba(60,34,110,.8); border-color: var(--accent); }

/* keep the page still behind the card */
html:has(.rsvp-card[open]){ overflow: hidden; }

@media (prefers-reduced-motion: reduce){
  .rsvp-card[open]{ animation: none; }
}

/* ---------- music ---------- */

.music{
  position: fixed;
  top: 18px; right: 20px;
  /* the list drops down beneath, so this is its anchor */
  z-index: 6;
  display: flex; align-items: center; gap: 8px;
}

.music-play, .music-list{
  display: grid; place-items: center;
  color: var(--ink);
  background: rgba(28,14,58,.62);
  border: 1px solid rgba(160,143,200,.28);
  border-radius: 50%;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background .2s, border-color .2s;
}
.music-play{ width: 40px; height: 40px; color: var(--accent); }
.music-list{ width: 32px; height: 32px; }
.music-play:hover, .music-list:hover,
.music.menu-open .music-list{ background: rgba(40,22,80,.8); border-color: var(--accent); }

.music-play .i-pause{ display: none; }
.music.is-playing .music-play .i-play{ display: none; }
.music.is-playing .music-play .i-pause{ display: block; }
.music.is-playing .music-play{ box-shadow: 0 0 0 0 rgba(143,214,47,.45); animation: beat 1.7s ease-out infinite; }
@keyframes beat{ 0%{ box-shadow: 0 0 0 0 rgba(143,214,47,.45); } 100%{ box-shadow: 0 0 0 12px rgba(143,214,47,0); } }

/* the list of songs */
.music-menu{
  position: absolute;
  top: calc(100% + 10px); right: 0;
  margin: 0; padding: 6px;
  list-style: none;
  width: min(340px, calc(100vw - 24px));
  background: rgba(19,9,42,.96);
  border: 1px solid rgba(160,143,200,.26);
  border-radius: 18px;
  box-shadow: 0 18px 50px rgba(0,0,0,.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  animation: menu-in .2s ease-out;
}
.music-menu[hidden]{ display: none; }
@keyframes menu-in{ from{ opacity: 0; transform: translateY(-6px); } }
.music-menu li{ display: flex; align-items: center; gap: 4px; }
.music-menu .m-pick{
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px;
  border: 0; border-radius: 12px;
  background: transparent;
  color: var(--ink);
  font: inherit; text-align: left;
  cursor: pointer;
}
.music-menu .m-pick:hover, .music-menu .m-pick:focus-visible{ background: rgba(60,34,110,.55); outline: none; }
/* credit for where each song streams from */
.music-menu .m-src{
  flex: none;
  font-size: 11px;
  color: var(--ink-dim);
  border: 0;
  padding: 6px 8px;
  border-radius: 8px;
}
.music-menu .m-src::after{ content: " \2197"; }
.music-menu .m-src:hover, .music-menu .m-src:focus-visible{ color: var(--accent); background: rgba(60,34,110,.55); outline: none; }
.music-menu .m-text{ display: flex; flex-direction: column; min-width: 0; }
.music-menu .m-title{ font-size: 15px; }
.music-menu .m-artist{ font-size: 12px; color: var(--ink-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-menu .is-current .m-title{ color: var(--accent); }

/* a little equaliser beside the song that's playing */
.music-menu .m-eq{ flex: none; display: flex; gap: 2px; align-items: flex-end; width: 13px; height: 13px; opacity: .25; }
.music-menu .m-eq i{ display: block; width: 3px; height: 40%; background: var(--accent); border-radius: 1px; }
.music-menu .is-current .m-eq{ opacity: 1; }
.music-menu .is-playing .m-eq i{ animation: eq .9s ease-in-out infinite; height: 100%; transform-origin: bottom; }
.music-menu .is-playing .m-eq i:nth-child(2){ animation-delay: -.3s; }
.music-menu .is-playing .m-eq i:nth-child(3){ animation-delay: -.6s; }
@keyframes eq{ 0%,100%{ transform: scaleY(.3); } 50%{ transform: scaleY(1); } }

/* the song name: on hover, on keyboard focus, and for a moment when a song starts */
.music-tip{
  order: -1;
  max-width: min(60vw, 340px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-size: 13px;
  color: var(--ink);
  background: rgba(28,14,58,.72);
  border: 1px solid rgba(160,143,200,.22);
  border-radius: 999px;
  padding: 6px 12px;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  transform: translateX(6px);
  pointer-events: none;
  transition: opacity .25s, transform .25s;
}
.music:hover .music-tip,
.music:focus-within .music-tip,
.music.show-tip .music-tip{ opacity: 1; transform: none; }
.music.menu-open .music-tip{ opacity: 0; }

/* The real player only shows when it's needed: SoundCloud asks for a tap on its
   own play button to start Bound 2, and Spotify's appears if a browser won't
   start a song from ours. It tucks away again as soon as the music is going. */
.music-card{
  position: fixed;
  top: 68px; right: 20px;
  z-index: 6;
  width: min(330px, calc(100vw - 32px));
  border-radius: 16px;
  overflow: hidden;
  background: rgba(19,9,42,.96);
  border: 1px solid rgba(160,143,200,.26);
  box-shadow: 0 18px 50px rgba(0,0,0,.5);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity .25s ease, transform .25s ease;
}
.music-card.is-open{ opacity: 1; transform: none; pointer-events: auto; }

.music-card-bar{
  display: flex; align-items: center; gap: 8px;
  padding: 8px 8px 6px 14px;
}
.music-card-hint{ flex: 1; font-size: 13px; color: var(--accent); }
.music-card-close{
  flex: none;
  width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid rgba(160,143,200,.28);
  background: rgba(40,22,80,.6); color: var(--ink);
  font: inherit; font-size: 15px; line-height: 1; cursor: pointer;
}
.music-card-close:hover{ border-color: var(--accent); }

.music-card iframe{ display: block; border: 0; width: 100%; }
.music-card .player-soundcloud{ margin: 0 10px 10px 8px; }
.music-card .player-soundcloud iframe{ height: 20px; }
/* only the player for the current song shows */
.music-card .player-slot{ display: none; }
.music-card[data-player="spotify"]    .player-spotify,
.music-card[data-player="soundcloud"] .player-soundcloud{ display: block; }

@media (max-width: 720px){
  .music{ top: 12px; right: 12px; }
  .music-card{ top: 62px; right: 16px; }
}
@media (prefers-reduced-motion: reduce){
  .music.is-playing .music-play{ animation: none; }
  .music-menu .is-playing .m-eq i{ animation: none; }
}

/* ---------- the first screen ---------- */
/* everything centred and low, under the faces in the photo */
.hero{
  justify-content: flex-end;
  align-items: center;
  text-align: center;
  max-width: none;
  padding-bottom: 12vh;
}
.hero .inner{ display: flex; flex-direction: column; align-items: center; }
.hero .inner > *{ max-width: none; }

/* phones: the names on one line, under the faces */
.hero h1{
  font-weight: 400;
  text-transform: uppercase;
  white-space: nowrap;
  font-size: min(112px, 9.4vw);
  letter-spacing: .05em;
  line-height: 1.02;
  margin: 0 0 20px;
}
.hero h1 .amp{ font-size: .55em; vertical-align: .18em; margin: 0 .12em; }

.hero-date{
  text-transform: uppercase;
  font-size: clamp(22px, 2.6vw, 34px);
  letter-spacing: .07em;
  color: var(--ink);
  margin: 0 0 6px;
}
.hero-place{
  font-size: var(--fs-ui);
  color: var(--text);
  margin: 0 0 18px;
}

.countdown{
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 4px 16px;
  font-size: var(--fs-ui);
  color: var(--ink-dim);
  margin: 0 0 26px;
  min-height: 1.6em;
}
.countdown .cd-n{
  display: inline-block;
  min-width: 1.4em;                 /* so the numbers don't jostle each second */
  text-align: right;
  color: var(--ink);
}

.hero .rsvp-open{ margin: 0; }

/* wide screens: the whole group centred in the dark space left of the photo
   (art.js measures that space and sets --dark-w) */
@media (min-aspect-ratio: 1/1){
  .hero{ align-items: flex-start; justify-content: center; padding: 10vh 0; }
  .hero .inner{ width: var(--dark-w, 52vw); }
  /* stacked, so they're not cramped: LONIS / & / ANDREA */
  .hero h1{ white-space: normal; font-size: min(104px, 7.4vw); margin-bottom: 24px; }
  .hero h1 .n{ display: block; }
  .hero h1 .amp{ display: block; font-size: .5em; line-height: 1; margin: .12em 0 .16em; vertical-align: 0; }
}

/* ---------- letters ----------
   Plain white letters, no outline: the calm dot card behind each block of
   text (art.js, "room for the words") plus the soft shadows keep them
   readable. Only the names on the opening screen keep a thin dark outline
   drawn behind the letters, since they sit over the photo. */
@supports (paint-order: stroke fill){
  .hero h1{ paint-order: stroke fill; -webkit-text-stroke: .07em rgba(13,6,32,.8); }
}

/* ---------- keeping the words off the sun (wide screens) ----------
   art.js sets --dodge to slide a section's words up or down, just clear of the
   sun, without changing which side the section is on. */
.inner{ transform: translateY(var(--dodge, 0px)); }
}

/* ---------- the story: full, TL;DR, still too long, one-liner ---------- */
.story{ transition: opacity .18s ease; }
.story.is-changing{ opacity: 0; }
.story-short{ font-size: clamp(20px, 2.1vw, 26px); line-height: 1.5; color: var(--ink); }
.story-emoji{ font-size: clamp(30px, 4vw, 46px); line-height: 1.4; letter-spacing: .02em; color: var(--ink); }
/* emoji keep their own colours: no letter outline drawn around them */
.emoji{ -webkit-text-stroke: 0; text-shadow: none; }

/* a heading with a small button on its right (the story's TL;DR, the day's map).
   The button sits on the heading's line, centred on it, and inside the soft dot
   card (art.js counts it in). On wider screens every section's column is wide
   enough for heading + button; the paragraphs keep their own reading width. */
.inner > .head-row{ max-width: none; }
.head-row{ display: flex; align-items: center; gap: 10px 20px; margin: 0 0 24px; }
/* if a narrow phone has no room, the heading folds onto two even lines and the button stays beside it */
.head-row h2{ margin: 0; flex: 0 1 auto; min-width: 0; text-wrap: balance; }
.head-row > :not(h2){ flex: none; }
/* very big text: the button goes underneath rather than over the heading (layout.js) */
.head-row.is-stacked{ flex-wrap: wrap; }
/* a pause of pure landscape between one block of words and the next */
.sec:not(.hero):not(:last-child){ padding-top: 30vh; padding-bottom: 30vh; }
/* big text on a phone (layout.js): a longer pause still, since each block of
   words fills most of the screen */
.big-text .sec:not(.hero){ padding-top: 72vh; padding-bottom: 72vh; }
.big-text .sec:last-child{ padding-bottom: 30vh; }   /* but don't end on a long empty scroll */
@media (min-width: 721px){
  .sec:nth-child(even) .inner{ width: min(42em, 100%); }
  .story-next, .pill{ padding: 11px 24px; }                     /* a touch roomier beside the big headings */
}
/* a fact with a second line (the date, then the time) */
.facts dd .line{ display: block; }
/* a smaller note under a fact (the time under the date, the shoes advice under Summer formal) */
.facts dd .note{ font-size: var(--fs-ui); line-height: 1.55; margin-top: 4px; }
/* a fact in two parts (From Copenhagen / From Stockholm): a little space between, each led by its place */
.facts dd .gap{ margin-top: 10px; }
.facts dd .lead{ color: var(--ink); }

/* add to calendar (beside The Weekend): the same pill, opening a small list of calendars */
.cal{ position: relative; -webkit-text-stroke: 0; text-shadow: none; }
.cal > summary{ list-style: none; }
.cal > summary::-webkit-details-marker{ display: none; }
.cal[open] > summary{ background: rgba(40,22,80,.8); border-color: var(--accent); }
.cal-menu{
  position: absolute; z-index: 5;
  top: calc(100% + 8px); right: 0;              /* opens leftwards, so it never runs off a phone screen */
  display: flex; flex-direction: column;
  min-width: 210px; padding: 6px;
  background: rgba(19,9,42,.96);
  border: 1px solid rgba(160,143,200,.26);
  border-radius: 18px;
  box-shadow: 0 18px 50px rgba(0,0,0,.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  animation: menu-in .2s ease-out;
}
.cal-menu a{ display: block; padding: 10px 14px; border: 0; border-radius: 12px; font-size: var(--fs-ui); color: var(--ink); }
.cal-menu a:hover, .cal-menu a:focus-visible{ background: rgba(60,34,110,.55); color: var(--ink); outline: none; }
.story-next, .pill{
  display: inline-block;
  font: inherit; font-size: var(--fs-ui); line-height: 1.2;
  text-decoration: none;
  color: var(--ink);
  background: rgba(28,14,58,.62);
  border: 1px solid rgba(160,143,200,.4);
  border-radius: 999px;
  padding: 9px 20px;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background .2s, border-color .2s;
}
.story-next:hover, .pill:hover{ background: rgba(40,22,80,.8); border-color: var(--accent); color: var(--ink); }
/* the paragraphs keep the same reading width they had before the versions were added */
.inner > .story{ max-width: none; }
.story p{ max-width: 46ch; }
/* the story handles its own scroll position when it changes length */
html{ overflow-anchor: none; }
/* phones: a more compact button, so TL;DR fits beside the heading */
@media (max-width: 480px){
  .head-row{ gap: 10px 12px; }
  .story-next, .pill{ padding: 7px 13px; }
}

/* the #check badge (layout.js): only appears when the link ends in #check */
.check-badge{
  position: fixed; z-index: 50;
  left: max(10px, env(safe-area-inset-left, 0px)); bottom: max(10px, env(safe-area-inset-bottom, 0px));
  padding: 8px 12px; border-radius: 12px;
  background: rgba(19,9,42,.92); border: 1px solid rgba(160,143,200,.35);
  font: 13px/1.4 var(--font); color: #f6f1ff;
  pointer-events: none;
}

/* ---------- the two of us, dancing (dance.js) ----------
   An easter egg: hidden until the moon turns into the disco ball (tap the moon,
   or hover RSVP with a mouse), then the two of us fade in, dancing underneath
   it, and fade out again when the party stops. Phones: just above "Are you in?". Wide screens: in the open space to the left of the RSVP words. */
.dance{
  display: block;
  width: min(78vw, 360px);
  aspect-ratio: 72 / 112;
  margin: 0 auto 3vh;
  opacity: 0;
  transform: scale(.96);
  transition: opacity .7s ease, transform .7s ease;
}
body.disco .dance{ opacity: 1; transform: none; }
@media (min-width: 1280px){
  .sec:last-child .dance{
    position: absolute;
    top: 50%;
    right: calc(clamp(24px, 9vw, 160px) + min(42em, 100%) + 5vw);
    width: clamp(320px, 28vw, 440px);
    margin: 0;
    transform: translateY(-50%) scale(.96);
  }
  body.disco .sec:last-child .dance{ transform: translateY(-50%); }
}
@media (prefers-reduced-motion: reduce){ .dance{ transition: none; } }

/* ---------- where to stay (Getting there → Places to stay) ----------
   Small orange group labels, then each place: its name is the link (with a
   small arrow, no web address shown), a short description, and the price in
   the small, softer size. */
.stays{ margin: 0 0 18px; }
.stays > p{ margin: 0 0 6px; }
.stays .stay-group{
  margin: 26px 0 4px;
  font-size: 13px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--warm);
}
.stay{ padding: 12px 0 14px; border-top: 1px solid rgba(160,143,200,.22); }
.stay p{ margin: 0; }
.stay-name{ font-size: var(--fs-body); line-height: 1.4; }
.stay-name a, .stay-more a{ color: var(--ink); border-bottom: 0; padding-bottom: 0; }
.stay-name a::after, .stay-more a::after{ content: " \2197"; color: var(--ink-dim); font-size: .8em; }
.stay-name a:hover, .stay-more a:hover{ color: var(--accent); }
.stay-text{ margin-top: 4px; font-size: var(--fs-body); line-height: 1.6; color: var(--text); }
.stay-price{ margin-top: 6px; font-size: var(--fs-ui); line-height: 1.5; color: var(--ink-dim); }
.stays .stay-more{ margin: 18px 0 0; font-size: var(--fs-body); }

/* ---------- the "click me" nudge on the story's TL;DR button (story.js) ----------
   A hand-drawn lime arrow curving down to the button with a little note, drawn
   in like a pen stroke when the story comes into view, then bobbing gently.
   It fades away once the button has been tapped. */
.nudge-wrap{ position: relative; display: inline-block; flex: none; }
.nudge{
  position: absolute;
  left: 58%; bottom: calc(100% - 6px);
  display: flex; align-items: flex-start;
  pointer-events: none;
  color: var(--accent);
  transition: opacity .5s ease;
}
.nudge svg{ display: block; order: 1; overflow: visible; }
.nudge-text{
  order: 2;
  margin: -6px 0 0 2px;
  font-size: 13px; letter-spacing: .02em; white-space: nowrap;
  transform: rotate(-7deg);
  text-shadow: 0 1px 10px rgba(9,4,22,.9);
}
/* not enough room on the right (narrow phones): the note sits on the left instead */
.nudge.is-flipped{ left: auto; right: 58%; flex-direction: row-reverse; }
.nudge.is-flipped svg{ transform: scaleX(-1); }
.nudge.is-flipped .nudge-text{ margin: -6px 2px 0 0; transform: rotate(7deg); }
.nudge-tap{ display: none; }
@media (hover: none){ .nudge-click{ display: none; } .nudge-tap{ display: inline; } }
.nudge path{ fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.nudge-line{ stroke-dasharray: 60; stroke-dashoffset: 60; }
.nudge-head{ stroke-dasharray: 26; stroke-dashoffset: 26; }
.nudge-text{ opacity: 0; transition: opacity .5s ease .7s; }
.nudge.is-drawn .nudge-line{ animation: nudge-draw .7s ease-out forwards; }
.nudge.is-drawn .nudge-head{ animation: nudge-draw .25s ease-out .62s forwards; }
.nudge.is-drawn .nudge-text{ opacity: 1; }
.nudge.is-drawn{ animation: nudge-bob 2.4s ease-in-out 1.2s infinite; }
.nudge.is-done{ opacity: 0; }
@keyframes nudge-draw{ to{ stroke-dashoffset: 0; } }
@keyframes nudge-bob{ 0%, 100%{ transform: translateY(0); } 50%{ transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce){
  .nudge-line, .nudge-head{ stroke-dashoffset: 0; animation: none !important; }
  .nudge-text{ opacity: 1; transition: none; }
  .nudge.is-drawn{ animation: none; }
}

/* ---------- live head count above the RSVP button (form.js) ---------- */
.headcount{ display: flex; align-items: center; gap: 10px; margin: -4px 0 22px; }
.headcount[hidden]{ display: none; }
.hc-dot{
  flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 rgba(143,214,47,.55);
  animation: hc-pulse 2.2s ease-out infinite;
}
.hc-n{ color: var(--warm); }
@keyframes hc-pulse{
  0%  { box-shadow: 0 0 0 0 rgba(143,214,47,.55); }
  70% { box-shadow: 0 0 0 9px rgba(143,214,47,0); }
  100%{ box-shadow: 0 0 0 0 rgba(143,214,47,0); }
}
@media (prefers-reduced-motion: reduce){ .hc-dot{ animation: none; } }

/* ---------- after sending an RSVP (form.js) ----------
   The card swaps the form for a little party (yes: the two of us dancing,
   while the moon turns into the disco ball behind) or a soft landing (no). */
.rsvp-card.is-done .rsvp-body > .kicker,
.rsvp-card.is-done #rsvp-title,
.rsvp-card.is-done form.contact{ display: none; }
.rsvp-done{ text-align: center; padding: 6px 0 4px; animation: card-in .5s cubic-bezier(.2,.8,.2,1); }
.rsvp-done[hidden]{ display: none; }
.dance-yes, .sad{ display: block; width: min(52vw, 210px); aspect-ratio: 72 / 112; margin: 0 auto 6px; }
.sad{ aspect-ratio: 60 / 107; }
.rsvp-done .done-title{ margin: 0 0 10px; }
.rsvp-done .done-text{ margin: 0 auto; max-width: 30ch; color: var(--text); text-shadow: none; }
.rsvp-done .done-note{ margin: 10px auto 0; max-width: 34ch; text-wrap: balance; font-size: var(--fs-ui); line-height: 1.55; color: var(--text); text-shadow: none; }
.rsvp-done .done-img{ display: block; width: min(60vw, 260px); height: auto; margin: 0 auto 18px; border-radius: 18px; }
@media (prefers-reduced-motion: reduce){ .rsvp-done{ animation: none; } }
