/* =====================================================================
   Astra TS ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â Homepage "opens like an invitation"
   ---------------------------------------------------------------------
   Loaded AFTER astra/home-light.css. Turns the marketing page into the
   product it sells: a photographic hero the visitor re-themes per
   occasion, ivory stationery instead of flat white, gold foil rules
   between sections, and a wax seal on the hero card.

   A DELIBERATELY SEPARATE FILE. astra/styles.css and astra/home-light.css
   are shared with concurrent work on the template gallery, so nothing here
   reorganises them ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â this sheet only adds, and wins on cascade order.

   THE OCCASION CONTRACT. Everything occasion-dependent is a custom
   property set on body[data-occasion="wedding|graduation|birthday"], so
   the switcher toggles ONE attribute and never touches markup. Values
   match config('events.types') keys so the hero and the template gallery
   filter speak the same language.

   Because --hero-photo is a url() inside a custom property, only the
   occasion actually in use is ever fetched, and only at the width the
   media query selects. Relative URLs resolve against THIS file.
   ===================================================================== */

/* ---- Layout tokens -------------------------------------------------- */
/* home-light.css raised the shared rhythm tokens with !important; these bring
   them back down by roughly a third. At 1440px a section boundary was
   64 + 48 + 64 = 176px of dead space and is now 43 + 32 + 43 = 118px, which
   is the whole page tightened from one place rather than per-section. The
   higher specificity (body[data-occasion] beats :root) is what wins. */
body[data-occasion] {
  --section-padding-y: clamp(1.5rem, 0.8rem + 2.7vw, 2.7rem) !important;
  --section-gap: clamp(1.05rem, 0.5rem + 2vw, 2rem) !important;

  /* Measured from the real header by the script in home.blade.php, because
     the header's height depends on the brand name wrapping. The fallback is
     the desktop measurement, so a visitor with JS off still gets a hero that
     starts below the header rather than under it. */
  --header-h: 104px;
}

/* ---- Occasion palettes --------------------------------------------- */
body[data-occasion] {
  --hero-photo: url("home-hero-wedding-960.jpg?v=2");
  --hero-photo-focus: center 42%;

  /* Scrim colour + strength. Light photos get an ivory veil to hold the
     card away from the flowers; the navy graduation photo is deepened
     instead, which keeps its drama without darkening the source. */
  --scrim-rgb: 255, 252, 246;
  --scrim-core: 0.16;
  --scrim-top: 0.3;
  --scrim-bottom: 0.9;

  --card-tint: 253, 250, 244;
  /* 0.90 let enough of the blush photograph through that champagne gold on the
     headline card measured 4.28:1 Ã¢â‚¬â€ just under AA. 0.93 is still visibly
     translucent and buys the margin back. */
  --card-alpha: 0.93;

  --drift-anim: heroDriftFall;
  --drift-radius: 62% 38% 58% 42% / 60% 56% 44% 40%;
  --drift-w: 11px;
  --drift-h: 9px;
  --drift-a: rgba(226, 176, 172, 0.72);
  --drift-b: rgba(238, 213, 189, 0.66);
  --drift-c: rgba(233, 226, 210, 0.6);
  --drift-glow: none;
}

body[data-occasion="wedding"] {
  --ink: #23201c;
  --text: #2c2a27;
  --muted: #6f675b;
  --bg: #faf7f2;
  --bg-rgb: 250, 247, 242;
  --card: #fffdf9;
  --gold: #b89766;
  --gold-deep: #a07f4f;
  /* Measured against the translucent headline card over the blush hero, not
     against flat ivory: #8a6a3d only reached 4.42:1 there. */
  --gold-text: #82633a;
  --gold-soft: rgba(184, 151, 102, 0.4);
  --gold-tint: rgba(184, 151, 102, 0.1);
}

body[data-occasion="graduation"] {
  --hero-photo: url("home-hero-graduation-960.jpg?v=2");
  --hero-photo-focus: center 38%;

  --scrim-rgb: 10, 18, 40;
  --scrim-core: 0.1;
  --scrim-top: 0.3;
  --scrim-bottom: 0.42;

  --card-tint: 252, 250, 245;
  --card-alpha: 0.94;

  --ink: #1b2440;
  --text: #262d3f;
  /* Measured, not eyeballed: at #5d6478 the quiet "Login" link came out at
     4.32:1 against the darkest pixel the translucent header pill lets
     through from the navy photograph. This clears AA there and on the card. */
  --muted: #4f566c;
  --bg: #f7f6f2;
  --bg-rgb: 247, 246, 242;
  --card: #fffefb;
  --gold: #c2a35a;
  --gold-deep: #94762f;
  --gold-text: #7a6024;
  --gold-soft: rgba(194, 163, 90, 0.42);
  --gold-tint: rgba(194, 163, 90, 0.12);

  --drift-anim: heroDriftRise;
  --drift-radius: 50%;
  --drift-w: 6px;
  --drift-h: 6px;
  --drift-a: rgba(255, 226, 160, 0.8);
  --drift-b: rgba(255, 238, 202, 0.7);
  --drift-c: rgba(214, 226, 255, 0.6);
  --drift-glow: 0 0 10px rgba(255, 224, 156, 0.75);
}

body[data-occasion="birthday"] {
  --hero-photo: url("home-hero-birthday-960.jpg?v=2");
  --hero-photo-focus: center 46%;

  --scrim-rgb: 255, 250, 244;
  --scrim-core: 0.15;
  --scrim-top: 0.28;
  --scrim-bottom: 0.88;

  --ink: #2b2320;
  --text: #322926;
  --muted: #6d6058;
  --bg: #fdf8f1;
  --bg-rgb: 253, 248, 241;
  --card: #fffdf8;
  --gold: #e0906f;
  --gold-deep: #c2593c;
  --gold-text: #ab4529;
  --gold-soft: rgba(224, 144, 111, 0.42);
  --gold-tint: rgba(224, 144, 111, 0.11);
  --sage: #4f9d97;

  --drift-anim: heroDriftFall;
  --drift-radius: 1px;
  --drift-w: 5px;
  --drift-h: 10px;
  --drift-a: rgba(214, 168, 74, 0.85);
  --drift-b: rgba(228, 122, 96, 0.75);
  --drift-c: rgba(101, 190, 184, 0.7);
  --drift-glow: none;
}

/* Desktop swaps to the 1536px source. The 960px variant is the default so
   a phone never downloads the large one; the sources are 1536x1024, so
   1536 IS the native width and nothing is upscaled. */
@media (min-width: 61.25em) {
  body[data-occasion="wedding"] { --hero-photo: url("home-hero-wedding-1536.jpg?v=2"); }
  body[data-occasion="graduation"] { --hero-photo: url("home-hero-graduation-1536.jpg?v=2"); }
  body[data-occasion="birthday"] { --hero-photo: url("home-hero-birthday-1536.jpg?v=2"); }
}

/* =====================================================================
   PAPER AS A MATERIAL
   ===================================================================== */

/* The letterpress tile is a light ivory JPEG, so it is veiled by a flat
   wash of the canvas colour in the same shorthand rather than shipping an
   alpha PNG. 256px renders the 512px mirrored tile at half scale, which
   makes the grain fine enough to read as paper rather than pattern. */
main {
  background-image:
    linear-gradient(rgba(250, 247, 242, 0.66), rgba(250, 247, 242, 0.66)),
    url("home-paper-ivory-384.jpg");
  background-size: auto, 256px 256px;
  background-repeat: repeat;
  background-position: center top;
}

body[data-occasion="graduation"] main {
  background-image:
    linear-gradient(rgba(247, 246, 242, 0.68), rgba(247, 246, 242, 0.68)),
    url("home-paper-ivory-384.jpg");
}

body[data-occasion="birthday"] main {
  background-image:
    linear-gradient(rgba(253, 248, 241, 0.64), rgba(253, 248, 241, 0.64)),
    url("home-paper-ivory-384.jpg");
}

