/* =====================================================================
   WEDDING INVITATION — STYLES
   Warm cream + sage green + pastel blush.
   Change the palette in :root to re-theme everything.
   ===================================================================== */

:root {
  --cream:       #F7EFE2;   /* paper */
  --cream-soft:  #FBF6EE;   /* inputs, light text on sage */
  --cream-deep:  #EADFCB;
  --sage:        #7E9275;   /* band + RSVP background */
  --sage-deep:   #5B6E51;   /* headings, buttons */
  --sage-ink:    #4C5C44;
  --sage-light:  #B9C6AE;
  --blush:       #EBC4BE;
  --blush-deep:  #D59C95;
  --ink:         #4A463B;   /* body text, warm */
  --ink-soft:    #776F60;
  --gold:        #C2A577;

  --font-script: "Great Vibes", cursive;
  --font-serif:  "Cormorant Garamond", Georgia, serif;
  --font-sans:   "Jost", "Helvetica Neue", Arial, sans-serif;

  /* Page width: full phone width, capped on desktop.
     Garland offsets below are derived from this and from the measured
     alpha profile of the garland PNGs (see comments at .garland). */
  --pw: min(100vw, 520px);
  --gutter: 28px;
  --page-bg: #E7DDCB;        /* colour around the invitation on wide screens (intro uses the same) */

  --card-url: none;          /* set by JS from config.images.cardstock */
  --bouquets-url: none;      /* set by JS from config.images.bouquets */

  --img-grade: none;         /* colour grade applied to the decorative images */
  --paper-tint: transparent; /* warm wash multiplied over the cardstock texture */
}

/* ---------- WARM theme (config.theme = "warm") ----------
   The classic palette (:root above), nudged just a touch warmer.
   The previous candle-light palette is kept in _backup/warm-2026-10-27/. */
html[data-theme="warm"] {
  --cream:       #F8EFE1;
  --cream-soft:  #FCF6ED;
  --cream-deep:  #EBDECA;
  --sage:        #819274;
  --sage-deep:   #5E6E50;
  --sage-ink:    #4E5C43;
  --sage-light:  #BCC6AC;
  --blush:       #ECC3BB;
  --blush-deep:  #D69B92;
  --ink:         #4C4639;
  --ink-soft:    #79705F;
  --gold:        #C4A575;

  /* barely-there warmth on the decorative images */
  --img-grade: sepia(.05) saturate(1.02);
  --paper-tint: #FFFCF6;
}

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

html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }  /* no width jump when the scrollbar appears after the intro */

