/* Katie & Jake hero: curtain intros A, B, C.
   Reads only these tokens from :root / [data-p]:
   --bg --ink --accent --line-ink --panel-fill --window --art-filter --names-filter --frame --frame2
   and --curtain (optional cloth colour; unset = her original white curtain)
   Fonts come from the page. url(art/...) resolves next to this file, i.e. hero/art/. */

.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;align-items:center;
  justify-content:center;padding:clamp(28px,5vh,56px) 16px clamp(56px,8vh,80px);text-align:center;overflow:hidden}
.hero::after{content:"";position:absolute;inset:clamp(8px,1.6vw,20px);border:var(--frame);outline:var(--frame2);
  outline-offset:-7px;pointer-events:none;z-index:1}

/* V1A: the names are a small logo at the top; SAVE THE DATE is the headline, bold Bodoni caps in wine, larger than
   "YOU'RE INVITED!" on her formal invite */
.hero{--w:min(420px,80vw,calc((100svh - 340px) * .75))}
.hero .names{margin:0 0 clamp(10px,2vh,20px);width:min(150px,36vw)}
.hero .headline{font-weight:700;font-size:clamp(26px,min(calc(var(--w) * .115),8.6vw),50px);line-height:1.05;letter-spacing:.07em;
  text-indent:.07em;text-transform:uppercase;color:var(--accent);margin:0 0 clamp(8px,1.8vh,18px);text-wrap:balance}
.hero .names img{display:block;width:100%;height:auto;filter:var(--names-filter)}

.hero .scene{position:relative;width:var(--w);aspect-ratio:1086/1448;
  margin:clamp(4px,1vh,12px) auto 0;transition:opacity .6s ease}
.hero .scene > *{position:absolute;inset:0;width:100%;height:100%}
.hero .scene img{display:block;max-width:none}
.hero .wwrap{transform-origin:50% 60%}
.hero .wwrap > *{position:absolute;inset:0;width:100%;height:100%}
.hero .backing{background:var(--window);
  -webkit-mask:url(art/water-backing.webp) center/100% 100% no-repeat;mask:url(art/water-backing.webp) center/100% 100% no-repeat}
/* her painting now runs edge to edge (tools/fill_window.py); the window shape comes from the mask */
/* the painting file is opaque (no alpha edges to fringe on iPhone); its outline comes from water-alpha, cut to the window */
.hero .water{will-change:filter;
  -webkit-mask:url(art/water-backing.webp) center/100% 100% no-repeat,url(art/water-alpha.webp) center/100% 100% no-repeat;-webkit-mask-composite:source-in;
  mask:url(art/water-backing.webp) center/100% 100% no-repeat,url(art/water-alpha.webp) center/100% 100% no-repeat;mask-composite:intersect}
.hero .glow{pointer-events:none;
  -webkit-mask:url(art/water-backing.webp) center/100% 100% no-repeat;mask:url(art/water-backing.webp) center/100% 100% no-repeat}
.hero .glow{background:radial-gradient(38% 30% at var(--gx,40%) var(--gy,35%),rgba(255,236,190,.55),transparent 70%);
  mix-blend-mode:soft-light;opacity:0}
.hero .scene.dark .glow{mix-blend-mode:screen}

/* her static drawing, and the two drapes that move once the intro is over. Only her curtains move; the painting is
   still (Katie 9/30: "maybe the curtains are just swaying a little as if wind is blowing"). ?idle= picks the motion:
   1 a gentle sway, 2 the sway plus a slow breath that flares the hems, 3 a gust about 3 s after the curtain settles, then every 10 to 11.5 s with rest between,
   4 a breeze that crosses the stage (both drapes lean the same way in turn), 0 none. Individual rotate/scale properties, so the two motions of idle 2 stack. */
