// ============================================================
// BVS — Legal pages (Privacy Policy + Terms of Service)
// Site design language (Helvetica Neue, brand tokens) rendered
// over the node-network background that darkens as you scroll.
// Content data lives in legal-data.js (window.BVS_LEGAL).
// ============================================================
const { useState: useLegalState, useEffect: useLegalEffect, useRef: useLegalRef } = React;

// Background gradient that spans the full scroll height → darkens downward.
const LEGAL_GRADIENT =
  'linear-gradient(180deg,#0c1fd0 0%,#0017DB 20%,#0a1566 50%,#050b30 76%,#01030f 100%)';
const PERIWINKLE = '#9DB0FF';

// ---- node-network canvas (drifting nodes + proximity links + cursor pull) ----
function NodeNet() {
  const ref = useLegalRef(null);
  useLegalEffect(() => {
    const canvas = ref.current;
    if (!canvas || !canvas.getContext) return;
    const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const ctx = canvas.getContext('2d');
    let w = 0, h = 0, dpr = 1, nodes = [], raf = 0;
    const mouse = { x: -9999, y: -9999 };
    const build = () => {
      dpr = Math.min(2, window.devicePixelRatio || 1);
      w = canvas.width = Math.floor(window.innerWidth * dpr);
      h = canvas.height = Math.floor(window.innerHeight * dpr);
      canvas.style.width = window.innerWidth + 'px';
      canvas.style.height = window.innerHeight + 'px';
      const count = Math.max(22, Math.min(58, Math.round(window.innerWidth * window.innerHeight / 23000)));
      nodes = [];
      for (let i = 0; i < count; i++) {
        nodes.push({
          x: Math.random() * w, y: Math.random() * h,
          vx: (Math.random() - 0.5) * 0.22 * dpr, vy: (Math.random() - 0.5) * 0.22 * dpr,
          mint: Math.random() < 0.16,
        });
      }
    };
    const drawFrame = () => {
      const dist = 150 * dpr;
      ctx.clearRect(0, 0, w, h);
      for (let i = 0; i < nodes.length; i++) {
        const n = nodes[i];
        n.x += n.vx; n.y += n.vy;
        if (n.x < 0 || n.x > w) n.vx *= -1;
        if (n.y < 0 || n.y > h) n.vy *= -1;
      }
      for (let i = 0; i < nodes.length; i++) {
        for (let j = i + 1; j < nodes.length; j++) {
          const a = nodes[i], b = nodes[j];
          const dx = a.x - b.x, dy = a.y - b.y;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < dist) {
            const al = (1 - d / dist) * 0.16;
            ctx.strokeStyle = 'rgba(150,178,255,' + al + ')';
            ctx.lineWidth = 1 * dpr;
            ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.stroke();
          }
        }
      }
      if (mouse.x > 0) {
        const mx = mouse.x * dpr, my = mouse.y * dpr, md = 190 * dpr;
        for (const n of nodes) {
          const dx = n.x - mx, dy = n.y - my;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < md) {
            const al = (1 - d / md) * 0.5;
            ctx.strokeStyle = 'rgba(180,200,255,' + al + ')';
            ctx.lineWidth = 1 * dpr;
            ctx.beginPath(); ctx.moveTo(n.x, n.y); ctx.lineTo(mx, my); ctx.stroke();
          }
        }
      }
      for (const n of nodes) {
        ctx.beginPath();
        ctx.arc(n.x, n.y, (n.mint ? 2.0 : 1.4) * dpr, 0, Math.PI * 2);
        ctx.fillStyle = n.mint ? 'rgba(150,235,160,0.9)' : 'rgba(190,205,255,0.62)';
        ctx.fill();
      }
    };
    const loop = () => { drawFrame(); raf = requestAnimationFrame(loop); };
    build();
    const onResize = () => build();
    const onMove = (e) => { mouse.x = e.clientX; mouse.y = e.clientY; };
    const onLeave = () => { mouse.x = -9999; mouse.y = -9999; };
    window.addEventListener('resize', onResize);
    window.addEventListener('pointermove', onMove, { passive: true });
    window.addEventListener('pointerleave', onLeave);
    if (reduce) drawFrame(); else raf = requestAnimationFrame(loop);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', onResize);
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerleave', onLeave);
    };
  }, []);
  return <canvas ref={ref} aria-hidden="true" style={{ position: 'fixed', inset: 0, zIndex: 0, pointerEvents: 'none', display: 'block' }}></canvas>;
}

