/* ============================================================
   Ronald ♥ Amala — 14 September 2026

   Two pages. The first is the card; the second is where to be.
   Both are a viewport tall and snap, so the invitation is read
   the way a card is turned over rather than scrolled through.
   ============================================================ */

/* Self-hosted so the invitation looks the same on any network, and offline.
   Latin subsets of the variable faces; see assets/fonts/OFL-*.txt. */

@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/cormorant-garamond.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Cormorant Garamond";
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/cormorant-garamond-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Jost";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/jost.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --paper:   #fbf5ec;
  --card:    #fffcf6;
  --ink:     #2a241d;
  --ink-2:   #6b6055;
  --line:    rgba(42, 36, 29, .14);

  /* Terracotta carries the whole design. The lighter tone is for display
     sizes and ornament; anything set small uses the deeper one, which clears
     4.5:1 on the paper. */
  --clay:      #c05a34;
  --clay-ink:  #9b4322;
  --clay-wash: rgba(192, 90, 52, .07);
  --leaf:      #7d8a63;

  --serif: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --sans:  "Jost", ui-sans-serif, "Helvetica Neue", Arial, sans-serif;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --pop:  cubic-bezier(.34, 1.56, .64, 1);
  --pad:  clamp(1.15rem, 5vw, 2.75rem);
  --seal: clamp(76px, 19vw, 104px);
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* proximity, not mandatory: on a short screen page two is taller than the
     viewport, and mandatory would fight anyone trying to reach its last line */
  scroll-snap-type: y proximity;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.55;
  /* Cormorant sets oldstyle figures by default, which turns "14" into "I4"
     and drops the 4 below the baseline. Not for the date on a wedding invite. */
  font-variant-numeric: lining-nums;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--clay); color: #fffaf3; }

:where(a):focus-visible,
:where(button):focus-visible {
  outline: 2px solid var(--clay-ink);
  outline-offset: 3px;
  border-radius: 2px;
}

/* the <symbol> holder — present in the DOM, absent from the layout */
.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* the heart, wherever it stands in for an ampersand */
.hrt {
  display: inline-block;
  width: .8em;
  aspect-ratio: 32 / 28;
  fill: var(--clay);
  vertical-align: -.02em;
}

.hrt--beat { animation: beat 2.4s var(--ease) infinite; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* warm light in the corners, and a little tooth on the paper */
.bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(115% 70% at 50% -12%, #fffdf8 0%, rgba(255, 253, 248, 0) 62%),
    radial-gradient(70% 50% at 108% 104%, rgba(192, 90, 52, .10) 0%, rgba(192, 90, 52, 0) 62%),
    radial-gradient(60% 45% at -8% 88%, rgba(140, 128, 88, .10) 0%, rgba(140, 128, 88, 0) 60%);
}

.bg::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ──────────────────────────  petals  ────────────────────────── */

/* Ten of them, falling on a fixed layer so they carry across both pages.
   The span falls and the <i> inside sways and turns, which keeps the two
   motions on separate elements and so on separate `translate` properties. */
.petals {
  position: fixed;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
}

.petal {
  position: absolute;
  top: -10vh;
  left: var(--x);
  animation: fall var(--d) linear var(--w) infinite;
}

.petal i {
  display: block;
  width: calc(11px * var(--s));
  height: calc(13px * var(--s));
  border-radius: 50% 8% 50% 8%;
  background: linear-gradient(140deg, rgba(226, 158, 132, .75), rgba(192, 90, 52, .38));
  animation:
    sway calc(var(--d) / 3.5) ease-in-out var(--w) infinite alternate,
    tumble calc(var(--d) / 2.2) linear var(--w) infinite;
}

@keyframes fall   { to { translate: 0 118vh; } }
@keyframes sway   { from { translate: -16px 0; } to { translate: 16px 0; } }
@keyframes tumble { to { rotate: 360deg; } }

/* ──────────────────────────  the pages  ────────────────────────── */

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

.page {
  min-height: 100svh;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(1.5rem, 5vh, 3rem) var(--pad);
}

.page--card { position: relative; gap: clamp(1rem, 3vh, 2rem); }

/* ──────────────────────────  shared type  ────────────────────────── */

.eyebrow {
  margin: 0;
  font-family: var(--sans);
  font-weight: 500;
  font-size: clamp(.6rem, 1.5vw, .7rem);
  line-height: 1.4;
  letter-spacing: .3em;
  text-indent: .3em;
  text-transform: uppercase;
  color: var(--clay-ink);
}

/* ──────────────────────────  the card  ────────────────────────── */

/* The arched top is the one shape doing the heavy lifting: it reads as
   stationery from across the room, and it costs a border-radius. */
.card {
  --arch:  clamp(8rem, 38vw, 14rem);
  --frame: clamp(.5rem, 1.7vw, .8rem);

  position: relative;
  width: min(100%, 40rem);
  padding: clamp(3.5rem, 14vw, 5.5rem) clamp(1.4rem, 6vw, 3.5rem) calc(var(--seal) / 2 + clamp(1.6rem, 5vw, 2.3rem));
  text-align: center;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--arch) var(--arch) 3px 3px;
  box-shadow:
    0 1px 2px rgba(80, 52, 20, .05),
    0 44px 80px -54px rgba(80, 52, 20, .65);
}