body {
  margin: 0;
  background: var(--page-bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* no overflow on body: on iOS it breaks drawing behind the browser bars.
     Wide decorations are clipped by .invite / .intro / .flare themselves. */
}

/* Desktop only: no scrolling behind the envelope. Phones are stopped by
   touch-action on the intro (locking the body makes iOS bars solid). */
html:not(.is-touch) body.is-locked { overflow: hidden; }

/* iOS Safari paints its top bar with the page (html) background colour. It is the same light
   paper colour during the envelope and on the site afterwards, so the bar never changes. */
html.is-intro,
html.is-intro body { background: var(--intro-bar, var(--cream)); }

/* On phones the invitation is full width: give the page the paper colour, so the strip
   behind the browser bars (and the overscroll bounce) blends in instead of showing a cut */
@media (max-width: 560px) {
  html, body { background: var(--cream); }
}

img { display: block; max-width: 100%; user-select: none; -webkit-user-drag: none; }
button { font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* =====================================================================
   1. INTRO
   ===================================================================== */

/* iOS 26 Safari clips position: fixed layers at its toolbars and paints the toolbars
   solid. The intro only exists while the page sits at the very top (scroll is locked),
   so it is positioned absolutely on the page instead: it then runs behind the toolbars,
   edge to edge. Height = the LARGE viewport, i.e. including the area under the bars. */
.intro {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  height: var(--screen-h, 100lvh);   /* exactly the hero height (see --screen-h) */
  z-index: 60;
  touch-action: none;            /* the page behind must not scroll while the envelope is shown */
  overscroll-behavior: none;
  background: var(--page-bg);       /* same as the page around the invitation: no change at the hand-over */
  overflow: hidden;
}

.intro.is-gone { display: none; }

/* Wide screens used to show a blurred copy of the poster on the sides; now the sides are
   the plain page colour, exactly like the site after the intro (kept here, switched off) */
.intro::before {
  display: none;
  content: "";
  position: absolute;
  inset: -40px;
  background: var(--intro-bg, none) center / cover;
  filter: blur(30px) saturate(.9);
  opacity: .6;
}

.intro__stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  height: 100%;
  max-width: var(--pw);               /* same width as the page, so the last video frame = the hero */
  transform: translate(-50%, -50%);
  overflow: hidden;
  container-type: size;               /* lets the hint sit relative to the envelope in the cover-fitted poster */
}

/* Phones (portrait): the envelope always fills the whole screen, edge to edge */
@media (max-aspect-ratio: 3 / 4) {
  .intro__stage { max-width: none; }
}

.intro__poster,
.intro__final,
.intro__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Sharp hero still over the video; its opacity follows the video time (app.js, intro.detailFade) */
.intro__final { opacity: 0; will-change: opacity; pointer-events: none; }

/* Poster sits on top of the (identical) first video frame and fades away once playback starts */
.intro__poster { z-index: 1; transition: opacity .35s ease; }
.intro.is-rolling .intro__poster { opacity: 0; }

.intro__tap {
  position: absolute;
  inset: 0;
  z-index: 2;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.intro.is-playing .intro__tap { pointer-events: none; }

.intro__hint {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: calc(7vh + env(safe-area-inset-bottom, 0px));   /* fallback for old browsers */
  transform: translateX(-50%);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 20px 11px 16px;
  border-radius: 999px;
  background: rgba(251, 246, 238, .86);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  box-shadow: 0 8px 24px -10px rgba(76, 92, 68, .45);
  color: var(--sage-ink);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity .4s ease;
}

/* ~30px under the envelope. The poster is 9:16 and object-fit: cover, so its rendered height is
   max(stage height, stage width * 16/9) and it is centred; the envelope's bottom edge sits at
   66% of the poster height (--env-bottom — change it if the poster changes) */
@supports (width: 1cqh) {
  .intro__hint {
    --env-bottom: .66;
    bottom: auto;
    top: calc(50% + (var(--env-bottom) - .5) * max(100cqh, 100cqw * 16 / 9) + 30px);
  }
}

.intro__hint-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--sage);
  animation: pulse 1.8s ease-out infinite;
}

.intro.is-playing .intro__hint { opacity: 0; }

@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(126, 146, 117, .55); }
  100% { box-shadow: 0 0 0 14px rgba(126, 146, 117, 0); }
}

/* ---------- Light flare transition ---------- */

.flare {
  position: absolute;            /* same reason as .intro; it only plays at the top of the page */
  overflow: hidden;              /* the growing glow must not widen the page (sideways scroll) */
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  height: var(--screen-h, 100lvh);
  z-index: 70;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}

.flare__glow,
.flare__leak,
.flare__veil { position: absolute; inset: 0; }

/* Soft warm bloom where the card comes out of the envelope — no hard edges, no rays */
.flare__glow {
  will-change: transform, opacity;
  background: radial-gradient(ellipse 85% 65% at 50% 44%,
    rgba(255, 252, 244, 1) 0%,
    rgba(255, 246, 228, .92) 22%,
    rgba(252, 236, 214, .62) 44%,
    rgba(247, 226, 208, .26) 66%,
    rgba(247, 226, 208, 0) 100%);
  transform: scale(.5);
  opacity: 0;
}

/* Daylight seeping in from the top, like a window being opened */
.flare__leak {
  background:
    radial-gradient(ellipse 90% 55% at 70% -8%, rgba(255, 238, 205, .85) 0%, rgba(255, 238, 205, 0) 70%),
    linear-gradient(to bottom, rgba(255, 247, 232, .55) 0%, rgba(255, 247, 232, 0) 65%);
  opacity: 0;
}

.flare__veil { background: var(--cream-soft); opacity: 0; }

/* ---------- Floating petals ---------- */

/* Inside the page (not fixed): scrolls natively with it; JS adds the slower drift */
.invite > .petals {
  position: absolute;
  inset: 0;
  z-index: 30;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
}

.petal {
  position: absolute;
  top: 0;
  left: 0;
  width: 30px;
  height: 30px;
  background-size: 200% 200%;
  background-repeat: no-repeat;
  will-change: transform;
}

