@font-face {
  font-family: "Italianno";
  src: url("assets/Italianno-Regular.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}

:root {
  --paper: #f1ede4;
  --paper-deep: #e9e3d5;
  --ink: #191713;
  --wine: #6d1425;
  --sage: #606653;
  --champagne: #d4ac8c;
  --cream: #f6ead9;
  --line: rgba(25, 23, 19, 0.22);
  --line-light: rgba(246, 234, 217, 0.16);
  --serif: "Italiana", "Times New Roman", serif;
  --italianno: "Italianno", "Italiana", cursive;
  --sans: "Manrope", sans-serif;
  --mono: "DM Mono", monospace;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 30px; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
body { margin: 0; background: var(--ink); color: var(--ink); font-family: var(--sans); font-weight: 300; }
button, input, select, textarea { font: inherit; }
button, a { -webkit-tap-highlight-color: transparent; }
a { color: inherit; }
::selection { background: var(--wine); color: var(--cream); }
:focus-visible { outline: 1.5px solid var(--wine); outline-offset: 3px; }
.sheet--dark :focus-visible { outline-color: var(--champagne); }

.noise { position: fixed; inset: 0; z-index: 50; pointer-events: none; opacity: .045; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.7'/%3E%3C/svg%3E"); }

.progress { position: fixed; z-index: 60; top: 0; left: 0; right: 0; height: 2px; pointer-events: none; }
.progress i { display: block; height: 100%; width: 100%; background: var(--wine); transform: scaleX(0); transform-origin: left; }

/* ---------- Hero (sticky; the sheets slide over it) ---------- */

.hero-wrap { position: relative; height: 138svh; background: var(--paper); }

.topbar { position: absolute; z-index: 6; top: 0; left: 0; right: 0; display: flex; justify-content: space-between; align-items: center; padding: 26px 5vw; }
.wordmark { font-family: var(--serif); font-size: 21px; letter-spacing: .02em; text-decoration: none; }
.wordmark i { color: var(--wine); font-style: normal; }
.wordmark span { font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .22em; vertical-align: 2px; margin-left: 2px; }
.lang-switch { display: flex; align-items: center; gap: 7px; border: 0; background: transparent; padding: 6px 2px; cursor: pointer; font: 400 10px var(--mono); letter-spacing: .14em; color: var(--ink); }
.lang-switch i { color: var(--line); font-style: normal; }
.lang-switch span { opacity: .38; transition: opacity .3s ease, color .3s ease; }
.lang-switch span.active { opacity: 1; color: var(--wine); }

.hero { position: sticky; top: 0; height: 100svh; display: grid; overflow: hidden; background: var(--paper); }
.hero::before { content: ""; position: absolute; inset: 0; opacity: .5; background: radial-gradient(120% 80% at 82% -10%, rgba(109, 20, 37, 0.07), transparent 60%), radial-gradient(90% 70% at 8% 110%, rgba(96, 102, 83, 0.09), transparent 55%); pointer-events: none; }
.hero-inner { position: relative; z-index: 2; align-self: center; padding: 0 5vw; max-width: 1180px; width: 100%; margin: 0 auto; will-change: transform, opacity; }

.eyebrow { display: flex; align-items: center; gap: 14px; margin: 0 0 30px; font: 400 10px var(--mono); text-transform: uppercase; letter-spacing: .24em; color: var(--wine); }
.eyebrow::before { content: ""; width: 44px; height: 1px; background: var(--wine); flex: none; }

.hero-title { margin: 0; font: 400 clamp(52px, 8.6vw, 118px)/1.02 var(--serif); letter-spacing: -.012em; text-wrap: balance; }
.hero-title .line { display: block; }
.hero-title .script { font: 400 clamp(46px, 6.4vw, 88px)/1 var(--italianno); letter-spacing: normal; color: var(--wine); font-style: normal; margin: clamp(10px, 1.6vw, 22px) 0 0 clamp(4px, 8vw, 150px); }

.hero-sub { margin: 34px 0 0; max-width: 560px; font-size: 15.5px; line-height: 1.72; color: rgba(25, 23, 19, .78); }
.hero-cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 38px; }
.hero-kicker { margin: 30px 0 0; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .2em; color: var(--sage); }

/* Staggered ink-settle load choreography.
   Scoped to html.js (set by the inline script in <head>) so that a blocked or
   broken script leaves the hero visible instead of invisible. */
html.js .eyebrow, html.js .hero-title .line, html.js .hero-sub, html.js .hero-cta, html.js .hero-kicker {
  opacity: 0; transform: translateY(30px); filter: blur(7px);
  transition: opacity 1s cubic-bezier(.19, 1, .22, 1), transform 1s cubic-bezier(.19, 1, .22, 1), filter 1s cubic-bezier(.19, 1, .22, 1);
}
.eyebrow { transition-delay: .1s; }
.hero-title .line:nth-child(1) { transition-delay: .28s; }
.hero-title .line:nth-child(2) { transition-delay: .46s; }
.hero-title .line:nth-child(3) { transition-delay: .68s; }
.hero-sub { transition-delay: .92s; }
.hero-cta { transition-delay: 1.06s; }
.hero-kicker { transition-delay: 1.2s; }
body.is-loaded .eyebrow, body.is-loaded .hero-title .line, body.is-loaded .hero-sub, body.is-loaded .hero-cta, body.is-loaded .hero-kicker {
  opacity: 1; transform: translateY(0); filter: blur(0);
}

/* ---------- Preloader: floral bloom + signature draw, then hands off to the hero ---------- */

/* will-change on the animating parts keeps the 905px corner PNGs and the blurred
   glyphs on their own compositor layers instead of re-rasterising every frame.
   The whole overlay is set to hidden when it finishes, so the layers go away. */
.preloader { display: none; position: fixed; inset: 0; z-index: 100; background: var(--paper); align-items: center; justify-content: center; transition: opacity 900ms cubic-bezier(.19, 1, .22, 1); will-change: opacity; }
html.js .preloader { display: flex; }
.preloader.is-out { opacity: 0; pointer-events: none; }
/* The fixed full-screen grain layer is invisible behind the opaque preloader —
   don't make mobile composite it until the hero is actually on screen. */
html.js body:not(.is-loaded) .noise { display: none; }

.preloader-corner { position: absolute; width: min(24vw, 260px); height: auto; opacity: 0; transform: scale(.92); transition: opacity .7s cubic-bezier(.19, 1, .22, 1), transform .7s cubic-bezier(.19, 1, .22, 1); will-change: opacity, transform; }
.preloader.is-in .preloader-corner { opacity: .85; transform: scale(1); }
.preloader-corner--tl { top: 0; left: 0; }
.preloader-corner--tr { top: 0; right: 0; transform: scaleX(-1); }
.preloader.is-in .preloader-corner--tr { transform: scaleX(-1) scale(1); }
.preloader-corner--bl { bottom: 0; left: 0; transform: scaleY(-1); }
.preloader.is-in .preloader-corner--bl { transform: scaleY(-1) scale(1); }
.preloader-corner--br { bottom: 0; right: 0; transform: rotate(180deg); }
.preloader.is-in .preloader-corner--br { transform: rotate(180deg) scale(1); }

.preloader-copy { text-align: center; position: relative; z-index: 2; }
.preloader-eyebrow { margin: 0 0 18px; font: 400 10px var(--mono); letter-spacing: .24em; text-transform: uppercase; color: var(--wine); opacity: 0; transform: translateY(8px); transition: opacity .8s ease, transform .8s ease; }
.preloader.is-in .preloader-eyebrow { opacity: 1; transform: translateY(0); }

.preloader-signature { margin: 0; font: 400 clamp(56px, 9vw, 90px) var(--italianno); color: var(--wine); }
/* blur was 16px — dropped to 10px because blur radius is the single most
   expensive thing here on a phone GPU, and at this size it reads the same. */
.preloader-signature span { display: inline-block; opacity: 0; filter: blur(10px); transform: translateY(14px); transition: opacity 1s cubic-bezier(.19, 1, .22, 1), filter 1s cubic-bezier(.19, 1, .22, 1), transform 1s cubic-bezier(.19, 1, .22, 1); will-change: opacity, filter, transform; }
.preloader.is-in .preloader-signature span { opacity: 1; filter: blur(0); transform: translateY(0); }

.preloader-label { position: absolute; left: clamp(20px, 4vw, 40px); bottom: clamp(20px, 4vw, 32px); font: 400 9px var(--mono); letter-spacing: .2em; text-transform: uppercase; color: rgba(109, 20, 37, .65); opacity: 0; transition: opacity .8s ease; }
.preloader.is-in .preloader-label { opacity: 1; }

.preloader-counter { position: absolute; right: clamp(20px, 4vw, 40px); bottom: clamp(20px, 4vw, 32px); font: 400 11px var(--mono); letter-spacing: .1em; color: rgba(109, 20, 37, .75); font-variant-numeric: tabular-nums; opacity: 0; transition: opacity .8s ease; }
.preloader.is-in .preloader-counter { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .preloader, .preloader-corner, .preloader-eyebrow, .preloader-signature span, .preloader-label, .preloader-counter { transition: none !important; }
}

.hero-video { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-scrim { position: absolute; inset: 0; z-index: 0; background: rgba(241, 237, 228, .32); }
@media (prefers-reduced-motion: reduce) {
  .hero-video { display: none; }
}

.floral-corner { position: absolute; z-index: 1; width: clamp(100px, 11vw, 170px); height: auto; pointer-events: none; opacity: .8; }
.floral-corner--tl { top: 0; left: 0; }
.floral-corner--br { bottom: 0; right: 0; transform: rotate(180deg); }
.hero .floral-corner--tl { top: 58px; width: clamp(110px, 12vw, 190px); opacity: .85; }
.hero .floral-corner--br { width: clamp(110px, 12vw, 190px); opacity: .85; }

.scroll-cue { position: absolute; z-index: 2; left: 50%; bottom: max(26px, env(safe-area-inset-bottom)); transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 10px; font: 400 8px var(--mono); text-transform: uppercase; letter-spacing: .2em; text-decoration: none; color: var(--ink); opacity: .8; transition: opacity 1s ease 1.7s; }
html.js .scroll-cue { opacity: 0; }
body.is-loaded .scroll-cue { opacity: .8; }
.scroll-cue i { width: 1px; height: 36px; background: var(--wine); animation: cue-pulse 1.9s ease-in-out infinite; transform-origin: top; }
@keyframes cue-pulse { 0%, 100% { transform: scaleY(.35); opacity: .4; } 50% { transform: scaleY(1); opacity: 1; } }

/* ---------- Sheets ---------- */

.sheets { position: relative; z-index: 3; }
.sheet { position: relative; }
.sheet--paper { background: var(--paper); color: var(--ink); }
.sheet--dark { background: #1c1a16; color: #efe9dc; }
.sheet--dark { border-radius: 30px 30px 0 0; margin-top: -30px; box-shadow: 0 -30px 60px rgba(25, 23, 19, .38); z-index: 1; }
.sheet--dark + .sheet--paper { border-radius: 30px 30px 0 0; margin-top: -30px; box-shadow: 0 -30px 60px rgba(25, 23, 19, .45); z-index: 1; }

/* ---------- Atmosphere: one illustrated backdrop under sections 01-03 ---------- */

/* The backdrop is a sticky layer with a matching negative bottom margin, so it
   pins to the viewport like a fixed background but occupies no layout space and
   stops dead at the pricing sheet. background-attachment:fixed would have been
   the obvious tool and is broken on iOS Safari, hence this. */
.atmos { position: relative; z-index: 0; }
.atmos-bg { position: sticky; top: 0; z-index: 0; height: 100svh; margin-bottom: -100svh; overflow: hidden; background: var(--paper); }
.atmos .sheet { z-index: 1; }
.atmos .sheet--paper { background: transparent; }

/* The first sheet used to own this shadow — it's what sells the sheet sliding up
   over the hero. The sheets are see-through now, so the seam carries it instead. */
.atmos::before { content: ""; position: absolute; z-index: 2; top: 0; left: 0; right: 0; height: 1px; box-shadow: 0 -34px 70px rgba(25, 23, 19, .34); pointer-events: none; }

.atmos-frame { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scale(1.06); will-change: transform; }
.atmos-video { display: none; }
/* Shown once app.js has attached a source (see .is-live) — on phones too, using
   the lighter cut. The still sits underneath and shows through until the loop
   is buffered, and stays put if autoplay is refused (iOS Low Power Mode). */
html.js .atmos-video.is-live { display: block; }

/* Heavy cream wash. The artwork is atmosphere, not a picture to look at — body
   copy has to stay comfortable on top of it.
   The wash is a radial clearing rather than a flat sheet: near-opaque through
   the middle where the text column sits, thinning toward the edges so the roses
   and branches stay alive in the margins. A flat veil strong enough to protect
   the copy killed the artwork everywhere else.
   --veil-dark is driven by the scroll loop in app.js, so the light is already
   falling by the time the dark pricing sheet arrives. */
/* No global wash — the artwork is meant to read at full strength, and a veil
   strong enough to protect the copy killed it everywhere at once.
   Instead this is a soft clearing sized and placed over the TEXT COLUMN only
   (content is max-width 1180 and the copy sits left of centre), fading to fully
   transparent well before the edges, so the roses, petals and steeple stay
   crisp. --veil-dark still carries the handoff into the dark pricing sheet. */
.atmos-veil {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(0deg, rgba(28, 26, 22, var(--veil-dark, 0)), rgba(28, 26, 22, 0) 58%),
    radial-gradient(74% 60% at 42% 50%,
      rgba(241, 237, 228, .93) 0%,
      rgba(241, 237, 228, .82) 42%,
      rgba(241, 237, 228, 0) 100%);
}

/* Phones: no second video decode, and a 16:9 illustration cropped to a tall
   viewport would show a meaningless sliver — so the scene sits along the bottom
   as a horizon with open cream above it, which is where the text lands anyway. */
@media (max-width: 860px) {
  .atmos-frame {
    inset: auto 0 0 0; height: auto; object-fit: contain; transform: none;
    /* Without this the band's top edge is a hard horizontal line across the
       screen and reads as a misplaced rectangle. Fade it into the cream. */
    -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 36%);
    mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000 36%);
  }
  /* The art is a band along the bottom here, mostly clear of the copy, so it
     only needs a light wash where text actually crosses it. */
  .atmos-veil { background: linear-gradient(180deg, rgba(241, 237, 228, .40) 0%, rgba(241, 237, 228, .66) 100%); }
}

@media (prefers-reduced-motion: reduce) {
  .atmos-frame { transform: none; }
}

.steps, .templates, .why, .pricing, .contact { max-width: 1180px; margin: 0 auto; padding: clamp(86px, 11vw, 140px) 5vw; }
.steps { position: relative; overflow: hidden; }
.steps .section-head, .steps .steps-line { position: relative; z-index: 2; }

.section-head { display: grid; grid-template-columns: auto 1fr; gap: 8px 26px; align-items: baseline; border-top: 1px solid var(--line); padding-top: 26px; margin-bottom: clamp(44px, 6vw, 70px); position: relative; }
.section-head::before { content: ""; position: absolute; top: -1px; left: 0; right: 0; height: 1px; background: var(--wine); transform: scaleX(0); transform-origin: left; transition: transform 1.2s cubic-bezier(.19, 1, .22, 1) .15s; }
.section-head.is-in::before { transform: scaleX(1); }
.sheet--dark .section-head { border-top-color: var(--line-light); }
.sheet--dark .section-head::before { background: var(--champagne); }
.sec-index { margin: 0; font: 400 10px var(--mono); letter-spacing: .2em; color: var(--wine); }
.sheet--dark .sec-index { color: var(--champagne); }
.section-head h2 { margin: 0; font: 400 clamp(34px, 4.6vw, 58px)/1.05 var(--serif); letter-spacing: -.01em; }
.section-note { grid-column: 2; margin: 6px 0 0; font-size: 13.5px; color: rgba(25, 23, 19, .62); }
.sheet--dark .section-note { color: rgba(239, 233, 220, .55); }

/* scroll reveals — hidden only when JS is actually running (see html.js above) */
html.js .reveal { opacity: 0; transform: translateY(34px); filter: blur(5px); transition: opacity .95s cubic-bezier(.19, 1, .22, 1) var(--d, 0s), transform .95s cubic-bezier(.19, 1, .22, 1) var(--d, 0s), filter .95s cubic-bezier(.19, 1, .22, 1) var(--d, 0s); }
html.js .reveal.is-in { opacity: 1; transform: translateY(0); filter: blur(0); }

/* ---------- Steps (editorial index list, not an icon-card grid) ---------- */

.steps-line { position: relative; list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.steps-line li { position: relative; display: grid; grid-template-columns: clamp(52px, 7vw, 90px) 1fr; gap: clamp(18px, 3vw, 34px); align-items: baseline; padding: clamp(26px, 3.4vw, 40px) 0; border-bottom: 1px solid var(--line); }
.steps-line i { position: relative; z-index: 2; font: 400 clamp(38px, 4.4vw, 56px)/1 var(--serif); font-style: normal; color: rgba(25, 23, 19, .14); transition: color .5s ease; }
.steps-line li.is-lit i { color: var(--wine); }
.steps-line h3 { margin: 0 0 8px; font: 400 21px/1.25 var(--serif); }
.steps-line p { margin: 0; max-width: 46ch; font-size: 13.5px; line-height: 1.68; color: rgba(25, 23, 19, .72); }

/* ink line that draws itself down through the steps as you scroll */
.ink-track { position: absolute; top: 0; bottom: 0; left: clamp(26px, 3.5vw, 45px); width: 1px; background: var(--line); z-index: 1; }
.ink-fill { position: absolute; top: 0; left: 0; width: 1px; height: 100%; background: var(--wine); transform: scaleY(0); transform-origin: top; z-index: 1; }
/* The bouquet art is portrait (490x660 after trimming its transparent margins),
   so the box is sized by width and the vertical centring is done in app.js from
   the element's real height — don't hard-code a half-height here. */
.ink-dot {
  --dot-w: clamp(32px, 3.2vw, 44px);
  position: absolute; left: clamp(26px, 3.5vw, 45px); top: 0;
  width: var(--dot-w); height: auto; margin-left: calc(var(--dot-w) / -2);
  /* An ivory rose on cream paper has almost no contrast of its own, so it has
     to be seated with shadow: a tight contact shadow to define the petal edge,
     then a soft wine cast so it lifts off the sheet rather than floating. */
  filter: drop-shadow(0 1px 2px rgba(25, 23, 19, .22)) drop-shadow(0 3px 9px rgba(109, 20, 37, .20));
  opacity: 0; transition: opacity .3s ease; z-index: 3; pointer-events: none;
}
@media (max-width: 640px) {
  .ink-track, .ink-fill, .ink-dot { left: 20px; }
  .ink-dot { --dot-w: 34px; }
}
@media (max-width: 640px) {
  .steps-line li { grid-template-columns: 40px 1fr; }
  .steps-line i { font-size: 28px; }
}

/* ---------- Templates ---------- */

.template-grid { list-style: none; margin: 0; padding: 0 0 clamp(0px, 3vw, 40px); display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: clamp(24px, 3.2vw, 44px); }
.template-card a { display: block; text-decoration: none; transition: transform .6s cubic-bezier(.19, 1, .22, 1); }
.template-card a:hover { transform: translateY(-7px); }
.template-card figure { margin: 0; padding: 11px; background: #faf6ee; border: 1px solid rgba(25, 23, 19, .24); box-shadow: 0 18px 44px rgba(25, 23, 19, .13); overflow: hidden; transition: box-shadow .6s ease; }
.template-card a:hover figure { box-shadow: 0 30px 60px rgba(25, 23, 19, .2); }
.template-card figure > img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; transform: scale(1.09); will-change: transform; }
.card-meta { padding: 17px 4px 0; }
.card-tag { margin: 0 0 8px; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .2em; color: var(--wine); }
.card-names { margin: 0 0 10px; font: 400 26px/1.1 var(--serif); letter-spacing: .01em; }
.card-names i { color: var(--wine); font-style: italic; font-size: .82em; }
.card-open { margin: 0; display: flex; align-items: center; gap: 7px; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .18em; color: rgba(25, 23, 19, .65); }
.card-open i { font-style: normal; transition: transform .45s cubic-bezier(.19, 1, .22, 1); }
.template-card a:hover .card-open { color: var(--wine); }
.template-card a:hover .card-open i { transform: translateX(5px); }
@media (min-width: 900px) {
  .template-card:nth-child(2) { transform: translateY(38px); }
  html.js .template-card:nth-child(2).reveal { transform: translateY(72px); }
  html.js .template-card:nth-child(2).reveal.is-in { transform: translateY(38px); }
}
.templates-note { margin: clamp(30px, 4vw, 54px) 0 0; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .2em; color: var(--sage); }

/* ---------- Why (trust / differentiators) ---------- */

.why-list { list-style: none; margin: 0 0 clamp(34px, 4.6vw, 54px); padding: 0; border-top: 1px solid var(--line); max-width: 780px; }
.why-row { display: grid; grid-template-columns: 130px 1fr; gap: 8px 30px; padding: 20px 0; border-bottom: 1px solid var(--line); }
.why-label { font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .18em; color: var(--wine); padding-top: 3px; }
.why-value { font-size: 14.5px; line-height: 1.62; color: rgba(25, 23, 19, .8); }
@media (max-width: 640px) {
  .why-row { grid-template-columns: 1fr; gap: 6px; }
}
.why-anchor { max-width: 62ch; margin: 0 0 22px; font: 400 17px/1.6 var(--serif); color: rgba(25, 23, 19, .82); }
.why-sign { margin: 0; font: 400 30px var(--italianno); color: var(--wine); }

/* ---------- Marquee (top of the dark sheet) ---------- */

.marquee { display: flex; overflow: hidden; gap: 0; padding: 26px 0; border-bottom: 1px solid var(--line-light); user-select: none; }
.marquee-track { display: flex; align-items: center; gap: 34px; padding-right: 34px; flex: none; animation: marquee 30s linear infinite; }
.marquee-track span { font: 400 clamp(30px, 3.4vw, 44px)/1 var(--italianno); color: var(--champagne); white-space: nowrap; }
.marquee-track i { font: 300 12px var(--mono); color: rgba(239, 233, 220, .35); font-style: normal; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-100%); } }

/* ---------- Pricing (a rate list, not a 3-card SaaS grid) ---------- */

.price-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid rgba(246, 234, 217, .18); }
/* minmax(0,1fr), not the default auto: an auto track is sized by its content's
   max-content width, so the .includes grid below resolved its auto-fit columns
   against 708px and overflowed a 390px phone — with the excess unreachable,
   which silently hid half of every tier's feature list. */
.price-row { padding: clamp(28px, 3.6vw, 46px) 0; border-bottom: 1px solid rgba(246, 234, 217, .18); display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(16px, 2.4vw, 26px); }
.price-row-top { display: flex; align-items: baseline; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.price-row-top h3 { margin: 0; font: 400 clamp(24px, 2.6vw, 29px) var(--serif); letter-spacing: .01em; }
.price { margin: 0; font: 400 clamp(32px, 3.2vw, 42px)/1 var(--serif); color: var(--champagne); }
.includes { list-style: none; margin: 0; padding: 0; min-width: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 4px clamp(24px, 3vw, 44px); max-width: 900px; }
.includes li { padding: 7px 0; font-size: 13.5px; line-height: 1.55; color: rgba(239, 233, 220, .78); }
.price-row-foot { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.price-badge { margin: 0; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .2em; color: var(--champagne); }

.price-row--featured { border-left: 2px solid var(--champagne); padding-left: clamp(18px, 2.4vw, 30px); margin-left: clamp(-30px, -2.4vw, -18px); }
.price-row--featured .price-row-top h3 { color: var(--champagne); }
.price-row--featured .includes li { color: rgba(246, 234, 217, .95); }

/* ---------- Contact ---------- */

/* Not sticky like .atmos-bg: this artwork has a strong bottom-heavy structure
   (the laid table) that needs to line up with the section, not drift past it. */
#contact { overflow: hidden; }
.contact-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.contact-bg > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 100%; }
/* Form inputs are the most fragile text on the page — thin underlines, 9px
   labels, placeholders at 34% opacity. The clearing sits left, over the form
   column, and fades out before the ornate edges. */
.contact-veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(241, 237, 228, .88) 0%, rgba(241, 237, 228, .30) 34%, rgba(241, 237, 228, 0) 100%),
    radial-gradient(58% 62% at 34% 52%,
      rgba(241, 237, 228, .94) 0%,
      rgba(241, 237, 228, .84) 45%,
      rgba(241, 237, 228, 0) 100%);
}
.contact { position: relative; z-index: 1; }
/* A 16:9 scene cropped to a phone shows an arbitrary vertical slice, so the
   composition can't be aimed at the copy the way it can on desktop — the wash
   has to do the work instead. */
