/* Prisma landing page — scroll-scrubbed video hero + About + Features. */
const {
  WordsPullUp, WordsPullUpMultiStyle, ScrollRevealText,
  CardReveal, FadeUp, ArrowRight, Check
} = window;
const { useEffect } = React;

const HERO_VIDEO = 'assets/clouds-laptop-scrub.mp4?v=2';
const IDLE_HERO_VIDEO = 'assets/hero-idle-loop.mp4';
const IDLE_LOOP_END = 4;             // before scroll, loop the opening four seconds of the idle clip
const HERO_DURATION = 8;            // seconds
const SCRUB_END = 7.55;             // end the scrub a touch early...
const WHITE_START = 0.82;           // ...and dissolve the last stretch to pure white
const WHITE_END = 0.98;
const SCREEN_WHITE = '#ECEBE6';     // warm white of the laptop screen end-frame
const CANVAS_VIDEO = 'https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260406_133058_0504132a-0cf3-4450-a370-8ea3b05c95d4.mp4';

const ICON_STORYBOARD = 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260405_171918_4a5edc79-d78f-4637-ac8b-53c43c220606.png&w=1280&q=85';
const ICON_CRITIQUES = 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260405_171741_ed9845ab-f5b2-4018-8ce7-07cc01823522.png&w=1280&q=85';
const ICON_CAPSULE = 'https://images.higgs.ai/?default=1&output=webp&url=https%3A%2F%2Fd8j0ntlcm91z4.cloudfront.net%2Fuser_38xzZboKViGWJOttwIXH07lWA1P%2Fhf_20260405_171809_f56666dc-c099-4778-ad82-9ad4f209567b.png&w=1280&q=85';

const CREAM = '#E1E0CC';
const HERO_BLACK = '#0D0F12';
const HERO_GRAPHITE = '#25292A';
const HERO_UMBER = '#6D553F';
const HERO_COPPER = '#A07656';
const HERO_PEACH = '#E5B88E';
const ABOUT_INK = '#18140F';     // heading ink on the white screen
const ABOUT_BODY = '#362B22';    // body ink on the white screen
const ABOUT_MUTED = '#7B6958';   // muted label on the white screen
const NAV_ITEMS = ['About', 'Work', 'Sessions', 'Inquiries'];
const navHref = (item) => ({
  About: '#profile-section',
  Work: '#capabilities',
  Sessions: '#experiments',
  Inquiries: '#inquiries'
}[item] || '#');


function SiteNav() {
  return (
    <nav id="site-nav" className="fixed top-0 left-1/2 -translate-x-1/2 z-[80] bg-black rounded-b-2xl md:rounded-b-3xl px-4 py-2 md:px-8 shadow-[0_10px_30px_rgba(0,0,0,0.24)]">
      <ul className="flex items-center gap-3 sm:gap-6 md:gap-12 lg:gap-14">
        {NAV_ITEMS.map((item) => (
          <li key={item}>
            <a href={navHref(item)} className="nav-link text-[10px] sm:text-xs md:text-sm whitespace-nowrap">{item}</a>
          </li>
        ))}
      </ul>
    </nav>
  );
}

