/* =========================================================
   NOABRIDGE — Top page motion layer
   Loaded on index.html only, AFTER style.css.
   Everything here is progressive enhancement: with JS or
   motion disabled the page still renders complete & readable.
   ========================================================= */

:root {
  --ease-soft: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-back: cubic-bezier(0.34, 1.4, 0.42, 1);
}

/* =========================================================
   1. Intro veil (built by JS, once per session)
   ========================================================= */
.intro-veil {
  position: fixed; inset: 0; z-index: 999;
  display: flex; align-items: center; justify-content: center;
  background: var(--navy-900);
  transition: opacity 0.9s var(--ease-soft), transform 1.1s var(--ease-soft);
}
.intro-veil::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 45%, rgba(29,64,103,0.55), transparent 60%);
}
.intro-figure {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 1.4rem;
}
.intro-name {
  font-family: var(--ff-sans);
  font-size: clamp(1.1rem, 3vw, 1.5rem);
  font-weight: 300;
  letter-spacing: 1.1em;
  text-indent: 1.1em;
  color: var(--text);
  opacity: 0;
  transform: translateY(10px);
  animation: introName 1.1s var(--ease-soft) 0.12s forwards;
}
.intro-rule {
  display: block; width: min(280px, 52vw); height: 1px;
  background: var(--line-soft);
  position: relative; overflow: hidden;
}
.intro-rule i {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--bronze), transparent);
  transform: scaleX(0); transform-origin: left;
  animation: introRule 1.15s var(--ease-inout) 0.28s forwards;
}
@keyframes introName { to { opacity: 1; transform: none; } }
@keyframes introRule {
  0%   { transform: scaleX(0); transform-origin: left; }
  60%  { transform: scaleX(1); transform-origin: left; }
  100% { transform: scaleX(1); transform-origin: left; opacity: 0.35; }
}
.intro-veil.is-leaving { opacity: 0; transform: translateY(-2.5%); pointer-events: none; }
body.intro-locked { overflow: hidden; }

/* =========================================================
   2. Header — retracts on scroll-down, returns on scroll-up
   ========================================================= */
.site-header { will-change: transform; }
.site-header.is-hidden { transform: translateY(-100%); }

/* =========================================================
   3. Hero — video, scroll choreography, title reveal
   ========================================================= */
.hero-parallax {
  position: absolute; inset: 0;
  will-change: transform;
}
.hero-media { z-index: 0; }

.hero-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 38%;
  opacity: 0;
  transition: opacity 1.8s var(--ease-soft);
  pointer-events: none;
}
.hero-video.is-ready { opacity: 1; }

/* Corner vignette that breathes very slowly. Kept light — .hero-overlay in
   style.css already carries most of the darkening. */
.hero-vignette {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse 82% 74% at 50% 48%, transparent 52%, rgba(8,19,32,0.32) 100%);
  animation: vignetteBreath 16s ease-in-out infinite alternate;
}
@keyframes vignetteBreath {
  from { opacity: 0.55; }
  to   { opacity: 1; }
}

/* Bronze light that tracks the cursor across the hero */
.hero-cursor {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(420px circle at var(--cx, 50%) var(--cy, 45%),
              rgba(221,192,134,0.20), transparent 62%);
  opacity: 0;
  transition: opacity 0.7s var(--ease-soft);
  mix-blend-mode: screen;
}
.hero.is-live .hero-cursor { opacity: 1; }

.hero-inner { will-change: transform, opacity; }

/* ---- Title: per-character reveal, then scroll scatter ---- */
body.title-split .hero-title,
body.title-split .section-title,
body.title-split .contact-title,
body.title-split .statement-text .line {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
  transition: none !important;
  clip-path: none !important;
}

.ch {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
  /* scroll-driven scatter — --hp is written by JS on the heading */
  transform:
    translateY(calc(var(--hp, 0) * var(--sy, 0) * 1px))
    rotate(calc(var(--hp, 0) * var(--sr, 0) * 1deg));
}
.ch > i {
  display: inline-block;
  font-style: normal;
  transform: translateY(118%) rotate(6deg);
  opacity: 0;
  transition: transform 1s var(--ease-soft), opacity 0.7s var(--ease-soft);
  transition-delay: var(--d, 0s);
}
body.hero-in .hero-title .ch > i,
[data-anim].is-in .ch > i { transform: none; opacity: 1; }

