// SiteChrome.jsx — persistent shell: nav + footer + scroll reveal helpers
const { useState: useStateChrome, useEffect: useEffectChrome } = React;

function useIsMobile() {
  const [mob, setMob] = useStateChrome(() => window.innerWidth < 780);
  useEffectChrome(() => {
    const h = () => setMob(window.innerWidth < 780);
    window.addEventListener('resize', h);
    return () => window.removeEventListener('resize', h);
  }, []);
  return mob;
}
window.useIsMobile = useIsMobile;

let _alpMarkCount = 0;

function MonogramMark({ size = 28 }) {
  const uid = React.useRef(null);
  if (uid.current === null) uid.current = ++_alpMarkCount;
  const mid = `alpm${uid.current}`;
  const sid = `alps${uid.current}`;

  return (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" width={size} height={size} aria-hidden="true" style={{ display: 'block', flexShrink: 0 }}>
      <defs>
        <linearGradient id={mid} x1="0" y1="0" x2="0.3" y2="1">
          <stop offset="0%"   stopColor="#6e7a8e"/>
          <stop offset="22%"  stopColor="#adb6c4"/>
          <stop offset="44%"  stopColor="#d6dbe5"/>
          <stop offset="52%"  stopColor="#f2f4f8"/>
          <stop offset="68%"  stopColor="#b0b9c8"/>
          <stop offset="100%" stopColor="#6a7484"/>
        </linearGradient>
        <linearGradient id={sid} gradientUnits="userSpaceOnUse" x1="-60" y1="0" x2="0" y2="0">
          <stop offset="0%"   stopColor="rgba(255,255,255,0)"/>
          <stop offset="50%"  stopColor="rgba(255,255,255,0.62)"/>
          <stop offset="100%" stopColor="rgba(255,255,255,0)"/>
          <animate attributeName="x1" values="-60;120;120" keyTimes="0;0.44;1" dur="4s" repeatCount="indefinite"/>
          <animate attributeName="x2" values="0;180;180"   keyTimes="0;0.44;1" dur="4s" repeatCount="indefinite"/>
        </linearGradient>
      </defs>
      <path d="M 30 96 L 60 24 L 90 96" fill="none" stroke={`url(#${mid})`} strokeWidth="9" strokeLinecap="square" strokeLinejoin="miter"/>
      <path d="M 30 96 L 60 24 L 90 96" fill="none" stroke={`url(#${sid})`} strokeWidth="9" strokeLinecap="square" strokeLinejoin="miter"/>
      <rect x="36" y="104" width="48" height="6" fill="var(--alp-jade)"/>
      <rect x="36" y="104" width="48" height="6" fill={`url(#${sid})`} opacity="0.45"/>
    </svg>
  );
}
window.MonogramMark = MonogramMark;

function useScrollReveal() {
  useEffectChrome(() => {
    const seen = new WeakSet();

    const revealBatch = () => {
      const fresh = [];
      document.querySelectorAll('[data-reveal]').forEach(el => {
        if (seen.has(el)) return;
        seen.add(el);
        fresh.push(el);
      });
      if (!fresh.length) return;
      fresh.forEach(el => el.classList.add('reveal-prime'));
      void document.body.offsetHeight; // commit opacity:0 before starting transitions
      requestAnimationFrame(() => fresh.forEach(el => el.classList.remove('reveal-prime')));
    };

    revealBatch();

    // Re-run when new page content is added (SPA navigation)
    let rafId = null;
    const mo = new MutationObserver(() => {
      if (rafId) cancelAnimationFrame(rafId);
      rafId = requestAnimationFrame(() => { rafId = null; revealBatch(); });
    });
    mo.observe(document.body, { childList: true, subtree: true });

    return () => { mo.disconnect(); if (rafId) cancelAnimationFrame(rafId); };
  }, []);
}

function Reveal({ children, delay = 0, as: Tag = 'div', style = {}, ...rest }) {
  return (
    <Tag data-reveal style={{ ...style, transitionDelay: `${delay}ms` }} {...rest}>
      {children}
    </Tag>
  );
}

