// site-shared.jsx — shared components for all GMR sites.
// Load with: <script type="text/babel" src="../_shared/site-shared.jsx"></script>
// AFTER React + ReactDOM + Babel.

const SITE_BRANDS = {
  gmr:       { long: 'GMR',       mono: 'GMR', accent: '#34D399', url: 'https://genmr.co',     status: 'group',     desc: 'The proprietary AI stack for marketing agencies.' },
  brynx:     { long: 'BRYNX',     mono: 'BX',  accent: '#3B82F6', url: 'https://brynx.ai',     status: 'live',      desc: 'Generative market research. 2h vs 6 weeks.' },
  dtwin:     { long: 'DTWIN',     mono: 'DT',  accent: '#6B6B80', url: 'https://dtwin.now',    status: 'live',      desc: 'Audience digital twins. Simulate. Explore. Decide.' },
  marketear: { long: 'MARKETEAR', mono: 'ME',  accent: '#8B5CF6', url: 'https://marketear.co', status: 'live',      desc: 'Agentic social listening. 5 agents, one report.' },
  geoke:     { long: 'GEOKE',     mono: 'GK',  accent: '#EC4899', url: 'https://geoke.genmr.co', status: 'pre-launch', desc: 'How LLMs talk about your brand. Polled every 6h.' },
  geoky:     { long: 'GEOKY',     mono: 'GK',  accent: '#EC4899', url: 'https://geoky.ai',     status: 'live',      desc: 'What does AI say about your brand? Tracked weekly.' },
  klenux:    { long: 'KLENUX',    mono: 'KX',  accent: '#06B6D4', url: 'https://klenux.com',   status: 'pre-launch', desc: 'AI-native UX testing on audience-realistic digital twins.' },
  crewrev:   { long: 'CREWREV',   mono: 'CR',  accent: '#34D399', url: 'https://crewrev.com',  status: 'pre-launch', desc: 'Your revenue team in chat. CRO + CMO + 7 specialists.' },
  influrep:  { long: 'INFLUREP',  mono: 'IR',  accent: '#F59E0B', url: 'https://influrep.com', status: 'pre-launch', desc: 'Social intelligence for creator due diligence.' },
};

// Inline data-URI fallbacks (set by logos-inline.js when present — used after bundling).
const __INLINE = (typeof window !== 'undefined' && window.__LOGO_DATA) || {};
const __resolve = (filename, fallback) => __INLINE[filename] || fallback;

const LOGO_FILES = {
  gmr:       __resolve('GMR.svg',       '../../assets/logos/GMR.svg'),
  brynx:     __resolve('BRYNX.svg',     '../../assets/logos/BRYNX.svg'),
  dtwin:     __resolve('DTWIN.svg',     '../../assets/logos/DTWIN.svg'),
  marketear: __resolve('MARKETEAR.svg', '../../assets/logos/MARKETEAR.svg'),
  crewrev:   __resolve('CREWREV.svg',   '../../assets/logos/CREWREV.svg'),
  geoke:     __resolve('GEOKE.svg',     '../../assets/logos/GEOKE.svg'),
  influrep:  __resolve('INFLUREP@3x.png','../../assets/logos/INFLUREP@3x.png'),
};
const MONO_FILES = {
  brynx:     __resolve('BX.svg', '../../assets/logos/BX.svg'),
  dtwin:     __resolve('DT.svg', '../../assets/logos/DT.svg'),
  marketear: __resolve('ME.svg', '../../assets/logos/ME.svg'),
  crewrev:   __resolve('CR.svg', '../../assets/logos/CR.svg'),
  geoke:     __resolve('GK.svg', '../../assets/logos/GK.svg'),
  geoky:     __resolve('GK.svg', '../../assets/logos/GK.svg'),
  klenux:    __resolve('KX.svg', '../../assets/logos/KX.svg'),
  influrep:  __resolve('IR.svg', '../../assets/logos/IR.svg'),
};
const GMR_SMALL = __resolve('GMR-small.svg', '../../assets/logos/GMR-small.svg');