/* Fallback petal shape when no sprite sheet is available */
.petal.is-css {
  border-radius: 80% 0 80% 0;
  background: linear-gradient(135deg, #F6DAD5, var(--blush-deep));
  opacity: .8;
}

.petal.is-css.is-leaf {
  border-radius: 0 80% 0 80%;
  background: linear-gradient(135deg, #D6DECB, var(--sage));
}

/* =====================================================================
   2. INVITATION — page frame
   ===================================================================== */

#smooth-wrapper { overflow: hidden; }

.invite {
  position: relative;
  width: var(--pw);
  margin: 0 auto;
  background-color: var(--cream);
  background-image: var(--card-url);      /* seamless cardstock tile, set by JS */
  background-size: 560px 560px;
  background-repeat: repeat;
  box-shadow: 0 0 70px rgba(76, 92, 68, .16);
  overflow: hidden;
  opacity: 0;
}

.invite.is-visible { opacity: 1; }

/* Warm wash over the cardstock (multiply keeps the texture, adds the candle-light tone) */
html[data-theme="warm"] .invite,
html[data-theme="warm"] .hero__fade { background-color: var(--paper-tint); background-blend-mode: multiply; }

/* Same golden-hour grade on every decorative image (static, so it costs nothing while scrolling) */
.garland, .hero__front, .vine img, .plan__icon, .footer__rings, .plan__bouquets { filter: var(--img-grade); }

.invite > * { position: relative; z-index: 1; }

/* ---------- Hero ---------- */

.hero { position: relative; }

/* Full screen height on every device (the photo is cropped to fit) */
.hero__media {
  position: relative;
  height: 100vh;
  height: var(--screen-h, 100lvh);  /* SAME height as the intro → last video frame and hero line up exactly */
  overflow: hidden;
}

/* Soft fade of the photo into the paper. The overlay is the SAME cardstock texture as
   the page (tile lined up with the page), revealed by a gradient mask: the photo melts
   into the paper with no visible line. The overlay itself never moves, so its mask
   is not re-painted while the photo slides (parallax). */
.hero__fade {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 7%;
  /* seamless intro: 0 at the hand-over, fades in as you scroll (see app.js). A real element whose
     opacity is tweened stays on the GPU; a CSS variable on the hero re-styled and re-painted it every frame */
  will-change: opacity;
  background-color: var(--cream);
  background-image: var(--card-url);
  background-size: 560px 560px;
  background-repeat: repeat;
  background-position: 0 calc(-93vh);          /* fallback */
  background-position: 0 calc(var(--screen-h, 100lvh) * -.93);   /* = top of this overlay (100% - 7% height) in the page tile grid */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.55) 50%, rgba(0,0,0,.92) 100%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.55) 50%, rgba(0,0,0,.92) 100%, #000 100%);
  pointer-events: none;
  z-index: 1;
}

.hero__img {
  width: 100%;
  height: 100%;                  /* exactly the video's last frame; the parallax only moves it down */
  max-width: none;
  object-fit: cover;
  object-position: 50% 50%;      /* same framing as the intro video (both object-fit: cover, centred) */
  transform-origin: 50% 60%;
  will-change: transform;
  backface-visibility: hidden;
}

.hero.is-empty .hero__media { display: none; }
.hero.is-empty { padding: 90px 0 50px; }

/* Tiny drifting light specks in the sky */
.hero__dust { position: absolute; inset: 0 0 40% 0; pointer-events: none; overflow: hidden; }

.hero__dust i {
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 250, 236, 1), rgba(255, 244, 220, 0) 70%);
  box-shadow: 0 0 8px 2px rgba(255, 246, 226, .6);
  animation: dust 9s ease-in-out infinite;
  will-change: transform, opacity;
}

@keyframes dust {
  0%, 100% { transform: translate(0, 0); opacity: 0; }
  20%      { opacity: .9; }
  50%      { transform: translate(14px, -26px); opacity: .6; }
  80%      { opacity: .9; }
}

.hero__names {
  position: absolute;
  left: 0;
  right: 0;
  top: 10.5%;
  z-index: 2;
  text-align: center;
  pointer-events: none;
}

.hero.is-empty .hero__names { position: relative; top: 0; }

/* Names painted into the hero image: keep the HTML only for screen readers / SEO,
   and let clouds + specks fade in after the video hands over (see heroIntro) */
