// app.jsx — Nav + App shell. Hero is now in hero-section.jsx
const { useState, useEffect, useRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "dark",
  "accent": "#10B981",
  "displayFont": "General Sans",
  "heroImage": "hero-bg-health"
}/*EDITMODE-END*/;

// ── Echo Logo SVG ─────────────────────────────────────────────────
// Teal dot + three concentric arcs sweeping right. Tight 24×28 viewBox
// (no trailing whitespace) so the wordmark sits closer to the symbol.
// Radii arithmetic 5 → 8 → 11; chord length always equals 2r so each
// arc is a clean semicircle, giving an even radio-wave silhouette.
function LogoMark({ size = 26, light = false }) {
  // Brand mark — uses the canonical Echo logo image asset.
  // The asset is the dark-bg version; on light backgrounds we keep it as-is
  // because the logo container reads cleanly on both via subtle border-radius
  // and the inherent dark canvas of the logo.
  return (
    <img
      src="img/echo-logo.jpeg"
      alt="Echo"
      width={size}
      height={size}
      style={{ display: 'block', borderRadius: 4, objectFit: 'contain' }}
    />
  );
}

// ── Agent glyph icons — distinctive SVG marks per agent (Series-A grade) ──
function AgentGlyph({ name }) {
  const glyphs = {
    'Triage':  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><path d="M3 8h18M5 12h14M8 16h8"/><circle cx="20" cy="6" r="1.5" fill="currentColor" stroke="none"/></svg>,
    'Docs':    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><path d="M6 3h9l4 4v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/><path d="M15 3v4h4"/><path d="M9 14l2.5 2.5L16 12"/></svg>,
    'Cal':     <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/><path d="M21 12h-2"/></svg>,
    'Ledger':  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><circle cx="12" cy="13" r="8"/><path d="M9 2h6M12 8v5l3 2"/><path d="M19 5l1.5 1.5"/></svg>,
    'Audit':   <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6l8-4z"/><path d="M9 12l2 2 4-4"/></svg>,
    'Recover': <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><rect x="2" y="6" width="14" height="12" rx="2"/><path d="M16 10h4l2 3v5h-6"/><circle cx="6" cy="20" r="2"/><circle cx="18" cy="20" r="2"/></svg>,
    'Intake':  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><path d="M4 7c0-1 1-2 2-2h12c1 0 2 1 2 2v10c0 1-1 2-2 2H6c-1 0-2-1-2-2V7z"/><path d="M4 11h16M9 5v-2M15 5v-2"/></svg>,
    'Quote':   <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" style={{display:'block'}}><rect x="3" y="3" width="18" height="18" rx="4"/><path d="M12 7v10M9.5 9.5c0-1.2 1.1-2 2.5-2s2.5 0.8 2.5 2c0 1-0.8 1.6-2.5 2-1.7 0.4-2.5 1-2.5 2 0 1.2 1.1 2 2.5 2s2.5-0.8 2.5-2"/></svg>,
  };
  return glyphs[name] || <span>{name[0]}</span>;
}