/* the second, thinner rule inside the first — the oldest trick on a wedding
   invitation, and still the one that makes it look printed */
.card::before {
  content: "";
  position: absolute;
  inset: var(--frame);
  border: 1px solid rgba(192, 90, 52, .2);
  border-radius: calc(var(--arch) - var(--frame)) calc(var(--arch) - var(--frame)) 2px 2px;
  pointer-events: none;
}

.card > * { position: relative; }

/* ──────────────────────────  eucalyptus  ────────────────────────── */

.sprig {
  position: absolute;
  bottom: clamp(-1rem, -1vw, 0rem);
  width: clamp(46px, 13vw, 74px);
  height: auto;
  color: var(--leaf);
  opacity: .5;
  pointer-events: none;
  transform-origin: 50% 100%;
}

.sprig--l { left: clamp(-.6rem, -1vw, .2rem); }
.sprig--r { right: clamp(-.6rem, -1vw, .2rem); scale: -1 1; }

/* ──────────────────────────  the names  ────────────────────────── */

.names {
  margin: clamp(.7rem, 2.6vw, 1.2rem) 0 0;
  font-weight: 300;
  line-height: .96;
  letter-spacing: .005em;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.names__n { font-size: clamp(2.7rem, 14vw, 5.4rem); }

.names__heart {
  display: block;
  margin: clamp(.25rem, 1.4vw, .6rem) 0;
  color: var(--clay);
  animation: beat 2.4s var(--ease) infinite;
}

.names__heart svg {
  display: block;
  width: clamp(1.5rem, 6vw, 2.4rem);
  aspect-ratio: 32 / 28;
  fill: currentColor;
  filter: drop-shadow(0 4px 10px rgba(192, 90, 52, .3));
}

/* two quick beats, then a rest — a pulse rather than a throb */
@keyframes beat {
  0%, 100% { scale: 1; }
  12%      { scale: 1.16; }
  24%      { scale: 1; }
  36%      { scale: 1.1; }
  48%      { scale: 1; }
}

.squiggle {
  display: block;
  width: clamp(6rem, 24vw, 8.5rem);
  height: auto;
  margin: clamp(.9rem, 3vw, 1.4rem) auto clamp(.8rem, 2.6vw, 1.2rem);
  color: var(--clay);
  opacity: .75;
}

.tagline {
  margin: 0 auto;
  max-width: 26rem;
  font-size: clamp(1.02rem, 3.3vw, 1.32rem);
  font-style: italic;
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: balance;
}

.when {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(.5rem, 2vw, .9rem);
  margin: clamp(1.1rem, 4vw, 1.8rem) 0 0;
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(.68rem, 2.1vw, .8rem);
  letter-spacing: .22em;
  text-transform: uppercase;
}

.when i {
  width: 3px;
  height: 3px;
  rotate: 45deg;
  background: var(--clay);
}

/* ──────────────────────────  countdown  ────────────────────────── */

.count {
  display: flex;
  justify-content: center;
  gap: clamp(1.1rem, 5vw, 2.1rem);
  margin: clamp(1.2rem, 4vw, 1.9rem) 0 0;
}

.count[hidden] { display: none; }

.count__t {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .2rem;
  min-width: 3.4rem;
}

.count__t + .count__t { border-left: 1px solid var(--line); padding-left: clamp(1.1rem, 5vw, 2.1rem); }

.count__t b {
  font-weight: 300;
  font-size: clamp(1.8rem, 6.6vw, 2.5rem);
  line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
}

/* a little kick each time a figure rolls over */
.count__t b.is-new { animation: tick .5s var(--pop); }

@keyframes tick {
  0%   { scale: 1;    color: var(--clay); }
  40%  { scale: 1.18; color: var(--clay); }
  100% { scale: 1; }
}

.count__t span {
  font-family: var(--sans);
  font-size: .56rem;
  letter-spacing: .24em;
  text-indent: .24em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* the day itself, once it has arrived */
.count--done {
  display: block;
  font-style: italic;
  font-size: clamp(1.1rem, 3.6vw, 1.4rem);
  color: var(--clay-ink);
}

/* ──────────────────────────  buttons  ────────────────────────── */

.actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .6rem;
  margin: clamp(1.3rem, 4.5vw, 2rem) 0 0;
}

.btn {
  appearance: none;
  position: relative;
  display: inline-block;
  padding: .8rem 1.35rem;
  font-family: var(--sans);
  font-weight: 500;
  font-size: .72rem;
  line-height: 1.2;
  letter-spacing: .15em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  background: transparent;
  border: 1px solid rgba(42, 36, 29, .22);
  border-radius: 999px;
  cursor: pointer;
  transition: background .35s var(--ease), color .35s var(--ease),
              border-color .35s var(--ease), translate .35s var(--ease);
}

.btn:hover { border-color: var(--clay-ink); color: var(--clay-ink); translate: 0 -2px; }

.btn--solid {
  background: var(--clay-ink);
  border-color: var(--clay-ink);
  color: #fffaf3;
}

.btn--solid:hover { background: var(--clay); border-color: var(--clay); color: #fffaf3; }

/* hearts thrown by the calendar button; positioned by main.js */
.burst {
  position: fixed;
  z-index: 30;
  width: 14px;
  height: 13px;
  pointer-events: none;
  color: var(--clay);
  animation: throw .9s var(--ease) forwards;
}

.burst svg { width: 100%; height: 100%; fill: currentColor; display: block; }

@keyframes throw {
  from { opacity: 1; translate: 0 0; scale: .4; }
  to   { opacity: 0; translate: var(--dx) var(--dy); scale: 1; rotate: var(--dr); }
}

.toast {
  margin: .8rem 0 0;
  min-height: 1.1em;
  font-family: var(--sans);
  font-size: .66rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-2);
  opacity: 0;
  transition: opacity .3s var(--ease);
}

.toast.is-on { opacity: 1; }

/* ──────────────────────────  the seal  ────────────────────────── */

.seal {
  position: absolute;
  left: 50%;
  bottom: calc(var(--seal) / -2);
  width: var(--seal);
  height: var(--seal);
  translate: -50% 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--card);
  border: 1px solid rgba(192, 90, 52, .28);
  box-shadow: 0 10px 26px -14px rgba(80, 52, 20, .6);
}

