/* =========================================================================
   Nanuca — WOW layer (entrance choreography, scroll cinema, micro-interactions)
   Loads after enhance.css. Every effect gated behind a body class.
   ========================================================================= */

/* Panel grows with more toggles — let it scroll on short screens. */
.fx-panel {
  max-height: min(78vh, 640px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* =========================================================================
   1. ENTRANCE CHOREOGRAPHY  (body.fx-intro, triggered by body.fx-loaded)
   ========================================================================= */

/* Hero copy rises in, staggered (h1 handled separately via word reveal). */
.fx-intro .hero-content > *:not(h1) {
  opacity: 0;
  transform: translateY(22px);
}
.fx-intro.fx-loaded .hero-content > *:not(h1) {
  animation: wowRiseIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.fx-intro.fx-loaded .hero-content > *:nth-child(1) { animation-delay: 0.05s; }
.fx-intro.fx-loaded .hero-content > *:nth-child(3) { animation-delay: 0.26s; }
.fx-intro.fx-loaded .hero-content > *:nth-child(4) { animation-delay: 0.34s; }
.fx-intro.fx-loaded .hero-content > *:nth-child(5) { animation-delay: 0.42s; }

@keyframes wowRiseIn {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Word-by-word headline reveal (JS wraps each word in .fx-word > span). */
.fx-intro .fx-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.06em;
}
.fx-intro .fx-word > span {
  display: inline-block;
  transform: translateY(110%);
}
.fx-intro.fx-loaded .fx-word > span {
  animation: wowWordUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes wowWordUp {
  from { transform: translateY(110%); }
  to   { transform: translateY(0); }
}

/* The striped panel wipes in from the left. */
.fx-intro .hero-stripes { clip-path: inset(0 100% 0 0); }
.fx-intro.fx-loaded .hero-stripes {
  animation: wowWipeX 0.8s cubic-bezier(0.76, 0, 0.24, 1) 0.05s both;
}
@keyframes wowWipeX {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* Logo image scales + fades up (separate layer from the mark's tilt/levitate). */
.fx-intro .hero-brand-logo { opacity: 0; transform: scale(0.92) translateY(16px); }
.fx-intro.fx-loaded .hero-brand-logo {
  animation: wowLogoIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.25s both;
}
@keyframes wowLogoIn {
  to { opacity: 1; transform: scale(1) translateY(0); }
}

/* Halo blooms behind the card. */
.fx-intro .hero-brand-halo { opacity: 0; transform: scale(0.6); }
.fx-intro.fx-loaded .hero-brand-halo {
  animation: wowHalo 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.2s both;
}
@keyframes wowHalo {
  to { opacity: 1; transform: scale(1); }
}

/* Caption pills stagger up last. */
.fx-intro .hero-brand-caption span { opacity: 0; transform: translateY(12px); }
.fx-intro.fx-loaded .hero-brand-caption span {
  animation: wowRiseIn 0.6s ease both;
}
.fx-intro.fx-loaded .hero-brand-caption span:nth-child(1) { animation-delay: 0.50s; }
.fx-intro.fx-loaded .hero-brand-caption span:nth-child(2) { animation-delay: 0.58s; }
.fx-intro.fx-loaded .hero-brand-caption span:nth-child(3) { animation-delay: 0.66s; }

/* About hero copy uses the same plain staggered rise as the other subpage
   heroes (no word masks — they clip the headline's text-shadow into slabs). */
.fx-intro .about-hero-content > * {
  opacity: 0;
  transform: translateY(18px);
}
.fx-intro.fx-loaded .about-hero-content > * {
  animation: wowRiseIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.fx-intro.fx-loaded .about-hero-content > *:nth-child(1) { animation-delay: 0.05s; }
.fx-intro.fx-loaded .about-hero-content > *:nth-child(2) { animation-delay: 0.16s; }
.fx-intro.fx-loaded .about-hero-content > *:nth-child(3) { animation-delay: 0.30s; }

/* Steam / warmth wisps rising off the logo card (JS injects .fx-steam). */
.fx-steam {
  position: absolute;
  top: -6%;
  left: 50%;
  width: 60%;
  height: 60%;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 1;
  display: none;
}
.fx-hero .fx-steam { display: block; }
.fx-steam i {
  position: absolute;
  bottom: 0;
  width: 14px;
  height: 60%;
  border-radius: 50%;
  background: linear-gradient(to top, rgba(255, 252, 244, 0), rgba(255, 252, 244, 0.55));
  filter: blur(7px);
  opacity: 0;
  animation: wowSteam calc(5.5s / max(var(--fx-intensity, 1), 0.3)) ease-in-out infinite;
}
.fx-steam i:nth-child(1) { left: 28%; animation-delay: 0s; }
.fx-steam i:nth-child(2) { left: 48%; animation-delay: 1.4s; height: 72%; }
.fx-steam i:nth-child(3) { left: 66%; animation-delay: 2.6s; }
@keyframes wowSteam {
  0%   { opacity: 0; transform: translateY(10%) scaleX(1); }
  30%  { opacity: 0.5; }
  70%  { opacity: 0.3; }
  100% { opacity: 0; transform: translateY(-55%) scaleX(1.6); }
}

/* =========================================================================
   2. SCROLL CINEMA  (body.fx-unmask)
   ========================================================================= */

/* About hero photo unmasks downward on load. */
.fx-unmask .about-hero-media img { clip-path: inset(0 0 100% 0); }
.fx-unmask.fx-loaded .about-hero-media img {
  animation: wowUnmaskDown 1.1s cubic-bezier(0.76, 0, 0.24, 1) 0.15s both;
}
/* Paused until the photo decodes (fx-img-hold managed by enhance-wow.js) —
   the curtain should reveal pixels, not an empty frame. */
.fx-unmask.fx-loaded .about-hero-media img.fx-img-hold {
  animation-play-state: paused;
}
@keyframes wowUnmaskDown {
  from { clip-path: inset(0 0 100% 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* Story photos curtain-reveal as their section scrolls in. */
.fx-unmask .about-story .about-photo img {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.15s cubic-bezier(0.76, 0, 0.24, 1);
}
.fx-unmask .about-story.is-visible .about-photo img {
  clip-path: inset(0 0 0 0);
}

/* A thin light bar sweeps the seam of each revealing photo. */
.fx-unmask .about-photo { position: relative; }
.fx-unmask .about-photo::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, rgba(255, 248, 232, 0.9), transparent);
  opacity: 0;
}
.fx-unmask .about-story.is-visible .about-photo::after {
  animation: wowSeamSweep 1.15s cubic-bezier(0.76, 0, 0.24, 1) forwards;
}
@keyframes wowSeamSweep {
  0%   { opacity: 0; top: 0; }
  12%  { opacity: 1; }
  100% { opacity: 0; top: 100%; }
}

/* Pinned scroll moment: photo holds while the story text scrolls past. */
@media (min-width: 860px) {
  .fx-unmask .about-story-grid .about-photo {
    position: sticky;
    top: 104px;
    align-self: start;
  }
}

/* =========================================================================
   3. MAGNETIC CTAS  (body.fx-magnetic)
   ========================================================================= */
.fx-magnetic .btn {
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s ease;
  will-change: transform;
}
.fx-magnetic .btn.fx-mag-active {
  transition: transform 0.08s linear, box-shadow 0.3s ease;
}
.fx-magnetic .btn-primary.fx-mag-active {
  box-shadow:
    0 18px 40px -14px rgba(31, 74, 52, 0.55),
    0 0 30px -4px rgba(74, 155, 115, 0.5);
}

/* =========================================================================
   4. 3D TILT + GLARE ON CARDS  (body.fx-tilt)
   ========================================================================= */
.fx-tilt .product-card {
  transform-style: preserve-3d;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s ease;
  will-change: transform;
}
.fx-tilt .product-card.fx-tilting {
  transition: transform 0.08s linear, box-shadow 0.3s ease;
}
.fx-glare {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 3;
  opacity: 0;
  background: radial-gradient(
    circle at var(--gx, 50%) var(--gy, 50%),
    rgba(255, 255, 255, 0.55),
    rgba(255, 255, 255, 0) 46%
  );
  mix-blend-mode: soft-light;
  transition: opacity 0.3s ease;
}
.fx-tilt .product-card:hover .fx-glare { opacity: 1; }

/* =========================================================================
   5. FLOW & TRANSITIONS  (body.fx-pageflow)
   ========================================================================= */

/* Ambient hue drift tied to scroll position. */
.fx-hue {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s ease;
  background:
    radial-gradient(60% 50% at 82% 8%, rgba(130, 217, 189, 0.12), transparent 60%),
    radial-gradient(52% 46% at 8% 92%, rgba(214, 184, 122, 0.12), transparent 62%);
  filter: hue-rotate(calc(var(--scrollp, 0) * 30deg));
}
.fx-pageflow .fx-hue { opacity: 1; }

/* Velocity-reactive marquee — JS skews the band; the track keeps scrolling. */
.fx-pageflow .marquee-band {
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

/* Cross-document View Transitions between internal pages. The opt-in
   (@view-transition) and the persistent header/WhatsApp names (site-topbar,
   site-whatsapp) live in styles.css; this layer owns the animations and the
   hero morph. JS only skips the transition when fx-pageflow is off
   (pageswap/pagereveal handlers in enhance-wow.js). Browsers without
   support simply navigate instantly. */

/* Each page has exactly one hero; sharing the name lets the browser morph
   one hero into the next (shared-element transition). */
.hero,
.products-showcase,
.clients-page-hero,
.events-page-hero,
.about-hero { view-transition-name: page-hero; }

/* Outgoing page drops away fast; incoming rises in — asymmetric on purpose. */
::view-transition-old(root) {
  animation: wowVtOut 0.16s cubic-bezier(0.23, 1, 0.32, 1) both;
}
::view-transition-new(root) {
  animation: wowVtIn 0.26s cubic-bezier(0.23, 1, 0.32, 1) both;
}
@keyframes wowVtOut {
  to { opacity: 0; }
}
@keyframes wowVtIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Hero morph and header settle use the same snappy curve. */
::view-transition-group(page-hero),
::view-transition-group(site-topbar) {
  animation-duration: 0.28s;
  animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
}

/* =========================================================================
   Return visits (same session, same page) — the entrance already played;
   show the hero instantly. fx-intro-seen is set from sessionStorage by
   enhance-wow.js before the fx-loaded trigger.
   ========================================================================= */
.fx-intro-seen.fx-intro .hero-content > *:not(h1),
.fx-intro-seen.fx-intro .about-hero-content > *,
.fx-intro-seen.fx-intro .fx-word > span,
.fx-intro-seen.fx-intro .hero-brand-logo,
.fx-intro-seen.fx-intro .hero-brand-halo,
.fx-intro-seen.fx-intro .hero-brand-caption span {
  opacity: 1;
  transform: none;
  animation: none;
}
.fx-intro-seen.fx-intro .hero-stripes {
  clip-path: none;
  animation: none;
}
.fx-intro-seen.fx-unmask .about-hero-media img {
  clip-path: none;
  animation: none;
}

/* =========================================================================
   Reduced motion — show everything, animate nothing.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .fx-intro .hero-content > *:not(h1),
  .fx-intro .about-hero-content > *,
  .fx-intro .fx-word > span,
  .fx-intro .hero-brand-logo,
  .fx-intro .hero-brand-halo,
  .fx-intro .hero-brand-caption span {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  .fx-intro .hero-stripes,
  .fx-unmask .about-hero-media img,
  .fx-unmask .about-story .about-photo img {
    clip-path: none !important;
    animation: none !important;
  }
  .fx-steam i { animation: none !important; opacity: 0 !important; }
  /* View transitions are disabled under reduced motion in styles.css. */
}