function SiteNav({ page, setPage, theme, setTheme }) {
  const [open, setOpen] = useStateChrome(false);
  const links = [
    { k: 'home', label: 'Home' },
    { k: 'services', label: 'Services' },
    { k: 'pricing', label: 'Pricing' },
    { k: 'about', label: 'About' },
  ];
  const go = (k) => { setPage(k); setOpen(false); window.scrollTo({ top: 0, behavior: 'instant' }); };
  return (
    <nav className="site-nav">
      <button className="site-mark" onClick={() => go('home')}>
        <MonogramMark size={30} />
        <span className="mark-a">ALP</span>
        <span className="mark-bar" />
        <span className="mark-b">DIGITAL</span>
      </button>
      <div className={`site-links ${open ? 'is-open' : ''}`}>
        {links.map(l => (
          <button key={l.k} onClick={() => go(l.k)}
            className={`site-link ${page === l.k ? 'is-active' : ''}`}>
            {l.label}
          </button>
        ))}
      </div>
      <div className="site-tools">
        <button className="theme-toggle" onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} title="Toggle theme">
          {theme === 'dark' ? '☾' : '☀'}
        </button>
        <button className="site-cta" onClick={() => go('contact')}>
          Get in touch <span>→</span>
        </button>
        <button className="site-burger" onClick={() => setOpen(o => !o)} aria-label="Menu">
          <span /><span /><span />
        </button>
      </div>
    </nav>
  );
}

function SiteFooter({ setPage }) {
  return (
    <footer className="site-footer">
      <div className="foot-top">
        <div className="foot-col">
          <div className="foot-mark">
            <MonogramMark size={28} />
            <span className="mark-a">ALP</span><span className="mark-bar" /><span className="mark-b">DIGITAL</span>
          </div>
          <p className="foot-pitch">Websites, photography, and ongoing care for local businesses across South Wales.</p>
        </div>
        <div className="foot-col">
          <div className="foot-head">Pages</div>
          {['home','services','pricing','about','contact'].map(k => (
            <button key={k} className="foot-link" onClick={() => { setPage(k); window.scrollTo({top:0}); }}>{k[0].toUpperCase()+k.slice(1)}</button>
          ))}
        </div>
        <div className="foot-col">
          <div className="foot-head">Contact</div>
          <div className="foot-kv"><span>Email</span><span>andrew@alpdigital.co.uk</span></div>
          <div className="foot-kv"><span>Mobile</span><span>07786 604 347</span></div>
          <div className="foot-kv"><span>Based</span><span>Hendy, South Wales</span></div>
        </div>
        <div className="foot-col">
          <div className="foot-head">Follow</div>
          <a className="foot-link" href="https://instagram.com/alpdigitalsw" target="_blank" rel="noopener noreferrer">Instagram · @alpdigitalsw</a>
          <a className="foot-link" href="mailto:andrew@alpdigital.co.uk">Email</a>
        </div>
      </div>
      <div className="foot-bot">
        <div>© 2026 ALP Media · Hendy, South Wales</div>
        <div>Part of the ALP Media group — Photography · Digital · Marketplace</div>
      </div>
    </footer>
  );
}

// ────────── CARD TILT ──────────
function useCardTilt() {
  useEffectChrome(() => {
    const styleEl = document.createElement('style');
    styleEl.textContent = '.card.hover { will-change: transform; transition: opacity 700ms var(--ease-out), transform 400ms cubic-bezier(0.23,1,0.32,1), border-color 200ms var(--ease-out); }';
    document.head.appendChild(styleEl);

    let active = null;

    const onMove = (e) => {
      const card = e.target.closest('.card.hover');
      if (active && active !== card) {
        active.style.transform = '';
        active = null;
      }
      if (!card) return;
      active = card;
      const r = card.getBoundingClientRect();
      const dx = (e.clientX - (r.left + r.width  / 2)) / (r.width  / 2);
      const dy = (e.clientY - (r.top  + r.height / 2)) / (r.height / 2);
      card.style.transform = `perspective(700px) rotateY(${dx * 7}deg) rotateX(${-dy * 7}deg) translateZ(8px)`;
    };

    document.addEventListener('mousemove', onMove);
    return () => {
      document.removeEventListener('mousemove', onMove);
      styleEl.remove();
    };
  }, []);
}

