/* «Taqdir ipi» (fa7e) — anime night-sky invitation.
   One evening passing top to bottom: every .sky section owns a solid from the
   design doc's table (--sky, set inline in the HTML); a ::before bridge blends
   from the PREVIOUS visible section's color (--sky-prev, set by main.js after
   every config/i18n pass — heights and the visible set vary, so a single body
   gradient could never line up). The red thread (#E0304B) is an SVG overlay
   per section, drawn by scroll — js/main.js builds the paths into .thread-svg
   mounts; here we only style them. */

:root {
  --night: #0E1633;
  --indigo: #1E2A5C;
  --violet: #5D4B8C;
  --peach: #FFB37B;
  --pink: #FF8FA3;
  --thread: #E0304B;
  --gold: #FFD98E;
  --cream: #FFF3EC;
  --ink: #2A2440;        /* on light cards */
  --ink-soft: #574D6E;
  --text: #F2EEFF;       /* on night */
  --text-soft: #C9C2E8;
  --card: rgba(255, 243, 236, .07);
  --card-line: rgba(255, 243, 236, .16);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
/* the invitation reads like a card — hide the scrollbar, scrolling itself stays
   (parity with a1f4/f1da; the visible scrollbar was the stray "scrolling tick") */
html { scrollbar-width: none; -ms-overflow-style: none; }
html::-webkit-scrollbar { width: 0; height: 0; display: none; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  /* the surround the phone column floats on (desktop) — a soft top glow over
     night so it isn't dead-flat behind the centered invitation */
  background: radial-gradient(90% 55% at 50% 0%, #1B2245, var(--night) 60%);
  background-attachment: fixed;
  color: var(--text);
  font-family: 'Manrope', system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
  /* long unbroken values must wrap, never overflow the fixed column */
  overflow-wrap: break-word;
}
body.lock { overflow: hidden; }

/* ---------- the phone column ----------
   Like a1f4/f1da: the whole invitation is a 480px column centered on the
   surround, so desktop reads as an invitation, not a full-width website. On a
   phone the column simply fills the screen. NB: no position/z-index here — the
   fixed particle canvas (z 1) must stay able to float over the opaque section
   art while text (z 2) stays above it; a stacking context on .page would bury
   the particles behind the whole column. */
.page {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100dvh;
  overflow: hidden; /* clip any horizontal bleed to the column edge */
  box-shadow: 0 0 80px rgba(0, 0, 0, .55);
}

/* class-only selector (NOT img.art): height:auto lets content images override
   their HTML height attribute and scale by aspect ratio, but keeps specificity
   at (0,1,0) so `.hero-art{height:100%}` — defined later, same specificity —
   wins for the full-bleed hero (an `img.art` selector would out-specify it and
   collapse the hero to its aspect ratio, leaving a gap). */
.art { display: block; max-width: 100%; height: auto; user-select: none; -webkit-user-drag: none; }

/* flex/grid sections would cancel [hidden] — the repo's recurring gotcha */
.sec[hidden] { display: none !important; }
.lang[hidden] { display: none; }

/* ---------- shared chrome ---------- */

.kicker {
  font-size: .78rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold);
  text-align: center;
}

.sec-title {
  font-family: 'Philosopher', serif;
  font-weight: 700;
  font-size: clamp(1.5rem, 5.2vw, 2.1rem);
  text-align: center;
  margin-top: .5rem;
  text-wrap: balance;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  font: 600 .95rem/1 'Manrope', system-ui, sans-serif;
  color: #2A1A34;
  /* warm gold→coral, richer than the old flat peach-pink */
  background: linear-gradient(135deg, #FFD98E 0%, #FF9E82 100%);
  border: 0;
  border-radius: 999px;
  padding: .9em 1.9em;
  cursor: pointer;
  text-decoration: none;
  transition: transform .25s cubic-bezier(.22,1,.36,1), box-shadow .25s;
  box-shadow: 0 6px 22px rgba(255, 158, 130, .28);
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(255, 158, 130, .4); }
.btn:active { transform: none; }

/* language pill + demo back — same fixed chrome as the sibling templates */
.lang {
  position: fixed;
  top: max(.8rem, env(safe-area-inset-top));
  /* hug the 480px column's right edge on desktop, the window edge on mobile */
  right: max(.8rem, env(safe-area-inset-right), calc((100% - 480px) / 2 + .8rem));
  z-index: 110; /* above the splash (100) — switchable on the splash too */
  display: flex;
  gap: .2rem;
  background: rgba(14, 22, 51, .55);
  backdrop-filter: blur(6px);
  border: 1px solid var(--card-line);
  border-radius: 999px;
  padding: .22rem;
}
.lang-btn {
  font: 600 .78rem/1 'Manrope', sans-serif;
  color: var(--text-soft);
  background: none;
  border: 0;
  border-radius: 999px;
  padding: .45em .8em;
  cursor: pointer;
}
.lang-btn.is-active { color: var(--night); background: var(--gold); }

.demo-back {
  position: fixed;
  top: max(.8rem, env(safe-area-inset-top));
  left: max(.8rem, env(safe-area-inset-left), calc((100% - 480px) / 2 + .8rem));
  z-index: 110;
  display: none;
  font: 600 .8rem/1 'Manrope', sans-serif;
  color: var(--text);
  text-decoration: none;
  background: rgba(14, 22, 51, .55);
  backdrop-filter: blur(6px);
  border: 1px solid var(--card-line);
  border-radius: 999px;
  padding: .6em 1em;
}
html.is-demo .demo-back { display: inline-block; }

/* ---------- particles (canvas, js-driven) ---------- */
.particles {
  position: fixed;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---------- splash: «Yulduz to‘ri» ----------
   The night sky writes their fate: eight stars wake one by one and the red
   thread joins them into a heart constellation over a live starfield. The
   names rise from a dusk veil at the bottom; opening contracts the
   constellation into a single thread that lifts the whole night away. */
.splash {
  position: fixed;
  inset: 0;
  /* the same 480px column as .page, centered over the surround (f1da parity) */
  width: min(100%, 480px);
  margin-inline: auto;
  box-shadow: 0 0 80px rgba(0, 0, 0, .55);
  z-index: 100;
  overflow: hidden;
  background: var(--night);
}
.splash:focus, .splash:focus-visible { outline: none; } /* JS focuses it — no UA ring */
.splash-art { position: absolute; inset: 0; z-index: 0; }
.splash-art img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 100%; }
/* stars own the top two-thirds — the art glows up from the horizon */
.splash-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* the top band is near-opaque: it swallows the painted "thread" descending
     from the art's top edge (which used to meet the top-pinned heart; the heart
     now crowns the names, so that stub would just dangle). The canvas starfield
     paints ABOVE this, so the night keeps its stars. */
  background: linear-gradient(180deg,
    rgba(9, 13, 31, .98) 0%, rgba(9, 13, 31, .93) 12%, rgba(9, 13, 31, .74) 32%,
    rgba(14, 22, 51, .32) 58%, rgba(224, 90, 60, .10) 100%);
}
.splash-stars { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; }

