/* Victor & Rihab — 24.10.2026
   One screen at a time: a tap moves to the next page. Palette and geometry come
   from the invitation itself — sage paper, gold rules, wax gold, and the
   eight-point khatim rosette embossed on the card. */

:root {
  --night: #0a0b09;
  --gold: #c39b5d;
  --gold-bright: #e6cd97;
  --cream: #f4efe3;
  --ink: #262c22;
  --ink-soft: #5d6455;
  --ink-hint: #2b3226;

  --serif: "Cormorant Garamond", "Iowan Old Style", Palatino, Georgia, serif;
  --script: "Allura", "Snell Roundhand", cursive;
  --sans: "Jost", "Avenir Next", "Helvetica Neue", Arial, sans-serif;

  /* the seal, measured on the film's first frame (see prepare_site_media.py) */
  --seal-x: 37.2222%;
  --seal-y: 42.9688%;
  --seal-w: 24.4444%;
  --seal-h: 13.75%;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* dissolves and long moves want an even curve, not a front-loaded one */
  --fade: cubic-bezier(0.4, 0, 0.5, 1);
  --glide: cubic-bezier(0.45, 0, 0.55, 1);
  /* a camera push: away at once, then easing off as it dissolves */
  --push: cubic-bezier(0.2, 0.55, 0.3, 1);
}

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

