/* ============================================================
   MERIDIAN — bright hero
   ADDITIVE. Loads AFTER assets/css/style.css and only adds.
   No reset, no body rule, no redefinition of the shared tokens —
   it reuses .btn / .brand / .avatars / .word / [data-anim] from
   style.css and the motion primitives from app.js.

   The house is a cut-out with alpha, so sky and house are separate
   layers that parallax against each other. Each layer's ENTRANCE is
   a transition on its <img>, while its PARALLAX is a JS transform on
   the wrapping element — two different nodes, so they never fight.
   01 Tokens · 02 Nav · 03 Scene · 04 Content · 05 UI
   06 Responsive · 07 Motion
   ============================================================ */

/* ── 01 · TOKENS (additions only) ────────────────────────── */
:root{
  --ink-sub:#1B2733;                     /* body copy over sky */

  --house-aspect:1.8066;                 /* hero-house.webp, 1700x941 */
  --house-w:min(2400px,116vw);           /* wider than the frame, so it bleeds */
  --house-h:calc(var(--house-w) / var(--house-aspect));
  /* How much of the house clears the fold. The second term is a floor-guard:
     the cut-out's base is landscaped down to ~y0.93 and then tapers, so
     revealing past ~82% starts to show it standing on nothing. Capping on
     the house's OWN height (rather than a vw guess) keeps the crop honest
     at every aspect ratio, so svh can drive the rest. */
  --house-show:min(50svh,calc(var(--house-h) * .82));
}

/* ── 02 · NAV over a bright hero ─────────────────────────── */
/* style.css builds the nav light-on-dark; on daylight it has to invert until
   it sticks. Scoped to the body class so the rest of the site is untouched. */
body.bright-hero .nav__inner{justify-content:flex-start;gap:clamp(1rem,3vw,2.6rem)}
/* Colour is scoped OUT of the open mobile menu: .menu__panel is var(--ink) and the
   burger draws in currentColor, so forcing ink here painted the only dismiss control
   invisibly on an ink panel. :not() keeps this at 0-2-1 so .nav.is-stuck still wins. */
body.bright-hero:not(.menu-open) .nav__inner{color:var(--ink)}
body.bright-hero .nav__links{margin-left:auto}
body.bright-hero .nav:not(.is-stuck) .nav__links a{opacity:.72}
body.bright-hero .nav:not(.is-stuck) .nav__links a:hover{opacity:1}
body.bright-hero .nav:not(.is-stuck) .btn--dark{
  background:var(--ink);color:var(--paper);border-color:transparent;
  backdrop-filter:none;-webkit-backdrop-filter:none;
  box-shadow:0 14px 34px -16px rgba(8,12,20,.5);
}

/* ── 03 · SCENE ──────────────────────────────────────────── */
.bhero{
  position:relative;isolation:isolate;overflow:clip;
  min-height:100svh;display:flex;flex-direction:column;
  padding-top:calc(var(--nav-h) + clamp(.75rem,3.4vh,2.8rem));
  padding-bottom:var(--house-show);
  background:#BBD9F2;
}

/* The far layer — overscanned on all four sides so the parallax never slides
   an edge into view. The horizontal budget must stay ahead of the pointer
   travel in hero-bright.js (`mx * -17`), or bare .bhero background shows at
   the left/right edge on mouse move. object-fit:cover absorbs the extra width
   out of the crop the source already has to spare, so this costs no sharpness. */
:root{--sky-overscan-x:24px}   /* > the 17px of pointer travel, with margin */
.bhero__sky{position:absolute;inset:-11% calc(var(--sky-overscan-x) * -1) -5%;
  z-index:-3;will-change:transform}
.bhero__sky img{width:100%;height:100%;object-fit:cover;object-position:center bottom}

/* drifting wisps, between sky and house */
.bhero__wisps{position:absolute;left:0;right:0;top:2%;height:62%;z-index:-2;
  overflow:hidden;pointer-events:none;opacity:.3}
.bhero__wisps i{
  /* left:-4% for the same reason: drift runs 0 → -50%, so at the top of the
     cycle the pointer lean (mx * -1.6%) is the only term and can go positive.
     The tile is a seamless repeat, so starting off-phase looks identical. */
  position:absolute;inset:0;left:-4%;width:200%;
  background:url('../img/hero-wisps.png') repeat-x 0 50%/50% 100%;
  will-change:transform;
}