// ────────── WIRE SHAPES ──────────
const _phi = (1 + Math.sqrt(5)) / 2;
const WIRE_SHAPES = {
  octahedron: {
    v: [[0,1,0],[0,-1,0],[1,0,0],[-1,0,0],[0,0,1],[0,0,-1]],
    e: [[0,2],[0,3],[0,4],[0,5],[1,2],[1,3],[1,4],[1,5],[2,4],[4,3],[3,5],[5,2]]
  },
  icosahedron: {
    v: [[0,1,_phi],[0,-1,_phi],[0,1,-_phi],[0,-1,-_phi],
        [1,_phi,0],[-1,_phi,0],[1,-_phi,0],[-1,-_phi,0],
        [_phi,0,1],[-_phi,0,1],[_phi,0,-1],[-_phi,0,-1]],
    e: [[0,1],[0,4],[0,5],[0,8],[0,9],
        [1,6],[1,7],[1,8],[1,9],
        [2,3],[2,4],[2,5],[2,10],[2,11],
        [3,6],[3,7],[3,10],[3,11],
        [4,5],[4,8],[4,10],
        [5,9],[5,11],
        [6,7],[6,8],[6,10],
        [7,9],[7,11],
        [8,10],[9,11]]
  },
  cube: {
    v: [[-1,-1,-1],[1,-1,-1],[1,1,-1],[-1,1,-1],[-1,-1,1],[1,-1,1],[1,1,1],[-1,1,1]],
    e: [[0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7]]
  }
};

function WireShape({ shape='octahedron', size=120, speedY=0.5, speedX=0.2,
                     strokeWidth=1, opacity=0.15, initY=0, initX=0.4 }) {
  const svgRef = React.useRef(null);
  const rafRef = React.useRef(null);
  const ang    = React.useRef({ y: initY, x: initX });

  React.useEffect(() => {
    const svg = svgRef.current;
    if (!svg) return;
    const { v, e } = WIRE_SHAPES[shape];
    const half = size / 2;

    const project = ([x, y, z]) => {
      const s = half * 0.52 / (4 + z * 0.22);
      return [x * s + half, y * s + half];
    };
    const rotY = (pts, a) => pts.map(([x,y,z]) => [ x*Math.cos(a)+z*Math.sin(a), y, -x*Math.sin(a)+z*Math.cos(a)]);
    const rotX = (pts, a) => pts.map(([x,y,z]) => [ x, y*Math.cos(a)-z*Math.sin(a),  y*Math.sin(a)+z*Math.cos(a)]);

    const lines = svg.querySelectorAll('line');
    const tick = () => {
      ang.current.y += speedY * 0.004;
      ang.current.x += speedX * 0.004;
      const proj = rotX(rotY(v, ang.current.y), ang.current.x).map(project);
      e.forEach(([a, b], i) => {
        lines[i].setAttribute('x1', proj[a][0].toFixed(1));
        lines[i].setAttribute('y1', proj[a][1].toFixed(1));
        lines[i].setAttribute('x2', proj[b][0].toFixed(1));
        lines[i].setAttribute('y2', proj[b][1].toFixed(1));
      });
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [shape, size, speedY, speedX]);

  const { e } = WIRE_SHAPES[shape];
  return (
    <svg ref={svgRef} width={size} height={size} style={{ overflow:'visible', display:'block' }} aria-hidden="true">
      {e.map((_, i) => (
        <line key={i} stroke="var(--alp-jade)" strokeWidth={strokeWidth} opacity={opacity} x1="0" y1="0" x2="0" y2="0"/>
      ))}
    </svg>
  );
}

function WireBackground() {
  const mob = useIsMobile();
  if (mob) return null;
  return (
    <div style={{ position:'fixed', inset:0, pointerEvents:'none', overflow:'hidden', zIndex:0 }} aria-hidden="true">
      <div style={{ position:'absolute', top:'7%',  right:'3%'   }}>
        <WireShape shape="octahedron"  size={150} speedY={0.50} speedX={0.18} opacity={0.09} initY={0.8} initX={0.3}/>
      </div>
      <div style={{ position:'absolute', top:'52%', left:'1.5%'  }}>
        <WireShape shape="cube"        size={100} speedY={0.30} speedX={0.10} opacity={0.07} initY={1.3} initX={0.6}/>
      </div>
      <div style={{ position:'absolute', top:'74%', right:'6%'   }}>
        <WireShape shape="octahedron"  size={85}  speedY={0.65} speedX={0.25} opacity={0.06} initY={2.2} initX={0.4}/>
      </div>
    </div>
  );
}

window.SiteNav = SiteNav;
window.SiteFooter = SiteFooter;
window.useScrollReveal = useScrollReveal;
window.useCardTilt = useCardTilt;
window.Reveal = Reveal;
window.WireShape = WireShape;
window.WireBackground = WireBackground;
