// ═══════════════════════════════════════════════════════════
// Leftshifted - Services Overview Page
// ═══════════════════════════════════════════════════════════

const ServicesPage = () => {
  const { useState, useEffect, useRef } = React;
  const heroRef = useRef(null);
  const megaWrapRef = useRef(null);
  const animLayerRefs = useRef({});
  const animIframeRefs = useRef({});
  const animRootRefs = useRef({});
  const progressFillRef = useRef(null);
  const progressFillVertRef = useRef(null);
  const pillRefs = useRef({});
  const pillVertRefs = useRef({});
  const [frameScale, setFrameScale] = useState(0.78);
  const [isMobile, setIsMobile] = useState(typeof window !== 'undefined' && window.innerWidth <= 900);
  useEffect(() => {
    const onR = () => setIsMobile(window.innerWidth <= 900);
    window.addEventListener('resize', onR);
    return () => window.removeEventListener('resize', onR);
  }, []);
  const [stopIdx, setStopIdx] = useState(0);
  const stopIdxRef = useRef(0);
  const [loaded, setLoaded] = useState({});
  const [showKeepScrolling, setShowKeepScrolling] = useState(false);
  const [activeSvc, setActiveSvc] = useState(0);
  const activeSvcRef = useRef(0);
  const [revealAll, setRevealAll] = useState(false);
  const dwellTimerRef = useRef(null);
  const barVertRef = useRef(null);
  const flagRef = useRef(null);
  const flagRefs = useRef({});
  const cardRefs = useRef({});
  const expertRefs = useRef({});
  const subServicesMap = {
    Strategy: ['Leadership', 'Data Strategy'],
    Data: ['Data Architecture', 'Data Engineering', 'Data Science', 'Data Analysis'],
    AI: ['MLOps', 'AIOps'],
    Cloud: ['Solution Architecture', 'Cloud Engineering', 'Security', 'DevOps'],
  };
  const [cycleIdx, setCycleIdx] = useState({ Strategy: 0, Data: 0, AI: 0, Cloud: 0 });
  const order = ['Strategy', 'Data', 'AI', 'Cloud'];
  const ANIM = {
    Strategy: { src: res('assets/animations/strategy-loop.html'), dur: 6 },
    Data: { src: res('assets/animations/data-loop.html'), dur: 6 },
    AI: { src: res('assets/animations/ai-loop.html'), dur: 6 },
    Cloud: { src: res('assets/animations/cloud-loop.html'), dur: 6 },
  };
  const segLen = 1 / order.length;
  const tw = 0.04;
  const smoothPRef = useRef(0);
  const stops = [0, 0.15, 0.375, 0.625, 1];
  const stopFill = [0, 0.25, 0.5, 0.75, 1];
  const copy = {
    Strategy: { color: 'var(--ls-lime)', dark: true, text: 'Get clear.' },
    Data: { color: 'var(--ls-midnight-navy)', dark: false, text: 'See our expertise.' },
    AI: { color: '#FF5A6E', dark: false, text: 'Enhance it.' },
    Cloud: { color: '#FFC845', dark: true, text: 'Scale it.' },
  };
  useEffect(() => {
    const timers = order.map(name => setInterval(() => {
      setCycleIdx(c => ({ ...c, [name]: (c[name] + 1) % subServicesMap[name].length }));
    }, 1800));
    return () => timers.forEach(clearInterval);
  }, []);
  useEffect(() => {
    const compute = () => {
      const pageWrapW = Math.min(1440, window.innerWidth) - 160;
      const target = Math.min(636, pageWrapW * 0.72);
      setFrameScale(Math.max(0.24, target / 816));
    };
    compute();
    window.addEventListener('resize', compute);
    return () => window.removeEventListener('resize', compute);
  }, []);
  useEffect(() => {
    const mega = megaWrapRef.current;
    if (!mega) return;
    let animId = null;
    let armed = true;
    let rearmTimer = null;
    const getPoints = () => {
      const wrapTop = mega.getBoundingClientRect().top + window.scrollY;
      const totalH = mega.offsetHeight - window.innerHeight;
      return stops.map(s => wrapTop + s * totalH);
    };
    const animateTo = (target) => {
      if (animId) cancelAnimationFrame(animId);
      const startY = window.scrollY;
      const dist = target - startY;
      const dur = 1300;
      const t0 = performance.now();
      const step = (now) => {
        const t = Math.min(1, (now - t0) / dur);
        const eased = 1 - Math.pow(1 - t, 3);
        window.scrollTo(0, startY + dist * eased);
        if (t < 1) animId = requestAnimationFrame(step);
        else animId = null;
      };
      animId = requestAnimationFrame(step);
    };
    const onWheel = (e) => {
      if (!armed) { e.preventDefault(); return; }
      const points = getPoints();
      const cur = window.scrollY;
      if (cur < points[0] || cur > points[points.length - 1]) return;
      if (Math.abs(e.deltaY) < 4) return;
      let idx = 0, best = Infinity;
      points.forEach((p, i) => { const d = Math.abs(p - cur); if (d < best) { best = d; idx = i; } });
      const dir = e.deltaY > 0 ? 1 : -1;
      if (idx === 0 && dir < 0) return;
      if (idx === points.length - 1 && dir > 0) return;
      e.preventDefault();
      armed = false;
      if (rearmTimer) clearTimeout(rearmTimer);
      rearmTimer = setTimeout(() => { armed = true; }, 1300);
      const nextIdx = Math.min(points.length - 1, Math.max(0, idx + dir));
      animateTo(points[nextIdx]);
    };
    if (window.innerWidth <= 900) return;
    window.addEventListener('wheel', onWheel, { passive: false });
    return () => { window.removeEventListener('wheel', onWheel); if (animId) cancelAnimationFrame(animId); if (rearmTimer) clearTimeout(rearmTimer); };
  }, []);
  useEffect(() => {
    let raf;
    const tick = () => {
      if (heroRef.current) {
        const rect = heroRef.current.getBoundingClientRect();
        const fade = Math.min(1, Math.max(0, 1 - (-rect.top) / (rect.height * 0.7)));
        heroRef.current.style.opacity = fade;
      }
      const mega = megaWrapRef.current;
      if (mega) {
        const rect = mega.getBoundingClientRect();
        const wrapTop = rect.top + window.scrollY;
        const totalH = mega.offsetHeight;
        const target = totalH > 0 ? Math.min(1, Math.max(0, (window.scrollY - wrapTop) / (totalH - window.innerHeight))) : 0;
        const cur = smoothPRef.current;
        const p = Math.abs(target - cur) < 0.0008 ? target : cur + (target - cur) * 0.18;
        smoothPRef.current = p;
        let stopIdx2 = 0, best = Infinity;
        stops.forEach((s, i) => { const d = Math.abs(s - target); if (d < best) { best = d; stopIdx2 = i; } });
        if (progressFillRef.current) progressFillRef.current.style.width = `${(1 - stopFill[stopIdx2]) * 100}%`;
        if (progressFillVertRef.current) progressFillVertRef.current.style.height = `${(1 - stopFill[stopIdx2]) * 100}%`;
        if (barVertRef.current) {
          const fullyIn = rect.top <= 0 ? 1 : 0;
          barVertRef.current.style.opacity = fullyIn;
          barVertRef.current.style.transition = 'opacity 300ms linear';
          const svc = order[Math.min(order.length - 1, Math.floor(target / segLen))];
          const barH = barVertRef.current.offsetHeight;
          const segH = barH / order.length;
          order.forEach((n, idx) => {
            const el = flagRefs.current[n];
            if (!el) return;
            el.style.top = `${idx * segH + segH / 2}px`;
            el.style.transform = 'translateY(-50%)';
            el.style.opacity = n === svc ? 1 : 0.4;
            const card = cardRefs.current[n];
            if (card) {
              card.style.top = `${idx * segH}px`;
              card.style.height = `${segH}px`;
              card.style.transform = 'none';
            }
            const expert = expertRefs.current[n];
            if (expert) {
              expert.style.top = `${idx * segH}px`;
              expert.style.height = `${segH}px`;
            }
          });
        }
        if (stopIdxRef.current !== stopIdx2) {
          stopIdxRef.current = stopIdx2;
          setStopIdx(stopIdx2);
          setShowKeepScrolling(false);
          if (dwellTimerRef.current) clearTimeout(dwellTimerRef.current);
          if (stopIdx2 === 0) {
            dwellTimerRef.current = setTimeout(() => setShowKeepScrolling(true), 1000);
          }
        }
        const activeIdx = Math.min(order.length - 1, Math.floor(p / segLen));
        activeSvcRef.current = activeIdx;
        setActiveSvc(a => a === activeIdx ? a : activeIdx);
        order.forEach((n, idx) => {
          const el = pillRefs.current[n];
          if (el) el.style.opacity = idx === activeIdx ? 1 : 0.4;
          const elv = pillVertRefs.current[n];
          if (elv) elv.style.opacity = idx === activeIdx ? 1 : 0.4;
        });
        order.forEach((name, i) => {
          const root = animRootRefs.current[name];
          const layer = animLayerRefs.current[name];
          if (!root || !layer) return;
          root.style.setProperty('box-shadow', 'none', 'important');
          const segStart = i * segLen;
          const segEnd = segStart + segLen;
          const segProg = Math.min(1, Math.max(0, (p - segStart) / segLen));
          root.dispatchEvent(new CustomEvent('data-om-seek-to-time-frame', {
            detail: { time: segProg * ANIM[name].dur, playing: false },
          }));
          let op = 1;
          if (i > 0) op = Math.min(op, Math.min(1, Math.max(0, (p - (segStart - tw)) / (2 * tw))));
          if (i < order.length - 1) op = Math.min(op, Math.min(1, Math.max(0, ((segEnd + tw) - p) / (2 * tw))));
          layer.style.opacity = op;
        });
      }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  const onAnimLoad = (name) => () => {
    let tries = 0;
    const tryFind = () => {
      tries++;
      try {
        const doc = animIframeRefs.current[name].contentDocument;
        const root = doc.querySelector('[data-om-exportable-video-with-duration-secs]');
        if (root) {
          animRootRefs.current[name] = root;
          root.style.setProperty('box-shadow', 'none', 'important');
          if (doc.head) {
            const style = doc.createElement('style');
            style.textContent = '[data-omelette-chrome]{display:none!important}html,body{overflow:hidden!important}';
            doc.head.appendChild(style);
          }
          root.dispatchEvent(new CustomEvent('data-om-seek-to-time-frame', { detail: { time: 0, playing: false } }));
          setLoaded(l => ({ ...l, [name]: true }));
          return;
        }
      } catch (e) {}
      if (tries < 40) setTimeout(tryFind, 150);
    };
    tryFind();
  };

  return (
    <PageShell current="/services">
      <div style={{ position: 'relative' }}>
      {/* ── HERO ───────────────────────────────── */}
      <div className="services-hero">
        <img src={res("assets/brand/services-topo-light.png")} alt="" style={{
          position: 'absolute', inset: 0, width: '100%', height: '100%',
          objectFit: 'cover', pointerEvents: 'none', opacity: 0.5,
        }} />
        <div className="page-wrap services-hero__grid" ref={heroRef} style={{ transition: 'opacity 80ms linear' }}>
          <div className="services-hero__content">
            <Eyebrow variant="dark">Services</Eyebrow>
            <h1 style={{
              font: 'var(--type-display-2)', letterSpacing: 'var(--tracking-display)',
              color: '#fff', marginTop: 24, maxWidth: 640,
            }}>
              We do one thing: <span style={{ color: 'var(--ls-lime)' }}>drive commercial value</span> from data and AI.
            </h1>
            <p style={{
              font: 'var(--type-body-lg)', color: 'rgba(255,255,255,.8)', marginTop: 24,
              maxWidth: 520,
            }}>
              We handle everything you need, end-to-end. Whatever your starting point.
            </p>
          </div>
          <div className="services-hero__graphic">
            <img src={res("assets/brand/services-hero-graphic.svg")} alt="" style={{ width: '100%', maxWidth: 620 }} />
          </div>
        </div>
      </div>
      </div>

      {/* ── SERVICE ANIMATIONS (crossfade) ────────────────── */}
      {isMobile ? (
        <Section className="m-svc-help" style={{ background: 'var(--ls-ultramarine-blue)', padding: '56px 0' }}>
          <Eyebrow variant="dark">How we help</Eyebrow>
          <div className="m-svc-help__list" style={{ display: 'flex', flexDirection: 'column', gap: 16, marginTop: 24 }}>
            {order.map(name => {
              const detail = {
                Strategy: "Typically we're brought in for senior technical oversight, to 'tell us what we've actually got' and to head-chef projects through to delivery and outcomes.",
                Data: "We stand up lean teams immediately, no ramping up. We're experts across the entire end-to-end chain of disciplines.",
                AI: "Apply the best AI models on the market and build capabilities others don't have.",
                Cloud: "Keep everything running reliably, securely and cost-effectively, to match your ambitions.",
              }[name];
              const onDark = copy[name].dark;
              return (
                <div key={name} style={{ background: copy[name].color, borderRadius: 'var(--radius-lg)', padding: 20, display: 'flex', flexDirection: 'column', gap: 12 }}>
                  <span style={{ alignSelf: 'flex-start', font: '600 11px/1 var(--font-mono)', letterSpacing: '.04em', textTransform: 'uppercase', padding: '7px 14px', borderRadius: 'var(--radius-pill)', background: onDark ? 'rgba(3,2,40,.12)' : 'rgba(255,255,255,.22)', color: onDark ? 'var(--ls-midnight-navy)' : '#fff' }}>{name}</span>
                  <p style={{ font: 'var(--type-body-sm)', color: onDark ? 'var(--ls-midnight-navy)' : '#fff' }}>{detail}</p>
                  {name === 'Data' && (
                    <a onClick={() => navigate('/data')} style={{ alignSelf: 'flex-start', display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer', font: '700 15px/1 var(--font-display)', color: onDark ? 'var(--ls-midnight-navy)' : '#fff', borderBottom: `1px solid ${onDark ? 'var(--ls-midnight-navy)' : '#fff'}`, paddingBottom: 2 }}>{copy[name].text}</a>
                  )}
                </div>
              );
            })}
          </div>
        </Section>
      ) : (
      <Section style={{ position: 'relative', background: 'var(--ls-ultramarine-blue)', padding: 0 }}>
        <div ref={megaWrapRef} style={{ minHeight: `${order.length * 450}vh`, position: 'relative' }}>
          <div style={{
            position: 'sticky', top: 0, height: '100vh', width: '100%',
          }}>
            <div ref={barVertRef} style={{
              position: 'absolute', top: 'calc(50% + 40px)', left: 0, transform: 'translateY(-50%)',
              zIndex: 2, height: '80vh',
              display: 'flex', alignItems: 'stretch', gap: 16,
            }}>
              <div style={{ position: 'relative', width: 90, height: '100%' }}>
                {order.map(name => (
                  <div key={name} ref={el => flagRefs.current[name] = el} style={{
                    position: 'absolute', right: 0,
                    background: copy[name].color, color: copy[name].dark ? 'var(--ls-midnight-navy)' : '#fff',
                    display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center',
                    padding: '6px 16px', borderRadius: 'var(--radius-pill)',
                    font: '600 12px/1 var(--font-mono)', letterSpacing: '.04em', textTransform: 'uppercase',
                    transition: 'opacity 300ms linear', whiteSpace: 'nowrap', width: 'max-content',
                  }}>{name}</div>
                ))}
              </div>
              <div style={{ position: 'relative', width: 5, height: '100%', borderRadius: 999, overflow: 'hidden', background: 'rgba(255,255,255,.25)' }}>
                <div style={{ position: 'absolute', inset: 0, background: `linear-gradient(to bottom, ${copy.Strategy.color} 0 25%, ${copy.Data.color} 25% 50%, ${copy.AI.color} 50% 75%, ${copy.Cloud.color} 75% 100%)` }}></div>
                <div ref={progressFillVertRef} style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: '100%', background: 'var(--ls-ultramarine-blue)', transition: 'height 700ms cubic-bezier(0.65,0,0.35,1)' }}></div>
              </div>
              <div style={{ position: 'relative', width: 440, height: '100%' }}>
                {order.map((name, idx) => {
                  const isActive = idx === activeSvc && !(name === 'Strategy' && stopIdx === 0) && loaded[name];
                  const reached = idx < activeSvc || isActive;
                  const detail = {
                    Strategy: "Typically we're brought in for senior technical oversight, to 'tell us what we've actually got' and to head-chef projects through to delivery and outcomes.",
                    Data: "We stand up lean teams immediately, no ramping up. We're experts across the entire end-to-end chain of disciplines.",
                    AI: "Apply the best AI models on the market and build capabilities others don't have.",
                    Cloud: "Keep everything running reliably, securely and cost-effectively, to match your ambitions.",
                  }[name];
                  return (
                    <div key={name} ref={el => cardRefs.current[name] = el} style={{
                      position: 'absolute', left: 0, right: 0,
                      color: '#fff', background: isActive ? copy[name].color : 'transparent',
                      padding: 16, display: 'flex', flexDirection: 'column', alignItems: 'flex-start', justifyContent: 'center', textAlign: 'left', overflow: 'hidden', gap: 12,
                      transition: 'background 400ms ease-out, opacity 200ms linear',
                      opacity: isActive ? 1 : (reached ? 0.4 : 0),
                    }}>
                      <p style={{ font: 'var(--type-caption)', color: isActive ? (copy[name].dark ? 'var(--ls-midnight-navy)' : '#fff') : 'rgba(255,255,255,.85)' }}>{detail}</p>
                      {name === 'Data' ? (
                        <a onClick={() => navigate('/data')} style={{
                          display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer',
                          font: '700 15px/1 var(--font-display)', color: isActive ? (copy[name].dark ? 'var(--ls-midnight-navy)' : '#fff') : '#fff',
                          borderBottom: `1px solid ${isActive ? (copy[name].dark ? 'var(--ls-midnight-navy)' : '#fff') : '#fff'}`, paddingBottom: 2,
                        }}>{copy[name].text}</a>
                      ) : (
                        <span style={{
                          display: 'inline-flex', alignItems: 'center', gap: 8,
                          font: '700 15px/1 var(--font-display)', color: isActive ? (copy[name].dark ? 'var(--ls-midnight-navy)' : '#fff') : '#fff',
                        }}>{copy[name].text}</span>
                      )}
                    </div>
                  );
                })}
              </div>
            </div>
            <div style={{
              position: 'absolute', top: '10vh', left: 0, right: 0, textAlign: 'center', zIndex: 2 }}>
              <Eyebrow variant="dark">How we help</Eyebrow>
            </div>
            {order.map((name, i) => (
              <div key={name} ref={el => animLayerRefs.current[name] = el} style={{
                position: 'absolute', top: 40, left: 0, right: 0, bottom: 0, display: 'flex', alignItems: 'center', justifyContent: 'flex-end',
                opacity: i === 0 ? 1 : 0, zIndex: 1,
              }}>
                <div style={{ width: 816 * frameScale, height: 860 * frameScale, overflow: 'hidden', position: 'relative' }}>
                  <iframe ref={el => { animIframeRefs.current[name] = el; }} onLoad={onAnimLoad(name)} src={ANIM[name].src} title={`${name} loop`} scrolling="no" loading="eager" style={{ position: 'absolute', top: 0, left: 0, width: 816, height: 860, border: 'none', display: 'block', transform: `scale(${frameScale})`, transformOrigin: 'top left', pointerEvents: 'none', background: 'transparent', opacity: loaded[name] ? 1 : 0, transition: 'opacity 250ms linear' }} />
                </div>
              </div>
            ))}
          </div>
        </div>
      </Section>
      )}
    </PageShell>
  );
};

Object.assign(window, { ServicesPage });
