// ZION micro-polish utilities: ScrollReveal + Toast

// ScrollReveal — fades + rises its children in once when scrolled into view.
// Reliable scroll-based check (works in iframes where IO can be flaky).
function ScrollReveal({ children, delay = 0, y = 40 }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  const [settled, setSettled] = React.useState(false);

  React.useEffect(() => {
    if (!ref.current) return;
    let raf = 0;
    const check = () => {
      if (!ref.current) return;
      const r = ref.current.getBoundingClientRect();
      if (r.top < window.innerHeight * 0.9 && r.bottom > 0) {
        setShown(true);
        window.removeEventListener('scroll', onScroll);
      }
    };
    const onScroll = () => { cancelAnimationFrame(raf); raf = requestAnimationFrame(check); };
    check();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); cancelAnimationFrame(raf); };
  }, []);

  // Fallback in case transitionend doesn't fire — settle shortly after reveal.
  React.useEffect(() => {
    if (!shown) return;
    const t = setTimeout(() => setSettled(true), 1100);
    return () => clearTimeout(t);
  }, [shown]);

  return (
    <div ref={ref}
      onTransitionEnd={() => { if (shown) setSettled(true); }}
      style={{
        opacity: shown ? 1 : 0,
        // After the reveal finishes, drop transform + will-change so the browser
        // de-composites this layer. Leaving will-change on permanently promotes each
        // section to its own GPU layer and paints a faint 1px seam where two meet.
        transform: settled ? 'none' : (shown ? 'translateY(0)' : `translateY(${y}px)`),
        transition: `opacity 900ms cubic-bezier(0.16,1,0.3,1) ${delay}ms, transform 900ms cubic-bezier(0.16,1,0.3,1) ${delay}ms`,
        willChange: settled ? 'auto' : 'transform, opacity',
      }}>{children}</div>
  );
}

// Toast — small auto-dismissing notification, bottom-center.
function Toast({ message, show }) {
  return (
    <div style={{
      position: 'fixed', left: '50%', bottom: 32, zIndex: 300,
      transform: `translateX(-50%) translateY(${show ? '0' : '24px'})`,
      opacity: show ? 1 : 0,
      pointerEvents: 'none',
      transition: 'opacity 260ms cubic-bezier(0.16,1,0.3,1), transform 260ms cubic-bezier(0.16,1,0.3,1)',
      display: 'flex', alignItems: 'center', gap: 10,
      background: '#F7591F', color: '#fff',
      padding: '14px 22px', borderRadius: 999,
      fontFamily: 'Poppins, sans-serif', fontWeight: 800, fontSize: 12,
      letterSpacing: '0.12em', textTransform: 'uppercase',
      boxShadow: '0 12px 40px rgba(247,89,31,0.4)',
    }}>
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        <path d="M20 6 L9 17 L4 12" />
      </svg>
      {message}
    </div>
  );
}

window.ScrollReveal = ScrollReveal;
window.Toast = Toast;
