/* Inner portfolio site — everything the hero zooms into.
   Editorial paper-white system: Almarai + Instrument Serif italic accents,
   GSAP ScrollTrigger for kinetic type, focus rows and the horizontal work rail. */
const { HeroScroll, useHeroScrub, ScrollRevealText, ArrowRight } = window;
const { useEffect } = React;

/* ---------------- Sticky inner-site chrome ---------------- */
function Chrome() {
  return (
    <header className="pf-chrome">
      <div className="pf-chrome-inner">
        <a className="pf-chrome-mark" href="#top"
          onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}>
          Mat H<span>*</span>
        </a>
        <span className="pf-chrome-mid">Portfolio — 2026</span>
        <nav>
          <a href="#about">About</a>
          <a href="#focus">Focus</a>
          <a href="#work">Work</a>
          <a href="#contact">Contact</a>
        </nav>
      </div>
    </header>
  );
}

/* ---------------- About ---------------- */
function AboutSection() {
  return (
    <section id="about" className="pf-section" data-screen-label="About">
      <div className="pf-grid">
        <div className="pf-side">
          <span className="pf-index">01</span>
          <span className="pf-label">About</span>
        </div>
        <div>
          <ScrollRevealText
            className="pf-statement"
            segments={[
              { text: 'I’m Mat Hanson — a self-confessed geek, ', className: '' },
              { text: 'let loose with AI.', className: 'pf-serif pf-bronze' },
              { text: ' I turn complex organisational problems into clearer operating models, useful systems and working prototypes.', className: '' }
            ]} />
          <p className="pf-about-body pf-fade">
            Where customer data, marketing technology, internal knowledge and delivery
            teams need to line up — that’s where I do my best work.
          </p>
        </div>
      </div>
    </section>
  );
}

/* ---------------- "I like to" kinetic list ---------------- */
const LIKE_LINES = [
  { text: 'tinker,', serif: false, off: 0 },
  { text: 'prototype,', serif: true, off: 2 },
  { text: 'solve problems,', serif: false, off: 1 },
  { text: 'automate,', serif: false, off: 3 },
  { text: 'challenge “how we’ve always done it”,', serif: true, off: 0 },
  { text: 'build,', serif: false, off: 2 },
  { text: 'find efficiencies,', serif: false, off: 1 },
  { text: 'make impactful comms,', serif: true, off: 2 },
  { text: 'embrace change.', serif: false, off: 0 }
];

function LikeToSection() {
  return (
    <section className="pf-liketo" data-screen-label="I like to">
      <div className="pf-liketo-head">
        <span className="pf-label">I like to —</span>
      </div>
      <div className="pf-lines">
        {LIKE_LINES.map((line, i) => (
          <div className="pf-line" data-off={line.off} key={i}>
            <span className={'pf-line-inner' + (line.serif ? ' pf-serif' : '')}>{line.text}</span>
          </div>
        ))}
      </div>
    </section>
  );
}

/* ---------------- Focus ---------------- */
const FOCUS_ROWS = [
  {
    num: '01', title: 'CRM transformation',
    desc: 'Clearer operating models for customer data, martech and the teams that run them.'
  },
  {
    num: '02', title: 'Customer engagement',
    desc: 'Journeys and lifecycle comms that actually land with the people they’re meant for.'
  },
  {
    num: '03', title: 'Automation',
    desc: 'Useful systems that take the manual work out of getting things done.'
  },
  {
    num: '04', title: 'Practical AI',
    desc: 'Working prototypes over slideware — AI applied to real organisational problems.'
  }
];

