// Runtime bundle for Babel-standalone.
// Source of truth: GlassHeader.jsx, GridScanBG.jsx, HeroShell.jsx in this
// folder, vendored verbatim from handoff 2/. This file concatenates them
// with the ES-module `import React...` / `export default` boilerplate
// removed so browser-side Babel (no module resolver) can consume them
// as plain globals on window.RepleyHero.
//
// Component internals (inline styles, filters, animations, RAF loops,
// rgba values, turbulence frequencies, blend modes, scroll-shrink curve,
// cursor-driven dispScale, illuminated cells, scanner sweep, caustics,
// grain, vignette, grid densities) are preserved byte-for-byte.

const { useState, useEffect, useRef } = React;

/* ==================================================================
   GlassHeader  (from ./GlassHeader.jsx)
   ================================================================== */
function NavContent({ scrolled, nav, logo, cta, onNav, isMobile }) {
  const padX = isMobile ? 14 : (24 - scrolled * 4);
  const padXLeft = isMobile ? 16 : (28 - scrolled * 4);
  return (
    <div style={{
      position: 'relative',
      zIndex: 2,
      height: '100%',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      padding: `0 ${padX}px 0 ${padXLeft}px`,
      color: 'white',
      fontFamily: 'Inter, -apple-system, sans-serif',
    }}>
      <div style={{
        fontSize: isMobile ? 16 : 19,
        fontWeight: 500,
        letterSpacing: '-0.02em',
        color: '#14110D',
        display: 'flex',
        alignItems: 'center',
      }}>
        {logo}
      </div>

      {!isMobile && (
        <nav style={{
          display: 'flex',
          gap: 4,
          position: 'absolute',
          left: '50%',
          transform: 'translateX(-50%)',
        }}>
          {nav.map(item => (
            <a
              key={item}
              href="#"
              onClick={e => { e.preventDefault(); onNav?.(item, e); }}
              style={{
                fontSize: 14,
                color: '#14110D',
                textDecoration: 'none',
                padding: '8px 14px',
                borderRadius: 999,
                fontWeight: 500,
                transition: 'background 200ms, color 200ms',
              }}
              onMouseEnter={e => e.currentTarget.style.background = 'rgba(20,17,13,0.08)'}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
            >
              {item}
            </a>
          ))}
        </nav>
      )}

      <button
        onClick={cta?.onClick}
        style={{
          border: 'none',
          background: 'linear-gradient(180deg, rgba(255,255,255,0.98), rgba(255,255,255,0.88))',
          color: '#3d1608',
          fontSize: isMobile ? 13 : 14,
          fontWeight: 550,
          padding: isMobile ? '7px 14px' : `${8 - scrolled * 1}px 18px`,
          borderRadius: 999,
          cursor: 'pointer',
          letterSpacing: '-0.01em',
          boxShadow: '0 2px 8px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.9), inset 0 -1px 0 rgba(0,0,0,0.05)',
          fontFamily: 'inherit',
          whiteSpace: 'nowrap',
        }}
      >
        {cta?.label ?? 'Get Started'}
      </button>
    </div>
  );
}