/* The dot-grid overlay reads as digital noise against paper. */
.page-noise { display: none !important; }
.page-glow { opacity: 0.12 !important; }

/* ---- Gold foil rule + diamond ornament between sections ------------ */
/* styles.css gives every non-hero section `content-visibility: auto`,
   which brings paint containment with it ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â anything hung above the
   padding box would be clipped, so the rule sits just inside the top
   edge and the flex gap above it does the spacing. */
main > .section {
  position: relative;
}

main > .section::before {
  content: "";
  position: absolute;
  top: 6px;
  left: 50%;
  width: min(720px, 84%);
  height: 1px;
  transform: translateX(-50%);
  background: linear-gradient(90deg, transparent, var(--gold-soft) 14%, var(--gold) 50%, var(--gold-soft) 86%, transparent);
  pointer-events: none;
}

main > .section::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 50%;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  transform: rotate(45deg);
  background: var(--gold);
  box-shadow: 0 0 0 4px var(--bg);
  pointer-events: none;
}

/* The hero closes with its own rule, so the section after it stays bare. */
main > .section:first-child::before,
main > .section:first-child::after,
main > #hero + .section::before,
main > #hero + .section::after {
  display: none;
}

/* ---- Small-caps eyebrows over the existing Inter stack ------------- */
.eyebrow {
  font-variant-caps: all-small-caps;
  font-feature-settings: "c2sc" 1, "smcp" 1;
}

/* =====================================================================
   THE HEADER FLOATS ON THE PHOTOGRAPH
   ---------------------------------------------------------------------
   Taking the header out of flow is what lets the hero photograph start at
   the very top edge of the viewport instead of below a band of flat cream.
   The header keeps its own translucent ivory pill so the nav and the CTA
   are legible over all three photographs ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â including the navy graduation
   one, where dark text straight on the image would fail AA outright.
   ===================================================================== */
body[data-occasion] .site-header {
  position: fixed;
  left: 0;
  right: 0;
  margin: 8px auto 0;
  background: rgba(255, 253, 248, 0.78);
  border: 1px solid rgba(184, 151, 102, 0.28);
  box-shadow: 0 10px 30px rgba(43, 38, 28, 0.1);
  -webkit-backdrop-filter: blur(14px) saturate(118%);
  backdrop-filter: blur(14px) saturate(118%);
}

/* Once the page has moved, the pill firms up: the content behind it is now
   ordinary page copy rather than the photograph. */
body[data-occasion].nav-scrolled .site-header {
  background: rgba(252, 249, 243, 0.94) !important;
  border-color: var(--gold-soft) !important;
}

/* Anchor targets have to clear a header that no longer occupies flow. */
body[data-occasion] #hero,
body[data-occasion] main > .section,
body[data-occasion] main > .trust-strip {
  scroll-margin-top: calc(var(--header-h) + 12px);
}

/* An 88px logo was set for a header sitting on a flat background; floating
   over a photograph it wants to be lighter, and every pixel saved here is a
   pixel the hero gets back. */
body[data-occasion] .brand--header .brand__logo { height: 64px; }
body[data-occasion] .brand--header .brand__line:first-child { font-size: 1.2rem; }

/* A wrapped nav link turned the header into three ragged lines at ~1024px
   and cost the hero 30px of height. The links keep their words together and
   the row tightens instead. */
body[data-occasion] .site-nav a { white-space: nowrap; }

@media (min-width: 981px) and (max-width: 1220px) {
  body[data-occasion] .site-nav { gap: 14px; font-size: 0.84rem; }
  body[data-occasion] .site-header { gap: 14px; }
  body[data-occasion] .brand--header .brand__logo { height: 52px; }
  body[data-occasion] .brand--header .brand__name { white-space: nowrap; }
  body[data-occasion] .brand--header .brand__line:first-child { font-size: 1.05rem; }
  body[data-occasion] .header-cta { padding: 0 14px; }
  body[data-occasion] .site-header__actions { gap: 10px; }
}

/* =====================================================================
   1. CINEMATIC HERO
   ---------------------------------------------------------------------
   TWO BOXES, ONE SECTION. `.hero__screen` is the first screen and is
   exactly 100svh: reserved header space, the two cards, the scroll cue.
   The foil rule and the feature ticker live outside it and are therefore
   the first thing a scroll reveals ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â previously they were inside the
   100svh budget and the ticker got shaved off by the bottom edge on a
   short laptop.

   Everything that makes the first screen fit is here plus the height
   tiers at the foot of this file.
   ===================================================================== */
.hero--invitation {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0;
}

.hero__screen {
  position: relative;
  z-index: 1;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  padding-top: var(--header-h);
}

/* The champagne aurora from home-light.css has a photograph in front of
   it now. */
.hero--invitation::before {
  display: none !important;
}

.hero__stage {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.hero__photo {
  position: absolute;
  inset: -1.5%;
  background-image: var(--hero-photo);
  background-size: cover;
  background-position: var(--hero-photo-focus);
  background-repeat: no-repeat;
  /* No blur filter — softness lives in the photograph itself (and only lightly).
     Occasion changes cross-fade the custom property via the opacity pulse below. */
  filter: none;
  transform-origin: 52% 46%;
  will-change: transform, opacity;
  animation: heroKenBurns 26s ease-in-out infinite alternate;
  transition: opacity 0.55s ease;
}

@keyframes heroKenBurns {
  from { transform: scale(1) translate3d(0, 0, 0); }
  to { transform: scale(1.06) translate3d(-1.1%, -0.9%, 0); }
}

.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(118% 88% at 50% 44%, rgba(var(--scrim-rgb), var(--scrim-core)), rgba(var(--scrim-rgb), 0) 66%),
    linear-gradient(
      180deg,
      rgba(var(--scrim-rgb), var(--scrim-top)) 0%,
      rgba(var(--scrim-rgb), 0) 30%,
      rgba(var(--scrim-rgb), 0) 58%,
      rgba(var(--scrim-rgb), var(--scrim-bottom)) 100%
    );
}

/* A soft ivory veil under the floating header. Deliberately NOT keyed to
   --scrim-rgb: that is navy for graduations, and darkening the image behind
   dark header text is the wrong direction. This lifts the photograph towards
   the ivory the header pill is made of, on all three occasions. */
.hero__stage::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: calc(var(--header-h) + 40px);
  background: linear-gradient(180deg, rgba(255, 253, 248, 0.42), rgba(255, 253, 248, 0));
}

/* The photograph resolves into the page canvas at the foot rather than
   stopping at a hard edge, and the hero signs off with the same foil rule
   the sections use. */
.hero__stage::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(70px, 12vw, 140px);
  background: linear-gradient(180deg, rgba(var(--bg-rgb), 0) 0%, var(--bg) 96%);
}

/* The hero signs off with the same foil rule the sections use. It sits BELOW
   the first screen, with the ticker after it, so the two of them are what the
   first scroll reveals ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â and the rule's margins are the air that separates
   them from the scroll cue above. */
.hero__rule {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  width: min(720px, 84%);
  height: 1px;
  margin: clamp(15px, 2vw, 26px) auto 0;
  background: linear-gradient(90deg, transparent, var(--gold-soft) 14%, var(--gold) 50%, var(--gold-soft) 86%, transparent);
  pointer-events: none;
}

.hero__rule::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -4px;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  transform: rotate(45deg);
  background: var(--gold);
  box-shadow: 0 0 0 4px var(--bg);
}

/* A wider left column is worth more than a smaller headline: it takes the
   h1 from four lines to three at every desktop width, which is ~57px of
   height recovered without touching the type size.

   `align-items: center` rather than stretch: with the photograph filling the
   preview card the two columns come out within ~20px of each other on their
   own, and letting them keep their natural heights is what stops the picture
   being stretched past the resolution of its source. */