@media (max-width: 860px) {
  .contact-veil { background: linear-gradient(180deg, rgba(241, 237, 228, .86) 0%, rgba(241, 237, 228, .70) 40%, rgba(241, 237, 228, .64) 100%); }
}

.contact-split { display: grid; grid-template-columns: 1.2fr .8fr; gap: clamp(40px, 6vw, 90px); }

/* chosen package, carried over from the pricing section */
.form-tier { position: relative; display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 12px; margin: 0 0 30px; padding: 14px 46px 14px 16px; background: rgba(109, 20, 37, .06); border: 1px solid rgba(109, 20, 37, .3); }
.form-tier[hidden] { display: none; }
.form-tier-label { font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .16em; color: var(--wine); }
.form-tier-value { font-family: var(--serif); font-size: 19px; letter-spacing: .01em; }
/* pinned so the × never wraps onto a line of its own on narrow screens */
.form-tier-clear { position: absolute; top: 4px; right: 4px; border: 0; background: transparent; cursor: pointer; padding: 8px 12px; font-size: 19px; line-height: 1; color: rgba(25, 23, 19, .45); transition: color .3s ease; }
.form-tier-clear:hover { color: var(--wine); }
#quote-form label { display: block; margin-bottom: 24px; }
#quote-form label > span { display: block; margin-bottom: 9px; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .16em; color: rgba(25, 23, 19, .68); }
#quote-form input, #quote-form textarea { width: 100%; border: 0; border-bottom: 1px solid rgba(25, 23, 19, .35); background: transparent; padding: 9px 2px; font-size: 15px; color: var(--ink); border-radius: 0; transition: border-color .35s ease; }
#quote-form input::placeholder, #quote-form textarea::placeholder { color: rgba(25, 23, 19, .34); }
#quote-form input:focus, #quote-form textarea:focus { outline: none; border-bottom-color: var(--wine); }
#quote-form textarea { resize: vertical; min-height: 96px; }
#quote-form .btn { margin-top: 8px; }
.form-privacy { margin: 16px 0 0; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .14em; color: var(--sage); }
.form-success { margin-top: 26px; border: 1px solid var(--wine); padding: 22px 24px; }
.form-success[hidden] { display: none; }
.form-success h3 { margin: 0 0 8px; font: 400 24px var(--serif); color: var(--wine); }
.form-success p { margin: 0 0 10px; font-size: 13.5px; line-height: 1.6; color: rgba(25, 23, 19, .8); }
.form-success-links { font-size: 14px; }
.form-success-links a { color: var(--wine); text-underline-offset: 4px; }

