/* ============================================================
   Webfluence — Apple Animation States
   v1.0.0 | Pairs with animations.js
   ============================================================ */

/* ── 1. WORD-BY-WORD REVEAL ────────────────────────────────────────── */
/* Scoped to html.js — so content is visible if JS fails to load */
html.js .wf-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(22px);
  filter: blur(6px);
  transition:
    opacity    0.70s cubic-bezier(0.25, 0.46, 0.45, 0.94),
    transform  0.70s cubic-bezier(0.25, 0.46, 0.45, 0.94),
    filter     0.50s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  will-change: transform, opacity, filter;
}

html.js .wf-word.visible {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* ── 2. SECTION SCALE + FADE REVEAL ────────────────────────────────── */
/* Scoped to html.js — visible without JS */
html.js .wf-reveal {
  opacity: 0;
  transform: translateY(30px) scale(0.97);
  transition:
    opacity   0.80s cubic-bezier(0.25, 0.46, 0.45, 0.94),
    transform 0.80s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  will-change: transform, opacity;
}

html.js .wf-reveal.visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* Delay variants for staggered siblings */
html.js .wf-reveal.d1 { transition-delay: 0.10s; }
html.js .wf-reveal.d2 { transition-delay: 0.20s; }
html.js .wf-reveal.d3 { transition-delay: 0.30s; }
html.js .wf-reveal.d4 { transition-delay: 0.40s; }
html.js .wf-reveal.d5 { transition-delay: 0.50s; }

/* ── 3. KICKER CLIP-PATH WIPE ───────────────────────────────────────── */
/* Gold eyebrow text wipes in left-to-right */
.wf-kicker {
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.65s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  will-change: clip-path;
}

.wf-kicker.wf-kicker-revealed {
  clip-path: inset(0 0% 0 0);
}

/* ── 4. CARD CASCADE ────────────────────────────────────────────────── */
/* For blog post cards, work cards, stat cells */
html.js .wf-card-cascade {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity   0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94),
    transform 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  will-change: transform, opacity;
}

html.js .wf-card-cascade.visible {
  opacity: 1;
  transform: translateY(0);
}

/* ── 5. SERVICE ACTIVE STATE (sticky walkthrough) ───────────────────── */
/* Left number/label column pops when service is in view */
.wf-service-block .wf-service-num-large {
  transition: color 0.45s ease, transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  transform: translateX(-8px);
  color: var(--border-lt);
}

.wf-service-block.wf-service-active .wf-service-num-large {
  color: var(--ink);
  transform: translateX(0);
}

.wf-service-block .wf-service-left {
  transition: opacity 0.45s ease;
  opacity: 0.4;
}

.wf-service-block.wf-service-active .wf-service-left {
  opacity: 1;
}

/* ── 6. SCROLL PROGRESS BAR ─────────────────────────────────────────── */
#wf-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 0%;
  background: var(--gold);
  z-index: 9999;
  pointer-events: none;
  transition: width 0.05s linear;
}

/* ── 7. NAV SCROLL STATES ───────────────────────────────────────────── */
/* Three states driven by JS class toggling */
.wf-nav {
  transition:
    background 0.35s ease,
    box-shadow 0.35s ease,
    border-color 0.35s ease;
}

/* At top of hero — fully transparent, links still visible */
.wf-nav.wf-nav-top {
  background: rgba(255, 255, 255, 0.0) !important;
  border-bottom-color: transparent;
  box-shadow: none;
}

.wf-nav.wf-nav-top .wf-nav-logo,
.wf-nav.wf-nav-top .wf-nav-links a {
  color: var(--ink);
}

