// Silk and Blow — icon set (Lucide-style thin geometric strokes, currentColor)
function Icon({ name, size = 20, stroke = 1.5, style }) {
  const p = {
    width: size, height: size, viewBox: '0 0 24 24', fill: 'none',
    stroke: 'currentColor', strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round',
    style,
  };
  const paths = {
    cart: <React.Fragment><circle cx="9" cy="20" r="1.2"/><circle cx="18" cy="20" r="1.2"/><path d="M2 3h2.2l2.3 12.4a1.5 1.5 0 0 0 1.5 1.2h8.6a1.5 1.5 0 0 0 1.5-1.2L20 7H6"/></React.Fragment>,
    close: <path d="M18 6 6 18M6 6l12 12"/>,
    plus: <path d="M12 5v14M5 12h14"/>,
    minus: <path d="M5 12h14"/>,
    arrowRight: <path d="M5 12h14M13 6l6 6-6 6"/>,
    arrowDown: <path d="M12 5v14M6 13l6 6 6-6"/>,
    arrowLeft: <path d="M19 12H5M11 6l-6 6 6 6"/>,
    check: <path d="M20 6 9 17l-5-5"/>,
    pin: <React.Fragment><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="2.6"/></React.Fragment>,
    clock: <React.Fragment><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></React.Fragment>,
    calendar: <React.Fragment><rect x="3" y="5" width="18" height="16" rx="1.5"/><path d="M3 9h18M8 3v4M16 3v4"/></React.Fragment>,
    scissors: <React.Fragment><circle cx="6" cy="6" r="2.6"/><circle cx="6" cy="18" r="2.6"/><path d="M8.1 7.9 20 18M8.1 16.1 20 6"/></React.Fragment>,
    sparkle: <path d="M12 3l1.7 5.3L19 10l-5.3 1.7L12 17l-1.7-5.3L5 10l5.3-1.7L12 3Z"/>,
    droplet: <path d="M12 3s6 5.7 6 10a6 6 0 0 1-12 0c0-4.3 6-10 6-10Z"/>,
    star: <path d="M12 3.3l2.6 5.3 5.8.85-4.2 4.1 1 5.8L12 16.6 6.8 19.3l1-5.8-4.2-4.1 5.8-.85L12 3.3Z"/>,
    quote: <path d="M9 7H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h2v3H4M19 7h-4a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h2v3h-3"/>,
    chevDown: <path d="M6 9l6 6 6-6"/>,
    chevRight: <path d="M9 6l6 6-6 6"/>,
    play: <path d="M7 4.5v15l13-7.5-13-7.5Z"/>,
    menu: <path d="M3 6h18M3 12h18M3 18h18"/>,
    bag: <React.Fragment><path d="M5 8h14l-1 12.5a1.5 1.5 0 0 1-1.5 1.4h-9A1.5 1.5 0 0 1 6 20.5L5 8Z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></React.Fragment>,
    heart: <path d="M12 20s-7-4.6-7-9.4A3.6 3.6 0 0 1 12 8a3.6 3.6 0 0 1 7 2.6C19 15.4 12 20 12 20Z"/>,
    leaf: <path d="M11 20A7 7 0 0 1 4 13c0-5 6-9 16-9 0 8-4 16-9 16a4.5 4.5 0 0 1-4.5-4.5C6.5 11 11 9 14 9"/>,
    arrowUpRight: <path d="M7 17 17 7M9 7h8v8"/>,
  };
  return <svg {...p}>{paths[name] || null}</svg>;
}

Object.assign(window, { Icon });

// ---- shared hooks ----
function useInView(opts) {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((es) => {
      es.forEach((e) => { if (e.isIntersecting) { setInView(true); io.unobserve(e.target); } });
    }, { threshold: 0.3, ...(opts || {}) });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, inView];
}

// count-up that animates once when scrolled into view; supports suffix like "k+" / "%"
function useCountUp(target, { duration = 1600, decimals = 0 } = {}) {
  const [ref, inView] = useInView();
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    if (!inView) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setVal(target); return; }
    let raf, start;
    const ease = (t) => 1 - Math.pow(1 - t, 3);
    const tick = (ts) => {
      if (!start) start = ts;
      const p = Math.min(1, (ts - start) / duration);
      setVal(target * ease(p));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, target]);
  const display = decimals > 0 ? val.toFixed(decimals) : Math.round(val).toLocaleString();
  return [ref, display];
}

function Stars({ n = 5, size = 15 }) {
  return (
    <span className="stars" aria-label={n + ' star rating'}>
      {Array.from({ length: n }).map((_, i) => <Icon key={i} name="star" size={size} stroke={1.2} style={{ fill: 'currentColor' }} />)}
    </span>
  );
}

Object.assign(window, { useInView, useCountUp, Stars });