.hero-text-in-image .hero__names {
  position: absolute !important;
  width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.hero-text-in-image .hero__clouds,
.hero-text-in-image .hero__dust { display: none; }   /* nothing extra may appear over the hero after the video */
.hero-text-in-image .hero__fade { opacity: 0; }

/* Clouds: soft blurred blobs, drifted by GSAP (transform only) */
.hero__clouds { position: absolute; inset: 0 0 45% 0; pointer-events: none; }

.cloud {
  position: absolute;
  display: block;
  border-radius: 50%;
  background:
    radial-gradient(closest-side at 30% 60%, rgba(255, 252, 245, .95), rgba(255, 252, 245, 0)),
    radial-gradient(closest-side at 62% 45%, rgba(255, 250, 240, .9), rgba(255, 250, 240, 0)),
    radial-gradient(closest-side at 80% 65%, rgba(255, 252, 245, .8), rgba(255, 252, 245, 0));
  filter: blur(6px);
  opacity: .75;
  will-change: transform;
}

.cloud--1 { width: 70%; height: 16%; top: 30%; left: -20%; }
.cloud--2 { width: 55%; height: 12%; top: 48%; left: 55%; opacity: .55; }
.cloud--3 { width: 80%; height: 18%; top: 8%;  left: 30%; opacity: .45; }

/* Foreground flowers over the bottom of the scene (fastest parallax layer) */
/* Slim hanging garland on the seam: its flower line (15% of its height) sits
   just above the end of the hero, the tendrils hang over the invitation paper */
.hero__front {
  position: absolute;
  z-index: 3;
  left: 50%;
  /* Flower line sits just BELOW the hero: the first screen shows only the photo and the
     names; the garland appears as soon as you start scrolling */
  top: 100%;                     /* fully below the first screen: not even a leaf shows at the start */
  width: calc(var(--pw) * 1.18);
  max-width: none;
  margin-left: calc(var(--pw) * -.59);
  pointer-events: none;
}

.hero.is-empty .hero__front { display: none; }

.hero__names h1 {
  position: relative;
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: calc(var(--pw) * .2);
  line-height: .92;
  color: var(--sage-deep);
  text-shadow: 0 2px 20px rgba(251, 246, 238, .95), 0 0 3px rgba(251, 246, 238, .8);
}

.hero__bride,
.hero__groom { display: block; }

.hero__amp {
  position: absolute;
  left: 50%;
  top: -14%;
  transform: translateX(-50%);
  font-family: var(--font-script);
  font-size: calc(var(--pw) * .5);
  line-height: 1;
  color: rgba(213, 156, 149, .32);
}

.hero__date {
  margin: 10px 0 0;
  font-family: var(--font-serif);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: .42em;
  padding-left: .42em;
  color: var(--sage-ink);
  text-shadow: 0 1px 12px rgba(251, 246, 238, .95);
}

/* ---------- Paper sections ---------- */

.paper {
  position: relative;
  display: flow-root;        /* stops a first-child garland margin from collapsing */
  padding-left: var(--gutter);
  padding-right: var(--gutter);
  text-align: center;
}

/* Florals along the page edge — asymmetric, soft ends (never a hard cut) */
/* The rose branch, stood upright along the page edge.
   The source image (config: images.branch) has the branch on a ~27° diagonal;
   the inner <img> is rotated around the middle of the branch so it runs straight
   down, and that middle point is placed on the wrapper's centre. The wrapper is
   centred on the page edge, so about half of the branch is hidden by the edge.
   GSAP animates the wrapper (reveal + parallax), CSS rotates the image. */
.vine {
  --vw: calc(var(--pw) * .74);      /* branch image width; the branch itself is ~1.05x this long */
  --in: calc(var(--pw) * .03);      /* how far the branch's middle sits inside the edge */
  position: absolute;
  z-index: 0;
  width: var(--vw);
  height: calc(var(--vw) * 1.1);
  pointer-events: none;
}

.vine img {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--vw);
  max-width: none;
  /* middle of the branch in the source image: 64% across, 46.5% down (image is 1520x2688) */
  margin-left: calc(var(--vw) * -.64);
  margin-top: calc(var(--vw) * -.822);
  transform-origin: 64% 46.5%;
}

.vine--right { right: calc(var(--vw) * -.5 + var(--in)); }
.vine--right img { rotate: -27deg; }              /* straight down, roses on top */

.vine--left { left: calc(var(--vw) * -.5 + var(--in)); }
.vine--left img { rotate: 153deg; }               /* turned around: roses at the bottom */

.vine--inv      { top: 8%;  --vw: calc(var(--pw) * .62); }
/* right branch: low in the plan section, in the empty space between "Proslava" and the countdown */
.vine--plan-top { top: auto; bottom: calc(var(--pw) * -.42); }
.vine--plan-low { top: 50%; }

.ornament {
  display: block;
  width: 150px;
  height: 18px;
  margin: 0 auto 18px;
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.1;
  stroke-linecap: round;
}

.invitation { padding-top: calc(var(--pw) * .34); padding-bottom: calc(var(--pw) * .36); }  /* room for the hero's foreground flowers */