/* ---------------- HERO (scroll-scrubbed video) ---------------- */
function HeroScroll() {
  return (
    <div id="hero-track" style={{ position: 'relative', height: '420vh', background: '#000' }}>
      <div id="hero-sticky" style={{ position: 'sticky', top: 0, height: '100lvh', minHeight: '100dvh', overflow: 'hidden', background: '#000' }}>
        <video id="hero-idle-video" className="hero-video-layer"
          autoPlay muted playsInline preload="auto" tabIndex={-1} aria-hidden="true"
          src={IDLE_HERO_VIDEO}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', opacity: 1, zIndex: 0, willChange: 'opacity' }} />
        <video id="hero-video" className="hero-video-layer"
          muted playsInline preload="auto" tabIndex={-1} aria-hidden="true"
          src={HERO_VIDEO}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', opacity: 0, zIndex: 1, willChange: 'opacity' }} />

        {/* Final-stretch dissolve to a whole-white screen */}
        <div id="hero-white" style={{ position: 'absolute', inset: 0, background: SCREEN_WHITE, opacity: 0, pointerEvents: 'none', zIndex: 2 }} />

        {/* About copy appears inside the final laptop-screen phase. Designed as a
            screen surface rather than loose type, so the handoff feels intentional. */}
        <div id="hero-about-preview" aria-hidden="true"
          className="absolute inset-0 flex items-center justify-center px-5 sm:px-7 md:px-10"
          style={{ color: ABOUT_INK, opacity: 0, pointerEvents: 'none', zIndex: 6, transform: 'translateY(64px)', willChange: 'opacity, transform' }}>
          <div className="relative w-full max-w-5xl overflow-hidden rounded-[26px] md:rounded-[34px] border border-[#D8D2BF]/80 bg-[#ECEBE6]/[0.92] shadow-[0_30px_120px_rgba(26,24,18,0.20)] backdrop-blur-sm">
            <div className="pointer-events-none absolute inset-0 profile-paper-grain opacity-[0.38] mix-blend-multiply" />
            <div className="pointer-events-none absolute -right-20 -top-24 h-64 w-64 rounded-full bg-[#E5B88E]/25 blur-3xl" />
            <div className="relative flex items-center justify-between border-b border-[#D8D2BF]/70 px-5 py-3 md:px-8 md:py-4">
              <div className="flex items-center gap-3">
                <span className="h-2 w-2 rounded-full bg-[#7A5C3C] shadow-[0_0_0_6px_rgba(122,92,60,0.08)]" />
                <span className="text-[10px] sm:text-xs uppercase tracking-[0.28em]" style={{ color: ABOUT_MUTED }}>Hanmat / Personal profile</span>
              </div>
              <span className="hidden sm:inline text-[10px] uppercase tracking-[0.22em]" style={{ color: ABOUT_MUTED }}>Screen 01</span>
            </div>

            <div className="relative grid gap-4 px-4 py-4 text-left sm:gap-5 sm:px-7 sm:py-6 md:grid-cols-[1.05fr_1.25fr] md:gap-8 md:px-8 md:py-7 lg:px-10 lg:py-8">
              <div className="flex flex-col justify-between gap-5">
                <div>
                  <p className="mb-4 text-[10px] uppercase tracking-[0.24em]" style={{ color: ABOUT_MUTED }}>About Mat</p>
                  <h2 className="text-2xl leading-[1.02] tracking-[-0.05em] sm:text-3xl md:text-4xl" style={{ color: ABOUT_INK }}>
                    Self-confessed geek, <span className="italic font-serif text-[#7A5C3C]">let loose with AI.</span>
                  </h2>
                  <p className="mt-3 max-w-md text-sm leading-relaxed sm:mt-4 sm:text-[15px]" style={{ color: ABOUT_BODY }}>
                    By day I help organisations make CRM, engagement and change actually work. By night I build, test and automate the things I wish existed already.
                  </p>
                </div>
                <div className="grid grid-cols-3 gap-2 rounded-2xl border border-[#D8D2BF]/70 bg-white/45 p-2.5">
                  {[
                    ['Mode', 'Builder'],
                    ['Bias', 'Practical'],
                    ['Signal', 'Useful']
                  ].map(([label, value]) => (
                    <div key={label} className="rounded-xl bg-[#ECEBE6]/70 px-3 py-2">
                      <span className="block text-[9px] uppercase tracking-[0.18em]" style={{ color: ABOUT_MUTED }}>{label}</span>
                      <span className="mt-1 block text-sm" style={{ color: ABOUT_INK }}>{value}</span>
                    </div>
                  ))}
                </div>
              </div>

              <div className="grid gap-3">
                <div className="rounded-3xl border border-[#D8D2BF]/75 bg-white/[0.46] p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.35)]">
                  <div className="mb-3 flex items-center justify-between">
                    <span className="text-[10px] uppercase tracking-[0.24em]" style={{ color: ABOUT_MUTED }}>Operating notes</span>
                    <span className="text-[10px] tabular-nums" style={{ color: ABOUT_MUTED }}>03</span>
                  </div>
                  <div className="grid gap-2.5 sm:grid-cols-3">
                    {[
                      ['01', 'Tinker until the abstract becomes tangible.'],
                      ['02', 'Turn messy problems into cleaner operating rhythms.'],
                      ['03', 'Use AI where it removes friction, not where it adds theatre.']
                    ].map(([num, item]) => (
                      <div key={num} className="rounded-2xl border border-[#D8D2BF]/70 bg-[#ECEBE6]/65 px-3.5 py-3">
                        <span className="mb-2 block text-[10px] tracking-[0.18em]" style={{ color: ABOUT_MUTED }}>{num}</span>
                        <span className="text-sm leading-snug" style={{ color: ABOUT_BODY }}>{item}</span>
                      </div>
                    ))}
                  </div>
                </div>

                <div className="hidden gap-3 sm:grid sm:grid-cols-[0.92fr_1.08fr]">
                  <div className="rounded-3xl border border-[#E5B88E]/20 bg-[#0D0F12] p-4 text-[#E1E0CC] shadow-[0_20px_70px_rgba(26,24,18,0.16)]">
                    <p className="text-[10px] uppercase tracking-[0.24em] text-[#E5B88E]">Current curiosity</p>
                    <p className="mt-3 text-sm leading-relaxed text-[#F2EEDB]">Local-first AI, private knowledge systems and agentic workflows that earn their keep.</p>
                  </div>
                  <div className="rounded-3xl border border-[#D8D2BF]/75 bg-white/[0.48] p-4">
                    <p className="text-[10px] uppercase tracking-[0.24em]" style={{ color: ABOUT_MUTED }}>Useful when</p>
                    <p className="mt-3 text-sm leading-relaxed" style={{ color: ABOUT_BODY }}>A team needs the fog turned into a brief, a prototype, a workflow, or a decision.</p>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Branding overlay — fades out as the camera pushes into the screen */}
        <div id="hero-ui" style={{ position: 'absolute', inset: 0, zIndex: 5, willChange: 'opacity, transform' }}>
          {/* legibility gradient (part of the UI layer so it fades with the branding) */}
          <div className="absolute inset-0 bg-gradient-to-b from-black/30 via-transparent to-black/70 pointer-events-none" />
          <div className="noise-overlay absolute inset-0 opacity-[0.5] mix-blend-overlay pointer-events-none" />

          {/* Bottom content */}
          <div className="absolute bottom-8 left-0 right-0 p-5 sm:bottom-0 sm:p-7 md:p-10 lg:p-12">
            <div className="grid grid-cols-12 gap-4 md:gap-6 items-end">
              <div className="col-span-12 lg:col-span-8">
                <h1 className="font-medium leading-[0.85] tracking-[-0.07em] text-[26vw] sm:text-[24vw] md:text-[22vw] lg:text-[20vw] xl:text-[19vw] 2xl:text-[20vw]"
                  style={{ color: CREAM }}>
                  <WordsPullUp text="Mat H" showAsterisk />
                </h1>
              </div>
              <div className="col-span-12 lg:col-span-4 flex flex-col gap-5 md:gap-6 lg:pb-3">
                <FadeUp delay={0.5}
                  className="text-xs sm:text-sm md:text-base flex flex-col gap-3"
                  style={{ lineHeight: 1.4, color: '#E1E0CC' }}>
                  <p>I work at the intersection of CRM transformation, customer engagement, automation and practical AI.</p>
                  <p>My focus is turning complex organisational problems into clearer operating models, useful systems and working prototypes — especially where customer data, marketing technology, internal knowledge and delivery teams need to line up.</p>
                </FadeUp>
                <FadeUp delay={0.7} className="self-start">
                  <button className="group bg-primary rounded-full text-black font-medium text-sm sm:text-base flex items-center gap-2 hover:gap-3 transition-all duration-300 pl-5 pr-1.5 py-1.5">
                    Read more
                    <span className="bg-black rounded-full w-9 h-9 sm:w-10 sm:h-10 flex items-center justify-center transition-transform duration-300 group-hover:scale-110">
                      <ArrowRight className="w-4 h-4" style={{ color: CREAM }} />
                    </span>
                  </button>
                </FadeUp>
              </div>
            </div>
          </div>

          {/* Scroll cue */}
          <div id="scroll-cue" className="absolute left-1/2 -translate-x-1/2 bottom-4 flex flex-col items-center gap-1.5 pointer-events-none">
            <span className="text-[10px] uppercase" style={{ color: CREAM, letterSpacing: '0.25em' }}>Scroll</span>
            <span style={{ width: 1, height: 26, background: `linear-gradient(${CREAM}, transparent)` }} />
          </div>
        </div>
      </div>
    </div>
  );
}

/* ---------------- ABOUT (the white laptop screen content) ---------------- */
function About() {
  return (
    <section id="about-screen"
      className="relative min-h-screen flex items-start justify-center px-6 md:px-10 pt-16 pb-28 sm:pt-20 md:pt-24 md:pb-36"
      style={{ background: 'linear-gradient(180deg, #1B1814 0%, #2B241D 12%, #6D553F 34%, #E5B88E 58%, #ECEBE6 100%)', color: ABOUT_INK }}>
      <div className="max-w-5xl mx-auto text-center">
        <p className="text-[10px] sm:text-xs uppercase tracking-[0.25em] mb-8 md:mb-12"
          style={{ color: ABOUT_MUTED }}>About</p>
        <ScrollRevealText
          className="text-xl sm:text-2xl md:text-3xl lg:text-4xl max-w-4xl mx-auto"
          style={{ color: ABOUT_INK, lineHeight: 1.4 }}
          segments={[
            { text: 'I am Mat Hanson, ', className: 'font-normal' },
            { text: 'a self-confessed geek (let loose with AI).', className: 'italic font-serif text-[#7A5C3C]' },
            { text: '\nBy day I help organisations make CRM, engagement and change actually work. By night I build, test and automate the things I wish existed already.', className: 'font-normal' }
          ]} />
      </div>
    </section>
  );
}