.hero--invitation .hero__shell {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  display: grid;
  /* Wider left paper so the brand line, headline and body can breathe. */
  grid-template-columns: minmax(0, 1.50fr) minmax(0, 0.64fr);
  gap: clamp(16px, 2.4vw, 34px);
  align-items: center;
  padding-top: clamp(8px, 1.4vw, 18px);
  padding-bottom: clamp(12px, 1.6vw, 22px);
}

/* ---- The invitation card ------------------------------------------- */
/* The OUTSIDE of this card is settled — deckled ivory paper, gold hairline,
   cast shadow. Inside: three bands in a flex column (switcher / message /
   action), all centre-aligned to the paper so the card reads as one finished
   piece of stationery rather than a left-stacked form. */
.hero__card {
  --deckle: 8px;
  --deckle-w: 26px;
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center !important;
  max-width: none;
  padding: clamp(26px, 2.4vw, 36px) clamp(22px, 2.6vw, 40px);
}

/* Soft cast shadow. A separate unmasked caster, because a drop-shadow on
   the translucent paper below would be visible straight through it. */
.hero__card::before {
  content: "";
  position: absolute;
  inset: 14px 8px -6px 8px;
  z-index: -2;
  border-radius: 8px;
  background: rgba(43, 38, 28, 0.26);
  filter: blur(26px);
}

/* The paper itself: translucent ivory, a fine gold hairline down each
   side and a deckled top and bottom edge cut with a mask. The mask is on
   this layer and NOT on .hero__card, so the wax seal can still overhang
   the card without being clipped. */