.invitation__text {
  max-width: 30ch;
  margin: 0 auto;
  font-family: var(--font-serif);
  font-size: 22px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
  text-wrap: balance;
}

.invitation__text strong { font-weight: 700; color: var(--sage-ink); }

/* ---------- Garlands ----------
   Measured alpha profiles (share of opaque pixels per row):
   - garland-band: solid flowers from 44% to 79% of its height, fades out by 95%
   - garland-hang: solid flowers from 9% to 21% of its height, tendrils below
   The garland is 1.18 x page width; its height is 0.506 x page width.
   Offsets place the section boundary inside the solid flower band. */

.garland {
  position: relative;
  z-index: 2;
  display: block;
  width: calc(var(--pw) * 1.18);
  max-width: none;
  margin-left: calc(var(--pw) * -.09);
  pointer-events: none;
}

/* Boundary at 55% of the garland height */
.garland--band { margin-top: calc(var(--pw) * -.278); margin-bottom: 0; }

/* Boundary at 15% of the garland height; tendrils hang over the next section */
.garland--hang {
  margin-top: calc(var(--pw) * -.076);
  margin-bottom: calc(var(--pw) * -.12);
  transform-origin: 50% 0;
}

.paper > .garland--hang { margin-left: calc(var(--pw) * -.09 - var(--gutter)); }

/* Flipped hanging garland closes the RSVP section: boundary at 85% (= 15% flipped) */
.garland--flip {
  scale: 1 -1;                 /* mirror in place; separate from `transform`, which GSAP animates */
  transform-origin: 50% 50%;   /* the hang rule sets a top origin, which would flip it upward */
  margin-top: calc(var(--pw) * -.2);
  margin-bottom: calc(var(--pw) * -.076);
}

/* ---------- Sage band ---------- */

/* Sage sections: very soft radial light in the middle, slightly deeper edges,
   with the cardstock texture multiplied on top so they read as paper, not flat colour */
.band,
.rsvp {
  background:
    radial-gradient(120% 75% at 50% 38%, rgba(255, 248, 232, .13) 0%, rgba(255, 248, 232, 0) 62%),
    radial-gradient(150% 110% at 50% 50%, rgba(38, 44, 28, 0) 58%, rgba(38, 44, 28, .12) 100%),
    var(--sage);
}

.band {
  position: relative;
  display: flow-root;
  color: var(--cream-soft);
  text-align: center;
}

.band::after,
.rsvp::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--card-url) 0 0 / 560px 560px repeat;
  mix-blend-mode: multiply;     /* paper fibres show through the green */
  opacity: .9;
  pointer-events: none;
}

.band__inner {
  position: relative;
  z-index: 3;
  padding: 30px var(--gutter) calc(var(--pw) * .1 + 30px);
}

.band__month {
  margin: 0;
  padding: 0 .15em;                 /* room for the script swashes */
  font-kerning: normal;
  font-family: var(--font-script);
  font-size: calc(var(--pw) * .22);
  line-height: 1;
}

.band__year {
  margin: 4px 0 26px;
  font-family: var(--font-serif);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: .3em;
  padding-left: .3em;
}

.week {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  max-width: 380px;
  margin: 0 auto 30px;
}

.week__day { display: flex; flex-direction: column; align-items: center; gap: 2px; }

.week__name { font-size: 12px; letter-spacing: .08em; opacity: .85; }

.week__num {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 30px;
  font-weight: 600;
  line-height: 1;
}

.week__day.is-active .week__num { color: var(--sage-deep); }