html,
body {
  height: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  background: var(--night);
  color: var(--cream);
  font-family: var(--serif);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* ————————————————————————— the deck ————————————————————————— */

.deck {
  position: fixed;
  inset: 0;
  overflow: hidden;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

.slide {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: max(1.4rem, env(safe-area-inset-top)) clamp(1.2rem, 5vw, 3.2rem)
    max(3.4rem, calc(env(safe-area-inset-bottom) + 3rem));
  opacity: 0;
  pointer-events: none;
  /* every turn is one move forward: a page waits a whisper behind, grows into
     place, and later drifts on past the viewer as it dissolves */
  transform: scale(0.962);
  /* the page holds a beat before dissolving, so one image gives way to the next
     instead of both washing out together */
  transition:
    opacity 1.1s var(--fade) 0.3s,
    transform 2.2s var(--glide);
}

.slide.is-current {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}

.slide.is-back {
  transform: scale(1.045);
}

/* the film doesn't step aside when it ends, it keeps coming: the frame pushes in
   on the card and dissolves, and the paper grows up through it. the push is
   front-loaded so most of it happens while the film can still be seen */
.slide--film {
  transition:
    opacity 1.5s var(--fade) 0.34s,
    transform 2s var(--push);
}

.slide--film.is-back {
  transform: scale(1.17);
}

/* backdrops drift very slowly, the way a held shot breathes */
.bg {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  transform: scale(1.05);
}

.slide.is-current .bg {
  animation: drift 22s ease-out both;
}

@keyframes drift {
  from {
    transform: scale(1.05);
  }
  to {
    transform: scale(1.15) translate(-0.8%, -0.5%);
  }
}

.bg::after {
  content: "";
  position: absolute;
  inset: 0;
}

.slide--sage .bg::after {
  background: linear-gradient(180deg, rgba(28, 35, 25, 0.4), rgba(24, 31, 22, 0.5));
}

.slide--arch .bg::after {
  background:
    linear-gradient(180deg, rgba(22, 16, 8, 0.5), rgba(18, 13, 7, 0.58)),
    radial-gradient(78% 62% at 50% 45%, rgba(0, 0, 0, 0), rgba(12, 9, 4, 0.5));
}

.slide--arch .in {
  text-shadow: 0 1px 26px rgba(0, 0, 0, 0.5);
}

.slide--paper {
  color: var(--ink);
}

/* a gold hairline frame, drawn rather than photographed so it stays square */
.slide--paper::after,
.slide--sage::after,
.slide--arch::after {
  content: "";
  position: absolute;
  inset: clamp(0.7rem, 2.2vmin, 1.5rem);
  border: 1px solid rgba(195, 155, 93, 0.34);
  pointer-events: none;
}

.slide--paper::after {
  border-color: rgba(195, 155, 93, 0.42);
}

/* ——— content, arriving a beat after the fade ——— */

.in {
  position: relative;
  width: min(100%, 34rem);
  text-align: center;
  max-height: 100%;
  overflow: hidden auto;
  scrollbar-width: none;
}

.in::-webkit-scrollbar {
  display: none;
}

.in--wide {
  width: min(100%, 62rem);
}

.in > * {
  opacity: 0;
  transform: translateY(15px);
  transition:
    opacity 0.95s var(--ease),
    transform 0.95s var(--ease);
}

.is-current .in > * {
  opacity: 1;
  transform: none;
}

.is-current .in > :nth-child(1) {
  transition-delay: 0.46s;
}
.is-current .in > :nth-child(2) {
  transition-delay: 0.58s;
}
.is-current .in > :nth-child(3) {
  transition-delay: 0.7s;
}
.is-current .in > :nth-child(4) {
  transition-delay: 0.82s;
}
.is-current .in > :nth-child(5) {
  transition-delay: 0.94s;
}

/* ————————————————————————— the film ————————————————————————— */

.slide--film {
  padding: 0;
  background: #070806;
}

/* while the seal is unbroken the only thing to click is the wax itself */
body[data-state="sealed"] .slide--film,
body[data-state="revealed"] .slide--film,
body[data-state="playing"] .slide--film {
  cursor: default;
}

/* On a wide screen the portrait film sits in a soft wash of its own colours.
   Narrower than the film's own 9:16 there is no room left to see it: the frame
   covers the glass, and a blur this broad would be painted, and dragged through
   the whole pull-away, purely to hide behind an opaque picture. That is the
   costliest thing on the page at the very moment the invitation arrives and its
   monogram draws itself, so below that width it is not painted at all. */
@media (min-aspect-ratio: 9 / 16) {
  .slide--film::before {
    content: "";
    position: absolute;
    inset: -10%;
    background:
      radial-gradient(70% 55% at 50% 50%, rgba(0, 0, 0, 0), rgba(6, 7, 5, 0.72)),
      url("media/poster.jpg") center / cover;
    filter: blur(90px) brightness(0.44) saturate(0.7);
  }
}

.slide--film::after {
  display: none;
}

.film-box {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  height: 100vh;
  height: 100dvh;
  aspect-ratio: 9 / 16;
}

/* the still opens pushed in on the wax and stays there while the seal flares;
   only once it is burning does the camera pull back to the whole envelope, in
   time for the flap to open */
.film-zoom {
  position: absolute;
  inset: 0;
  transform-origin: 49.6% 49.9%;
  transform: scale(1.3);
  transition: transform 1.4s var(--ease);
}

body:not([data-state="sealed"]) .film-zoom {
  transform: scale(1);
  transition-delay: 1.05s;
}

.film {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the still sits under the film: a phone that is slow to decode the first
     frame shows the sealed envelope rather than a black rectangle */
  background: #0f100c url("media/poster.jpg") center / cover;
  /* the pull-back scales the box the film sits in, and a phone redrawing the
     film inside a moving box can drop it to black; its own layer holds it */
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.scratch {
  position: absolute;
  left: var(--seal-x);
  top: var(--seal-y);
  width: var(--seal-w);
  height: var(--seal-h);
  cursor: crosshair;
  touch-action: none;
  /* the last crumbs of wax clear quickly so they are not still there when the
     seal underneath lights up */
  transition: opacity 0.5s var(--ease);
}

.scratch:focus-visible {
  outline: 1px solid var(--gold-bright);
  outline-offset: 6px;
}

body:not([data-state="sealed"]) .scratch {
  opacity: 0;
  pointer-events: none;
}

.halo {
  position: absolute;
  left: var(--seal-x);
  top: var(--seal-y);
  width: var(--seal-w);
  height: var(--seal-h);
  border: 1px solid rgba(255, 250, 235, 0.6);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: halo 3.6s ease-in-out 1.4s infinite;
  transform: scale(0.72);
}

body:not([data-state="sealed"]) .halo {
  animation: none;
  opacity: 0;
}

@keyframes halo {
  0% {
    opacity: 0;
    transform: scale(0.68);
  }
  30% {
    opacity: 0.55;
  }
  75%,
  100% {
    opacity: 0;
    transform: scale(0.86);
  }
}

.hint {
  position: absolute;
  left: 50%;
  top: 59%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  /* a breath of vellum so the words hold up over leaves or wax alike */
  padding: 0.7rem 1.5rem 0.8rem;
  background: radial-gradient(
    closest-side,
    rgba(247, 243, 233, 0.7),
    rgba(247, 243, 233, 0.42) 62%,
    rgba(247, 243, 233, 0)
  );
  font-family: var(--sans);
  font-size: clamp(0.66rem, 0.6rem + 0.3vw, 0.8rem);
  font-weight: 400;
  letter-spacing: 0.36em;
  text-indent: 0.36em;
  text-transform: uppercase;
  color: var(--ink-hint);
  text-shadow: 0 1px 14px rgba(247, 243, 232, 0.85), 0 0 4px rgba(247, 243, 232, 0.9);
  transition: opacity 0.7s var(--ease);
}

.hint svg {
  width: 1.15rem;
  height: 1.15rem;
  animation: bob 2.4s ease-in-out infinite;
}

@keyframes bob {
  0%,
  100% {
    transform: translateY(3px);
    opacity: 0.55;
  }
  50% {
    transform: translateY(-3px);
    opacity: 1;
  }
}

body:not([data-state="sealed"]) .hint {
  opacity: 0;
}

/* the seal is off but the phone has refused the film: the same words come back,
   now asking for the touch it wants before it will play */
body[data-state="stalled"] .hint {
  opacity: 1;
}

.hint.is-nudged {
  animation: nudge 0.5s ease-in-out 2;
}

@keyframes nudge {
  25% {
    transform: translate(-50%, -4px) scale(1.04);
  }
  75% {
    transform: translate(-50%, 2px) scale(1);
  }
}

/* ————————————————————————— words ————————————————————————— */

/* ——— their monogram ———
   the ring draws itself when the page arrives, the laced initials rise into it,
   and a spark runs round the gold */

.mark {
  position: relative;
  display: block;
  width: clamp(3.4rem, 9vmin, 4.8rem);
  aspect-ratio: 1;
  margin: 0 auto clamp(1rem, 3vh, 1.7rem);
  color: rgba(236, 214, 166, 0.95);
  --bloom: rgba(255, 224, 158, 0.9);
}

.slide--paper .mark {
  color: rgba(172, 133, 70, 0.95);
  /* gold spreading over cream reads as a stain, so on paper the light is white */
  --bloom: rgba(255, 253, 246, 0.95);
}

.mark__seal {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* the names of the keyframes inside the symbol: passing them down starts the
   ring drawing, the initials rising and the spark turning, and each visit plays
   it again */
.is-current .mark__seal {
  --draw: mono-draw;
  --lift: mono-lift;
  --turn: mono-turn;
  --glint: mono-glint;
  animation: breathe 5.5s ease-in-out 2.6s infinite;
}

@keyframes breathe {
  0%,
  100% {
    filter: drop-shadow(0 0 1px currentColor);
  }
  50% {
    filter: drop-shadow(0 0 8px currentColor);
  }
}

/* the seal takes the light once, the moment the ring closes */
.mark__glow {
  position: absolute;
  inset: -36%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--bloom) 0%, transparent 62%);
  opacity: 0;
  pointer-events: none;
}

.is-current .mark__glow {
  animation: bloom 2.3s ease-out 2.3s;
}

@keyframes bloom {
  0% {
    opacity: 0;
    transform: scale(0.5);
  }
  32% {
    opacity: 0.4;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(1.4);
  }
}


.eyebrow {
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(0.62rem, 0.56rem + 0.3vw, 0.76rem);
  font-weight: 300;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  text-transform: uppercase;
  color: rgba(230, 205, 151, 0.85);
}

.slide--paper .eyebrow {
  color: #7d7256;
}


.names {
  margin: clamp(0.6rem, 2vh, 1.2rem) 0 0;
  font-family: var(--script);
  font-size: clamp(3.1rem, 1.6rem + 8vw, 6.2rem);
  font-weight: 400;
  line-height: 1.14;
  color: var(--cream);
}

/* full-strength ink under a hairline script reads stamped rather than written, so
   the names are set a shade warmer and lighter, with the faintest bleed to take
   the edge off the strokes */
.slide--paper .names {
  color: rgba(70, 75, 58, 0.93);
  text-shadow: 0 0 2.5px rgba(70, 75, 58, 0.24);
}

.title {
  margin: 0 0 clamp(1.5rem, 4.4vh, 2.6rem);
  font-size: clamp(1.5rem, 1.1rem + 2vw, 2.4rem);
  font-weight: 300;
  letter-spacing: 0.015em;
  color: var(--cream);
}

.slide--paper .title {
  color: var(--ink);
}

.title--script {
  margin-bottom: clamp(0.9rem, 2.4vh, 1.4rem);
  font-family: var(--script);
  font-size: clamp(2.8rem, 1.6rem + 6vw, 4.6rem);
  line-height: 1.16;
}

.lead {
  margin: clamp(1.1rem, 3vh, 1.8rem) auto 0;
  max-width: 26rem;
  font-size: clamp(1.06rem, 0.98rem + 0.55vw, 1.34rem);
  font-weight: 300;
  font-style: italic;
  line-height: 1.75;
  text-wrap: balance;
  color: rgba(244, 239, 227, 0.92);
}

.slide--paper .lead {
  color: var(--ink-soft);
}

.rule {
  display: block;
  width: clamp(3rem, 12vmin, 5rem);
  height: 1px;
  margin: clamp(1rem, 3vh, 1.6rem) auto;
  background: linear-gradient(90deg, transparent, rgba(230, 205, 151, 0.75), transparent);
}

.line {
  margin: 0.55rem 0 0;
  font-size: clamp(1.02rem, 0.95rem + 0.5vw, 1.24rem);
  font-weight: 400;
  letter-spacing: 0.02em;
}

.line--soft {
  font-family: var(--sans);
  font-size: clamp(0.76rem, 0.7rem + 0.3vw, 0.9rem);
  font-weight: 300;
  letter-spacing: 0.22em;
  text-indent: 0.22em;
  text-transform: uppercase;
  color: rgba(244, 239, 227, 0.72);
  margin-top: 0.9rem;
}

/* ——— the invitation and the couple on one page ——— */

.meet {
  display: flex;
  flex-direction: column;
  gap: clamp(1.3rem, 4vh, 2.4rem);
}

.meet .lead {
  margin-top: clamp(0.9rem, 2.4vh, 1.4rem);
}

/* room enough for two columns: the words beside them, the photographs beside */
@media (min-width: 900px) and (min-aspect-ratio: 1 / 1) {
  .meet {
    display: grid;
    grid-template-columns: 1fr 1.1fr;
    align-items: center;
    gap: clamp(2rem, 5vw, 4rem);
    width: min(100%, 66rem);
    text-align: left;
  }

  .meet .mark {
    margin-left: 0;
  }

  .meet .lead {
    margin-left: 0;
    max-width: 22rem;
  }

  /* their names hold one line here, whatever the window does */
  .meet .names {
    font-size: clamp(2.8rem, 1.4rem + 3.2vw, 4.6rem);
  }

  /* the column already limits them, so the photographs can fill it */
  .meet .trio {
    width: 100%;
  }
}

/* ——— the couple, under Moorish arches ——— */

.trio {
  display: grid;
  grid-template-columns: 1fr 1.14fr 1fr;
  align-items: center;
  gap: clamp(0.7rem, 2.4vw, 1.8rem);
  width: min(100%, 34rem, 78vh);
  margin-inline: auto;
}

.trio figure {
  position: relative;
  margin: 0;
  padding: clamp(0.3rem, 1vmin, 0.55rem);
}

.trio figure::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid rgba(230, 205, 151, 0.5);
  border-radius: 50% 50% 5px 5px / 30% 30% 5px 5px;
}

.shot {
  display: block;
  overflow: hidden;
  border-radius: 50% 50% 4px 4px / 30% 30% 4px 4px;
  box-shadow: 0 26px 50px -30px rgba(0, 0, 0, 0.85);
}

.trio img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: 50% 26%;
  filter: saturate(0.95) contrast(1.02);
}

