/* ============================================================
   lib.jsx — shared primitives for the HelloCharge site
   ============================================================ */
const { useState, useEffect, useRef, useCallback, createContext, useContext } = React;

/* ---------------- Icons (lucide-style, stroke=currentColor) ---------------- */
const ICONS = {
  bolt: 'M13 2 3 14h9l-1 8 10-12h-9l1-8z',
  pin: 'M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z|dot:12,10,3',
  battery: 'M3 8h13a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2z M21 11v2 M11 9l-2 3h3l-2 3',
  store: 'M2 7 3.5 3.5A2 2 0 0 1 5.3 2.5h13.4a2 2 0 0 1 1.8 1L22 7 M2 7h20 M4 7v12a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V7',
  mail: 'M2 6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2z M2 7l10 6 10-6',
  phone: '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.6A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .4 1.9.7 2.8a2 2 0 0 1-.5 2.1L8.1 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.6 2.8.7a2 2 0 0 1 1.7 2z',
  check: 'm20 6-11 11-5-5',
  plus: 'M12 5v14 M5 12h14',
  arrow: 'M5 12h14 M13 6l6 6-6 6',
  arrowUR: 'M7 17 17 7 M8 7h9v9',
  apple: 'M16.4 12.9c0-2.3 1.9-3.4 2-3.4-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.9-3.5.9s-1.8-.9-3-.8c-1.5 0-2.9.9-3.7 2.3-1.6 2.7-.4 6.8 1.1 9 .7 1.1 1.6 2.3 2.8 2.3 1.1 0 1.5-.7 2.9-.7s1.7.7 2.9.7 2-1.1 2.7-2.1c.9-1.2 1.2-2.4 1.2-2.5 0 0-2.3-.9-2.3-3.6zM14.2 5.8c.6-.8 1-1.8.9-2.8-.9 0-2 .6-2.6 1.3-.6.7-1.1 1.7-1 2.7 1 .1 2-.5 2.7-1.2z',
  google: 'M3 3.5 13.5 12 3 20.5z|fill',
  sun: 'M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10z M12 1v2 M12 21v2 M4.2 4.2l1.4 1.4 M18.4 18.4l1.4 1.4 M1 12h2 M21 12h2 M4.2 19.8l1.4-1.4 M18.4 5.6l1.4-1.4',
  moon: 'M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z',
  building: 'M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18 M2 22h20 M10 6h.01 M14 6h.01 M10 10h.01 M14 10h.01 M10 14h.01 M14 14h.01',
  user: 'M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2|circ:12,7,4',
  qr: 'M5 5h4v4H5z M15 5h4v4h-4z M5 15h4v4H5z M14 14h2v2h-2z M18 14h1v1h-1z M14 18h1v1h-1z M18 18h1v1h-1z',
  clock: 'M12 7v5l3 2|circ:12,12,9',
  shield: 'M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z M9 12l2 2 4-4',
  refresh: 'M3 12a9 9 0 0 1 15-6.7L21 8 M21 3v5h-5 M21 12a9 9 0 0 1-15 6.7L3 16 M3 21v-5h5',
  wrench: 'M14.7 6.3a4 4 0 0 0-5.2 5.2L3 18v3h3l6.5-6.5a4 4 0 0 0 5.2-5.2l-2.6 2.6-2.2-.4-.4-2.2 2.6-2.6z',
  headset: 'M3 14v-2a9 9 0 0 1 18 0v2 M21 16a2 2 0 0 1-2 2h-1v-6h1a2 2 0 0 1 2 2zM3 16a2 2 0 0 0 2 2h1v-6H5a2 2 0 0 0-2 2z M21 18a4 4 0 0 1-4 4h-3',
  cable: 'M4 9V6a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v3 M5 9h6 M8 9v5a4 4 0 0 0 8 0v-1 M16 13V9 M20 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM16 9V7',
  card: 'M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2z M2 10h20 M6 15h4',
  map: 'M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z M9 4v14 M15 6v14',
  star: 'M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.9 6.8 19.2l1-5.8L3.5 9.2l5.9-.9z|fill',
  spark: 'M12 3v4 M12 17v4 M3 12h4 M17 12h4 M6 6l2.5 2.5 M15.5 15.5 18 18 M18 6l-2.5 2.5 M8.5 15.5 6 18',
  leaf: 'M11 20A7 7 0 0 1 4 13c0-6 6-9 14-9 0 8-3 14-9 14 M4 21c1-3 3-6 7-8',
  globe: 'M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z M3 12h18 M12 3c2.5 2.7 3.5 5.8 3.5 9s-1 6.3-3.5 9c-2.5-2.7-3.5-5.8-3.5-9S9.5 5.7 12 3z',
  layers: 'M12 2 2 7l10 5 10-5-10-5z M2 17l10 5 10-5 M2 12l10 5 10-5',
  trend: 'M3 17l6-6 4 4 8-8 M21 7v4h-4',
  award: 'M8 15 7 22l5-3 5 3-1-7|circ:12,8,6',
  scan: 'M3 7V5a2 2 0 0 1 2-2h2 M17 3h2a2 2 0 0 1 2 2v2 M21 17v2a2 2 0 0 1-2 2h-2 M7 21H5a2 2 0 0 1-2-2v-2 M7 12h10',
  download: 'M12 3v12 M7 11l5 4 5-4 M5 21h14',
  party: 'M5.8 11.3 2 22l10.7-3.8 M4 3h.01 M22 8h.01 M15 2h.01 M22 20h.01 M22 2 11 13 M11 13c1.5 1.5 3 2 3 2M14 7s1 1 1 3M19 11s1 0 2 1',
  utensils: 'M3 2v7a3 3 0 0 0 6 0V2 M6 2v20 M16 2c-1.7 0-3 2-3 5s1 5 3 5v10',
  monitor: 'M3 4h18a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z M8 20h8 M12 16v4',
  box: 'M12 2 3 7v10l9 5 9-5V7l-9-5z M3 7l9 5 9-5 M12 12v10',
  weight: 'M6.5 8h11l1.7 11a1 1 0 0 1-1 1.2H5.8a1 1 0 0 1-1-1.2L6.5 8z M9 8a3 3 0 1 1 6 0',
  wifi: 'M2.5 9.5a14 14 0 0 1 19 0 M6 13a9 9 0 0 1 12 0 M9.5 16.5a4 4 0 0 1 5 0 M12 20h.01',
  droplet: 'M12 3c3.5 4.5 6 8 6 11a6 6 0 0 1-12 0c0-3 2.5-6.5 6-11z',
  thermometer: 'M10 13.5V5a2 2 0 1 1 4 0v8.5a4 4 0 1 1-4 0z|dot:12,17,1.4',
  gauge: 'M12 14l3.5-3.5 M20.5 14a8.5 8.5 0 1 0-17 0|dot:12,14,1.4',
  close: 'M6 6l12 12 M18 6 6 18',
};
function Icon({ name, size = 22, stroke = 2, style, className }) {
  const spec = ICONS[name] || '';
  const segs = spec.split('|');
  const fill = segs.includes('fill');
  const parts = [];
  segs.forEach((s, i) => {
    if (s === 'fill') return;
    if (s.startsWith('dot:')) { const [x,y,r] = s.slice(4).split(','); parts.push(React.createElement('circle',{key:i,cx:x,cy:y,r:r,fill:'currentColor',stroke:'none'})); }
    else if (s.startsWith('circ:')) { const [x,y,r] = s.slice(5).split(','); parts.push(React.createElement('circle',{key:i,cx:x,cy:y,r:r})); }
    else parts.push(React.createElement('path',{key:i,d:s}));
  });
  return React.createElement('svg', {
    className, viewBox: '0 0 24 24', width: size, height: size,
    fill: fill ? 'currentColor' : 'none', stroke: fill ? 'none' : 'currentColor',
    strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round', style,
  }, parts);
}