/* Once the entrance has landed, stop clipping so the scatter can leave the box */
body.hero-settled .hero-title .ch { overflow: visible; }

/* Bronze light sweeps across the headline once it has landed */
.hero-title { position: relative; }
.hero-title::after {
  content: ""; position: absolute; inset: -0.2em -0.6em; pointer-events: none;
  background: linear-gradient(105deg, transparent 42%, rgba(221,192,134,0.5) 50%, transparent 58%);
  mix-blend-mode: overlay;
  opacity: 0;
  transform: translateX(-70%);
}
body.hero-in .hero-title::after { animation: titleSheen 1.9s var(--ease-inout) 1.4s 1; }
@keyframes titleSheen {
  0%   { opacity: 0; transform: translateX(-70%); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(70%); }
}

/* Eyebrow: letters settle inward */
body.js-motion .hero-eyebrow {
  letter-spacing: 0.62em;
  transition: opacity 1.1s var(--ease-soft) 0.15s,
              letter-spacing 1.6s var(--ease-soft) 0.15s,
              transform 1.1s var(--ease-soft) 0.15s,
              filter 1.1s var(--ease-soft) 0.15s;
}
body.hero-in .hero-eyebrow { letter-spacing: 0.35em; }

.hero-rule {
  display: block;
  width: min(360px, 60vw);
  height: 1px;
  margin: -0.6rem auto 2.6rem;
  background: linear-gradient(90deg, transparent, var(--bronze), transparent);
  transform: scaleX(0);
  transition: transform 1.5s var(--ease-inout) 1.1s;
}
body.hero-in .hero-rule { transform: scaleX(1); }

/* =========================================================
   4. Scroll-reveal system  [data-anim]
   ========================================================= */
.services, .cases, .insights, .news, .about-inner, .statement, .contact {
  perspective: 1200px;
}

[data-anim] {
  opacity: 0;
  transition:
    opacity 0.9s var(--ease-soft),
    transform 1.15s var(--ease-soft),
    clip-path 1.2s var(--ease-soft),
    filter 0.9s var(--ease-soft);
  transition-delay: var(--d, 0s);
  transform-origin: center top;
}
[data-anim="rise"]  { transform: translateY(90px) rotateX(14deg) scale(0.97); }
[data-anim="left"]  { transform: translateX(-110px) rotateY(12deg); }
[data-anim="right"] { transform: translateX(110px) rotateY(-12deg); }
[data-anim="zoom"]  { transform: scale(0.9) translateY(60px); filter: blur(10px); }
/* Cards deal in from alternating sides — --dir is -1 or 1 */
[data-anim="deal"] {
  transform:
    translate3d(calc(var(--dir, 1) * 120px), 70px, -120px)
    rotateY(calc(var(--dir, 1) * -14deg))
    rotateZ(calc(var(--dir, 1) * 2deg));
}
[data-anim="mask"] {
  clip-path: inset(0 0 105% 0);
  transform: translateY(26px);
}
[data-anim].is-in {
  opacity: 1;
  transform: none;
  filter: none;
}
/* Only the mask variant needs a resting clip-path — a generous negative inset
   so nothing (box-shadows included) gets cut off once it has landed. */
[data-anim="mask"].is-in { clip-path: inset(-25% -10% -25% -10%); }

.statement-text .line { display: block; }

/* Scroll-velocity skew: the page leans into the direction of travel */
.vel { will-change: transform; }

/* Oversized ghost word behind each section head */
.section-head { position: relative; }
.section-head[data-ghost]::before {
  content: attr(data-ghost);
  position: absolute;
  left: 50%; top: 50%;
  transform: translate3d(calc(-50% + var(--gx, 0px)), -58%, 0);
  font-family: var(--ff-display);
  font-size: clamp(5rem, 16vw, 13rem);
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1;
  white-space: nowrap;
  color: var(--text);
  /* Texture, not a second label — it must never compete with the real heading. */
  opacity: 0.03;
  pointer-events: none;
  z-index: 0;
  will-change: transform;
}
.section-head > * { position: relative; z-index: 1; }

