const navStyles = {
  wrap: {
    position: 'sticky', top: 0, zIndex: 50,
    borderBottom: '1px solid var(--line-soft)',
    background: 'rgba(255,255,255,0.82)',
    backdropFilter: 'saturate(140%) blur(14px)',
    WebkitBackdropFilter: 'saturate(140%) blur(14px)',
    transition: 'transform .28s ease',
    willChange: 'transform',
  },
  inner: {
    maxWidth: 1280, margin: '0 auto',
    padding: '14px 32px',
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    gap: 32,
  },
  logo: { display: 'flex', alignItems: 'center', gap: 10 },
  logoMark: {
    width: 28, height: 28, borderRadius: 8, background: 'var(--blue)',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    color: '#fff', fontWeight: 600, fontSize: 14, letterSpacing: '-0.02em',
  },
  logoText: { fontSize: 17, fontWeight: 600, letterSpacing: '-0.02em' },
  links: { display: 'flex', alignItems: 'center', gap: 28, fontSize: 14, color: 'var(--ink-soft)', fontWeight: 500 },
  // `color` is duplicated inline on each <a> (not just on the parent <nav>)
  // so it beats `legal.css`'s global `a { color: var(--blue); }` rule on
  // the hub pages (services / who-we-serve / virtual-assistants) which load
  // legal.css for their shared layout. Without this, the nav links there
  // render blue instead of ink-soft.
  link: { cursor: 'pointer', transition: 'color .15s', color: 'var(--ink-soft)', position: 'relative' },
  // Active state: links the user is currently on. Page-level links match on
  // pathname; section-anchor links match on scroll-spy (IntersectionObserver).
  // We render the underline as a pseudo-ish absolute span so it doesn't shift
  // layout on toggle and works consistently with the inline hover handlers.
  linkActive: { color: 'var(--blue)' },
  linkActiveBar: {
    position: 'absolute', left: 0, right: 0, bottom: -6, height: 2,
    background: 'var(--blue)', borderRadius: 2,
  },
  right: { display: 'flex', alignItems: 'center', gap: 12 },
  signin: { fontSize: 14, fontWeight: 500, color: 'var(--ink-soft)', cursor: 'pointer' },
  cta: {
    background: 'var(--ink)', color: 'var(--paper)',
    padding: '12px 20px', borderRadius: 12,
    fontSize: 14, fontWeight: 500,
    display: 'inline-flex', alignItems: 'center', gap: 8,
    transition: 'transform .15s, background .2s',
  },
};

function BMMark({ size = 28, showWordmark = false }) {
  if (showWordmark) {
    return <BMLogo height={size} tone="blue" />;
  }
  return (
    <img src="brand/bluemoso-icon-256x256.png" alt="BlueMoso" width={size} height={size} style={{ display: 'block' }} />
  );
}

