/* =====================================================================
   Core v2 — MagButton, Pill, SectionHead, Logo, Nav, TodIndicator, useReveal
   ===================================================================== */
const { useEffect: useEfCo, useRef: useRefCo, useState: useStCo } = React;

function useReveal(ref, opts = {}) {
  useEfCo(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(entries => {
      entries.forEach(e => { if (e.isIntersecting) { el.classList.add('is-in'); io.unobserve(el); } });
    }, { threshold: opts.threshold || 0.1, rootMargin: opts.rootMargin || '0px 0px -6% 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);
}

function MagButton({ children, variant = 'primary', size = 'md', onClick, href, style = {}, full, iconAfter = '→', noArrow }) {
  const ref = useRefCo(null), labelRef = useRefCo(null);
  const [pressed, setPressed] = useStCo(false);
  useEfCo(() => {
    const el = ref.current; if (!el || window.matchMedia('(hover:none)').matches) return;
    const onMove = e => {
      const r = el.getBoundingClientRect(), cx = r.left+r.width/2, cy = r.top+r.height/2;
      const dx = e.clientX-cx, dy = e.clientY-cy, d = Math.hypot(dx,dy), range = 110;
      if (d < range) {
        const f = (1-d/range)*0.3;
        el.style.transform = `translate(${dx*f}px,${dy*f}px)`;
        if (labelRef.current) labelRef.current.style.transform = `translate(${dx*f*0.6}px,${dy*f*0.6}px)`;
      } else { el.style.transform=''; if(labelRef.current)labelRef.current.style.transform=''; }
    };
    const onLeave = () => { el.style.transform=''; if(labelRef.current)labelRef.current.style.transform=''; };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseleave', onLeave);
    return () => { window.removeEventListener('mousemove',onMove); window.removeEventListener('mouseleave',onLeave); };
  }, []);
  const sizes = { sm:{padding:'8px 14px',fontSize:11}, md:{padding:'14px 22px',fontSize:13}, lg:{padding:'18px 28px',fontSize:14} };
  const base = { display:full?'flex':'inline-flex', width:full?'100%':undefined, justifyContent:'center', alignItems:'center', gap:10,
    fontFamily:'var(--font-mono)', fontWeight:500, letterSpacing:'0.12em', textTransform:'uppercase',
    border:'1px solid var(--border-strong)', cursor:'pointer', userSelect:'none',
    transition:'transform .25s var(--ease-out),background .18s,color .18s,border-color .18s,box-shadow .25s',
    position:'relative', overflow:'hidden', textDecoration:'none', ...sizes[size], ...style };
  const variants = {
    primary: { background: pressed?'var(--fg-1)':'var(--accent)', color:pressed?'var(--bg)':'var(--accent-ink)', border:'1px solid var(--accent)', boxShadow:pressed?'none':'0 0 40px -12px color-mix(in oklab, var(--accent) 80%, transparent)' },
    ghost:   { background:'transparent', color:'var(--fg-1)' },
    ink:     { background:'var(--fg-1)', color:'var(--bg)', border:'1px solid var(--fg-1)' },
  };
  const Tag = href?'a':'button';
  return (
    <Tag ref={ref} href={href} onClick={onClick}
      onMouseDown={()=>setPressed(true)} onMouseUp={()=>setPressed(false)} onMouseLeave={()=>setPressed(false)}
      style={{...base,...variants[variant]}}>
      <span ref={labelRef} style={{position:'relative',zIndex:1,display:'inline-flex',alignItems:'center',gap:10,transition:'transform .25s var(--ease-out)'}}>
        {children}{!noArrow&&iconAfter&&<span style={{opacity:.75}}>{iconAfter}</span>}
      </span>
    </Tag>
  );
}

function Pill({ children, dot, color }) {
  return (
    <span style={{ display:'inline-flex', alignItems:'center', gap:8, padding:'5px 10px',
      border:'1px solid var(--border-strong)', borderRadius:999,
      fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.14em', textTransform:'uppercase',
      color:color||'var(--fg-2)', background:'color-mix(in oklab, var(--bg) 40%, transparent)', backdropFilter:'blur(6px)' }}>
      {dot && <span style={{width:6,height:6,borderRadius:3,background:'var(--accent)',boxShadow:'0 0 8px var(--accent)',animation:'mwBreathe 2s ease-in-out infinite'}}/>}
      {children}
    </span>
  );
}

function SectionHead({ eyebrow, title, kicker, right }) {
  const ref = useRefCo(null); useReveal(ref);
  return (
    <div ref={ref} className="mw-reveal" style={{ display:'flex', alignItems:'flex-end', justifyContent:'space-between',
      gap:24, marginBottom:40, borderBottom:'1px solid var(--border)', paddingBottom:20, flexWrap:'wrap' }}>
      <div style={{display:'flex',flexDirection:'column',gap:14,flex:'1 1 300px',minWidth:0}}>
        {eyebrow && <div className="mw-eyebrow" style={{display:'inline-flex',alignItems:'center',gap:10}}>
          <span style={{width:6,height:6,background:'var(--accent)',display:'inline-block'}}/>
          {eyebrow}
        </div>}
        <h2 style={{margin:0,fontFamily:'var(--font-display)',fontSize:'clamp(32px,5.2vw,64px)',fontWeight:500,lineHeight:0.95,letterSpacing:'-0.035em'}}>{title}</h2>
        {kicker && <div style={{color:'var(--fg-3)',maxWidth:640,fontSize:'clamp(14px,1.6vw,17px)',lineHeight:1.5,textWrap:'pretty'}}>{kicker}</div>}
      </div>
      {right && <div style={{flexShrink:0}}>{right}</div>}
    </div>
  );
}

function Logo({ size = 28, wordmark = true }) {
  return (
    <div style={{display:'flex',alignItems:'center',gap:10,color:'var(--fg-1)'}}>
      <svg width={size} height={size} viewBox="0 0 68 68" fill="none" shapeRendering="geometricPrecision" style={{flexShrink:0}}>
        <circle cx="34" cy="34" r="31" stroke="currentColor" strokeWidth="2"/>
        <path d="M19 48 L19 22 L34 35 L49 22 L49 48" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
        <path d="M13 22 L55 22" stroke="currentColor" strokeWidth="2.25" strokeLinecap="round"/>
        <circle cx="34" cy="34" r="1.75" fill="var(--accent)"/>
      </svg>
      {wordmark && (
        <div style={{display:'flex',flexDirection:'column',lineHeight:1}}>
          <span style={{fontFamily:'var(--font-display)',fontWeight:600,fontSize:13,letterSpacing:'-0.01em',whiteSpace:'nowrap'}}>MIDWEST&nbsp;TECHNOLOGIES</span>
          <span style={{fontFamily:'var(--font-mono)',fontSize:8,letterSpacing:'0.22em',opacity:0.6,marginTop:4}}>OKLAHOMA&nbsp;STATE&nbsp;·&nbsp;STUDIO</span>
        </div>
      )}
    </div>
  );
}

function TodIndicator({ tod, setTod, auto, setAuto }) {
  const labels = { night:'◐ NIGHT', sunrise:'◓ SUNRISE', day:'◑ DAY', sunset:'◒ SUNSET' };
  const [open, setOpen] = useStCo(false);
  return (
    <div style={{position:'relative'}}>
      <button onClick={()=>setOpen(!open)} style={{
        padding:'6px 10px', background:'transparent', border:'1px solid var(--border-strong)',
        color:'var(--fg-2)', fontFamily:'var(--font-mono)', fontSize:10, letterSpacing:'0.14em',
        cursor:'pointer', textTransform:'uppercase', display:'flex', alignItems:'center', gap:6 }}>
        <span style={{width:6,height:6,background:'var(--accent)',display:'inline-block',boxShadow:'0 0 8px var(--accent)'}}/>
        {labels[tod]}{auto&&<span style={{opacity:.5}}>&nbsp;· AUTO</span>}
      </button>
      {open && (
        <div style={{position:'absolute',right:0,top:'calc(100% + 6px)',background:'var(--bg-elev-2)',
          border:'1px solid var(--border-strong)',zIndex:100,minWidth:180,padding:6,boxShadow:'0 20px 48px rgba(0,0,0,0.4)'}}>
          <div style={{padding:'6px 10px',fontFamily:'var(--font-mono)',fontSize:9,letterSpacing:'0.16em',color:'var(--fg-4)'}}>— THEME</div>
          {Object.entries(labels).map(([k,l])=>(
            <button key={k} onClick={()=>{setTod(k);setAuto(false);setOpen(false);}} style={{
              display:'flex',width:'100%',padding:'8px 10px',background:tod===k?'var(--accent)':'transparent',
              color:tod===k?'var(--accent-ink)':'var(--fg-2)',border:'none',
              fontFamily:'var(--font-mono)',fontSize:11,letterSpacing:'0.1em',cursor:'pointer',textAlign:'left'}}>{l}</button>
          ))}
          <button onClick={()=>{setAuto(true);setOpen(false);}} style={{
            display:'flex',width:'100%',padding:'8px 10px',background:auto?'var(--fg-1)':'transparent',
            color:auto?'var(--bg)':'var(--fg-3)',border:'none',borderTop:'1px solid var(--border)',
            fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.14em',cursor:'pointer',textAlign:'left',marginTop:4}}>
            {auto?'✓ ':'↻ '}AUTO (BY TIME)
          </button>
        </div>
      )}
    </div>
  );
}

function Nav({ tod, setTod, auto, setAuto }) {
  const [open, setOpen] = useStCo(false);
  const [scrolled, setScrolled] = useStCo(false);
  const triggerRef = useRefCo(null);
  const closeBtnRef = useRefCo(null);
  const panelRef = useRefCo(null);
  const headerRef = useRefCo(null);
  useEfCo(() => {
    const fn = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', fn, {passive:true}); fn();
    return () => window.removeEventListener('scroll', fn);
  }, []);
  // Keep --mw-nav-h synced with the live header height. The header pads
  // 14px → 8px at scrollY > 40 (~16px shrink), and the sub-strip below
  // pins to top: var(--mw-nav-h, 57px). Without this observer the var
  // stays at its 57px fallback while the header compresses to ~41px,
  // leaving a visible gap between header bottom and strip top on scroll.
  // ResizeObserver fires on every box-size change (padding included),
  // covering scroll-shrink, font/zoom changes, and viewport resizes
  // without binding a per-frame scroll handler. Falls back gracefully
  // when ResizeObserver is unavailable: we still set the var once at
  // mount so the strip lines up under the unscrolled header height.
  useEfCo(() => {
    const el = headerRef.current; if (!el) return;
    const root = document.documentElement;
    const apply = () => {
      const h = el.offsetHeight;
      if (h > 0) root.style.setProperty('--mw-nav-h', `${h}px`);
    };
    apply();
    if (typeof ResizeObserver === 'undefined') return;
    const ro = new ResizeObserver(apply);
    ro.observe(el);
    return () => { ro.disconnect(); };
  }, []);
  // iOS-safe body scroll lock. body{overflow:hidden} alone does NOT lock
  // scroll on iOS Safari, which causes the page beneath the menu to drift
  // and "lose" the header. The position:fixed + negative top trick freezes
  // the document at the saved scrollY; on close we restore via scrollTo
  // — UNLESS the close was triggered by an in-menu hash link tap (Work,
  // Services, Get a free quote, etc). In that path the browser's anchor
  // navigation could not actually scroll while body was position:fixed,
  // and an unconditional scrollTo(0, scrollY) would clobber the intent.
  // Detect link-driven close by comparing window.location.hash at open
  // vs. cleanup; if it changed, the user navigated, so skip restore and
  // perform the anchor scroll the browser was prevented from doing.
  useEfCo(() => {
    if (!open) return;
    const scrollY = window.scrollY;
    const initialHash = window.location.hash;
    const body = document.body;
    const prev = {
      position: body.style.position,
      top: body.style.top,
      width: body.style.width,
      overflow: body.style.overflow,
    };
    body.style.position = 'fixed';
    body.style.top = `-${scrollY}px`;
    body.style.width = '100%';
    body.style.overflow = 'hidden';
    return () => {
      body.style.position = prev.position;
      body.style.top = prev.top;
      body.style.width = prev.width;
      body.style.overflow = prev.overflow;
      const finalHash = window.location.hash;
      if (finalHash && finalHash !== initialHash) {
        const target = document.querySelector(finalHash);
        if (target && typeof target.scrollIntoView === 'function') {
          target.scrollIntoView({ block:'start' });
          return;
        }
      }
      window.scrollTo(0, scrollY);
    };
  }, [open]);
  // Close the slide-out on Escape so keyboard users can dismiss it.
  useEfCo(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') { setOpen(false); } };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open]);
  // Focus management: when the menu opens, move focus to the close button.
  // When it closes, return focus to the hamburger trigger. A simple Tab
  // focus trap keeps focus inside the panel while open.
  useEfCo(() => {
    if (!open) {
      // Return focus to the trigger after close (skip on initial mount).
      if (triggerRef.current && document.activeElement === document.body) return;
      if (triggerRef.current) triggerRef.current.focus();
      return;
    }
    // Defer to next frame so the panel is visible before focusing.
    const id = window.requestAnimationFrame(() => {
      if (closeBtnRef.current) closeBtnRef.current.focus();
    });
    const onKey = (e) => {
      if (e.key !== 'Tab' || !panelRef.current) return;
      const focusables = panelRef.current.querySelectorAll(
        'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'
      );
      if (!focusables.length) return;
      const first = focusables[0];
      const last = focusables[focusables.length - 1];
      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault(); last.focus();
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault(); first.focus();
      }
    };
    document.addEventListener('keydown', onKey);
    return () => {
      window.cancelAnimationFrame(id);
      document.removeEventListener('keydown', onKey);
    };
  }, [open]);
  // Hide the Work link when there are zero showcases. The Projects
  // component returns null on empty (operator's "no placeholders" rule),
  // so the #work anchor doesn't exist on a fresh deploy. Same gate
  // pattern as app/components/SiteHeader.tsx so the desktop and mobile
  // nav surfaces here stay aligned with the SSR build-pages header.
  // window.MWT_SITE is emitted by app/components/PublicSettingsShim.tsx
  // before any text/babel script runs, so the read here always sees
  // either an array or undefined — never a transient empty state.
  const hasProjects =
    typeof window !== 'undefined' &&
    Array.isArray(window.MWT_SITE && window.MWT_SITE.projects) &&
    window.MWT_SITE.projects.length > 0;
  const links = hasProjects
    ? ['Work', 'Services', 'SEO', 'AI', 'Contact']
    : ['Services', 'SEO', 'AI', 'Contact'];
  return (
    <>
      <header ref={headerRef} style={{ position:'sticky', top:0, zIndex:50, display:'grid',
        gridTemplateColumns:'1fr auto 1fr', alignItems:'center',
        padding: scrolled?'8px clamp(16px,4vw,40px)':'14px clamp(16px,4vw,40px)',
        background:'color-mix(in oklab, var(--bg) 88%, transparent)',
        backdropFilter:'blur(20px)', WebkitBackdropFilter:'blur(20px)',
        borderBottom:'1px solid var(--border)',
        transition:'padding .25s var(--ease-out)' }}>
        <a href="#top" aria-label="Midwest Technologies — top" style={{textDecoration:'none', justifySelf:'start', display:'inline-flex', alignItems:'center'}}><Logo/></a>
        <nav className="mw-nav-desktop" aria-label="Primary" style={{gap:28, justifySelf:'center'}}>
          {links.map(l=>(
            <a key={l} href={`#${l.toLowerCase()}`} style={{fontFamily:'var(--font-mono)',fontSize:11,letterSpacing:'0.14em',
              textTransform:'uppercase',color:'var(--fg-3)',textDecoration:'none',transition:'color .15s'}}
              onMouseEnter={e=>e.currentTarget.style.color='var(--fg-1)'}
              onMouseLeave={e=>e.currentTarget.style.color='var(--fg-3)'}>{l}</a>
          ))}
        </nav>
        <div className="mw-nav-desktop" style={{gap:10,alignItems:'center', justifySelf:'end'}}>
          <TodIndicator tod={tod} setTod={setTod} auto={auto} setAuto={setAuto}/>
          <MagButton
            size="sm"
            variant="primary"
            href="#contact"
            onClick={() => window['mwtTrack'] && window['mwtTrack']('select_content', {
              content_type: 'cta',
              content_id: 'nav_get_quote_desktop',
              cta_label: 'Get a free quote',
              page_section: 'nav_desktop',
              page_path: typeof window !== 'undefined' ? window.location.pathname : '',
            })}
          >Get a free quote</MagButton>
        </div>
        <button ref={triggerRef} className="mw-nav-mobile" onClick={()=>setOpen(!open)}
          aria-expanded={open} aria-controls="mw-mobile-menu" aria-label={open?'Close menu':'Open menu'}
          style={{ width:44,height:44,padding:0, justifySelf:'end', gridColumn:3,
            background:'transparent',border:'1px solid var(--border-strong)',cursor:'pointer',
            alignItems:'center',justifyContent:'center', flexDirection:'column', gap:5,
            borderRadius:6 }}>
          <span aria-hidden="true" style={{width:18,height:1.5,background:'var(--fg-1)',display:'block',transition:'transform .3s var(--ease-out)',transform:open?'translateY(3.25px) rotate(45deg)':'none'}}/>
          <span aria-hidden="true" style={{width:18,height:1.5,background:'var(--fg-1)',display:'block',transition:'transform .3s var(--ease-out)',transform:open?'translateY(-3.25px) rotate(-45deg)':'none'}}/>
        </button>
      </header>

      {/* Mobile menu lives OUTSIDE <header>. The header has backdrop-filter,
          which establishes a containing block for fixed-positioned descendants
          per the Filter Effects spec. Nesting the panel inside would anchor
          its position:fixed to the ~60px-tall header instead of the viewport,
          collapsing the panel to zero height. Rendering as a sibling keeps
          fixed positioning anchored to the viewport's initial containing block.

          Backdrop covers the FULL viewport (inset:0). The menu panel sits on
          top with its own pinned header (brand + close button), so the user
          never "loses" navigation context regardless of how the underlying
          page is positioned. On wider mobile viewports the panel is capped
          at min(420px, 100vw) leaving a backdrop strip on the left for
          click-to-close. */}
      {open && (
        <div onClick={()=>setOpen(false)} aria-hidden="true"
          style={{ position:'fixed', inset:0, zIndex:51,
            background:'color-mix(in oklab, var(--bg) 60%, transparent)',
            backdropFilter:'blur(8px)', WebkitBackdropFilter:'blur(8px)' }}/>
      )}

      {/* Panel z-index 52 sits ABOVE the sticky <header> at z-index 50 so
          that opening the menu while scrolled to the top of the page (where
          the sticky header is at viewport y=0) does not double-stack the
          original header on top of the in-menu pinned header. The morphed
          hamburger inside the original header is intentionally covered when
          the menu is open — the in-menu ✕ close button is the close
          affordance from that point on. */}
      <div id="mw-mobile-menu" ref={panelRef} className="mw-mobile-panel"
        role="dialog" aria-modal={open ? 'true' : undefined} aria-label="Site navigation"
        style={{ position:'fixed', inset:0, zIndex:52, background:'var(--bg)',
          display:'flex', flexDirection:'column',
          transform:open?'translateX(0)':'translateX(100%)',
          transition:'transform .35s var(--ease-out)',
          pointerEvents:open?'auto':'none',
          visibility:open?'visible':'hidden' }}>
        {/* Pinned in-menu header. Stays put regardless of menu scroll —
            the brand mark on the left, the close button on the right.
            This is what the user looks for when they want to escape. */}
        <div style={{ flex:'0 0 auto',
          display:'flex', alignItems:'center', justifyContent:'space-between',
          padding:'14px clamp(16px,4vw,24px)',
          borderBottom:'1px solid var(--border)',
          background:'var(--bg)' }}>
          <a href="#top" onClick={()=>setOpen(false)} aria-label="Midwest Technologies — top"
            style={{textDecoration:'none', display:'inline-flex', alignItems:'center'}}>
            <Logo/>
          </a>
          <button ref={closeBtnRef} type="button" onClick={()=>setOpen(false)}
            aria-label="Close menu"
            style={{ width:44, height:44, display:'inline-flex',
              alignItems:'center', justifyContent:'center',
              background:'transparent', border:'1px solid var(--border-strong)',
              borderRadius:6, cursor:'pointer',
              fontFamily:'var(--font-mono)', fontSize:18, lineHeight:1,
              color:'var(--fg-1)' }}>
            <span aria-hidden="true">✕</span>
          </button>
        </div>

        {/* Inner scroll region. Scrolls independently of the pinned header
            above; overscroll-behavior:contain (in globals.css) prevents
            rubber-band bleed on iOS. */}
        <div className="mw-mobile-scroll"
          style={{ padding:'8px clamp(16px,4vw,24px) env(safe-area-inset-bottom, 24px)',
            display:'flex', flexDirection:'column' }}>
          {links.map((l,i)=>(
            <a key={l} href={`#${l.toLowerCase()}`} onClick={()=>setOpen(false)} style={{
              padding:'18px 0', borderBottom:'1px solid var(--border)',
              fontFamily:'var(--font-display)',fontSize:28,fontWeight:500,letterSpacing:'-0.02em',
              color:'var(--fg-1)',textDecoration:'none',
              opacity:open?1:0,transform:open?'none':'translateX(20px)',
              transition:`opacity .4s ${i*0.05+0.1}s, transform .4s var(--ease-out) ${i*0.05+0.1}s`,
              display:'flex',justifyContent:'space-between',alignItems:'center',
              minHeight:44}}>
              <span>{l}</span>
              <span aria-hidden="true" style={{fontFamily:'var(--font-mono)',fontSize:12,color:'var(--fg-4)'}}>0{i+1} →</span>
            </a>
          ))}
          <div style={{marginTop:24,display:'flex',flexDirection:'column',gap:14}}>
            <TodIndicator tod={tod} setTod={setTod} auto={auto} setAuto={setAuto}/>
            <MagButton full variant="primary" size="lg" href="#contact"
              onClick={() => {
                if (window['mwtTrack']) {
                  window['mwtTrack']('select_content', {
                    content_type: 'cta',
                    content_id: 'nav_get_quote_mobile',
                    cta_label: 'Get a free quote',
                    page_section: 'nav_mobile',
                    page_path: typeof window !== 'undefined' ? window.location.pathname : '',
                  });
                }
                setOpen(false);
              }}>Get a free quote</MagButton>
          </div>
          <div style={{marginTop:'auto',paddingTop:24,fontFamily:'var(--font-mono)',fontSize:10,letterSpacing:'0.14em',color:'var(--fg-4)'}}>
            MIDWEST TECHNOLOGIES · OKLAHOMA STATE · 2026
          </div>
        </div>
      </div>
    </>
  );
}

Object.assign(window, { useReveal, MagButton, Pill, SectionHead, Logo, Nav, TodIndicator });