/* =========================================================
   5. Keyword marquee (JS-driven; CSS animation is the no-JS fallback)
   ========================================================= */
.marquee {
  position: relative;
  overflow: hidden;
  padding: 1.9rem 0;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  background: linear-gradient(180deg, rgba(15,34,56,0.5), rgba(8,19,32,0.5));
  -webkit-mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent);
}
.marquee-track {
  display: flex;
  width: max-content;
  align-items: center;
  gap: 2.6rem;
  will-change: transform;
  animation: marqueeSlide 42s linear infinite;
}
.marquee-track span {
  font-family: var(--ff-display);
  font-size: clamp(1.1rem, 2.2vw, 1.6rem);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.marquee-track span:nth-child(4n + 1) { color: var(--bronze-light); }
.marquee-track i {
  flex: 0 0 auto;
  width: 6px; height: 6px;
  transform: rotate(45deg);
  background: var(--bronze);
  opacity: 0.65;
}
@keyframes marqueeSlide {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* =========================================================
   6. Cards — pointer tilt, spotlight, hover video
   ========================================================= */
.service-grid, .post-grid { perspective: 1400px; }

.service-card, .post-card {
  --mx: 50%;
  --my: 0%;
  transform-style: preserve-3d;
}
.service-card::before,
.post-card::before {
  content: ""; position: absolute; inset: 0; z-index: 2;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(320px circle at var(--mx) var(--my),
              rgba(200,163,91,0.18), transparent 62%);
  opacity: 0;
  transition: opacity 0.55s var(--ease-soft);
}
.post-card { position: relative; overflow: hidden; }
.service-card.is-hot::before,
.post-card.is-hot::before { opacity: 1; }

/* While the pointer is inside, the tilt has to track it, not glide behind it. */
.service-card.is-hot,
.post-card.is-hot {
  transition: transform 0.16s ease-out,
              border-color 0.5s var(--ease),
              box-shadow 0.5s var(--ease);
}

/* Still layer gets a scroll parallax; --py is written by JS */
.service-media {
  background-position: center calc(50% + var(--py, 0px));
  will-change: background-position;
}

/* Hover video sits between the still and the scrim.
   Selector must be at least as specific as style.css's
   `.service-card > *:not(.service-media)`, which otherwise forces
   position:relative / z-index:2 onto it. */
.service-card .service-video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Same duotone pipeline as .service-media so stills and motion match */
  filter: grayscale(100%) sepia(60%) hue-rotate(178deg) saturate(2.4)
          brightness(0.62) contrast(1.02);
  opacity: 0;
  transition: opacity 0.9s var(--ease-soft);
  pointer-events: none;
}
.service-card.is-hot .service-video.is-ready { opacity: 0.9; }

.service-no {
  transition: transform 0.6s var(--ease-back), opacity 0.5s var(--ease-soft),
              letter-spacing 0.6s var(--ease-soft);
}
.service-card:hover .service-no { transform: translateY(-8px); opacity: 0.9; letter-spacing: 0.06em; }
.service-card h3 { transition: transform 0.6s var(--ease-back) 0.04s; }
.service-card:hover h3 { transform: translateX(6px); }

.post-cat { transition: border-color 0.45s var(--ease), color 0.45s var(--ease), transform 0.5s var(--ease-back); }
.post-card:hover .post-cat { transform: translateY(-3px) scale(1.04); border-color: var(--bronze); }

/* =========================================================
   7. News rows — bronze wipe + arrow
   ========================================================= */
.news-list a { position: relative; overflow: hidden; }
.news-list a::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, var(--bronze), transparent);
  transform: scaleY(0); transform-origin: top;
  transition: transform 0.5s var(--ease-soft);
}
.news-list a::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(90deg, rgba(200,163,91,0.10), transparent 60%);
  transform: translateX(-100%);
  transition: transform 0.6s var(--ease-soft);
}
.news-list a:hover::before { transform: scaleY(1); }
.news-list a:hover::after { transform: none; }
.news-list time { transition: transform 0.5s var(--ease-back); display: inline-block; }
.news-list a:hover time { transform: translateX(5px); }

