/* ============================================================
   BUILT IN — motion layer
   All hidden states are gated behind .pre-anim (set by an inline
   <head> script) with a hard failsafe, so a script/CDN failure can
   never leave content invisible.
   ============================================================ */

.pre-anim [data-reveal],
.pre-anim [data-stagger] > *,
.pre-anim [data-fade] { opacity: 0; }
.pre-anim [data-reveal] { transform: translateY(34px); }
.pre-anim [data-stagger] > * { transform: translateY(28px); }
.pre-anim [data-reveal="left"]  { transform: translateX(-40px); }
.pre-anim [data-reveal="right"] { transform: translateX(40px); }
.pre-anim [data-reveal="scale"] { transform: scale(.95); }
.pre-anim .line__inner { transform: translateY(185%); }
.pre-anim [data-clip], .pre-anim .split__media, .pre-anim .hero__banner, .pre-anim .phero__banner { clip-path: inset(0 0 100% 0); }
.pre-anim .hero__banner img { transform: scale(1.2); }

/* Line-mask headings */
.lines { display: block; }
/* The mask clips at the line box, but ink overflows it — descenders always,
   and a script face on both sides. Pad the box so nothing is ever cut, and
   pull the padding back out with a matching negative margin so the tight
   display leading is unchanged. The pre-state offset above is 150% rather
   than 110% to stay clear of the taller box. */
.line { display: block; overflow: hidden; padding-block: .26em .34em; margin-block: -.26em -.34em; }
.line__inner { display: block; will-change: transform; }

/* ---------- Image failure resilience ---------- */
.hero__banner, .phero__banner, .split__media, .svc__media,
.tile, .ig-grid a, .cta-media { background: var(--sand); }
.hero__banner img, .phero__banner img, .split__media img, .svc__media img,
.tile img, .ig-grid img, .cta-media img, .pfloat img { color: transparent; }

/* ---------- Preloader ---------- */
.preloader {
  position: fixed; inset: 0; z-index: 9999; background: var(--navy-black);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px;
  color: #fff;
  animation: bl-pre-out .7s 2.4s forwards; /* CSS failsafe if JS never runs */
}
@keyframes bl-pre-out { to { opacity: 0; visibility: hidden; } }
html.gsap-on .preloader { animation: none; }
html.force-show .preloader { display: none !important; }
html.force-show [data-reveal],
html.force-show [data-stagger] > *,
html.force-show [data-fade],
html.force-show .line__inner,
html.force-show [data-clip],
html.force-show .split__media,
html.force-show .hero__banner,
html.force-show .phero__banner {
  opacity: 1 !important; transform: none !important; clip-path: none !important;
}
.preloader__wm { display: block; color: #fff; opacity: 0; }
.preloader__wm::before {
  content: "";
  display: block; width: clamp(60px, 7vw, 78px); aspect-ratio: 1;
  margin: 0 auto clamp(22px, 3vw, 30px);
  background: url("assets/logo-bi-badge-256.png") center / contain no-repeat;
  border-radius: 14%;
  box-shadow: 0 18px 50px rgba(0,0,0,.5);
}
.preloader__wm svg { display: block; width: clamp(160px, 22vw, 240px); height: auto; }
/* Live type, matching the header, menu and footer lockups — the first frame of
   a page load must not show a different wordmark from the one that follows. */
.preloader__wm--type {
  font-family: var(--display); font-weight: var(--display-weight);
  font-size: clamp(2.3rem, 5vw, 3.4rem); line-height: 1; letter-spacing: -.01em;
}
.preloader__name { font-family: var(--sans); font-size: .72rem; font-weight: 500; letter-spacing: .16em; text-transform: uppercase; color: #C6A063; opacity: 0; padding-left: .2em; }
.preloader__bar { width: min(220px, 54vw); height: 1px; background: rgba(255,255,255,.2); overflow: hidden; }
.preloader__bar i { display: block; height: 100%; background: #fff; transform: scaleX(0); transform-origin: left; }

/* ---------- Custom cursor ---------- */
.cursor, .cursor-dot { position: fixed; top:0; left:0; z-index: 9000; pointer-events: none; border-radius: 50%; mix-blend-mode: difference; opacity: 0; transition: opacity .3s; }
.cursor { width: 34px; height: 34px; border: 1px solid rgba(255,255,255,.9); transform: translate(-50%,-50%); transition: width .35s var(--ease), height .35s var(--ease), background .3s, opacity .3s; }
.cursor-dot { width: 4px; height: 4px; background: #fff; transform: translate(-50%,-50%); }
body.cursor-live .cursor, body.cursor-live .cursor-dot { opacity: 1; }
.cursor.grow { width: 64px; height: 64px; background: rgba(255,255,255,.12); }
@media (hover: none), (pointer: coarse) { .cursor, .cursor-dot { display: none !important; } }
@media (hover: hover) and (pointer: fine) { body.cursor-on, body.cursor-on a, body.cursor-on button { cursor: none; } }

/* Magnetic buttons */
.btn[data-magnetic] { will-change: transform; }

@media (prefers-reduced-motion: reduce){
  .pre-anim [data-reveal], .pre-anim [data-stagger] > *, .pre-anim [data-fade],
  .pre-anim .line__inner, .pre-anim [data-clip], .pre-anim .split__media,
  .pre-anim .hero__banner, .pre-anim .phero__banner {
    opacity: 1 !important; transform: none !important; clip-path: none !important;
  }
  .preloader { display: none !important; }
  .cursor, .cursor-dot, .pfloat { display: none !important; }
}

/* The horizontal reveal offsets push elements past the right edge until they
   animate in. Clip at the root so that never becomes a sideways scroll on a
   phone — `clip` rather than `hidden`, which would break position: sticky. */
html { overflow-x: clip; }
@media (max-width: 700px){
  .pre-anim [data-reveal="left"]  { transform: translateX(-18px); }
  .pre-anim [data-reveal="right"] { transform: translateX(18px); }
}