.week__heart {
  position: absolute;
  inset: -2px;
  z-index: -1;
  background: var(--cream-soft);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 21.3 10.6 20C5.4 15.4 2 12.3 2 8.5 2 5.4 4.4 3 7.5 3c1.7 0 3.4.8 4.5 2.1C13.1 3.8 14.8 3 16.5 3 19.6 3 22 5.4 22 8.5c0 3.8-3.4 6.9-8.6 11.5L12 21.3z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 21.3 10.6 20C5.4 15.4 2 12.3 2 8.5 2 5.4 4.4 3 7.5 3c1.7 0 3.4.8 4.5 2.1C13.1 3.8 14.8 3 16.5 3 19.6 3 22 5.4 22 8.5c0 3.8-3.4 6.9-8.6 11.5L12 21.3z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Calendar button + menu */
.cal { position: relative; display: inline-block; }

/* The band (with the seam garland at its bottom) sits above the plan section; inside the band
   the calendar menu (z 10 within .band__inner) is above that garland */
.invite > .band { z-index: 2; }

.band > .garland--seam {
  position: absolute;
  left: calc(var(--pw) * -.09);
  top: calc(100% - var(--pw) * .076);   /* same spot as before: 7.6% of the page width above the seam */
  margin: 0;
  z-index: 2;
}

.cal__menu {
  position: absolute;
  z-index: 10;
  left: 50%;
  top: calc(100% + 10px);
  transform: translateX(-50%);
  min-width: 240px;
  padding: 6px;
  border-radius: 18px;
  background: var(--cream-soft);
  box-shadow: 0 18px 40px -14px rgba(40, 50, 35, .45);
  text-align: left;
  animation: menuIn .2s ease;
}

@keyframes menuIn {
  from { opacity: 0; transform: translate(-50%, -6px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

.cal__opt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 12px;
  color: var(--ink);
  font-size: 15px;
  text-decoration: none;
}

.cal__opt:hover { background: rgba(185, 198, 174, .3); }
.cal__opt svg { width: 22px; height: 22px; flex: none; }

/* ---------- Pills (buttons) ---------- */

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  font-family: var(--font-serif);
  font-size: 19px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform .25s ease, box-shadow .25s ease, background .25s ease;
}

.pill svg { width: 22px; height: 22px; flex: none; }
.pill:active { transform: scale(.97); }
.pill:focus-visible { outline: 2px solid var(--blush-deep); outline-offset: 3px; }

.pill--light {
  background: var(--cream-soft);
  color: var(--sage-ink);
  box-shadow: 0 8px 22px -10px rgba(40, 50, 35, .5);
}

.pill--light:hover { transform: translateY(-2px); box-shadow: 0 14px 26px -12px rgba(40, 50, 35, .55); }

.pill--sage {
  position: relative;
  overflow: hidden;
  min-width: 200px;
  background: var(--sage-deep);
  color: var(--cream-soft);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .16), 0 10px 20px -12px rgba(76, 92, 68, .8);
}

/* Soft light sweep across the map buttons */
.pill--sage::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255, 250, 238, .28), transparent);
  transform: translateX(-150%) skewX(-18deg);
  animation: sweep 5.5s ease-in-out infinite;
  will-change: transform;
}

@keyframes sweep {
  0%, 70% { transform: translateX(-150%) skewX(-18deg); }
  100%    { transform: translateX(330%) skewX(-18deg); }
}

.pill--sage:hover { background: var(--sage-ink); transform: translateY(-2px); }

.pill--outline {
  flex: none;
  min-height: 46px;
  padding: 0 18px;
  background: transparent;
  color: var(--cream-soft);
  box-shadow: inset 0 0 0 1.5px var(--cream-soft);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
}

.pill--outline:hover { background: rgba(251, 246, 238, .12); }

.pill--submit {
  width: 100%;
  background: var(--cream-soft);
  color: var(--sage-ink);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: .06em;
  box-shadow: 0 10px 24px -12px rgba(30, 40, 25, .6);
}

.pill--submit[disabled] { opacity: .65; cursor: wait; }

/* ---------- Plan dana ---------- */

/* top padding = the room the hanging garland used to take in this section
   (garland height .5057pw minus its -.076pw / -.12pw overlaps) */
.plan { padding-top: calc(var(--pw) * .3097); padding-bottom: 20px; }   /* no overflow clip: the garland must reach up into the band */

/* Faint watercolor bouquets in the background of the long plan section */
.plan__bouquets {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 0;
  aspect-ratio: 9 / 16;
  background: var(--bouquets-url) center / cover no-repeat;
  opacity: .9;
  pointer-events: none;
}

.plan__bouquets--top {
  top: 8%;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 70%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 70%, transparent);
}

.plan__bouquets--bottom {
  bottom: 0;
  scale: -1 -1;               /* mirrored copy so the two halves never look repeated */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 25%, #000 75%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 25%, #000 75%, transparent);
}

.plan__title {
  position: relative;
  z-index: 1;
  margin: 0 0 14px;
  font-weight: 400;
  line-height: 1;
  color: var(--sage-deep);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.plan__small {
  font-family: var(--font-serif);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: .5em;
  padding-left: .5em;
  text-transform: uppercase;
}

.plan__script {
  margin-top: -6px;
  padding: 0 .15em .1em;
  font-family: var(--font-script);
  font-size: calc(var(--pw) * .24);
}

.plan__list { position: relative; z-index: 1; list-style: none; margin: 0; padding: 0; }

.plan__item { padding: 10px 0 38px; }

/* Vertical gold connector between plan items: drawn as you scroll */
.plan__link {
  position: relative;
  display: block;
  width: 2px;
  height: 64px;
  margin: 0 auto 18px;
}

.plan__link::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(var(--gold) 50%, transparent 0) 0 0 / 2px 7px repeat-y;
  opacity: .75;
  transform-origin: 50% 0;
  transform: scaleY(var(--draw, 1));
}