/* the constellation crowns the names as a monogram — main.js seeds the eight
   stars into .const-stars. Gold stars are the heroes; the thread is a fine,
   soft rose gesture, not a bold red outline. */
.splash-const {
  width: clamp(132px, 40vw, 178px);
  margin: 0 auto .1rem;
  overflow: visible;
  filter: drop-shadow(0 8px 22px rgba(9, 13, 31, .55));
}
.const-line {
  fill: none;
  stroke: var(--thread);
  stroke-width: 1.1;
  stroke-linejoin: round;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: .85;
  filter: drop-shadow(0 0 2.5px rgba(224, 48, 75, .45));
  animation: const-draw 1.4s cubic-bezier(.45,0,.3,1) .55s forwards;
}
@keyframes const-draw { to { stroke-dashoffset: 0; } }
.const-star-flare {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: star-flare .85s ease-out var(--d) forwards;
}
@keyframes star-flare {
  0% { opacity: 0; transform: scale(.2); }
  35% { opacity: .9; }
  100% { opacity: 0; transform: scale(2.4); }
}
.const-star-core {
  fill: var(--gold);
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(.45);
  opacity: .35;
  filter: drop-shadow(0 0 6px rgba(255, 217, 142, 1));
  animation: star-wake .55s ease-out var(--d) forwards;
}
@keyframes star-wake { to { transform: scale(1); opacity: 1; } }
/* a whisper of warm rose fills the heart once drawn — subtle, not neon */
.const-glow {
  stroke: none;
  fill: rgba(224, 48, 75, 0);
  animation: const-breathe 5s ease-in-out 2.6s infinite;
}
@keyframes const-breathe {
  0%, 100% { fill: rgba(255, 143, 163, .05); }
  50%      { fill: rgba(255, 143, 163, .11); }
}