.seal__ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: var(--clay-ink);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  /* tuned so the legend fills the 282.7 unit circumference of #sealArc
     without colliding with its own tail — measured at 96.6% */
  letter-spacing: 1.25px;
  animation: spin 26s linear infinite;
}

@keyframes spin { to { rotate: 360deg; } }

.seal__core {
  font-size: calc(var(--seal) * .26);
  font-weight: 300;
  line-height: 1;
  letter-spacing: .02em;
}

.seal__core .hrt { width: .72em; }

/* ──────────────────────────  the scroll cue  ────────────────────────── */

.cue {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
  margin-top: calc(var(--seal) / 2 + clamp(.5rem, 2vh, 1.2rem));
  font-family: var(--sans);
  font-size: .6rem;
  font-weight: 500;
  letter-spacing: .3em;
  text-indent: .3em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--clay-ink);
  transition: opacity .4s var(--ease);
}

.cue svg { width: 1.05rem; animation: nudge 2.2s var(--ease) infinite; }

.cue:hover { opacity: .65; }

@keyframes nudge {
  0%, 100% { translate: 0 0;    opacity: .55; }
  50%      { translate: 0 .35rem; opacity: 1; }
}

/* ──────────────────────────  page two  ────────────────────────── */

.day {
  width: min(100%, 46rem);
  text-align: center;
}

.rail {
  margin: clamp(1.4rem, 5vh, 2.4rem) 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
}