.plan__link i {
  position: absolute;
  left: 50%;
  bottom: -6px;
  width: 9px;
  height: 9px;
  border: 1.5px solid var(--gold);
  border-radius: 50%;
  background: var(--cream-soft);
  transform: translateX(-50%) scale(var(--dot, 1));
}

/* Icon "paints itself": watercolor wash spreads, then the illustration develops inside a soft mask */
.plan__art {
  position: relative;
  width: 160px;
  height: 160px;
  margin: 0 auto 4px;
}

.plan__wash {
  position: absolute;
  inset: 4%;
  border-radius: 46% 54% 50% 50% / 55% 45% 55% 45%;
  background:
    radial-gradient(circle at 38% 40%, rgba(235, 196, 190, .55), transparent 62%),
    radial-gradient(circle at 64% 62%, rgba(185, 198, 174, .55), transparent 60%);
  filter: blur(10px);
  opacity: .8;
}

/* (the round "developing" mask was removed: it repainted every frame and made the reveal choppy) */
.plan__art .plan__icon { position: relative; }

.plan__time .split-char { display: inline-block; }

.plan__icon {
  width: 160px;
  height: 160px;
  object-fit: contain;
}

.plan__name {
  margin: 0 0 8px;
  font-family: var(--font-serif);
  font-size: 32px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--sage-deep);
}

/* Optional small line under the name (events[].note), e.g. "u restoranu" */
.plan__note {
  margin: -4px 0 10px;
  font-family: var(--font-serif);
  font-size: 19px;
  font-style: italic;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink-soft);
}

.plan__time { margin: 0; font-family: var(--font-serif); font-size: 22px; font-weight: 700; color: var(--ink); }
.plan__place { margin: 0; font-family: var(--font-serif); font-size: 21px; font-weight: 500; line-height: 1.3; }
.plan__address { margin: 2px 0 18px; font-size: 14px; color: var(--ink-soft); }

/* ---------- Countdown ---------- */

.countdown { padding-top: 30px; padding-bottom: calc(var(--pw) * .36); }

.countdown__title {
  margin: 0 0 22px;
  font-family: var(--font-serif);
  font-size: 38px;
  font-weight: 700;
  color: var(--sage-deep);
}

.countdown__row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  max-width: 380px;
  margin: 0 auto;
}

.ring { position: relative; display: flex; flex-direction: column; align-items: center; }

.ring svg { width: 100%; max-width: 78px; transform: rotate(-90deg); overflow: visible; }

.ring__track { fill: var(--sage); stroke: rgba(251, 246, 238, .35); stroke-width: 4; }

.ring__bar {
  fill: none;
  stroke: var(--cream-soft);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-dasharray: 226.2;
  stroke-dashoffset: 226.2;
}

