/* ═══════════════════════════════════════════════════════════════════
   MUDRIKA — శంఖం
   Two conches on carved stands, in the deep green light off the coast,
   with one low raking sun running along the whorl.

   The engagement line now has four grounds and no two share an hour of
   the day. Tambulam is full forenoon on sandal cream; Lagna Patrika is
   an oil lamp raking across parchment; Pasupu Kumkum is granite after
   the lamps are lit. This one is FIRST LIGHT ON WATER — which is both
   why the ground is sea green rather than another neutral, and why the
   only warm thing on the page is a single low sun. A conch is the one
   object in a Telugu house that came out of the sea, and putting it on
   any other ground would have thrown that away.

   Dark grounds are not light grounds with the numbers flipped, and the
   places that differ are marked below: the grain has to be heavier, the
   hero veil is a SHADOW rather than a scrim, the cards need a hairline
   because a dark card on a dark band has no edge of its own, and every
   piece of body copy sits a step brighter than it would on cream.

   Layout lives HERE, not in utility classes. Tailwind's inline config
   is the colour contract only — the utilities themselves must never be
   load-bearing, because the stylesheet the CDN generates is not
   guaranteed to be applied by the time the page is read, and the class
   ORDER in the markup does not decide which of two utilities wins.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* ── deep navy: the dark half of the alternation ── */
  --navy-300:#4a6296; --navy-400:#33477a; --navy-500:#22335c;
  --navy-600:#17243f; --navy-700:#101a2e; --navy-800:#0a1120;
  --navy-900:#060a14;
  /* ── soft gold: the light half, and the accent on navy ── */
  --gold-100:#faf3e2; --gold-200:#f3e7cb; --gold-300:#e8d5a8;
  --gold-400:#d9b871; --gold-500:#b4934f; --gold-600:#8e7139;
  /* ── the type ── */
  --ivory-50:#fffdf7; --ivory-100:#f7f1e4; --ivory-200:#e6ddca;
  --ivory-300:#c9bda4; --ivory-400:#9c9280; --ivory-500:#7b7361;

  /* Role tokens. Everything below reads these, so a reskin is this block
     plus the tailwind.config in the head and nothing else. */
  --bg:var(--navy-700); --bg-2:var(--navy-800);
  --fg:var(--ivory-200); --fg-hi:var(--ivory-50);
  --accent:var(--gold-400); --accent-hi:var(--gold-300);
  --accent-soft:rgba(217,184,113,.34);
  --hair:rgba(217,184,113,.18); --hair-strong:rgba(217,184,113,.34);
  --card:var(--navy-600); --shadow:rgba(0,0,0,.7);

  --display:"Gilda Display",Georgia,serif;
  --serif:"Newsreader",Georgia,serif;
  --script:"Allura",cursive;
  --sans:"Manrope",system-ui,sans-serif;
  --ease-luxe:cubic-bezier(.22,1,.36,1);
  --ease-soft:cubic-bezier(.4,0,.2,1);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;overflow-x:hidden;background:var(--bg);color:var(--fg);
  font-family:var(--sans);font-weight:400;line-height:1.7;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
img{max-width:100%;height:auto;display:block}
::selection{background:rgba(242,233,210,.3);color:var(--ivory-50)}

/* small helpers the markup uses — defined here so nothing depends on a
   utility framework having been applied */
.text-center{text-align:center}
.font-telugu{font-family:"Noto Serif Telugu",var(--serif)}
.font-script{font-family:var(--script)}

/* Themed scrollbar — a silver rail on deep water, never the OS default grey */
html{scrollbar-width:thin;scrollbar-color:var(--plat-400) var(--blue-900)}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:var(--blue-900)}
::-webkit-scrollbar-thumb{border-radius:99px;border:2px solid var(--blue-900);
  background:linear-gradient(180deg,var(--plat-300),var(--plat-500))}
::-webkit-scrollbar-thumb:hover{background:var(--plat-200)}
::-webkit-scrollbar-corner{background:var(--blue-900)}

[data-reveal]{opacity:0;will-change:transform,opacity,filter}
:focus-visible{outline:2px solid var(--gold-400);outline-offset:3px;border-radius:4px}

/* Fixed grain. Flat vector gradients read as sterile; this breaks the
   digital evenness without costing a request.
   HEAVIER than on the library's cream pages, which run this at .028. On
   a light ground that much noise reads as dirt on paper; on deep water
   the same value is invisible, and the large flat darks are exactly
   where banding in a gradient shows up worst. pointer-events:none so it
   can never swallow a tap. */
body::after{content:"";position:fixed;inset:0;z-index:60;pointer-events:none;
  opacity:.05;transform:translateZ(0);
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
  background-size:140px 140px}

/* ═══ 1 · HERO — two conches at first light ═══════════════════════
   Viewport height, done the only way that survives the Tailwind CDN:
   two declarations of the same property in one rule. Two utilities
   (min-h-screen min-h-[100svh]) do NOT cascade by class order — the
   generated sheet decides, .min-h-screen is emitted last, so 100vh wins
   and svh never applies. That is backwards: on iOS 100vh is the TALL
   value measured under the collapsing toolbar. */
