// Northbound Automations — landing page
// Single React artifact. British English. No em dashes.

const { useState, useEffect, useRef } = React;
const { motion, AnimatePresence, useScroll, useTransform } = window.framerMotion || {};

// ---------- Inline icon components (lucide via createIcons not ideal in React; use SVG) ----------
const Icon = ({ path, className = "w-4 h-4", stroke = 1.6 }) =>
<svg
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  strokeWidth={stroke}
  strokeLinecap="round"
  strokeLinejoin="round"
  className={className}
  aria-hidden="true">
  
    {path}
  </svg>;


const ArrowUpRight = (p) =>
<Icon {...p} path={<><path d="M7 7h10v10" /><path d="M7 17 17 7" /></>} />;

const Play = (p) => <Icon {...p} path={<polygon points="6 3 20 12 6 21 6 3" />} />;
const Zap = (p) => <Icon {...p} path={<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />} />;
const Palette = (p) =>
<Icon {...p} path={<>
    <circle cx="13.5" cy="6.5" r=".5" fill="currentColor" />
    <circle cx="17.5" cy="10.5" r=".5" fill="currentColor" />
    <circle cx="8.5" cy="7.5" r=".5" fill="currentColor" />
    <circle cx="6.5" cy="12.5" r=".5" fill="currentColor" />
    <path d="M12 2a10 10 0 1 0 0 20 2 2 0 0 0 2-2 2 2 0 0 1 2-2h2a4 4 0 0 0 4-4 10 10 0 0 0-10-10Z" />
  </>} />;

const BarChart3 = (p) =>
<Icon {...p} path={<><path d="M3 3v18h18" /><path d="M7 16V9" /><path d="M12 16v-5" /><path d="M17 16v-9" /></>} />;

