/* v2 — shared utilities */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

function useReveal(opts = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    let fired = false;
    const setIn = () => { if (!fired) { fired = true; setInView(true); } };
    const check = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || 800;
      if (r.top < vh * 0.95 && r.bottom > 0) setIn();
    };
    check();
    let io;
    if (typeof IntersectionObserver !== 'undefined') {
      io = new IntersectionObserver((es) => es.forEach((e) => { if (e.isIntersecting) { setIn(); io && io.unobserve(e.target); } }), { threshold: opts.threshold || 0.15, rootMargin: '0px 0px -10% 0px' });
      io.observe(el);
    }
    const onScroll = () => check();
    window.addEventListener('scroll', onScroll, { passive: true });
    const t = setTimeout(check, 350);
    return () => { io && io.disconnect(); window.removeEventListener('scroll', onScroll); clearTimeout(t); };
  }, []);
  return [ref, inView];
}

function R({ children, as = 'div', className = '', delay = 0, variant = '', style, ...rest }) {
  const [ref, inView] = useReveal();
  const Tag = as;
  const cls = `r ${variant ? variant : ''} ${inView ? 'in' : ''} ${className}`;
  return <Tag ref={ref} className={cls} style={{ transitionDelay: `${delay}ms`, ...style }} {...rest}>{children}</Tag>;
}

function CountUp({ to, duration = 1800, suffix = '', prefix = '', decimals = 0 }) {
  const [val, setVal] = useState(0);
  const [ref, inView] = useReveal({ threshold: 0.4 });
  useEffect(() => {
    if (!inView) return;
    const start = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setVal(to * eased);
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, to, duration]);
  const display = decimals > 0 ? val.toFixed(decimals) : Math.round(val).toLocaleString();
  return <span ref={ref}>{prefix}{display}{suffix}</span>;
}

function BeforeAfter({ before, after }) {
  const [pos, setPos] = useState(50);
  const ref = useRef(null);
  const drag = useRef(false);
  const update = (e) => {
    if (!ref.current) return;
    const r = ref.current.getBoundingClientRect();
    const x = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
    const p = Math.max(0, Math.min(100, (x / r.width) * 100));
    setPos(p);
  };
  return (
    <div className="smile__ba" ref={ref}
      onMouseDown={(e) => { drag.current = true; update(e); }}
      onMouseMove={(e) => { if (drag.current) update(e); }}
      onMouseUp={() => drag.current = false}
      onMouseLeave={() => drag.current = false}
      onTouchStart={(e) => { drag.current = true; update(e); }}
      onTouchMove={(e) => { if (drag.current) update(e); }}
      onTouchEnd={() => drag.current = false}>
      <div className="layer before">{before}</div>
      <div className="layer after" style={{ clipPath: `inset(0 0 0 ${pos}%)` }}>{after}</div>
      <span className="lbl before">Before</span>
      <span className="lbl after">After</span>
      <div className="handle" style={{ left: `${pos}%` }} />
    </div>
  );
}