// ── Solutions dropdown ────────────────────────────────────────────
function SolutionsDropdown({ onPhoto }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  const closeTimer = useRef(null);
  const hoverOpen = () => { clearTimeout(closeTimer.current); setOpen(true); };
  const hoverClose = () => { closeTimer.current = setTimeout(() => setOpen(false), 120); };

  useEffect(() => {
    const close = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', close);
    return () => document.removeEventListener('mousedown', close);
  }, []);

  const items = [
    { label: 'Carriers',            sub: 'Asset-based · LTL · TL',      href: '/' },
    { label: 'Oracle ERP',          sub: 'Fusion · NetSuite · JD Edwards',    href: '/erp' },
    { label: 'Freight & Logistics', sub: 'Brokers · Freight forwarders',                    href: '/freight' },
    { label: 'Regenerative Health', sub: 'Clinics · Wellness · Aesthetics',   href: '/health' },
  ];

  const linkColor = onPhoto ? 'rgba(244,240,232,0.72)' : 'var(--muted)';
  const linkHover = onPhoto ? '#F4F0E8' : 'var(--ink)';

  return (
    <div ref={ref} style={{ position: 'relative' }} onMouseEnter={hoverOpen} onMouseLeave={hoverClose}>
      <button
        onClick={() => setOpen(o => !o)}
        style={{
          background: 'none', border: 'none', cursor: 'pointer', padding: 0,
          fontFamily: 'var(--ff-mono)', fontSize: 11, letterSpacing: '0.1em',
          color: open ? linkHover : linkColor,
          textTransform: 'uppercase', transition: 'color 0.2s',
          fontWeight: 500, display: 'flex', alignItems: 'center', gap: 5,
        }}
        onMouseEnter={e => e.currentTarget.style.color = linkHover}
        onMouseLeave={e => { if (!open) e.currentTarget.style.color = linkColor; }}
      >
        Verticals
        <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 0.2s' }}><path d="M6 9l6 6 6-6"/></svg>
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 14px)', left: '50%', transform: 'translateX(-50%)',
          background: 'var(--bg)', border: '1px solid var(--hairline)', borderRadius: 12,
          padding: '8px', minWidth: 240,
          boxShadow: '0 20px 60px rgba(0,0,0,0.22)', zIndex: 200,
        }}>
          {items.map(item => (
            <a key={item.href} href={item.href} onClick={() => setOpen(false)} style={{
              display: 'flex', flexDirection: 'column', gap: 2,
              padding: '11px 14px', borderRadius: 8,
              textDecoration: 'none', color: 'inherit',
              transition: 'background 0.15s',
            }}
              onMouseEnter={e => e.currentTarget.style.background = 'var(--surface)'}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
            >
              <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 11, fontWeight: 600, color: 'var(--ink)', letterSpacing: '0.04em' }}>{item.label}</span>
              <span style={{ fontSize: 11, color: 'var(--muted)' }}>{item.sub}</span>
            </a>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Agents dropdown ───────────────────────────────────────────────
// Same anchor/positioning as SolutionsDropdown so the two read as a
// matched pair. Each row carries the agent's signature color as a dot —
// same palette used on the agent detail pages.
function AgentsDropdown({ onPhoto }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  const closeTimer = useRef(null);

  useEffect(() => {
    const close = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', close);
    return () => document.removeEventListener('mousedown', close);
  }, []);

  // Hover-intent: open on enter, close on leave with a small grace
  // period so the cursor can travel from button → menu without dropping.
  const hoverOpen = () => { clearTimeout(closeTimer.current); setOpen(true); };
  const hoverClose = () => { closeTimer.current = setTimeout(() => setOpen(false), 120); };

  const items = [
    { name: 'Intake', domain: 'Patient Intake & Authorization', color: '#0EA5E9', href: 'agents/intake.html' },
    { name: 'Docs',   domain: 'Consent & Compliance',           color: '#F59E0B', href: 'agents/docs.html' },
    { name: 'Cal',    domain: 'Treatment Scheduling',           color: '#10B981', href: 'agents/cal.html' },
    { name: 'Ledger', domain: 'AR & Collections',               color: '#A855F7', href: 'agents/ledger.html' },
  ];

  const linkColor = onPhoto ? 'rgba(244,240,232,0.72)' : 'var(--muted)';
  const linkHover = onPhoto ? '#F4F0E8' : 'var(--ink)';

  return (
    <div ref={ref} style={{ position: 'relative' }} onMouseEnter={hoverOpen} onMouseLeave={hoverClose}>
      <button
        onClick={() => setOpen(o => !o)}
        style={{
          background: 'none', border: 'none', cursor: 'pointer', padding: 0,
          fontFamily: 'var(--ff-mono)', fontSize: 11, letterSpacing: '0.1em',
          color: open ? linkHover : linkColor,
          textTransform: 'uppercase', transition: 'color 0.2s',
          fontWeight: 500, display: 'flex', alignItems: 'center', gap: 5,
        }}
        onMouseEnter={e => e.currentTarget.style.color = linkHover}
        onMouseLeave={e => { if (!open) e.currentTarget.style.color = linkColor; }}
      >
        Agents
        <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 0.2s' }}><path d="M6 9l6 6 6-6"/></svg>
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 14px)', left: '50%', transform: 'translateX(-50%)',
          background: 'var(--bg)', border: '1px solid var(--hairline)', borderRadius: 12,
          padding: '8px', width: 300,
          boxShadow: '0 20px 60px rgba(0,0,0,0.22)', zIndex: 200,
        }}>
          {items.map(item => (
            <a key={item.href} href={item.href} onClick={() => setOpen(false)} style={{
              display: 'flex', alignItems: 'center', gap: 12,
              padding: '10px 12px', borderRadius: 8,
              textDecoration: 'none', color: 'inherit',
              transition: 'background 0.15s',
            }}
              onMouseEnter={e => {
                e.currentTarget.style.background = `${item.color}14`;
                const mark = e.currentTarget.querySelector('[data-agent-mark]');
                if (mark) {
                  mark.style.transform = 'scale(1.06)';
                  mark.style.boxShadow = `0 6px 16px ${item.color}55, inset 0 1px 0 rgba(255,255,255,0.26)`;
                }
              }}
              onMouseLeave={e => {
                e.currentTarget.style.background = 'transparent';
                const mark = e.currentTarget.querySelector('[data-agent-mark]');
                if (mark) {
                  mark.style.transform = 'scale(1)';
                  mark.style.boxShadow = `0 4px 12px ${item.color}33, inset 0 1px 0 rgba(255,255,255,0.22)`;
                }
              }}
            >
              <span
                data-agent-mark
                style={{
                  width: 32, height: 32,
                  borderRadius: 8,
                  background: `linear-gradient(180deg, ${item.color}EE 0%, ${item.color} 100%)`,
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  color: '#fff',
                  fontFamily: 'var(--ff-display)',
                  fontSize: 15, fontWeight: 600,
                  letterSpacing: '-0.02em',
                  boxShadow: `0 4px 12px ${item.color}33, inset 0 1px 0 rgba(255,255,255,0.22)`,
                  flexShrink: 0,
                  transition: 'transform 0.18s ease, box-shadow 0.18s ease',
                  lineHeight: 1,
                }}
              >
                <AgentGlyph name={item.name} />
              </span>
              <span style={{ display: 'flex', flexDirection: 'column', gap: 2, minWidth: 0 }}>
                <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 11, fontWeight: 600, color: 'var(--ink)', letterSpacing: '0.04em' }}>{item.name}</span>
                <span style={{ fontSize: 11, color: 'var(--muted)' }}>{item.domain}</span>
              </span>
            </a>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Mobile menu (full-screen overlay) ─────────────────────────────
function MobileMenu({ open, onClose, onPhoto }) {
  const [solOpen, setSolOpen] = useState(false);
  const [agentsOpen, setAgentsOpen] = useState(false);

  useEffect(() => {
    if (open) {
      const prev = document.body.style.overflow;
      document.body.style.overflow = 'hidden';
      return () => { document.body.style.overflow = prev; };
    }
  }, [open]);

  const links = [
    { label: 'Why Echo',     href: '#why-echo' },
    { label: 'How It Works', href: '#how-it-works' },
  ];
  const solutions = [
    { label: 'Carriers',            sub: 'Asset-based · LTL · TL',      href: '/' },
    { label: 'Oracle ERP',          sub: 'Fusion · NetSuite · JD Edwards',    href: '/erp' },
    { label: 'Freight & Logistics', sub: 'Brokers · Freight forwarders',                    href: '/freight' },
    { label: 'Regenerative Health', sub: 'Clinics · Wellness · Aesthetics',   href: '/health' },
  ];
  const agents = [
    { name: 'Intake', domain: 'Patient Intake & Authorization', color: '#0EA5E9', href: 'agents/intake.html' },
    { name: 'Docs',   domain: 'Consent & Compliance',           color: '#F59E0B', href: 'agents/docs.html' },
    { name: 'Cal',    domain: 'Treatment Scheduling',           color: '#10B981', href: 'agents/cal.html' },
    { name: 'Ledger', domain: 'AR & Collections',               color: '#A855F7', href: 'agents/ledger.html' },
  ];

  return (
    <div
      className="mobile-menu-overlay"
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, zIndex: 150,
        background: 'rgba(10,22,18,0.96)',
        backdropFilter: 'blur(10px)',
        opacity: open ? 1 : 0,
        pointerEvents: open ? 'auto' : 'none',
        transition: 'opacity 0.25s cubic-bezier(0.4,0,0.2,1)',
        display: 'flex', flexDirection: 'column',
        padding: '88px 24px 32px',
        overflowY: 'auto',
      }}
    >
      <div onClick={e => e.stopPropagation()} style={{ display: 'flex', flexDirection: 'column', gap: 4, flex: 1 }}>
        {/* Solutions (expandable) */}
        <button
          onClick={() => setSolOpen(o => !o)}
          style={{
            background: 'none', border: 'none', cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '18px 8px', width: '100%',
            fontFamily: 'var(--ff-mono)', fontSize: 13, letterSpacing: '0.12em',
            color: '#F4F0E8', textTransform: 'uppercase', fontWeight: 500,
            borderBottom: '1px solid rgba(244,240,232,0.10)',
          }}
        >
          Verticals
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"
            style={{ transform: solOpen ? 'rotate(180deg)' : 'none', transition: 'transform 0.2s' }}>
            <path d="M6 9l6 6 6-6"/>
          </svg>
        </button>
        {solOpen && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 2, padding: '8px 0 16px 16px', borderBottom: '1px solid rgba(244,240,232,0.10)' }}>
            {solutions.map(s => (
              <a key={s.href} href={s.href} onClick={onClose} style={{
                display: 'flex', flexDirection: 'column', gap: 4,
                padding: '12px 8px', textDecoration: 'none',
              }}>
                <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 12, fontWeight: 600, color: '#F4F0E8', letterSpacing: '0.04em' }}>{s.label}</span>
                <span style={{ fontSize: 12, color: 'rgba(244,240,232,0.55)' }}>{s.sub}</span>
              </a>
            ))}
          </div>
        )}

        {/* Agents (expandable) */}
        <button
          onClick={() => setAgentsOpen(o => !o)}
          style={{
            background: 'none', border: 'none', cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '18px 8px', width: '100%',
            fontFamily: 'var(--ff-mono)', fontSize: 13, letterSpacing: '0.12em',
            color: '#F4F0E8', textTransform: 'uppercase', fontWeight: 500,
            borderBottom: '1px solid rgba(244,240,232,0.10)',
          }}
        >
          Agents
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"
            style={{ transform: agentsOpen ? 'rotate(180deg)' : 'none', transition: 'transform 0.2s' }}>
            <path d="M6 9l6 6 6-6"/>
          </svg>
        </button>
        {agentsOpen && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 2, padding: '8px 0 16px 16px', borderBottom: '1px solid rgba(244,240,232,0.10)' }}>
            {agents.map(a => (
              <a key={a.href} href={a.href} onClick={onClose} style={{
                display: 'flex', alignItems: 'center', gap: 14,
                padding: '12px 8px', textDecoration: 'none',
              }}>
                <span style={{
                  width: 36, height: 36,
                  borderRadius: 9,
                  background: `linear-gradient(180deg, ${a.color}EE 0%, ${a.color} 100%)`,
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  color: '#fff',
                  fontFamily: 'var(--ff-display)',
                  fontSize: 16, fontWeight: 600,
                  letterSpacing: '-0.02em',
                  boxShadow: `0 4px 14px ${a.color}40, inset 0 1px 0 rgba(255,255,255,0.22)`,
                  flexShrink: 0,
                  lineHeight: 1,
                }}>
                  <AgentGlyph name={a.name} />
                </span>
                <span style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
                  <span style={{ fontFamily: 'var(--ff-mono)', fontSize: 12, fontWeight: 600, color: '#F4F0E8', letterSpacing: '0.04em' }}>{a.name}</span>
                  <span style={{ fontSize: 12, color: 'rgba(244,240,232,0.55)' }}>{a.domain}</span>
                </span>
              </a>
            ))}
          </div>
        )}

        {links.map(l => (
          <a
            key={l.label}
            href={l.href}
            onClick={onClose}
            style={{
              display: 'block',
              padding: '18px 8px',
              fontFamily: 'var(--ff-mono)', fontSize: 13, letterSpacing: '0.12em',
              color: '#F4F0E8', textTransform: 'uppercase', fontWeight: 500,
              textDecoration: 'none',
              borderBottom: '1px solid rgba(244,240,232,0.10)',
            }}
          >
            {l.label}
          </a>
        ))}

        <div style={{ marginTop: 32 }}>
          <a
            href="#book"
            data-open-book-call
            onClick={onClose}
            style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
              width: '100%',
              padding: '18px 24px',
              background: 'linear-gradient(180deg, #3B82F6 0%, #2563EB 100%)',
              color: '#F4F0E8',
              fontFamily: 'var(--ff-mono)', fontSize: 13, letterSpacing: '0.12em',
              fontWeight: 600, textTransform: 'uppercase',
              borderRadius: 10, textDecoration: 'none',
              border: '1px solid rgba(96,165,250,0.55)',
              boxShadow: '0 14px 40px rgba(37,99,235,0.5), inset 0 1px 0 rgba(255,255,255,0.22)',
            }}
          >
            <span style={{ width: 7, height: 7, borderRadius: '50%', background: '#7DC9A8', boxShadow: '0 0 10px rgba(125,201,168,0.9)' }} />
            Get a demo
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
          </a>
        </div>
      </div>
    </div>
  );
}