/* ---------------- PROFILE DOSSIER ---------------- */
function ProfileCapabilityCard({ index, label, title, body, items }) {
  return (
    <CardReveal index={index}
      className="group relative overflow-hidden rounded-[28px] border border-[#A07656]/35 bg-[#F3E7D2]/[0.76] p-5 shadow-[0_24px_80px_rgba(26,24,18,0.08)] backdrop-blur-sm sm:p-6 lg:p-7"
      style={{ color: ABOUT_INK }}>
      <div className="pointer-events-none absolute -right-10 -top-10 h-36 w-36 rounded-full bg-[#E5B88E]/[0.16] blur-3xl transition-opacity duration-500 group-hover:opacity-100 opacity-70" />
      <div className="relative">
        <div className="mb-8 flex items-center justify-between">
          <span className="rounded-full border border-[#A07656]/35 bg-[#E5B88E]/20 px-3 py-1 text-[10px] uppercase tracking-[0.24em]" style={{ color: ABOUT_MUTED }}>{label}</span>
          <span className="text-xs tabular-nums" style={{ color: ABOUT_MUTED }}>{String(index + 1).padStart(2, '0')}</span>
        </div>
        <h3 className="text-2xl leading-[1.05] tracking-[-0.045em] sm:text-3xl" style={{ color: ABOUT_INK }}>{title}</h3>
        <p className="mt-4 text-sm leading-relaxed sm:text-[15px]" style={{ color: ABOUT_BODY }}>{body}</p>
        <div className="mt-7 grid gap-2">
          {items.map((item) => (
            <div key={item} className="flex items-start gap-2.5 rounded-2xl border border-[#A07656]/30 bg-[#E5B88E]/16 px-3.5 py-2.5 text-sm" style={{ color: ABOUT_BODY }}>
              <Check className="mt-[3px] h-4 w-4 shrink-0 text-[#7A5C3C]" />
              <span>{item}</span>
            </div>
          ))}
        </div>
      </div>
    </CardReveal>
  );
}