// ---- Brand mark ----
function Brand({ brand = 'gmr', size = 'm', style = {} }) {
  const src = LOGO_FILES[brand];
  return <img className={`wm wm-${size}`} src={src} alt={SITE_BRANDS[brand]?.long || brand} style={style}/>;
}

// ---- Header ----
function SiteHeader({ brand = 'gmr', nav = [], cta = null }) {
  return (
    <header style={{
      position: 'sticky', top: 0, zIndex: 30,
      background: 'rgba(6,6,10,0.78)',
      backdropFilter: 'blur(16px)',
      WebkitBackdropFilter: 'blur(16px)',
      borderBottom: '1px solid var(--hair)',
    }}>
      <div className="container row between" style={{ padding: '18px 32px', alignItems: 'center' }}>
        <a href="#top" className="row center" style={{ gap: 12 }}>
          <Brand brand={brand} size="m"/>
          {brand !== 'gmr' && (
            <span className="mono" style={{ fontSize: 11, color: 'var(--ink-5)', borderLeft: '1px solid var(--hair-2)', paddingLeft: 12 }}>
              part of GMR
            </span>
          )}
        </a>

        <nav className="row gap-6" style={{ alignItems: 'center' }}>
          {nav.map(item => (
            <a key={item.href} href={item.href} style={{
              fontSize: 13, fontWeight: 500, color: 'var(--ink-3)',
              transition: 'color 200ms',
            }}
              onMouseEnter={e => e.target.style.color = 'var(--ink)'}
              onMouseLeave={e => e.target.style.color = 'var(--ink-3)'}
            >{item.label}</a>
          ))}
          {cta && (
            <a href={cta.href} className="btn btn-secondary">
              {cta.label}
            </a>
          )}
        </nav>
      </div>
    </header>
  );
}

// ---- Footer ----
function SiteFooter({ brand = 'gmr', links = [] }) {
  const isGmr = brand === 'gmr';
  return (
    <footer style={{ borderTop: '1px solid var(--hair)', padding: '64px 0 48px' }}>
      <div className="container">
        <div className="row between" style={{ alignItems: 'flex-start', marginBottom: 48, flexWrap: 'wrap', gap: 32 }}>
          <div className="col gap-4">
            <Brand brand={brand} size="l"/>
            <span className="body-s" style={{ color: 'var(--ink-4)', maxWidth: 320 }}>
              {SITE_BRANDS[brand]?.desc || ''}
            </span>
          </div>
          <div className="row gap-7" style={{ flexWrap: 'wrap' }}>
            {links.map(group => (
              <div key={group.label} className="col gap-3" style={{ minWidth: 140 }}>
                <span className="eyebrow no-rule">{group.label}</span>
                {group.items.map(item => (
                  <a key={`${group.label}-${item.label}`} href={item.href} style={{ fontSize: 13, color: 'var(--ink-3)' }}>
                    {item.label}
                  </a>
                ))}
              </div>
            ))}
          </div>
        </div>
        <hr className="hr"/>
        <div className="row between" style={{ padding: '24px 0 0', alignItems: 'center', flexWrap: 'wrap', gap: 16 }}>
          <span className="mono" style={{ fontSize: 11, color: 'var(--ink-5)' }}>
            © GMR Inc · {new Date().getFullYear()} · {isGmr ? '7 brands' : `${SITE_BRANDS[brand]?.long} is part of GMR`}
          </span>
          <span className="mono" style={{ fontSize: 11, color: 'var(--ink-5)' }}>
            genmr.co
          </span>
        </div>
      </div>
    </footer>
  );
}