.hero .lines,.hero .sway-l,.hero .sway-r{filter:var(--art-filter)}
.hero .sway-l,.hero .fab-l{transform-origin:12.9% 41.8%}
.hero .sway-r,.hero .fab-r{transform-origin:87.9% 35.9%}
.hero .scene.live.idle-1 .sway-l,.hero .scene.live.idle-1 .fab-l{animation:heroSwayL 7.5s ease-in-out infinite}
.hero .scene.live.idle-1 .sway-r,.hero .scene.live.idle-1 .fab-r{animation:heroSwayR 8.5s ease-in-out infinite}
.hero .scene.live.idle-2 .sway-l,.hero .scene.live.idle-2 .fab-l{animation:heroSwayL 7.5s ease-in-out infinite,heroBreath 11s ease-in-out infinite}
.hero .scene.live.idle-2 .sway-r,.hero .scene.live.idle-2 .fab-r{animation:heroSwayR 8.5s ease-in-out infinite,heroBreath 12.5s ease-in-out -3s infinite}
.hero .scene.live.idle-3 .sway-l,.hero .scene.live.idle-3 .fab-l{animation:heroGustL 10s ease-in-out -2.6s infinite}
.hero .scene.live.idle-3 .sway-r,.hero .scene.live.idle-3 .fab-r{animation:heroGustR 11.5s ease-in-out -2.2s infinite}
/* 4 a breeze crossing the stage: both drapes lean the same way, the right one a beat after the left, larger than 1 */
.hero .scene.live.idle-4 .sway-l,.hero .scene.live.idle-4 .fab-l{animation:heroBreezeL 9s ease-in-out infinite}
.hero .scene.live.idle-4 .sway-r,.hero .scene.live.idle-4 .fab-r{animation:heroBreezeR 9s ease-in-out infinite}
/* every motion starts and ends at rest, so the drapes ease into the breeze instead of snapping */
@keyframes heroSwayL{0%,100%{rotate:0deg}25%{rotate:-.35deg}75%{rotate:.42deg}}
@keyframes heroSwayR{0%,100%{rotate:0deg}25%{rotate:.33deg}75%{rotate:-.4deg}}
@keyframes heroBreezeL{0%,100%{rotate:0deg}30%{rotate:.85deg}60%{rotate:-.3deg}80%{rotate:.1deg}}
@keyframes heroBreezeR{0%,12%,100%{rotate:0deg}42%{rotate:.8deg}70%{rotate:-.28deg}88%{rotate:.08deg}}
@keyframes heroBreath{0%,100%{scale:1 1}50%{scale:1.022 1.006}}
@keyframes heroGustL{0%,58%,100%{rotate:0deg}64%{rotate:-.75deg}71%{rotate:.5deg}78%{rotate:-.28deg}85%{rotate:.12deg}92%{rotate:-.04deg}}
@keyframes heroGustR{0%,58%,100%{rotate:0deg}64%{rotate:.7deg}71%{rotate:-.46deg}78%{rotate:.26deg}85%{rotate:-.11deg}92%{rotate:.04deg}}

/* with WebGL the canvas paints the curtain and then the living painting; the plain image steps aside for good.
   Her ink lines fade in over the animated ink at the end (hero.js), so the handoff never dims. */
.hero .curtain{pointer-events:none;opacity:0}
/* the canvas reaches past the scene box, so moving cloth is never cut at its edge (hero.js PAD matches these) */
.hero .scene > .curtain{inset:auto;left:-8%;top:-3%;width:116%;height:106%}
.hero .scene.gl .curtain{opacity:1}
.hero .scene.gl .wwrap{opacity:0}
/* the data video stays rendered (Safari will not decode a display:none video) but invisible */
.hero .hero-vid{position:fixed;left:0;top:0;width:2px;height:2px;opacity:0;pointer-events:none}

/* date and city as on her approved save the date card: the date in regular Bodoni with wide tracking, the city right
   under it in bold caps at about the same width, stacked tight below the curtain hem (the scene box has ~16% of its
   width of floor below the hems, taken back with the negative margin) */
.hero .date{font-weight:400;font-size:clamp(14px,calc(var(--w) * .043),19px);letter-spacing:.26em;text-indent:.26em;color:var(--accent);
  margin:calc(var(--w) * -.14) 0 0;font-variant-numeric:lining-nums;line-height:1.3}
.hero .date span{display:inline-block}
.hero .city{font-weight:700;font-size:clamp(16px,calc(var(--w) * .051),23px);letter-spacing:.06em;text-indent:.06em;color:var(--accent);
  margin:.1em 0 0;text-transform:uppercase;line-height:1.2}

/* first paint: her closed curtain in the line colour, from one 25 KB alpha image, before any script runs */
.hero .poster{pointer-events:none}
.hero .poster > *{position:absolute;inset:0}
.hero .poster .pi{background:var(--line-ink);
  -webkit-mask:url(art/curtain-poster.webp) center/100% 100% no-repeat;mask:url(art/curtain-poster.webp) center/100% 100% no-repeat}
.hero .poster .pf{background:var(--curtain,transparent);
  -webkit-mask:url(art/curtain-poster-fabric.webp) center/100% 100% no-repeat;mask:url(art/curtain-poster-fabric.webp) center/100% 100% no-repeat}
.hero .poster.off{visibility:hidden}
/* B opens full screen: until hero.js sets the camera, place the poster where the camera will start
   (camStart() in hero.js: the scene scaled to cover the viewport x1.08, its 46% line on the viewport centre) */