// ── Nav ───────────────────────────────────────────────────────────
function Nav({ theme, setTheme, scrolled }) {
  const [mobileOpen, setMobileOpen] = useState(false);
  const links = [
    { label: 'Why Echo',     href: '#why-echo' },
    { label: 'How It Works', href: '#how-it-works' },
  ];

  // Top of page (over photo) — light text. After scroll — paper bg.
  const onPhoto = !scrolled;

  return (
    <nav style={{
      position: 'fixed', top: 0, left: 0, right: 0, zIndex: 100,
      background: scrolled
        ? (theme === 'dark' ? '#0A1612' : '#F4F0E8')
        : 'transparent',
      borderBottom: scrolled ? '1px solid var(--hairline)' : '1px solid transparent',
      transition: 'all 0.4s cubic-bezier(0.16,1,0.3,1)',
    }}>
      <div className="nav-inner" style={{ maxWidth: 1280, margin: '0 auto', padding: '0 48px', height: 68, display: 'flex', alignItems: 'center', gap: 40 }}>
        {/* Logo */}
        <a href="/" style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
          <LogoMark size={26} light={onPhoto} />
          <span style={{
            fontFamily: 'var(--ff-display)',
            fontSize: 19, fontWeight: 500, letterSpacing: '-0.01em',
            color: onPhoto ? '#F4F0E8' : 'var(--ink)',
            transition: 'color 0.4s',
          }}>Echo</span>
        </a>

        {/* Links */}
        <div className="nav-links" style={{ flex: 1, display: 'flex', gap: 32, alignItems: 'center' }}>
          <SolutionsDropdown onPhoto={onPhoto} />
          <AgentsDropdown onPhoto={onPhoto} />
          {links.map(l => (
            <a key={l.label} href={l.href} style={{
              fontFamily: 'var(--ff-mono)', fontSize: 11, letterSpacing: '0.1em',
              color: onPhoto ? 'rgba(244,240,232,0.72)' : 'var(--muted)',
              textTransform: 'uppercase', transition: 'color 0.2s',
              fontWeight: 500,
            }}
              onMouseEnter={e => e.target.style.color = onPhoto ? '#F4F0E8' : 'var(--ink)'}
              onMouseLeave={e => e.target.style.color = onPhoto ? 'rgba(244,240,232,0.72)' : 'var(--muted)'}
            >{l.label}</a>
          ))}
        </div>

        {/* Right */}
        <div className="nav-right" style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <button
            className="nav-hamburger"
            aria-label={mobileOpen ? 'Close menu' : 'Open menu'}
            aria-expanded={mobileOpen}
            onClick={() => setMobileOpen(o => !o)}
            style={{
              background: 'none', border: 'none', cursor: 'pointer',
              color: mobileOpen ? '#F4F0E8' : (onPhoto ? 'rgba(244,240,232,0.85)' : 'var(--muted)'),
              padding: 8, borderRadius: 8,
              alignItems: 'center', justifyContent: 'center',
              position: 'relative', zIndex: 160,
            }}
          >
            {mobileOpen
              ? <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
              : <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M3 6h18M3 12h18M3 18h18"/></svg>
            }
          </button>
          {/* Theme toggle hidden — Phase 2 will wire up light mode properly */}
          <a href="#book" data-open-book-call className="echo-cta echo-cta--primary echo-cta--nav">
            <span className="echo-cta__dot" />
            <span className="echo-cta__label">Get a demo</span>
            <svg className="echo-cta__arrow" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
          </a>
        </div>
      </div>
      <MobileMenu open={mobileOpen} onClose={() => setMobileOpen(false)} onPhoto={onPhoto} />
    </nav>
  );
}

