/* global React, ReactDOM, Icon, Reveal, useMagnetic, HeroDashboard, FeatureBento, LogoStrip, StatsBand, HowItWorks, Testimonials, Pricing, FinalCTA, Footer */
const { useEffect, useRef, useState } = React;

function Nav() {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <nav className={`nav ${scrolled ? 'scrolled' : ''}`}>
      <a className="nav-logo">
        <div className="nav-logo-mark"/> Markflow
      </a>
      <div className="nav-links">
        <a href="#features">Features</a>
        <a href="#pricing">Pricing</a>
        <a>Customers</a>
        <a>Docs</a>
      </div>
      <div className="nav-cta">
        <a className="btn btn-ghost">Sign in</a>
        <a className="btn btn-primary">Start free<span className="btn-shine"/></a>
      </div>
    </nav>
  );
}

function Hero() {
  // Inverted animation strategy: the HEAVY dashboard (~650 nodes) stays perfectly still.
  // The LIGHT hero text (~15 nodes) animates up + fades out. Cheap to paint, buttery smooth.
  // Scroll progress is written to the DOM via refs only — no React state is touched
  // during scroll, so the 656-node HeroDashboard never re-reconciles mid-scroll.
  const trackRef = useRef(null);
  const wrapRef = useRef(null);
  const heroInnerRef = useRef(null);
  const blurRef = useRef(null);
  const scrimRef = useRef(null);
  const hintInlineRef = useRef(null);
  const hintFixedRef = useRef(null);
  const DASH_VISIBLE_H = 640;
  const DASH_FULL_H    = 1420;
  const REVEAL_DIST    = DASH_FULL_H - DASH_VISIBLE_H;

  useEffect(() => {
    let rafId = 0;
    let lastP = -1, lastRP = -1;
    let pendingP = 0, pendingRP = 0;
    let scrollEndTimer = 0;

    const compute = () => {
      // Phase 1: hero text fade-out (slower now — 0 → ~900px scroll)
      const v = Math.min(1, Math.max(0, window.scrollY / 900));
      const eased = 1 - Math.pow(1 - v, 3);
      pendingP = eased;

      // Phase 2: reveal progress inside sticky track.
      // Dashboard internal scroll is delayed significantly: starts only after the
      // user has had time to see the full top of the dashboard with the hero text gone.
      const track = trackRef.current;
      if (track) {
        const rect = track.getBoundingClientRect();
        const stickyTop = 120;
        const start = -rect.top + stickyTop;
        // Add a "dwell zone" of extra scroll before internal reveal begins.
        const DWELL = 500;
        const gatedStart = Math.max(0, start - DWELL);
        const end = rect.height - DASH_VISIBLE_H - DWELL;
        pendingRP = Math.min(1, Math.max(0, gatedStart / end));
      }
    };

    const write = () => {
      rafId = 0;
      const p = pendingP;
      const rp = pendingRP;
      if (p === lastP && rp === lastRP) return;
      lastP = p; lastRP = rp;

      // Animate the HERO TEXT (small, cheap) instead of the dashboard (huge, expensive).
      // Text moves up and fades out as user scrolls. Dashboard stays perfectly still.
      const heroInner = heroInnerRef.current;
      if (heroInner) {
        heroInner.style.transform = `translate3d(0, ${-120 * p}px, 0)`;
        heroInner.style.opacity = (1 - p).toFixed(3);
        heroInner.style.pointerEvents = p > 0.8 ? 'none' : 'auto';
      }

      // Dashboard wrap: keep static. Only update the reveal CSS var (controls the
      // inner scroll of db-content as user scrolls through the track).
      const wrap = wrapRef.current;
      if (wrap) {
        wrap.style.setProperty('--dash-reveal-y', `${-REVEAL_DIST * rp}px`);
      }

      // Overlay fades out as user scrolls. Scrim fades too.
      const blurEl = blurRef.current;
      if (blurEl) blurEl.style.opacity = (1 - p).toFixed(3);
      const scrim = scrimRef.current;
      if (scrim) scrim.style.opacity = ((1 - p) * 0.75).toFixed(3);

      const hintI = hintInlineRef.current;
      if (hintI) hintI.style.opacity = (1 - p).toFixed(3);
      const hintF = hintFixedRef.current;
      if (hintF) hintF.style.opacity = (p > 0.85 && rp < 0.95) ? '1' : '0';
    };

    const onScroll = () => {
      // Mark body as scrolling — useLivePulse and other background timers check this
      // and skip re-renders while it's set.
      document.body.setAttribute('data-scrolling', '');
      if (scrollEndTimer) clearTimeout(scrollEndTimer);
      scrollEndTimer = setTimeout(() => {
        document.body.removeAttribute('data-scrolling');
      }, 150);
      compute();
      if (!rafId) rafId = requestAnimationFrame(write);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      if (rafId) cancelAnimationFrame(rafId);
    };
  }, []);

  // Track height = visible dashboard + dwell zone (pause after text gone) + reveal distance.
  const DWELL = 500;
  const trackHeight = DASH_VISIBLE_H + DWELL + REVEAL_DIST;

  // Pre-mount the full dashboard during browser idle time (after initial paint),
  // so by the time the user scrolls, DOM + chart SVGs are already laid out.
  const [fullMounted, setFullMounted] = useState(false);
  useEffect(() => {
    const cb = () => setFullMounted(true);
    if ('requestIdleCallback' in window) {
      const id = window.requestIdleCallback(cb, { timeout: 1500 });
      return () => window.cancelIdleCallback && window.cancelIdleCallback(id);
    } else {
      const t = setTimeout(cb, 800);
      return () => clearTimeout(t);
    }
  }, []);

  // Swap skeleton → full dashboard as soon as idle mount completes, so the
  // heavy paint happens while the user is still reading the hero (blur
  // overlay hides it). Gating on scroll position meant the expensive mount
  // ran during scroll, which caused visible jank.
  const showFullDashboard = fullMounted;


  return (
    <section className="hero">
      <div className="hero-bg">
        <div className="grid"/>
        <div className="glow glow-1"/>
        <div className="glow glow-2"/>
        <div className="glow glow-3"/>
      </div>

      <div ref={heroInnerRef} className="hero-inner">
        <div className="eyebrow">
          <span className="eyebrow-pill">NEW</span>
          <span className="eyebrow-dot"/>
          <span>MarkAI v1.2 — weekly strategy briefs are live</span>
        </div>
        <h1 className="hero-title">
          All your marketing,<br/>
          in <span className="gradient">one flow</span>.
        </h1>
        <p className="hero-sub">
          Markflow brings <b>analytics, AI content, scheduling and budget</b> into a single platform.
          Replace five tools, ship twice as fast, and finally see every channel in one dashboard.
        </p>
        <div className="hero-ctas">
          <a className="btn btn-lg btn-primary">Start free — 14 days<span className="btn-shine"/></a>
          <a className="btn btn-lg btn-secondary"><Icon name="play" size={14}/> Watch 2-min demo</a>
        </div>
        <div className="hero-micro">
          <div className="avatars">
            <div style={{ background: 'linear-gradient(135deg, #EC4899, #8B7BFF)' }}/>
            <div style={{ background: 'linear-gradient(135deg, #22D3EE, #2F7BFF)' }}/>
            <div style={{ background: 'linear-gradient(135deg, #10B981, #34D399)' }}/>
            <div style={{ background: 'linear-gradient(135deg, #F59E0B, #EC4899)' }}/>
          </div>
          <span><b style={{ color: 'var(--ink)' }}>2,400+</b> marketers in flow</span>
          <span className="stars">
            {[0,0,0,0,0].map((_, i) => <Icon key={i} name="star" size={13}/>)}
            <b style={{ marginLeft: 6, color: 'var(--ink)' }}>4.9</b>
          </span>
        </div>
        <div ref={hintInlineRef} className="scroll-hint scroll-hint-inline" style={{ opacity: 1 }}>
          <span>Scroll to explore</span>
          <div className="scroll-hint-line"><div className="scroll-hint-dot"/></div>
        </div>
      </div>

      {/* Scroll track — tall container that makes the sticky dashboard stay pinned while the inner content scrolls up */}
      <div
        ref={trackRef}
        className="hero-dashboard-track"
        style={{ height: trackHeight }}
      >
        <div
          ref={wrapRef}
          className="hero-dashboard-wrap hero-dashboard-behind"
          style={{
            ['--dash-visible-h']: `${DASH_VISIBLE_H}px`,
            ['--dash-reveal-y']: `0px`,
          }}
        >
          {/* Dashboard is rendered from page load — no pre-mount/skeleton gymnastics needed.
              It stays perfectly still; the hero text animates over the top of it. */}
          <div className="dash-layer dash-layer-full" data-eager-inview>
            <HeroDashboard/>
          </div>
          {/* Overlay that fades out as user scrolls */}
          <div ref={blurRef} className="hero-dashboard-blur-overlay" style={{ opacity: 1 }} aria-hidden="true"/>
        </div>
      </div>

      {/* Scroll hint — fixed to viewport during dashboard reveal, OUTSIDE the scrolling track */}
      <div
        ref={hintFixedRef}
        className="scroll-hint scroll-hint-fixed"
        style={{ opacity: 0 }}
      >
        <span>Scroll to explore</span>
        <div className="scroll-hint-line"><div className="scroll-hint-dot"/></div>
      </div>

      {/* Scrim over the blurred dashboard while it sits behind text */}
      <div
        ref={scrimRef}
        className="hero-scrim"
        style={{ opacity: 0.75 }}
      />
    </section>
  );
}

function App() {
  return (
    <div className="page">
      <Nav/>
      <Hero/>
      <LogoStrip/>
      <FeatureBento/>
      <StatsBand/>
      <HowItWorks/>
      <Testimonials/>
      <Pricing/>
      <FinalCTA/>
      <Footer/>
    </div>
  );
}

// Global fadeIn keyframe for SVG use
const fadeKF = document.createElement('style');
fadeKF.textContent = '@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }';
document.head.appendChild(fadeKF);

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