function FocusSection() {
  return (
    <section id="focus" className="pf-section" data-screen-label="Focus">
      <div className="pf-grid">
        <div className="pf-side">
          <span className="pf-index">02</span>
          <span className="pf-label">Focus</span>
        </div>
        <div className="pf-rows">
          {FOCUS_ROWS.map((row) => (
            <div className="pf-row" key={row.num}>
              <span className="pf-row-fill"></span>
              <span className="pf-row-num">{row.num}</span>
              <h3 className="pf-row-title">{row.title}</h3>
              <p className="pf-row-desc">{row.desc}</p>
              <span className="pf-row-arrow"><ArrowRight strokeWidth={1.5} /></span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Selected work (horizontal rail on desktop) ---------------- */
const WORK_PATTERNS = [
  {
    title: 'CRM leakage maps',
    note: '01 — make the joins visible',
    body: 'Where customer data, comms, ownership and delivery stop lining up — mapped clearly enough that a team can act.'
  },
  {
    title: 'Prototype workflows',
    note: '02 — prove the useful thing first',
    body: 'Small internal tools, automations and AI-assisted sequences that test the operating rhythm before platform weight arrives.'
  },
  {
    title: 'Operating rhythm briefs',
    note: '03 — fewer haunted spreadsheets',
    body: 'Decision-ready notes on who does what, when, from which signal, and what should happen next.'
  }
];

function WorkPatternCard({ item, lift }) {
  return (
    <div className="pf-card pf-work-pattern" data-lift={lift}>
      <div className="pf-pattern-face">
        <span className="pf-pattern-note">{item.note}</span>
        <h3>{item.title}</h3>
        <p>{item.body}</p>
      </div>
      <div className="pf-card-cap">
        <span className="pf-cap-title">{item.title}</span>
        <span className="pf-cap-note">{item.note}</span>
      </div>
    </div>
  );
}

function WorkSection() {
  return (
    <section id="work" className="pf-work" data-screen-label="Selected work">
      <div className="pf-work-pin">
        <div className="pf-work-head">
          <div className="pf-side">
            <span className="pf-index">03</span>
            <span className="pf-label">Selected work</span>
          </div>
          <span className="pf-label pf-work-hint">Keep scrolling →</span>
        </div>
        <div className="pf-work-track">
          <div className="pf-panel-intro">
            <h2 className="pf-panel-title">
              Things I’m<br /><span className="pf-serif pf-bronze">building towards.</span>
            </h2>
          </div>
          <WorkPatternCard item={WORK_PATTERNS[0]} lift="up" />
          <WorkPatternCard item={WORK_PATTERNS[1]} lift="down" />
          <WorkPatternCard item={WORK_PATTERNS[2]} lift="up" />
        </div>
      </div>
    </section>
  );
}

/* ---------------- Contact / footer ---------------- */
const MARQUEE_ITEMS = ['CRM Transformation', 'Customer Engagement', 'Automation', 'Practical AI'];

function MarqueeRun() {
  return (
    <span aria-hidden="true">
      {MARQUEE_ITEMS.map((item) => (
        <React.Fragment key={item}>
          <span>{item}</span>
          <span className="pf-star">*</span>
        </React.Fragment>
      ))}
    </span>
  );
}

function ContactSection() {
  return (
    <section id="contact" className="pf-contact" data-screen-label="Contact">
      <div className="pf-marquee">
        <div className="pf-marquee-inner">
          <MarqueeRun /><MarqueeRun />
        </div>
      </div>
      <div className="pf-contact-main">
        <span className="pf-label">04 — Inquiries</span>
        <h2 className="pf-contact-h pf-fade">
          Let’s make something <span className="pf-serif">useful.</span>
        </h2>
        <a className="pf-cta pf-fade" href="mailto:hello@hanmat.uk">
          Get in touch
          <span className="pf-cta-orb"><ArrowRight strokeWidth={2} /></span>
        </a>
      </div>
      <div className="pf-foot">
        <span>© 2026 Mat Hanson</span>
        <a href="#top" onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}>
          Back to the clouds ↑
        </a>
      </div>
      <span className="pf-giant" aria-hidden="true">MAT H*</span>
    </section>
  );
}

/* ---------------- GSAP motion ---------------- */
function initPortfolioMotion() {
  if (window.__pfMotionInit) return;
  window.__pfMotionInit = true;
  if (!window.gsap || !window.ScrollTrigger) return;
  gsap.registerPlugin(ScrollTrigger);
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

  // Some hosts freeze the rAF-driven gsap ticker while JS timers and scroll
  // events still run. Every entrance tween gets a timer fallback that commits
  // the final (visible) state if the tween hasn't finished on its own.
  const settleTween = (self) => {
    setTimeout(() => {
      const tw = self.animation;
      if (tw && tw.progress() < 1) tw.progress(1);
    }, 1500);
  };

  // Generic fade-up reveals
  gsap.utils.toArray('.pf-fade').forEach((el) => {
    gsap.from(el, {
      y: 36, opacity: 0, duration: 1, ease: 'expo.out',
      scrollTrigger: { trigger: el, start: 'top 90%', once: true, onEnter: settleTween }
    });
  });

  // Kinetic list — masked line reveals
  gsap.utils.toArray('.pf-line-inner').forEach((el) => {
    gsap.from(el, {
      yPercent: 118, duration: 1.05, ease: 'expo.out',
      scrollTrigger: { trigger: el.parentNode, start: 'top 94%', once: true, onEnter: settleTween }
    });
  });

  // Focus rows stagger in
  gsap.from('.pf-row', {
    y: 30, opacity: 0, duration: 0.85, ease: 'expo.out', stagger: 0.09,
    scrollTrigger: { trigger: '.pf-rows', start: 'top 85%', once: true, onEnter: settleTween }
  });

  // Horizontal work rail (desktop only)
  const mm = gsap.matchMedia();
  mm.add('(min-width: 900px)', () => {
    const track = document.querySelector('.pf-work-track');
    const pin = document.querySelector('.pf-work-pin');
    if (!track || !pin) return;
    const dist = () => Math.max(0, track.scrollWidth - window.innerWidth);
    const tween = gsap.to(track, {
      x: () => -dist(),
      ease: 'none',
      scrollTrigger: {
        trigger: pin, start: 'top top',
        end: () => '+=' + dist(),
        scrub: true, pin: true, anticipatePin: 1, invalidateOnRefresh: true
      }
    });
    return () => { if (tween.scrollTrigger) tween.scrollTrigger.kill(); tween.kill(); };
  });

  // Giant footer wordmark drifts up as the footer arrives
  gsap.fromTo('.pf-giant', { yPercent: 38 }, {
    yPercent: 0, ease: 'none',
    scrollTrigger: { trigger: '.pf-contact', start: 'top bottom', end: 'bottom bottom', scrub: true }
  });

  // Recompute after media/fonts settle
  window.addEventListener('load', () => { if (!window.__pfStaticMode) ScrollTrigger.refresh(true); });
  setTimeout(() => { if (!window.__pfStaticMode) ScrollTrigger.refresh(true); }, 800);

  // Watchdog: some hosts freeze requestAnimationFrame entirely (JS timers and
  // scroll events still run). GSAP's ticker — and with it ScrollTrigger's
  // refresh, callbacks, scrub and pinning — all hang off rAF, so keeping them
  // alive there is a losing battle. Instead, drop to a static fully-visible
  // layout: complete every entrance, kill all triggers (reverting the pinned
  // rail) and stack the work cards vertically via body.pf-no-pin.
  // Normal browsers never enter this branch.
  setTimeout(() => {
    if (gsap.ticker.frame > 0 || window.__pfStaticMode) return;
    window.__pfStaticMode = true;
    document.body.classList.add('pf-no-pin');
    ScrollTrigger.getAll().forEach((st) => st.kill(true));
    gsap.set(['.pf-fade', '.pf-row', '.pf-line-inner', '.pf-giant', '.pf-work-track'],
      { clearProps: 'all' });
  }, 500);
}

/* ---------------- App ---------------- */
function App() {
  useHeroScrub();
  useEffect(() => { initPortfolioMotion(); }, []);
  return (
    <React.Fragment>
      <HeroScroll />
      <div id="portfolio">
        <Chrome />
        <AboutSection />
        <LikeToSection />
        <FocusSection />
        <WorkSection />
        <ContactSection />
      </div>

      {/* White "screen-on" beat that the portfolio emerges from (fixed, JS-driven opacity) */}
      <div id="boot-flash" style={{
        position: 'fixed', inset: 0, background: '#ECEBE6', opacity: 0,
        pointerEvents: 'none', zIndex: 60
      }}></div>
    </React.Fragment>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