// ── Tweaks ────────────────────────────────────────────────────────
function EchoTweaks({ tweaks, setTweak }) {
  return (
    <TweaksPanel>
      <TweakSection label="Theme">
        <TweakRadio id="theme" label="Mode" value={tweaks.theme} options={['light', 'dark']} onChange={v => setTweak('theme', v)} />
      </TweakSection>
      <TweakSection label="Accent Color">
        <TweakColor id="accent" label="Accent" value={tweaks.accent} onChange={v => setTweak('accent', v)} />
      </TweakSection>
      <TweakSection label="Hero Image">
        <TweakSelect id="heroImage" label="Photo" value={tweaks.heroImage}
          options={[
            { label: 'Container yard (default)', value: 'hero-truck-corridor' },
            { label: 'Port at dawn',              value: 'mood-port-lights' },
            { label: 'Truck on mountain road',    value: 'truck-distance' },
            { label: 'Truck on highway',          value: 'truck-on-highway' },
            { label: 'Aerial: container grid',    value: 'highway-aerial-1' },
            { label: 'Aerial: distribution',      value: 'fleet-row' },
          ]}
          onChange={v => setTweak('heroImage', v)}
        />
      </TweakSection>
      <TweakSection label="Display Font">
        <TweakSelect id="displayFont" label="Font" value={tweaks.displayFont}
          options={[
            { label: 'General Sans (default)', value: 'General Sans' },
            { label: 'Geist', value: 'Geist' },
            { label: 'Aeonik', value: 'Aeonik' },
          ]}
          onChange={v => setTweak('displayFont', v)}
        />
      </TweakSection>
    </TweaksPanel>
  );
}

