/* ============================================================
   Choyce Landing — Cinematic layer
   Loaded AFTER styles.css. Adds the scrolling "journey": camera
   moves, 3D transforms, scroll-triggered reveals and pointer
   interactions.

   Performance model:
   - Continuous scroll effects use native CSS scroll-driven
     animations (animation-timeline) → run on the compositor,
     zero main-thread cost. Gated behind @supports; where absent
     the page is simply calm (graceful degradation).
   - Reveals reuse the existing IntersectionObserver (.is-visible)
     and animate ONLY opacity + the individual `translate`/`scale`
     properties, leaving `transform` free for 3D tilt — so nothing
     ever fights over a single transform.
   - Motion is disabled wholesale under prefers-reduced-motion.
   ============================================================ */

/* ---------- 0. Contain off-screen reveal motion --------------
   Directional reveals start translated off-screen (±46px). `clip`
   hides that horizontal spill without creating a scroll container,
   so it never fights the scroll-driven timelines or fixed header. */
html, body { overflow-x: clip; }

/* ---------- 1. Scroll progress rail --------------------------
   A goal-gradient cue: a visible finish line makes people scroll
   further and faster (progress reduces uncertainty). */
.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 200;
  transform-origin: 0 50%;
  transform: scaleX(var(--progress, 0));
  background: linear-gradient(90deg, var(--brand), var(--accent) 55%, var(--brand-dark));
  will-change: transform;
}
@supports (animation-timeline: scroll()) {
  .scroll-progress {
    transform: scaleX(0);
    animation-name: cx-progress;
    animation-fill-mode: both;
    animation-timing-function: linear;
    animation-duration: auto;
    animation-timeline: scroll(root block);
  }
  @keyframes cx-progress { to { transform: scaleX(1); } }
}

/* ---------- 2. Reveal engine (compose-safe) ------------------
   Overrides the base .reveal to use `translate`/`scale` (not the
   `transform` shorthand). Directional variety guides the eye and
   the staggered cascade turns a static grid into a "dealt hand",
   which reads as intentional and premium. */
.js .reveal {
  opacity: 0;
  transform: none;                 /* release transform for tilt */
  translate: 0 26px;
  scale: 1;
  transition:
    opacity .75s cubic-bezier(.16, 1, .3, 1),
    translate .75s cubic-bezier(.16, 1, .3, 1),
    scale .75s cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--d, 0s);
}
.js .reveal.is-visible { opacity: 1; translate: 0 0; scale: 1; }

.js .reveal[data-reveal="left"]  { translate: -46px 0; }
.js .reveal[data-reveal="right"] { translate: 46px 0; }
.js .reveal[data-reveal="zoom"]  { translate: 0 0; scale: .9; }

/* 3D "camera tilt up" for headings & focal blocks (non-tilt els).
   A slight perspective rotation reads as the camera craning up to
   meet the content — motion with spatial meaning, not decoration. */
.js .reveal[data-reveal="rise3d"] {
  opacity: 0;
  translate: 0 0;
  transform: perspective(1400px) rotateX(12deg) translateY(46px);
  transform-origin: 50% 100%;
  transition:
    opacity .8s cubic-bezier(.16, 1, .3, 1),
    transform .8s cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--d, 0s);
}
.js .reveal[data-reveal="rise3d"].is-visible {
  opacity: 1;
  transform: perspective(1400px) rotateX(0deg) translateY(0);
}

/* ---------- 3. Hero: establishing shot -----------------------
   Ken Burns keeps the image alive (cinema's "a still frame reads
   as dead"), while the scroll-linked dolly makes the copy recede
   and hand off to the photo as you leave — a camera move, not a
   page swap, so the journey feels continuous. */
.hero-media {
  will-change: transform;
  animation: cx-kenburns 28s ease-in-out infinite alternate;
}
@keyframes cx-kenburns {
  from { transform: scale(1.05); }
  to   { transform: scale(1.16) translate3d(0, -1.5%, 0); }
}

@supports (animation-timeline: scroll()) {
  .hero-content {
    animation-name: cx-hero-dolly;
    animation-fill-mode: both;
    animation-timing-function: linear;
    animation-duration: auto;
    animation-timeline: scroll(root block);
    animation-range: 0 82vh;
  }
  @keyframes cx-hero-dolly {
    to { transform: translate3d(0, -7vh, 0); opacity: 0; }
  }
}