.hero__card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(168deg, rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0) 46%),
    rgba(var(--card-tint), var(--card-alpha));
  border-left: 1px solid var(--gold-soft);
  border-right: 1px solid var(--gold-soft);
  -webkit-backdrop-filter: blur(3px) saturate(115%);
  backdrop-filter: blur(3px) saturate(115%);
  -webkit-mask:
    radial-gradient(calc(var(--deckle-w) / 2) var(--deckle) at 50% 0, transparent 98%, #000 100%) top left / var(--deckle-w) var(--deckle) repeat-x,
    radial-gradient(calc(var(--deckle-w) / 2) var(--deckle) at 50% 100%, transparent 98%, #000 100%) bottom left / var(--deckle-w) var(--deckle) repeat-x,
    linear-gradient(#000, #000) center / 100% calc(100% - var(--deckle) * 2) no-repeat;
  mask:
    radial-gradient(calc(var(--deckle-w) / 2) var(--deckle) at 50% 0, transparent 98%, #000 100%) top left / var(--deckle-w) var(--deckle) repeat-x,
    radial-gradient(calc(var(--deckle-w) / 2) var(--deckle) at 50% 100%, transparent 98%, #000 100%) bottom left / var(--deckle-w) var(--deckle) repeat-x,
    linear-gradient(#000, #000) center / 100% calc(100% - var(--deckle) * 2) no-repeat;
}

/* The pressed keyline every printed invitation has. A real element rather
   than a third pseudo-class, which the shadow and the paper have taken. */
.hero__card-rule {
  position: absolute;
  inset: 13px 12px;
  z-index: 0;
  border: 1px solid var(--gold-soft);
  border-radius: 2px;
  opacity: 0.62;
  pointer-events: none;
}

.hero__card > *:not(.hero__card-rule):not(.hero__seal) {
  position: relative;
  z-index: 1;
  width: 100%;
}

/* styles.css hides .reveal children until the observer marks them, and
   app.js needs the .reveal ancestor to release the split headline. The
   card keeps the hook but takes its entrance from the flap below. */
.hero__card.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ---- Inside the card: the message band ----------------------------- */
.hero__card-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Tighter under the subhead so the foil + CTAs sit nearer the copy
     without crowding the H1 (top padding stays a hair looser). */
  padding-block: clamp(10px, 1.3vw, 18px) clamp(2px, 0.45vw, 6px);
  text-align: center;
}

/* The eyebrow was the THIRD small letterspaced element in a row — after the
   switcher's micro-label and before the headline — and all three competed at
   the same size. Reset as an italic Cormorant line it becomes a studio
   signature in a different register entirely, so the eye goes
   switcher → signature → headline instead of triaging three equals. */
.hero--invitation .hero__card .eyebrow {
  display: block;
  margin: 0 auto clamp(8px, 0.9vw, 12px) !important;
  width: max-content;
  max-width: 100%;
  font-family: var(--font-script) !important;
  font-style: italic;
  font-size: clamp(0.94rem, 0.85vw + 0.6rem, 1.1rem) !important;
  font-weight: 500 !important;
  letter-spacing: 0.02em !important;
  line-height: 1.4;
  text-align: center !important;
  text-transform: none !important;
  /* Desktop: one line. Phones may wrap if the paper is too narrow. */
  white-space: nowrap;
  font-variant-caps: normal;
  font-feature-settings: normal;
  color: var(--gold-text) !important;
}

/* Its gold dash was the second hairline in 40px of card. The printer's rule
   above the action does that job now, with air around it. */
.hero--invitation .hero__card .eyebrow::before { display: none !important; }

.hero--invitation .hero__title {
  margin: 0 auto clamp(12px, 1.4vw, 18px) !important;
  max-width: 25ch;
  font-size: clamp(1.95rem, 3.5vw, 3.15rem) !important;
  line-height: 1.12 !important;
  letter-spacing: -0.012em !important;
  text-align: center !important;
  text-wrap: balance;
}

/* Split-text wraps each word (and each space) in an inline-block. Negative
   letter-spacing was collapsing the space spans so the headline read as one
   jammed string — give spaces a real width and keep word tracking gentle. */
.hero--invitation .hero__title .split-word {
  letter-spacing: -0.012em;
}

.hero--invitation .hero__title .split-word--space {
  display: inline-block;
  width: 0.32em;
  min-width: 0.32em;
  letter-spacing: 0;
}

/* Supporting paragraph under the H1 — quieter than the headline, still
   readable as two short lines rather than dense small print. */
.hero--invitation .hero__copy {
  margin: 0 auto !important;
  max-width: 44ch;
  color: var(--text) !important;
  font-size: clamp(0.86rem, 0.35vw + 0.72rem, 0.94rem) !important;
  line-height: 1.65 !important;
  text-align: center !important;
  text-wrap: pretty;
}

/* Centred copy cannot carry a floated drop-cap — it pulls the first line off
   centre and looks broken. Keep a quiet gold initial instead. */
.hero--invitation .hero__copy::first-letter {
  float: none !important;
  font-family: inherit !important;
  font-size: inherit !important;
  font-weight: 600 !important;
  line-height: inherit !important;
  margin: 0 !important;
  color: var(--gold-deep) !important;
}

/* ---- Inside the card: the action band ------------------------------ */
.hero__card-foot {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* A printer's rule: centred measure, fading both ways, with a lozenge in the
   middle. It separates "what this is" from "what to do next". */
.hero__foil {
  display: block;
  position: relative;
  width: min(220px, 72%);
  height: 1px;
  margin: clamp(6px, 0.8vw, 10px) auto clamp(12px, 1.4vw, 18px);
  background: linear-gradient(90deg, rgba(184, 151, 102, 0), var(--gold-soft) 22%, var(--gold) 50%, var(--gold-soft) 78%, rgba(184, 151, 102, 0));
}

.hero__foil::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -3px;
  width: 7px;
  height: 7px;
  margin-left: -3.5px;
  transform: rotate(45deg);
  background: var(--gold-deep);
}

.hero--invitation .hero__actions {
  display: flex !important;
  flex-wrap: wrap;
  margin: 0 auto !important;
  justify-content: center !important;
  align-items: center !important;
  gap: clamp(14px, 1.8vw, 24px);
  width: 100%;
}

/* The two buttons carried near-identical weight, so neither led. The primary
   grows and gains a champagne underglow; the secondary drops its box for a
   foil-underlined link with a direction arrow. Still a real, obvious control
   ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â just unmistakably the second one. */
.hero--invitation .hero__actions .button:not(.button--ghost) {
  min-height: 52px;
  padding: 0 clamp(22px, 2.2vw, 32px);
  font-size: 0.82rem !important;
  letter-spacing: 0.11em !important;
  box-shadow: 0 12px 26px rgba(35, 32, 28, 0.22), 0 0 0 1px var(--gold-soft) !important;
}

.hero--invitation .hero__actions .button:not(.button--ghost):hover,
.hero--invitation .hero__actions .button:not(.button--ghost):focus-visible {
  box-shadow: 0 16px 34px rgba(160, 127, 79, 0.34), 0 0 0 1px var(--gold) !important;
}

/* Secondary is a quiet text link — not a second equal button. Overrides
   home-light's uppercase/weight on .button so it reads as sentence case. */
.hero--invitation .hero__actions .button--ghost {
  min-height: 0;
  padding: 2px 0;
  gap: 0;
  border: 0 !important;
  border-bottom: 1px solid transparent !important;
  border-radius: 0 !important;
  background: none !important;
  box-shadow: none !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  color: var(--muted) !important;
  font-size: 0.8rem !important;
  font-weight: 400 !important;
  letter-spacing: 0.02em !important;
  text-transform: none !important;
  transition: color 0.25s ease, border-color 0.25s ease;
}

/* The shared stylesheet owns ::after for the button sheen, so the arrow rides
   on ::before and is ordered back after the label. */
.hero--invitation .hero__actions .button--ghost::before {
  content: "\2192";
  order: 1;
  margin-inline-start: 0.55em;
  font-size: 1.05em;
  line-height: 1;
  transition: transform 0.25s ease;
}

[dir="rtl"] .hero--invitation .hero__actions .button--ghost::before { content: "\2190"; }

/* A light streak sweeping across a borderless link reads as a glitch. */
.hero--invitation .hero__actions .button--ghost::after { display: none !important; }

.hero--invitation .hero__actions .button--ghost:hover,
.hero--invitation .hero__actions .button--ghost:focus-visible {
  transform: none;
  border-bottom-color: var(--gold-soft) !important;
  background: none !important;
  color: var(--gold-deep) !important;
}

.hero--invitation .hero__actions .button--ghost:hover::before { transform: translateX(4px); }
[dir="rtl"] .hero--invitation .hero__actions .button--ghost:hover::before { transform: translateX(-4px); }

/* =====================================================================
   2. OCCASION SWITCHER
   ===================================================================== */
.hero__occasions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px clamp(12px, 1.5vw, 18px);
  margin-bottom: clamp(12px, 1.4vw, 16px);
  padding-bottom: clamp(12px, 1.4vw, 16px);
  border-bottom: 1px solid var(--gold-soft);
  text-align: center;
}

.hero__occasions-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-variant-caps: all-small-caps;
  color: var(--gold-text);
  white-space: nowrap;
}

.hero__occasions-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 8px;
}

.occ-pill {
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 10px 18px;
  border-radius: 999px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--gold-soft);
  transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.occ-pill:hover {
  color: var(--gold-text);
  border-color: var(--gold-deep);
  transform: translateY(-1px);
}

.occ-pill[aria-pressed="true"] {
  color: #fffaf1;
  background: var(--ink);
  border-color: var(--ink);
  box-shadow: 0 6px 16px rgba(35, 32, 28, 0.2);
}

.occ-pill:focus-visible {
  outline: 3px solid var(--gold-deep);
  outline-offset: 3px;
}

/* =====================================================================
   4. OCCASION-AWARE AMBIENT MOTION
   ---------------------------------------------------------------------
   Twelve elements, no library and no new image: petals are a lopsided
   border-radius, confetti a spinning rectangle, motes a blurred dot that
   rises. public/templates/_shared/samples/invitation_fallingImage/
   petal.png was considered and rejected ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â 129 KB for what a border-radius
   draws for nothing.
   ===================================================================== */
.hero__drift {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.hero__drift span {
  position: absolute;
  top: -3%;
  width: var(--drift-w);
  height: var(--drift-h);
  border-radius: var(--drift-radius);
  background: var(--drift-a);
  box-shadow: var(--drift-glow);
  opacity: 0;
  will-change: transform, opacity;
  animation: var(--drift-anim) var(--drift-dur) linear var(--drift-delay) infinite;
}

.hero__drift span:nth-child(3n) { background: var(--drift-b); }
.hero__drift span:nth-child(3n + 1) { background: var(--drift-c); }

.hero__drift span:nth-child(1) { left: 4%; --drift-dur: 21s; --drift-delay: 0s; --drift-sway: 34px; --drift-scale: 1; }
.hero__drift span:nth-child(2) { left: 13%; --drift-dur: 27s; --drift-delay: 3.5s; --drift-sway: -26px; --drift-scale: 0.7; }
.hero__drift span:nth-child(3) { left: 22%; --drift-dur: 24s; --drift-delay: 8s; --drift-sway: 20px; --drift-scale: 1.15; }
.hero__drift span:nth-child(4) { left: 31%; --drift-dur: 30s; --drift-delay: 1.5s; --drift-sway: -38px; --drift-scale: 0.85; }
.hero__drift span:nth-child(5) { left: 41%; --drift-dur: 23s; --drift-delay: 11s; --drift-sway: 28px; --drift-scale: 0.65; }
.hero__drift span:nth-child(6) { left: 49%; --drift-dur: 29s; --drift-delay: 6s; --drift-sway: -18px; --drift-scale: 1.05; }
.hero__drift span:nth-child(7) { left: 58%; --drift-dur: 22s; --drift-delay: 14s; --drift-sway: 40px; --drift-scale: 0.8; }
.hero__drift span:nth-child(8) { left: 67%; --drift-dur: 26s; --drift-delay: 2.5s; --drift-sway: -30px; --drift-scale: 1.2; }
.hero__drift span:nth-child(9) { left: 76%; --drift-dur: 31s; --drift-delay: 9.5s; --drift-sway: 22px; --drift-scale: 0.75; }
.hero__drift span:nth-child(10) { left: 84%; --drift-dur: 25s; --drift-delay: 5s; --drift-sway: -34px; --drift-scale: 0.95; }
.hero__drift span:nth-child(11) { left: 91%; --drift-dur: 28s; --drift-delay: 16s; --drift-sway: 24px; --drift-scale: 0.7; }
.hero__drift span:nth-child(12) { left: 96%; --drift-dur: 20s; --drift-delay: 12s; --drift-sway: -20px; --drift-scale: 1.1; }

@keyframes heroDriftFall {
  0% { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg) scale(var(--drift-scale, 1)); }
  9% { opacity: 0.85; }
  50% { transform: translate3d(var(--drift-sway, 24px), 46vh, 0) rotate(190deg) scale(var(--drift-scale, 1)); }
  88% { opacity: 0.7; }
  100% { opacity: 0; transform: translate3d(0, 96vh, 0) rotate(380deg) scale(var(--drift-scale, 1)); }
}

@keyframes heroDriftRise {
  0% { opacity: 0; transform: translate3d(0, 92vh, 0) scale(calc(var(--drift-scale, 1) * 0.6)); }
  14% { opacity: 0.9; }
  55% { transform: translate3d(var(--drift-sway, 24px), 44vh, 0) scale(var(--drift-scale, 1)); }
  86% { opacity: 0.5; }
  100% { opacity: 0; transform: translate3d(0, 2vh, 0) scale(calc(var(--drift-scale, 1) * 0.75)); }
}

/* Nothing animates behind a tab the visitor is not looking at. */
body.is-page-hidden .hero__photo,
body.is-page-hidden .hero__drift span,
body.is-page-hidden .hero__invite-float {
  animation-play-state: paused;
}

/* =====================================================================
   5. ENVELOPE FLOURISH
   ===================================================================== */

/* The card arrives as a flap falling open, hinged on its top edge. */
.hero__card {
  animation: heroCardFlap 1s cubic-bezier(0.22, 1, 0.36, 1) 120ms both;
  transform-origin: 50% 0;
}

@keyframes heroCardFlap {
  0% { opacity: 0; transform: perspective(1200px) rotateX(-13deg) translateY(-16px); }
  100% { opacity: 1; transform: perspective(1200px) rotateX(0deg) translateY(0); }
}

/* Wax medallions stamped on all four corners of the paper card — same
   material language as the `wax-seal` envelope. Every seal shares the
   hover/focus break flourish so the stationery reads as one finished set. */
.hero__seal {
  position: absolute;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 47% 53% 51% 49% / 52% 48% 52% 48%;
  background:
    radial-gradient(circle at 34% 28%, rgba(255, 255, 255, 0.55), transparent 46%),
    radial-gradient(circle at 72% 78%, rgba(0, 0, 0, 0.3), transparent 52%),
    var(--gold-deep);
  box-shadow: 0 5px 14px rgba(43, 38, 28, 0.34), inset 0 0 12px rgba(0, 0, 0, 0.22);
  transition: transform 0.55s cubic-bezier(0.34, 1.3, 0.64, 1), box-shadow 0.45s ease;
  pointer-events: none;
}

.hero__seal--tl { top: -10px; inset-inline-start: clamp(12px, 2vw, 22px); }
.hero__seal--tr { top: -10px; inset-inline-end: clamp(12px, 2vw, 22px); }
.hero__seal--bl { bottom: -10px; inset-inline-start: clamp(12px, 2vw, 22px); }
.hero__seal--br { bottom: -10px; inset-inline-end: clamp(12px, 2vw, 22px); }

.hero__seal-mark {
  font-family: var(--font-serif);
  font-size: 0.92rem;
  line-height: 1;
  color: #fff7e6;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}

/* The crack, drawn but weightless until the seal breaks — same on every
   corner. Percentage inset keeps the hairline proportional across sizes. */
.hero__seal::after {
  content: "";
  position: absolute;
  inset: 14% 46%;
  background: linear-gradient(180deg, transparent, rgba(255, 246, 224, 0.85), transparent);
  opacity: 0;
  transform: scaleY(0.2);
  transition: opacity 0.3s ease, transform 0.45s ease;
}

.hero__card:hover .hero__seal,
.hero__card:focus-within .hero__seal {
  transform: translateY(-9px) rotate(-13deg) scale(1.04);
  box-shadow: 0 14px 26px rgba(43, 38, 28, 0.32), inset 0 0 12px rgba(0, 0, 0, 0.22);
}

.hero__card:hover .hero__seal::after,
.hero__card:focus-within .hero__seal::after {
  opacity: 1;
  transform: scaleY(1);
}

/* =====================================================================
   HERO FURNITURE ON A PHOTOGRAPH
   ---------------------------------------------------------------------
   No small text sits directly on the image: every label below carries its
   own translucent ivory surface, which is what keeps contrast at AA on
   all three occasions including the navy one.
   ===================================================================== */

/* The sample invitation keeps its printed look but goes slightly
   translucent so it reads as stationery on the same table as the card. */
.hero--invitation .hero__invite {
  width: 100%;
  padding: clamp(16px, 1.7vw, 22px) clamp(16px, 1.8vw, 24px) clamp(20px, 2vw, 26px);
  background: linear-gradient(180deg, rgba(255, 254, 251, 0.93), rgba(253, 250, 243, 0.9)) !important;
  border: 1px solid var(--gold-soft) !important;
  box-shadow: 0 26px 56px rgba(43, 38, 28, 0.22) !important;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

/* Fills the column so the two boxes finish level. */
.hero--invitation .hero__visual {
  display: flex;
  flex-direction: column;
}

/* Gentle bob for the preview card only — lives on a wrapper so tilt-card's
   inline transforms cannot cancel it. Stats stay still underneath. */
.hero--invitation .hero__invite-float {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  will-change: transform;
  animation: heroInviteFloat 5.8s ease-in-out infinite;
}

@keyframes heroInviteFloat {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50% { transform: translate3d(0, -7px, 0); }
}

.hero--invitation .hero__invite {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

/* ---- The photographic invitation -----------------------------------
   ART DIRECTION. The wording is set ON the picture, the way a printed
   photo invitation is made, and three things make that safe:

   1. THE WINDOW. The frame is 4:3 and the source is 2.1826:1, so `cover`
      is height-driven and shows the middle 61% of the source's width. The
      couple occupy x 38-57% of the source, so they are inside that window
      at every card size and can never be clipped. Because height governs,
      the full frame height is always shown and the faces land at 15-37%
      from the top Ã¢â‚¬â€ the clear part of the picture.

   2. THE DEAD SPACE. Below the couple the frame is the car's bonnet:
      dark, broad and empty. That is where the type goes, pinned to the
      bottom of the frame.

   3. THE VEIL. A gradient that is fully transparent across the faces and
      reaches 0.78 at the foot. It deepens what is already dark rather
      than washing the picture out, and it is strong enough that even a
      blown-out chrome highlight under the type clears AA against ivory
      ink Ã¢â‚¬â€ see the measured figures.
--------------------------------------------------------------------- */
body[data-occasion] {
  --invite-photo: url("home-invite-couple-502.jpg");

  /* Ink for type over the picture. Deliberately NOT the page palette: on a
     dark veil the AA-safe DARK golds would disappear, so each occasion gets
     a light tint of its own accent instead. */
  --on-photo-ink: #fffdf8;
  --on-photo-soft: #efe6d8;
  /* The eyebrow is the topmost line, so it sits where the scrim is still
     ramping in — a saturated accent measured 3.84:1 there. These are warm
     near-whites: the occasion still tints the line, at a luminance that
     clears AA over the brightest highlight the picture can put behind it. */
  --on-photo-accent: #f8ecd6;
}

body[data-occasion="graduation"] {
  --on-photo-soft: #e5e7f1;
  --on-photo-accent: #f7f0d4;
}

body[data-occasion="birthday"] {
  --on-photo-soft: #f3e7dd;
  --on-photo-accent: #fce2d4;
}

/* Picture at the top, foil mark floating in the mount, counters at the foot Ã¢â‚¬â€
   so when the card stretches to match the headline card the slack becomes a
   deliberate mount rather than a blank band. */
/* FULL BLEED, matching the mobile card the studio signed off: the photograph
   runs to the card's top and side edges and grows down to meet the counters,
   so there is never a band of empty cream between them. The card's horizontal
   padding is cancelled by a negative inline margin and its top padding is
   dropped; the card's own radius and `overflow: hidden` do the clipping. */
.hero--invitation .hero__invite--plated {
  --invite-pad-x: clamp(13px, 1.5vw, 20px);
  justify-content: flex-start;
  padding: 0 var(--invite-pad-x) clamp(15px, 1.7vw, 21px) !important;
}

/* The pressed keyline would otherwise draw a gold rectangle across the
   picture now that the picture reaches the card's edges. */
.hero--invitation .hero__invite--plated::before {
  display: none !important;
}

.hero__invite-frame {
  position: relative;
  /* Takes whatever height the card has spare, with 4:3 as its floor. */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 4 / 3;
  min-height: 0;
  overflow: hidden;
  margin: 0 calc(-1 * var(--invite-pad-x)) clamp(11px, 1.2vw, 15px);
  /* No padding: the wording block below carries its own inset, so its scrim
     can run all the way to the frame's bottom edge. */
  padding: 0;
  background-color: #2b2724;
  background-image: var(--invite-photo);
  background-repeat: no-repeat;
  /* Source is ~2.18:1; cover on a 4:3 frame shows ~61% of its width. The
     couple (kiss ~40% across the source) sits left of true center, so a
     centered crop leaves them hugging the left edge with foliage on the
     right. ~35% X pans left of center enough to keep faces in frame without
     drifting the subjects too far toward the right edge. */
  background-position: 35% 30%;
  background-size: cover;
  border-bottom: 1px solid var(--gold-soft);
}

/* A soft base wash over the lower part of the picture, for mood. The scrim
   that legibility actually depends on is on the wording block below. */
.hero__invite-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(16, 13, 11, 0) 34%,
    rgba(16, 13, 11, 0.14) 56%,
    rgba(16, 13, 11, 0.30) 100%
  );
}

/* THE SCRIM IS ANCHORED TO THE TYPE, not to a percentage of the frame. The
   wording block is a fixed number of lines while the frame scales with the
   card, so the type sat 40% down the frame at 1024px and 57% down at 1440px —
   a frame-relative gradient could not cover both, and the eyebrow ended up on
   a barely-veiled highlight at 1.75:1. Carrying the gradient on the block
   itself means it is always exactly under the words, at any card size. */
.hero__invite-block {
  position: relative;
  z-index: 1;
  display: block;
  text-align: center;
  padding: clamp(30px, 4.4vw, 54px) clamp(12px, 1.4vw, 18px) clamp(13px, 1.5vw, 19px);
  background: linear-gradient(
    180deg,
    rgba(16, 13, 11, 0) 0%,
    rgba(16, 13, 11, 0.42) 14%,
    rgba(16, 13, 11, 0.78) 30%,
    rgba(16, 13, 11, 0.88) 100%
  );
}

/* Optical separation only. Every figure reported for these three strings is
   measured against the veiled photograph, never against this shadow. */
.hero--invitation .hero__invite-eyebrow,
.hero--invitation .hero__invite-names,
.hero--invitation .hero__invite-date {
  text-shadow: 0 1px 7px rgba(12, 9, 7, 0.55);
}

.hero--invitation .hero__invite-eyebrow {
  display: block;
  color: var(--on-photo-accent) !important;
}

.hero--invitation .hero__invite-names {
  margin: 7px 0 4px !important;
  font-size: clamp(1.6rem, 2.2vw, 2.1rem) !important;
  color: var(--on-photo-ink) !important;
  -webkit-text-fill-color: var(--on-photo-ink) !important;
}

.hero--invitation .hero__invite-date {
  color: var(--on-photo-soft) !important;
}

/* The hairline between the names and the date has a photograph behind it now,
   so it takes the light accent rather than the page's darker gold. */
.hero--invitation .hero__invite-names + .hero__invite-date::before {
  background: linear-gradient(90deg, transparent, var(--on-photo-accent), transparent) !important;
}

/* The counters stay on the paper below the print. They are product UI, not
   invitation wording: four boxed chips over the picture would have fought the
   names for the same space and turned a photograph into a dashboard. */
.hero--invitation .hero__invite-count strong {
  color: var(--gold-text) !important;
}

.hero--invitation .hero__invite-count {
  margin-top: 0;
  margin-inline: 0;
  padding-top: 0;
  width: 100%;
  box-sizing: border-box;
  justify-items: stretch;
}

.hero--invitation .hero__invite-count div { padding: 9px 5px; }
.hero--invitation .hero__invite-count strong { font-size: 1.2rem; }

/* Left column: paper card stacked over the three stat chips. */
.hero--invitation .hero__lead {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* The counters sit under the LEFT paper box — same width as the card above. */
.hero--invitation .hero__lead .hero__stats,
.hero__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(7px, 0.8vw, 10px);
  /* Clear the wax seals that overhang the card's bottom edge. */
  margin-top: clamp(16px, 1.6vw, 22px);
  width: 100%;
}

/* Pressed cream seals under the card — gold hairline, soft inset-ish cast
   rather than floating glass tiles. */
.hero--invitation .hero-stat {
  padding: clamp(9px, 1vw, 13px) 6px;
  text-align: center;
  background: rgba(var(--card-tint), 0.94) !important;
  border: 1px solid var(--gold-soft) !important;
  border-radius: 4px !important;
  box-shadow: 0 1px 2px rgba(43, 38, 28, 0.05), inset 0 1px 0 rgba(255, 255, 255, 0.45) !important;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.hero--invitation .hero-stat strong {
  margin-bottom: 3px;
  font-size: clamp(1.35rem, 1.65vw, 1.72rem);
  font-weight: 600;
  line-height: 1.05;
}

.hero--invitation .hero-stat span {
  display: block;
  font-size: 0.64rem;
  line-height: 1.35;
  letter-spacing: 0.05em;
  text-transform: none;
  font-weight: 400;
}

.hero--invitation .hero__scroll-hint,
.hero--invitation .hero__scroll-hint .hero__scroll-hint-text {
  color: var(--muted) !important;
  text-shadow: none !important;
}

/* The cue is the last thing in the first screen and the thing the visitor is
   promised they will see, so it gets real air on both sides rather than being
   sandwiched against the ticker. */
.hero--invitation .hero__scroll-hint {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  gap: 0.5rem;
  margin-top: 0;
  padding: clamp(6px, 1.2vw, 16px) 1.5rem clamp(20px, 2.6vw, 32px);
}

.hero--invitation .hero__scroll-hint-text {
  padding: 5px 14px;
  border-radius: 999px;
  background: rgba(var(--card-tint), 0.86);
  border: 1px solid var(--gold-soft);
  font-size: 0.62rem;
}

.hero--invitation .hero__scroll-hint-arrow {
  width: 14px;
  height: 14px;
  border-right-width: 2px;
  border-bottom-width: 2px;
  border-color: var(--gold-deep) !important;
  filter: none;
}

/* The feature ticker becomes the torn strip along the foot of the hero ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â now
   just past the fold, which is where it stops being clipped by the bottom of
   a short laptop screen. */
.hero--invitation .hero__marquee {
  position: relative;
  z-index: 1;
  margin-top: clamp(12px, 1.6vw, 20px);
  background: rgba(var(--card-tint), 0.88) !important;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

.hero--invitation .hero__marquee-track {
  color: var(--text) !important;
  font-size: 0.8rem;
}

/* The ticker's leading bullet still carried the dark theme's blue halo. */
.hero--invitation .hero__marquee-track span::before {
  width: 5px;
  height: 5px;
  margin-right: 12px;
  background: var(--gold) !important;
  box-shadow: none !important;
}

/* =====================================================================
   FOOTER ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â the back of the envelope
   ===================================================================== */
.site-footer {
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, #211f1b 0%, #191712 100%) !important;
  border-top: 1px solid var(--gold-soft) !important;
  color: rgba(238, 231, 218, 0.78) !important;
}

/* The two flaps of a closed envelope, meeting at the centre. */
.site-footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 0;
  width: 150%;
  aspect-ratio: 5 / 1;
  transform: translateX(-50%);
  background: linear-gradient(180deg, rgba(255, 250, 240, 0.045), rgba(255, 250, 240, 0));
  clip-path: polygon(0 0, 50% 100%, 100% 0);
  border-bottom: 1px solid rgba(184, 151, 102, 0.22);
  pointer-events: none;
}

.site-footer__main,
.site-footer__bottom {
  position: relative;
  z-index: 1;
}

.site-footer__name { color: #f6efe1 !important; }

.site-footer__tagline,
.site-footer__address,
.site-footer__address a,
.site-footer__hours,
.site-footer__visit-note,
.site-footer__copyright,
.site-footer__copyright a { color: rgba(233, 225, 211, 0.72) !important; }

.site-footer a { color: rgba(242, 236, 225, 0.9) !important; }
.site-footer a:hover { color: #e2c48c !important; }

.site-footer__nav-label { color: #d3b478 !important; }

.site-footer__company {
  color: #e2c48c !important;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(226, 196, 140, 0.5);
}

.site-footer__company:hover { color: #f0dcb2 !important; }

.site-footer__social-link {
  background: rgba(255, 250, 240, 0.06) !important;
  border: 1px solid rgba(184, 151, 102, 0.34) !important;
}

.site-footer__social-icon { color: #d3b478 !important; }

.site-footer__social-link:hover {
  background: #d3b478 !important;
  border-color: #d3b478 !important;
}

.site-footer__social-link:hover .site-footer__social-icon { color: #201e19 !important; }

.site-footer__logo { filter: brightness(1.9) contrast(0.92); }

/* A wax seal where the two flaps meet. */
.site-footer__bottom::before {
  content: "\2726";
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin: 0 auto 14px;
  border-radius: 48% 52% 51% 49% / 53% 47% 53% 47%;
  background:
    radial-gradient(circle at 34% 30%, rgba(255, 255, 255, 0.42), transparent 48%),
    #a07f4f;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45), inset 0 0 10px rgba(0, 0, 0, 0.28);
  color: #fff5e2;
  font-size: 0.82rem;
  line-height: 1;
}

/* =====================================================================
   RESPONSIVE ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â checked at 375px, 768px and 1440px
   ===================================================================== */
/* =====================================================================
   TEMPLATE GALLERY ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â shorter cards at the SAME 3:4 preview
   ---------------------------------------------------------------------
   The 12 card JPEGs are cut to exactly 3:4 to match
   .tmpl-card__preview's aspect-ratio, which is what stopped them being
   cover-cropped. So the height comes off the card WIDTH, not the ratio:
   five per row instead of four takes a 1440px preview from 389px to 305px
   with the images still landing pixel-exact and uncropped. The rest comes
   out of the content block, which was padded for a much larger card.
   ===================================================================== */
@media (min-width: 1200px) {
  body[data-occasion] #templates .service-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
    gap: 0.95rem !important;
  }
}

/* home-light.css dropped straight from four per row to three below 1080px,
   which made the cards WIDER and therefore taller than they are at 1440.
   Four per row holds down to 900px. */
@media (min-width: 900px) and (max-width: 1199px) {
  body[data-occasion] #templates .service-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    gap: 0.9rem !important;
  }
}

body[data-occasion] #templates .service-card__content {
  padding: 0.85rem 0.85rem 0.95rem !important;
  gap: 0.35rem !important;
}

body[data-occasion] #templates .service-card h3 { font-size: 1rem !important; }

body[data-occasion] #templates .service-card p {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.78rem !important;
  line-height: 1.5 !important;
}

body[data-occasion] #templates .tmpl-card__actions {
  gap: 6px;
  padding-top: 2px;
}

body[data-occasion] #templates .tmpl-card__actions .button {
  min-height: 34px !important;
  font-size: 0.63rem !important;
  padding: 0 9px !important;
}

@media (max-width: 980px) {
  .hero--invitation .hero__shell {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(18px, 3vw, 28px);
  }

  .hero--invitation .hero__visual {
    width: min(100%, 420px);
    margin-inline: auto;
  }
}

/* A stacked hero on a tablet is two cards tall, so the bands below them are
   trimmed to keep the scroll cue on the first screen. */
@media (max-width: 980px) and (max-height: 1100px) {
  .hero--invitation .hero__shell { padding-bottom: 10px; }
  .hero--invitation .hero__card-body { padding-block: 10px; }
  .hero--invitation .hero__scroll-hint { padding-top: 2px; padding-bottom: 10px; }
  .hero--invitation .hero__invite { padding-bottom: 16px; }
}

/* =====================================================================
   SHORT VIEWPORTS ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â the hero is a single screen, not a scroll
   ---------------------------------------------------------------------
   Width alone was never the constraint: a 1024x640 laptop has 640px of
   height to hold a header, a switcher, a headline, two cards and a scroll
   cue. These two tiers take the composition down proportionally rather
   than shrinking the type to illegibility ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â padding, leading and the
   decorative drop cap go first, and the headline only after that.
   ===================================================================== */
@media (min-width: 981px) and (max-height: 860px) {
  .hero--invitation .hero__shell {
    gap: clamp(16px, 2.2vw, 30px);
    padding-top: 6px;
    padding-bottom: 12px;
  }

  .hero__card { padding: 20px 26px; }
  .hero__card-body { padding-block: 12px; }

  .hero__occasions {
    margin-bottom: 11px;
    padding-bottom: 10px;
  }

  .hero--invitation .hero__title {
    margin: 0 auto 11px !important;
    font-size: clamp(1.72rem, 2.7vw, 2.45rem) !important;
  }

  .hero--invitation .hero__copy {
    font-size: 0.86rem !important;
    line-height: 1.62 !important;
  }

  .hero__foil { margin-bottom: 14px; }
  .hero--invitation .hero__actions .button:not(.button--ghost) { min-height: 48px; }

  .hero--invitation .hero__invite { padding-bottom: 17px; }
  .hero--invitation .hero__invite-names { font-size: 1.7rem !important; margin: 6px 0 4px !important; }

  .hero--invitation .hero__scroll-hint { padding-top: 4px; padding-bottom: 14px; }
}

/* The last tier. The photograph's height is a function of the card's WIDTH
   (it is laid in uncropped at its own ratio), so the strongest lever left on
   a short screen is to narrow the right column Ã¢â‚¬â€ which shortens the plate AND
   widens the left card enough for the headline to hold its line count. */
@media (min-width: 981px) and (max-height: 720px) {
  .hero--invitation .hero__shell {
    grid-template-columns: minmax(0, 1.48fr) minmax(0, 0.56fr);
    padding-top: 2px;
    padding-bottom: 8px;
  }

  .hero__card { padding: 16px 22px; }
  .hero__card-body { padding-block: 8px; }

  .hero--invitation .hero__card .eyebrow {
    margin-bottom: 5px;
    font-size: 0.92rem !important;
  }

  .hero--invitation .hero__title {
    margin: 0 auto 9px !important;
    font-size: clamp(1.62rem, 2.3vw, 2.1rem) !important;
  }

  .hero--invitation .hero__copy {
    font-size: 0.82rem !important;
    line-height: 1.55 !important;
  }

  /* The drop cap is three lines tall; on a short screen that is the scroll
     cue's whole budget. */
  .hero--invitation .hero__copy::first-letter {
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    float: none;
    margin: 0;
    color: inherit;
  }

  .hero__foil { margin-bottom: 11px; }
  .hero--invitation .hero__actions { gap: 14px; }
  .hero--invitation .hero__actions .button:not(.button--ghost) { min-height: 42px; font-size: 0.76rem !important; }

  .hero--invitation .hero__occasions { margin-bottom: 9px; padding-bottom: 8px; }
  .hero--invitation .hero__invite { padding: 12px 15px 15px; }
  .hero--invitation .hero__invite-names { font-size: 1.5rem !important; margin: 5px 0 3px !important; }
 .hero--invitation .hero__invite-count { padding-top: 9px; }
  .hero--invitation .hero__invite-count div { padding: 5px 4px; }
  .hero--invitation .hero__invite-count strong { font-size: 1.02rem; }
  .hero--invitation .hero-stat { padding: 6px 4px; }
  .hero--invitation .hero-stat strong { font-size: 1.22rem; }
  .hero__stats { margin-top: 7px; }

  .hero--invitation .hero__scroll-hint {
    padding-top: 2px;
    padding-bottom: 8px;
    gap: 0.25rem;
  }
}

/* Windows that are not maximised. A 1020x560 or 1020x465 viewport is a real
   thing on a small laptop, and the promise is that the scroll cue is visible
   there Ã¢â‚¬â€ so the header gives up its tagline line, the plate narrows further
   and every band tightens. Type stays at a readable size; what goes is
   padding. */
@media (min-width: 981px) and (max-height: 640px) {
  body[data-occasion] .site-header { padding: 0.5rem 1rem; }
  body[data-occasion] .brand--header .brand__logo { height: 44px; }
  body[data-occasion] .brand--header .brand__line:first-child { font-size: 0.98rem; }
  body[data-occasion] .brand--header .brand__line:last-child { display: none; }
  body[data-occasion] .header-cta { min-height: 38px; }

  .hero--invitation .hero__shell {
    grid-template-columns: minmax(0, 1.52fr) minmax(0, 0.52fr);
    gap: 20px;
    padding-top: 0;
    padding-bottom: 4px;
  }

  .hero__card { padding: 13px 20px; }
  .hero__card-body { padding-block: 5px; }
  .hero--invitation .hero__card .eyebrow { margin-bottom: 3px; font-size: 0.88rem !important; }
  .hero--invitation .hero__title { margin: 0 auto 7px !important; font-size: 1.9rem !important; }
  .hero--invitation .hero__copy { font-size: 0.78rem !important; line-height: 1.5 !important; }
  .hero__foil { margin-bottom: 9px; }
  .hero--invitation .hero__actions .button:not(.button--ghost) { min-height: 40px; }
  .hero--invitation .hero__occasions { margin-bottom: 7px; padding-bottom: 6px; }
  .occ-pill { padding: 6px 12px; font-size: 0.7rem; }

  .hero--invitation .hero__invite { padding: 10px 13px 13px; }
 .hero--invitation .hero__invite-names { font-size: 1.3rem !important; margin: 4px 0 2px !important; }
  .hero--invitation .hero__invite-date { font-size: 0.78rem; }
  .hero--invitation .hero__invite-count { padding-top: 7px; }
  .hero--invitation .hero__invite-count div { padding: 4px 3px; }
  .hero--invitation .hero__invite-count strong { font-size: 0.92rem; }
  .hero--invitation .hero__invite-count span { font-size: 0.5rem; }
  .hero__stats { margin-top: 6px; gap: 6px; }
  .hero--invitation .hero-stat { padding: 5px 3px; }
  .hero--invitation .hero-stat strong { font-size: 1.12rem; margin-bottom: 0; }
  .hero--invitation .hero-stat span { font-size: 0.58rem; letter-spacing: 0.05em; }

  .hero--invitation .hero__scroll-hint { padding-top: 0; padding-bottom: 6px; gap: 0.2rem; }
  .hero--invitation .hero__scroll-hint-text { padding: 3px 11px; font-size: 0.56rem; }
  .hero--invitation .hero__scroll-hint-arrow { width: 11px; height: 11px; }
}

@media (min-width: 981px) and (max-height: 500px) {
  .hero--invitation .hero__shell { gap: 16px; padding-bottom: 0; }
  .hero--invitation .hero__scroll-hint { padding-bottom: 2px; }
  .hero__card { padding: 10px 17px; }
  .hero__card-body { padding-block: 2px; }
  .hero--invitation .hero__card .eyebrow { font-size: 0.82rem !important; }
  .hero--invitation .hero__title { margin: 0 auto 5px !important; font-size: 1.6rem !important; }
  .hero--invitation .hero__copy { font-size: 0.74rem !important; line-height: 1.45 !important; }
  .hero__foil { margin-bottom: 7px; }
  .hero--invitation .hero__actions .button:not(.button--ghost) { min-height: 36px; font-size: 0.7rem !important; }
  .hero--invitation .hero__invite { padding: 8px 11px 11px; }
  .hero--invitation .hero__invite-names { font-size: 1.14rem !important; }
  .hero--invitation .hero__invite-count { padding-top: 5px; }
  .hero__stats { margin-top: 5px; }
}

/* The header stacks below 980px and, with the brand name wrapping onto two
   lines above a two-row nav, was spending ~200px of a 667px screen before the
   hero even began ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â which is the difference between the primary call to
   action sitting above the fold on a phone or below it. Same links, same
   order, tighter. */
@media (max-width: 720px) {
  .site-header {
    gap: 0.55rem;
    padding: 0.7rem 1rem;
  }

  .brand--header {
    gap: 0.55rem;
    justify-content: center;
  }

  .brand--header .brand__logo { height: 46px; }

  .brand--header .brand__name {
    align-items: flex-start;
    text-align: left;
    line-height: 1.2;
  }

  .brand--header .brand__line:first-child { font-size: 1.02rem; }
  .brand--header .brand__line:last-child { font-size: 0.55rem; letter-spacing: 0.12em; }

  .site-nav a {
    min-height: 28px;
    padding: 0.22rem 0.34rem;
    font-size: 0.71rem;
  }
}

/* A fixed header is permanent furniture, so on a phone every row it spends
   is a row the hero never gets back. */
@media (max-width: 560px) {
  body[data-occasion] .site-header { padding: 0.55rem 0.9rem; }
  body[data-occasion] .brand--header .brand__logo { height: 42px; }
  body[data-occasion] .brand--header .brand__line:first-child { font-size: 0.96rem; }
}

@media (max-width: 560px) {
  /* MUST keep reserving the floating header's height ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â an override of
     padding-top here put the occasion switcher and the eyebrow underneath
     the header on a phone. */
  .hero__screen {
    padding-top: calc(var(--header-h) + 4px);
  }

  .hero--invitation .hero__shell {
    padding-top: 4px;
    padding-bottom: 24px;
  }

  .hero__card-body { padding-block: 10px; }

  .hero__card {
    --deckle: 6px;
    --deckle-w: 20px;
    padding: 20px 17px;
  }

  .hero--invitation .hero__card .eyebrow {
    white-space: normal;
    width: auto;
  }

  .hero--invitation .hero__title {
    max-width: none;
    font-size: clamp(1.72rem, 8.4vw, 2.2rem) !important;
  }

  .hero--invitation .hero__copy {
    font-size: 0.82rem !important;
    line-height: 1.5 !important;
  }

  /* The drop cap costs three lines of height on a phone, which is the
     difference between the call to action being above the fold or not. */
  .hero--invitation .hero__copy::first-letter {
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    float: none;
    margin: 0;
    color: inherit;
  }

  .hero--invitation .hero__actions {
    gap: 14px;
  }

  .hero--invitation .hero__actions .button:not(.button--ghost) {
    width: 100%;
    min-height: 48px;
  }

  /* The secondary is a link on a phone too, but centred under the full-width
     primary rather than stretched to match it. */
  .hero--invitation .hero__actions .button--ghost {
    width: auto;
    margin-inline: auto;
  }

  .hero__occasions {
    gap: 7px 10px;
    margin-bottom: 13px;
    padding-bottom: 12px;
  }

  .occ-pill {
    padding: 7px 12px;
    font-size: 0.7rem;
  }

  .hero__seal {
    width: 36px;
    height: 36px;
  }

  .hero__seal--tl,
  .hero__seal--tr { top: -8px; }
  .hero__seal--bl,
  .hero__seal--br { bottom: -8px; }
  .hero__seal--tl,
  .hero__seal--bl { inset-inline-start: 10px; }
  .hero__seal--tr,
  .hero__seal--br { inset-inline-end: 10px; }

  .hero--invitation .hero__invite { padding-bottom: 15px; }

  .hero__stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  .hero--invitation .hero-stat strong { font-size: 1.34rem; }
  .hero--invitation .hero-stat span { font-size: 0.62rem; letter-spacing: 0.05em; }

  .site-footer__bottom::before { width: 30px; height: 30px; }
}

/* =====================================================================
   REDUCED MOTION ÃƒÂ¢Ã¢â€šÂ¬Ã¢â‚¬Â the page holds perfectly still
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .hero__photo { animation: none; }
  .hero__drift { display: none; }

  .hero__card {
    animation: none;
    opacity: 1;
    transform: none;
  }

  .hero--invitation .hero__invite-float {
    animation: none;
    transform: none;
    will-change: auto;
  }

  .hero__seal,
  .hero__seal::after,
  .hero__photo,
  .occ-pill { transition: none; }

  .hero__card:hover .hero__seal,
  .hero__card:focus-within .hero__seal { transform: none; }

  .hero__card:hover .hero__seal::after,
  .hero__card:focus-within .hero__seal::after {
    opacity: 0;
    transform: scaleY(0.2);
  }

  .occ-pill:hover { transform: none; }
}