function ProfileDossierPanel() {
  const experiments = [
    ['Local-first AI', 'Private knowledge systems and personal operating layers.'],
    ['Agentic workflows', 'Small systems that remove friction rather than create theatre.'],
    ['CRM operations', 'Customer engagement models that teams can actually run.'],
    ['Useful automation', 'Replacing brittle manual effort with clear, observable sequences.']
  ];
  return (
    <div id="experiments" className="scroll-mt-24">
      <CardReveal index={4}
        className="relative overflow-hidden rounded-[30px] border border-[#D8D2BF] bg-[#0D0F12] p-5 shadow-[0_30px_110px_rgba(26,24,18,0.22)] sm:p-6 lg:p-7"
      style={{ color: CREAM }}>
      <video className="ambient-video pointer-events-none absolute inset-0 h-full w-full object-cover opacity-[0.28] saturate-[0.85] contrast-[1.08]"
        autoPlay loop muted playsInline preload="none" tabIndex={-1} aria-hidden="true"
        src={IDLE_HERO_VIDEO} />
      <div className="absolute inset-0 bg-[#0D0F12]/80" />
      <div className="absolute inset-0 opacity-[0.18] profile-dossier-grid" />
      <div className="absolute -right-16 top-10 h-44 w-44 rounded-full bg-[#E5B88E]/35 blur-3xl" />
      <div className="relative">
        <div className="flex items-center justify-between border-b border-white/10 pb-4">
          <span className="text-[10px] uppercase tracking-[0.28em] text-[#E5B88E]">Active experiments</span>
          <span className="h-2 w-2 rounded-full bg-[#E5B88E] shadow-[0_0_24px_rgba(201,163,111,0.9)]" />
        </div>
        <div className="mt-5 grid gap-4">
          {experiments.map(([title, body], i) => (
            <div key={title} className="grid grid-cols-[42px_1fr] gap-3 rounded-2xl border border-[#E5B88E]/16 bg-[#E5B88E]/[0.045] p-3.5">
              <span className="text-xs tabular-nums text-[#A9927C]">{String(i + 1).padStart(2, '0')}</span>
              <div>
                <h4 className="text-sm text-[#F2EEDB]">{title}</h4>
                <p className="mt-1 text-xs leading-relaxed text-[#D6C0A8]">{body}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
      </CardReveal>
    </div>
  );
}

function CapabilityRail() {
  const items = ['CRM transformation', 'Customer engagement', 'Marketing technology', 'Automation', 'AI agents', 'Knowledge systems', 'Prototyping', 'Change delivery'];
  return (
    <div className="relative my-10 overflow-hidden border-y border-[#D8D2BF] py-4 sm:my-14">
      <div className="pointer-events-none absolute inset-y-0 left-0 z-10 w-20 bg-gradient-to-r from-[#ECEBE6] to-transparent" />
      <div className="pointer-events-none absolute inset-y-0 right-0 z-10 w-20 bg-gradient-to-l from-[#ECEBE6] to-transparent" />
      <div className="profile-rail-track flex w-max gap-3">
        {[...items, ...items].map((item, i) => (
          <span key={`${item}-${i}`} className="rounded-full border border-[#A07656]/35 bg-[#F3E7D2]/70 px-4 py-2 text-[10px] uppercase tracking-[0.22em] shadow-[0_10px_34px_rgba(26,24,18,0.05)]" style={{ color: ABOUT_MUTED }}>{item}</span>
        ))}
      </div>
    </div>
  );
}

function Features() {
  const cards = [
    {
      label: 'Transform',
      title: 'Customer operations that stop leaking energy.',
      body: 'CRM and engagement work usually fails in the joins: data, process, ownership, tooling and decision-making. I help make those joins visible, then workable.',
      items: ['CRM transformation', 'Engagement strategy', 'Operating model clarity']
    },
    {
      label: 'Prototype',
      title: 'AI systems with a job, not a halo.',
      body: 'The useful work is not “adding AI”. It is finding the repeated judgement, retrieval or coordination problem — then building a small system that proves the point.',
      items: ['Internal tools', 'Knowledge workflows', 'Practical automation']
    },
    {
      label: 'Simplify',
      title: 'Complexity translated into something humans can run.',
      body: 'The output should be a clearer brief, a better sequence, a sharper operating rhythm, or fewer haunted spreadsheets. Preferably all four.',
      items: ['Clearer decisions', 'Better briefs', 'Reusable systems']
    }
  ];

  return (
    <section id="profile-section" className="relative overflow-hidden px-5 py-20 sm:px-7 sm:py-24 md:px-10 lg:px-12 lg:py-28"
      style={{ background: 'linear-gradient(180deg, #1B1814 0%, #2B241D 12%, #6D553F 34%, #E5B88E 58%, #ECEBE6 100%)', color: ABOUT_INK }}>
      <div className="pointer-events-none absolute inset-0 profile-paper-grain opacity-[0.38] mix-blend-multiply" />
      <div className="pointer-events-none absolute left-1/2 top-0 h-[520px] w-[860px] -translate-x-1/2 rounded-full bg-[#E5B88E]/35 blur-3xl" />
      <div className="pointer-events-none absolute inset-x-0 top-0 h-[44vh] bg-[radial-gradient(circle_at_20%_10%,rgba(229,184,142,0.22),transparent_32%),radial-gradient(circle_at_78%_18%,rgba(109,85,63,0.28),transparent_34%)]" />

      <div className="relative mx-auto max-w-7xl">
        <CardReveal index={0} className="mx-auto max-w-5xl text-center">
          <div className="mx-auto mb-7 inline-flex items-center gap-3 rounded-full border border-[#E5B88E]/25 bg-[#0D0F12]/70 px-4 py-2 text-[10px] uppercase tracking-[0.26em] shadow-[0_18px_70px_rgba(26,24,18,0.07)]" style={{ color: ABOUT_MUTED }}>
            <span className="h-2 w-2 rounded-full bg-[#7A5C3C]" />
            Profile / Operating Layer
          </div>
          <ScrollRevealText
            className="text-3xl leading-[1.08] tracking-[-0.055em] sm:text-4xl md:text-5xl lg:text-6xl"
            style={{ color: ABOUT_INK }}
            segments={[
              { text: 'I work where ', className: 'font-normal' },
              { text: 'customer strategy, marketing technology and practical AI', className: 'italic font-serif text-[#7A5C3C]' },
              { text: ' collide — turning messy operating problems into systems people can actually use.', className: 'font-normal' }
            ]} />
        </CardReveal>

        <CapabilityRail />

        <div id="capabilities" className="grid scroll-mt-24 gap-4 lg:grid-cols-3 lg:gap-5">
          {cards.map((card, i) => <ProfileCapabilityCard key={card.label} index={i} {...card} />)}
        </div>

        <div className="mt-5 grid gap-5 lg:grid-cols-[1fr_0.78fr]">
          <CardReveal index={3}
            className="relative overflow-hidden rounded-[30px] border border-[#A07656]/35 bg-[#F3E7D2]/[0.76] p-5 shadow-[0_24px_80px_rgba(26,24,18,0.08)] backdrop-blur-sm sm:p-7 lg:p-9"
            style={{ color: ABOUT_INK }}>
            <div className="pointer-events-none absolute inset-0 profile-dossier-grid opacity-[0.42]" />
            <div className="relative grid gap-8 md:grid-cols-[0.8fr_1.2fr] md:items-end">
              <div>
                <p className="text-[10px] uppercase tracking-[0.28em]" style={{ color: ABOUT_MUTED }}>Current signal</p>
                <h3 className="mt-4 text-3xl leading-[1.03] tracking-[-0.05em] sm:text-4xl" style={{ color: ABOUT_INK }}>Less theatre. More working systems.</h3>
              </div>
              <p className="text-base leading-relaxed sm:text-lg" style={{ color: ABOUT_BODY }}>
                I am interested in the practical edge: where transformation stops being a deck and becomes an operating rhythm, a prototype, a usable workflow, or a decision someone can make faster.
              </p>
            </div>
          </CardReveal>

          <ProfileDossierPanel />
        </div>
      </div>
    </section>
  );
}


/* ---------------- OPERATING LAYER PROTOTYPE ---------------- */
function OperatingLayerWindow({ eyebrow, title, children, className = '', dark = false }) {
  return (
    <div className={`relative overflow-hidden rounded-[28px] border ${dark ? 'border-[#E5B88E]/18 bg-[#0D0F12]/88 text-[#E1E0CC]' : 'border-[#E5B88E]/22 bg-[#F2E2C8]/[0.84] text-[#18140F]'} p-5 shadow-[0_30px_100px_rgba(0,0,0,0.22)] backdrop-blur-sm sm:p-6 lg:p-7 ${className}`}>
      <div className="pointer-events-none absolute inset-0 profile-dossier-grid opacity-[0.18]" />
      <div className="relative">
        <div className="mb-6 flex items-center justify-between border-b border-current/10 pb-3">
          <span className="text-[10px] uppercase tracking-[0.28em]" style={{ color: dark ? HERO_PEACH : ABOUT_MUTED }}>{eyebrow}</span>
          <span className="h-2 w-2 rounded-full" style={{ background: dark ? HERO_PEACH : HERO_UMBER }} />
        </div>
        <h3 className="text-2xl leading-[1.02] tracking-[-0.05em] sm:text-3xl">{title}</h3>
        {children}
      </div>
    </div>
  );
}

function OperatingLayerChapter({ index, label, title, problem, intervention, output }) {
  return (
    <CardReveal index={index} className="group relative grid gap-4 rounded-[30px] border border-[#E5B88E]/18 bg-[#11100D]/82 p-4 text-[#E1E0CC] shadow-[0_30px_100px_rgba(0,0,0,0.22)] backdrop-blur-sm md:grid-cols-[0.42fr_1fr_1fr_1fr] md:items-stretch md:p-5">
      <div className="relative overflow-hidden rounded-[22px] border border-[#E5B88E]/18 bg-[#E5B88E]/[0.045] p-4">
        <span className="block text-xs tabular-nums text-[#E5B88E]">{String(index + 1).padStart(2, '0')}</span>
        <span className="mt-10 block text-[10px] uppercase tracking-[0.28em] text-[#D6C0A8]">{label}</span>
      </div>
      {[
        ['Symptom', problem],
        ['Intervention', intervention],
        ['Afterwards', output]
      ].map(([k, v]) => (
        <div key={k} className="rounded-[22px] border border-white/10 bg-white/[0.035] p-4 transition-colors group-hover:border-[#E5B88E]/24">
          <p className="text-[10px] uppercase tracking-[0.24em] text-[#A9927C]">{k}</p>
          <p className="mt-3 text-sm leading-relaxed text-[#F2EEDB]">{v}</p>
        </div>
      ))}
    </CardReveal>
  );
}

function OperatingLayerArtifact({ index, title, body, tags }) {
  return (
    <CardReveal index={index} className="relative overflow-hidden rounded-[26px] border border-[#E5B88E]/18 bg-[#F2E2C8]/[0.86] p-5 text-[#18140F] shadow-[0_22px_80px_rgba(0,0,0,0.16)]">
      <div className="absolute -right-10 -top-10 h-36 w-36 rounded-full bg-[#A07656]/20 blur-3xl" />
      <div className="relative">
        <div className="mb-10 flex items-center justify-between">
          <span className="text-xs tabular-nums text-[#7B6958]">{String(index + 1).padStart(2, '0')}</span>
          <span className="rounded-full border border-[#A07656]/28 px-3 py-1 text-[10px] uppercase tracking-[0.22em] text-[#7B6958]">Specimen</span>
        </div>
        <h4 className="text-2xl leading-[1.04] tracking-[-0.045em]">{title}</h4>
        <p className="mt-4 text-sm leading-relaxed text-[#362B22]">{body}</p>
        <div className="mt-6 flex flex-wrap gap-2">
          {tags.map((tag) => (
            <span key={tag} className="rounded-full bg-[#0D0F12]/[0.06] px-3 py-1 text-[10px] uppercase tracking-[0.18em] text-[#6D553F]">{tag}</span>
          ))}
        </div>
      </div>
    </CardReveal>
  );
}

function OperatingLayerPostHero() {
  const chapters = [
    {
      label: 'The Fog',
      title: 'Mess made visible.',
      problem: 'Customer data, campaigns, handoffs and ownership drift apart until nobody can see where the work is leaking.',
      intervention: 'Map the joins: source, decision, owner, action, feedback loop. Name what is actually broken before adding tools.',
      output: 'A shared diagnostic view: fewer opinions, clearer constraints, and a first useful brief.'
    },
    {
      label: 'The Joins',
      title: 'The operating model takes shape.',
      problem: 'CRM, marketing technology and delivery teams each hold part of the truth, but not enough to act cleanly.',
      intervention: 'Translate the messy edge into journeys, states, rules, handoffs and evidence the team can reason about.',
      output: 'A workable model of how customer engagement should actually run.'
    },
    {
      label: 'The Prototype',
      title: 'Build the smallest system that proves it.',
      problem: 'Big platforms and vague AI ideas hide whether the operating rhythm is sound.',
      intervention: 'Build a thin tool, workflow or agentic sequence that does one useful job and can be observed failing safely.',
      output: 'A tangible artefact: prototype, workflow, evaluation checklist, or private knowledge layer.'
    },
    {
      label: 'The Rhythm',
      title: 'Make it repeatable.',
      problem: 'Good interventions decay when they live in decks, meetings or one person’s head.',
      intervention: 'Embed the sequence into cadence, ownership, documentation, automation and decision habits.',
      output: 'A clearer way of working that teams can run without theatrical supervision.'
    }
  ];

  const artifacts = [
    ['CRM leakage map', 'A practical view of where customer data, campaign activity and team ownership stop lining up.', ['journey', 'ownership', 'risk']],
    ['Prototype workflow', 'A thin working sequence for retrieval, decision support or automation before committing to platform weight.', ['prototype', 'AI', 'workflow']],
    ['Operating rhythm brief', 'A decision-ready description of who does what, when, with which signal, and what happens next.', ['cadence', 'handoff', 'brief']],
    ['Private knowledge layer', 'A local-first way to preserve source material, context and recommendations without throwing raw content into random systems.', ['local-first', 'retrieval', 'trust']]
  ];

  return (
    <section id="profile-section" className="relative overflow-hidden bg-[#0D0F12] text-[#E1E0CC]">
      <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_30%_0%,rgba(229,184,142,0.20),transparent_32%),radial-gradient(circle_at_80%_14%,rgba(109,85,63,0.34),transparent_34%),linear-gradient(180deg,#0D0F12_0%,#191712_38%,#6D553F_100%)]" />
      <video className="ambient-video pointer-events-none absolute left-1/2 top-0 h-[70vh] w-full -translate-x-1/2 object-cover opacity-[0.14] saturate-[0.78] contrast-[1.08]"
        autoPlay loop muted playsInline preload="none" tabIndex={-1} aria-hidden="true" src={IDLE_HERO_VIDEO} />
      <div className="noise-overlay pointer-events-none absolute inset-0 opacity-[0.20] mix-blend-overlay" />

      <div className="relative mx-auto max-w-7xl px-5 py-20 sm:px-7 md:px-10 lg:px-12 lg:py-28">
        <div className="rounded-[34px] border border-[#E5B88E]/18 bg-black/34 p-3 shadow-[0_50px_160px_rgba(0,0,0,0.45)] backdrop-blur-md">
          <div className="rounded-[28px] border border-white/10 bg-[#0D0F12]/88">
            <div className="flex flex-wrap items-center justify-between gap-3 border-b border-white/10 px-5 py-4">
              <div className="flex items-center gap-3">
                <span className="h-2.5 w-2.5 rounded-full bg-[#E5B88E] shadow-[0_0_24px_rgba(229,184,142,0.75)]" />
                <span className="text-[10px] uppercase tracking-[0.30em] text-[#D6C0A8]">Hanmat / Operating Layer</span>
              </div>
              <span className="text-[10px] uppercase tracking-[0.22em] text-[#A9927C]">Prototype 01</span>
            </div>

            <div className="grid gap-8 p-5 sm:p-7 lg:grid-cols-[0.74fr_1.26fr] lg:p-9">
              <CardReveal index={0} className="flex min-h-[520px] flex-col justify-between rounded-[30px] border border-[#E5B88E]/18 bg-[#11100D]/72 p-6 shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] lg:p-8">
                <div>
                  <p className="text-[10px] uppercase tracking-[0.28em] text-[#E5B88E]">Screen expansion</p>
                  <h2 className="mt-5 text-5xl leading-[0.92] tracking-[-0.075em] text-[#F2EEDB] sm:text-6xl lg:text-7xl">
                    Inside the working layer.
                  </h2>
                  <p className="mt-6 max-w-xl text-base leading-relaxed text-[#D6C0A8] sm:text-lg">
                    I turn ambiguous customer, CRM and AI problems into systems people can actually run — by making the mess visible, building the smallest useful prototype, then embedding the rhythm.
                  </p>
                </div>
                <div className="mt-10 grid gap-2 text-sm text-[#F2EEDB]">
                  {['Map the joins', 'Prototype the useful system', 'Embed the operating rhythm'].map((item) => (
                    <div key={item} className="flex items-center justify-between rounded-2xl border border-white/10 bg-white/[0.035] px-4 py-3">
                      <span>{item}</span>
                      <ArrowRight className="h-4 w-4 text-[#E5B88E]" />
                    </div>
                  ))}
                </div>
              </CardReveal>

              <div id="capabilities" className="grid scroll-mt-24 gap-5">
                <OperatingLayerWindow eyebrow="Diagnostic surface" title="The work is not to add another system. It is to make the current one stop apologising for itself." dark>
                  <div className="mt-6 grid gap-3 md:grid-cols-3">
                    {[
                      ['Input', 'Customer data, campaign signals, operational friction.'],
                      ['Method', 'Map joins, prototype workflows, test what breaks.'],
                      ['Output', 'Briefs, tools, rhythms and decisions people can use.']
                    ].map(([k, v]) => (
                      <div key={k} className="rounded-2xl border border-[#E5B88E]/14 bg-[#E5B88E]/[0.045] p-4">
                        <p className="text-[10px] uppercase tracking-[0.24em] text-[#A9927C]">{k}</p>
                        <p className="mt-3 text-sm leading-relaxed text-[#F2EEDB]">{v}</p>
                      </div>
                    ))}
                  </div>
                </OperatingLayerWindow>

                <div className="grid gap-4">
                  {chapters.map((chapter, i) => <OperatingLayerChapter key={chapter.label} index={i} {...chapter} />)}
                </div>
              </div>
            </div>
          </div>
        </div>

        <div id="experiments" className="scroll-mt-24 pt-10 lg:pt-14">
          <div className="mb-6 flex flex-wrap items-end justify-between gap-4">
            <div>
              <p className="text-[10px] uppercase tracking-[0.30em] text-[#E5B88E]">Artifact specimens</p>
              <h3 className="mt-3 max-w-3xl text-4xl leading-[0.98] tracking-[-0.06em] text-[#F2EEDB] sm:text-5xl lg:text-6xl">
                Evidence, not another capability grid.
              </h3>
            </div>
            <p className="max-w-md text-sm leading-relaxed text-[#D6C0A8]">
              Representative artefacts. Enough to show the shape of the work without pretending this is a SaaS product.
            </p>
          </div>
          <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
            {artifacts.map(([title, body, tags], i) => <OperatingLayerArtifact key={title} index={i} title={title} body={body} tags={tags} />)}
          </div>
        </div>
      </div>
    </section>
  );
}


/* ---------------- OPERATING LAYER V2: CINEMATIC CASE BOARD ---------------- */
function CaseBoardSignal({ x, y, label, detail, tone = 'cream' }) {
  const bg = tone === 'dark' ? 'rgba(13,15,18,0.82)' : 'rgba(236,235,230,0.88)';
  const fg = tone === 'dark' ? '#F2EEDB' : '#18140F';
  const muted = tone === 'dark' ? '#D6C0A8' : '#6D553F';
  return (
    <div className="absolute w-[230px] -translate-x-1/2 -translate-y-1/2 border border-[#E5B88E]/30 p-4 shadow-[0_24px_90px_rgba(0,0,0,0.30)] backdrop-blur-md sm:w-[270px]"
      style={{ left: x, top: y, background: bg, color: fg, clipPath: 'polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 18px 100%, 0 calc(100% - 18px))' }}>
      <p className="text-[10px] uppercase tracking-[0.24em]" style={{ color: muted }}>{label}</p>
      <p className="mt-3 text-sm leading-relaxed">{detail}</p>
    </div>
  );
}

function CaseBoardRow({ index, verb, text }) {
  return (
    <div className="grid grid-cols-[54px_1fr] gap-4 border-t border-[#E5B88E]/18 py-5 first:border-t-0">
      <div className="text-xs tabular-nums text-[#E5B88E]">{String(index).padStart(2, '0')}</div>
      <div>
        <p className="text-[10px] uppercase tracking-[0.26em] text-[#A9927C]">{verb}</p>
        <p className="mt-2 max-w-xl text-lg leading-snug text-[#F2EEDB]">{text}</p>
      </div>
    </div>
  );
}

function OperatingLayerV2PostHero() {
  const specimenRows = [
    ['CRM leakage map', 'Where customer data, ownership and action stop lining up.', 'journey / ownership / risk'],
    ['Prototype workflow', 'One thin sequence that proves whether AI or automation has a real job.', 'prototype / run log / evaluation'],
    ['Operating rhythm brief', 'Who does what, when, using which signal, and what changes afterwards.', 'cadence / decision / handoff'],
    ['Private knowledge layer', 'Source-preserving retrieval and recommendations without spraying raw context everywhere.', 'local-first / retrieval / trust']
  ];

  return (
    <section id="profile-section" className="relative overflow-hidden bg-[#050505] text-[#E1E0CC]">
      <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_54%_8%,rgba(229,184,142,0.16),transparent_28%),radial-gradient(circle_at_28%_42%,rgba(109,85,63,0.42),transparent_34%),linear-gradient(180deg,#050505_0%,#0D0F12_30%,#2A2119_66%,#0D0F12_100%)]" />
      <video className="ambient-video pointer-events-none absolute inset-x-0 top-0 h-[92vh] w-full object-cover opacity-[0.18] saturate-[0.75] contrast-[1.15]"
        autoPlay loop muted playsInline preload="none" tabIndex={-1} aria-hidden="true" src={IDLE_HERO_VIDEO} />
      <div className="noise-overlay pointer-events-none absolute inset-0 opacity-[0.24] mix-blend-overlay" />

      <div className="relative mx-auto max-w-[1500px] px-5 py-20 sm:px-7 md:px-10 lg:px-12 lg:py-28">
        <div className="grid min-h-[92vh] gap-10 lg:grid-cols-[0.92fr_1.08fr] lg:items-center">
          <div className="relative z-10">
            <p className="text-[10px] uppercase tracking-[0.34em] text-[#E5B88E]">Hanmat / Case Board</p>
            <h2 className="mt-5 max-w-3xl text-[18vw] leading-[0.78] tracking-[-0.09em] text-[#F2EEDB] sm:text-8xl lg:text-[8.5rem]">
              Make the mess visible.
            </h2>
            <p className="mt-7 max-w-xl text-lg leading-relaxed text-[#D6C0A8] sm:text-xl">
              The hero ends inside the laptop. This is the next surface: not a services grid, but a working board for customer systems, CRM leakage, prototype loops and operating rhythm.
            </p>
            <div className="mt-10 max-w-xl border-y border-[#E5B88E]/18">
              <CaseBoardRow index={1} verb="Observe" text="Where customer signals, teams and tools stop agreeing." />
              <CaseBoardRow index={2} verb="Connect" text="The joins between data, ownership, handoff and action." />
              <CaseBoardRow index={3} verb="Build" text="The smallest useful prototype that proves the rhythm." />
            </div>
          </div>

          <div id="capabilities" className="relative min-h-[720px] scroll-mt-24 overflow-hidden border border-[#E5B88E]/22 bg-[#0D0F12]/56 shadow-[0_50px_180px_rgba(0,0,0,0.48)] backdrop-blur-sm"
            style={{ clipPath: 'polygon(0 0, calc(100% - 34px) 0, 100% 34px, 100% 100%, 34px 100%, 0 calc(100% - 34px))' }}>
            <div className="absolute inset-0 profile-dossier-grid opacity-[0.20]" />
            <svg className="absolute inset-0 h-full w-full" viewBox="0 0 800 720" preserveAspectRatio="none" aria-hidden="true">
              <defs>
                <linearGradient id="hanmatLine" x1="0" x2="1" y1="0" y2="1">
                  <stop offset="0%" stopColor="#E5B88E" stopOpacity="0.08" />
                  <stop offset="55%" stopColor="#E5B88E" stopOpacity="0.56" />
                  <stop offset="100%" stopColor="#F2EEDB" stopOpacity="0.18" />
                </linearGradient>
              </defs>
              <path d="M70 530 C190 390 260 430 342 295 S520 145 716 214" fill="none" stroke="url(#hanmatLine)" strokeWidth="2" />
              <path d="M126 210 C220 310 330 250 430 350 S565 545 704 474" fill="none" stroke="#E5B88E" strokeOpacity="0.20" strokeWidth="1.5" strokeDasharray="8 10" />
              <path d="M96 612 L275 485 L426 515 L666 328" fill="none" stroke="#F2EEDB" strokeOpacity="0.15" strokeWidth="1" />
              <circle cx="116" cy="210" r="7" fill="#E5B88E" fillOpacity="0.70" />
              <circle cx="116" cy="210" r="22" fill="none" stroke="#E5B88E" strokeOpacity="0.15" />
              <circle cx="342" cy="295" r="7" fill="#E5B88E" fillOpacity="0.70" />
              <circle cx="342" cy="295" r="22" fill="none" stroke="#E5B88E" strokeOpacity="0.15" />
              <circle cx="716" cy="214" r="7" fill="#E5B88E" fillOpacity="0.70" />
              <circle cx="716" cy="214" r="22" fill="none" stroke="#E5B88E" strokeOpacity="0.15" />
              <circle cx="426" cy="515" r="7" fill="#E5B88E" fillOpacity="0.70" />
              <circle cx="426" cy="515" r="22" fill="none" stroke="#E5B88E" strokeOpacity="0.15" />
              <circle cx="666" cy="328" r="7" fill="#E5B88E" fillOpacity="0.70" />
              <circle cx="666" cy="328" r="22" fill="none" stroke="#E5B88E" strokeOpacity="0.15" />
              <circle cx="96" cy="612" r="7" fill="#E5B88E" fillOpacity="0.70" />
              <circle cx="96" cy="612" r="22" fill="none" stroke="#E5B88E" strokeOpacity="0.15" />
            </svg>
            <div className="absolute left-6 top-6 text-[10px] uppercase tracking-[0.30em] text-[#A9927C]">Live operating map / representative</div>
            <div className="absolute bottom-6 left-6 right-6 flex flex-wrap gap-2 text-[10px] uppercase tracking-[0.20em] text-[#D6C0A8]">
              {['CRM leakage', 'Journey state', 'Decision loop', 'Prototype run', 'Knowledge layer'].map(t => <span key={t} className="border border-[#E5B88E]/18 bg-[#E5B88E]/[0.045] px-3 py-2">{t}</span>)}
            </div>
            <CaseBoardSignal x="20%" y="31%" label="Fog" detail="Signals exist, but the operating picture does not." tone="dark" />
            <CaseBoardSignal x="52%" y="43%" label="Joins" detail="Customer data, campaign action and delivery ownership get linked." />
            <CaseBoardSignal x="75%" y="25%" label="Prototype" detail="A thin working sequence tests the rhythm before platform weight." tone="dark" />
            <CaseBoardSignal x="72%" y="69%" label="Rhythm" detail="The useful behaviour becomes repeatable, observable and owned." />
          </div>
        </div>

        <div id="experiments" className="scroll-mt-24 py-18 lg:py-24">
          <div className="grid gap-10 lg:grid-cols-[0.82fr_1.18fr] lg:items-start">
            <div className="sticky top-28 hidden lg:block">
              <p className="text-[10px] uppercase tracking-[0.34em] text-[#E5B88E]">Specimens / not features</p>
              <h3 className="mt-4 text-6xl leading-[0.90] tracking-[-0.075em] text-[#F2EEDB]">Show the working, not the brochure.</h3>
            </div>
            <div className="grid gap-0 border-y border-[#E5B88E]/22">
              {specimenRows.map(([title, body, meta], i) => (
                <div key={title} className="group grid gap-4 border-b border-[#E5B88E]/16 py-8 last:border-b-0 md:grid-cols-[96px_1fr_0.72fr] md:items-center">
                  <span className="text-sm tabular-nums text-[#E5B88E]">{String(i + 1).padStart(2, '0')}</span>
                  <div>
                    <h4 className="text-3xl leading-none tracking-[-0.055em] text-[#F2EEDB] sm:text-4xl">{title}</h4>
                    <p className="mt-3 max-w-2xl text-base leading-relaxed text-[#D6C0A8]">{body}</p>
                  </div>
                  <p className="text-[10px] uppercase tracking-[0.24em] text-[#A9927C] md:text-right">{meta}</p>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------------- CONTACT / HOLDING CLOSE ---------------- */
function ContactClose() {
  return (
    <section id="inquiries" className="relative overflow-hidden bg-black px-5 py-20 text-[#E1E0CC] sm:px-7 md:px-10 lg:px-12 lg:py-28">
      <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_0%,rgba(201,163,111,0.18),transparent_34%),linear-gradient(180deg,rgba(236,235,230,0.04),transparent)]" />
      <div className="noise-overlay pointer-events-none absolute inset-0 opacity-[0.18] mix-blend-overlay" />
      <div className="relative mx-auto grid max-w-7xl gap-10 lg:grid-cols-[0.92fr_1.08fr] lg:items-end">
        <div>
          <p className="text-[10px] uppercase tracking-[0.28em] text-[#E5B88E]">Inquiries / Holding pattern</p>
          <h2 className="mt-5 max-w-3xl text-4xl leading-[0.98] tracking-[-0.06em] sm:text-5xl md:text-6xl lg:text-7xl">
            Useful systems, clearer change, and fewer haunted spreadsheets.
          </h2>
        </div>
        <div className="rounded-[30px] border border-[#E5B88E]/16 bg-[#E5B88E]/[0.045] p-5 shadow-[0_30px_100px_rgba(0,0,0,0.35)] sm:p-7">
          <p className="text-base leading-relaxed text-[#D8D2BF] sm:text-lg">
            This is a holding page for now. The next version will add selected work, experiments, and practical notes from the edge of CRM transformation, automation and local-first AI.
          </p>
          <div className="mt-7 flex flex-wrap gap-3">
            <a href="mailto:hello@hanmat.uk" className="group inline-flex items-center gap-2 rounded-full bg-[#E1E0CC] py-2 pl-5 pr-2 text-sm font-medium text-black transition-all hover:gap-3">
              Start a conversation
              <span className="flex h-9 w-9 items-center justify-center rounded-full bg-black">
                <ArrowRight className="h-4 w-4" style={{ color: CREAM }} />
              </span>
            </a>
            <a href="#profile-section" className="inline-flex items-center rounded-full border border-white/15 px-5 py-2 text-sm text-[#D8D2BF] transition-colors hover:border-[#C9A36F]/70 hover:text-[#F2EEDB]">
              Back to profile
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------------- Scroll scrub + screen-handoff controller ---------------- */
function useHeroScrub() {
  useEffect(() => {
    const video = document.getElementById('hero-video');
    const idleVideo = document.getElementById('hero-idle-video');
    const track = document.getElementById('hero-track');
    const ui = document.getElementById('hero-ui');
    const cue = document.getElementById('scroll-cue');
    const boot = document.getElementById('boot-flash');
    const heroWhite = document.getElementById('hero-white');
    const heroAbout = document.getElementById('hero-about-preview');
    if (!video || !track) return;

    const clamp = (x, a, b) => Math.min(b, Math.max(a, x));
    const smooth = (e0, e1, x) => { const t = clamp((x - e0) / (e1 - e0), 0, 1); return t * t * (3 - 2 * t); };

    let target = 0, current = 0, raf = 0, lastSeekAt = 0;

    function compute() {
      const vh = window.innerHeight;
      const range = track.offsetHeight - vh;
      const scrolled = clamp(-track.getBoundingClientRect().top, 0, range);
      const p = range > 0 ? scrolled / range : 0;
      target = p * SCRUB_END;


      // At rest, play the ambient idle loop. As soon as the user scrolls, crossfade
      // to the scrubbed laptop video so one element is never asked to both loop and seek.
      const scrubIn = smooth(0.002, 0.035, p);
      if (idleVideo) {
        idleVideo.style.opacity = String(1 - scrubIn);
        if (p < 0.004 && idleVideo.paused) {
          if (idleVideo.currentTime >= IDLE_LOOP_END) {
            try { idleVideo.currentTime = 0; } catch (e) {}
          }
          const idlePlay = idleVideo.play();
          if (idlePlay && idlePlay.catch) idlePlay.catch(() => {});
        }
        if (p > 0.06 && !idleVideo.paused) idleVideo.pause();
      }
      video.style.opacity = String(scrubIn);


      // Final stretch dissolves to a whole-white screen, then reveals the About
      // copy inside the hero before the separate About section takes over.
      if (heroWhite) heroWhite.style.opacity = String(smooth(WHITE_START, WHITE_END, p));
      if (heroAbout) {
        const aboutIn = smooth(0.88, 0.98, p);
        heroAbout.style.opacity = String(aboutIn);
        heroAbout.style.transform = 'translateY(' + ((1 - aboutIn) * 24) + 'px)';
      }

      // Branding fades + drifts up as the camera pushes in (kept on screen longer)
      const uiHide = smooth(0.08, 0.56, p);
      if (ui) {
        ui.style.opacity = String(1 - uiHide);
        ui.style.transform = 'translateY(' + (-uiHide * 36) + 'px)';
        ui.style.pointerEvents = uiHide > 0.9 ? 'none' : '';
      }
      if (cue) cue.style.opacity = String(1 - smooth(0.02, 0.12, p));

      // The About preview now provides the handoff. Keep the old white flash
      // disabled so it doesn't blank out the laptop-screen content at the seam.
      if (boot) boot.style.opacity = '0';
    }

    function loop(ts = 0) {
      current += (target - current) * 0.18;            // lerp → smooth, eased scrub
      if (Math.abs(target - current) < 0.006) current = target;
      if (idleVideo && !idleVideo.paused && idleVideo.currentTime >= IDLE_LOOP_END) {
        try { idleVideo.currentTime = 0; } catch (e) {}
      }
      if (video.readyState >= 1) {
        const diff = Math.abs(video.currentTime - current);
        const canSeek = !video.seeking || diff > 0.22;
        if (diff > 0.016 && canSeek && (ts - lastSeekAt > 30 || diff > 0.18)) {
          try { video.currentTime = current; lastSeekAt = ts; } catch (e) {}
        }
      }
      raf = requestAnimationFrame(loop);
    }

    // Prime decoding on first interaction (helps mobile seek smoothly)
    let primed = false;
    const prime = () => {
      if (primed) return; primed = true;
      const pr = video.play();
      if (pr && pr.then) pr.then(() => video.pause()).catch(() => {});
    };
    ['wheel', 'touchstart', 'pointerdown', 'keydown'].forEach((e) =>
      window.addEventListener(e, prime, { once: true, passive: true }));

    const showFirst = () => {
      try { video.currentTime = 0; } catch (e) {}
    };
    if (video.readyState >= 1) showFirst(); else video.addEventListener('loadeddata', showFirst, { once: true });
    if (idleVideo) {
      const idlePlay = idleVideo.play();
      if (idlePlay && idlePlay.catch) idlePlay.catch(() => {});
    }

    compute();
    window.addEventListener('scroll', compute, { passive: true });
    window.addEventListener('resize', compute);
    raf = requestAnimationFrame(loop);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('scroll', compute);
      window.removeEventListener('resize', compute);
    };
  }, []);
}

function App() {
  useHeroScrub();
  const sectionTest = new URLSearchParams(window.location.search).get('sectionTest');
  const useOperatingLayer = sectionTest === 'operating-layer';
  const useOperatingLayerV2 = sectionTest === 'operating-layer-v2';
  useEffect(() => {
    window.__hanmatSectionDebug = {
      sectionTest: useOperatingLayerV2 ? 'operating-layer-v2' : (useOperatingLayer ? 'operating-layer' : 'default'),
      operatingLayerPresent: !!document.body.innerText.includes('Inside the working layer'),
      operatingLayerV2Present: !!document.body.innerText.includes('Make the mess visible.'),
      defaultFeaturesTextPresent: !!document.body.innerText.includes('Customer operations that stop leaking energy.'),
    };
  }, [useOperatingLayer, useOperatingLayerV2]);
  return (
    <React.Fragment>
      <SiteNav />
      <HeroScroll />
      {useOperatingLayerV2 ? <OperatingLayerV2PostHero /> : (useOperatingLayer ? <OperatingLayerPostHero /> : <Features />)}
      <ContactClose />

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

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