[data-v="b"] .hero.pre .poster{position:fixed;inset:auto;left:50%;top:50vh;top:50svh;height:auto;aspect-ratio:1086/1448;
  width:calc(max(100vw, 100vh * 1086 / 1448) * 1.08);width:calc(max(100vw, 100svh * 1086 / 1448) * 1.08);transform:translate(-50%,-46%)}
/* C draws the curtain from nothing, so it has no poster */
[data-v="c"] .hero .poster{display:none}

/* before the intro plays */
.hero.pre .headline,.hero.pre .names,.hero.pre .date,.hero.pre .city,.hero.pre .scene > :not(.poster){opacity:0}
/* ?t= review frames are exact: no transitions in flight */
.frozen .hero *,.frozen .hero *::before,.frozen .hero *::after{transition:none!important}

/* ?review: A / B / C switcher */
.hero-rev{position:fixed;left:50%;bottom:14px;transform:translateX(-50%);z-index:50;display:flex;gap:6px;align-items:center;
  background:rgba(250,249,246,.94);border:1px solid rgba(35,31,28,.18);border-radius:999px;padding:6px;box-shadow:0 8px 24px rgba(0,0,0,.08);
  font:700 11px/1 Georgia,serif;letter-spacing:.14em;text-transform:uppercase}
.hero-rev a,.hero-rev button{font:inherit;letter-spacing:inherit;text-transform:inherit;border:0;background:transparent;color:#231F1C;
  padding:9px 12px;border-radius:999px;cursor:pointer;text-decoration:none}
.hero-rev .on{background:#7C3341;color:#fff}

@media (prefers-reduced-motion:reduce){
  .hero .poster{display:none}
  .hero .scene.live .sway-l,.hero .scene.live .sway-r,.hero .scene.live .fab-l,.hero .scene.live .fab-r{animation:none!important}
  .hero *,.hero *::before,.hero *::after{transition:none!important}
}

/* ---------- data-layout="v1a": the layout Katie reviewed (commit 056b3db), on today's renderer ----------
   big names lettering with the small "Save the Date" eyebrow above, the spaced date and city, the Scroll cue,
   falling leaves, moving light and the rigid drape sway she saw. Markup: hero-v1a.html. */
[data-layout="v1a"] .hero .eyebrow{font-weight:700;font-size:clamp(12px,1.3vw,14px);letter-spacing:.32em;text-indent:.32em;
  text-transform:uppercase;color:var(--accent);margin:0 0 clamp(10px,1.6vh,18px)}
[data-layout="v1a"] .hero .names{margin:0;width:min(340px,64vw)}
[data-layout="v1a"] .hero .date{font-weight:400;font-size:clamp(22px,3vw,30px);letter-spacing:.34em;text-indent:.34em;
  margin:clamp(6px,1.4vh,14px) 0 0;line-height:1.55}
[data-layout="v1a"] .hero .city{font-weight:700;font-size:clamp(17px,2.2vw,22px);letter-spacing:.12em;text-indent:.12em;
  margin:2px 0 0;line-height:1.55}
[data-layout="v1a"] .hero .cue{position:absolute;left:50%;bottom:18px;transform:translateX(-50%);font-size:11px;letter-spacing:.3em;
  text-transform:uppercase;color:var(--accent);text-decoration:none;opacity:.75;display:flex;flex-direction:column;align-items:center;gap:8px}
[data-layout="v1a"] .hero .cue::after{content:"";width:1px;height:28px;background:currentColor;transform-origin:top;animation:heroCue 2.4s ease-in-out infinite}
@keyframes heroCue{0%{transform:scaleY(0)}50%{transform:scaleY(1);transform-origin:top}51%{transform-origin:bottom}100%{transform:scaleY(0);transform-origin:bottom}}
[data-layout="v1a"] .hero .leaves{pointer-events:none;
  -webkit-mask:url(art/water-backing.webp) center/100% 100% no-repeat;mask:url(art/water-backing.webp) center/100% 100% no-repeat}
[data-layout="v1a"] .hero.pre .eyebrow,[data-layout="v1a"] .hero.pre .cue{opacity:0}
[data-layout="v1a"] .hero .scene.live .sway-l{animation:heroSwayL 7.5s ease-in-out infinite}
[data-layout="v1a"] .hero .scene.live .sway-r{animation:heroSwayR 8.5s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  [data-layout="v1a"] .hero .cue::after,[data-layout="v1a"] .hero .scene.live .sway-l,[data-layout="v1a"] .hero .scene.live .sway-r{animation:none!important}
}