/* Honeypot — off-screen rather than display:none, because some bots skip
   fields that are not rendered at all. Never focusable, never announced. */
.form-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Same frame as the success block, on the sage side so a failure never wears
   the celebratory wine colour. */
.form-error { margin-top: 26px; border: 1px solid var(--sage); padding: 22px 24px; background: rgba(96, 102, 83, .06); }
.form-error[hidden] { display: none; }
.form-error h3 { margin: 0 0 8px; font: 400 24px var(--serif); color: var(--sage); }
.form-error p { margin: 0 0 10px; font-size: 13.5px; line-height: 1.6; color: rgba(25, 23, 19, .8); }

#quote-form .btn[disabled] { opacity: .55; cursor: progress; }

.contact-direct { border-left: 1px solid var(--line); padding-left: clamp(28px, 4vw, 54px); align-self: start; }
.direct-heading { margin: 0 0 26px; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .2em; color: var(--sage); }
.direct-row { display: block; text-decoration: none; padding: 16px 0; border-top: 1px solid var(--line); transition: padding-left .45s cubic-bezier(.19, 1, .22, 1); }
.direct-row:last-child { border-bottom: 1px solid var(--line); }
.direct-row:hover { padding-left: 10px; }
.direct-label { display: block; font: 400 9px var(--mono); text-transform: uppercase; letter-spacing: .18em; color: var(--wine); margin-bottom: 5px; }
.direct-value { font-size: 16.5px; letter-spacing: .01em; }
.direct-row:hover .direct-value { color: var(--wine); }