.hero{position:relative;display:flex;flex-direction:column;align-items:center;
  justify-content:flex-start;width:100%;overflow:hidden;text-align:center;
  min-height:100vh;min-height:100svh;
  /* Every pixel the type block takes is a pixel the framing solver has to
     take away from the conches, so the top padding is deliberately tight
     on a phone and only opens up where there is room for it. */
  padding:clamp(40px,6.5vh,126px) clamp(18px,5vw,34px) clamp(96px,20vh,248px);
  /* The morning, before the 3D draws a thing. A low warm sun on the left,
     the wet floor picking it up, and deep green everywhere the light does
     not reach — so a device that cannot run WebGL still gets a lit room
     rather than a flat rectangle.

     THE TOP TWO THIRDS ARE ONE FLAT COLOUR ON PURPOSE, and it is the same
     #16283f that script.js gives THREE.Fog. The floor has to stop
     somewhere, and wherever it stops it draws a horizontal line across
     the full width of the hero. Fog takes it down into the dark before
     that edge is reached — but only into the FOG's colour, so if the page
     behind it is a gradient the boundary comes straight back as a tonal
     step.

     It has to be flat this FAR DOWN because of where this hero's horizon
     falls. Pasupu Kumkum looks steeply down at a slab and its horizon sits
     in the top third, so a flat band to 38% covers it. This camera is
     nearly level with the floor — which is the whole point of the raking
     light — so the horizon lands somewhere between 40% and 62% depending
     on what the framing solver did with the aim, and the first pass put a
     gradient stop right through the middle of that range. The step came
     back across the full width. The tonal life is carried by the two
     radial washes above instead, which vary smoothly enough that crossing
     the horizon costs nothing. */
  background:
    
    
    radial-gradient(46% 32% at 18% 2%, rgba(217,184,113,.10) 0%, transparent 72%),
    radial-gradient(128% 56% at 50% 104%, rgba(74,98,150,.20) 0%, transparent 74%),
    linear-gradient(180deg,#0a1120 0%,#101a2e 46%,#17243f 78%,#0d1626 100%)}
#mudrika-scene{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:0}
/* On a dark hero the veil is a SHADOW, not a scrim: it puts the type back
   on top of the bright water instead of lifting it off a pale ground, and
   it closes the bottom edge so the floor does not simply stop. */
.hero-veil{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(180deg,rgba(6,10,20,.72) 0%,rgba(6,10,20,.28) 26%,transparent 50%),
    linear-gradient(0deg,rgba(6,10,20,.55) 0%,rgba(6,10,20,.16) 9%,transparent 20%)}

/* The prompt sits in the clear strip BELOW the conches, so the closed
   hero reads top-to-bottom as light, subject, invitation-to-tap — and the
   shells get the whole middle of the frame instead of the bottom two
   thirds of it. The framing solver knows: while the gate is shut this
   block is the BOTTOM constraint, not the top one (see cueTop() in
   script.js).

   It is a wide rule-style flourish — never a flat drawing of the subject
   on top of the subject, which reads as a rendering bug. */
.hero-open{position:absolute;left:50%;bottom:clamp(54px,11vh,132px);transform:translateX(-50%);
  z-index:12;display:flex;flex-direction:column;align-items:center;cursor:pointer;
  padding:14px 20px;transition:opacity .9s var(--ease-luxe),transform .9s var(--ease-luxe)}
.hero-open.is-open{opacity:0;transform:translateX(-50%) translateY(16px);pointer-events:none}
.open-orn{width:clamp(190px,34vw,330px);color:var(--plat-200);opacity:.72}
.open-orn svg{width:100%;height:auto}
.open-hint{display:inline-flex;align-items:center;gap:11px;margin:24px 0 0;white-space:nowrap;
  font-size:11px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;
  color:var(--ivory-100);padding:14px 30px 14px calc(30px + .26em);
  border:1px solid var(--accent-soft);border-radius:999px;background:rgba(20,36,64,.62);
  backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
  box-shadow:0 12px 34px -18px #000,inset 0 1px 0 rgba(255,253,246,.09);
  transition:border-color .6s var(--ease-luxe),background-color .6s var(--ease-luxe)}
.hero-open:hover .open-hint{border-color:var(--gold-400);background:rgba(39,70,127,.8)}
@media (max-width:400px){.open-hint{font-size:10px;letter-spacing:.16em;padding:12px 20px}}
.open-dot{width:6px;height:6px;border-radius:50%;background:var(--gold-400);flex:none;
  box-shadow:0 0 12px 3px rgba(242,233,210,.6);
  animation:openPulse 2.6s var(--ease-soft) infinite}
@keyframes openPulse{0%,100%{opacity:.4;transform:scale(.8)}50%{opacity:1;transform:scale(1.35)}}

/* All four locks are needed — overflow:hidden alone loses to Lenis. */
body.gate-shut{overflow:hidden;position:fixed;inset:0;width:100%;height:100%;
  overscroll-behavior:none}

/* margin-inline:auto is REQUIRED: without it the whole hero block sits at
   the left edge on a wide screen, and a phone-shaped device gate cannot
   see it, because below the max-width full-width and centred are the
   same pixels. */
.hero-in{position:relative;z-index:10;width:100%;max-width:940px;margin-inline:auto;
  text-align:center}
.hero-eyebrow{margin:0;font-size:clamp(10px,1.5vw,12px);font-weight:500;letter-spacing:.4em;
  text-transform:uppercase;color:var(--gold-300);padding-left:.4em}
.hero-names{margin:18px 0 0;display:flex;align-items:center;justify-content:center;
  gap:clamp(12px,2.8vw,34px);flex-wrap:wrap}
/* Sized against the SHORTER of the two axes. A width-only clamp set the
   names at 96px on a 1280x720 laptop, where the type block then ate most
   of a 720px frame and the framing solver had to shrink the subject to a
   thumbnail to clear it. Height is the scarce axis in this hero.
   The glow is not decoration: the display face is a high-contrast serif
   whose hairlines are a pixel at this size, and against moving water they
   flicker without something soft sitting behind them. */
.hero-name{font-family:var(--display);font-weight:400;
  font-size:clamp(38px,min(8vw,9.6vh),88px);
  line-height:1.12;letter-spacing:-.006em;color:var(--ivory-50);
  text-shadow:0 2px 34px rgba(13,24,40,.95),0 0 60px rgba(242,233,210,.14)}
.hero-amp{width:clamp(54px,7.4vw,86px);color:var(--gold-400);flex:none}
.hero-amp svg{width:100%;height:auto}
.hero-telugu{margin:14px 0 0;font-size:clamp(15px,2.1vw,21px);color:var(--ivory-200);opacity:.9}
.hero-rule{width:132px;height:1px;margin:24px auto 0;
  background:linear-gradient(90deg,transparent,var(--plat-300),transparent)}
.hero-date{margin:18px 0 0;font-size:clamp(10px,1.5vw,13px);font-weight:400;letter-spacing:.28em;
  text-transform:uppercase;color:var(--ivory-300);padding-left:.28em}
#open-invite{margin-top:clamp(22px,3.4vh,42px)}

/* ═══ Bands & layout ══════════════════════════════════════════════
   Two greens alternating and one loud band for the wedding date. A dark
   page cannot alternate light and dark the way a cream one does, so the
   rhythm has to come from how much warm light each band is given. */
.band{position:relative;overflow:hidden;padding:clamp(66px,9vw,116px) 0 clamp(78px,11vw,150px)}
.band-navy{background:
  radial-gradient(96% 58% at 50% 0%, rgba(74,98,150,.22), transparent 62%),
  linear-gradient(180deg,var(--navy-700) 0%,var(--navy-600) 100%);
  color:var(--ivory-200)}
/* THE LIGHT HALF. Every section alternates navy, gold, navy, gold — so the
   two colours are visibly the page's structure rather than a tint on one
   ground. A light band needs its OWN type colours, because everything below
   is written for ivory on navy and would disappear into it. */
.band-gold{background:
  radial-gradient(90% 60% at 50% 0%, rgba(217,184,113,.20), transparent 66%),
  linear-gradient(180deg,var(--gold-100) 0%,var(--gold-200) 100%);
  color:var(--navy-600)}
.band-gold .h2,.band-gold .fam-names,.band-gold .detail-h,.band-gold .tl-name,
.band-gold .venue-name,.band-gold .person-name,.band-gold .wed-date{color:var(--navy-700)}
.band-gold .lede,.band-gold .fam-note,.band-gold .detail-p,.band-gold .tl-note,
.band-gold .venue-addr,.band-gold .venue-note,.band-gold .person-note,
.band-gold .bless-quote,.band-gold .fam-join,.band-gold .reveal-hint,
.band-gold .count-when,.band-gold .wed-note,.band-gold .foot-meta{color:var(--navy-500)}
.band-gold .kicker,.band-gold .script-xl,.band-gold .fam-side,.band-gold .fam-town,
.band-gold .tl-when,.band-gold .person-role,.band-gold .bless-src,
.band-gold .count-label,.band-gold .f-label,.band-gold .count-num,
.band-gold .wed-hour,.band-gold .wed-place{color:var(--gold-600)}
.band-gold .orn-rule,.band-gold .bless-mark{color:var(--gold-500)}
.band-gold .f-fine{color:var(--navy-400)}
.band-gold .fam-card,.band-gold .detail-card,.band-gold .card,
.band-gold .count-box{background:var(--ivory-50);
  border-color:rgba(16,26,46,.14);
  box-shadow:0 1px 2px rgba(16,26,46,.06),0 18px 40px -26px rgba(16,26,46,.30)}
.band-gold .f-in{color:var(--navy-700);border-bottom-color:rgba(16,26,46,.28)}
.band-gold .f-in::placeholder{color:rgba(16,26,46,.42)}
.band-gold .tl-spine{background:rgba(16,26,46,.18)}
.band-gold .tl-dot{background:var(--ivory-50);border-color:var(--gold-500)}
.band-gold .btn-line{color:var(--navy-600);border-color:rgba(16,26,46,.34);
  background:rgba(255,253,247,.6)}
.band-gold .fam-rule,.band-gold .wed-rule{background:var(--gold-500)}
.band-gold .venue-map iframe{filter:saturate(.9) contrast(1)}
.band-accent{background:
  radial-gradient(88% 72% at 50% 0%, rgba(217,184,113,.26), transparent 62%),
  linear-gradient(135deg,var(--navy-900) 0%,var(--navy-700) 46%,var(--navy-600) 100%);
  color:var(--ivory-100)}
.band-accent + .band::before,.band + .band-accent::before{display:none}

.wrap{position:relative;z-index:1;max-width:1080px;margin:0 auto;padding:0 clamp(20px,5vw,40px)}
.wrap-sm{position:relative;z-index:1;max-width:700px;margin:0 auto;padding:0 clamp(20px,5vw,40px)}
.head{margin-bottom:clamp(34px,5.4vw,62px)}

/* ═══ Type ════════════════════════════════════════════════════════
   Display type needs NEGATIVE tracking and tight leading; small caps
   need positive. Setting both at the same tracking is what makes a
   headline read as merely "large text".

   Body copy runs one step brighter than the cream pages' equivalent.
   pearl-200 on sea-700 is the same contrast ratio ink-600 has on sandal,
   but light-on-dark reads thinner at the same weight, so the body serif
   is set at 400 where a light page would use 300. */
.kicker{display:inline-flex;align-items:center;gap:10px;margin:0;font-size:10.5px;font-weight:500;
  letter-spacing:.32em;text-transform:uppercase;color:var(--gold-300);padding-left:.32em}
.band-accent .kicker{color:var(--gold-300)}
.kicker-c{display:block;text-align:center}
/* the families' line under the invitation message — a .kicker carries no
   top margin of its own because inside .head it sits first */
.lede + .kicker-c{margin-top:clamp(28px,4vw,42px)}
.h2{font-family:var(--display);font-weight:400;font-size:clamp(28px,4.4vw,50px);
  line-height:1.16;letter-spacing:-.004em;text-align:center;text-wrap:balance;
  margin:14px 0 0;color:var(--ivory-50)}
.band-accent .h2{color:var(--ivory-50)}
.h2-tight{margin-top:6px}
.lede{font-family:var(--serif);font-weight:400;font-size:clamp(18px,2.2vw,23px);line-height:1.78;
  color:var(--ivory-200);margin:26px auto 0;max-width:62ch;text-wrap:pretty}
.script-xl{font-family:var(--script);font-size:clamp(40px,6vw,68px);line-height:1.2;
  color:var(--gold-300);margin:26px 0 0}
.orn-rule{width:clamp(190px,32vw,272px);margin:0 auto;color:var(--plat-300)}
.orn-rule svg{width:100%;height:auto}

/* ═══ 3 · The two ═════════════════════════════════════════════════
   Arched frames — the shape of a mandapam doorway, and the shape both
   families walk through on the morning. On a dark band a photograph is
   the brightest thing in the frame, so the inner shadow is heavier than
   a light page needs: without it the picture floats. */
.couple-grid{display:grid;grid-template-columns:1fr auto 1fr;gap:clamp(22px,5vw,64px);
  align-items:start}
.person{text-align:center;min-width:0}
.person-frame{position:relative;overflow:hidden;
  border-radius:50% 50% 8px 8px / 30% 30% 5px 5px;
  box-shadow:0 44px 74px -44px #000}
.person-frame::after{content:"";position:absolute;inset:0;pointer-events:none;
  border-radius:inherit;box-shadow:inset 0 0 0 1px rgba(255,248,231,.38);
  background:linear-gradient(180deg,transparent 52%,rgba(13,24,40,.6) 100%)}
.person-frame img{aspect-ratio:4/5;object-fit:cover;width:100%;filter:saturate(1.02) contrast(1.02);
  transition:transform 1.5s var(--ease-luxe),filter 1.5s var(--ease-luxe)}
@media (hover:hover){.person:hover .person-frame img{transform:scale(1.045);filter:saturate(1.1)}}
.person-name{font-family:var(--display);font-weight:400;font-size:clamp(24px,3.2vw,34px);
  margin:26px 0 0;color:var(--ivory-50)}
.person-role{font-size:10.5px;font-weight:500;letter-spacing:.24em;text-transform:uppercase;
  color:var(--gold-300);margin:12px 0 0;padding-left:.24em}
.person-note{font-family:var(--serif);font-style:italic;font-size:18px;
  color:var(--ivory-300);margin:14px 0 0}
/* a stem between them, not a plain rule */
.couple-stem{align-self:stretch;display:flex;flex-direction:column;align-items:center;
  margin-top:52px;gap:10px}
.couple-stem i{flex:1;width:1px;min-height:40px;
  background:linear-gradient(180deg,transparent,rgba(255,248,231,.5))}
.couple-stem i:last-child{background:linear-gradient(0deg,transparent,rgba(255,248,231,.5))}
.couple-stem b{width:7px;height:7px;border-radius:50%;background:var(--gold-400);flex:none;
  box-shadow:0 0 14px 4px rgba(242,233,210,.4)}
@media (max-width:860px){
  .couple-grid{grid-template-columns:1fr;gap:48px}
  .couple-stem{flex-direction:row;margin:0 auto;width:120px;align-self:center}
  .couple-stem i{min-height:0;height:1px;width:auto;
    background:linear-gradient(90deg,transparent,rgba(255,248,231,.5))}
  .couple-stem i:last-child{background:linear-gradient(270deg,transparent,rgba(255,248,231,.5))}
}

/* ═══ 4 · Families ════════════════════════════════════════════════
   Two columns of DELIBERATELY equal weight. On a wedding page the
   families are a supporting band; on an engagement page the agreement
   between them is the entire event, so neither side may read as the
   host and the other as the guest.

   A dark card on a dark band has no silhouette of its own — a light
   page can lift a card with a shadow alone, and here that does nothing.
   The card is lifted with a hairline and a top-edge highlight instead,
   which is how a silver-bound box sits on a wet floor. */
.fam-grid{display:grid;gap:26px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.fam-card{padding:40px 30px;text-align:center;border-radius:16px;
  background:linear-gradient(180deg,var(--blue-600),var(--blue-800));
  border:1px solid var(--hair);
  box-shadow:0 26px 54px -30px #000,inset 0 1px 0 rgba(255,253,246,.07);
  transition:transform .6s var(--ease-luxe),border-color .6s var(--ease-luxe)}
@media (hover:hover){.fam-card:hover{transform:translateY(-4px);border-color:var(--hair-strong)}}
.fam-side{margin:0;font-size:10px;font-weight:500;letter-spacing:.28em;text-transform:uppercase;
  color:var(--gold-300);padding-left:.28em}
.fam-names{font-family:var(--display);font-weight:400;font-size:clamp(18px,2.1vw,23px);
  color:var(--ivory-50);margin:16px 0 0;line-height:1.44}
.fam-rule{width:44px;height:1px;margin:18px auto;background:var(--plat-400)}
.fam-note{font-family:var(--serif);font-style:italic;font-size:17px;color:var(--ivory-300);margin:0}
.fam-town{margin:14px 0 0;font-size:10px;font-weight:500;letter-spacing:.26em;
  text-transform:uppercase;color:var(--plat-200);padding-left:.26em}
.fam-join{text-align:center;font-family:var(--serif);font-style:italic;
  font-size:clamp(17px,2.1vw,21px);color:var(--ivory-300);margin:clamp(30px,4vw,46px) auto 0;
  max-width:46ch}

/* ═══ 5 · Countdown, behind the sounding ══════════════════════════ */
.reveal-hint{font-family:var(--serif);font-style:italic;font-size:clamp(16px,2vw,20px);
  color:var(--ivory-300);margin:0 auto;max-width:46ch}
.scratch-wrap{position:relative;max-width:600px;margin:clamp(30px,4.4vw,52px) auto 0;
  overflow:hidden;border-radius:18px;touch-action:none}
.count-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(8px,1.6vw,16px)}
.count-box{padding:26px 8px;text-align:center;border-radius:14px;
  background:linear-gradient(180deg,var(--blue-600),var(--blue-800));
  border:1px solid var(--hair);
  box-shadow:0 18px 38px -22px #000,inset 0 1px 0 rgba(255,253,246,.06)}
.count-num{display:block;font-family:var(--display);font-weight:400;
  font-size:clamp(24px,4.2vw,42px);line-height:1;color:var(--gold-300);
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.count-label{display:block;font-size:9.5px;font-weight:500;letter-spacing:.24em;
  text-transform:uppercase;color:var(--ivory-400);margin-top:11px;padding-left:.24em}
.scratch-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:3;cursor:grab;
  border-radius:18px;transition:opacity .9s var(--ease-luxe)}
.scratch-canvas:active{cursor:grabbing}
.scratch-canvas.done{opacity:0;pointer-events:none}
.scratch-label{position:absolute;inset:auto 0 14px;z-index:4;margin:0;pointer-events:none;
  text-align:center;font-size:10px;font-weight:600;letter-spacing:.3em;text-transform:uppercase;
  color:rgba(255,253,246,.8);padding-left:.3em;transition:opacity .5s var(--ease-luxe)}
.scratch-label.done{opacity:0}
.count-when{margin:clamp(30px,4.4vw,52px) 0 0;font-size:11px;font-weight:500;letter-spacing:.24em;
  text-transform:uppercase;color:var(--gold-300);padding-left:.24em}
@media (max-width:520px){.count-grid{grid-template-columns:repeat(2,1fr)}}

/* ═══ 6 · The morning ═════════════════════════════════════════════ */
.tl{position:relative;max-width:720px;margin-inline:auto;padding-left:38px}
.tl-spine{position:absolute;left:7px;top:8px;bottom:8px;width:1px;background:rgba(255,248,231,.14)}
.tl-spine i{position:absolute;inset:0;transform-origin:top;transform:scaleY(0);
  background:var(--plat-300)}
.tl-item{position:relative;padding-bottom:40px}
.tl-item:last-child{padding-bottom:0}
.tl-dot{position:absolute;left:-35px;top:11px;width:9px;height:9px;border-radius:50%;
  background:var(--blue-700);border:1px solid var(--plat-400);
  transition:background-color .6s var(--ease-luxe),box-shadow .6s var(--ease-luxe)}
@media (hover:hover){.tl-item:hover .tl-dot{background:var(--gold-400);
  border-color:var(--gold-400);box-shadow:0 0 14px 4px rgba(242,233,210,.34)}}
.tl-card{transition:transform .7s var(--ease-luxe)}
@media (hover:hover){.tl-item:hover .tl-card{transform:translateX(5px)}}
.tl-when{margin:0;font-size:10px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;
  color:var(--gold-300);padding-left:.26em}
.tl-name{font-family:var(--display);font-weight:400;font-size:clamp(19px,2.3vw,26px);
  color:var(--ivory-50);margin:10px 0 0}
.tl-note{font-family:var(--serif);font-size:17.5px;color:var(--ivory-300);margin:9px 0 0}

/* ═══ 7 · Venue ═══════════════════════════════════════════════════ */
.venue-grid{display:grid;gap:38px;grid-template-columns:1fr 1fr;align-items:stretch}
.venue-card{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  padding:14px 0;min-width:0}
.venue-name{font-family:var(--display);font-weight:400;font-size:clamp(22px,2.9vw,32px);
  color:var(--ivory-50);margin:0;line-height:1.28}
.venue-addr{font-family:var(--serif);font-size:19px;color:var(--ivory-200);margin:16px 0 0}
.venue-note{font-family:var(--serif);font-style:italic;font-size:17px;
  color:var(--ivory-400);margin:14px 0 0;max-width:52ch}
.venue-card .btn{margin-top:30px}
.venue-map{position:relative;overflow:hidden;min-height:330px;border-radius:18px;
  border:1px solid var(--hair);
  box-shadow:0 26px 54px -26px #000}
/* Google's map tiles are a bright white sheet, and dropped into a dark
   band untouched they are the brightest thing on the page by a mile.
   Inverting is wrong — the labels go negative and the roads read as
   rivers. Dimming and cooling it keeps the map a map. */
.venue-map iframe{position:absolute;inset:0;width:100%;height:100%;border:0;
  filter:saturate(.6) contrast(1.04) brightness(.76)}
@media (max-width:860px){.venue-grid{grid-template-columns:1fr}}

/* ═══ 8 · The wedding this morning fixes ══════════════════════════
   No wedding template in the library has this band, because no wedding
   invitation has a later date to hand over. */
.wed-date{font-family:var(--display);font-weight:400;font-size:clamp(30px,5.2vw,58px);
  line-height:1.14;letter-spacing:-.008em;color:#fff8e7;margin:clamp(22px,3vw,34px) 0 0;
  text-shadow:0 6px 40px rgba(80,26,10,.45)}
.wed-hour{margin:16px 0 0;font-size:clamp(11px,1.6vw,13px);font-weight:500;letter-spacing:.26em;
  text-transform:uppercase;color:rgba(255,246,238,.9);padding-left:.26em}
.wed-rule{width:96px;height:1px;margin:clamp(26px,3.4vw,38px) auto;
  background:linear-gradient(90deg,transparent,rgba(255,246,238,.8),transparent)}
.wed-place{margin:0;font-family:var(--script);font-size:clamp(34px,5vw,54px);line-height:1.2;
  color:rgba(255,246,238,.96)}
.wed-note{font-family:var(--serif);font-size:clamp(17px,2.1vw,20px);line-height:1.72;
  color:rgba(255,246,238,.86);margin:22px auto 0;max-width:50ch}

/* ═══ 9 · Details ════════════════════════════════════════════════ */
.detail-grid{display:grid;gap:24px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.detail-card{padding:34px 30px;text-align:center;border-radius:16px;
  background:linear-gradient(180deg,var(--blue-600),var(--blue-800));
  border:1px solid var(--hair);
  box-shadow:0 22px 46px -28px #000,inset 0 1px 0 rgba(255,253,246,.06);
  transition:transform .6s var(--ease-luxe),border-color .6s var(--ease-luxe)}
@media (hover:hover){.detail-card:hover{transform:translateY(-4px);border-color:var(--hair-strong)}}
.detail-card-gift{border-color:rgba(242,233,210,.34)}
.detail-h{font-family:var(--display);font-weight:400;font-size:21px;color:var(--ivory-50);margin:0}
.detail-p{font-family:var(--serif);font-size:17.5px;color:var(--ivory-300);margin:14px 0 0}

/* ═══ 10 · Gallery ════════════════════════════════════════════════
   One tall tile and four quarters: 4 + 1 + 1 + 1 + 1 fills four columns
   by two rows exactly, with no cell left standing empty. */
.gal-grid{display:grid;gap:14px;grid-template-columns:repeat(4,1fr);grid-auto-rows:188px}
.gal{position:relative;overflow:hidden;margin:0;border-radius:16px;
  box-shadow:0 20px 42px -20px #000;
  transition:transform .45s cubic-bezier(.2,.9,.25,1),box-shadow .45s ease}
.gal::after{content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  box-shadow:inset 0 0 0 1px rgba(255,248,231,.2)}
.gal img{width:100%;height:100%;object-fit:cover;filter:saturate(1);
  transition:transform .7s cubic-bezier(.2,.9,.25,1),filter .7s ease}
@media (hover:hover){
  .gal:hover{transform:translateY(-4px)}
  .gal:hover img{transform:scale(1.05);filter:saturate(1.08)}
}
.gal.g1{grid-column:span 2;grid-row:span 2}
.gal.g2,.gal.g3,.gal.g4,.gal.g5{grid-column:span 1}
@media (max-width:760px){
  .gal-grid{grid-template-columns:repeat(2,1fr);grid-auto-rows:148px}
  .gal.g1,.gal.g2,.gal.g5{grid-column:span 2}
}

/* ═══ 11 · Blessings ══════════════════════════════════════════════
   A quiet band, and the only place on the page where anyone speaks in
   the first person. The mark is three dashed rings — the note leaving
   the shell, drawn as the water would carry it. */
.bless-mark{width:clamp(86px,12vw,116px);margin:0 auto;color:var(--plat-300);opacity:.66}
.bless-mark svg{width:100%;height:auto}
.bless-quote{font-family:var(--serif);font-style:italic;font-size:clamp(20px,2.8vw,29px);
  line-height:1.6;color:var(--ivory-100);margin:clamp(26px,3.4vw,40px) auto 0;max-width:36ch;
  text-wrap:pretty}
.bless-src{margin:22px 0 0;font-size:10.5px;font-weight:500;letter-spacing:.24em;
  text-transform:uppercase;color:var(--gold-300);padding-left:.24em}

/* ═══ 12 · RSVP ═══════════════════════════════════════════════════ */
.card{margin:clamp(32px,4.6vw,52px) auto 0;padding:clamp(28px,4vw,48px);border-radius:20px;
  background:linear-gradient(180deg,var(--blue-600),var(--blue-800));
  border:1px solid var(--hair);text-align:left;
  box-shadow:0 44px 84px -48px #000,inset 0 1px 0 rgba(255,253,246,.07)}
.f-row + .f-row,.f-two + .f-row,.f-row + .f-two{margin-top:22px}
.f-two{display:grid;gap:22px;grid-template-columns:1fr 1fr}
@media (max-width:560px){.f-two{grid-template-columns:1fr}}
.f-label{display:block;font-size:10px;font-weight:600;letter-spacing:.24em;text-transform:uppercase;
  color:var(--gold-300);margin-bottom:9px;padding-left:.24em}
.f-in{width:100%;padding:13px 2px;background:transparent;color:var(--ivory-100);border:0;
  border-bottom:1px solid var(--hair-strong);font-family:var(--serif);font-size:19px;
  transition:border-color .5s var(--ease-luxe)}
.f-in::placeholder{color:var(--ivory-500)}
.f-in:focus{outline:none;border-bottom-color:var(--gold-400)}
/* A native <option> list is painted by the OS, not by this stylesheet, and
   on a dark form it comes back as black text on white. Colour the option
   itself so the open menu belongs to the page. */
.f-sel option{background:var(--blue-800);color:var(--ivory-100)}
.f-sel{cursor:pointer;appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c8ccd0' stroke-width='1.8'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 2px center;background-size:16px;
  padding-right:32px}
textarea.f-in{resize:none}
.f-fine{text-align:center;font-size:11.5px;color:var(--ivory-400);margin:20px 0 0}

/* ═══ Buttons ═════════════════════════════════════════════════════
   Nothing acknowledged a press before this. A button that does not move
   under the finger feels broken on a phone even when it works. */
.btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:10px;
  cursor:pointer;text-decoration:none;font-family:var(--sans);font-size:11.5px;font-weight:500;
  letter-spacing:.24em;text-transform:uppercase;border-radius:999px;
  transition:transform .3s cubic-bezier(.2,.9,.25,1),box-shadow .3s ease,
             background-color .4s ease,border-color .4s ease,color .4s ease}
@media (hover:hover){.btn:hover{transform:translateY(-2px)}}
.btn:active{transform:translateY(1px) scale(.985)}
.btn-line{padding:15px 34px 15px calc(34px + .24em);border:1px solid var(--hair-strong);
  background:rgba(39,70,127,.5);color:var(--ivory-100)}
.btn-line:hover{border-color:var(--gold-400);background:rgba(242,233,210,.16)}
.btn-solid{width:100%;margin-top:26px;padding:17px 34px 17px calc(34px + .24em);border:0;
  font-weight:600;color:#fff8e7;
  background:linear-gradient(135deg,var(--gold-400),var(--gold-500) 56%,var(--gold-600));
  box-shadow:0 16px 34px -16px rgba(179,170,146,.9),inset 0 0 0 1px rgba(255,253,246,.22)}
.btn-solid:hover{box-shadow:0 24px 44px -18px rgba(179,170,146,.95),
  inset 0 0 0 1px rgba(255,253,246,.44)}

.ic-round{position:fixed;top:22px;right:22px;z-index:120;display:grid;place-items:center;
  width:44px;height:44px;border-radius:50%;cursor:pointer;background:rgba(20,36,64,.7);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  border:1px solid var(--hair-strong);color:var(--gold-300);
  box-shadow:0 10px 26px -14px #000;
  transition:border-color .5s var(--ease-luxe),transform .5s var(--ease-luxe)}
.ic-round svg{width:18px;height:18px}
.ic-round:hover{border-color:var(--gold-400);transform:scale(1.06)}
@media (max-width:880px){.ic-round{top:auto;bottom:20px;right:16px}}

/* ═══ Footer ══════════════════════════════════════════════════════ */
.foot{position:relative;background:var(--blue-900);color:var(--ivory-300);padding:88px 0 0;
  text-align:center}
.foot::before{content:"";position:absolute;top:0;left:50%;width:min(460px,64%);height:1px;
  transform:translateX(-50%);background:linear-gradient(90deg,transparent,var(--plat-400),transparent)}
.foot-mark{width:70px;margin:0 auto;color:var(--plat-300)}
.foot-mark svg{width:100%;height:auto}
.foot-names{font-size:clamp(42px,6vw,66px);line-height:1.22;color:var(--gold-300);margin:20px 0 0}
.foot-rule{width:48px;height:1px;margin:20px auto;background:rgba(255,248,231,.5)}
.foot-meta{margin:0;font-size:10.5px;font-weight:500;letter-spacing:.28em;text-transform:uppercase;
  color:var(--ivory-400);padding-left:.28em}
.foot-tag{margin:14px 0 0;font-size:10.5px;font-weight:500;letter-spacing:.2em;
  color:var(--plat-200);padding-left:.2em}

/* ═══ Invitocraft bar — the studio's mark, on every template ══════ */
.ic-bar{margin-top:58px;padding:26px 26px 8px;border-top:1px solid rgba(255,248,231,.14)}
.ic-bar-in{max-width:44rem;margin:0 auto;display:flex;align-items:center;
  justify-content:space-between;gap:20px;flex-wrap:wrap}
.ic-brand{display:inline-flex;align-items:center;gap:12px;color:var(--plat-200);
  text-decoration:none;transition:color .4s var(--ease-luxe)}
.ic-brand:hover{color:var(--plat-100)}
.ic-seal{width:30px;height:30px;border-radius:50%;flex:none;background:var(--ivory-50);padding:3px;
  box-shadow:0 0 0 1px rgba(255,248,231,.42)}
.ic-made{font-size:12px;font-weight:400;letter-spacing:.06em;display:inline-flex;align-items:center;
  gap:6px}
.ic-made strong{font-weight:600;letter-spacing:.1em}
.ic-heart{width:13px;height:13px;color:var(--gold-400)}
.ic-cta{font-size:10.5px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;
  color:var(--plat-200);text-decoration:none;padding:10px 20px 10px calc(20px + .18em);
  border:1px solid rgba(255,248,231,.28);border-radius:999px;
  transition:border-color .4s var(--ease-luxe),color .4s var(--ease-luxe),
             transform .4s var(--ease-luxe)}
.ic-cta:hover{border-color:var(--plat-100);color:var(--gold-200);transform:translateY(-2px)}
.ic-fine{margin:20px 0 0;text-align:center;font-size:10.5px;letter-spacing:.14em;
  color:var(--ivory-500)}
@media (max-width:560px){.ic-bar-in{justify-content:center;text-align:center}}

/* ═══ Cursor glow ═════════════════════════════════════════════════ */
#cursor-glow{position:fixed;top:0;left:0;width:360px;height:360px;border-radius:50%;
  pointer-events:none;z-index:90;opacity:0;transform:translate(-50%,-50%);
  background:radial-gradient(circle,rgba(242,233,210,.1),transparent 66%)}
@media (hover:none),(pointer:coarse){#cursor-glow{display:none}}

/* No prefers-reduced-motion block, on purpose. iOS reports that flag
   whenever Low Power Mode is on — not only when Reduce Motion is set —
   so honouring it here would quietly hand most phone guests a lesser
   invitation than everyone else sees. The motion is one reveal the guest
   taps for plus slow ambient drift, with no parallax, flashing or
   large-scale travel. See the note at the top of script.js. */

/* Do not bounce past the ends where the browser will let us say so.
   Chrome and Android honour this; iOS Safari does NOT apply
   overscroll-behavior to the document scroller, only to nested ones,
   which is why the page-canvas colour below is the fix that lands. */
html{overscroll-behavior-y:none}

/* ═══ The page canvas ══════════════════════════════════════════════
   iOS Safari's page-level rubber-band cannot be turned off, so flinging
   to the bottom of a long page always exposes a strip below the content.
   Whatever is painted there is the CANVAS background, and the canvas
   takes html's background; only if html has none does it fall back to
   body's. Give html the colour the page ENDS in and it is fixed by
   definition rather than by covering it. On this template body and the
   footer are both dark, so the strip would have been survivable — it is
   still declared, because the value that makes it survivable is a
   palette choice and the next reskin should not have to rediscover the
   rule by shipping a bright band under the footer. */
html{background:#060a14}

/* body{overflow-x:hidden} forces overflow-y to compute to `auto`, which
   makes body a scroll container in its own right and lets it hold a
   scroll extent that can diverge from the viewport's. `clip` clips
   identically and creates no scroller. Guarded: Safari below 16 has no
   clip and keeps hidden. */
@supports (overflow-x:clip){ body{overflow-x:clip} }

/* ═══ Two names that will not fit on one line ═════════════════════
   The hero names are a flex row — name · ornament · name — and when the
   pair is too wide the row wraps wherever it runs out of room, which
   strands the ornament at the END of the first name and drops the second
   name alone underneath. That reads as one name with a mark after it
   rather than as two names joined.

   No CSS expresses "wrap all three or none": whether it wraps depends on
   how long this couple's names happen to be, not on the viewport, so
   script.js measures and sets this class. Each of the three then gets its
   own centred line.

   PHONES ONLY. On a wide screen the pair fits on one line and the class
   is never set anyway, so the media query changes nothing today — it is
   here as a guarantee that a desktop hero cannot be restacked by this,
   which is a layout that has been signed off as it stands. */
@media (max-width:900px){
  .hero-names.is-stacked{flex-direction:column;align-items:center;
    gap:clamp(2px,.8vw,10px)}
}