const Shield = (p) =>
<Icon {...p} path={<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z" />} />;

const Settings = (p) =>
<Icon {...p} path={<>
    <circle cx="12" cy="12" r="3" />
    <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" />
  </>} />;

const LineChart = (p) =>
<Icon {...p} path={<><path d="M3 3v18h18" /><path d="m19 9-5 5-4-4-3 3" /></>} />;

const Bot = (p) =>
<Icon {...p} path={<>
    <path d="M12 8V4H8" />
    <rect width="16" height="12" x="4" y="8" rx="2" />
    <path d="M2 14h2" /><path d="M20 14h2" />
    <path d="M15 13v2" /><path d="M9 13v2" />
  </>} />;

const Workflow = (p) =>
<Icon {...p} path={<>
    <rect width="8" height="8" x="3" y="3" rx="2" />
    <path d="M7 11v4a2 2 0 0 0 2 2h4" />
    <rect width="8" height="8" x="13" y="13" rx="2" />
  </>} />;

const Wrench = (p) =>
<Icon {...p} path={<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76Z" />} />;

const Database = (p) =>
<Icon {...p} path={<>
    <ellipse cx="12" cy="5" rx="9" ry="3" />
    <path d="M3 5v14a9 3 0 0 0 18 0V5" />
    <path d="M3 12a9 3 0 0 0 18 0" />
  </>} />;

const Quote = (p) =>
<Icon {...p} path={<>
    <path d="M3 21c3 0 7-1 7-8V5c0-1.25-.76-2-2-2H4c-1.25 0-2 .75-2 1.97V11c0 1.25.75 2 2 2h3c0 4-3 5-4 5" />
    <path d="M15 21c3 0 7-1 7-8V5c0-1.25-.76-2-2-2h-4c-1.25 0-2 .75-2 1.97V11c0 1.25.75 2 2 2h3c0 4-3 5-4 5" />
  </>} />;

const Compass = (p) =>
<Icon {...p} path={<>
    <circle cx="12" cy="12" r="10" />
    <polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" />
  </>} />;

const Menu = (p) => <Icon {...p} path={<><path d="M4 6h16" /><path d="M4 12h16" /><path d="M4 18h16" /></>} />;
const X = (p) => <Icon {...p} path={<><path d="M18 6 6 18" /><path d="m6 6 12 12" /></>} />;

// ------------------ NAV ------------------
function Nav() {
  const [open, setOpen] = useState(false);
  const links = ["Home", "Services", "Work", "Process", "About", "Contact"];
  return (
    <header
      className="fixed top-4 left-0 right-0 z-50 px-5 md:px-8 lg:px-16 py-3"
      data-screen-label="Nav">
      
      <div className="flex items-center justify-between">
        {/* Logo */}
        <a href="#home" className="flex items-center gap-2 group">
          <span className="relative inline-flex items-center justify-center w-9 h-9 rounded-full liquid-glass">
            <Compass className="w-4 h-4 text-white" />
          </span>
          <span className="font-heading italic text-2xl text-white leading-none">
            Northbound
          </span>
        </a>

        {/* Centre pill */}
        <nav className="hidden md:block">
          <div className="liquid-glass rounded-full px-1.5 py-1">
            <ul className="flex items-center">
              {links.map((l, i) =>
              <li key={l}>
                  <a
                  href={`#${l.toLowerCase()}`}
                  className={`px-3 py-2 text-sm font-medium font-body rounded-full transition-colors ${
                  i === 0 ? "text-white" : "text-white/70 hover:text-white"}`
                  }>
                  
                    {l}
                  </a>
                </li>
              )}
            </ul>
          </div>
        </nav>

        {/* Right CTA */}
        <div className="flex items-center gap-2">
          <a
            href="#contact"
            className="hidden md:inline-flex liquid-glass-strong rounded-full pl-4 pr-2 py-2 items-center gap-2 text-sm font-medium text-white">
            
            Book a call
            <span className="inline-flex items-center justify-center w-7 h-7 rounded-full bg-white text-black">
              <ArrowUpRight className="w-3.5 h-3.5" stroke={2} />
            </span>
          </a>
          <button
            onClick={() => setOpen((v) => !v)}
            className="md:hidden liquid-glass rounded-full w-10 h-10 inline-flex items-center justify-center text-white"
            aria-label="Toggle menu">
            
            {open ? <X className="w-4 h-4" /> : <Menu className="w-4 h-4" />}
          </button>
        </div>
      </div>

      {open &&
      <div className="md:hidden mt-3 liquid-glass rounded-3xl p-4">
          <ul className="grid gap-1">
            {links.map((l) =>
          <li key={l}>
                <a
              href={`#${l.toLowerCase()}`}
              className="block px-3 py-2 text-sm text-white/80 font-body rounded-full hover:bg-white/5"
              onClick={() => setOpen(false)}>
              
                  {l}
                </a>
              </li>
          )}
          </ul>
        </div>
      }
    </header>);

}

// ------------------ HERO ------------------
function HeroVideo({ src = "assets/hero.mp4", objectPosition = "center" }) {
  const aRef = React.useRef(null);
  const bRef = React.useRef(null);
  const [active, setActive] = React.useState("a"); // which video is currently visible
  const fadingRef = React.useRef(false);
  const FADE = 1.2; // seconds of crossfade

  React.useEffect(() => {
    const a = aRef.current;
    const b = bRef.current;
    if (!a || !b) return;

    // Start A, pre-seek B to 0 and pause until needed
    a.play().catch(() => {});
    b.pause();
    b.currentTime = 0;

    const onTime = (e) => {
      const cur = e.target;
      const dur = cur.duration;
      if (!dur || isNaN(dur) || fadingRef.current) return;
      // Trigger crossfade when FADE seconds remain
      if (dur - cur.currentTime <= FADE) {
        fadingRef.current = true;
        const other = cur === a ? b : a;
        try {
          other.currentTime = 0;
          other.play().catch(() => {});
        } catch (err) {}
        setActive(cur === a ? "b" : "a");
        // Reset the finishing video once faded out, ready for its next turn
        setTimeout(() => {
          try {
            cur.pause();
            cur.currentTime = 0;
          } catch (err) {}
          fadingRef.current = false;
        }, FADE * 1000 + 40);
      }
    };

    a.addEventListener("timeupdate", onTime);
    b.addEventListener("timeupdate", onTime);
    return () => {
      a.removeEventListener("timeupdate", onTime);
      b.removeEventListener("timeupdate", onTime);
    };
  }, []);

  const common =
  "absolute inset-0 w-full h-full object-cover transition-opacity duration-[1200ms] ease-linear";

  return (
    <>
      <video
        ref={aRef}
        className={common}
        style={{ opacity: active === "a" ? 1 : 0, objectPosition }}
        src={src}
        autoPlay
        muted
        playsInline
        preload="auto" />
      
      <video
        ref={bRef}
        className={common}
        style={{ opacity: active === "b" ? 1 : 0, objectPosition }}
        src={src}
        muted
        playsInline
        preload="auto" />
      
    </>);

}

function Hero() {
  return (
    <section
      id="home"
      data-screen-label="Hero"
      className="relative min-h-[100svh] flex items-end pb-20 px-5 md:px-8 lg:px-16 pt-40 overflow-hidden">
      
      {/* Hero video background — dual-video crossfade to hide loop jump */}
      <div className="absolute inset-0">
        <HeroVideo />
        <div className="absolute inset-0 scanlines" />
        {/* Simulated HUD overlays */}
        <div className="absolute inset-0 mix-blend-screen opacity-50">
          <HUDLines />
        </div>
        {/* Fade overlays */}
        <div
          className="absolute inset-0 pointer-events-none"
          style={{
            background:
            "linear-gradient(to bottom, rgba(10,14,24,0.55) 0%, rgba(10,14,24,0.15) 40%, rgba(10,14,24,0.75) 85%, hsl(213 45% 8%) 100%)"
          }} />
        
        <div
          className="absolute inset-0 pointer-events-none"
          style={{
            background:
            "linear-gradient(to right, rgba(10,14,24,0.45), transparent 30%, transparent 70%, rgba(10,14,24,0.45))"
          }} />
        
      </div>

      {/* Live tag, top right */}
      <div className="absolute top-28 right-5 md:right-8 lg:right-16 liquid-glass rounded-full px-3.5 py-1.5 flex items-center gap-2">
        <span className="w-1.5 h-1.5 rounded-full bg-[hsl(213_80%_65%)] pulse-dot" />
        <span className="text-[11px] tracking-[0.18em] uppercase text-white/70 font-body">
          Taking on Q3 projects
        </span>
      </div>

      {/* Compass indicator, left rail */}
      <div className="hidden lg:flex absolute left-8 top-1/2 -translate-y-1/2 flex-col items-center gap-4 text-white/50">
        <span className="text-[10px] tracking-[0.3em] font-body">N</span>
        <span className="w-px h-16 bg-gradient-to-b from-white/40 to-transparent" />
        <span className="font-heading italic text-xs">54.9°N</span>
        <span className="w-px h-16 bg-gradient-to-b from-transparent to-white/40" />
        <span className="text-[10px] tracking-[0.3em] font-body">UK</span>
      </div>

      <div className="relative z-10 w-full max-w-7xl mx-auto grid lg:grid-cols-12 gap-10 items-end">
        <div className="lg:col-span-8">
          <div className="inline-flex liquid-glass rounded-full px-3.5 py-1 mb-6">
            <span className="text-xs font-medium text-white font-body">
              Northbound Automations · Est. 2026 · Sunderland, UK
            </span>
          </div>

          <h1 className="font-heading italic text-white tracking-tight leading-[0.9] text-[clamp(3.5rem,10vw,9rem)]">
            True North<br />for industry.
          </h1>

          <p className="mt-8 max-w-2xl text-white/70 font-body font-light text-base md:text-lg leading-relaxed">
            AI, automation, and considered software for UK manufacturers,
            engineered by people who've worked the line.
          </p>

          <div className="mt-10 flex flex-wrap items-center gap-3">
            <a
              href="#contact"
              className="liquid-glass-strong rounded-full pl-5 pr-2 py-2 inline-flex items-center gap-3 text-sm font-medium text-white">
              
              Book a discovery call
              <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white text-black">
                <ArrowUpRight className="w-4 h-4" stroke={2} />
              </span>
            </a>
            <a
              href="#work"
              className="rounded-full pl-5 pr-2 py-2 inline-flex items-center gap-3 text-sm font-medium text-white/90 hover:text-white bg-white/5 hover:bg-white/10 transition-colors">
              
              See recent work
              <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10">
                <Play className="w-3.5 h-3.5" stroke={2} />
              </span>
            </a>
          </div>
        </div>

        {/* Stats rail */}
        <div className="lg:col-span-4 grid grid-cols-3 lg:grid-cols-1 gap-3">
          {[
          { k: "Built for", v: "UK manufacturing" },
          { k: "Based in", v: "Sunderland, NE" },
          { k: "Founded", v: "April 2026" }].
          map((s) =>
          <div key={s.k} className="liquid-glass rounded-2xl p-4">
              <div className="text-[11px] tracking-[0.18em] uppercase text-white/50 font-body">
                {s.k}
              </div>
              <div className="mt-1 font-heading italic text-xl text-white">
                {s.v}
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Scroll hint */}
      <div className="absolute bottom-6 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-white/40">
        <span className="text-[10px] tracking-[0.3em] font-body uppercase">
          Scroll
        </span>
        <span className="w-px h-8 bg-gradient-to-b from-white/40 to-transparent" />
      </div>
    </section>);

}

function RotatingWord({ words, interval = 2200 }) {
  const [idx, setIdx] = React.useState(0);
  React.useEffect(() => {
    const t = setInterval(() => setIdx((p) => (p + 1) % words.length), interval);
    return () => clearInterval(t);
  }, [words.length, interval]);
  const longest = words.reduce((a, b) => a.length > b.length ? a : b, "");
  return (
    <span className="relative inline-block align-baseline overflow-hidden">
      <span className="invisible whitespace-nowrap">{longest}</span>
      {words.map((w, i) =>
      <span
        key={w}
        className="absolute left-0 top-0 whitespace-nowrap transition-all duration-500"
        style={{
          opacity: i === idx ? 1 : 0,
          transform:
          i === idx ?
          "translateY(0)" :
          i === (idx - 1 + words.length) % words.length ?
          "translateY(-60%)" :
          "translateY(60%)"
        }}>
        
          {w}
        </span>
      )}
    </span>);

}

function HUDLines() {
  // tiny decorative svg overlay for cinematic feel
  return (
    <svg className="w-full h-full" viewBox="0 0 1600 900" preserveAspectRatio="none">
      <defs>
        <linearGradient id="hud" x1="0" x2="1">
          <stop offset="0" stopColor="white" stopOpacity="0" />
          <stop offset="0.5" stopColor="white" stopOpacity="0.35" />
          <stop offset="1" stopColor="white" stopOpacity="0" />
        </linearGradient>
      </defs>
      <g stroke="url(#hud)" strokeWidth="1" fill="none">
        <path d="M0 700 L400 700 L430 680 L900 680 L930 700 L1600 700" />
        <path d="M0 720 L1600 720" opacity="0.15" />
        <circle cx="1200" cy="260" r="120" opacity="0.25" />
        <circle cx="1200" cy="260" r="60" opacity="0.4" />
        <path d="M1200 140 L1200 380 M1080 260 L1320 260" opacity="0.35" />
      </g>
    </svg>);

}

function LogoStrip() {
  // TODO: replace placeholder wordmarks with real client logos
  const logos = [
  "NORTHSTAR MOTORS",
  "HALDANE AEROSPACE",
  "TEESIDE STEEL",
  "PARKGATE FOODS",
  "PENNINE POLYMERS",
  "WEARSIDE MFG",
  "DURHAM PRECISION",
  "ALNWICK DAIRY"];

  return (
    <section className="relative py-10 border-y border-white/5">
      <div className="max-w-7xl mx-auto px-5 md:px-8 lg:px-16 mb-5 flex items-center gap-3">
        <span className="w-1.5 h-1.5 rounded-full bg-white/40" />
        <span className="text-[11px] tracking-[0.24em] uppercase text-white/50 font-body">
          Trusted by UK manufacturers
        </span>
      </div>
      <div className="relative overflow-hidden [mask-image:linear-gradient(to_right,transparent,black_10%,black_90%,transparent)]">
        <div className="marquee flex gap-16 whitespace-nowrap w-max">
          {[...logos, ...logos].map((l, i) =>
          <span
            key={i}
            className="font-heading italic text-white/40 text-2xl md:text-3xl">
            
              {l}
            </span>
          )}
        </div>
      </div>
    </section>);

}

// ------------------ SERVICES (What We Do) ------------------
function Services() {
  const items = [
  {
    icon: Workflow,
    title: "Process automation",
    body: "Eliminate the spreadsheet sprawl. We automate handovers, audits, CAPA workflows and the daily rituals that eat engineer time.",
    tag: "01"
  },
  {
    icon: Bot,
    title: "AI tools",
    body: "Pragmatic AI for the shop floor: defect triage assistants, SOP summarisers, shift-report copilots. Built to survive real plant data.",
    tag: "02"
  },
  {
    icon: BarChart3,
    title: "Data dashboards",
    body: "Plant-manager dashboards that actually get opened every morning. OEE, SPC, scrap rates, live and honest.",
    tag: "03"
  },
  {
    icon: Zap,
    title: "Web and app development",
    body: "Customer-facing sites and internal tooling. Next.js, React Native, built to specification and built to last.",
    tag: "04"
  },
  {
    icon: Palette,
    title: "Web and UX/UI design",
    body: "Considered design for industrial clients. No fluff, no stock photography of smiling handshakes. Just clarity.",
    tag: "05"
  },
  {
    icon: Shield,
    title: "Support and maintenance",
    body: "Retainers that keep your tools shipshape. Audit-ready documentation, version control, incident response.",
    tag: "06"
  }];


  // Panel coordinates (percentages of the 1920x1080 video frame).
  // Individual rects per panel so they can be calibrated independently.
  const DEFAULT_RECTS = [
  { x: 21.21, y: 21.22, w: 17.67, h: 27.56 },
  { x: 41.48, y: 21.70, w: 17.12, h: 26.70 },
  { x: 61.33, y: 21.09, w: 17.26, h: 27.31 },
  { x: 21.35, y: 52.96, w: 17.60, h: 26.83 },
  { x: 41.48, y: 53.45, w: 17.19, h: 26.58 },
  { x: 61.26, y: 53.33, w: 17.19, h: 26.46 },
  { x: 19.50, y: 88.40, w: 10.94, h: 10.27 },
  { x: 41.14, y: 88.03, w: 17.67, h: 11.24 },
  { x: 61.88, y: 88.15, w: 17.19, h: 11.00 }];


  const [rects, setRects] = React.useState(() => {
    try {
      const saved = localStorage.getItem("nb_service_rects");
      if (saved) {
        const parsed = JSON.parse(saved);
        // Merge with defaults so new entries (e.g. the Also bar) appear
        return DEFAULT_RECTS.map((d, i) => parsed[i] || d);
      }
    } catch (e) {}
    return DEFAULT_RECTS;
  });

  const [calibrate, setCalibrate] = React.useState(() => {
    try {
      return new URLSearchParams(location.search).has("calibrate");
    } catch (e) {
      return false;
    }
  });

  React.useEffect(() => {
    try {
      localStorage.setItem("nb_service_rects", JSON.stringify(rects));
    } catch (e) {}
  }, [rects]);

  const [alsoHover, setAlsoHover] = React.useState(false);
  const stageRef = React.useRef(null);

  const goToContact = (e) => {
    if (calibrate) {e.preventDefault();return;}
    const el = document.getElementById('contact');
    if (el) {
      e.preventDefault();
      el.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  };

  const alsoHoverProps = {
    onMouseEnter: () => !calibrate && setAlsoHover(true),
    onMouseLeave: () => setAlsoHover(false),
    onClick: goToContact
  };

  const startDrag = (e, i, mode) => {
    if (!calibrate) return;
    e.preventDefault();
    e.stopPropagation();
    const stage = stageRef.current;
    if (!stage) return;
    const stageRect = stage.getBoundingClientRect();
    const startX = e.clientX;
    const startY = e.clientY;
    const start = { ...rects[i] };

    const onMove = (ev) => {
      const dx = (ev.clientX - startX) / stageRect.width * 100;
      const dy = (ev.clientY - startY) / stageRect.height * 100;
      setRects((prev) => {
        const next = prev.slice();
        if (mode === "move") {
          next[i] = { ...start, x: start.x + dx, y: start.y + dy };
        } else if (mode === "resize") {
          next[i] = {
            ...start,
            w: Math.max(4, start.w + dx),
            h: Math.max(4, start.h + dy)
          };
        } else if (mode === "moveAll") {
          return prev.map((r) => ({ ...r, x: r.x + dx, y: r.y + dy }));
        } else if (mode === "sizeAll") {
          return prev.map((r) => ({
            ...r,
            w: Math.max(4, r.w + dx),
            h: Math.max(4, r.h + dy)
          }));
        }
        return next;
      });
    };
    const onUp = () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseup", onUp);
    };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);
  };

  const panelFor = (i) => {
    const r = rects[i];
    return {
      left: `${r.x}%`,
      top: `${r.y}%`,
      width: `${r.w}%`,
      height: `${r.h}%`
    };
  };

  return (
    <section
      id="services"
      data-screen-label="Services"
      className="relative overflow-hidden">
      
      {/* Section heading above the video stage */}
      <div className="relative px-5 md:px-8 lg:px-16 pt-12 md:pt-16 pb-8">
        <div className="max-w-7xl mx-auto flex items-end justify-between flex-wrap gap-6">
          <div>
            <div className="liquid-glass rounded-full px-3.5 py-1 text-xs font-medium text-white font-body inline-flex items-center gap-2">
              <span className="w-1 h-1 rounded-full bg-white/60" />
              What we do
            </div>
            <h2 className="mt-5 font-heading italic text-4xl md:text-5xl lg:text-6xl text-white tracking-tight leading-[0.9] max-w-3xl">
              Six capabilities,<br />one engineering mindset.
            </h2>
          </div>
          <p className="max-w-sm text-white/60 font-body font-light text-sm md:text-base">
            Every brief is different. Every deliverable is measured against the
            same standard: does it hold up on a Monday morning when the line is
            running?
          </p>
        </div>
      </div>

      {/* Video stage, full-width, with panel-aligned overlay cards.
                Outer is shorter than 16:9 so the dead space at the top of the
                source footage is cropped away cleanly. */}
      <div
        className="relative w-full overflow-hidden"
        style={{ aspectRatio: "16 / 7.47" }}>
        
        {/* Top fade from navy page bg down into the video */}
        <div
          className="absolute inset-x-0 top-0 z-20 pointer-events-none"
          style={{
            height: "18%",
            background:
            "linear-gradient(to bottom, hsl(213 45% 8%) 0%, hsla(213,45%,8%,0.85) 35%, hsla(213,45%,8%,0) 100%)"
          }} />
        
        <div
          className="absolute left-0 w-full"
          style={{ aspectRatio: "16 / 9", top: "-17%" /* of its own height */ }}>
          
        <video
            className="absolute inset-0 w-full h-full object-cover"
            src="assets/services.mp4"
            autoPlay
            muted
            loop
            playsInline
            preload="auto" />
          

        <div ref={stageRef} className="absolute inset-0">
        {items.map((it, i) => {
              const Ic = it.icon;
              const pos = panelFor(i);
              return (
                <article
                  key={it.title}
                  className="absolute group cursor-pointer"
                  style={{ ...pos, outline: calibrate ? "2px dashed #ff2d55" : undefined }}
                  onMouseDown={(e) => calibrate && startDrag(e, i, "move")}>
                  
              <div className="relative w-full h-full rounded-[1vw] p-[1.1vw] flex flex-col justify-between text-white overflow-hidden transition-all duration-500 hover:bg-white/[0.04]">
                {/* inner panel glow on hover */}
                <div
                      className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none"
                      style={{
                        background:
                        "radial-gradient(circle at 50% 30%, hsla(213,90%,55%,0.22), transparent 65%)"
                      }} />
                    

                <div className="flex items-start justify-between relative z-10">
                  <span
                        className="inline-flex items-center justify-center rounded-full bg-white/10 text-white backdrop-blur-sm"
                        style={{ width: "2vw", height: "2vw", minWidth: 26, minHeight: 26 }}>
                        
                    <Ic className="w-[48%] h-[48%]" />
                  </span>
                </div>

                <div className="relative z-10">
                  <h3
                        className="font-heading italic text-white leading-[1.05] tracking-tight"
                        style={{ fontSize: "clamp(13px, 1.4vw, 28px)" }}>
                        
                    {it.title}
                  </h3>
                  <p
                        className="mt-[0.4vw] text-white/70 font-body font-light leading-snug"
                        style={{ fontSize: "clamp(10px, 0.78vw, 14px)" }}>
                        
                    {it.body}
                  </p>
                  <div className="mt-[0.8vw] flex items-center justify-between">
                    <span
                          className="text-white/40 font-body uppercase tracking-[0.2em]"
                          style={{ fontSize: "clamp(8px, 0.58vw, 11px)" }}>
                          
                      Capability
                    </span>
                    <span
                          className="inline-flex items-center justify-center rounded-full bg-white/10 text-white/80 group-hover:bg-white group-hover:text-black transition-colors"
                          style={{ width: "1.7vw", height: "1.7vw", minWidth: 22, minHeight: 22 }}>
                          
                      <ArrowUpRight className="w-[48%] h-[48%]" stroke={2} />
                    </span>
                  </div>
                </div>
              </div>
            </article>);

            })}
        {/* Also-bar: 3 independently calibratable pieces across bottom terminals */}
        {rects[6] &&
            <article
              className="absolute cursor-pointer transition-all duration-300"
              style={{
                left: `${rects[6].x}%`,
                top: `${rects[6].y}%`,
                width: `${rects[6].w}%`,
                height: `${rects[6].h}%`,
                outline: calibrate ? "2px dashed #ff2d55" : undefined
              }}
              onMouseDown={(e) => calibrate && startDrag(e, 6, "move")}
              {...alsoHoverProps}>
              
            <div className="w-full h-full flex items-center justify-center">
              <span
                  className="inline-flex items-center justify-center rounded-full transition-colors duration-300"
                  style={{
                    width: "3vw", height: "3vw", minWidth: 32, minHeight: 32,
                    background: alsoHover ? "white" : "rgba(255,255,255,0.1)",
                    color: alsoHover ? "black" : "white"
                  }}>
                  
                <Database className="w-[48%] h-[48%]" />
              </span>
            </div>
          </article>
            }
        {rects[7] &&
            <article
              className="absolute cursor-pointer transition-all duration-300"
              style={{
                left: `${rects[7].x}%`,
                top: `${rects[7].y}%`,
                width: `${rects[7].w}%`,
                height: `${rects[7].h}%`,
                outline: calibrate ? "2px dashed #ff2d55" : undefined
              }}
              onMouseDown={(e) => calibrate && startDrag(e, 7, "move")}
              {...alsoHoverProps}>
              
            <div
                className="w-full h-full flex flex-col items-center justify-center text-center px-[0.6vw] transition-colors duration-300"
                style={{ color: alsoHover ? "white" : "rgba(255,255,255,0.95)" }}>
                
              <div
                  className="font-heading italic leading-[1.05] tracking-tight flex items-baseline justify-center flex-wrap gap-x-[0.35em]"
                  style={{ fontSize: "clamp(12px, 1.25vw, 24px)" }}>
                  
                <span>Also:</span>
                <RotatingWord
                    words={[
                    "quality systems",
                    "data pipelines",
                    "legacy integrations",
                    "SPC & MES hooks",
                    "SAP extracts",
                    "PLC read-outs"]
                    } />
                  
              </div>
              <div
                  className="mt-[0.35vw] font-body font-light leading-snug transition-colors duration-300"
                  style={{
                    fontSize: "clamp(9px, 0.78vw, 14px)",
                    color: alsoHover ? "rgba(255,255,255,0.85)" : "rgba(255,255,255,0.55)"
                  }}>
                  
                SPC · MES · SAP · PLC · CSV · MQTT · Modbus
              </div>
            </div>
          </article>
            }
        {rects[8] &&
            <article
              className="absolute cursor-pointer transition-all duration-300"
              style={{
                left: `${rects[8].x}%`,
                top: `${rects[8].y}%`,
                width: `${rects[8].w}%`,
                height: `${rects[8].h}%`,
                outline: calibrate ? "2px dashed #ff2d55" : undefined
              }}
              onMouseDown={(e) => calibrate && startDrag(e, 8, "move")}
              {...alsoHoverProps}>
              
            <div className="w-full h-full flex items-center justify-center">
              <div
                  className="rounded-full pl-[1vw] pr-[0.3vw] py-[0.3vw] inline-flex items-center gap-[0.5vw] font-medium transition-all duration-300"
                  style={{
                    fontSize: "clamp(10px, 0.85vw, 15px)",
                    background: alsoHover ? "white" : "rgba(255,255,255,0.1)",
                    color: alsoHover ? "black" : "white",
                    transform: alsoHover ? "translateY(-1px)" : "none"
                  }}>
                  
                Start a conversation
                <span
                    className="inline-flex items-center justify-center rounded-full transition-colors duration-300"
                    style={{
                      width: "1.9vw", height: "1.9vw", minWidth: 24, minHeight: 24,
                      background: alsoHover ? "black" : "white",
                      color: alsoHover ? "white" : "black"
                    }}>
                    
                  <ArrowUpRight className="w-[48%] h-[48%]" stroke={2} />
                </span>
              </div>
            </div>
          </article>
            }
        {calibrate && rects.map((r, i) =>
            <div
              key={"h" + i}
              className="absolute"
              style={{
                left: `calc(${r.x + r.w}% - 10px)`,
                top: `calc(${r.y + r.h}% - 10px)`,
                width: 20, height: 20,
                background: "#ff2d55", borderRadius: 4,
                cursor: "nwse-resize", zIndex: 50
              }}
              onMouseDown={(e) => startDrag(e, i, "resize")} />

            )}
        </div>
        </div>
        {calibrate &&
        <div
          className="absolute top-3 right-3 z-50 liquid-glass-strong rounded-xl p-3 text-[11px] font-mono text-white max-w-[280px]"
          style={{ whiteSpace: "pre-wrap" }}>
          
            <div className="flex items-center justify-between gap-2 mb-2">
              <strong>Calibration</strong>
              <div className="flex gap-1">
                <button
                className="px-2 py-0.5 rounded bg-white/10 hover:bg-white/20"
                onClick={() => setRects(DEFAULT_RECTS)}>
                reset</button>
                <button
                className="px-2 py-0.5 rounded bg-white/10 hover:bg-white/20"
                onClick={() => {
                  navigator.clipboard?.writeText(JSON.stringify(rects, null, 2));
                }}>
                copy</button>
                <button
                className="px-2 py-0.5 rounded bg-white/10 hover:bg-white/20"
                onClick={() => setCalibrate(false)}>
                close</button>
              </div>
            </div>
            <div>drag a card to move, red corner to resize</div>
            <div className="mt-2 opacity-70">{JSON.stringify(rects, null, 1)}</div>
          </div>
        }
        {!calibrate &&
        <button
          className="absolute bottom-3 right-3 z-50 text-[10px] font-mono text-white/30 hover:text-white/80 px-2 py-1 rounded bg-black/30"
          onClick={() => setCalibrate(true)}>
          calibrate</button>
        }
      </div>

      <div className="relative pb-28 md:pb-36" style={{ height: "10px", padding: "0px 0px 1px" }} />
    </section>);

}

// ------------------ POSITIONING ------------------
function Positioning() {
  return (
    <section
      id="about"
      data-screen-label="Positioning"
      className="relative pb-28 md:pb-36 px-5 md:px-8 lg:px-16 overflow-hidden">

      {/* Full-bleed background video — wrapper is taller than the visible section
           so the black letterbox baked into the top of the source gets clipped away
           instead of zoomed. Adjust top/bottom % to nudge the crop. */}
      <div className="absolute inset-0 overflow-hidden pointer-events-none">
        <div className="absolute left-0 right-0" style={{ top: "-18%", bottom: "0%" }}>
          <HeroVideo src="assets/about.mp4" objectPosition="center top" />
        </div>
        {/* Corner vignettes only — centre stays clean so copy/rotating tags stay legible */}
        <div
          className="absolute inset-0"
          style={{
            background:
            "radial-gradient(ellipse 70% 55% at 0% 0%, rgba(2,6,12,0.95) 0%, rgba(2,6,12,0.5) 40%, transparent 70%),\
               radial-gradient(ellipse 70% 55% at 100% 0%, rgba(2,6,12,0.95) 0%, rgba(2,6,12,0.5) 40%, transparent 70%),\
               radial-gradient(ellipse 70% 55% at 0% 100%, rgba(2,6,12,0.95) 0%, rgba(2,6,12,0.5) 40%, transparent 70%),\
               radial-gradient(ellipse 70% 55% at 100% 100%, rgba(2,6,12,0.95) 0%, rgba(2,6,12,0.5) 40%, transparent 70%)"



          }} />
        
      </div>

      <div className="max-w-7xl mx-auto relative">
        {/* Section intro so the block reads in context even before scrolling into the grid */}
        <div className="mb-14 max-w-4xl">
          <div className="inline-flex items-center gap-2 rounded-full liquid-glass px-3.5 py-1 text-xs font-medium text-white font-body">
            <span className="w-1 h-1 rounded-full bg-white/60" />
            About Northbound
          </div>
          <div className="mt-5 liquid-glass rounded-3xl px-6 md:px-8 py-6 md:py-8">
            <h2 className="font-heading italic text-4xl md:text-5xl lg:text-6xl text-white tracking-tight leading-[0.9]">
              Software that understands<br />a Monday morning.
            </h2>
            <p className="mt-6 max-w-2xl text-white/80 font-body font-light text-base md:text-lg leading-relaxed">
              We build AI and automation for the people who actually run
              factories. Founded by a quality engineer at Nissan Sunderland, so
              everything we ship is grounded in real shop-floor reality.
            </p>
          </div>
        </div>

        <div className="grid lg:grid-cols-12 gap-10">
        <div className="lg:col-span-5">
          <div className="liquid-glass rounded-2xl p-2 relative overflow-hidden">
            {/* TODO: replace with real shop-floor photography of Daniel / line */}
            <div className="aspect-[4/5] rounded-[14px] relative overflow-hidden">
              <div className="video-placeholder" />
              <div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/10 to-transparent" />
              {/* overlaid shop-floor HUD */}
              <div className="absolute inset-0 p-5 flex flex-col justify-between text-white/80 font-body">
                <div className="flex items-center justify-between text-[11px] uppercase tracking-[0.22em]">
                  <span>Line 04 · Body shop</span>
                  <span className="flex items-center gap-1.5">
                    <span className="w-1.5 h-1.5 rounded-full bg-emerald-400 pulse-dot" />
                    Live
                  </span>
                </div>
                <div>
                  <div className="text-[10px] uppercase tracking-[0.25em] text-white/50 mb-3">
                    Placeholder · founder portrait on shop floor
                  </div>
                  <div className="font-heading italic text-3xl leading-tight">
                    Built by engineers<br />who've stood on<br />the shop floor.
                  </div>
                  <div className="mt-3 grid grid-cols-3 gap-2 text-[11px]">
                    <Readout label="OEE" value="87.4%" />
                    <Readout label="Scrap" value="0.31%" />
                    <Readout label="Takt" value="58s" />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div className="lg:col-span-7 lg:pl-8 flex flex-col justify-center">
          <div className="liquid-glass rounded-3xl px-6 md:px-8 py-6 md:py-8">
            <h3 className="font-heading italic text-3xl md:text-4xl text-white tracking-tight leading-[1.05] max-w-2xl">
              Not another agency. An engineering partner.
            </h3>
            <p className="mt-6 text-white/80 font-body font-light text-base md:text-lg leading-relaxed max-w-2xl">
              Northbound builds AI and automation for the people who actually run
              factories. Our founder is a quality engineer at Nissan Sunderland,
              so the software we ship understands SPC, shift handovers, defect
              logs, and the reality of a busy line.
            </p>
            <p className="mt-5 text-white/75 font-body font-light text-base md:text-lg leading-relaxed max-w-2xl">
              We work with UK manufacturers on the tooling that genuinely moves
              the numbers: dashboards that plant managers open daily, quality
              systems engineers trust, and automations that survive the audit.
            </p>
          </div>

          <div className="mt-10 grid sm:grid-cols-3 gap-3">
            {[
              { k: "Shop-floor hours", v: "6,000+" },
              { k: "Sectors", v: "Auto · Aero · F&B" },
              { k: "Home base", v: "Sunderland" }].
              map((s) =>
              <div key={s.k} className="liquid-glass rounded-2xl p-4">
                <div className="text-[11px] tracking-[0.2em] uppercase text-white/50 font-body">
                  {s.k}
                </div>
                <div className="mt-1 font-heading italic text-2xl text-white">
                  {s.v}
                </div>
              </div>
              )}
          </div>
        </div>
        </div>
      </div>

      {/* Calibration overlay — tweak paddingTop + scrollMarginTop, persists to localStorage */}

    </section>);

}

function Readout({ label, value }) {
  return (
    <div className="liquid-glass rounded-xl px-3 py-2">
      <div className="text-[9px] uppercase tracking-[0.2em] text-white/50">
        {label}
      </div>
      <div className="font-heading italic text-base text-white">{value}</div>
    </div>);

}

// ------------------ RECENT WORK ------------------
function Work() {
  const cases = [
  {
    sector: "Automotive · Tier 1",
    title: "Defect triage copilot for a pressing plant",
    outcome: "41% faster root cause, £180k/yr in scrap avoided",
    stack: ["Next.js", "OpenAI", "MES hook", "SPC"],
    hue: 213
  },
  {
    sector: "Food & Beverage",
    title: "Live OEE dashboard across four lines",
    outcome: "Plant manager opens it daily, 12pp lift in OEE Q1",
    stack: ["Grafana", "Timescale", "PLC", "Modbus"],
    hue: 200
  },
  {
    sector: "Aerospace components",
    title: "Audit-ready quality system, paperless",
    outcome: "AS9100 audit passed with zero majors, two weeks early",
    stack: ["Supabase", "React", "DocuSign", "CAPA"],
    hue: 220
  }];


  return (
    <section
      id="work"
      data-screen-label="Work"
      className="relative py-28 md:py-36 px-5 md:px-8 lg:px-16">
      
      <div className="max-w-7xl mx-auto">
        <div className="flex items-end justify-between flex-wrap gap-6 mb-14">
          <div>
            <div className="liquid-glass rounded-full px-3.5 py-1 text-xs font-medium text-white font-body inline-flex items-center gap-2">
              Recent work
            </div>
            <h2 className="mt-5 font-heading italic text-4xl md:text-5xl lg:text-6xl text-white tracking-tight leading-[0.9] max-w-3xl">
              Outcomes first.<br />Always outcomes first.
            </h2>
          </div>
          <a
            href="#"
            className="rounded-full pl-4 pr-1.5 py-1.5 inline-flex items-center gap-2 text-sm font-medium text-white bg-white/5 hover:bg-white/10">
            
            View the full case book
            <span className="inline-flex items-center justify-center w-7 h-7 rounded-full bg-white text-black">
              <ArrowUpRight className="w-3.5 h-3.5" stroke={2} />
            </span>
          </a>
        </div>

        <div className="grid lg:grid-cols-3 gap-4">
          {cases.map((c, i) =>
          <article
            key={c.title}
            className="liquid-glass rounded-2xl p-3 flex flex-col group">
            
              <div className="relative aspect-[4/3] rounded-xl overflow-hidden">
                {/* TODO: replace with real case-study imagery */}
                <div
                className="absolute inset-0"
                style={{
                  background: `radial-gradient(circle at 30% 30%, hsla(${c.hue},80%,55%,0.55), transparent 55%), radial-gradient(circle at 70% 80%, hsla(${
                  c.hue - 15},70%,35%,0.7), transparent 60%), linear-gradient(180deg, hsl(213 45% 9%), hsl(213 60% 14%))`

                }} />
              
                <div className="absolute inset-0 scanlines" />
                <div className="absolute inset-0 p-4 flex items-start justify-between">
                  <span className="liquid-glass rounded-full px-2.5 py-1 text-[10px] uppercase tracking-[0.2em] text-white/80">
                    Case {String(i + 1).padStart(2, "0")}
                  </span>
                  <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white text-black group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-transform">
                    <ArrowUpRight className="w-4 h-4" stroke={2} />
                  </span>
                </div>
                <div className="absolute left-4 bottom-4 right-4">
                  <MiniChart hue={c.hue} />
                </div>
              </div>

              <div className="p-4 md:p-5 flex-1 flex flex-col">
                <div className="text-[11px] tracking-[0.2em] uppercase text-white/50 font-body">
                  {c.sector}
                </div>
                <h3 className="mt-2 font-heading italic text-white text-2xl leading-tight">
                  {c.title}
                </h3>
                <p className="mt-3 text-white/70 font-body font-light text-sm leading-relaxed">
                  {c.outcome}
                </p>

                <div className="mt-5 flex flex-wrap gap-1.5">
                  {c.stack.map((s) =>
                <span
                  key={s}
                  className="rounded-full px-2.5 py-1 text-[11px] text-white/70 bg-white/5 font-body">
                  
                      {s}
                    </span>
                )}
                </div>
              </div>
            </article>
          )}
        </div>
      </div>
    </section>);

}

function MiniChart({ hue = 213 }) {
  // Procedural line/bar chart for the card hero
  const bars = [32, 48, 40, 58, 54, 70, 66, 82, 78, 92, 88, 96];
  return (
    <div className="liquid-glass rounded-xl p-3">
      <div className="flex items-end justify-between">
        <div>
          <div className="text-[9px] uppercase tracking-[0.22em] text-white/50 font-body">
            Weekly output
          </div>
          <div className="font-heading italic text-white text-lg leading-none mt-0.5">
            +24.8%
          </div>
        </div>
        <div className="flex items-end gap-[3px] h-8">
          {bars.map((b, i) =>
          <span
            key={i}
            className="w-1.5 rounded-sm"
            style={{
              height: `${b}%`,
              background: `hsla(${hue}, 80%, ${40 + i % 5 * 5}%, 0.85)`
            }} />

          )}
        </div>
      </div>
    </div>);

}

// ------------------ WHY US ------------------
function WhyUs() {
  const items = [
  {
    title: "Shop-floor literacy",
    body: "We know what a 5-why looks like, what SPC chart rules trip, and why the Monday audit matters more than the roadmap.",
    icon: Wrench
  },
  {
    title: "British engineering rigour",
    body: "Documented, auditable, versioned. No cowboy shipping. No vendor lock-in. ISO-aware by default.",
    icon: Shield
  },
  {
    title: "Founder-led delivery",
    body: "You talk to the person who builds it. No account-management pass-the-parcel between brief and delivery.",
    icon: Compass
  },
  {
    title: "Boring where it matters",
    body: "Proven stacks, conservative choices, and rigorous testing. We save the novelty for the problems, not the tools.",
    icon: Settings
  }];


  return (
    <section
      id="process"
      data-screen-label="Why Us"
      className="relative py-28 md:py-36 px-5 md:px-8 lg:px-16">
      
      <div className="max-w-7xl mx-auto">
        <div className="grid lg:grid-cols-12 gap-10 mb-14">
          <div className="lg:col-span-5">
            <div className="liquid-glass rounded-full px-3.5 py-1 text-xs font-medium text-white font-body inline-flex items-center gap-2">
              Why Northbound
            </div>
            <h2 className="mt-5 font-heading italic text-4xl md:text-5xl lg:text-6xl text-white tracking-tight leading-[0.9]">
              Four reasons<br />teams stay.
            </h2>
          </div>
          <p className="lg:col-span-7 text-white/60 font-body font-light text-base md:text-lg leading-relaxed self-end">
            Most agencies write software for software people. We write it for
            the supervisor who has thirty minutes between shift briefings and a
            clipboard in one hand.
          </p>
        </div>

        <div className="grid md:grid-cols-2 gap-4">
          {items.map((it, i) => {
            const Ic = it.icon;
            return (
              <article
                key={it.title}
                className="liquid-glass rounded-2xl p-7 md:p-8 flex gap-6 items-start">
                
                <span className="inline-flex items-center justify-center w-12 h-12 rounded-full bg-white/5 text-white shrink-0">
                  <Ic className="w-5 h-5" />
                </span>
                <div>
                  <div className="flex items-center gap-3 mb-1">
                    <span className="text-[11px] tracking-[0.22em] text-white/40 font-body">
                      {String(i + 1).padStart(2, "0")}
                    </span>
                    <span className="h-px flex-1 bg-white/10" />
                  </div>
                  <h3 className="font-heading italic text-white text-2xl md:text-3xl leading-tight">
                    {it.title}
                  </h3>
                  <p className="mt-3 text-white/60 font-body font-light text-sm md:text-base leading-relaxed">
                    {it.body}
                  </p>
                </div>
              </article>);

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

}

// ------------------ STATS ------------------
function Stats() {
  const stats = [
  { v: "6k+", l: "Shop-floor hours logged by the founder" },
  { v: "£1.4m", l: "Scrap and rework prevented for clients in 2025" },
  { v: "12pp", l: "Average OEE uplift across deployments" },
  { v: "0", l: "Major findings on client audits to date" }];

  return (
    <section className="relative py-28 md:py-36 px-5 md:px-8 lg:px-16 overflow-hidden">
      <div className="absolute inset-0">
        <div className="video-placeholder scanlines" />
        {/* TODO: replace with cinematic stamping/press shot */}
        <div
          className="absolute inset-0"
          style={{
            background:
            "linear-gradient(to bottom, hsl(213 45% 8%) 0%, transparent 20%, transparent 80%, hsl(213 45% 8%) 100%)"
          }} />
        
      </div>

      <div className="relative max-w-7xl mx-auto">
        <div className="liquid-glass rounded-full px-3.5 py-1 text-xs font-medium text-white font-body inline-flex items-center gap-2">
          By the numbers
        </div>
        <h2 className="mt-5 font-heading italic text-4xl md:text-5xl lg:text-6xl text-white tracking-tight leading-[0.9] max-w-3xl">
          The numbers our<br />clients watch.
        </h2>

        <div className="mt-14 grid grid-cols-2 lg:grid-cols-4 gap-px bg-white/10 rounded-3xl overflow-hidden liquid-glass-strong">
          {stats.map((s, i) =>
          <div
            key={i}
            className="p-7 md:p-10 bg-[hsl(213_45%_8%/0.5)] backdrop-blur-sm">
            
              <div className="font-heading italic text-white text-5xl md:text-6xl lg:text-7xl leading-none tracking-tight">
                {s.v}
              </div>
              <div className="mt-4 text-white/60 font-body font-light text-sm leading-relaxed max-w-[18ch]">
                {s.l}
              </div>
            </div>
          )}
        </div>
      </div>
    </section>);

}

// ------------------ TESTIMONIALS ------------------
function Testimonials() {
  // TODO: replace with real client testimonials once consent is signed
  const quotes = [
  {
    quote:
    "Northbound turned our scrap logs into a weekly rhythm that actually changes behaviour on the floor. The first dashboard we've ever had that survived past January.",
    name: "Helen Marsden",
    role: "Operations Director",
    org: "Tier 1 automotive supplier"
  },
  {
    quote:
    "Daniel writes software like a quality engineer, because he is one. Our audit pack wrote itself. We passed AS9100 two weeks early with zero majors.",
    name: "Raj Sandhu",
    role: "Head of Quality",
    org: "Aerospace components, Midlands"
  },
  {
    quote:
    "We asked for a dashboard. We got a culture change. Our supervisors open Northbound's tools before they open their emails.",
    name: "Claire Whitfield",
    role: "Plant Manager",
    org: "Food & beverage, Yorkshire"
  }];

  return (
    <section className="relative py-28 md:py-36 px-5 md:px-8 lg:px-16">
      <div className="max-w-7xl mx-auto">
        <div className="flex items-end justify-between flex-wrap gap-6 mb-14">
          <div>
            <div className="liquid-glass rounded-full px-3.5 py-1 text-xs font-medium text-white font-body inline-flex items-center gap-2">
              From the line
            </div>
            <h2 className="mt-5 font-heading italic text-4xl md:text-5xl lg:text-6xl text-white tracking-tight leading-[0.9] max-w-3xl">
              What plant managers<br />actually say.
            </h2>
          </div>
        </div>

        <div className="grid lg:grid-cols-3 gap-4">
          {quotes.map((q, i) =>
          <figure
            key={i}
            className="liquid-glass rounded-2xl p-7 md:p-8 flex flex-col">
            
              <Quote className="w-6 h-6 text-white/40" />
              <blockquote className="mt-5 text-white/85 font-body font-light text-base md:text-lg leading-relaxed flex-1">
                {q.quote}
              </blockquote>
              <figcaption className="mt-8 pt-5 border-t border-white/10 flex items-center gap-3">
                <span className="inline-flex items-center justify-center w-10 h-10 rounded-full bg-white/10 font-heading italic text-white">
                  {q.name.split(" ").map((p) => p[0]).join("")}
                </span>
                <div>
                  <div className="text-sm text-white font-body font-medium">
                    {q.name}
                  </div>
                  <div className="text-xs text-white/50 font-body">
                    {q.role} · {q.org}
                  </div>
                </div>
              </figcaption>
            </figure>
          )}
        </div>
      </div>
    </section>);

}

// ------------------ CTA + FOOTER ------------------
function CTAFooter() {
  return (
    <section
      id="contact"
      data-screen-label="CTA + Footer"
      className="relative pt-28 md:pt-36 px-5 md:px-8 lg:px-16 pb-10">
      
      <div className="max-w-7xl mx-auto">
        <div className="relative liquid-glass-strong rounded-[32px] overflow-hidden p-8 md:p-14 lg:p-20">
          <div className="absolute inset-0 -z-10">
            <div className="video-placeholder" />
            <div className="absolute inset-0 bg-[hsl(213_45%_8%/0.4)]" />
          </div>

          <div className="grid lg:grid-cols-12 gap-10 items-end">
            <div className="lg:col-span-8">
              <div className="liquid-glass rounded-full px-3.5 py-1 text-xs font-medium text-white font-body inline-flex items-center gap-2 w-fit">
                Ready when you are
              </div>
              <h2 className="mt-5 font-heading italic text-5xl md:text-7xl lg:text-8xl text-white tracking-tight leading-[0.85]">
                Let's find<br />your true north.
              </h2>
              <p className="mt-6 max-w-xl text-white/70 font-body font-light text-base md:text-lg leading-relaxed">
                A 30-minute discovery call. No slides, no sales deck. Tell us
                what's breaking on the floor and we'll tell you honestly
                whether software is the right answer.
              </p>
            </div>
            <div className="lg:col-span-4 flex flex-col gap-3">
              <a
                href="mailto:daniel@northboundautomations.co.uk"
                className="liquid-glass-strong rounded-full pl-5 pr-2 py-2 inline-flex items-center justify-between gap-3 text-sm font-medium text-white">
                
                Book a discovery call
                <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white text-black">
                  <ArrowUpRight className="w-4 h-4" stroke={2} />
                </span>
              </a>
              <a
                href="#"
                className="rounded-full pl-5 pr-2 py-2 inline-flex items-center justify-between gap-3 text-sm font-medium text-white/90 bg-white/5 hover:bg-white/10">
                
                View pricing
                <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-white/10">
                  <ArrowUpRight className="w-4 h-4" stroke={2} />
                </span>
              </a>
              <div className="liquid-glass rounded-2xl p-4 text-sm text-white/70 font-body">
                <div className="flex items-center gap-2 text-[11px] uppercase tracking-[0.22em] text-white/50">
                  <span className="w-1.5 h-1.5 rounded-full bg-emerald-400 pulse-dot" />
                  Replies within one working day
                </div>
                <div className="mt-2 font-heading italic text-white text-lg">
                  daniel@northboundautomations.co.uk
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* FOOTER */}
        <footer className="mt-14 pt-10 border-t border-white/10 grid lg:grid-cols-12 gap-8">
          <div className="lg:col-span-5">
            <div className="flex items-center gap-2">
              <span className="relative inline-flex items-center justify-center w-9 h-9 rounded-full liquid-glass">
                <Compass className="w-4 h-4 text-white" />
              </span>
              <span className="font-heading italic text-2xl text-white leading-none">
                Northbound
              </span>
            </div>
            <p className="mt-5 text-white/60 font-body font-light text-sm max-w-sm leading-relaxed">
              Northbound Automations Ltd · Registered in England &amp; Wales,
              April 2026. Based in Sunderland, serving UK manufacturing.
            </p>
          </div>

          <FooterCol
            title="Services"
            links={[
            "Process automation",
            "AI tools",
            "Data dashboards",
            "Web &amp; app",
            "UX/UI design",
            "Support"]
            } />
          
          <FooterCol
            title="Company"
            links={["About", "Work", "Process", "Pricing", "Contact"]} />
          
          <FooterCol
            title="Contact"
            links={[
            "daniel@northboundautomations.co.uk",
            "+44 (0)7000 000 000",
            "Sunderland, NE England",
            "LinkedIn"]
            } />
          
        </footer>

        <div className="mt-10 pt-6 border-t border-white/5 flex flex-wrap items-center justify-between gap-4 text-xs text-white/40 font-body">
          <div>© 2026 Northbound Automations Ltd. All rights reserved.</div>
          <div className="flex items-center gap-5">
            <a href="#" className="hover:text-white/70">Privacy</a>
            <a href="#" className="hover:text-white/70">Terms</a>
            <a href="#" className="hover:text-white/70">Modern Slavery Statement</a>
          </div>
        </div>
      </div>
    </section>);

}

function FooterCol({ title, links }) {
  return (
    <div className="lg:col-span-2">
      <div className="text-[11px] tracking-[0.22em] uppercase text-white/40 font-body">
        {title}
      </div>
      <ul className="mt-4 grid gap-2.5">
        {links.map((l) =>
        <li key={l}>
            <a
            href="#"
            dangerouslySetInnerHTML={{ __html: l }}
            className="text-sm text-white/70 hover:text-white font-body font-light" />
          
          </li>
        )}
      </ul>
    </div>);

}

// ------------------ SECTION CALIBRATOR ------------------
// Global overlay that lets you nudge padding-top + scroll-margin-top of any
// section with id, and persists the values to localStorage. The topmost
// section currently in view is the one being edited.
const CAL_SECTIONS = [
{ id: "home", label: "Home" },
{ id: "services", label: "Services" },
{ id: "about", label: "About" },
{ id: "work", label: "Work" },
{ id: "process", label: "Process" },
{ id: "contact", label: "Contact" }];

const CAL_DEFAULTS = {
  home: { pt: 0, smt: 0 },
  services: { pt: 0, smt: 0 },
  about: { pt: 40, smt: 0 },
  work: { pt: 0, smt: 0 },
  process: { pt: 0, smt: 0 },
  contact: { pt: 0, smt: 0 }
};
function SectionCalibrator() {
  const [values, setValues] = React.useState(() => {
    try {
      const v = JSON.parse(localStorage.getItem("nb_cal_values") || "null");
      return v || CAL_DEFAULTS;
    } catch {return CAL_DEFAULTS;}
  });
  const [activeId, setActiveId] = React.useState("home");

  // Persist
  React.useEffect(() => {
    try {localStorage.setItem("nb_cal_values", JSON.stringify(values));} catch {}
  }, [values]);

  // Apply inline styles to each section
  React.useEffect(() => {
    CAL_SECTIONS.forEach(({ id }) => {
      const el = document.getElementById(id);
      if (!el) return;
      const v = values[id] || { pt: 0, smt: 0 };
      // only override if non-zero OR always (to reset back cleanly)
      el.style.paddingTop = v.pt ? `${v.pt}px` : "";
      el.style.scrollMarginTop = `${v.smt}px`;
    });
  }, [values]);

  // Detect which section is topmost visible
  React.useEffect(() => {
    const onScroll = () => {
      let best = { id: "home", dist: Infinity };
      CAL_SECTIONS.forEach(({ id }) => {
        const el = document.getElementById(id);
        if (!el) return;
        const r = el.getBoundingClientRect();
        // section whose top is just above viewport top or just entering
        const d = Math.abs(r.top - 100);
        if (r.bottom > 80 && d < best.dist) best = { id, dist: d };
      });
      if (best.id !== activeId) setActiveId(best.id);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, [activeId]);

  const v = values[activeId] || { pt: 0, smt: 0 };
  const activeLabel = CAL_SECTIONS.find((s) => s.id === activeId)?.label || activeId;
  const nudge = (k, d) => setValues((prev) => ({
    ...prev,
    [activeId]: { ...(prev[activeId] || { pt: 0, smt: 0 }), [k]: (prev[activeId]?.[k] ?? 0) + d }
  }));
  const resetOne = () => setValues((prev) => ({
    ...prev, [activeId]: CAL_DEFAULTS[activeId] || { pt: 0, smt: 0 }
  }));
  const copyAll = () => {
    try {navigator.clipboard?.writeText(JSON.stringify(values, null, 2));} catch {}
  };

  return (
    <div className="fixed bottom-4 right-4 z-[60] liquid-glass-strong rounded-xl p-3 text-[11px] font-mono text-white w-[260px] select-none">
      <div className="flex items-center justify-between mb-2">
        <strong>Calibrate · {activeLabel}</strong>
        <div className="flex gap-1">
          <button className="px-2 py-0.5 rounded bg-white/10 hover:bg-white/20" onClick={resetOne}>reset</button>
          <button className="px-2 py-0.5 rounded bg-white/10 hover:bg-white/20" onClick={copyAll}>copy all</button>
        </div>
      </div>
      {[["pt", "padding-top", 4], ["smt", "scroll-margin-top", 4]].map(([k, label, step]) =>
      <div key={k} className="flex items-center justify-between gap-2 mb-1">
          <span className="opacity-70">{label}</span>
          <div className="flex items-center gap-1">
            <button className="w-6 h-6 rounded bg-white/10 hover:bg-white/20" onClick={() => nudge(k, -step)}>-</button>
            <span className="w-10 text-center tabular-nums">{v[k] ?? 0}</span>
            <button className="w-6 h-6 rounded bg-white/10 hover:bg-white/20" onClick={() => nudge(k, step)}>+</button>
          </div>
        </div>
      )}
      <div className="mt-2 flex flex-wrap gap-1">
        {CAL_SECTIONS.map((s) =>
        <button
          key={s.id}
          onClick={() => document.querySelector(`a[href="#${s.id}"]`)?.click()}
          className={`px-2 py-0.5 rounded text-[10px] ${s.id === activeId ? "bg-white/25" : "bg-white/10 hover:bg-white/20"}`}>
            {s.label}
          </button>
        )}
      </div>
    </div>);

}

// ------------------ APP ------------------
function App() {
  return (
    <div className="relative">
      <Nav />
      <main>
        <Hero />
        <LogoStrip />
        <Services />
        <Positioning />
        <Work />
        <WhyUs />
        <Stats />
        <Testimonials />
        <CTAFooter />
      </main>
      <SectionCalibrator />
    </div>);

}

const __nb_root_el = document.getElementById("root");
if (__nb_root_el) {
  if (!window.__nb_root) window.__nb_root = ReactDOM.createRoot(__nb_root_el);
  window.__nb_root.render(<App />);
}