/* ══════════════════════════════════════════════════
   TECOMDOM — PREMIUM EFFECTS
   Film Grain · Text Split · 3D Card Tilt · Magnetic
   Loaded after fresco-dark.css to override where needed
════════════════════════════════════════════════════ */

/* ─────────── 1. FILM GRAIN ─────────── */
/* Subtle animated noise texture — adds premium filmic depth.
   mix-blend-mode:overlay keeps it invisible on pure black,
   and very subtle on dark surfaces (exactly what we want). */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  opacity: 0.032;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 200px 200px;
  animation: grain 0.18s steps(1) infinite;
  mix-blend-mode: overlay;
}
@keyframes grain {
  0%   { background-position:   0px   0px; }
  10%  { background-position: -24px  -6px; }
  20%  { background-position:  11px -18px; }
  30%  { background-position: -18px   9px; }
  40%  { background-position:  25px -22px; }
  50%  { background-position:  -5px  32px; }
  60%  { background-position:  14px -13px; }
  70%  { background-position: -26px  20px; }
  80%  { background-position:   7px  28px; }
  90%  { background-position: -20px -17px; }
  100% { background-position:   0px   0px; }
}
@media (prefers-reduced-motion: reduce) {
  body::after { animation: none; background-image: none; }
}

/* ─────────── 2. TEXT SPLIT — WORD REVEAL ─────────── */
/* Words are wrapped in .split-wrap (overflow:hidden clip mask)
   and .split-inner (the element that slides up into view).
   JS controls the translateY via inline style — no CSS transition
   here since rAF from scroll-exp.js provides the interpolation. */
.split-wrap {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  line-height: inherit;
}
.split-inner {
  display: inline-block;
  will-change: transform;
  /* Initial state: hidden below the clip boundary */
  transform: translateY(108%);
}

/* ─────────── 3. PLY POINT CLOUD BACKGROUND ─────────── */
/* Canvas WebGL du nuage de points (Bridge Island, La Réunion).
   z-index:0 = peint dans le groupe des éléments positionnés, donc AU-DESSUS
   du fond --ink de la section .frame-approach mais SOUS .approach-wrap
   (qui crée son propre contexte d'empilement via will-change:transform et
   suit le canvas dans le DOM → rendu par-dessus). */
#ply-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  display: block;
  z-index: 0;
}
/* Supprimé si l'utilisateur préfère pas d'animations */
@media (prefers-reduced-motion: reduce) {
  #ply-bg { display: none; }
}

/* ─────────── 4. CONTACT TITLE — LINE REVEAL ─────────── */
/* The contact title (<h2> with 2 lines) gets a per-line reveal.
   Each line is a display:block wrap with overflow:hidden. */
.contact-line-wrap {
  display: block;
  overflow: hidden;
  /* Let the h2's line-height propagate */
  line-height: inherit;
}
.contact-line-inner {
  display: block;
  will-change: transform;
  /* Initial state: hidden below the clip */
  transform: translateY(112%);
}

/* ─────────── 4. SERVICE CARD 3D TILT ON HOVER ─────────── */
/* Overrides fresco-dark.css: .svc-row:hover { transform: translateY(-2px) !important }
   Same !important, loaded after = wins via cascade order. */
.svc-row:hover {
  transform:
    translateY(-4px)
    perspective(900px)
    rotateX(var(--card-rx, 0deg))
    rotateY(var(--card-ry, 0deg)) !important;
  border-color: rgba(107, 190, 214, .38) !important;
  box-shadow:
    0 16px 48px -12px rgba(43, 139, 174, .25),
    inset 0 1px 0 rgba(107, 190, 214, .12) !important;
}
/* Smoother return transition (spring-like) */
.svc-row {
  transition:
    background-color .2s var(--ease),
    border-color .25s var(--ease),
    box-shadow .3s var(--ease),
    transform .45s cubic-bezier(.34, 1.28, .64, 1) !important;
}

/* ─────────── 5. MAGNETIC BUTTON TRANSITIONS ─────────── */
/* Fast follow during magnetic tracking, springy return on leave.
   JS adds/removes .mag-active to switch between the two states. */
.hero-cta,
.nav-cta {
  transition:
    background-color .3s var(--ease),
    color .3s var(--ease),
    box-shadow .35s var(--ease),
    transform .55s cubic-bezier(.34, 1.56, .64, 1) !important;
}
.hero-cta.mag-active,
.nav-cta.mag-active {
  transition:
    background-color .2s var(--ease),
    color .2s var(--ease),
    box-shadow .2s var(--ease),
    transform .06s linear !important;
}

/* ─────────── 6. ENHANCED APPROACH CARD HOVER GLOW ─────────── */
/* Intensified glow on active card hover — consistent with the
   3D tilt on service cards. */