function Nav({ baseHref = '', localHashes = null }) {
  // Both "Book a call" buttons (desktop + mobile drawer) use data-booking-modal-trigger
  // so the global BookingModal delegated handler catches the click and opens
  // the modal — the same behavior on every page (homepage, ICP, hubs, playbook).
  // The href fallback (#cta / index.html#cta) only fires if BookingModal.jsx
  // hasn't loaded yet, which would mean the page is broken anyway.

  // `localHashes` lets a sub-page (e.g. an ICP page) declare which #anchors
  // already exist on the current page. Those stay as same-page hashes;
  // everything else gets the `baseHref` prefix so it routes back to the homepage.
  // When `localHashes` is null, fall back to legacy behaviour (apply baseHref to all #anchors).
  const isLocalHash = (href) => {
    if (!href.startsWith('#')) return false;
    if (localHashes == null) return !baseHref;
    return localHashes.indexOf(href) !== -1;
  };
  const resolve = (href) => {
    if (isLocalHash(href)) return href;
    return (baseHref && href.startsWith('#')) ? baseHref + href : href;
  };
  const items = [
    // "Home" only shows on sub-pages (baseHref is set). On the homepage itself,
    // the logo in the top-left already serves as the home link, so showing
    // another "Home" item would be redundant.
    ...(baseHref ? [{ label: 'Home', href: baseHref }] : []),
    { label: 'Who we serve', href: 'who-we-serve.html' },
    { label: 'Services', href: 'services.html' },
    { label: 'How it works', href: '#matching' },
    { label: 'Pricing', href: '#packages' },
  ];
  // Secondary links — only shown in the mobile drawer, not the desktop nav.
  // Referrals hidden from navigation while the program is paused; page stays
  // accessible via direct URL (/referrals.html) but is noindex'd.
  const drawerExtras = [
    { label: 'The human in the loop', href: 'human-in-the-loop.html' },
    { label: 'Story', href: '#story' },
    { label: 'FAQ', href: '#faq' },
    { label: 'Playbook', href: 'playbook.html' },
    { label: 'Apply as a VA', href: 'apply.html' },
  ];
  const [drawerOpen, setDrawerOpen] = React.useState(false);
  React.useEffect(() => {
    document.body.style.overflow = drawerOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [drawerOpen]);

  // Hide on scroll-down, show on scroll-up
  const [hidden, setHidden] = React.useState(false);
  React.useEffect(() => {
    let lastY = window.scrollY;
    let ticking = false;
    const onScroll = () => {
      if (ticking) return;
      ticking = true;
      window.requestAnimationFrame(() => {
        const y = window.scrollY;
        const delta = y - lastY;
        if (drawerOpen) {
          setHidden(false);
        } else if (y < 80) {
          setHidden(false);
        } else if (delta > 6) {
          setHidden(true);
        } else if (delta < -6) {
          setHidden(false);
        }
        lastY = y;
        ticking = false;
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [drawerOpen]);

  // Active nav item: page-level links match on pathname (services.html etc.);
  // section anchors (#matching, #packages) light up via scroll-spy when those
  // sections actually exist on the current page. We re-query the DOM on each
  // scroll tick because section components are Babel-rendered after Nav mounts,
  // so they may not exist when the effect first runs.
  const [activeHref, setActiveHref] = React.useState(null);
  React.useEffect(() => {
    const currentPage = (() => {
      const last = (window.location.pathname.split('/').pop() || '').trim();
      return last || 'index.html';
    })();
    const pageMatch = items.find(i => {
      if (i.href.startsWith('#')) return false;
      const file = i.href.split('#')[0].split('/').pop();
      return file === currentPage;
    });
    const sectionItems = items.filter(i => i.href.startsWith('#') && isLocalHash(i.href));

    const update = () => {
      // Threshold: a section counts as "current" once its top has crossed
      // below the sticky nav (~80px). Pick the section whose top is closest
      // to (but past) that threshold.
      const navThreshold = 120;
      let bestHref = null;
      let bestTop = -Infinity;
      for (const s of sectionItems) {
        const el = document.getElementById(s.href.slice(1));
        if (!el) continue;
        const top = el.getBoundingClientRect().top;
        if (top <= navThreshold && top > bestTop) {
          bestTop = top;
          bestHref = s.href;
        }
      }
      // If we're near the bottom of the page, force the last section to be
      // active so users can scroll into Pricing and still see it highlight.
      const nearBottom = window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 8;
      if (nearBottom && sectionItems.length) {
        const last = sectionItems[sectionItems.length - 1];
        if (document.getElementById(last.href.slice(1))) bestHref = last.href;
      }
      setActiveHref(bestHref || (pageMatch ? pageMatch.href : null));
    };
    update();
    let ticking = false;
    const onScroll = () => {
      if (ticking) return;
      ticking = true;
      window.requestAnimationFrame(() => { update(); ticking = false; });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    // Re-check after a tick in case section components are still mounting
    const t1 = setTimeout(update, 250);
    const t2 = setTimeout(update, 1000);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      clearTimeout(t1);
      clearTimeout(t2);
    };
  }, [baseHref, localHashes]);

  // Focus trap + Esc + body scroll lock for mobile drawer
  React.useEffect(() => {
    if (!drawerOpen) return;
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    const panel = document.querySelector('.bm-mobile-drawer-panel');
    const focusables = panel ? panel.querySelectorAll('a, button') : [];
    const first = focusables[0];
    const last = focusables[focusables.length - 1];
    if (first) first.focus();
    const onKey = (e) => {
      if (e.key === 'Escape') { setDrawerOpen(false); return; }
      if (e.key === 'Tab' && focusables.length) {
        if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
        else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = prevOverflow; };
  }, [drawerOpen]);

  return (
    <React.Fragment>
    <header style={{ ...navStyles.wrap, transform: hidden ? 'translateY(-100%)' : 'translateY(0)' }}>
      <div style={navStyles.inner} className="bm-nav-inner">
        <a href={baseHref ? baseHref + '#top' : '#top'} style={navStyles.logo}>
          <BMLogo height={38} tone="blue" />
        </a>
        <nav style={navStyles.links} className="bm-nav-links-desktop">
          {items.map(i => {
            const isActive = activeHref === i.href;
            return (
              <a key={i.label} href={resolve(i.href)}
                 style={{ ...navStyles.link, ...(isActive ? navStyles.linkActive : {}) }}
                 aria-current={isActive ? 'page' : undefined}
                 onMouseEnter={e => { if (!isActive) e.currentTarget.style.color = 'var(--ink)'; }}
                 onMouseLeave={e => { if (!isActive) e.currentTarget.style.color = 'var(--ink-soft)'; }}>
                {i.label}
                {isActive && <span style={navStyles.linkActiveBar} aria-hidden="true" />}
              </a>
            );
          })}
        </nav>
        <div style={navStyles.right}>
          <a href={resolve('#cta')} data-booking-modal-trigger data-booking-source="nav_book_call" style={navStyles.cta} className="bm-nav-links-desktop"
             onMouseEnter={e => e.currentTarget.style.background = 'var(--blue)'}
             onMouseLeave={e => e.currentTarget.style.background = 'var(--ink)'}>
            Book a call <Icon name="arrow" size={16} />
          </a>
          <button className="bm-nav-hamburger" onClick={() => setDrawerOpen(true)} aria-label="Open menu" style={{
            width: 40, height: 40, borderRadius: 8,
            display: 'none', alignItems: 'center', justifyContent: 'center',
            color: 'var(--ink)',
          }}>
            <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M3 6h14M3 10h14M3 14h14" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
          </button>
        </div>
      </div>
    </header>
    <div className={`bm-mobile-drawer${drawerOpen ? ' open' : ''}`} onClick={(e) => { if (e.target === e.currentTarget) setDrawerOpen(false); }} role="dialog" aria-modal="true" aria-label="Site menu">
        <div className="bm-mobile-drawer-panel">
          <button className="bm-mobile-drawer-close" onClick={() => setDrawerOpen(false)} aria-label="Close">
            <svg width="18" height="18" viewBox="0 0 18 18" fill="none"><path d="M4 4l10 10M14 4L4 14" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
          </button>
          {[...items, ...drawerExtras].map(i => {
            const isActive = activeHref === i.href;
            return (
              <a key={i.label} href={resolve(i.href)} className="bm-mobile-drawer-link"
                 aria-current={isActive ? 'page' : undefined}
                 style={isActive ? { color: 'var(--blue)', fontWeight: 600 } : undefined}
                 onClick={() => setDrawerOpen(false)}>
                {i.label}
                <svg width="14" height="14" viewBox="0 0 16 16" fill="none" style={{ opacity: isActive ? 0.7 : 0.4 }}><path d="M6 4l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
              </a>
            );
          })}
          <a href={resolve('#cta')} data-booking-modal-trigger data-booking-source="nav_drawer_book_call" className="bm-mobile-drawer-cta"
             onClick={() => setDrawerOpen(false)}>Book a call</a>
        </div>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, { Nav, BMMark });