.trio__lead img {
  aspect-ratio: 3 / 4.3;
}

/* ——— hours ——— */

.hours {
  list-style: none;
  margin: 0;
  padding: 0;
  text-align: left;
}

.hours li {
  display: grid;
  grid-template-columns: clamp(3.4rem, 11vw, 4.6rem) 1fr;
  gap: 0 clamp(0.9rem, 3vw, 1.5rem);
  padding: clamp(0.5rem, 1.5vh, 0.9rem) 0;
  border-top: 1px solid rgba(230, 205, 151, 0.22);
}

.slide--paper .hours li {
  border-top-color: rgba(195, 155, 93, 0.3);
}

.hours li:last-child {
  border-bottom: 1px solid rgba(230, 205, 151, 0.22);
}

.slide--paper .hours li:last-child {
  border-bottom-color: rgba(195, 155, 93, 0.3);
}

.hours__time {
  font-family: var(--sans);
  font-size: clamp(0.76rem, 0.7rem + 0.3vw, 0.9rem);
  font-weight: 400;
  letter-spacing: 0.12em;
  text-align: right;
  padding-top: 0.42em;
  color: rgba(230, 205, 151, 0.9);
}

.slide--paper .hours__time {
  color: #7d7256;
}

.hours__what b {
  display: block;
  font-weight: 400;
  font-size: clamp(1.06rem, 0.98rem + 0.55vw, 1.32rem);
  line-height: 1.35;
}