/* =========================================================
   8. Contact — aurora that drifts and breathes with scroll
   ========================================================= */
.contact { overflow: hidden; }
.contact::before {
  content: ""; position: absolute; inset: -30% -10%;
  pointer-events: none;
  background:
    radial-gradient(38% 44% at 22% 30%, rgba(200,163,91,0.13), transparent 65%),
    radial-gradient(46% 50% at 78% 62%, rgba(29,64,103,0.38), transparent 68%),
    radial-gradient(30% 38% at 55% 12%, rgba(221,192,134,0.08), transparent 70%);
  filter: blur(26px);
  transform: scale(var(--aurora, 1));
  animation: auroraDrift 22s ease-in-out infinite alternate;
}
.contact-inner { position: relative; z-index: 1; }
@keyframes auroraDrift {
  from { transform: translate3d(-4%, -3%, 0) scale(1); }
  to   { transform: translate3d(4%, 3%, 0) scale(1.12); }
}

/* =========================================================
   9. Magnetic buttons
   ========================================================= */
.btn.is-magnetic { will-change: transform; }
.btn.is-magnetic span { pointer-events: none; }

/* =========================================================
   10. Back-to-top
   ========================================================= */
.to-top {
  position: fixed; right: 1.6rem; bottom: 1.6rem; z-index: 90;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: rgba(8,19,32,0.7);
  backdrop-filter: blur(10px);
  color: var(--bronze-light);
  font-size: 0.9rem; line-height: 1;
  cursor: pointer;
  opacity: 0; transform: translateY(14px) scale(0.9);
  pointer-events: none;
  transition: opacity 0.5s var(--ease-soft), transform 0.5s var(--ease-back),
              border-color 0.4s var(--ease), background 0.4s var(--ease);
}
.to-top.is-visible { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { border-color: var(--bronze); background: rgba(200,163,91,0.12); transform: scale(1.08); }

/* =========================================================
   11. Responsive
   ========================================================= */
@media (max-width: 860px) {
  .hero-rule { margin: -0.9rem auto 1.6rem; }
  .marquee { padding: 1.4rem 0; }
  .marquee-track { gap: 1.8rem; animation-duration: 32s; }
  .to-top { right: 1rem; bottom: 1rem; width: 42px; height: 42px; }
  .section-head[data-ghost]::before { font-size: clamp(4rem, 22vw, 7rem); opacity: 0.05; }
  /* Softer travel on small screens so nothing overshoots the viewport */
  [data-anim="rise"]  { transform: translateY(52px) rotateX(8deg); }
  [data-anim="left"]  { transform: translateX(-48px); }
  [data-anim="right"] { transform: translateX(48px); }
  [data-anim="deal"]  { transform: translate3d(0, 52px, 0); }
  [data-anim="zoom"]  { transform: scale(0.95) translateY(40px); filter: blur(6px); }
}

@media (max-width: 560px) {
  /* The phone hero is already height-constrained — the extra rule would push
     the buttons into the scroll indicator. */
  .hero-rule { display: none; }
}

/* =========================================================
   12. Reduced motion — everything settles instantly
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  .hero-video, .hero-vignette, .contact::before { animation: none !important; }
  .marquee-track { animation: none !important; transform: none !important; }
  .ch, .ch > i { transform: none !important; opacity: 1 !important; overflow: visible !important; }
  .hero-title::after { display: none; }
  .hero-rule { transform: scaleX(1) !important; }
  .hero-cursor, .section-head[data-ghost]::before { display: none; }
  .site-header.is-hidden { transform: none !important; }
  body.js-motion .hero-eyebrow { letter-spacing: 0.35em !important; }
  [data-anim] { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; }
  .intro-veil { display: none !important; }
}