/* ---------- Buttons ---------- */

.btn { display: inline-block; border: 1px solid var(--wine); background: var(--wine); color: #fffaf0; padding: 17px 30px; font-size: 10px; text-transform: uppercase; letter-spacing: .17em; text-decoration: none; cursor: pointer; transition: color .35s ease, background .35s ease, transform .35s ease; }
.btn:hover { background: transparent; color: var(--wine); transform: translateY(-2px); }
.btn-ghost { background: transparent; color: var(--wine); }
.btn-ghost:hover { background: var(--wine); color: #fffaf0; }
.sheet--dark .btn-ghost { border-color: rgba(246, 234, 217, .5); color: var(--cream); }
.sheet--dark .btn-ghost:hover { background: var(--cream); border-color: var(--cream); color: var(--ink); }
.btn-cream { background: var(--cream); border-color: var(--cream); color: var(--wine); }
.btn-cream:hover { background: transparent; color: var(--cream); }

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

footer { position: relative; z-index: 3; background: #191a17; color: rgba(255, 255, 255, .7); padding: 30px 5vw; display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; font: 300 9px var(--mono); text-transform: uppercase; letter-spacing: .12em; }
footer p { margin: 0; }
footer a { text-underline-offset: 4px; }

/* ---------- Responsive ---------- */

@media (max-width: 860px) {
  .hero-wrap { height: 128svh; }
  .hero-title .script { margin-left: 8vw; }
  .hero-sub { font-size: 14.5px; }
  .contact-split { grid-template-columns: 1fr; }
  .contact-direct { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 34px; }
  .section-head { grid-template-columns: auto 1fr; }
  .section-note { grid-column: 1 / -1; }
  .sheets .sheet:first-child, .sheet--dark, .sheet--dark + .sheet--paper { border-radius: 20px 20px 0 0; }
  .sheet--dark, .sheet--dark + .sheet--paper { margin-top: -20px; }
}

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

@media (prefers-reduced-motion: reduce) {
  /* html.js prefixes here match the scoped rules above, so these still win */
  html.js .eyebrow, html.js .hero-title .line, html.js .hero-sub, html.js .hero-cta, html.js .hero-kicker, html.js .scroll-cue { opacity: 1; transform: none; filter: none; transition: none; }
  html.js .reveal, html.js .reveal.is-in { opacity: 1; transform: none; filter: none; transition: none; }
  html.js .template-card:nth-child(2), html.js .template-card:nth-child(2).reveal, html.js .template-card:nth-child(2).reveal.is-in { transform: none; }
  .template-card:nth-child(2) { transform: none; }
  .marquee-track { animation: none; }
  .scroll-cue i { animation: none; }
  .section-head::before { transition: none; transform: scaleX(1); }
  .template-card figure > img { transform: scale(1); }
  .hero { position: relative; height: auto; min-height: 100svh; }
  .hero-wrap { height: auto; }
}