/* the text sits on the art's brightest band — give it its own dusk veil */
.splash-veil {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 46%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(14, 22, 51, 0) 0%, rgba(14, 22, 51, .34) 38%,
    rgba(11, 16, 38, .58) 68%, rgba(9, 13, 31, .74) 100%);
}

/* ---- exit (codex motion pass): the night lifts as ONE graceful curtain to
   reveal the sunset hero underneath. The centred group departs first (a short
   up-and-fade), then the whole splash rises on a decelerating curve with a soft
   violet under-shadow between the two painted layers. No heartbeat, no
   constellation collapse, no top thread — one calm move. */
/* HOUSE exit (DESIGN.md, same as siblings): one soft dissolve — the night
   fades and drifts forward while the hero settles beneath it. */
.splash {
  transition: opacity .9s ease, transform 1.1s cubic-bezier(.22,1,.36,1), visibility 0s linear .9s;
}
.splash--closing {
  opacity: 0;
  transform: scale(1.08);
  visibility: hidden;
  pointer-events: none;
}
/* the revealed hero settles in — a whisper of scale, so it breathes rather than
   snapping into place as the curtain clears it */
body.is-open .hero-art { animation: hero-art-in 1.8s cubic-bezier(.22, 1, .36, 1) both; }
@keyframes hero-art-in { from { transform: scale(1.06); } to { transform: none; } }

/* a soft elliptical bloom lifts the whole group off the busy sky — violet-indigo
   at the core, a whisper of warm peach below, so the type reads without heavy
   shadows (the a1f4 splash's trick, in fa7e's palette) */
.splash-glow {
  position: absolute;
  left: 50%; top: 45%;
  transform: translate(-50%, -50%);
  width: 92%; height: 56%;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(58% 46% at 50% 40%, rgba(74, 60, 128, .58), rgba(30, 42, 92, .24) 48%, transparent 74%),
    radial-gradient(46% 30% at 50% 84%, rgba(255, 179, 123, .12), transparent 72%);
  filter: blur(4px);
}

/* one centered group: constellation crown → kicker → names → date → CTA.
   Optically raised (~45%) — night above for anticipation, horizon below. */
.splash-inner {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  padding: 6% 1.6rem 16%;
  text-align: center;
}
/* HOUSE entrance rhythm (DESIGN.md, same stagger as the siblings): the story
   resolves in ~1.2s — kicker .18s, names .32s, date .46s, CTA .62s. The
   constellation keeps drawing above on its own clock, pure ornament. */
.splash-kicker { animation: splash-up 1s cubic-bezier(.22,1,.36,1) .18s both; }
.splash-names  { animation: splash-up 1.1s cubic-bezier(.22,1,.36,1) .32s both; }
.splash-date   { animation: splash-up 1.1s cubic-bezier(.22,1,.36,1) .46s both; }
.splash-btn {
  animation:
    splash-up 1.1s cubic-bezier(.22,1,.36,1) .62s both,
    splash-glow 2.8s ease-in-out 2.2s infinite;
}
@keyframes splash-up { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
@keyframes splash-glow {
  0%, 100% { box-shadow: 0 6px 22px rgba(255, 158, 130, .28); }
  50%      { box-shadow: 0 6px 32px rgba(255, 217, 142, .55); }
}
.splash-kicker {
  color: rgba(255, 217, 142, .82);
  letter-spacing: .28em;
  margin-top: .3rem;
  text-shadow: 0 1px 3px rgba(9, 13, 31, .9), 0 2px 16px rgba(9, 13, 31, .85);
}
.splash-names {
  font-family: 'Philosopher', serif;
  font-weight: 700;
  font-size: clamp(2rem, 9vw, 3.15rem);
  line-height: 1.1;
  text-wrap: balance;
  max-width: 100%;
  text-shadow: 0 2px 6px rgba(9, 13, 31, .9), 0 4px 26px rgba(9, 13, 31, .85);
}
.splash-i { color: var(--gold); font-weight: 400; margin: 0 .12em; }
.splash-date {
  color: #E7E1F5;
  letter-spacing: .14em;
  font-size: 1rem;
  text-shadow: 0 1px 3px rgba(9, 13, 31, .9), 0 2px 14px rgba(9, 13, 31, .8);
}
/* the CTA: a solid midnight-indigo pill with a restrained gold rim + a faint
   inner highlight — reads decisively as "enter", not a thin glass outline */
/* HOUSE pattern: the splash CTA is this template's own primary .btn (the
   warm gold→coral pill) — no bespoke glass variant. Only spacing lives here;
   the entrance block above owns `animation` (redeclaring it at equal
   specificity later in the file would cancel the rise). */
.splash-btn {
  margin-top: 2.4rem;
}

/* ---------- sections + the sky bridge ---------- */
.sec { position: relative; }
.sky {
  background: var(--sky, var(--night));
  padding: 4.5rem 1.5rem 4.8rem; /* sibling mobile rhythm (f1da: 4.5/1.5) */
}
/* the blend from the previous visible section's sky (js sets --sky-prev) —
   taller = a softer dissolve between the evening's colours */
.sky::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 170px;
  background: linear-gradient(var(--sky-prev, var(--sky, var(--night))), transparent);
  pointer-events: none;
}
.sky > *:not(.thread-svg) { position: relative; z-index: 2; max-width: 640px; margin-left: auto; margin-right: auto; }