.ring__num {
  position: absolute;
  top: 0;
  width: 100%;
  max-width: 78px;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  color: var(--cream-soft);
  font-family: var(--font-serif);
  font-size: 26px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ring small {
  margin-top: 6px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.countdown__done { font-family: var(--font-script); font-size: 46px; color: var(--blush-deep); margin: 0; }

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

.rsvp { position: relative; display: flow-root; color: var(--cream-soft); text-align: center; }

.rsvp__inner { position: relative; z-index: 3; padding: 34px var(--gutter) 20px; }

.rsvp__title {
  margin: 0 0 14px;
  font-family: var(--font-serif);
  font-size: 44px;
  font-weight: 700;
  line-height: 1.05;
}

.rsvp__deadline { margin: 0 0 14px; font-size: 17px; }
.rsvp__deadline strong { font-weight: 600; }
.rsvp__lead { margin: 0 auto 26px; max-width: 30ch; font-size: 16px; opacity: .92; }

.form { display: grid; gap: 16px; text-align: center; }

.input {
  width: 100%;
  min-height: 50px;
  padding: 12px 20px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  background: var(--cream-soft);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  text-align: center;
  transition: border-color .2s ease, box-shadow .2s ease;
}

.input::placeholder { color: #A79F8F; }
.input:focus { outline: none; box-shadow: 0 0 0 3px rgba(235, 196, 190, .65); }
.input.is-invalid { border-color: var(--blush-deep); box-shadow: 0 0 0 3px rgba(213, 156, 149, .5); }

.form__note { margin: 0; font-style: italic; font-family: var(--font-serif); font-size: 17px; opacity: .95; }
.form__note + .form__note { margin-top: 4px; }

.guests { display: grid; }
/* Extra guests stay folded until the "add guests" button is pressed */
.guests.is-waiting { display: none; }

.guests__open {
  justify-self: center;
  margin: -4px auto 0;
  padding: 6px 4px;
  border: 0;
  background: none;
  color: var(--cream-soft);
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 18px;
  text-decoration: underline;
  text-decoration-color: rgba(251, 246, 238, .45);
  text-underline-offset: 4px;
  cursor: pointer;
}
.guests__open:hover { text-decoration-color: currentColor; }
.guests__open:focus-visible { outline: 2px solid var(--blush); outline-offset: 4px; border-radius: 4px; }
.guests__add { display: flex; gap: 8px; margin-top: 12px; }
.guests__add .input { text-align: left; min-width: 0; }

.guests__list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; }
.guests__list:empty { display: none; }

.guests__list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 6px 6px 20px;
  border-radius: 999px;
  background: rgba(251, 246, 238, .18);
  box-shadow: inset 0 0 0 1px rgba(251, 246, 238, .35);
  text-align: left;
}

.guests__list button {
  width: 34px;
  height: 34px;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: var(--cream-soft);
  color: var(--sage-ink);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.choice { margin: 6px 0 0; padding: 0; border: 0; display: flex; justify-content: center; gap: 34px; flex-wrap: wrap; }

.choice legend {
  width: 100%;
  margin-bottom: 10px;
  padding: 0;
  font-family: var(--font-serif);
  font-size: 22px;
  font-weight: 600;
}

.choice label { display: inline-flex; align-items: center; gap: 10px; font-size: 17px; cursor: pointer; }

.choice input {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin: 0;
  border-radius: 50%;
  border: 1.5px solid var(--cream-soft);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.choice input::after {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--cream-soft);
  transform: scale(0);
  transition: transform .2s cubic-bezier(.3, 1.6, .5, 1);
}

.choice input:checked::after { transform: scale(1); }
.choice input:focus-visible { box-shadow: 0 0 0 3px rgba(235, 196, 190, .7); }

.form__error {
  margin: 0;
  padding: 8px 14px;
  border-radius: 12px;
  background: rgba(213, 156, 149, .35);
  font-size: 14px;
}

.rsvp__done h3 { margin: 0 0 6px; font-family: var(--font-serif); font-size: 30px; font-weight: 700; }
.rsvp__done p { margin: 0 0 14px; font-size: 17px; }

.rsvp__again,
.rsvp__closed {
  border: 0;
  background: none;
  color: var(--cream-soft);
  font-size: 14px;
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
  opacity: .9;
}

.rsvp__closed { text-decoration: none; font-style: italic; font-size: 17px; }

/* ---------- Footer ---------- */

.footer { padding-top: calc(var(--pw) * .1); padding-bottom: 80px; }

.footer__rings { width: 120px; margin: 0 auto 8px; }

.footer__text { margin: 0; font-family: var(--font-serif); font-style: italic; font-size: 21px; color: var(--ink-soft); }

.footer__names {
  margin: 2px 0 0;
  padding: 0 .1em;
  font-family: var(--font-script);
  /* one line, always fits: on narrow phones the names used to wrap and look off-centre */
  white-space: nowrap;
  font-size: min(52px, calc((var(--pw) - var(--gutter) * 2) / 7.2));
  line-height: 1.2;
  color: var(--sage-deep);
}

.footer__date { margin: 4px 0 0; font-size: 12px; letter-spacing: .3em; color: var(--ink-soft); }

/* ---------- Music button ---------- */

.music {
  position: fixed;
  left: max(14px, calc(50% - var(--pw) / 2 + 14px));
  bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  z-index: 40;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: rgba(91, 110, 81, .88);
  color: var(--cream-soft);
  box-shadow: 0 6px 18px -6px rgba(40, 50, 35, .6);
  cursor: pointer;
}

.music svg { width: 22px; height: 22px; }
.music .music__off { display: none; }
.music.is-muted .music__on { display: none; }
.music.is-muted .music__off { display: block; }

/* SplitText helpers */
.split-char, .split-word { display: inline-block; will-change: transform, opacity; }

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition-duration: .01ms !important; }
  .petals, .hero__dust { display: none; }
}