.hours__what i {
  display: block;
  margin-top: 0.1rem;
  font-family: var(--sans);
  font-size: clamp(0.72rem, 0.68rem + 0.25vw, 0.82rem);
  font-style: normal;
  font-weight: 300;
  letter-spacing: 0.04em;
  color: rgba(244, 239, 227, 0.68);
}

.slide--paper .hours__what i {
  color: var(--ink-soft);
}

.hours--plain li {
  padding: clamp(0.62rem, 1.9vh, 1.05rem) 0;
}

/* staggered arrival, row by row */
.hours li {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 0.8s var(--ease),
    transform 0.8s var(--ease);
}

.is-current .hours li {
  opacity: 1;
  transform: none;
}

.is-current .hours li:nth-child(1) {
  transition-delay: 0.66s;
}
.is-current .hours li:nth-child(2) {
  transition-delay: 0.74s;
}
.is-current .hours li:nth-child(3) {
  transition-delay: 0.82s;
}
.is-current .hours li:nth-child(4) {
  transition-delay: 0.9s;
}
.is-current .hours li:nth-child(5) {
  transition-delay: 0.98s;
}
.is-current .hours li:nth-child(6) {
  transition-delay: 1.06s;
}
.is-current .hours li:nth-child(7) {
  transition-delay: 1.14s;
}