/* thread mounts: one absolutely-positioned SVG per section (js fills the path).
   Decorative only — hidden from AT, never carrying information. */
.thread-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
  overflow: visible;
}
.thread-svg path {
  fill: none;
  stroke-linecap: round;
}
.thread-path {
  stroke: var(--thread);
  stroke-width: 1.6;
  opacity: .85;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1);
}
.thread-glow {
  stroke: rgba(224, 48, 75, .22);
  stroke-width: 4;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1);
}
.sec.thread-drawn .thread-path,
.sec.thread-drawn .thread-glow { stroke-dashoffset: 0; }

/* ---------- hero ---------- */
.hero { min-height: 100svh; display: grid; }
.hero-canvas { position: absolute; inset: 0; overflow: hidden; }
.hero-art { width: 100%; height: 100%; object-fit: cover; object-position: center bottom; }
/* a soft veil lifts the title off the bright dusk sky and grounds the couple */
.hero-scrim {
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(14, 22, 51, .52) 0%, rgba(14, 22, 51, .14) 24%, transparent 46%,
    rgba(9, 13, 31, .12) 78%, rgba(9, 13, 31, .4) 100%);
}
/* bridge the hero's bottom into the first sky section (#462F66) so the warm art
   dissolves into the evening instead of meeting it at a hard edge */
.hero::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 34%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(70, 47, 102, .5) 56%, #462F66 100%);
}
.hero-content {
  position: relative;
  z-index: 2;
  place-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .55rem;
  text-align: center;
  padding: 4.5rem 1.4rem;
}
/* the red thread of fate, tied with a gold star — the title's crown */
.hero-thread { width: clamp(150px, 46vw, 210px); margin-bottom: .35rem; }
.hero-thread .ht-line {
  stroke: var(--thread); stroke-width: 1.4;
  filter: drop-shadow(0 0 3px rgba(224, 48, 75, .5));
}
.hero-thread .ht-star {
  fill: var(--gold);
  filter: drop-shadow(0 0 5px rgba(255, 217, 142, .95));
}
/* names: big for short couples, wrapping cleanly for long ones. flex-wrap so a
   long pair breaks to two lines (name / & name) instead of overflowing; the
   size eases down on narrow screens so it never clips the column edge. */
.hero-names {
  font-family: 'Philosopher', serif;
  font-weight: 700;
  font-size: clamp(2rem, 9vw, 3.5rem);
  line-height: 1.14;
  color: #fff;
  text-shadow: 0 2px 26px rgba(93, 75, 140, .65);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: .1em .3em;
  padding: 0 .4em;
  max-width: 100%;
  overflow-wrap: anywhere;
}
.hero-name { max-width: 100%; }
.hero-amp { color: var(--gold); font-size: .55em; }
.hero-date {
  margin-top: .9rem;
  color: #fff;
  letter-spacing: .14em;
  font-size: .95rem;
  max-width: calc(100vw - 2.4rem);
  margin-inline: auto;
  text-wrap: balance;
  text-shadow: 0 1px 14px rgba(93, 75, 140, .8);
}
/* the opening entrance — keyed by body.is-open (splash removed) */
.hero-content > * { opacity: 0; transform: translateY(14px); }
body.is-open .hero-content > *,
html.is-preview .hero-content > * {
  opacity: 1;
  transform: none;
  transition: opacity .9s ease .15s, transform .9s cubic-bezier(.22,1,.36,1) .15s;
}
body.is-open .hero-content > :nth-child(2) { transition-delay: .3s; }
body.is-open .hero-content > :nth-child(3) { transition-delay: .45s; }