/* ---------------- Logo ---------------- */
function Logo({ onClick }) {
  return React.createElement('div', { className: 'logo', onClick, style: { cursor: 'pointer' } },
    React.createElement('img', { src: 'assets/logo-mark.png', alt: 'HelloCharge' }),
    React.createElement('span', { className: 'word' }, 'Hello', React.createElement('b', null, 'Charge'))
  );
}

/* ---------------- Scroll reveal ---------------- */
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const items = el.matches('.reveal') ? [el] : Array.from(el.querySelectorAll('.reveal'));
    if (el.matches('.reveal')) items.push(el);
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } });
    }, { threshold: 0.14, rootMargin: '0px 0px -8% 0px' });
    items.forEach((i) => io.observe(i));
    return () => io.disconnect();
  });
  return ref;
}
// Section wrapper that observes its own .reveal children
function Reveal({ children, className = '', as = 'div', delay = '', style }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(([e]) => { if (e.isIntersecting) { el.classList.add('in'); io.disconnect(); } }, { threshold: 0.16, rootMargin: '0px 0px -7% 0px' });
    io.observe(el); return () => io.disconnect();
  }, []);
  return React.createElement(as, { ref, className: `reveal ${delay} ${className}`, style }, children);
}

/* ---------------- Animated counter ---------------- */
function Counter({ to, suffix = '', prefix = '', dur = 1600, decimals = 0 }) {
  const ref = useRef(null);
  const [val, setVal] = useState(0);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduced) { setVal(to); return; }
    let raf, started = false;
    // Fallback: if the animation never progresses (throttled timeline), snap to final.
    const fallback = setTimeout(() => { setVal((v) => (v < to ? to : v)); }, 2600);
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting && !started) {
        started = true;
        const t0 = performance.now();
        const tick = (t) => {
          const p = Math.min(1, (t - t0) / dur);
          const eased = 1 - Math.pow(1 - p, 3);
          setVal(to * eased);
          if (p < 1) raf = requestAnimationFrame(tick);
        };
        raf = requestAnimationFrame(tick);
        io.disconnect();
      }
    }, { threshold: 0.4 });
    io.observe(el);
    return () => { io.disconnect(); cancelAnimationFrame(raf); clearTimeout(fallback); };
  }, [to]);
  const display = decimals ? val.toFixed(decimals) : Math.round(val).toLocaleString('en-US');
  return React.createElement('span', { ref }, prefix, display, suffix);
}