/* ————————————————————————— reply ————————————————————————— */

.act {
  margin: clamp(1.4rem, 4vh, 2.2rem) 0 0;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.9rem 2rem;
  border: 1px solid rgba(195, 155, 93, 0.62);
  background: rgba(195, 155, 93, 0.06);
  color: inherit;
  font-family: var(--sans);
  font-size: clamp(0.66rem, 0.6rem + 0.3vw, 0.78rem);
  font-weight: 400;
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background 0.45s var(--ease),
    border-color 0.45s var(--ease);
}

.btn:hover {
  background: rgba(195, 155, 93, 0.18);
  border-color: var(--gold-bright);
}

.btn:focus-visible {
  outline: 1px solid var(--gold-bright);
  outline-offset: 4px;
}

.rsvp {
  display: grid;
  gap: clamp(0.85rem, 2.4vh, 1.35rem);
  margin-top: clamp(1rem, 3vh, 1.7rem);
  text-align: left;
}

/* le champ piège : sorti du flux plutôt que masqué, pour qu'un robot qui lit le
   HTML le remplisse sans qu'il prenne de place ni de rang dans la grille */
.piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.field__label {
  display: block;
  margin-bottom: 0.3rem;
  font-family: var(--sans);
  font-size: 0.64rem;
  font-weight: 400;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: #7d7256;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.4rem 0.1rem;
  border: 0;
  border-bottom: 1px solid rgba(195, 155, 93, 0.5);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 400;
}

.field textarea {
  resize: none;
  line-height: 1.5;
}