// ---- Portfolio strip — cross-brand bar shown on product sites ----
function PortfolioStrip({ activeBrand = null, eyebrow = 'Part of the GMR group', heading = null }) {
  const order = ['brynx', 'dtwin', 'marketear', 'geoke', 'crewrev', 'influrep'];
  const others = activeBrand ? order.filter(b => b !== activeBrand) : order;

  return (
    <section className="section section-tall" style={{ background: 'var(--paper-2)' }}>
      <div className="container">
        <div className="col gap-5" style={{ marginBottom: 56 }}>
          <span className="eyebrow">{eyebrow}</span>
          {heading && <h2 className="h2">{heading}</h2>}
        </div>

        <div className="grid grid-3" style={{ gap: 1, background: 'var(--hair)', border: '1px solid var(--hair)' }}>
          {others.map(id => {
            const b = SITE_BRANDS[id];
            return (
              <a key={id} href={b.url} target="_blank" rel="noopener"
                style={{
                  background: 'var(--paper)',
                  padding: '32px 28px',
                  display: 'flex', flexDirection: 'column', gap: 18,
                  minHeight: 200,
                  transition: 'background 200ms',
                }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--paper-3)'}
                onMouseLeave={e => e.currentTarget.style.background = 'var(--paper)'}
              >
                <div className="row between" style={{ alignItems: 'center' }}>
                  <Brand brand={id} size="l"/>
                  <span className={`pill ${b.status === 'live' ? 'live' : 'pre'}`}>
                    <span className="dot"/>{b.status === 'live' ? 'Live' : 'Soon'}
                  </span>
                </div>
                <p className="body-s" style={{ color: 'var(--ink-3)', flex: 1 }}>{b.desc}</p>
                <span className="row" style={{ alignItems: 'center', gap: 8, color: 'var(--ink-4)', fontSize: 12, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
                  Visit <span className="mono" style={{ fontSize: 14 }}>→</span>
                </span>
              </a>
            );
          })}
        </div>
      </div>
    </section>
  );
}

// ---- Reveal-on-scroll observer ----
function useRevealOnScroll() {
  React.useEffect(() => {
    const els = document.querySelectorAll('.reveal, .reveal-stagger');
    if (els.length === 0) return;

    const reveal = (el) => el.classList.add('is-visible');

    // 1. Reveal anything already in viewport at mount immediately (after one frame
    //    so the transition has a chance to play from the initial state).
    const vh = window.innerHeight || document.documentElement.clientHeight;
    requestAnimationFrame(() => {
      els.forEach(el => {
        const r = el.getBoundingClientRect();
        if (r.top < vh && r.bottom > 0) reveal(el);
      });
    });

    // 2. Belt-and-suspenders: in case IO is delayed or doesn't fire (some embed
    //    environments swallow it), force-reveal anything still hidden after 800ms.
    const fallback = setTimeout(() => {
      els.forEach(el => {
        if (!el.classList.contains('is-visible')) {
          const r = el.getBoundingClientRect();
          if (r.top < vh && r.bottom > 0) reveal(el);
        }
      });
    }, 800);

    // 3. Observe the rest for scroll-triggered reveal.
    if (typeof IntersectionObserver === 'undefined') {
      // No IO support — reveal everything as final fallback.
      els.forEach(reveal);
      return () => clearTimeout(fallback);
    }
    const io = new IntersectionObserver(entries => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          reveal(e.target);
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.1 });
    els.forEach(el => io.observe(el));

    return () => {
      clearTimeout(fallback);
      io.disconnect();
    };
  }, []);
}

// ---- CTA block — call-to-action block (reusable) ----
function CTABlock({ eyebrow = "Let's talk", heading, body, primary, secondary, accent = null }) {
  return (
    <section className="section section-tall" style={accent ? { borderTop: `1px solid var(--hair)` } : {}}>
      <div className="container col gap-7" style={{ alignItems: 'flex-start', maxWidth: 920 }}>
        <span className="eyebrow" style={{ color: accent || 'var(--ink-4)' }}>{eyebrow}</span>
        <h2 className="h2">{heading}</h2>
        {body && <p className="body-l">{body}</p>}
        <div className="row gap-3" style={{ marginTop: 16, flexWrap: 'wrap' }}>
          {primary && <a href={primary.href} className="btn btn-primary btn-arrow">{primary.label}</a>}
          {secondary && <a href={secondary.href} className="btn btn-secondary">{secondary.label}</a>}
        </div>
      </div>
    </section>
  );
}

// Export to window for cross-file use
Object.assign(window, {
  SITE_BRANDS, LOGO_FILES, MONO_FILES, GMR_SMALL,
  Brand, SiteHeader, SiteFooter, PortfolioStrip, CTABlock,
  useRevealOnScroll,
});