function GlassHeader({
  scrollY: scrollYProp,
  mouse: mouseProp,
  nav = ['Product', 'Process', 'Pricing', 'Support'],
  logo = 'Repley',
  cta = { label: 'Get Started' },
  onNav,
}) {
  const [scrollYSelf, setScrollYSelf] = useState(0);
  const [mouseSelf, setMouseSelf] = useState({ x: 0.5, y: 0.5 });
  const [isMobile, setIsMobile] = useState(
    typeof window !== 'undefined' ? window.innerWidth <= 720 : false
  );
  const [isLite, setIsLite] = useState(
    typeof window !== 'undefined'
      ? (window.matchMedia?.('(hover: none)').matches || window.innerWidth <= 900)
      : false
  );

  useEffect(() => {
    const onResize = () => {
      setIsMobile(window.innerWidth <= 720);
      setIsLite(window.matchMedia?.('(hover: none)').matches || window.innerWidth <= 900);
    };
    window.addEventListener('resize', onResize, { passive: true });
    return () => window.removeEventListener('resize', onResize);
  }, []);

  useEffect(() => {
    if (scrollYProp !== undefined) return;
    const onScroll = () => {
      const y = window.scrollY || document.documentElement.scrollTop || 0;
      setScrollYSelf(y);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [scrollYProp]);

  useEffect(() => {
    if (mouseProp !== undefined || isLite) return;
    const onMove = (e) => setMouseSelf({
      x: e.clientX / window.innerWidth,
      y: Math.min(1, e.clientY / 300),
    });
    window.addEventListener('mousemove', onMove);
    return () => window.removeEventListener('mousemove', onMove);
  }, [mouseProp, isLite]);

  const scrollY = scrollYProp ?? scrollYSelf;
  const mouse = mouseProp ?? mouseSelf;

  const scrolled = Math.min(scrollY / 200, 1);
  const width = isMobile
    ? 'calc(100% - 16px)'
    : `calc(${96 - scrolled * 6}% - 0px)`;
  const top = isMobile ? 12 : (20 - scrolled * 6);
  const radius = isMobile ? 18 : 22;
  const dispScale = isLite ? 0 : (14 + (mouse.x - 0.5) * 16);

  return (
    <>
      <svg width="0" height="0" style={{ position: 'absolute' }} aria-hidden="true">
        <defs>
          <filter id="refractGlassC" x="-10%" y="-10%" width="120%" height="120%">
            <feTurbulence type="fractalNoise" baseFrequency="0.008 0.015" numOctaves="2" seed="9">
              <animate attributeName="baseFrequency" dur="30s" values="0.008 0.015; 0.012 0.02; 0.008 0.015" repeatCount="indefinite" />
            </feTurbulence>
            <feDisplacementMap in="SourceGraphic" scale={dispScale} xChannelSelector="R" yChannelSelector="G" />
          </filter>
          <filter id="causticsC">
            <feTurbulence type="fractalNoise" baseFrequency="0.025" numOctaves="3" seed="12">
              <animate attributeName="baseFrequency" dur="18s" values="0.022;0.03;0.022" repeatCount="indefinite" />
            </feTurbulence>
            <feColorMatrix values="0 0 0 0 1   0 0 0 0 0.95   0 0 0 0 0.82   0 0 0 1.8 -0.6" />
            <feGaussianBlur stdDeviation="0.6" />
          </filter>
        </defs>
      </svg>

      <header
        style={{
          position: 'fixed',
          top,
          left: '50%',
          transform: 'translateX(-50%)',
          width,
          maxWidth: 1360,
          height: isMobile ? 52 : (64 - scrolled * 8),
          borderRadius: radius,
          zIndex: 50,
          overflow: 'hidden',
          transition: 'top 400ms cubic-bezier(.2,.8,.2,1), height 400ms cubic-bezier(.2,.8,.2,1), width 400ms cubic-bezier(.2,.8,.2,1)',
          boxShadow: isMobile
            ? '0 12px 30px -12px rgba(0,0,0,0.35), inset 0 0 0 1px rgba(255,255,255,0.25), inset 0 1px 0 rgba(255,255,255,0.55)'
            : `
            0 28px 80px -20px rgba(0,0,0,0.55),
            0 10px 30px -10px rgba(0,0,0,0.35),
            inset 0 0 0 1px rgba(255,255,255,0.22),
            inset 0 1.5px 0 rgba(255,255,255,0.5),
            inset 0 -1.5px 0 rgba(255,180,120,0.15)
          `,
        }}
      >
        <div style={{
          position: 'absolute', inset: 0,
          backdropFilter: 'blur(10px) saturate(1.7)',
          WebkitBackdropFilter: 'blur(10px) saturate(1.7)',
          background: 'linear-gradient(180deg, rgba(255,255,255,0.12), rgba(255,255,255,0.04))',
          filter: isLite ? 'none' : 'url(#refractGlassC)',
        }} />

        {!isLite && (
          <svg width="100%" height="100%" style={{
            position: 'absolute', inset: 0, mixBlendMode: 'screen',
            opacity: 0.45, pointerEvents: 'none',
          }}>
            <rect width="100%" height="100%" filter="url(#causticsC)" />
          </svg>
        )}

        {!isLite && (
          <div style={{
            position: 'absolute', inset: 0, pointerEvents: 'none',
            background: `radial-gradient(40% 200% at ${mouse.x * 100}% ${mouse.y * 100}%, rgba(255,230,190,0.5), transparent 55%)`,
            mixBlendMode: 'screen',
          }} />
        )}

        <div style={{
          position: 'absolute', inset: 0, borderRadius: radius, pointerEvents: 'none',
          boxShadow: `
            inset 1px 0 0 rgba(255,100,120,0.25),
            inset -1px 0 0 rgba(100,180,255,0.25),
            inset 0 1px 0 rgba(255,240,180,0.35),
            inset 0 -1px 0 rgba(200,120,255,0.2)
          `,
        }} />

        <div style={{
          position: 'absolute', inset: 0, borderRadius: radius, pointerEvents: 'none',
          background: 'linear-gradient(180deg, rgba(255,255,255,0.32) 0%, rgba(255,255,255,0) 45%)',
        }} />

        <NavContent scrolled={scrolled} nav={nav} logo={logo} cta={cta} onNav={onNav} isMobile={isMobile} />
      </header>
    </>
  );
}

/* ==================================================================
   GridScanBG  (from ./GridScanBG.jsx, default theme='light')
   ================================================================== */
function GridScanBG({ theme = 'light', scrollY: scrollYProp, zIndex = 0 }) {
  const canvasRef = useRef(null);
  const rafRef = useRef(0);
  const themeRef = useRef(theme);
  useEffect(() => { themeRef.current = theme; }, [theme]);

  const [scrollYSelf, setScrollYSelf] = useState(0);
  useEffect(() => {
    if (scrollYProp !== undefined) return;
    const on = () => setScrollYSelf(window.scrollY || document.documentElement.scrollTop || 0);
    on();
    window.addEventListener('scroll', on, { passive: true });
    return () => window.removeEventListener('scroll', on);
  }, [scrollYProp]);
  const scrollY = scrollYProp ?? scrollYSelf;

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let w = 0, h = 0;
    let lite = window.innerWidth <= 900 || window.matchMedia?.('(hover: none)').matches;
    const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;

    const resize = () => {
      w = window.innerWidth;
      h = window.innerHeight;
      lite = w <= 900 || window.matchMedia?.('(hover: none)').matches;
      const dpr = Math.min(window.devicePixelRatio || 1, lite ? 1.25 : 2);
      canvas.width = w * dpr;
      canvas.height = h * dpr;
      canvas.style.width = w + 'px';
      canvas.style.height = h + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener('resize', resize);

    const clamp01 = (v) => Math.max(0, Math.min(1, v));
    const start = performance.now();
    let frame = 0;

    const draw = (now) => {
      frame++;
      // Throttle to ~30fps on lite devices, paint every frame on desktop
      if (lite && (frame & 1)) {
        rafRef.current = requestAnimationFrame(draw);
        return;
      }
      if (reduceMotion) {
        // Static single frame; don't request next animation frame
      }
      const CELL = lite ? 56 : 40;
      const t = (now - start) / 1000;
      ctx.clearRect(0, 0, w, h);
      const isLight = themeRef.current === 'light';

      const DUR = 6;
      const p = (t % DUR) / DUR;
      const S = -h + p * (w + h * 2);
      const BEAM = 80;

      const cols = Math.ceil(w / CELL) + 2;
      const rows = Math.ceil(h / CELL) + 2;
      for (let j = 0; j < rows; j++) {
        for (let i = 0; i < cols; i++) {
          const cx = i * CELL + CELL / 2;
          const cy = j * CELL + CELL / 2;
          const d = Math.abs(cx + cy - S);
          if (d < BEAM * 2.5) {
            const k = Math.max(0, 1 - d / (BEAM * 2.5));
            const alpha = Math.pow(k, 2) * 0.9;
            const core = Math.pow(k, 6);
            ctx.fillStyle = isLight
              ? `rgba(230, ${110 + core * 40}, ${40 + core * 30}, ${alpha * 0.22})`
              : `rgba(255, ${160 + core * 80}, ${90 + core * 120}, ${alpha * 0.35})`;
            ctx.fillRect(i * CELL + 1, j * CELL + 1, CELL - 2, CELL - 2);
            if (k > 0.55) {
              ctx.strokeStyle = isLight
                ? `rgba(220, 100, 30, ${(k - 0.55) * 2.0})`
                : `rgba(255, 230, 180, ${(k - 0.55) * 2.2})`;
              ctx.lineWidth = 1;
              ctx.strokeRect(i * CELL + 0.5, j * CELL + 0.5, CELL - 1, CELL - 1);
            }
          }
        }
      }

      ctx.save();
      const grad = ctx.createLinearGradient(0, 0, w, h);
      const lo = clamp01(p - 0.08);
      const mid = clamp01(p);
      const hi = clamp01(p + 0.08);
      const loOut = clamp01(lo - 0.01);
      const hiOut = clamp01(hi + 0.01);
      const addStop = (off, col) => { try { grad.addColorStop(clamp01(off), col); } catch {} };
      if (isLight) {
        addStop(loOut, 'rgba(230,110,40,0)');
        if (lo > loOut) addStop(lo, 'rgba(230,140,70,0.05)');
        addStop(mid, 'rgba(235,130,60,0.28)');
        if (hi < hiOut) addStop(hi, 'rgba(230,140,70,0.05)');
        addStop(hiOut, 'rgba(230,110,40,0)');
        ctx.globalCompositeOperation = 'multiply';
      } else {
        addStop(loOut, 'rgba(255,140,80,0)');
        if (lo > loOut) addStop(lo, 'rgba(255,180,120,0.08)');
        addStop(mid, 'rgba(255,230,190,0.55)');
        if (hi < hiOut) addStop(hi, 'rgba(255,180,120,0.08)');
        addStop(hiOut, 'rgba(255,140,80,0)');
        ctx.globalCompositeOperation = 'screen';
      }
      ctx.fillStyle = grad;
      ctx.fillRect(0, 0, w, h);
      ctx.restore();

      ctx.save();
      ctx.globalCompositeOperation = isLight ? 'source-over' : 'screen';
      const x1 = Math.max(0, S - h);
      const y1 = Math.min(h, S);
      const x2 = Math.min(w, S);
      const y2 = Math.max(0, S - w);
      const lineGrad = ctx.createLinearGradient(x1, y1, x2, y2);
      if (isLight) {
        lineGrad.addColorStop(0, 'rgba(220,90,20,0)');
        lineGrad.addColorStop(0.3, 'rgba(220,90,20,0.85)');
        lineGrad.addColorStop(0.7, 'rgba(220,90,20,0.85)');
        lineGrad.addColorStop(1, 'rgba(220,90,20,0)');
        ctx.shadowColor = 'rgba(230,130,60,0.7)';
      } else {
        lineGrad.addColorStop(0, 'rgba(255,220,180,0)');
        lineGrad.addColorStop(0.3, 'rgba(255,240,210,0.9)');
        lineGrad.addColorStop(0.7, 'rgba(255,240,210,0.9)');
        lineGrad.addColorStop(1, 'rgba(255,220,180,0)');
        ctx.shadowColor = 'rgba(255,200,140,0.9)';
      }
      ctx.strokeStyle = lineGrad;
      ctx.lineWidth = 1.2;
      ctx.shadowBlur = 14;
      ctx.beginPath();
      ctx.moveTo(x1, y1);
      ctx.lineTo(x2, y2);
      ctx.stroke();
      ctx.restore();

      if (!reduceMotion) rafRef.current = requestAnimationFrame(draw);
    };
    rafRef.current = requestAnimationFrame(draw);

    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener('resize', resize);
    };
  }, []);

  const py = scrollY * 0.1;
  const isLight = theme === 'light';

  const baseBg = isLight
    ? 'linear-gradient(180deg, #fbf7f0 0%, #f7f1e6 50%, #f3ecdd 100%)'
    : 'linear-gradient(180deg, #0d0704 0%, #120905 50%, #1a0d07 100%)';

  const radialOverlay = isLight
    ? `
      radial-gradient(ellipse 90% 70% at 30% 20%, oklch(98% 0.02 80 / 0.7), transparent 60%),
      radial-gradient(ellipse 80% 70% at 80% 80%, oklch(94% 0.06 55 / 0.45), transparent 60%)
    `
    : `
      radial-gradient(ellipse 90% 70% at 30% 20%, oklch(40% 0.18 40 / 0.55), transparent 60%),
      radial-gradient(ellipse 80% 70% at 80% 80%, oklch(45% 0.22 30 / 0.5), transparent 60%)
    `;

  const gridFineColor = isLight ? 'rgba(180, 90, 30, 0.10)' : 'rgba(255,170,120,0.07)';
  const gridCoarseColor = isLight ? 'rgba(160, 70, 15, 0.18)' : 'rgba(255,190,140,0.14)';

  const vignette = isLight
    ? 'radial-gradient(ellipse 95% 75% at 50% 40%, transparent 55%, rgba(200,140,80,0.10) 100%)'
    : 'radial-gradient(ellipse 80% 60% at 50% 40%, transparent 40%, rgba(0,0,0,0.55) 100%)';

  const atmoBlob = isLight
    ? 'radial-gradient(circle, oklch(92% 0.08 55 / 0.18), transparent 70%)'
    : 'radial-gradient(circle, oklch(75% 0.22 45 / 0.45), transparent 70%)';

  return (
    <div style={{
      position: 'absolute',
      inset: 0,
      overflow: 'hidden',
      background: isLight ? '#f3e8d6' : '#0b0604',
      zIndex,
      transition: 'background 600ms ease',
    }}>
      <div style={{ position: 'absolute', inset: 0, background: radialOverlay }} />
      <div style={{ position: 'absolute', inset: 0, background: baseBg, opacity: isLight ? 0 : 1 }} />

      <div style={{
        position: 'absolute',
        inset: -2,
        transform: `translateY(${py}px)`,
        backgroundImage: `
          linear-gradient(to right, ${gridFineColor} 1px, transparent 1px),
          linear-gradient(to bottom, ${gridFineColor} 1px, transparent 1px)
        `,
        backgroundSize: '40px 40px',
      }} />
      <div style={{
        position: 'absolute',
        inset: -2,
        transform: `translateY(${py}px)`,
        backgroundImage: `
          linear-gradient(to right, ${gridCoarseColor} 1px, transparent 1px),
          linear-gradient(to bottom, ${gridCoarseColor} 1px, transparent 1px)
        `,
        backgroundSize: '200px 200px',
      }} />

      <canvas ref={canvasRef} style={{
        position: 'absolute',
        inset: 0,
        pointerEvents: 'none',
        mixBlendMode: isLight ? 'normal' : 'screen',
      }} />

      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: vignette,
      }} />

      <div style={{
        position: 'absolute',
        left: '50%', top: '40%',
        width: 700, height: 700,
        transform: 'translate(-50%, -50%)',
        borderRadius: '50%',
        background: atmoBlob,
        filter: 'blur(40px)',
        pointerEvents: 'none',
        mixBlendMode: isLight ? 'multiply' : 'screen',
      }} />

      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'200\' height=\'200\'><filter id=\'n\'><feTurbulence type=\'fractalNoise\' baseFrequency=\'0.9\' numOctaves=\'2\'/></filter><rect width=\'200\' height=\'200\' filter=\'url(%23n)\' opacity=\'0.5\'/></svg>")',
        opacity: isLight ? 0.06 : 0.09,
        mixBlendMode: 'overlay',
        pointerEvents: 'none',
      }} />
    </div>
  );
}

/* ==================================================================
   HeroShell  (from ./HeroShell.jsx, default theme='light')
   ================================================================== */
function HeroShell({
  theme = 'light',
  nav,
  logo,
  cta,
  onNav,
  children,
  style,
}) {
  return (
    <div style={{ position: 'relative', minHeight: '100vh', ...style }}>
      <div style={{ position: 'fixed', inset: 0, zIndex: 0, pointerEvents: 'none' }}>
        <GridScanBG theme={theme} />
      </div>
      <GlassHeader nav={nav} logo={logo} cta={cta} onNav={onNav} />
      <div style={{ position: 'relative', zIndex: 1 }}>
        {children}
      </div>
    </div>
  );
}

/* =============== EXPOSE AS GLOBALS =============== */
window.RepleyHero = { GlassHeader, GridScanBG, HeroShell };