.rail__item {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: clamp(.9rem, 3vw, 1.4rem);
  padding: 0 0 clamp(1.5rem, 4.5vh, 2.4rem) clamp(1.5rem, 5vw, 2.1rem);
}

/* the line linking the three dots, stopping at the last one */
.rail__item::before {
  content: "";
  position: absolute;
  left: clamp(.34rem, 1.2vw, .48rem);
  top: .7rem;
  bottom: -.3rem;
  width: 1px;
  background: linear-gradient(var(--clay-wash), rgba(192, 90, 52, .34));
}

.rail__item:last-child { padding-bottom: 0; }
.rail__item:last-child::before { display: none; }

.rail__dot {
  position: absolute;
  left: 0;
  top: .45rem;
  width: clamp(.7rem, 2.4vw, .95rem);
  height: clamp(.7rem, 2.4vw, .95rem);
  border-radius: 50%;
  border: 1px solid var(--clay);
  background: var(--paper);
}

.rail__dot::after {
  content: "";
  position: absolute;
  inset: 25%;
  border-radius: 50%;
  background: var(--clay);
  scale: 0;
  transition: scale .5s var(--pop) calc(var(--i, 0) * .12s + .2s);
}

.rail__item.is-in .rail__dot::after { scale: 1; }

.rail__item--main .rail__dot { box-shadow: 0 0 0 4px var(--clay-wash); }

.rail__body { flex: 1; min-width: 0; }

.rail__title {
  margin: 0;
  font-weight: 400;
  font-size: clamp(1.45rem, 5vw, 1.9rem);
  line-height: 1.1;
}

.rail__when {
  margin: .3rem 0 0;
  font-family: var(--sans);
  font-size: clamp(.66rem, 2vw, .72rem);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.rail__when b { color: var(--clay); font-weight: 400; }

.rail__where {
  margin: .35rem 0 0;
  font-size: clamp(1.02rem, 3.2vw, 1.15rem);
  line-height: 1.4;
  text-wrap: balance;
}

.rail__map {
  display: inline-block;
  margin: .5rem 0 0;
  padding-bottom: 2px;
  font-family: var(--sans);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--clay-ink);
  border-bottom: 1px solid rgba(155, 67, 34, .35);
  transition: border-color .3s var(--ease);
}

.rail__map::after { content: " \2197"; }
.rail__map:hover { border-color: var(--clay-ink); }

/* A QR is worthless on the phone you are already holding, and genuinely
   useful on a laptop — so it only shows up where it earns its space. */
.rail__qr { display: none; }

@media (min-width: 46rem) {
  .rail__qr {
    display: block;
    width: 76px;
    height: auto;
    opacity: .75;
    transition: opacity .3s var(--ease);
  }

  .rail__item:hover .rail__qr { opacity: 1; }
}

/* ──────────────────────────  sign-off  ────────────────────────── */

.outro {
  margin: clamp(1.8rem, 6vh, 3rem) auto 0;
  max-width: 30rem;
  padding-top: clamp(1.4rem, 4vh, 2.2rem);
  border-top: 1px solid var(--line);
}