// ── App ───────────────────────────────────────────────────────────
function App() {
  const [tweaks, setTweakState] = useState(TWEAK_DEFAULTS);
  const [scrolled, setScrolled] = useState(false);
  const [tweaksOpen, setTweaksOpen] = useState(false);

  const setTweak = (key, val) => {
    setTweakState(prev => {
      const next = typeof key === 'object' ? { ...prev, ...key } : { ...prev, [key]: val };
      window.parent.postMessage({ type: '__edit_mode_set_keys', edits: next }, '*');
      return next;
    });
  };

  useEffect(() => { document.documentElement.setAttribute('data-theme', tweaks.theme); }, [tweaks.theme]);

  useEffect(() => {
    document.documentElement.style.setProperty('--accent', tweaks.accent);
    document.documentElement.style.setProperty('--accent-dim', tweaks.accent + '1a');
    document.documentElement.style.setProperty('--accent-glow', tweaks.accent + '38');
  }, [tweaks.accent]);

  useEffect(() => {
    document.documentElement.style.setProperty('--ff-display', `'${tweaks.displayFont}', 'Geist', system-ui, sans-serif`);
  }, [tweaks.displayFont]);

  useEffect(() => {
    let ticking = false;
    const onScroll = () => {
      if (ticking) return;
      ticking = true;
      requestAnimationFrame(() => { setScrolled(window.scrollY > 80); ticking = false; });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  useEffect(() => {
    const handler = e => {
      if (e.data?.type === '__activate_edit_mode') setTweaksOpen(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  useEffect(() => {
    const obs = new IntersectionObserver(entries => {
      entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('visible'); obs.unobserve(e.target); } });
    }, { threshold: 0.07 });
    document.querySelectorAll('.reveal').forEach(el => obs.observe(el));

    // Tag plates with .in-view as they enter the viewport (drives both the
    // accent halo on dark mode plates AND the scroll-fade-up reveal).
    // Set-once: stays revealed after first crossing the threshold.
    const plateObs = new IntersectionObserver(entries => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add('in-view');
          plateObs.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    document.querySelectorAll('.glass-plate').forEach(el => plateObs.observe(el));

    // (Hero video parallax removed — was causing scroll lag due to
    // continuous transform on a 23MB video element. The fixed video
    // background already creates depth without scroll-coupled motion.)

    return () => { obs.disconnect(); plateObs.disconnect(); };
  }, []);

  return (
    <>
      <Nav theme={tweaks.theme} setTheme={fn => setTweak('theme', fn(tweaks.theme))} scrolled={scrolled} />
      <main>
        <Hero heroImage={tweaks.heroImage} />
        <Problem />
        <AgentsAndDemo />
        <WhyEcho />
        <Comparison />
        <HowItWorks />
        <FAQ />
      </main>
      <Footer theme={tweaks.theme} setTheme={fn => setTweak('theme', fn(tweaks.theme))} />
      <DemoModal />
      <BookCallModal />
      {tweaksOpen && <EchoTweaks tweaks={tweaks} setTweak={setTweak} />}
    </>
  );
}

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