.field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 1.4rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 9l7 7 7-7' fill='none' stroke='%23a58548' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.15rem center;
  background-size: 0.8rem;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--gold);
}

.field--slim select {
  max-width: 8rem;
}

.choice {
  margin: 0;
  padding: 0;
  border: 0;
  display: flex;
  gap: clamp(1rem, 5vw, 2rem);
}

.choice label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.02rem;
  cursor: pointer;
}

.choice input {
  accent-color: var(--gold);
  width: 0.95rem;
  height: 0.95rem;
}

.rsvp .btn {
  justify-self: start;
  margin-top: 0.3rem;
}

.rsvp__note {
  margin: 0;
  font-family: var(--sans);
  font-size: 0.74rem;
  font-weight: 300;
  line-height: 1.6;
  color: var(--ink-soft);
}

.rsvp__note:empty {
  display: none;
}

/* la réponse est partie : les champs cèdent la place au remerciement, et rien
   ne peut plus être envoyé deux fois */
.rsvp.is-sent > :not(.rsvp__note) {
  display: none;
}

.rsvp.is-sent .rsvp__note {
  font-family: var(--serif);
  font-size: clamp(1rem, 0.88rem + 0.7vw, 1.32rem);
  line-height: 1.5;
  letter-spacing: 0.01em;
  text-align: center;
  color: var(--ink-soft);
  animation: arrive 1.2s var(--ease) both;
}

/* le remerciement occupe la place du formulaire : la reprise se tient en
   retrait dessous, discrète mais atteignable */
.rsvp.is-sent > .rsvp__modifier:not([hidden]) {
  display: block;
  justify-self: center;
  margin-top: 0.2rem;
  padding: 0.2rem 0;
  border: 0;
  border-bottom: 1px solid rgba(195, 155, 93, 0.45);
  background: none;
  font-family: var(--sans);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
  animation: arrive 1.2s var(--ease) both;
}

.rsvp.is-sent > .rsvp__modifier:not([hidden]):hover,
.rsvp.is-sent > .rsvp__modifier:not([hidden]):focus-visible {
  color: var(--gold);
  border-bottom-color: var(--gold);
}

@keyframes arrive {
  from {
    opacity: 0;
    transform: translateY(0.6rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ————————————————————————— the quiet chrome ————————————————————————— */

.chrome {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding-bottom: max(0.85rem, env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s var(--ease);
  color: rgba(244, 239, 227, 0.75);
}

body[data-tone="light"] .chrome {
  color: rgba(38, 44, 34, 0.55);
}

body.is-open .chrome {
  opacity: 1;
}

/* the one piece of chrome you can actually press: it turns the page even where
   the page itself holds still, such as under the reply form */
.cue {
  pointer-events: auto;
  padding: 0.4rem 1.2rem;
  cursor: pointer;
}

.cue svg {
  display: block;
  width: 1.35rem;
  height: 1.35rem;
  animation: bob 2.6s ease-in-out infinite;
}

.ticks {
  display: flex;
  gap: 5px;
  transition: opacity 0.6s var(--fade);
}

.ticks span {
  display: block;
  width: clamp(14px, 3.4vw, 22px);
  height: 2px;
  background: currentColor;
  opacity: 0.22;
  transition: opacity 0.6s var(--ease);
}

.ticks span.is-on {
  opacity: 0.95;
}

/* the reply form is an aside, not a page of the story */
body.is-aside .ticks {
  opacity: 0;
}

/* ————————————————————————— narrow screens ————————————————————————— */

@media (max-width: 700px) {
  /* three across a phone would be thumbnails, so the portrait takes the lead */
  .trio {
    grid-template-columns: 1fr 1.55fr 1fr;
    gap: 0.45rem;
  }
}

@media (max-height: 620px) {
  .names {
    font-size: clamp(2.4rem, 1.4rem + 6vw, 4rem);
  }

  .lead {
    font-size: 1rem;
    line-height: 1.6;
  }

  .mark {
    width: 2.6rem;
    margin-bottom: 0.7rem;
  }

  .trio {
    width: min(100%, 26rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.2s !important;
  }

  .in > *,
  .hours li {
    opacity: 1;
    transform: none;
  }

  .mark__seal {
    stroke-dashoffset: 0;
  }
}