/* ---------------- Word rotator ---------------- */
function WordRotator({ words, interval = 2200 }) {
  const [i, setI] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setI((p) => (p + 1) % words.length), interval);
    return () => clearInterval(t);
  }, []);
  // measure widest
  return React.createElement('span', { className: 'rotor' },
    words.map((w, idx) => React.createElement('span', {
      key: idx,
      style: { visibility: idx === i ? 'visible' : 'hidden', position: idx === i ? 'static' : 'absolute' },
      className: idx === i ? 'in' : '',
    }, w))
  );
}

/* ---------------- Spotlight hover ---------------- */
function useSpotlight() {
  const onMove = useCallback((e) => {
    const r = e.currentTarget.getBoundingClientRect();
    e.currentTarget.style.setProperty('--mx', `${e.clientX - r.left}px`);
    e.currentTarget.style.setProperty('--my', `${e.clientY - r.top}px`);
  }, []);
  return onMove;
}

/* ---------------- Theme + Mode context ---------------- */
const AppCtx = createContext(null);
function useApp() { return useContext(AppCtx); }

const IOS_APP_URL = 'https://apps.apple.com/pl/app/hellocharge/id6742231208';
function AppStoreButtons({ compact }) {
  if (compact) {
    return React.createElement('div', { className: 'dl-mini' },
      React.createElement('span', null, 'Download'),
      React.createElement('a', { href: IOS_APP_URL, target: '_blank', rel: 'noopener noreferrer', 'aria-label': 'App Store' }, React.createElement(Icon, { name: 'apple', size: 17 })),
      React.createElement('a', { href: '#', 'aria-label': 'Google Play' }, React.createElement(Icon, { name: 'google', size: 16 }))
    );
  }
  return React.createElement('div', { className: 'row', style: { gap: '12px' } },
    React.createElement('a', { href: IOS_APP_URL, target: '_blank', rel: 'noopener noreferrer', className: 'store-badge' },
      React.createElement(Icon, { name: 'apple', size: 22 }),
      React.createElement('span', null, React.createElement('small', null, 'Download on the'), React.createElement('strong', null, 'App Store'))),
    React.createElement('a', { href: '#', className: 'store-badge' },
      React.createElement(Icon, { name: 'google', size: 20 }),
      React.createElement('span', null, React.createElement('small', null, 'Get it on'), React.createElement('strong', null, 'Google Play')))
  );
}

Object.assign(window, { Icon, Logo, Reveal, useReveal, Counter, WordRotator, useSpotlight, AppCtx, useApp, AppStoreButtons,
  React_hooks: { useState, useEffect, useRef, useCallback } });