// ---- one numbered legal section ----
function LegalSection({ s }) {
  const ref = useReveal();
  return (
    <section ref={ref} id={'section-' + s.num} data-screen-label={s.title} className="legal-sec reveal">
      <div className="legal-sec-num">
        <span className="mono" style={{ fontWeight: 700, fontSize: 30, color: PERIWINKLE, letterSpacing: '-0.02em', lineHeight: 1 }}>{s.num}</span>
        <span style={{ width: 30, height: 2, background: 'rgba(157,176,255,0.55)', display: 'block' }}></span>
      </div>
      <div style={{ flex: '1 1 440px', minWidth: 0 }}>
        <h2 style={{ fontFamily: 'var(--bvs-sans)', fontWeight: 700, fontSize: 'clamp(22px,3.2vw,30px)', lineHeight: 1.15, letterSpacing: '-0.02em', color: '#fff', margin: '0 0 20px' }}>{s.title}</h2>
        {s.summary && (
          <div className="legal-plain">
            <span className="legal-plain-mark"></span>
            <div style={{ minWidth: 0 }}>
              <div className="mono" style={{ fontSize: 10.5, letterSpacing: '0.24em', textTransform: 'uppercase', color: GREEN, marginBottom: 7 }}>In plain language</div>
              <p style={{ margin: 0, fontSize: 15.5, lineHeight: 1.6, color: 'rgba(225,255,222,0.95)' }}>{s.summary}</p>
            </div>
          </div>
        )}
        {s.body.map((b, i) => b.sub ? (
          <h3 key={i} style={{ fontFamily: 'var(--bvs-sans)', fontWeight: 700, fontSize: 15.5, letterSpacing: '0.01em', color: '#fff', margin: '26px 0 11px', display: 'flex', alignItems: 'center', gap: 11 }}>
            <span style={{ width: 14, height: 2, background: PERIWINKLE, display: 'inline-block', flex: 'none' }}></span>{b.text}
          </h3>
        ) : (
          <p key={i} style={{ margin: '0 0 16px', fontSize: 16.5, lineHeight: 1.8, color: 'rgba(232,234,247,0.8)' }}>{b.text}</p>
        ))}
      </div>
    </section>
  );
}