.monogram {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(.3rem, 1.6vw, .6rem);
  margin: 0;
  font-size: clamp(1.8rem, 6.4vw, 2.5rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: .03em;
}

.monogram .hrt { width: .62em; }

.outro__line {
  margin: clamp(.9rem, 3vh, 1.3rem) 0 0;
  font-size: clamp(1.1rem, 3.5vw, 1.35rem);
  font-style: italic;
  line-height: 1.5;
  color: var(--ink-2);
}

.outro__sign {
  margin: clamp(1rem, 3.5vh, 1.5rem) 0 0;
  font-family: var(--sans);
  font-size: clamp(.66rem, 2vw, .74rem);
  letter-spacing: .26em;
  text-indent: .26em;
  text-transform: uppercase;
  color: var(--clay-ink);
}


/* ────────────────────  when height is the constraint  ──────────────────── */

/* The card is sized off the viewport width, so a wide-but-short screen — a
   1440×900 laptop, or a small phone — grows it past the page it is meant to
   fill. These pull the vertical rhythm in without touching the type scale
   anywhere it already fits. Page one is centred, so trimming can only ever
   leave more air, never clip. */
/* Wherever the viewport is short, pull the vertical rhythm in. */
@media (max-height: 60rem) {
  .page { padding-block: clamp(.9rem, 2.5vh, 1.6rem); }

  /* the toast stops reserving a line it only needs after a click */
  .toast { min-height: 0; margin-top: .5rem; }

  .card {
    padding-top: clamp(2.75rem, 9vh, 4rem);
    padding-bottom: calc(var(--seal) / 2 + 1.2rem);
  }

  .names   { margin-top: .5rem; }
  .squiggle { margin-block: .7rem .6rem; }
  .when    { margin-top: 1rem; }
  .count   { margin-top: 1rem; }
  .actions { margin-top: 1.1rem; }
  .cue     { margin-top: calc(var(--seal) / 2 + .4rem); }

  .rail__item { padding-bottom: clamp(1.1rem, 3.2vh, 2rem); }
  .outro { margin-top: clamp(1.2rem, 4vh, 2.2rem); padding-top: clamp(1rem, 3vh, 1.8rem); }
}

/* wide but short — a laptop, where the type is sized off a generous width */
@media (min-width: 46rem) and (max-height: 60rem) {
  .names__n { font-size: clamp(2.6rem, 8.5vh, 4.4rem); }
}

/* narrow and short — a small phone, where every line has to earn its place */
@media (max-width: 46rem) and (max-height: 46rem) {
  :root { --seal: clamp(62px, 16vw, 80px); }

  .card { padding-top: clamp(1.8rem, 6.5vh, 2.6rem); }
  .names      { margin-top: .35rem; }
  .names__n   { font-size: clamp(2.05rem, 9.5vh, 3.1rem); }
  .tagline    { font-size: clamp(.95rem, 4.4vh, 1.1rem); line-height: 1.45; }
  .count__t b { font-size: clamp(1.45rem, 5.4vh, 1.95rem); }
  .squiggle   { width: clamp(4.5rem, 20vw, 6rem); margin-block: .5rem .45rem; }
  .when       { margin-top: .85rem; }
  .count      { margin-top: .85rem; }
  .actions    { margin-top: .9rem; }
  .rail__title { font-size: clamp(1.3rem, 4.6vw, 1.6rem); }
}

/* ──────────────────────────  motion  ────────────────────────── */

/* the card assembles itself once, on load */
.js .card > * {
  animation: rise .85s var(--ease) backwards;
  animation-delay: calc(.12s + var(--i, 0) * .085s);
}

@keyframes rise {
  from { opacity: 0; translate: 0 16px; }
}

/* the sprigs grow up out of the base instead of rising with the text */
.js .sprig {
  animation: grow 1.5s var(--ease) backwards;
  animation-delay: .5s;
}

@keyframes grow {
  from { opacity: 0; scale: 1 .4; }
}

.js .sprig--r { animation-name: grow-r; }

@keyframes grow-r {
  from { opacity: 0; scale: -1 .4; }
  to   { opacity: .5; scale: -1 1; }
}

/* the seal drops in last, and keeps its own centring translate */
.js .seal { animation-name: drop; }

@keyframes drop {
  from { opacity: 0; scale: .7; }
}

.js .cue { animation: rise 1s var(--ease) 1.1s backwards; }

/* page two waits until it is looked at */
.js .reveal {
  opacity: 0;
  translate: 0 20px;
  transition: opacity .8s var(--ease), translate .8s var(--ease);
  transition-delay: calc(var(--i, 0) * .1s);
}

.js .reveal.is-in { opacity: 1; translate: 0 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; scroll-snap-type: none; }

  .js .card > *,
  .js .sprig,
  .js .seal,
  .js .cue { animation: none; }

  .js .reveal { opacity: 1; translate: none; transition: none; }

  .petals { display: none; }

  .seal__ring,
  .names__heart,
  .hrt--beat,
  .cue svg { animation: none; }

  .rail__dot::after { scale: 1; transition: none; }

  .btn { transition: none; }
}

/* ──────────────────────────  on paper  ────────────────────────── */

@media print {
  .bg, .petals, .actions, .toast, .count, .cue { display: none; }

  html { scroll-snap-type: none; }
  body { background: #fff; }
  .page { min-height: 0; padding: 0 0 1.5rem; display: block; }
  .card, .rail__item { box-shadow: none; break-inside: avoid; }
  .seal__ring { animation: none; }
  .rail__qr { display: block; }
  .rail__map::after { content: ""; }
}