/* Scroll cue — a bobbing hint that answers "is there more?" */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 24px;
  translate: -50% 0;
  z-index: 3;
  display: grid;
  place-items: center;
  gap: 6px;
  color: rgba(255, 255, 255, 0.75);
  font-size: .68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.scroll-cue .mouse {
  width: 24px; height: 38px;
  border: 2px solid rgba(255, 255, 255, 0.55);
  border-radius: 999px;
  position: relative;
}
.scroll-cue .mouse::after {
  content: "";
  position: absolute;
  left: 50%; top: 7px;
  width: 3px; height: 7px;
  background: #fff;
  border-radius: 2px;
  translate: -50% 0;
  animation: cx-wheel 1.7s ease-in-out infinite;
}
@keyframes cx-wheel {
  0%   { opacity: 0; transform: translateY(-4px); }
  40%  { opacity: 1; }
  80%  { opacity: 0; transform: translateY(8px); }
  100% { opacity: 0; }
}
@supports (animation-timeline: scroll()) {
  .scroll-cue {
    animation-name: cx-cue-fade;
    animation-fill-mode: both;
    animation-timing-function: linear;
    animation-duration: auto;
    animation-timeline: scroll(root block);
    animation-range: 0 22vh;
  }
  @keyframes cx-cue-fade { to { opacity: 0; translate: -50% 12px; } }
}

/* ---------- 4. Service & step cards: 3D tilt -----------------
   Objects that respond to the cursor feel physical (embodied
   cognition) — the affordance invites touch and lengthens dwell
   time. Tilt lives on `transform`; the reveal used `translate`,
   so they never collide. */
.js [data-tilt] {
  position: relative;
  transform: perspective(var(--tp, 900px)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(var(--lift, 0px));
  transition: transform .2s cubic-bezier(.16, 1, .3, 1), box-shadow .3s ease, border-color .3s ease;
  transform-style: preserve-3d;
}
[data-tilt]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 0%), rgba(120, 158, 206, 0.20), transparent 62%);
  opacity: 0;
  transition: opacity .3s ease;
}
/* Override the base translateY hover so tilt owns the transform. */
.js .service-card[data-tilt]:hover,
.js .step-card[data-tilt]:hover {
  --lift: -6px;
  transform: perspective(var(--tp, 900px)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(var(--lift, -6px));
  box-shadow: var(--shadow-lift);
}
[data-tilt]:hover::after { opacity: 1; }

/* Step numbers spring in once their card reveals (overshoot easing
   = a little "pop" of delight that rewards arrival). */
.js .step-card .step-num {
  transition: transform .55s cubic-bezier(.34, 1.56, .64, 1);
  transition-delay: calc(var(--d, 0s) + .1s);
}
.js .step-card:not(.is-visible) .step-num { transform: scale(.35); opacity: .4; }
.js .step-card.is-visible .step-num { transform: scale(1); opacity: 1; }

/* ---------- 5. Gallery: rack focus + parallax ----------------
   The image drifts within its frame as the section passes — a
   window-into-depth cue that raises perceived quality. Reveal
   handles the entrance; this handles the in-view life. */
@supports (animation-timeline: view()) {
  .gallery-img {
    will-change: transform;
    animation-name: cx-parallax;
    animation-fill-mode: both;
    animation-timing-function: linear;
    animation-duration: auto;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  @keyframes cx-parallax {
    from { transform: translateY(-7%) scale(1.12); }
    to   { transform: translateY(7%) scale(1.12); }
  }
}

/* ---------- 6. For-stylists band: the dark, immersive scene --
   A hard cut to dark = a scene change; the eye recalibrates and
   attends more (contrast is salience). A cursor-tracking spotlight
   turns the section into a small stage focused on the pitch. */
.band { position: relative; overflow: hidden; }
.band::before {
  content: "";
  position: absolute;
  inset: -2px;
  pointer-events: none;
  background: radial-gradient(600px circle at var(--spot-x, 50%) var(--spot-y, 25%),
              color-mix(in srgb, var(--brand) 34%, transparent), transparent 60%);
  opacity: 0;
  transition: opacity .5s ease;
}
.band.spot::before { opacity: .55; }
.band > .container { position: relative; z-index: 1; }

/* ---------- 7. Magnetic CTAs ---------------------------------
   The primary buttons lean toward the cursor. A playful pull
   increases pointer "capture" and click intent. Uses `translate`
   so it stacks with the base :hover lift instead of fighting it. */
.magnetic {
  translate: var(--mgx, 0) var(--mgy, 0);
  transition: translate .3s cubic-bezier(.16, 1, .3, 1);
}

/* ---------- 8. Reduced motion & touch ------------------------
   Meaningful-motion-only means: when a visitor asks for calm,
   give them calm. Everything above collapses to a gentle fade. */
@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .reveal[data-reveal="rise3d"] {
    opacity: 1 !important;
    translate: none !important;
    scale: none !important;
    transform: none !important;
    transition: opacity .3s ease !important;
  }
  .hero-media { animation: none !important; }
  .scroll-cue { display: none; }
  .hero-content { animation: none !important; }
  .gallery-img { animation: none !important; transform: none !important; }
  .scroll-progress { animation: none; }
  [data-tilt] { transform: none !important; transition: box-shadow .3s ease; }
  .js .step-card:not(.is-visible) .step-num { transform: none; opacity: 1; }
  .magnetic { translate: none !important; }
  .band::before { display: none; }
}