// ---- full legal page (privacy | terms) ----
function LegalPage({ kind, onNav }) {
  const data = (window.BVS_LEGAL && window.BVS_LEGAL[kind]) || { sections: [], contacts: [], title: '', kicker: '', intro: '', contactLead: '' };
  const [progress, setProgress] = useLegalState(0);
  const [showTop, setShowTop] = useLegalState(false);
  const total = data.sections.length + 1; // +1 for contact

  useLegalEffect(() => {
    const onScroll = () => {
      const el = document.documentElement;
      const max = el.scrollHeight - el.clientHeight;
      setProgress(max > 0 ? Math.min(1, window.scrollY / max) : 0);
      setShowTop(window.scrollY > 620);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    const r = requestAnimationFrame(() => applyReveal(Array.from(document.querySelectorAll('.reveal:not(.pre)'))));
    return () => { window.removeEventListener('scroll', onScroll); cancelAnimationFrame(r); };
  }, [kind]);

  return (
    <div style={{ position: 'relative', background: LEGAL_GRADIENT, minHeight: '100vh', width: '100%', overflowX: 'hidden' }}>
      <NodeNet />
      <div aria-hidden="true" style={{ position: 'fixed', inset: 0, zIndex: 1, pointerEvents: 'none', background: 'radial-gradient(72% 56% at 50% 42%, rgba(2,5,26,0.5) 0%, rgba(2,5,26,0.22) 48%, rgba(2,5,26,0) 80%)' }}></div>
      <div aria-hidden="true" style={{ position: 'fixed', top: 0, left: 0, height: 3, width: '100%', transform: 'scaleX(' + progress + ')', transformOrigin: 'left center', background: 'linear-gradient(90deg,' + GREEN + ',' + PERIWINKLE + ' 55%,#fff)', zIndex: 55, willChange: 'transform' }}></div>

      {/* HERO */}
      <section data-screen-label={data.title + ' — Hero'} className="legal-hero" style={{ position: 'relative', zIndex: 2 }}>
        <div className="legal-hero-grid" aria-hidden="true"></div>
        <div className="legal-hero-ghost mono" aria-hidden="true">»</div>
        <div style={{ maxWidth: 860, margin: '0 auto', position: 'relative' }}>
          <div className="reveal mono" style={{ display: 'flex', alignItems: 'center', gap: 12, fontSize: 12, letterSpacing: '0.3em', textTransform: 'uppercase', color: GREEN, marginBottom: 26 }}>
            <span style={{ width: 28, height: 1, background: GREEN, display: 'inline-block' }}></span>{data.kicker}
          </div>
          <h1 className="reveal" style={{ fontFamily: 'var(--bvs-sans)', fontWeight: 700, fontSize: 'clamp(46px,8.5vw,104px)', lineHeight: 0.94, letterSpacing: '-0.035em', textTransform: 'uppercase', color: '#fff', margin: '0 0 30px', ...delay(1) }}>{data.title}</h1>
          <div className="reveal" style={{ display: 'flex', flexWrap: 'wrap', gap: 10, marginBottom: 34, ...delay(2) }}>
            <span className="mono legal-pill legal-pill-solid"><span style={{ width: 6, height: 6, background: BLUE, display: 'inline-block' }}></span>Effective {data.effectiveDate}</span>
            <span className="mono legal-pill legal-pill-ghost">{total} Sections</span>
          </div>
          <p className="reveal" style={{ maxWidth: 700, fontSize: 'clamp(16px,2vw,19px)', lineHeight: 1.72, color: 'rgba(255,255,255,0.9)', margin: 0, ...delay(3) }}>{data.intro}</p>
        </div>
      </section>

      {/* SECTIONS */}
      <main style={{ position: 'relative', zIndex: 2, maxWidth: 940, margin: '0 auto', padding: 'clamp(36px,6vw,64px) clamp(22px,6vw,80px) 40px' }}>
        {data.sections.map((s) => <LegalSection key={s.num} s={s} />)}

        {/* CONTACT */}
        <section className="legal-sec reveal" data-screen-label="Contact">
          <div className="legal-sec-num">
            <span className="mono" style={{ fontWeight: 700, fontSize: 30, color: PERIWINKLE, letterSpacing: '-0.02em', lineHeight: 1 }}>{String(total).padStart(2, '0')}</span>
            <span style={{ width: 30, height: 2, background: 'rgba(157,176,255,0.55)', display: 'block' }}></span>
          </div>
          <div style={{ flex: '1 1 440px', minWidth: 0 }}>
            <h2 style={{ fontFamily: 'var(--bvs-sans)', fontWeight: 700, fontSize: 'clamp(22px,3.2vw,30px)', lineHeight: 1.15, letterSpacing: '-0.02em', color: '#fff', margin: '0 0 20px' }}>Contact Us</h2>
            <p style={{ margin: '0 0 28px', fontSize: 16.5, lineHeight: 1.8, color: 'rgba(232,234,247,0.8)', maxWidth: 600 }}>{data.contactLead}</p>
            <div className="legal-contact-grid">
              {data.contacts.map((c) => (
                <a key={c.label} href={c.href} className="legal-contact">
                  <div className="mono" style={{ fontSize: 10.5, letterSpacing: '0.24em', textTransform: 'uppercase', color: PERIWINKLE, marginBottom: 12 }}>{c.label}</div>
                  <div style={{ fontFamily: 'var(--bvs-sans)', fontSize: 17, fontWeight: 600, color: '#fff', wordBreak: 'break-word', lineHeight: 1.3 }}>{c.value}</div>
                </a>
              ))}
            </div>
            <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', marginTop: 36 }}>
              <Button kind="white" onClick={() => onNav(kind === 'privacy' ? 'terms' : 'privacy')} arrow>
                {kind === 'privacy' ? 'Read Terms of Service' : 'Read Privacy Policy'}
              </Button>
              <Button kind="ghost-w" onClick={() => onNav('home')}>Back to site</Button>
            </div>
          </div>
        </section>
      </main>

      <button onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} aria-label="Back to top"
        style={{ position: 'fixed', bottom: 28, right: 28, zIndex: 56, width: 46, height: 46, border: '1px solid rgba(255,255,255,0.16)', background: 'rgba(0,23,219,0.92)', color: '#fff', borderRadius: 3, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', opacity: showTop ? 1 : 0, transform: showTop ? 'none' : 'translateY(12px)', pointerEvents: showTop ? 'auto' : 'none', transition: 'opacity .3s var(--ease), transform .3s var(--ease)', boxShadow: '0 8px 26px rgba(0,23,219,0.32)' }}>
        <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 13V3M8 3L3.5 7.5M8 3L12.5 7.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="square"></path></svg>
      </button>
    </div>
  );
}

const Privacy = ({ onNav }) => <LegalPage kind="privacy" onNav={onNav} />;
const Terms = ({ onNav }) => <LegalPage kind="terms" onNav={onNav} />;

Object.assign(window, { Privacy, Terms, LegalPage, NodeNet });