/* ---------- invite ---------- */
.invite-lead {
  margin-top: 1.2rem;
  text-align: center;
  font-size: 1.08rem;
  color: var(--text);
  text-wrap: balance;
}
.invite-accent { color: var(--gold); font-style: normal; font-family: 'Philosopher', serif; }
.couple-grid {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: .8rem;
  margin-top: 2.4rem;
}
.couple-card { text-align: center; min-width: 0; } /* long EN/RU names must wrap, not widen the grid */
.couple-name, .couple-line { overflow-wrap: anywhere; }
.couple-frame {
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--card-line);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .35);
  background: var(--card);
}
.couple-photo { aspect-ratio: 3/4; object-fit: cover; width: 100%; }
.couple-photo--real { filter: saturate(.92) sepia(.06); } /* real photos sit with the drawn art */
.couple-name {
  font-family: 'Philosopher', serif;
  font-weight: 700;
  font-size: 1.25rem;
  margin-top: .8rem;
}
.couple-line { font-size: .82rem; color: var(--text-soft); margin-top: .15rem; }
.couple-line[hidden] { display: none; }
.couple-amp {
  font-family: 'Philosopher', serif;
  font-size: 1.6rem;
  color: var(--gold);
}
.couple-ig[hidden] { display: none; } /* flex would silently cancel [hidden] — recurring gotcha */
.couple-ig {
  display: inline-flex;
  align-items: center;
  gap: .35em;
  max-width: 100%;
  margin-top: .35rem;
  font-size: .82rem;
  color: var(--text-soft);
  text-decoration: none;
}
.couple-ig::before { content: '📷'; font-size: .9em; }
.couple-ig-handle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.invite-quote {
  margin-top: 2.6rem;
  text-align: center;
  border-top: 1px solid var(--card-line);
  border-bottom: 1px solid var(--card-line);
  padding: 1.6rem .4rem;
}
.invite-quote-text {
  font-family: 'Philosopher', serif;
  font-size: 1.15rem;
  line-height: 1.55;
  text-wrap: balance;
}
.invite-quote-sub { margin-top: .7rem; font-size: .85rem; color: var(--text-soft); }

/* ---------- story ---------- */
.story-art { margin-top: 1.4rem; border-radius: 14px; overflow: hidden; box-shadow: 0 12px 44px rgba(0, 0, 0, .4); }
.story-text { margin-top: 1.1rem; text-align: center; color: var(--text); text-wrap: pretty; }
.story-text[hidden] { display: none; }