function Ico({ name, size = 24 }) {
  const s = size, p = { width: s, height: s, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round' };
  const i = {
    tooth: <svg {...p}><path d="M12 2c-3 0-5 1.5-6 1.5S4 3 3 4c-1 1.5 0 4 .5 6S5 14 5.5 16s1 5 2.5 5 2-3 2.5-5 1-1 1.5-1 1 1 1.5 1 1 0 1.5 0 1 0 1.5 0 1-1 1.5-1 1.5 0 2 0c.8 0 1.4-1 1.5-2s.5-3 1-5 1.5-4.5.5-6c-1-1-2-.5-3-.5S15 2 12 2z"/></svg>,
    sparkle: <svg {...p}><path d="M12 3v6m0 6v6m-9-9h6m6 0h6"/><path d="M5.6 5.6l4.2 4.2m4.4 4.4l4.2 4.2M5.6 18.4l4.2-4.2m4.4-4.4l4.2-4.2"/></svg>,
    align: <svg {...p}><rect x="3" y="9" width="18" height="6" rx="2"/><path d="M7 9v6m4-6v6m4-6v6"/></svg>,
    shield: <svg {...p}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="M9 12l2 2 4-4"/></svg>,
    laser: <svg {...p}><circle cx="12" cy="12" r="4"/><path d="M12 2v3m0 14v3M2 12h3m14 0h3M5 5l2 2m10 10l2 2M5 19l2-2m10-10l2-2"/></svg>,
    smile: <svg {...p}><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><circle cx="9" cy="10" r="0.8" fill="currentColor"/><circle cx="15" cy="10" r="0.8" fill="currentColor"/></svg>,
    moon: <svg {...p}><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>,
    scan: <svg {...p}><path d="M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2M7 12h10"/></svg>,
    check: <svg {...p}><polyline points="20 6 9 17 4 12"/></svg>,
    arr: <svg {...p}><line x1="5" y1="12" x2="19" y2="12"/><polyline points="13 6 19 12 13 18"/></svg>,
    arrUp: <svg {...p}><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>,
    play: <svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 22 12 6 21"/></svg>,
    star: <svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15 9 22 9.3 17 14 18.5 21 12 17.5 5.5 21 7 14 2 9.3 9 9"/></svg>,
    phone: <svg {...p}><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3-8.7A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7 12 12 0 0 0 .7 2.8 2 2 0 0 1-.5 2L8 9.6a16 16 0 0 0 6 6l1.1-1.3a2 2 0 0 1 2-.5 12 12 0 0 0 2.9.7 2 2 0 0 1 1.7 2z"/></svg>,
    mail: <svg {...p}><rect x="3" y="5" width="18" height="14" rx="2"/><polyline points="3 7 12 13 21 7"/></svg>,
    pin: <svg {...p}><path d="M21 10c0 7-9 13-9 13S3 17 3 10a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>,
    clock: <svg {...p}><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>,
    wa: <svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.75.46 3.45 1.32 4.95L2.05 22l5.25-1.38c1.45.79 3.08 1.21 4.74 1.21 5.46 0 9.91-4.45 9.91-9.91C21.95 6.78 17.5 2 12.04 2zm0 1.67c2.2 0 4.26.86 5.82 2.42 1.56 1.56 2.42 3.62 2.42 5.82 0 4.54-3.7 8.23-8.24 8.23-1.48 0-2.93-.39-4.19-1.15l-.3-.17-3.12.82.83-3.04-.2-.32C4.24 15 3.8 13.47 3.8 11.91c.01-4.54 3.7-8.24 8.24-8.24zM8.53 7.33c-.16 0-.43.06-.66.31-.22.25-.87.86-.87 2.07 0 1.22.89 2.39 1.02 2.56.12.17 1.74 2.67 4.23 3.73.59.27 1.05.42 1.41.53.59.19 1.13.16 1.56.1.48-.07 1.46-.6 1.67-1.18.21-.58.21-1.08.15-1.18-.07-.1-.23-.16-.48-.28-.25-.14-1.47-.74-1.7-.82-.22-.08-.37-.12-.56.12-.18.24-.74.8-.88.96-.15.17-.29.19-.53.07-.25-.13-1.05-.39-2-.12-.74-.66-1.23-1.47-1.38-1.71-.12-.24-.01-.38.11-.49.11-.11.27-.29.37-.44.13-.14.17-.25.25-.41.08-.17.04-.31-.02-.43-.06-.11-.56-1.35-.77-1.84-.2-.48-.4-.42-.56-.43l-.48-.01c-.16 0-.42.06-.64.31z"/></svg>,
    mic: <svg {...p}><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><rect x="9" y="2" width="6" height="13" rx="3"/></svg>,
    instagram: <svg {...p}><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="0.6" fill="currentColor"/></svg>,
    google: <svg width={s} height={s} viewBox="0 0 24 24"><path fill="#4285F4" d="M22 12c0-.7 0-1.4-.2-2.1H12v4h5.6c-.2 1.3-1 2.4-2 3.1v2.6h3.3c2-1.8 3.1-4.5 3.1-7.6z"/><path fill="#34A853" d="M12 22c2.7 0 5-1 6.6-2.5l-3.3-2.5c-.9.6-2 1-3.3 1-2.5 0-4.7-1.7-5.4-4H3.2v2.5C4.9 19.6 8.2 22 12 22z"/><path fill="#FBBC04" d="M6.6 14c-.4-1.3-.4-2.7 0-4V7.5H3.2c-1.5 3-1.5 6.5 0 9.5L6.6 14z"/><path fill="#EA4335" d="M12 5.5c1.5 0 2.8.5 3.8 1.5l2.9-2.9C16.9 2.6 14.6 1.7 12 1.7 8.2 1.7 4.9 4.1 3.2 7.5l3.4 2.5c.7-2.3 2.9-4 5.4-4z"/></svg>,
  };
  return i[name] || null;
}

Object.assign(window, { useReveal, R, CountUp, BeforeAfter, Ico });