/* sun bloom, low and left, following the plate's own sunset */
.bhero__sun{
  position:absolute;left:-8%;bottom:calc(var(--house-show) - 6vh);z-index:-2;
  width:min(880px,72vw);height:46vh;pointer-events:none;
  filter:blur(30px);will-change:transform;
  background:radial-gradient(58% 58% at 30% 78%,rgba(255,238,210,.45),rgba(255,238,210,0) 72%);
}

/* the near layer — the cut-out, pushed down so only --house-show clears the fold */
.bhero__house{
  position:absolute;z-index:-1;
  left:50%;margin-left:calc(var(--house-w) / -2);width:var(--house-w);
  bottom:calc(var(--house-show) - var(--house-h));
  pointer-events:none;will-change:transform;transform-origin:50% 100%;
}
/* style.css sets img{background:var(--ink-3)} as a loading placeholder, which
   shows straight through a cut-out's alpha as a dark slab. */
.bhero__house img{width:100%;height:auto;display:block;background:none}
/* its warm interiors, breathing */
.bhero__house::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:60%;pointer-events:none;
  background:radial-gradient(52% 70% at 50% 88%,rgba(255,182,92,.16),rgba(255,182,92,0) 70%);
  mix-blend-mode:screen;animation:embers 7.5s var(--e-io) infinite;
}
@keyframes embers{0%,100%{opacity:.45}50%{opacity:.9}}

/* ── 04 · CONTENT ────────────────────────────────────────── */
.bhero__content{
  position:relative;z-index:3;margin-block:auto;text-align:center;max-width:100%;
  width:min(var(--wrap),100% - var(--gut)*2);margin-inline:auto;
  display:flex;flex-direction:column;align-items:center;gap:clamp(.8rem,1.35vw,1.45rem);
  will-change:transform,opacity;
}
.bhero__badge{
  display:inline-flex;align-items:center;gap:.7rem;max-width:100%;
  padding:.34rem .95rem .34rem .4rem;border-radius:999px;
  border:1px solid rgba(255,255,255,.8);background:rgba(255,255,255,.62);
  backdrop-filter:blur(16px) saturate(1.5);-webkit-backdrop-filter:blur(16px) saturate(1.5);
  box-shadow:0 10px 26px -16px rgba(8,12,20,.45);
  font-size:.82rem;color:var(--ink-sub);
}
.bhero__badge strong{font-weight:600;color:var(--ink)}

/* the reference sets one heavy grotesk at full width — no serif accent */
.bhero__title{
  /* Sized so the line always occupies ~82% of the content wrapper, which leaves
     a real margin on both sides at every width. 6.62vw holds that ratio while
     the wrapper tracks the viewport; 6.3rem takes over once the wrapper hits its
     own 1400px ceiling, otherwise the text kept growing while the box did not
     (96% fill at 1920px). No ch cap — that forced a break mid-headline. */
  font:700 clamp(2.55rem,6.62vw,6.3rem)/.94 var(--disp);
  letter-spacing:-.046em;text-wrap:balance;max-width:100%;
  /* no text-shadow: [data-split] wraps every word in .word{overflow:hidden},
     which clips a 60px blur into a hard rectangle per word. */
  color:var(--ink);
}

/* [data-split] puts every word in .word{overflow:hidden} so the reveal can slide
   it up. That clip box is built from glyph ADVANCES, and letter-spacing:-.046em
   pulls it tighter than the ink — so the last glyph of each word lost a sliver
   and the 'y' lost its tail. Pad the clip box out, pull it back with matching
   negative margins: bigger box, identical layout, nothing cut. */
.bhero__title .word{padding:.1em .09em .2em;margin:-.1em -.09em -.2em}

/* Keeps the place name whole. An &nbsp; cannot do this — each word is an atomic
   inline and Chrome allows a soft wrap between two of them whatever sits between. */
.bhero__title .nb{white-space:nowrap}

/* Under 620px one line would crowd the gutters: the vw curve flattens against
   the clamp floor while the wrapper keeps shrinking (99% fill at 520px). Break
   after "Your" deliberately and size off the longest line instead. */
@media(max-width:620px){
  .bhero__title{font-size:clamp(1.8rem,9.7vw,3.85rem);line-height:1.02}
  .bhero__title .bhero__l{display:block}
}
.bhero__sub{
  max-width:min(50ch,100%);color:var(--ink-sub);text-wrap:balance;
  font-size:clamp(.97rem,1.1vw,1.18rem);line-height:1.52;
}
.bhero__actions{display:flex;flex-wrap:wrap;gap:.7rem;justify-content:center;margin-top:.35rem}