.approach-card.active .approach-card-frame {
  transition: box-shadow .45s var(--ease) !important;
}
.approach-card.active:hover .approach-card-frame {
  box-shadow:
    0 90px 180px -30px rgba(0, 0, 0, .95),
    0 60px 120px -40px rgba(0, 0, 0, .65),
    0 0 160px -5px  var(--card-glow, rgba(107, 190, 214, .6)),
    0 0  60px -20px var(--card-glow, rgba(107, 190, 214, .45)),
    inset 0  1px 0 rgba(255, 255, 255, .24),
    inset 0 -1px 0 rgba(255, 255, 255, .06) !important;
}

/* ─────────── 7. HERO PARALLAX LAYERS — smoother lerp ─────────── */
/* The .parallax divs inside .hero-bg respond to --mx/--my.
   Reduce the transition from 0.25s to 0.15s for crisper feel. */
.hero-bg .parallax {
  transition: transform .15s cubic-bezier(.2, .7, .2, 1) !important;
}

/* ─────────── 8. KICKER — LINE REVEAL ─────────── */
/* Small horizontal line that draws in from left when the kicker
   becomes visible. Activated via .line-reveal class by JS. */
.kicker {
  display: inline-flex !important;
  align-items: center;
  gap: 0;
}
.kicker::before {
  content: '';
  display: inline-block;
  flex-shrink: 0;
  width: 0;
  height: 1px;
  background: currentColor;
  opacity: .5;
  margin-right: 0;
  transition:
    width .55s cubic-bezier(.16, 1, .3, 1),
    margin-right .55s cubic-bezier(.16, 1, .3, 1);
}
.kicker.line-reveal::before {
  width: 20px;
  margin-right: 10px;
}

/* ─────────── 9. PROCESS LIST — GRADIENT UNDERLINE ─────────── */
/* A blue gradient line draws across the bottom of each item
   as it slides in, reinforcing the "circuit trace" metaphor. */
.proc-list li {
  position: relative;
  overflow: hidden;
}
.proc-list li::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0;
  height: 1px;
  background: linear-gradient(to right, var(--blue, #6BBED6), transparent 80%);
  opacity: .6;
  transition: width .9s cubic-bezier(.16, 1, .3, 1);
}
.proc-list li.line-drawn::after {
  width: 100%;
}

/* ══════════════════════════════════════════════════
   10. HERO TIMELINE — GSAP takes control
   ──────────────────────────────────────────────────
   Quand `html.js-gsap` est posé (avant le 1er paint via
   l'inline script du <head>), on désactive les @keyframes
   CSS de l'entrée du Hero. La timeline GSAP (hero-timeline.js)
   pilote alors opacité, scale, blur, transforms.
   Si JS échoue, les @keyframes CSS d'origine restent
   actifs → graceful degradation.
══════════════════════════════════════════════════ */
.js-gsap .hero-cross,
.js-gsap .hero-cross .cx-h,
.js-gsap .hero-cross .cx-v,
.js-gsap .hero-cross .cx-ring,
.js-gsap .hero-brackets,
.js-gsap .hero-burst,
.js-gsap .hero-logo,
.js-gsap .hero-cta,
.js-gsap .hero-scroll,
.js-gsap .hero-scroll .hs-bead {
  animation: none !important;
}
/* Wipe sombre + scan cyan : retirés du Hero (reveal par clip-path à la place).
   On les masque complètement — l'HTML reste en place pour graceful degradation
   (si JS échoue, html.js-gsap n'est jamais posé → les keyframes CSS reprennent). */
.js-gsap .mark-wipe,
.js-gsap .mark-scan {
  display: none !important;
}
/* On masque tout AVANT le premier set() GSAP pour éviter tout flash
   pendant le boot. La timeline rétablit autoAlpha dès qu'elle joue. */
.js-gsap .hero-cross,
.js-gsap .hero-brackets,
.js-gsap .hero-burst {
  opacity: 0;
}

/* ══════════════════════════════════════════════════
   11. HERO 3D PARTICLE FIELD
   ──────────────────────────────────────────────────
   Canvas qui remplace la grille en perspective.
   Le JS (hero-particles-3d.js) ajoute .is-ready une fois
   l'entrée du Hero terminée → fade-in doux .8s.
══════════════════════════════════════════════════ */
#hero3DParticles {
  position: absolute;
  inset: 0;
  z-index: 1;             /* sous .hero-center (z:2) et .hero-bottom (z:3) */
  opacity: 0;
  pointer-events: none;
  transition: opacity .8s cubic-bezier(.22, .61, .36, 1);
  /* Le scroll fade-out est géré DANS le canvas (scrollAlpha lit --p1-floor-op),
     ce qui évite le double-compounding avec le transition CSS. */
}
#hero3DParticles.is-ready { opacity: 1; }

/* Anciens éléments retirés du DOM — les règles deviennent dead code, on les
   neutralise explicitement par sécurité (au cas où un cache servirait
   l'ancien HTML après upgrade). */
.hero-floor,
.hero-code,
.hero-floor + *,
.hero-floor ~ .hero-code { display: none !important; }