/* ---------- calendar + comet countdown ---------- */
.cal-card {
  margin-top: 1.6rem;
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: 16px;
  padding: 1.1rem;
}
.cal-week, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; }
.cal-week span { font-size: .72rem; letter-spacing: .08em; color: var(--text-soft); padding-bottom: .5rem; text-transform: uppercase; }
.cal-day { position: relative; padding: .42em 0; font-size: .95rem; color: var(--text); }
.cal-day--wed { color: var(--night); font-weight: 700; }
.cal-day--wed::before {
  content: '';
  position: absolute;
  inset: .1em .28em;
  background: linear-gradient(135deg, var(--peach), var(--pink));
  border-radius: 999px;
  z-index: -1;
  box-shadow: 0 0 18px rgba(255, 143, 163, .5);
}
.cal-heart { display: block; font-size: .55em; line-height: .4; color: var(--thread); }
.comet-panel { margin-top: 2rem; }
.comet-svg { width: 100%; height: auto; overflow: visible; }
.comet-arc {
  stroke: rgba(255, 217, 142, .28);
  stroke-width: 1;
  stroke-dasharray: .012 .02; /* dotted star-track */
}
.comet-head { fill: var(--gold); filter: drop-shadow(0 0 6px var(--gold)); }
.comet-tail { fill: rgba(255, 217, 142, .5); }
.comet--today .comet-head { filter: drop-shadow(0 0 14px var(--gold)); }
.cd-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .7rem;
  margin-top: 1.4rem;
}
.cd-grid[hidden] { display: none; } /* grid would cancel [hidden] on the wedding day */
/* 320px phones: four tiles crush the labels — two rows read fine */
@media (max-width: 340px) { .cd-grid { grid-template-columns: repeat(2, 1fr); } }
.cd-num { font-variant-numeric: tabular-nums; } /* ticking must not shift layout */
.cd-today[hidden] { display: none; }
.cd-tile {
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: 14px;
  text-align: center;
  padding: .9rem .2rem .8rem;
}
.cd-num {
  display: block;
  font-family: 'Philosopher', serif;
  font-weight: 700;
  font-size: clamp(1.5rem, 7vw, 2.2rem);
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.cd-label { font-size: clamp(.5rem, 2.2vw, .68rem); letter-spacing: .06em; text-transform: uppercase; color: var(--text-soft); } /* «Секунды» must fit a 360px tile */
.cd-today {
  margin-top: 1.6rem;
  text-align: center;
  font-family: 'Philosopher', serif;
  font-size: 1.5rem;
  color: var(--gold);
}

/* ---------- venue ---------- */
.venue-card { margin-top: 1.6rem; border-radius: 16px; overflow: hidden; box-shadow: 0 14px 50px rgba(0, 0, 0, .45); }
.venue-info { text-align: center; }
.venue-address { margin-top: .5rem; color: var(--text-soft); }
.venue-address[hidden] { display: none; }
.venue-time { margin-top: .4rem; }
.venue-hour { color: var(--gold); font-weight: 600; }
.venue-info p:has(.venue-btn) { margin-top: 1.3rem; }
.venue-note { margin-top: 1rem; font-size: .85rem; color: var(--text-soft); }
.venue-note[hidden] { display: none; }

/* ---------- program: knots along the thread ---------- */
.prog-list {
  list-style: none;
  margin-top: 2rem;
  position: relative;
  padding-left: 2rem;
}
/* the vertical run the knots sit on — the thread passing through the section.
   left is aligned to the KNOT CENTRE (knot left .55rem + 5px radius − 1px half
   the 2px thread), so the thread runs through the middle of each ring, not its
   edge. It also stops at the first/last knot centre instead of overrunning. */
.prog-list::before {
  content: '';
  position: absolute;
  left: calc(.55rem + 4px);
  top: 1.1rem; bottom: 1.1rem;
  width: 2px;
  background: var(--thread);
  box-shadow: 0 0 8px rgba(224, 48, 75, .5);
  border-radius: 2px;
}
.prog-item { position: relative; display: flex; gap: .9rem; align-items: baseline; padding: .55rem 0; }
.prog-item[hidden] { display: none; }
.prog-knot {
  position: absolute;
  left: -1.45rem;
  top: 50%;
  width: 10px; height: 10px;
  border: 2px solid var(--thread);
  border-radius: 50%;
  background: var(--sky, var(--night));
  transform: translateY(-50%);
  box-shadow: 0 0 8px rgba(224, 48, 75, .55);
}
.prog-time {
  font-family: 'Philosopher', serif;
  font-weight: 700;
  color: var(--gold);
  min-width: 3.4em;
  font-variant-numeric: tabular-nums;
}
.prog-label { color: var(--text); }
.prog-label[hidden] { display: none; }

/* ---------- gallery: film strip ---------- */
.film-strip {
  display: flex;
  gap: 1rem;
  margin-top: 1.8rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 14px 1.2rem;
  scroll-padding-inline: 1.2rem;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.film-strip::-webkit-scrollbar { display: none; }
.film-cel {
  flex: 0 0 min(68%, 300px);
  aspect-ratio: 3/4;
  object-fit: cover;
  scroll-snap-align: center;
  border-radius: 10px;
  border: 10px solid #060B22;
  /* sprocket holes top & bottom — the anime cel frame */
  background:
    repeating-linear-gradient(90deg, transparent 0 6px, rgba(255,255,255,.28) 6px 12px, transparent 12px 18px) top / 100% 6px no-repeat,
    repeating-linear-gradient(90deg, transparent 0 6px, rgba(255,255,255,.28) 6px 12px, transparent 12px 18px) bottom / 100% 6px no-repeat,
    #060B22;
  box-shadow: 0 10px 36px rgba(0, 0, 0, .5);
}
.gallery-photo { filter: saturate(.92) sepia(.06); } /* real uploads get the film grade */

/* ---------- rsvp: tie the bow ---------- */
.rsvp-title { font-family: 'Philosopher', serif; font-weight: 700; font-size: 1.15rem; text-align: center; margin-top: .8rem; text-wrap: balance; }
.rsvp-form { margin-top: 1.8rem; display: grid; gap: 1.1rem; }
.rsvp-label { display: block; font-size: .82rem; letter-spacing: .06em; color: var(--text-soft); margin-bottom: .4rem; }
.rsvp-input {
  width: 100%;
  font: 400 1rem/1.5 'Manrope', sans-serif;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: 12px;
  padding: .8em 1em;
  outline: none;
  transition: border-color .2s;
}
.rsvp-input:focus { border-color: var(--gold); }
.rsvp-status { display: grid; gap: .6rem; }
.rsvp-status-opt {
  display: flex;
  align-items: center;
  gap: .7rem;
  background: var(--card);
  border: 1px solid var(--card-line);
  border-radius: 12px;
  padding: .75em 1em;
  cursor: pointer;
  transition: border-color .2s;
}
.rsvp-status-opt:has(input:checked) { border-color: var(--gold); }
.rsvp-status-opt input { accent-color: var(--thread); }
.rsvp-hp { position: absolute; left: -9999px; }
.rsvp-submit { justify-self: center; margin-top: .4rem; } /* plain button — parity with a1f4/f1da */
.rsvp-msg { text-align: center; min-height: 1.4em; font-size: .9rem; }
.rsvp-msg.is-ok { color: var(--gold); }
.rsvp-msg.is-err { color: #FF9AA8; }

/* ---------- wishes / gift ---------- */
.wish-closing { margin-top: 1.6rem; text-align: center; font-size: 1.05rem; }
.wish-closing[hidden] { display: none; }
.wish-bless {
  margin-top: 1rem;
  text-align: center;
  font-family: 'Philosopher', serif;
  color: var(--gold);
}
.gift-note { margin-top: 1.2rem; text-align: center; color: var(--text); }
/* the whole panel IS the gift card: the night-art becomes its texture under a
   dusk scrim, with a gold chip, the couple's mark, and the number embossed on
   top — a real card, not a cream chip floating on a painting */
.gift-wrap {
  position: relative;
  margin: 1.7rem auto 0;
  width: 100%;
  max-width: 22rem;
  aspect-ratio: 1.585;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid rgba(255, 217, 142, .4);
  box-shadow: 0 22px 52px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .16);
}
.gift-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.gift-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(120% 92% at 82% 10%, rgba(255, 143, 163, .28), transparent 55%),
    linear-gradient(135deg, rgba(18, 24, 56, .84), rgba(42, 34, 96, .66) 55%, rgba(11, 15, 38, .88));
}
.gift-scrim::after { /* a soft diagonal sheen */
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(118deg, transparent 42%, rgba(255, 255, 255, .12) 50%, transparent 58%);
}
.gift-card {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column;
  padding: clamp(.9rem, 4.4vw, 1.25rem) clamp(1rem, 4.8vw, 1.35rem);
  text-align: left; color: #FFF3EC; overflow-wrap: anywhere;
}
.gift-card-top { display: flex; align-items: center; justify-content: space-between; }
.gift-chip {
  position: relative;
  width: clamp(2rem, 9vw, 2.5rem); aspect-ratio: 1.38; border-radius: 5px;
  background: linear-gradient(150deg, #F8DE96 0%, #E8C36A 46%, #C8983C 100%);
  box-shadow: inset 0 0 0 1px rgba(120, 80, 20, .4);
}
.gift-chip::before {
  content: ''; position: absolute; inset: 22% 16%;
  background:
    linear-gradient(rgba(120,80,20,.45), rgba(120,80,20,.45)) center/100% 1.2px no-repeat,
    linear-gradient(rgba(120,80,20,.45), rgba(120,80,20,.45)) 32% 0/1.2px 100% no-repeat,
    linear-gradient(rgba(120,80,20,.45), rgba(120,80,20,.45)) 68% 0/1.2px 100% no-repeat;
}
.gift-brand { font-family: 'Philosopher', serif; font-weight: 700; font-size: clamp(.78rem, 3.6vw, .92rem); color: rgba(255, 243, 236, .92); }
.gift-brand span { color: var(--thread); margin: 0 .04em; }
.gift-card-number {
  margin-top: auto;
  font-family: 'Philosopher', serif;
  font-weight: 700;
  font-size: clamp(1.05rem, 5.4vw, 1.55rem);
  letter-spacing: .12em;
  color: #FFF3EC;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 0 rgba(0, 0, 0, .45), 0 0 14px rgba(255, 217, 142, .3);
}
.gift-card-name {
  margin-top: .5rem;
  text-transform: uppercase; letter-spacing: .12em;
  font-size: clamp(.62rem, 2.9vw, .72rem);
  color: rgba(255, 217, 142, .92);
}
.gift-card-name:empty { display: none; }
.gift-copy { margin: 1.4rem auto 0; display: flex; }
.gift-copy-icon { width: 1em; height: 1em; }
.gift-copy.is-done { background: linear-gradient(135deg, var(--gold), var(--peach)); }
p:has(> .gift-copy) { text-align: center; }

/* ---------- footer: dawn ---------- */
.footer { position: relative; background: #151E48; }
/* bridge from the last night section into the art's flat top edge */
.footer::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 120px;
  background: linear-gradient(#0C1230, transparent);
  z-index: 1;
}
.footer-inner {
  text-align: center;
  padding: 2.8rem 1rem 3.2rem; /* a clean night credits block (parity with a1f4/f1da) */
}
.nav-logo { font-family: 'Philosopher', serif; font-weight: 700; font-size: 1.1rem; }
.nav-logo-heart { color: var(--thread); }
.footer-inner p { font-size: .8rem; color: var(--text-soft); margin-top: .3rem; }

/* ---------- music button ---------- */
.music-btn {
  position: fixed;
  right: max(.9rem, env(safe-area-inset-right), calc((100% - 480px) / 2 + .9rem));
  bottom: max(.9rem, env(safe-area-inset-bottom));
  z-index: 60;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid var(--card-line);
  background: rgba(14, 22, 51, .6);
  backdrop-filter: blur(6px);
  cursor: pointer;
  display: grid;
  place-items: center;
  opacity: 1;
  transition: opacity .6s;
}
.music-btn[hidden] { display: none; }
.music-eq { display: flex; gap: 3px; align-items: flex-end; height: 16px; }
.music-bar {
  width: 3px;
  height: 6px;
  border-radius: 2px;
  background: var(--gold);
}
.music-btn.is-playing .music-bar { animation: eq 1s ease-in-out infinite alternate; }
.music-btn.is-playing .music-bar:nth-child(2) { animation-delay: .2s; }
.music-btn.is-playing .music-bar:nth-child(3) { animation-delay: .4s; }
.music-btn.is-playing .music-bar:nth-child(4) { animation-delay: .1s; }
@keyframes eq { from { height: 5px; } to { height: 16px; } }

/* ---------- reveal-on-scroll ---------- */
.reveal { opacity: 0; transform: translateY(12px); transition: opacity .5s ease var(--d, 0s), transform .5s cubic-bezier(.22,1,.36,1) var(--d, 0s); }
.reveal--scale { transform: scale(.96) translateY(8px); }
.reveal--blur { filter: blur(6px); transition: opacity .5s ease var(--d, 0s), transform .5s cubic-bezier(.22,1,.36,1) var(--d, 0s), filter .6s ease var(--d, 0s); }
.reveal.is-visible { opacity: 1; transform: none; filter: none; }
html.is-preview .reveal { opacity: 1; transform: none; filter: none; transition: none; }

/* ---------- desktop ---------- */
/* the column is a fixed 480px at every width — no viewport-based reflow (the
   invitation must look identical on a phone and inside the desktop column) */

/* ---------- reduced motion: everything readable, nothing moving ---------- */
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal--scale, .reveal--blur { opacity: 1; transform: none; filter: none; transition: none; }
  .hero-content > * { opacity: 1; transform: none; transition: none; }
  .const-line { animation: none; stroke-dashoffset: 0; }
  .const-star-core { animation: none; transform: scale(1); opacity: 1; }
  .const-star-flare, .const-glow { animation: none; }
  .splash-kicker, .splash-names, .splash-date, .splash-btn { animation: none; opacity: 1; }
  .splash { transition: none; }
  body.is-open .hero-art { animation: none; }
  /* JS removes the splash at once under reduced motion — no lift needed */
  .splash-stars { display: none; }
  .thread-path, .thread-glow { transition: none; stroke-dashoffset: 0; }
  .music-btn.is-playing .music-bar { animation: none; height: 10px; }
  .particles { display: none; }
  .splash, .splash-art { transition: none; }
}