/* ── 05 · UI (new variants only — .btn itself comes from style.css) ── */
.btn--frost{
  color:var(--ink);border:1px solid rgba(255,255,255,.8);
  background:rgba(255,255,255,.66);
  backdrop-filter:blur(16px) saturate(1.5);-webkit-backdrop-filter:blur(16px) saturate(1.5);
  box-shadow:0 14px 34px -18px rgba(8,12,20,.38);
}
.btn--frost::before{background:var(--paper-2)}
.btn--frost:hover{color:var(--ink)}
.btn--orb{padding-right:.5rem}
.btn__orb{
  display:grid;place-items:center;width:2em;height:2em;border-radius:999px;
  background:var(--paper);color:var(--ink);overflow:hidden;flex:none;
  transition:background-color .45s var(--e-out),color .45s var(--e-out);
}
.btn__orb svg{width:.72em;height:.72em;transition:transform .5s var(--e-out)}
.btn:hover .btn__orb{background:var(--ink);color:var(--paper)}
.btn:hover .btn__orb svg{transform:translate3d(140%,-140%,0)}
.btn--frost .btn__orb,.btn--frost:hover .btn__orb{background:var(--ink);color:var(--paper)}

/* ── 06 · RESPONSIVE ─────────────────────────────────────── */
@media(max-width:820px){
  /* The cut-out is scaled up on a narrow frame so it still has presence, but only
     so far: past ~160vw the crop eats the stepped roofline and the outer wings,
     and it stops reading as a house at all — it becomes a wall of balconies.
     Keep this in step with BOTH descriptors in index.html — `sizes` on the <img>
     and `imagesizes` on its preload <link>. If they disagree with each other the
     cut-out is fetched twice; if they overstate the width the browser picks the
     1700px master where the 1200px one would do. */
  :root{--house-w:min(2400px,150vw);--house-show:min(47svh,calc(var(--house-h) * .82))}
}
@media(max-width:640px){
  .bhero{padding-top:calc(var(--nav-h) + .7rem)}
  .bhero__content{gap:.7rem}
  .bhero__sub{font-size:.94rem;line-height:1.45}
  .bhero__badge{font-size:.75rem;padding:.3rem .8rem .3rem .35rem;gap:.55rem}
  .bhero__actions{width:100%;flex-direction:column;align-items:stretch}
  .bhero__actions .btn{justify-content:space-between}
}
@media(min-width:821px) and (max-width:1180px) and (orientation:portrait){
  :root{--house-w:min(2400px,150vw)}
}
/* Tall viewports — 4K panels, QHD, large portrait tablets — had spare vertical
   room the house was not using: contentBottomGap ran to 293px at 3840x2160
   while every laptop size was already content-bound. Hand it to the house.
   The reveal guard can go to .90 here because the cut-out still spans 96% of
   its width at y0.90; it only tapers past ~y0.93, which is the edge the .82
   default exists to stay clear of. Keyed on height, not width, because the
   constraint is vertical room — a 1600x1000 laptop must not pick this up. */
@media(min-height:1300px){
  :root{--house-show:min(56svh,calc(var(--house-h) * .9))}
}
@media(max-height:720px){
  :root{--house-show:min(40svh,calc(var(--house-h) * .82))}
  .bhero__title{font-size:clamp(2.2rem,6vw,4.2rem)}
}

/* ── 07 · MOTION ─────────────────────────────────────────── */
/* entrances live on the <img>; parallax lives on the wrapper */
.bhero__sky img,.bhero__house img{opacity:0}
.bhero__sky img{transform:scale(1.06)}
.bhero__house img{transform:translate3d(0,78px,0)}
.is-ready .bhero__sky img{
  opacity:1;transform:none;
  transition:opacity 1.4s var(--e-out) .05s,transform 2.2s var(--e-out) .05s;
}
/* the cut-out is the heaviest thing on the first screen, so it is allowed to
   arrive late: it fades in when BOTH the curtain is up and the file has landed
   (html.house-in, set by the inline curtain script), instead of holding the
   whole hero back to its own download time */
html.house-in body.is-ready .bhero__house img{
  opacity:1;transform:none;
  transition:opacity 1.1s var(--e-out) .12s,transform 1.5s var(--e-out) .12s;
}
@media(prefers-reduced-motion:reduce){
  .bhero__sky,.bhero__house,.bhero__sky img,.bhero__house img{
    opacity:1!important;transform:none!important;
  }
  .bhero__wisps i{transform:none!important}
}

/* Without JS the entrance transitions never fire, so the hero would stay blank.
   0-2-1 beats the .is-ready rules above. */
.no-js .bhero__sky img,.no-js .bhero__house img{opacity:1;transform:none}