/* Scrolled — Apple frosted glass */
.wf-nav.wf-nav-scrolled {
  background: rgba(255, 255, 255, 0.85) !important;
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

/* Deep in page — slightly more opaque */
.wf-nav.wf-nav-solid {
  background: rgba(255, 255, 255, 0.95) !important;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}

/* ── 8. LINE-BY-LINE REVEAL ─────────────────────────────────────────── */
html.js .wf-line-reveal {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity   0.60s cubic-bezier(0.25, 0.46, 0.45, 0.94),
    transform 0.60s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

html.js .wf-line-reveal.wf-line-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Stagger line reveals in sequence */
.wf-line-reveal:nth-child(1) { transition-delay: 0.00s; }
.wf-line-reveal:nth-child(2) { transition-delay: 0.08s; }
.wf-line-reveal:nth-child(3) { transition-delay: 0.16s; }
.wf-line-reveal:nth-child(4) { transition-delay: 0.24s; }
.wf-line-reveal:nth-child(5) { transition-delay: 0.32s; }

/* ── 9. HERO H1 SCRUB (scroll-driven) ───────────────────────────────── */
/* transform/opacity set by JS inline — just set will-change here */
.wf-hero-h1 {
  will-change: transform, opacity;
  transform-origin: center center;
}

/* ── 10. STAT ITEM REVEAL ───────────────────────────────────────────── */
/* Stats count up when in view — visual wrapper animation */
.wf-stat-item {
  transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* ── 11. HERO PARALLAX CONTAINER ────────────────────────────────────── */
.wf-hero .wf-container {
  will-change: transform;
  transform-origin: center top;
}

/* ── 12. REDUCED MOTION — no animations at all ──────────────────────── */
.no-motion *,
.no-motion *::before,
.no-motion *::after {
  animation-duration:      0.001ms !important;
  animation-delay:         0.001ms !important;
  transition-duration:     0.001ms !important;
  transition-delay:        0.001ms !important;
}

.no-motion .wf-word,
.no-motion .wf-reveal,
.no-motion .wf-card-cascade,
.no-motion .wf-kicker,
.no-motion .wf-line-reveal,
html:not(.js) .wf-word,
html:not(.js) .wf-reveal,
html:not(.js) .wf-card-cascade,
html:not(.js) .wf-line-reveal {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
  clip-path: none !important;
  transition: none !important;
}

/* ── 13. PERFORMANCE: gpu-hint on animated elements ─────────────────── */
.wf-word,
.wf-reveal,
.wf-card-cascade,
.wf-service-num-large {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
@media (prefers-reduced-motion: reduce) {
  .wf-word,
  .wf-reveal,
  .wf-card-cascade,
  .wf-kicker,
  .wf-line-reveal {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
    transition: none !important;
  }
}

/* ══════════════════════════════════════════════════════════
   CSS SCROLL-DRIVEN ANIMATIONS (v1.2.0)
   Runs 100% off the main thread — compositor only.
   Supported: Chrome 115+, Edge 115+, Safari 18+
   Falls back to IntersectionObserver for other browsers.
   
   Technique: animation-timeline: view() maps the element's
   position in the viewport to animation progress.
   animation-range: entry 0% entry 40% = animate during the
   first 40% of the element's entry into the viewport.
   
   The @supports guard ensures this ONLY applies when the
   browser supports it — IO-based fallback handles the rest.
═══════════════════════════════════════════════════════════ */

@keyframes wf-fade-in {
  from {
    opacity: 0;
    transform: translateY(30px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes wf-line-in {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes wf-kicker-wipe {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0% 0 0);   }
}

@keyframes wf-card-in {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@supports (animation-timeline: scroll()) {

  /* ── Sections ── */
  html.js .wf-reveal {
    /* Override IO-based approach: use scroll timeline instead */
    opacity: 0;
    transform: translateY(30px) scale(0.97);
    animation: wf-fade-in linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 50%;
    /* Disable the JS-based transition */
    transition: none !important;
  }

  html.js .wf-reveal.visible {
    /* When IO fires as backup, still show correctly */
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* Stagger delays via animation-delay */
  html.js .wf-reveal.d1 { animation-range: entry  5% entry 55%; }
  html.js .wf-reveal.d2 { animation-range: entry 10% entry 60%; }
  html.js .wf-reveal.d3 { animation-range: entry 15% entry 65%; }
  html.js .wf-reveal.d4 { animation-range: entry 20% entry 70%; }
  html.js .wf-reveal.d5 { animation-range: entry 25% entry 75%; }

  /* ── Kicker labels ── */
  html.js .wf-kicker {
    clip-path: inset(0 100% 0 0);
    animation: wf-kicker-wipe linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 25%;
    transition: none !important;
  }

  html.js .wf-kicker.wf-kicker-revealed {
    animation: none;
    clip-path: inset(0 0% 0 0);
  }

  /* ── Line reveals ── */
  html.js .wf-line-reveal {
    opacity: 0;
    transform: translateY(16px);
    animation: wf-line-in linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 40%;
    transition: none !important;
  }

  html.js .wf-line-reveal.wf-line-visible {
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* Stagger line reveals */
  html.js .wf-line-reveal:nth-child(1) { animation-delay: 0.00s; }
  html.js .wf-line-reveal:nth-child(2) { animation-delay: 0.06s; }
  html.js .wf-line-reveal:nth-child(3) { animation-delay: 0.12s; }
  html.js .wf-line-reveal:nth-child(4) { animation-delay: 0.18s; }
  html.js .wf-line-reveal:nth-child(5) { animation-delay: 0.24s; }

  /* ── Card cascade ── */
  html.js .wf-card-cascade {
    opacity: 0;
    transform: translateY(24px);
    animation: wf-card-in linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 40%;
    transition: none !important;
  }

  html.js .wf-card-cascade.visible {
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* ── Word reveals — each span gets view timeline ── */
  /* Note: wf-word spans are created by JS so they won't have
     view() timeline (created dynamically). JS-based approach
     remains for .wf-word spans. SDA handles the container. */
  html.js .wf-word-reveal {
    animation: none; /* container not animated — words are */
  }

  /* ── Progress bar — scroll-linked without JS ── */
  @keyframes wf-progress-grow {
    from { width: 0%; }
    to   { width: 100%; }
  }

  #wf-progress {
    animation: wf-progress-grow linear;
    animation-timeline: scroll(root);
    /* JS-based approach still updates width — this is a backup */
  }

}
/* end @supports */
