// Resultaatpagina: benchmark, strategie, data, kanalen, CTA's
// Alle teksten en cijfers komen uit `data` (door de server gegenereerd per scan).

// Vaste bucket-labels — identiek aan de opties van de spend-vraag
const BUCKET_LABELS = ['< €1.000', '€1.000 – €2.500', '€2.500 – €5.000', '€5.000 – €10.000', '€10.000 – €20.000', '€20.000+'];

// Echte specialisten van Brandmerck, gekoppeld aan kanaal-key
const EXPERTS = {
  sea: { name: 'Nico Zeinstra', role: 'Senior SEA-specialist', photo: 'images/expert-nico.jpg' },
  seo: { name: 'Thijs van Beijeren', role: 'SEO-specialist', photo: 'images/expert-thijs.jpg' },
  social: { name: 'Esther Wijbenga', role: 'Social & Google Ads-specialist', photo: 'images/expert-esther.jpg' },
};

// Fallback als reviews.json (echte reviews, zie server/fetch-reviews.js) ontbreekt
const REVIEWS_FALLBACK = [
  { text: 'Met veel SEO-bedrijven gewerkt, maar geen enkele kwam met daadwerkelijke verbetering. Brandmerck deed dit wel.', name: 'Eigenaar beveiligingsbedrijf', rating5: 5 },
  { text: 'Een duidelijke doelstelling en strategie na het eerste gesprek. Binnen één jaar uitstekende resultaten.', name: 'De Kreij Horeca', rating5: 5 },
  { text: 'Goede communicatie en korte lijnen! Leuke, enthousiaste mensen en veel kennis in huis.', name: 'MKB-ondernemer', rating5: 5 },
];

// useReviewsData / nlRating / ReviewBadge komen uit groeiscan-shared.jsx

function ResultHeader({ lead, data }) {
  return (
    <header style={{ background: '#fff' }}>
      {/* Topbar */}
      <div style={{ background: 'var(--bm-dark)', padding: '22px clamp(20px, 6vw, 72px)' }}>
        <div style={{ maxWidth: 1080, margin: '0 auto', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
          <BmLogo light />
          <CtaButton>Bespreek met een strateeg</CtaButton>
        </div>
      </div>

      {/* Hero met foto + diagonaal teal vlak */}
      <div style={{ position: 'relative', minHeight: 'clamp(320px, 42vw, 480px)', overflow: 'hidden', background: 'var(--bm-dark)' }}>
        <img src="images/overleg.jpg" alt="Overleg bij Brandmerck"
          style={{ position: 'absolute', top: 0, bottom: 0, left: '22%', width: '78%', height: '100%', objectFit: 'cover', objectPosition: 'center 25%' }} />
        <div style={{
          position: 'absolute', inset: 0, background: 'var(--bm-dark)',
          clipPath: 'polygon(0 0, 28% 0, 52% 100%, 0 100%)'
        }}></div>
        <div style={{
          position: 'absolute', left: 0, right: 0, bottom: 'clamp(28px, 6vw, 64px)',
          padding: '0 clamp(20px, 6vw, 72px)'
        }}>
          <div style={{ maxWidth: 1080, margin: '0 auto' }}>
            <span style={{
              display: 'inline-block', border: '1.5px solid #fff', color: '#fff',
              fontSize: 13, fontWeight: 700, letterSpacing: '2px', textTransform: 'uppercase',
              padding: '8px 16px', marginBottom: 18
            }}>Jouw groeiplan</span>
            <h1 style={{
              color: '#fff', fontWeight: 900, fontSize: 'clamp(30px, 4.4vw, 52px)',
              margin: 0, lineHeight: 1.1, maxWidth: 720,
              textShadow: '0 2px 16px rgba(9,43,41,0.35)'
            }}>
              Groeiplan voor {lead.website}
            </h1>
          </div>
        </div>
      </div>

      {/* Intro-band: teal panel met notch, badges rechts op wit */}
      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.5fr) minmax(240px, 1fr)', alignItems: 'stretch' }} className="gs-two-col">
        <div style={{
          background: 'var(--bm-dark)', color: '#C6DBD9',
          padding: '36px clamp(20px, 6vw, 72px) 40px',
          clipPath: 'polygon(0 0, 100% 0, 100% calc(100% - 26px), calc(100% - 26px) 100%, 0 100%)'
        }}>
          <p style={{ margin: 0, fontSize: 16, lineHeight: 1.7, maxWidth: 640 }}>
            {data.intro}{lead.email ? ` Ook verstuurd naar ${lead.email}.` : ''}
          </p>
        </div>
        <ResultHeaderBadges />
      </div>
    </header>
  );
}

// Reviewscores in de headerband: gecombineerd gemiddelde + beide bronnen
function ResultHeaderBadges() {
  const data = useReviewsData();
  const g = data?.google, f = data?.feedback_company;
  return (
    <div style={{ background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 22, padding: '24px 20px' }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontWeight: 900, fontSize: 24, color: '#12302E' }}>{nlRating(g?.rating) || '4,7'} <span style={{ color: '#F4B400', fontSize: 18 }}>★</span></div>
        <div style={{ fontSize: 12, color: '#5A7472' }}>{g?.count ? `${g.count} Google-reviews` : 'Google-reviews'}</div>
      </div>
      <div style={{ width: 1, height: 44, background: '#E4EDEC' }}></div>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontWeight: 900, fontSize: 24, color: '#12302E' }}>{nlRating(f?.rating) || '9,2'}<span style={{ color: '#5A7472', fontSize: 14, fontWeight: 700 }}>/10</span></div>
        <div style={{ fontSize: 12, color: '#5A7472' }}>{f?.count ? `${f.count} reviews · The Feedback Company` : 'The Feedback Company'}</div>
      </div>
    </div>
  );
}

function SectionShell({ num, tag, title, children, alt }) {
  return (
    <section style={{ background: alt ? 'var(--bm-mist)' : '#fff', padding: '58px clamp(20px, 6vw, 72px)' }}>
      <div style={{ maxWidth: 1080, margin: '0 auto' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14 }}>
          <span style={{ fontFamily: "'Lato', sans-serif", fontWeight: 900, fontSize: 15, color: 'var(--bm-teal)', letterSpacing: '1px' }}>{num}</span>
          <SectionTag>{tag}</SectionTag>
        </div>
        <h2 style={{ fontWeight: 900, fontSize: 'clamp(22px, 2.8vw, 30px)', color: '#12302E', margin: '0 0 24px', textWrap: 'balance' }}>{title}</h2>
        {children}
      </div>
    </section>
  );
}

function BenchmarkSection({ answers, benchView, data, num }) {
  const bench = data.benchmark;
  const buckets = BUCKET_LABELS.map((label, i) => ({ label, pct: bench.bucket_pcts[i] ?? 0 }));
  const spend = answers.spend;
  // In welke bucket valt de eigen uitgave?
  const ownBucket = spend === 'Minder dan €1.000' ? 0
    : spend === '€1.000 – €2.500' ? 1
    : spend === '€2.500 – €5.000' ? 2
    : spend === '€5.000 – €10.000' ? 3
    : spend === '€10.000 – €20.000' ? 4
    : spend === 'Meer dan €20.000' ? 5 : null;
  const sweetSpot = bench.sweet_spot || [];
  const max = Math.max(...buckets.map(b => b.pct), 1);

  return (
    <SectionShell num={num} tag="Benchmark" title="Wat investeren bedrijven zoals jij per maand?">
      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(260px, 340px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div>
          {benchView === 'range' ? (
            <NotchCard style={{ padding: '34px 30px', textAlign: 'center' }} notch={16}>
              <p style={{ margin: '0 0 4px', fontSize: 13, fontWeight: 700, letterSpacing: '1px', textTransform: 'uppercase', color: '#5A7472' }}>Gemiddelde maandelijkse investering</p>
              <div style={{ fontSize: 'clamp(36px, 5vw, 52px)', fontWeight: 900, color: 'var(--bm-teal-ink)' }}>{bench.range_value}</div>
              <p style={{ margin: '8px 0 0', color: '#5A7472', fontSize: 14 }}>{bench.range_sub}</p>
            </NotchCard>
          ) : (
            <div>
              <div style={{ display: 'grid', gridTemplateColumns: `repeat(${buckets.length}, 1fr)`, gap: 10, alignItems: 'end', height: 220 }}>
                {buckets.map((b, i) => {
                  const isSweet = sweetSpot.includes(i);
                  const isOwn = i === ownBucket;
                  return (
                    <div key={b.label} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, height: '100%', justifyContent: 'flex-end' }}>
                      <span style={{ fontSize: 13, fontWeight: 900, color: isSweet ? 'var(--bm-teal-ink)' : '#8AA3A1' }}>{b.pct}%</span>
                      <div title={b.label} style={{
                        width: '100%', height: `${(b.pct / max) * 150}px`, borderRadius: '4px 4px 0 0',
                        background: isSweet ? 'var(--bm-teal)' : '#CBDDDB',
                        outline: isOwn ? '3px solid var(--bm-cta-1)' : 'none', outlineOffset: 2,
                        transition: 'height 0.6s ease'
                      }}></div>
                    </div>
                  );
                })}
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: `repeat(${buckets.length}, 1fr)`, gap: 10, marginTop: 8 }}>
                {buckets.map((b, i) => (
                  <span key={b.label} style={{ fontSize: 11.5, textAlign: 'center', color: i === ownBucket ? 'var(--bm-cta-1)' : '#5A7472', fontWeight: i === ownBucket ? 900 : 400, lineHeight: 1.3 }}>
                    {b.label}{i === ownBucket ? <><br />← jij nu</> : ''}
                  </span>
                ))}
              </div>
              <p style={{ marginTop: 18, fontSize: 13, color: '#8AA3A1' }}>{bench.caption}</p>
            </div>
          )}
        </div>
        <NotchCard style={{ padding: '26px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 10px', fontSize: 16, fontWeight: 900, color: '#fff' }}>Wat betekent dit?</h3>
          <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.65, color: '#C6DBD9' }}>{bench.panel_p1}</p>
          <p style={{ margin: '12px 0 0', fontSize: 14.5, lineHeight: 1.65, color: '#C6DBD9' }}>{bench.panel_p2}</p>
          <p style={{ margin: '14px 0 0', fontSize: 13, color: '#8FB5B1' }}>{bench.panel_p3}</p>
        </NotchCard>
      </div>
    </SectionShell>
  );
}

function StrategySection({ data, num }) {
  const strat = data.strategy;
  return (
    <SectionShell num={num} tag="Strategie" title="Welke kanalen passen bij jouw bedrijf?" alt>
      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.2fr) minmax(0, 0.8fr)', gap: 'clamp(24px, 4vw, 48px)' }} className="gs-two-col">
        <div style={{ fontSize: 15.5, lineHeight: 1.7, color: '#3A5250' }}>
          {strat.paragraphs.map((p, i) => (
            <p key={i} style={{ marginTop: i === 0 ? 0 : undefined, marginBottom: i === strat.paragraphs.length - 1 ? 0 : undefined }}>{p}</p>
          ))}
        </div>
        <NotchCard style={{ padding: '26px 24px' }} notch={16}>
          <h3 style={{ margin: '0 0 14px', fontSize: 15, fontWeight: 900 }}>Aanbevolen mix</h3>
          {strat.mix.map(({ name, pct }) => (
            <div key={name} style={{ marginBottom: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13.5, fontWeight: 700, marginBottom: 5 }}>
                <span>{name}</span><span style={{ color: 'var(--bm-teal-ink)' }}>{pct}%</span>
              </div>
              <div style={{ height: 10, background: '#E4EDEC', borderRadius: 999 }}>
                <div style={{ width: `${pct}%`, height: '100%', background: 'var(--bm-teal)', borderRadius: 999 }}></div>
              </div>
            </div>
          ))}
          <p style={{ margin: '4px 0 0', fontSize: 12.5, color: '#8AA3A1' }}>{strat.mix_caption}</p>
        </NotchCard>
      </div>
    </SectionShell>
  );
}

// ── Sectie 03 vóór het onderzoek: formulier + mini-loader ──────────────────

const RESEARCH_STEPS = ['Zoektermen bepalen', 'Zoekvolumes ophalen', 'Posities meten', 'Concurrentie vergelijken', 'Onderbouwing schrijven'];

const REGION_OPTIONS = [
  { key: 'landelijk', label: 'Heel Nederland' },
  { key: 'provincie', label: 'Vooral in mijn provincie' },
];
const PROVINCIES = [
  { key: 'groningen', label: 'Groningen' }, { key: 'friesland', label: 'Friesland' },
  { key: 'drenthe', label: 'Drenthe' }, { key: 'overijssel', label: 'Overijssel' },
  { key: 'flevoland', label: 'Flevoland' }, { key: 'gelderland', label: 'Gelderland' },
  { key: 'utrecht', label: 'Utrecht' }, { key: 'noord-holland', label: 'Noord-Holland' },
  { key: 'zuid-holland', label: 'Zuid-Holland' }, { key: 'zeeland', label: 'Zeeland' },
  { key: 'noord-brabant', label: 'Noord-Brabant' }, { key: 'limburg', label: 'Limburg' },
];
const AUDIENCE_OPTIONS = [
  { key: 'b2b', label: 'Zakelijke klanten (B2B)' },
  { key: 'b2c', label: 'Consumenten (B2C)' },
  { key: 'beide', label: 'Beide' },
];

function ChipRow({ options, value, onPick }) {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
      {options.map((o) => {
        const active = value === o.key;
        return (
          <button key={o.key} type="button" onClick={() => onPick(o.key)} className="gs-chip" style={active ? {
            background: 'var(--bm-teal)', borderColor: 'var(--bm-teal)', color: '#fff',
          } : undefined}>{o.label}</button>
        );
      })}
    </div>
  );
}

function FieldLabel({ children, hint }) {
  return (
    <div style={{ margin: '0 0 10px' }}>
      <div style={{ fontSize: 14.5, fontWeight: 900, color: '#12302E' }}>{children}</div>
      {hint && <div style={{ fontSize: 12.5, color: '#8AA3A1', marginTop: 2 }}>{hint}</div>}
    </div>
  );
}

function ResearchSection({ data, scanId, onResearchDone, num, leadEmail, onEmail }) {
  const { useState, useEffect, useRef } = React;
  const [mode, setMode] = useState('form'); // 'form' | 'running'
  const [services, setServices] = useState([]);           // geselecteerd (max 3)
  const [customServices, setCustomServices] = useState([]); // zelf toegevoegde chips
  const [customInput, setCustomInput] = useState('');
  const [comps, setComps] = useState([]);                  // geselecteerde concurrenten (max 3)
  const [customComps, setCustomComps] = useState([]);      // zelf toegevoegde concurrent-chips
  const [compInput, setCompInput] = useState('');
  const [scope, setScope] = useState('landelijk');
  const [place, setPlace] = useState('');
  const [audience, setAudience] = useState('beide');
  const [error, setError] = useState('');
  const [step, setStep] = useState(0);
  // wizard: 0 doelgroep+regio, 1 diensten, 2 zoekwoorden cureren, 3 concurrenten+start
  const [formStep, setFormStep] = useState(0);
  const [provincie, setProvincie] = useState('');
  const [kwData, setKwData] = useState(null);      // perDienst-resultaat van /keywords
  const [kwSelected, setKwSelected] = useState([]); // gekozen zoektermen
  const [kwLoading, setKwLoading] = useState(false);
  const [compSuggesties, setCompSuggesties] = useState(null);
  const [compLoading, setCompLoading] = useState(false);
  // E-mail wordt pas bij de zoekwoorden-stap gevraagd; de termen laden
  // ondertussen op de achtergrond zodat de wachttijd wegvalt.
  const [emailOk, setEmailOk] = useState(!!leadEmail);
  const [emailVal, setEmailVal] = useState('');
  const [emailErr, setEmailErr] = useState('');
  const [emailBusy, setEmailBusy] = useState(false);
  const doneRef = useRef(false);

  async function saveEmail(e) {
    e.preventDefault();
    const em = emailVal.trim();
    if (!/^\S+@\S+\.\S+$/.test(em)) { setEmailErr('Vul een geldig e-mailadres in'); return; }
    setEmailErr(''); setEmailBusy(true);
    try {
      const res = await fetch(`/api/scan/${scanId}/email`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: em }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setEmailErr(d.error || 'Opslaan mislukte, probeer het opnieuw.');
        return;
      }
      if (onEmail) onEmail(em);
      setEmailOk(true);
    } catch {
      setEmailErr('Geen verbinding, probeer het opnieuw.');
    } finally {
      setEmailBusy(false);
    }
  }
  const regionBody = () => scope === 'provincie' ? { scope: 'provincie', provincie } : { scope: 'landelijk', place: '' };

  // Stap 2 → 3: zoektermen per dienst genereren en laten cureren
  async function loadKeywords() {
    setKwLoading(true); setError('');
    try {
      const res = await fetch(`/api/scan/${scanId}/keywords`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ services, region: regionBody(), audience }),
      });
      const d = await res.json().catch(() => ({}));
      if (!res.ok) { setError(d.error || 'Zoektermen ophalen mislukte. Probeer het opnieuw.'); setFormStep(1); return; }
      setKwData(d.perDienst);
      setKwSelected(d.perDienst.flatMap((x) => x.termen.map((t) => t.kw)));
    } catch (e) {
      setError('Geen verbinding. Probeer het opnieuw.'); setFormStep(1);
    } finally {
      setKwLoading(false);
    }
  }

  // Stap 3 → 4: concurrent-suggesties uit de SERP's van de gekozen termen.
  // Harde client-time-out: na 45s tonen we gewoon het lege-suggesties-pad
  // (zelf invullen kan altijd), zodat de stap nooit blijft hangen.
  async function loadCompSuggesties(chosen) {
    setCompLoading(true);
    try {
      const byVol = new Map((kwData || []).flatMap((d) => d.termen).map((t) => [t.kw, t.volRaw]));
      const sample = [...chosen].sort((a, b) => (byVol.get(b) || 0) - (byVol.get(a) || 0)).slice(0, 4);
      const res = await fetch(`/api/scan/${scanId}/competitors-suggest`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ keywords: sample, region: regionBody() }),
        signal: AbortSignal.timeout(45000),
      });
      const d = await res.json().catch(() => ({}));
      setCompSuggesties(Array.isArray(d.suggestions) ? d.suggestions : []);
    } catch (e) {
      setCompSuggesties([]);
    } finally {
      setCompLoading(false);
    }
  }

  const allServices = [...(data.suggestedServices || []), ...customServices];

  function toggleService(s) {
    setError('');
    setServices((cur) => cur.includes(s) ? cur.filter((x) => x !== s) : cur.length >= 3 ? cur : [...cur, s]);
  }

  function addCustom() {
    const s = customInput.trim().slice(0, 60);
    if (!s) return;
    if (!allServices.some((x) => x.toLowerCase() === s.toLowerCase())) setCustomServices((cur) => [...cur, s]);
    if (services.length < 3 && !services.includes(s)) setServices((cur) => [...cur, s]);
    setCustomInput('');
  }

  const allComps = [...(data.suggestedCompetitors || []), ...customComps];

  function toggleComp(d) {
    setError('');
    setComps((cur) => cur.includes(d) ? cur.filter((x) => x !== d) : cur.length >= 2 ? cur : [...cur, d]);
  }

  function addCompCustom() {
    // lichte normalisatie voor de chip; de server valideert het domein definitief
    const d = compInput.trim().toLowerCase().replace(/^https?:\/\//, '').split(/[/?#]/)[0].slice(0, 60);
    if (!d) return;
    if (!allComps.some((x) => x === d)) setCustomComps((cur) => [...cur, d]);
    if (comps.length < 2 && !comps.includes(d)) setComps((cur) => [...cur, d]);
    setCompInput('');
  }

  async function start() {
    if (!services.length) { setError('Kies minimaal één dienst om op te onderzoeken.'); return; }
    setError('');
    // Geen concurrenten gekozen → de twee sterkste suggesties uit de SERP's
    const chosenComps = comps.length ? comps.slice(0, 2) : (compSuggesties || []).slice(0, 2);
    // Term → dienst-koppeling zodat het rapport de zoektermen per dienst groepeert
    const keywordDiensten = Object.fromEntries((kwData || []).flatMap((d) =>
      d.termen.filter((t) => kwSelected.includes(t.kw)).map((t) => [t.kw, d.dienst])));
    setMode('running'); setStep(0);
    try {
      const res = await fetch(`/api/scan/${scanId}/research`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          services,
          competitors: chosenComps,
          region: regionBody(),
          audience,
          keywords: kwSelected.slice(0, 24),
          keywordDiensten,
        }),
      });
      if (!res.ok && res.status !== 409) {
        const d = await res.json().catch(() => ({}));
        setError(d.error || 'Het onderzoek kon niet worden gestart. Probeer het opnieuw.');
        setMode('form');
      }
      // 409 "loopt al" → gewoon doorpollen
    } catch (e) {
      setError('Geen verbinding. Controleer je internet en probeer het opnieuw.');
      setMode('form');
    }
  }

  // Bij mount: loopt er al een onderzoek (bv. na een refresh)? Dan meteen doorpollen.
  useEffect(() => {
    let cancelled = false;
    fetch(`/api/scan/${scanId}/research`).then((r) => r.json()).then((d) => {
      if (cancelled) return;
      if (d.status === 'running') setMode('running');
      else if (d.status === 'done' && d.result && !doneRef.current) { doneRef.current = true; onResearchDone(d.result); }
    }).catch(() => {});
    return () => { cancelled = true; };
  }, [scanId]);

  // Poll zolang het onderzoek loopt
  useEffect(() => {
    if (mode !== 'running') return;
    let stopped = false;
    let idlePolls = 0;
    async function poll() {
      try {
        const res = await fetch(`/api/scan/${scanId}/research`);
        const d = await res.json();
        if (stopped) return;
        if (d.status === 'running') { setStep(d.step ?? 0); return; }
        if (d.status === 'done' && d.result) {
          if (!doneRef.current) { doneRef.current = true; gsTrack('research_ready', { product: 'groeiscan', scan_id: scanId }, scanId); onResearchDone(d.result); }
          return;
        }
        if (d.status === 'error') { setError(d.error || 'Er ging iets mis bij het onderzoek. Probeer het opnieuw.'); setMode('form'); return; }
        // 'idle' vlak na de start kan een race zijn — na een paar polls opgeven
        if (++idlePolls >= 5) { setError('Het onderzoek is niet gestart. Probeer het opnieuw.'); setMode('form'); }
      } catch (e) { /* netwerk-hikje: volgende poll */ }
    }
    const iv = setInterval(poll, 1500);
    poll();
    return () => { stopped = true; clearInterval(iv); };
  }, [mode, scanId]);

  return (
    <SectionShell num={num} tag="Onderzoek" title="Wie pakt jouw klanten op Google en de socials?">
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>
        Kies je diensten en zie het live: jouw posities naast die van je concurrenten, wie er adverteert
        in Google én op social, en wat dat verkeer waard is. Gemeten met professionele bureaudata (live
        Google-metingen en Semrush), vertaald naar een concreet SEO- en Google Ads-plan. Gratis, een paar
        minuten werk.
      </p>

      {mode === 'running' ? (
        <NotchCard style={{ padding: '32px 30px', maxWidth: 560 }} notch={16}>
          <style>{`@keyframes gs-spin { to { transform: rotate(360deg); } }`}</style>
          <h3 style={{ margin: '0 0 18px', fontSize: 18, fontWeight: 900 }}>We onderzoeken je groeikansen…</h3>
          <div style={{ display: 'grid', gap: 0 }}>
            {RESEARCH_STEPS.map((s, i) => {
              const isDone = i < step;
              const isActive = i === step;
              return (
                <div key={s} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '7px 0', opacity: isDone || isActive ? 1 : 0.45 }}>
                  <span style={{
                    width: 26, height: 26, borderRadius: '50%', flex: '0 0 auto',
                    display: 'grid', placeItems: 'center', fontSize: 13, fontWeight: 900,
                    background: isDone ? 'var(--bm-teal)' : 'transparent',
                    border: isDone ? 'none' : isActive ? '2.5px solid var(--bm-teal)' : '2px solid #CBDDDB',
                    borderTopColor: isActive ? 'transparent' : undefined,
                    color: '#fff',
                    animation: isActive ? 'gs-spin 0.9s linear infinite' : 'none',
                  }}>{isDone ? '✓' : ''}</span>
                  <span style={{ color: isDone ? '#5A7472' : isActive ? '#12302E' : '#8AA3A1', fontSize: 15, fontWeight: isActive ? 900 : 400 }}>{s}</span>
                </div>
              );
            })}
          </div>
          <p style={{ margin: '16px 0 0', fontSize: 12.5, color: '#8AA3A1' }}>
            We halen live data op uit Google. Dit duurt ongeveer een minuut.
          </p>
        </NotchCard>
      ) : (
        <NotchCard style={{ padding: '28px 30px 28px', maxWidth: 720 }} notch={16}>
          {/* Spinner-animatie hier definiëren zodat elke wizard-stap hem heeft */}
          <style>{`@keyframes gs-spin { to { transform: rotate(360deg); } }`}</style>
          {/* Wizard-voortgang */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 6 }}>
            {formStep > 0 && (
              <button type="button" onClick={() => { setError(''); setFormStep(formStep - 1); }}
                style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 13, fontWeight: 700, color: '#8AA3A1', padding: 0, fontFamily: "'Lato', sans-serif" }}>
                ← Terug
              </button>
            )}
            <span style={{ fontSize: 12.5, fontWeight: 800, color: 'var(--bm-teal-ink)', marginLeft: 'auto' }}>Stap {formStep + 1} van 4</span>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 6, marginBottom: 24 }}>
            {[0, 1, 2, 3].map((i) => (
              <div key={i} style={{ height: 5, borderRadius: 999, background: i <= formStep ? 'var(--bm-teal)' : '#EEF4F3' }}></div>
            ))}
          </div>

          {/* Stap 1: doelgroep + regio — stuurt alle vervolgmetingen */}
          {formStep === 0 && (
            <React.Fragment>
              <FieldLabel hint="Bepaalt welke zoektermen en kanalen we voor je doorrekenen.">Voor wie werk je vooral?</FieldLabel>
              <div style={{ marginBottom: 22 }}>
                <ChipRow options={AUDIENCE_OPTIONS} value={audience} onPick={(k) => { setAudience(k); setError(''); }} />
              </div>
              <FieldLabel hint="We meten jouw posities en concurrenten dan vanuit dit gebied.">Waar zoek je klanten?</FieldLabel>
              <div style={{ marginBottom: scope === 'provincie' ? 12 : 26 }}>
                <ChipRow options={REGION_OPTIONS} value={scope} onPick={(k) => { setScope(k); setError(''); }} />
              </div>
              {scope === 'provincie' && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 26 }}>
                  {PROVINCIES.map((p) => (
                    <button key={p.key} type="button" onClick={() => { setProvincie(p.key); setError(''); }} className="gs-chip"
                      style={provincie === p.key ? { background: 'var(--bm-teal)', borderColor: 'var(--bm-teal)', color: '#fff' } : undefined}>{p.label}</button>
                  ))}
                </div>
              )}
              {error && <div style={{ color: '#C4441C', fontSize: 13.5, fontWeight: 700, marginBottom: 14 }}>{error}</div>}
              <CtaButton onClick={() => {
                if (scope === 'provincie' && !provincie) { setError('Kies je provincie.'); return; }
                setError(''); setFormStep(1);
              }}>Volgende stap →</CtaButton>
            </React.Fragment>
          )}

          {/* Stap 2: diensten */}
          {formStep === 1 && (
            <React.Fragment>
              <FieldLabel hint="Kies er maximaal 3, daar richten we het onderzoek op.">
                Welke diensten zijn voor jou het belangrijkst? <span style={{ color: 'var(--bm-teal-ink)' }}>({services.length}/3)</span>
              </FieldLabel>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 12 }}>
                {allServices.map((s) => {
                  const active = services.includes(s);
                  return (
                    <button key={s} type="button" onClick={() => toggleService(s)} className="gs-chip" style={active ? {
                      background: 'var(--bm-teal)', borderColor: 'var(--bm-teal)', color: '#fff',
                    } : services.length >= 3 ? { opacity: 0.5, cursor: 'default' } : undefined}>{s}</button>
                  );
                })}
              </div>
              <div style={{ display: 'flex', gap: 10, marginBottom: 26 }}>
                <input value={customInput} onChange={(e) => setCustomInput(e.target.value)}
                  onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCustom(); } }}
                  placeholder="Andere dienst…" className="gs-input" style={{ maxWidth: 280 }} />
                <button type="button" onClick={addCustom} className="gs-chip" style={{ flex: '0 0 auto' }}>+ Toevoegen</button>
              </div>
              {error && <div style={{ color: '#C4441C', fontSize: 13.5, fontWeight: 700, marginBottom: 14 }}>{error}</div>}
              <CtaButton onClick={() => {
                if (!services.length) { setError('Kies minimaal één dienst om op te onderzoeken.'); return; }
                setError(''); setFormStep(2); loadKeywords();
              }}>Zoektermen ophalen →</CtaButton>
            </React.Fragment>
          )}

          {/* Stap 3: zoekwoorden cureren (met e-mailstap; de termen laden ondertussen) */}
          {formStep === 2 && (
            <React.Fragment>
              {!emailOk ? (
                <React.Fragment>
                  <FieldLabel hint="We meten ondertussen alvast de zoektermen per dienst. Het volledige onderzoek sturen we je ook per mail, dan kun je het er later altijd bij pakken.">
                    Waar mogen we het onderzoek naartoe sturen?
                  </FieldLabel>
                  <form onSubmit={saveEmail} style={{ display: 'grid', gap: 12, maxWidth: 440 }}>
                    <input value={emailVal} onChange={(e) => setEmailVal(e.target.value)} placeholder="naam@jouwbedrijf.nl" type="email" className="gs-input" />
                    {emailErr && <div style={{ color: '#C4441C', fontSize: 13, fontWeight: 700 }}>{emailErr}</div>}
                    <CtaButton type="submit" style={{ opacity: emailBusy ? 0.6 : 1 }}>
                      {emailBusy ? 'Even geduld…' : 'Opslaan en verder →'}
                    </CtaButton>
                  </form>
                  <p style={{ margin: '14px 0 0', fontSize: 12, color: '#8AA3A1', lineHeight: 1.5 }}>
                    Alleen om je onderzoek toe te sturen. Geen spam, geen verplichtingen.
                  </p>
                </React.Fragment>
              ) : kwLoading ? (
                <div style={{ padding: '30px 0', textAlign: 'center' }}>
                  <style>{`@keyframes gs-spin { to { transform: rotate(360deg); } }`}</style>
                  <span style={{ display: 'inline-block', width: 30, height: 30, borderRadius: '50%', border: '3px solid #CBDDDB', borderTopColor: 'var(--bm-teal)', animation: 'gs-spin 0.9s linear infinite' }}></span>
                  <p style={{ margin: '14px 0 0', fontSize: 14.5, color: '#3A5250', fontWeight: 700 }}>We zoeken uit waar jouw klanten op googelen…</p>
                  <p style={{ margin: '4px 0 0', fontSize: 12.5, color: '#8AA3A1' }}>Per dienst meten we de zoektermen mét zoekvolume. Duurt ± 15 seconden.</p>
                </div>
              ) : kwData ? (
                <React.Fragment>
                  <FieldLabel hint="Dit zoeken jouw klanten écht (met gemeten zoekvolume per maand). Vink uit wat niet relevant is; de rest onderzoeken we.">
                    Kloppen deze zoektermen voor jou? <span style={{ color: 'var(--bm-teal-ink)' }}>({kwSelected.length} geselecteerd)</span>
                  </FieldLabel>
                  {kwData.map((d) => (
                    <div key={d.dienst} style={{ marginBottom: 16 }}>
                      <div style={{ fontSize: 13, fontWeight: 800, color: '#2E4A48', marginBottom: 6 }}>{d.dienst}</div>
                      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                        {d.termen.map((t) => {
                          const active = kwSelected.includes(t.kw);
                          return (
                            <button key={t.kw} type="button" className="gs-chip"
                              onClick={() => setKwSelected((cur) => active ? cur.filter((x) => x !== t.kw) : [...cur, t.kw])}
                              style={active ? { background: 'var(--bm-teal)', borderColor: 'var(--bm-teal)', color: '#fff' } : { opacity: 0.6 }}>
                              {t.kw} <span style={{ opacity: 0.75, fontSize: 11 }}>· {t.vol}/mnd</span>
                            </button>
                          );
                        })}
                        {!d.termen.length && <span style={{ fontSize: 12.5, color: '#8AA3A1' }}>Geen termen met meetbaar volume voor deze dienst.</span>}
                      </div>
                    </div>
                  ))}
                  {error && <div style={{ color: '#C4441C', fontSize: 13.5, fontWeight: 700, marginBottom: 14 }}>{error}</div>}
                  <CtaButton onClick={() => {
                    if (!kwSelected.length) { setError('Houd minimaal één zoekterm geselecteerd.'); return; }
                    setError(''); setFormStep(3); loadCompSuggesties(kwSelected);
                  }}>Volgende stap →</CtaButton>
                </React.Fragment>
              ) : (
                <div style={{ padding: '20px 0' }}>
                  {error && <div style={{ color: '#C4441C', fontSize: 13.5, fontWeight: 700, marginBottom: 14 }}>{error}</div>}
                  <CtaButton onClick={loadKeywords}>Opnieuw proberen</CtaButton>
                </div>
              )}
            </React.Fragment>
          )}

          {/* Stap 4: concurrenten (max 2) + start */}
          {formStep === 3 && (
            <React.Fragment>
              <FieldLabel hint={compLoading
                ? 'We kijken live in Google wie er op jouw zoektermen bovenaan staat…'
                : 'Deze partijen staan nú in de top-10 op jouw gekozen zoektermen. Kies er maximaal 2, of voeg zelf toe. Kies je niets, dan nemen we de twee sterkste.'}>
                Met wie wil je je vergelijken? <span style={{ fontWeight: 400, color: '#8AA3A1' }}>(max 2)</span>
              </FieldLabel>
              {compLoading ? (
                <div style={{ padding: '14px 0 22px' }}>
                  <span style={{ display: 'inline-block', width: 22, height: 22, borderRadius: '50%', border: '3px solid #CBDDDB', borderTopColor: 'var(--bm-teal)', animation: 'gs-spin 0.9s linear infinite', verticalAlign: 'middle' }}></span>
                  <span style={{ marginLeft: 10, fontSize: 13.5, color: '#5A7472' }}>Concurrenten zoeken in de live zoekresultaten… (± 15 sec)</span>
                </div>
              ) : (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 12 }}>
                  {[...(compSuggesties || []), ...customComps].map((d) => {
                    const active = comps.includes(d);
                    return (
                      <button key={d} type="button" onClick={() => toggleComp(d)} className="gs-chip" style={active ? {
                        background: 'var(--bm-teal)', borderColor: 'var(--bm-teal)', color: '#fff',
                      } : comps.length >= 2 ? { opacity: 0.5, cursor: 'default' } : undefined}>{d}</button>
                    );
                  })}
                  {!(compSuggesties || []).length && !customComps.length && (
                    <span style={{ fontSize: 12.5, color: '#8AA3A1' }}>Geen suggesties gevonden; voeg zelf een concurrent toe.</span>
                  )}
                </div>
              )}
              <div style={{ display: 'flex', gap: 10, marginBottom: 26 }}>
                <input value={compInput} onChange={(e) => setCompInput(e.target.value)}
                  onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCompCustom(); } }}
                  placeholder="Andere concurrent, bv. concurrent.nl" className="gs-input" style={{ maxWidth: 280 }} />
                <button type="button" onClick={addCompCustom} className="gs-chip" style={{ flex: '0 0 auto' }}>+ Toevoegen</button>
              </div>
              {error && <div style={{ color: '#C4441C', fontSize: 13.5, fontWeight: 700, marginBottom: 14 }}>{error}</div>}
              <CtaButton big onClick={start}>Start het gratis onderzoek</CtaButton>
              <p style={{ margin: '12px 0 0', fontSize: 12.5, color: '#8AA3A1' }}>
                SEO- én Google Ads-analyse op jouw {kwSelected.length} zoektermen, live gemeten{scope === 'provincie' ? ` vanuit ${PROVINCIES.find((p) => p.key === provincie)?.label || 'jouw provincie'}` : ''}.
              </p>
            </React.Fragment>
          )}
        </NotchCard>
      )}
    </SectionShell>
  );
}

function DataSection({ data, num }) {
  const keywords = data.keywords || [];
  return (
    <SectionShell num={num} tag="Data" title="Wat zegt de data over jouw positie?">
      {data.data_intro && (
        <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{data.data_intro}</p>
      )}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 18, marginBottom: 34 }}>
        {data.stats.map(s => (
          <NotchCard key={s.label} style={{ padding: '22px 20px' }} notch={14}>
            <div style={{ fontSize: 32, fontWeight: 900, color: 'var(--bm-teal-ink)', lineHeight: 1 }}>{s.value}</div>
            <div style={{ fontSize: 12.5, color: '#8AA3A1', margin: '4px 0 10px' }}>{s.sub}</div>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: '#2E4A48', lineHeight: 1.4 }}>{s.label}</div>
          </NotchCard>
        ))}
      </div>
      {keywords.length > 0 && (
        <React.Fragment>
          <NotchCard style={{ padding: '4px 0 0', overflow: 'hidden' }} notch={16}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
              <thead>
                <tr style={{ textAlign: 'left', color: '#5A7472', fontSize: 12, textTransform: 'uppercase', letterSpacing: '0.8px' }}>
                  <th style={{ padding: '14px 22px' }}>Kansrijke zoekterm</th>
                  <th style={{ padding: '14px 12px' }}>Zoekvolume p/m</th>
                  <th style={{ padding: '14px 12px' }}>Jouw positie</th>
                  <th style={{ padding: '14px 22px' }}>Klikprijs (indicatie)</th>
                </tr>
              </thead>
              <tbody>
                {keywords.map((k, i) => (
                  <tr key={k.kw} style={{ borderTop: '1px solid #E4EDEC', background: i % 2 ? '#FAFCFB' : '#fff' }}>
                    <td style={{ padding: '13px 22px', fontWeight: 700, color: '#12302E' }}>
                      {k.kw}
                      {k.aiOverview && (
                        <span title={k.aiRefs?.length ? `Google toont hier een AI-antwoord; citeert o.a. ${k.aiRefs.join(', ')}` : 'Google toont hier een AI-antwoord'}
                          style={{ marginLeft: 8, fontSize: 10, fontWeight: 800, background: '#EFE7FA', color: '#6B4FA3', borderRadius: 999, padding: '2px 8px', verticalAlign: 'middle', whiteSpace: 'nowrap' }}>AI-antwoord</span>
                      )}
                      {k.localPack && (
                        <span title="Google toont hier een lokaal kaartenblok (Google-bedrijfsprofiel telt mee)"
                          style={{ marginLeft: 6, fontSize: 10, fontWeight: 800, background: '#E9F2F1', color: 'var(--bm-teal-ink)', borderRadius: 999, padding: '2px 8px', verticalAlign: 'middle', whiteSpace: 'nowrap' }}>lokaal blok</span>
                      )}
                    </td>
                    <td style={{ padding: '13px 12px' }}>{k.vol}</td>
                    <td style={{ padding: '13px 12px', color: k.pos === '—' ? '#C4441C' : '#2E4A48', fontWeight: 700 }}
                      title={k.ownUrl ? `Je scoort hier met ${k.ownUrl}` : undefined}>
                      {k.pos === '—' ? 'Niet gevonden' : `#${k.pos}`}
                    </td>
                    <td style={{ padding: '13px 22px' }}>{k.cpc}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </NotchCard>
          {keywords.some((k) => k.aiOverview) && (
            <p style={{ marginTop: 16, fontSize: 13.5, fontWeight: 700, color: '#6B4FA3' }}>
              Op {keywords.filter((k) => k.aiOverview).length} van de {keywords.length} termen toont Google een AI-antwoord; wie daarin geciteerd wordt, pakt kliks vóór de gewone zoekresultaten.
            </p>
          )}
          <p style={{ marginTop: 16, fontSize: 13, color: '#8AA3A1' }}>
            {data.dataQuality?.positionsLive
              ? 'Posities vandaag live in Google gemeten (regio Nederland, zonder personalisatie); jouw eigen zoekresultaten kunnen door personalisatie en locatie iets afwijken. "Niet gevonden" = geen positie in de top 20.'
              : 'Bron: actuele zoekdata (DataForSEO), regio Nederland. "Niet gevonden" = geen positie in de top 100.'}
            {' '}Klikprijs = het lage en hoge topbod volgens Google Ads; wat je werkelijk betaalt hangt af van je kwaliteitsscore en concurrentie.
          </p>
        </React.Fragment>
      )}
    </SectionShell>
  );
}

const NL_MONTHS_SHORT = ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'];
const fmtNum = (n) => new Intl.NumberFormat('nl-NL').format(n);
const fmtShort = (n) => n >= 1000 ? `${new Intl.NumberFormat('nl-NL', { maximumFractionDigits: 1 }).format(n / 1000)}k` : String(Math.round(n));

function CompetitorsSection({ data, num }) {
  const comp = data.competitorData;
  const rows = [
    { domain: comp.lead.domain.replace(/^www\./, ''), etv: comp.lead.etv || 0, count: comp.lead.count || 0, authority: comp.lead.authority, refDomains: comp.lead.refDomains, isLead: true },
    ...comp.list.map(c => ({ domain: c.domain.replace(/^www\./, ''), etv: c.etv, count: c.count, authority: c.authority, refDomains: c.refDomains, isLead: false, noData: !!c.noData })),
  ];
  const pageComps = comp.list.filter(c => c.topPages && c.topPages.length);
  const maxEtv = Math.max(...rows.map(r => r.etv || 0), 1);
  const gap = comp.gap || [];
  const hero = data.serpHero;

  return (
    <SectionShell num={num} tag="Concurrentie" title="Wie pakt de klanten die jij misloopt?" alt>
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{data.competitors.intro}</p>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(260px, 340px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        {/* Verkeersvergelijking */}
        <NotchCard style={{ padding: '26px 24px' }} notch={16}>
          <h3 style={{ margin: '0 0 4px', fontSize: 15, fontWeight: 900 }}>Geschat organisch bezoek per maand</h3>
          <p style={{ margin: '0 0 18px', fontSize: 12.5, color: '#8AA3A1' }}>
            Op basis van positie × zoekvolume × klikkans per term, gekalibreerd met clickstream-metingen van echt klikgedrag (DataForSEO). Meer zoektermen betekent niet automatisch meer bezoek: hoge posities op zware termen tellen het hardst.
          </p>
          {rows.map(r => (
            <div key={r.domain} style={{ marginBottom: 14 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', fontSize: 13.5, marginBottom: 5, gap: 8 }}>
                <span style={{ fontWeight: r.isLead ? 900 : 700, color: r.isLead ? 'var(--bm-cta-2)' : '#2E4A48', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {r.domain}{r.isLead ? ' ← jij' : ''}
                </span>
                <span style={{ color: '#5A7472', flex: '0 0 auto' }}>
                  {r.noData ? 'geen meetbare organische aanwezigheid' : <React.Fragment>≈ {fmtNum(r.etv)} bez. p/m</React.Fragment>}
                  {r.authority != null && <span style={{ marginLeft: 8, fontSize: 11, background: '#E9F2F1', borderRadius: 999, padding: '2px 8px', color: 'var(--bm-teal-ink)', fontWeight: 700 }}>autoriteit {r.authority}/100</span>}
                </span>
              </div>
              <div style={{ height: 12, background: '#EEF4F3', borderRadius: 999 }}>
                {!r.noData && <div style={{
                  width: `${Math.max(2, ((r.etv || 0) / maxEtv) * 100)}%`, height: '100%', borderRadius: 999,
                  background: r.isLead ? '#CBDDDB' : 'var(--bm-teal)',
                  outline: r.isLead ? '2px solid var(--bm-cta-1)' : 'none', outlineOffset: 1,
                }}></div>}
              </div>
              <div style={{ fontSize: 11.5, color: '#8AA3A1', marginTop: 3 }}>
                {r.noData ? 'door jou opgegeven; nog geen zoektermen in de top-100 gevonden' : `${fmtNum(r.count)} zoektermen in top-100`}
                {r.refDomains != null && ` · ${fmtNum(r.refDomains)} verwijzende websites`}
              </div>
            </div>
          ))}

          {/* Waar concurrenten hun bezoekers vandaan halen (Labs relevant_pages) */}
          {pageComps.length > 0 && (
            <div style={{ marginTop: 20, paddingTop: 18, borderTop: '1px solid #E4EDEC' }}>
              <h3 style={{ margin: '0 0 4px', fontSize: 15, fontWeight: 900 }}>Waar halen zij hun bezoekers vandaan?</h3>
              <p style={{ margin: '0 0 12px', fontSize: 12.5, color: '#8AA3A1' }}>De sterkste pagina's per concurrent, buiten de homepage.</p>
              {pageComps.map((c) => (
                <div key={c.domain} style={{ marginBottom: 12 }}>
                  <div style={{ fontSize: 13, fontWeight: 800, color: '#2E4A48', marginBottom: 4 }}>{c.domain.replace(/^www\./, '')}</div>
                  {c.topPages.map((p) => (
                    <div key={p.path} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, fontSize: 12.5, padding: '3px 0', color: '#5A7472' }}>
                      <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontFamily: 'monospace', fontSize: 12 }}>{p.path}</span>
                      <span style={{ flex: '0 0 auto' }}>≈ {fmtNum(p.etv)} bez. p/m</span>
                    </div>
                  ))}
                </div>
              ))}
            </div>
          )}
        </NotchCard>

        {/* Duiding */}
        <NotchCard style={{ padding: '26px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 10px', fontSize: 16, fontWeight: 900, color: '#fff' }}>Wat betekent dit?</h3>
          <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.65, color: '#C6DBD9' }}>{data.competitors.insight}</p>
        </NotchCard>
      </div>

      {/* Keyword-gap tabel */}
      {gap.length > 0 && (
        <div style={{ marginTop: 34 }}>
          <h3 style={{ margin: '0 0 14px', fontSize: 17, fontWeight: 900, color: '#12302E' }}>Waar concurrenten wél gevonden worden</h3>
          <NotchCard style={{ padding: '4px 0 0', overflow: 'hidden' }} notch={16}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
              <thead>
                <tr style={{ textAlign: 'left', color: '#5A7472', fontSize: 12, textTransform: 'uppercase', letterSpacing: '0.8px' }}>
                  <th style={{ padding: '14px 22px' }}>Zoekterm</th>
                  <th style={{ padding: '14px 12px' }}>Zoekvolume p/m</th>
                  <th style={{ padding: '14px 12px' }}>Concurrent</th>
                  <th style={{ padding: '14px 22px' }}>Jouw positie</th>
                </tr>
              </thead>
              <tbody>
                {gap.map((g, i) => (
                  <tr key={g.kw} style={{ borderTop: '1px solid #E4EDEC', background: i % 2 ? '#FAFCFB' : '#fff' }}>
                    <td style={{ padding: '13px 22px', fontWeight: 700, color: '#12302E' }}>{g.kw}</td>
                    <td style={{ padding: '13px 12px' }}>{g.vol}</td>
                    <td style={{ padding: '13px 12px', color: '#2E4A48' }}>{g.compDomain.replace(/^www\./, '')} · <strong>#{g.compPos}</strong></td>
                    <td style={{ padding: '13px 22px', color: g.ownPos ? '#2E4A48' : '#C4441C', fontWeight: 700 }}>{g.ownPos ? `#${g.ownPos}` : 'Niet gevonden'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </NotchCard>
          <p style={{ marginTop: 14, fontSize: 13, color: '#8AA3A1' }}>Bron: DataForSEO Labs, regio Nederland. "Niet gevonden" = geen positie in de top 100 volgens de laatste databasegegevens.</p>
        </div>
      )}

      {/* SERP-hero */}
      {hero && (
        <div style={{ marginTop: 34 }}>
          <h3 style={{ margin: '0 0 14px', fontSize: 17, fontWeight: 900, color: '#12302E' }}>
            Zo ziet pagina 1 eruit voor "{hero.kw}" <span style={{ fontWeight: 400, fontSize: 14, color: '#5A7472' }}>({hero.vol} zoekopdrachten p/m)</span>
          </h3>
          <NotchCard style={{ padding: '18px 0 10px' }} notch={16}>
            {hero.items.map((it) => (
              <div key={it.pos} style={{ display: 'flex', alignItems: 'baseline', gap: 14, padding: '7px 24px', borderTop: it.pos > 1 ? '1px solid #F0F5F4' : 'none' }}>
                <span style={{ flex: '0 0 26px', fontWeight: 900, color: 'var(--bm-teal)', fontSize: 14 }}>#{it.pos}</span>
                <span style={{ flex: '0 0 auto', fontWeight: 700, fontSize: 13.5, color: '#2E4A48' }}>{it.domain}</span>
                <span style={{ fontSize: 13, color: '#8AA3A1', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{it.title}</span>
              </div>
            ))}
            <div style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '10px 24px', borderTop: '1.5px dashed #E4B8A6', background: '#FFF8F4' }}>
              <span style={{ flex: '0 0 26px', fontWeight: 900, color: 'var(--bm-cta-2)', fontSize: 14 }}>—</span>
              <span style={{ fontWeight: 900, fontSize: 13.5, color: 'var(--bm-cta-2)' }}>Jij staat er niet tussen</span>
            </div>
          </NotchCard>
        </div>
      )}
    </SectionShell>
  );
}

function PotentialSection({ data, num }) {
  const pot = data.potentialData;
  const trend = data.trend;
  const unused = data.unused;
  const maxTrend = trend ? Math.max(...trend.months.map(m => m.volume), 1) : 1;

  // Nieuwe rapporten hebben het tweelaagse scenario (totalExtra); oude alleen
  // het top-3-scenario op de onderzochte termen.
  const hasField = !!(pot.fmt.totalExtra && pot.fieldClicks > 0);
  const statCards = hasField ? [
    { value: pot.fmt.totalExtra, sub: 'extra bezoekers per maand', label: `Onderzochte termen naar de top-3 én de ${fmtNum(pot.fieldCount)} onbenutte termen naar positie ${pot.fieldPos}` },
    pot.fmt.totalValueMonth && { value: pot.fmt.totalValueMonth, sub: 'advertentiewaarde per maand', label: 'Wat dit verkeer zou kosten via Google Ads' },
    pot.fmt.totalValueYear && { value: pot.fmt.totalValueYear, sub: 'advertentiewaarde per jaar', label: 'De jaarlijkse waarde van deze organische zichtbaarheid' },
    unused && { value: fmtNum(unused.count), sub: `samen ${fmtNum(unused.totalVolume)} zoekopdrachten p/m`, label: 'Relevante zoektermen waar je nu nog niets uithaalt' },
  ].filter(Boolean) : [
    { value: pot.fmt.extraClicks, sub: 'extra bezoekers per maand', label: `Bij een top-3 positie op de ${pot.kwCount ? `${pot.kwCount} onderzochte` : 'geanalyseerde'} zoektermen (alleen deze termen, niet de hele site)` },
    pot.fmt.adValueMonth && { value: pot.fmt.adValueMonth, sub: 'advertentiewaarde per maand', label: 'Wat dit verkeer zou kosten via Google Ads' },
    pot.fmt.adValueYear && { value: pot.fmt.adValueYear, sub: 'advertentiewaarde per jaar', label: 'De jaarlijkse waarde van deze organische posities' },
    unused && { value: fmtNum(unused.count), sub: `samen ${fmtNum(unused.totalVolume)} zoekopdrachten p/m`, label: 'Extra relevante zoektermen, nog onbenut' },
  ].filter(Boolean);

  return (
    <SectionShell num={num} tag="Potentieel" title="Wat levert een top-3 positie op?">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 18, marginBottom: 34 }}>
        {statCards.map(s => (
          <NotchCard key={s.label} style={{ padding: '22px 20px' }} notch={14}>
            <div style={{ fontSize: 30, fontWeight: 900, color: 'var(--bm-teal-ink)', lineHeight: 1 }}>{s.value}</div>
            <div style={{ fontSize: 12.5, color: '#8AA3A1', margin: '4px 0 10px' }}>{s.sub}</div>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: '#2E4A48', lineHeight: 1.4 }}>{s.label}</div>
          </NotchCard>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.2fr) minmax(0, 0.8fr)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div style={{ fontSize: 15.5, lineHeight: 1.7, color: '#3A5250' }}>
          {data.investment.paragraphs.map((p, i) => (
            <p key={i} style={{ marginTop: i === 0 ? 0 : undefined }}>{p}</p>
          ))}
        </div>

        {trend && (
          <NotchCard style={{ padding: '26px 24px' }} notch={16}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 10, marginBottom: 16 }}>
              <h3 style={{ margin: 0, fontSize: 15, fontWeight: 900 }}>Zoekvraag per maand</h3>
              {trend.peakMonths && (
                <span style={{ fontSize: 11.5, fontWeight: 700, background: '#E9F2F1', color: 'var(--bm-teal-ink)', borderRadius: 999, padding: '3px 10px', whiteSpace: 'nowrap' }}>
                  piek in {trend.peakMonths.join(' & ')}
                </span>
              )}
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              {/* Y-as: max en midden, kort geformatteerd */}
              <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', height: 110, flex: '0 0 auto', textAlign: 'right', paddingBottom: 0 }}>
                {[maxTrend, maxTrend / 2, 0].map((v, i) => (
                  <span key={i} style={{ fontSize: 9.5, color: '#8AA3A1', lineHeight: 1 }}>{fmtShort(v)}</span>
                ))}
              </div>
              <div style={{ flex: 1, position: 'relative' }}>
                {/* gridlijnen op max en midden */}
                <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
                  <div style={{ position: 'absolute', top: 0, left: 0, right: 0, borderTop: '1px dashed #E4EDEC' }}></div>
                  <div style={{ position: 'absolute', top: '50%', left: 0, right: 0, borderTop: '1px dashed #E4EDEC' }}></div>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: `repeat(${trend.months.length}, 1fr)`, gap: 4, alignItems: 'end', height: 110 }}>
                  {trend.months.map(m => (
                    <div key={`${m.year}-${m.month}`} title={`${NL_MONTHS_SHORT[m.month - 1]}: ${fmtNum(m.volume)}`} style={{
                      height: `${Math.max(4, (m.volume / maxTrend) * 100)}%`,
                      background: 'var(--bm-teal)', opacity: 0.4 + 0.6 * (m.volume / maxTrend), borderRadius: '3px 3px 0 0',
                    }}></div>
                  ))}
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: `repeat(${trend.months.length}, 1fr)`, gap: 4, marginTop: 6 }}>
                  {trend.months.map(m => (
                    <span key={`${m.year}-${m.month}`} style={{ fontSize: 9.5, textAlign: 'center', color: '#8AA3A1' }}>{NL_MONTHS_SHORT[m.month - 1]}</span>
                  ))}
                </div>
              </div>
            </div>
            <p style={{ margin: '12px 0 0', fontSize: 12, color: '#8AA3A1' }}>Totaal zoekvolume over jouw zoektermen, afgelopen 12 maanden.</p>
          </NotchCard>
        )}
      </div>

      <p style={{ marginTop: 26, fontSize: 12.5, color: '#8AA3A1' }}>
        Berekend met de gemiddelde klikverdeling per Google-positie en de gemeten zoekvolumes en klikprijzen, gekalibreerd met clickstream-metingen van echt klikgedrag in deze branche{hasField ? `; het scenario telt je onderzochte termen (naar top-3) en het nog onbenutte speelveld (naar positie ${pot.fieldPos}) bij elkaar op` : ''}: een indicatie van de orde van grootte, geen garantie.
      </p>
    </SectionShell>
  );
}

// Social bereik: rekenmodel-doelgroepen per platform + echte concurrent-ads (Ad Library)
function SocialSection({ data, num }) {
  const s = data.socialData;
  const maxAudience = Math.max(...s.platforms.map((p) => p.audience), 1);
  const ads = s.competitorAds || [];

  return (
    <SectionShell num={num} tag="Social bereik" title="Hoeveel mensen kun je bereiken via social?" alt>
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{data.social.intro}</p>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(260px, 340px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div>
          {/* Doelgroepprofiel + bereikbaar per platform */}
          <NotchCard style={{ padding: '26px 24px' }} notch={16}>
            <h3 style={{ margin: '0 0 4px', fontSize: 15, fontWeight: 900 }}>Jouw doelgroep in {s.regionLabel}</h3>
            {s.doelgroep && (
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap', margin: '10px 0 6px' }}>
                <span style={{ fontSize: 26, fontWeight: 900, color: 'var(--bm-teal-ink)', fontFamily: "'Lato', sans-serif" }}>≈ {fmtNum(s.doelgroep.omvang)}</span>
                <span style={{ fontSize: 13.5, color: '#3A5250' }}>{s.doelgroep.omschrijving}</span>
              </div>
            )}
            <p style={{ margin: '0 0 18px', fontSize: 12.5, color: '#8AA3A1' }}>Daarvan bereikbaar per platform:</p>
            {s.platforms.map((p) => (
              <div key={p.key} style={{ marginBottom: 14 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', fontSize: 13.5, marginBottom: 5 }}>
                  <span style={{ fontWeight: 700, color: '#2E4A48' }}>{p.label}</span>
                  <span style={{ color: '#5A7472' }}>≈ {fmtNum(p.audience)} mensen</span>
                </div>
                <div style={{ height: 12, background: '#EEF4F3', borderRadius: 999 }}>
                  <div style={{ width: `${Math.max(3, (p.audience / maxAudience) * 100)}%`, height: '100%', borderRadius: 999, background: 'var(--bm-teal)' }}></div>
                </div>
              </div>
            ))}
            <div style={{ marginTop: 18, paddingTop: 16, borderTop: '1px solid #E4EDEC', display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
              {s.fullReach ? (
                <React.Fragment>
                  <span style={{ fontSize: 26, fontWeight: 900, color: 'var(--bm-teal-ink)', fontFamily: "'Lato', sans-serif" }}>~ €{fmtNum(s.fullReach.monthlyCost)} p/m</span>
                  <span style={{ fontSize: 13.5, color: '#3A5250' }}>kost het indicatief om je volledige doelgroep (≈ {fmtNum(s.fullReach.audience)} mensen) elke maand te bereiken op Facebook/Instagram</span>
                </React.Fragment>
              ) : (
                <React.Fragment>
                  <span style={{ fontSize: 26, fontWeight: 900, color: 'var(--bm-teal-ink)', fontFamily: "'Lato', sans-serif" }}>≈ {fmtNum(s.reach.people)}</span>
                  <span style={{ fontSize: 13.5, color: '#3A5250' }}>mensen per maand te bereiken op Facebook/Instagram met ~€{s.reach.budget} advertentiebudget</span>
                </React.Fragment>
              )}
            </div>
          </NotchCard>

          {/* Concurrenten die nu adverteren */}
          {ads.length > 0 && (
            <NotchCard style={{ padding: '22px 24px', marginTop: 22 }} notch={16}>
              <h3 style={{ margin: '0 0 12px', fontSize: 15, fontWeight: 900 }}>Wie adverteert er nú op Meta?</h3>
              {ads.map((a) => (
                <div key={a.domain} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0', borderTop: '1px solid #F0F5F4', fontSize: 13.5 }}>
                  <span style={{ fontWeight: 700, color: '#2E4A48' }}>{a.domain.replace(/^www\./, '')}</span>
                  {a.activeAds > 0 ? (
                    <span style={{ fontSize: 12, fontWeight: 700, background: '#FDEFD9', color: '#B96A12', borderRadius: 999, padding: '4px 12px' }}>
                      ✓ actief · {a.activeAds}{a.cappedAt ? '+' : ''} advertenties
                    </span>
                  ) : (
                    <span style={{ fontSize: 12, fontWeight: 700, background: '#EEF4F3', color: '#5A7472', borderRadius: 999, padding: '4px 12px' }}>geen actieve advertenties</span>
                  )}
                </div>
              ))}

              {/* Voorbeeldadvertenties (echte creatives uit de Ad Library) */}
              {ads.some((a) => a.preview) && (
                <div style={{ marginTop: 18 }}>
                  <p style={{ margin: '0 0 10px', fontSize: 12.5, color: '#8AA3A1' }}>Zo zien hun advertenties eruit:</p>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 12 }}>
                    {ads.filter((a) => a.preview).map((a) => {
                      const pv = a.preview;
                      return (
                        <a key={a.domain} href={pv.adLibraryUrl || undefined} target="_blank" rel="noopener noreferrer"
                          style={{ display: 'block', border: '1px solid #E4EDEC', borderRadius: 10, overflow: 'hidden', background: '#fff', textDecoration: 'none', color: 'inherit' }}>
                          {pv.image && (
                            <div style={{ position: 'relative' }}>
                              <img src={pv.image} alt={`Advertentie van ${a.domain.replace(/^www\./, '')}`}
                                style={{ display: 'block', width: '100%', aspectRatio: '4 / 3', objectFit: 'cover' }} />
                              {pv.isVideo && (
                                <span style={{ position: 'absolute', top: 8, right: 8, fontSize: 10.5, fontWeight: 700, background: 'rgba(15,32,31,0.72)', color: '#fff', borderRadius: 999, padding: '3px 9px' }}>▶ video</span>
                              )}
                            </div>
                          )}
                          <div style={{ padding: '10px 12px' }}>
                            <div style={{ fontSize: 12, fontWeight: 800, color: '#2E4A48', marginBottom: 3 }}>{pv.pageName || a.domain.replace(/^www\./, '')}</div>
                            {pv.title && <div style={{ fontSize: 12.5, fontWeight: 700, color: '#3A5250', marginBottom: 3 }}>{pv.title}</div>}
                            {pv.text && (
                              <div style={{ fontSize: 12, lineHeight: 1.5, color: '#5A7472', display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{pv.text}</div>
                            )}
                            {pv.adLibraryUrl && <div style={{ marginTop: 6, fontSize: 11.5, fontWeight: 700, color: 'var(--bm-teal)' }}>Bekijk in Ad Library ↗</div>}
                          </div>
                        </a>
                      );
                    })}
                  </div>
                </div>
              )}
              <p style={{ margin: '12px 0 0', fontSize: 12, color: '#8AA3A1' }}>Bron: openbare Meta Ad Library, advertenties gericht op Nederland.</p>
            </NotchCard>
          )}
        </div>

        {/* Duiding */}
        <NotchCard style={{ padding: '26px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 10px', fontSize: 16, fontWeight: 900, color: '#fff' }}>Wat betekent dit?</h3>
          <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.65, color: '#C6DBD9' }}>{data.social.insight}</p>
        </NotchCard>
      </div>

      <p style={{ marginTop: 26, fontSize: 12.5, color: '#8AA3A1' }}>
        Doelgroepen: Brandmerck-rekenmodel {s.edition} o.b.v. Newcom Nationale Social Media Onderzoek en CBS-bevolkingscijfers{s.regionAssumed ? ' (verzorgingsgebied als aanname)' : ''}; kostenindicatie o.b.v. gemiddelde Nederlandse advertentieprijzen (CPM).
      </p>
    </SectionShell>
  );
}

// Technische mini-audit (OnPage-crawl, max 15 pagina's): score + top-3
// verbeterpunten als teaser; de volledige audit is het strategiegesprek.
function TechSection({ data, num, onCta }) {
  const t = data.techData;
  const ok = t.totalIssues === 0;

  return (
    <SectionShell num={num} tag="Techniek" title={ok ? 'Jouw technische basis staat goed' : 'Wat remt je website technisch af?'}>
      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(260px, 340px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div>
          <p style={{ margin: '0 0 22px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>
            {ok
              ? `We hebben ${t.crawledPages ? `${fmtNum(t.crawledPages)} pagina's` : 'je website'} technisch doorgelicht en geen blokkerende problemen gevonden. Dat is een stevige basis: alles wat je aan content en autoriteit opbouwt, komt technisch ook echt aan.`
              : `We hebben ${t.crawledPages ? `${fmtNum(t.crawledPages)} pagina's` : 'je website'} technisch doorgelicht en ${fmtNum(t.totalIssues)} punten gevonden die je SEO-potentieel remmen. Niets onoverkomelijks, maar elk punt maakt het voor Google net wat lastiger om je pagina's goed te beoordelen.`}
          </p>
          {!ok && (
            <NotchCard style={{ padding: '22px 24px' }} notch={16}>
              <h3 style={{ margin: '0 0 12px', fontSize: 15, fontWeight: 900 }}>De belangrijkste verbeterpunten</h3>
              {t.top.map((i) => (
                <div key={i.key} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, padding: '9px 0', borderTop: '1px solid #F0F5F4', fontSize: 14 }}>
                  <span style={{ color: '#2E4A48', fontWeight: 700 }}>{i.label.charAt(0).toUpperCase() + i.label.slice(1)}</span>
                  <span style={{ flex: '0 0 auto', fontSize: 12, fontWeight: 700, background: '#FDEFD9', color: '#B96A12', borderRadius: 999, padding: '4px 12px' }}>{fmtNum(i.count)}×</span>
                </div>
              ))}
              <p style={{ margin: '14px 0 0', fontSize: 13, color: '#5A7472' }}>
                Dit zijn de drie grootste; de volledige lijst en de oplossing per punt nemen we door in het{' '}
                <a href="#" onClick={(e) => { e.preventDefault(); onCta?.(); }} style={{ color: 'var(--bm-teal-ink)', fontWeight: 700 }}>strategiegesprek</a>.
              </p>
            </NotchCard>
          )}
        </div>

        <NotchCard style={{ padding: '26px 24px', background: 'var(--bm-dark)', color: '#fff', textAlign: 'center' }} notch={16}>
          {t.onpageScore != null && (
            <React.Fragment>
              <div style={{ fontSize: 13, fontWeight: 700, color: '#8FB5B1', textTransform: 'uppercase', letterSpacing: '1px', marginBottom: 10 }}>Technische score</div>
              <div style={{ fontSize: 52, fontWeight: 900, lineHeight: 1, color: t.onpageScore >= 85 ? '#7FD1A8' : t.onpageScore >= 65 ? '#F0C05A' : '#F08A5A', fontFamily: "'Lato', sans-serif" }}>
                {t.onpageScore}<span style={{ fontSize: 22, color: '#8FB5B1' }}>/100</span>
              </div>
              <p style={{ margin: '14px 0 0', fontSize: 13.5, lineHeight: 1.6, color: '#C6DBD9' }}>
                {t.onpageScore >= 85 ? 'Technisch gezond; de winst zit vooral in content en autoriteit.' : t.onpageScore >= 65 ? 'Redelijke basis, maar de gevonden punten kosten je nu zichtbaarheid.' : 'De techniek remt je vindbaarheid serieus af; hier ligt snelle winst.'}
              </p>
            </React.Fragment>
          )}
        </NotchCard>
      </div>

      <p style={{ marginTop: 26, fontSize: 12.5, color: '#8AA3A1' }}>
        Technische crawl van maximaal 15 pagina's (DataForSEO OnPage); score o.b.v. ruim 60 technische checks.
      </p>
    </SectionShell>
  );
}

// ── Stapsgewijs vervolgonderzoek (v8): vijf stappen die de lezer meenemen ──

const FASE_ORDER = ['orienteren', 'vergelijken', 'kiezen'];
const FASE_META = {
  orienteren: { label: 'Oriënteren', sub: 'de klant verkent het onderwerp' },
  vergelijken: { label: 'Vergelijken', sub: 'de klant weegt opties en prijzen af' },
  kiezen: { label: 'Klaar om te kiezen', sub: 'de klant zoekt een partij; dit zijn de aanvragen' },
};

// Brug-zin onder elke stap: leidt de lezer naar de volgende vraag
function StepBrug({ text }) {
  if (!text) return null;
  return (
    <p style={{ margin: '30px 0 0', fontSize: 14.5, fontStyle: 'italic', color: '#5A7472', display: 'flex', alignItems: 'center', gap: 10 }}>
      <span style={{ fontSize: 18, color: 'var(--bm-teal)' }}>↓</span> {text}
    </p>
  );
}

// Kleine vervolgstap onderaan een datasectie: de brug van inzicht naar gesprek.
// Nuchter linkje, geen schreeuwende knop; scrolt naar het contactformulier.
function SectieCta({ text }) {
  return (
    <p style={{ margin: '16px 0 0' }}>
      <button onClick={() => document.getElementById('gs-contact')?.scrollIntoView({ behavior: 'smooth', block: 'start' })}
        style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer', fontFamily: "'Lato', sans-serif", fontSize: 14, fontWeight: 800, color: 'var(--bm-cta-2)', display: 'inline-flex', alignItems: 'center', gap: 8 }}>
        {text} <span style={{ fontSize: 16 }}>→</span>
      </button>
    </p>
  );
}

function PosBadge({ k }) {
  const found = k.pos !== '—';
  return (
    <span title={k.ownUrl ? `Je scoort hier met ${k.ownUrl}` : undefined}
      style={{ fontSize: 11.5, fontWeight: 800, borderRadius: 999, padding: '2px 9px', flex: '0 0 auto', background: found ? '#E9F2F1' : '#FBEAE2', color: found ? 'var(--bm-teal-ink)' : '#C4441C' }}>
      {found ? `#${k.pos}` : 'niet gevonden'}
    </span>
  );
}

// Stap 1 — Waar zoekt jouw klant op? (zoektermen per klantfase)
function Step1Section({ data, num, tag }) {
  const s = data.steps.step1;
  const kws = data.keywords || [];

  return (
    <SectionShell num={num} tag={tag || "Stap 1 van 5 · Zoekvraag"} title="Waar zoekt jouw klant op?">
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 18 }}>
        {FASE_ORDER.map((f) => {
          const terms = kws.filter((k) => k.fase === f);
          const vol = terms.reduce((sum, k) => sum + (k.volRaw || 0), 0);
          const visible = terms.filter((k) => k.posRaw && k.posRaw <= 20).length;
          return (
            <NotchCard key={f} style={{ padding: '22px 20px', display: 'flex', flexDirection: 'column' }} notch={14}>
              <div style={{ fontSize: 12, fontWeight: 800, color: '#8AA3A1', textTransform: 'uppercase', letterSpacing: '0.8px' }}>{FASE_META[f].sub}</div>
              <h3 style={{ margin: '2px 0 8px', fontSize: 17, fontWeight: 900 }}>{FASE_META[f].label}</h3>
              <div style={{ display: 'flex', gap: 14, alignItems: 'baseline', marginBottom: 10 }}>
                <span style={{ fontSize: 24, fontWeight: 900, color: 'var(--bm-teal-ink)', fontFamily: "'Lato', sans-serif" }}>{fmtNum(vol)}</span>
                <span style={{ fontSize: 12.5, color: '#8AA3A1' }}>zoekopdrachten p/m · zichtbaar op {visible} van {terms.length}</span>
              </div>
              {terms.length ? terms.map((k) => (
                <div key={k.kw} style={{ borderTop: '1px solid #F0F5F4', padding: '8px 0' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8, fontSize: 13.5 }}>
                    <span style={{ fontWeight: 700, color: '#12302E', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{k.kw}</span>
                    <PosBadge k={k} />
                  </div>
                  <div style={{ fontSize: 11.5, color: '#8AA3A1', marginTop: 2 }}>
                    {k.vol} p/m · klik {k.cpc}
                    {k.aiOverview && <span title={k.aiRefs?.length ? `AI-antwoord aanwezig; citeert o.a. ${k.aiRefs.join(', ')}` : 'AI-antwoord aanwezig'} style={{ marginLeft: 6, color: '#6B4FA3', fontWeight: 700 }}>· AI-antwoord</span>}
                    {k.localPack && <span title="Google toont hier een lokaal kaartenblok" style={{ marginLeft: 6, color: 'var(--bm-teal-ink)', fontWeight: 700 }}>· lokaal blok</span>}
                    {k.infoSerp && <span title="De zoekresultaten worden gedomineerd door naslagwerken: hier win je met content, niet met een productpagina" style={{ marginLeft: 6, color: '#B96A12', fontWeight: 700 }}>· contentkans</span>}
                  </div>
                </div>
              )) : (
                <div style={{ borderTop: '1px solid #F0F5F4', padding: '10px 0', fontSize: 12.5, color: '#8AA3A1' }}>Geen onderzochte termen in deze fase.</div>
              )}
              <p style={{ margin: '12px 0 0', paddingTop: 10, borderTop: '1px solid #F0F5F4', fontSize: 13, lineHeight: 1.55, color: '#3A5250' }}>{s.fases?.[f]}</p>
            </NotchCard>
          );
        })}
      </div>

      {kws.some((k) => k.aiOverview) && (
        <p style={{ marginTop: 18, fontSize: 13.5, fontWeight: 700, color: '#6B4FA3' }}>
          Op {kws.filter((k) => k.aiOverview).length} van de {kws.length} termen toont Google een AI-antwoord; wie daarin geciteerd wordt, pakt kliks vóór de gewone zoekresultaten.
        </p>
      )}

      {/* Wat klanten verder aan Google vragen (People Also Ask) */}
      {data.paaQuestions?.length > 0 && (
        <NotchCard style={{ padding: '22px 24px', marginTop: 22 }} notch={14}>
          <h3 style={{ margin: '0 0 4px', fontSize: 15, fontWeight: 900 }}>Dit vraagt jouw klant aan Google</h3>
          <p style={{ margin: '0 0 12px', fontSize: 12.5, color: '#8AA3A1' }}>Echte vervolgvragen uit de zoekresultaten op jouw termen; elke vraag is een pagina- of contentkans.</p>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: '4px 24px' }}>
            {data.paaQuestions.map((q) => (
              <div key={q.vraag} style={{ fontSize: 13.5, color: '#3A5250', padding: '5px 0', borderBottom: '1px solid #F0F5F4' }}>
                “{q.vraag}” <span style={{ fontSize: 11.5, color: '#8AA3A1' }}>bij "{q.kw}"</span>
              </div>
            ))}
          </div>
        </NotchCard>
      )}
      <p style={{ marginTop: 14, fontSize: 12.5, color: '#8AA3A1' }}>
        {data.dataQuality?.positionsLive
          ? 'Posities vandaag live in Google gemeten (regio Nederland, zonder personalisatie); "niet gevonden" = geen positie in de top 20.'
          : 'Bron: actuele zoekdata (DataForSEO), regio Nederland.'}
        {' '}Klikprijs = het lage en hoge topbod volgens Google Ads.
      </p>
      <StepBrug text={s.brug} />
    </SectionShell>
  );
}

// Stap 2 — Wie pakt die klant nu? (concurrentprofielen)
function Step2Section({ data, num, tag, title, deep }) {
  const s = data.steps.step2;
  const comp = data.competitorData;
  const kws = data.keywords || [];
  const ads = data.socialData?.competitorAds || [];
  const gAds = data.googleAds || [];
  const whyFor = (domain) => (s.winners || []).find((w) => domain.replace(/^www\./, '').includes(w.domain.replace(/^www\./, '')) || w.domain.replace(/^www\./, '').includes(domain.replace(/^www\./, '')))?.why;
  const lead = { domain: comp.lead.domain.replace(/^www\./, ''), etv: comp.lead.etv || 0 };
  const maxEtv = Math.max(lead.etv, ...comp.list.map((c) => c.etv || 0), 1);

  return (
    <SectionShell num={num} tag={tag || "Stap 2 van 5 · Concurrentie"} title={title || "Wie pakt die klant nu?"} alt>
      {!deep && <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>}

      {/* Compacte bezoekvergelijking als opmaat */}
      <NotchCard style={{ padding: '20px 22px', marginBottom: 22 }} notch={14}>
        {[{ ...lead, isLead: true }, ...comp.list.map((c) => ({ domain: c.domain.replace(/^www\./, ''), etv: c.etv, isLead: false, noData: !!c.noData }))].map((r) => (
          <div key={r.domain} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '5px 0' }}>
            <span style={{ flex: '0 0 200px', fontSize: 13, fontWeight: r.isLead ? 900 : 700, color: r.isLead ? 'var(--bm-cta-2)' : '#2E4A48', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.domain}{r.isLead ? ' ← jij' : ''}</span>
            <div style={{ flex: 1, height: 10, background: '#EEF4F3', borderRadius: 999 }}>
              {!r.noData && <div style={{ width: `${Math.max(2, ((r.etv || 0) / maxEtv) * 100)}%`, height: '100%', borderRadius: 999, background: r.isLead ? '#CBDDDB' : 'var(--bm-teal)', outline: r.isLead ? '2px solid var(--bm-cta-1)' : 'none', outlineOffset: 1 }}></div>}
            </div>
            <span style={{ flex: '0 0 auto', fontSize: 12.5, color: '#5A7472' }}>{r.noData ? 'geen data' : `≈ ${fmtNum(r.etv)} bez. p/m`}</span>
          </div>
        ))}
        <p style={{ margin: '10px 0 0', fontSize: 11.5, color: '#8AA3A1' }}>Geschat organisch bezoek per maand: positie × zoekvolume × klikkans, gekalibreerd met clickstream-metingen van echt klikgedrag.</p>
      </NotchCard>

      {/* Profielkaarten */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))', gap: 18 }}>
        {comp.list.map((c) => {
          const dom = c.domain.replace(/^www\./, '');
          const topOn = kws.filter((k) => (k.top3 || []).some((d) => d === dom)).map((k) => k.kw);
          const ad = ads.find((a) => a.domain.replace(/^www\./, '') === dom);
          const why = whyFor(c.domain);
          return (
            <NotchCard key={c.domain} style={{ padding: '20px 22px' }} notch={14}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>
                <h3 style={{ margin: 0, fontSize: 16, fontWeight: 900 }}>{dom}</h3>
                <span style={{ fontSize: 10.5, fontWeight: 800, borderRadius: 999, padding: '3px 10px', background: c.userProvided ? '#FDEFD9' : '#E9F2F1', color: c.userProvided ? '#B96A12' : 'var(--bm-teal-ink)' }}>
                  {c.userProvided ? 'door jou opgegeven' : c.serpFound ? 'staat in jouw zoekresultaten' : 'zelfde speelveld'}
                </span>
              </div>
              <div style={{ margin: '10px 0', fontSize: 12.5, color: '#5A7472' }}>
                {c.noData ? 'geen meetbare organische aanwezigheid' : <React.Fragment>≈ {fmtNum(c.etv)} bez. p/m</React.Fragment>}
                {c.authority != null && <React.Fragment> · autoriteit {c.authority}/100</React.Fragment>}
                {c.refDomains != null && <React.Fragment> · {fmtNum(c.refDomains)} verwijzende sites</React.Fragment>}
                {ad && <span style={{ color: ad.activeAds > 0 ? '#B96A12' : '#8AA3A1', fontWeight: 700 }}> · {ad.activeAds > 0 ? `adverteert op Meta (${ad.activeAds}${ad.cappedAt ? '+' : ''})` : 'geen Meta-advertenties'}</span>}
                {(() => { const g = gAds.find((x) => x.domain === dom); return g ? <span title={`Adverteert in Google op: ${g.terms.join(', ')}`} style={{ color: '#B96A12', fontWeight: 700 }}> · adverteert in Google ({g.terms.length} {g.terms.length === 1 ? 'term' : 'termen'})</span> : null; })()}
              </div>
              {topOn.length > 0 && (
                <div style={{ fontSize: 12.5, color: '#3A5250', marginBottom: 8 }}>
                  <span style={{ fontWeight: 800 }}>In de top-3 op jouw termen:</span> {topOn.slice(0, 3).join(' · ')}
                </div>
              )}
              {c.topPages?.length > 0 && (
                <div style={{ fontSize: 12, color: '#5A7472', marginBottom: 8 }}>
                  <span style={{ fontWeight: 800, color: '#3A5250' }}>Sterkste pagina's:</span>
                  {c.topPages.slice(0, 2).map((p) => (
                    <div key={p.path} style={{ display: 'flex', justifyContent: 'space-between', gap: 10, padding: '2px 0' }}>
                      <span style={{ fontFamily: 'monospace', fontSize: 11.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.path}</span>
                      <span style={{ flex: '0 0 auto' }}>≈ {fmtNum(p.etv)} bez.</span>
                    </div>
                  ))}
                </div>
              )}
              {why && <p style={{ margin: 0, paddingTop: 8, borderTop: '1px solid #F0F5F4', fontSize: 13, lineHeight: 1.55, color: '#3A5250' }}>{why}</p>}
            </NotchCard>
          );
        })}
      </div>

      {/* Diepgaand (v10): toppagina's van de lead, verkeershistorie en verkeerswaarde */}
      {deep && (
        <React.Fragment>
          {data.leadTopPages?.length > 0 && (
            <NotchCard style={{ padding: '20px 22px', marginTop: 22 }} notch={14}>
              <h3 style={{ margin: '0 0 8px', fontSize: 15, fontWeight: 900 }}>Waar haal jíj je bezoekers vandaan?</h3>
              {data.leadTopPages.map((p) => (
                <div key={p.path} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, fontSize: 12.5, padding: '3px 0', color: '#5A7472' }}>
                  <span style={{ fontFamily: 'monospace', fontSize: 11.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.path}</span>
                  <span style={{ flex: '0 0 auto' }}>≈ {fmtNum(p.etv)} bez. p/m</span>
                </div>
              ))}
            </NotchCard>
          )}
          {(data.history?.length >= 6 || comp.list.some((c) => c.history?.length >= 6)) && (
            <NotchCard style={{ padding: '20px 22px', marginTop: 22 }} notch={14}>
              <h3 style={{ margin: '0 0 4px', fontSize: 15, fontWeight: 900 }}>Geschat verkeer, afgelopen 12 maanden</h3>
              <p style={{ margin: '0 0 14px', fontSize: 12, color: '#8AA3A1' }}>Zichtbaarheidsindex per maand (richting telt, niet het absolute getal).</p>
              {[{ domain: comp.lead.domain, history: data.history, isLead: true },
                ...comp.list.map((c) => ({ domain: c.domain, history: c.history, isLead: false }))]
                .filter((r) => r.history?.length >= 6)
                .map((r) => {
                  const mx = Math.max(...r.history.map((m) => m.etv), 1);
                  return (
                    <div key={r.domain} style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 10 }}>
                      <span style={{ flex: '0 0 180px', fontSize: 12.5, fontWeight: r.isLead ? 900 : 700, color: r.isLead ? 'var(--bm-cta-2)' : '#2E4A48', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.domain.replace(/^www\./, '')}{r.isLead ? ' ← jij' : ''}</span>
                      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: `repeat(${r.history.length}, 1fr)`, gap: 2, alignItems: 'end', height: 30 }}>
                        {r.history.map((m) => (
                          <div key={m.ym} title={`${m.ym}: ${fmtNum(m.etv)}`} style={{ height: `${Math.max(8, (m.etv / mx) * 100)}%`, background: r.isLead ? 'var(--bm-cta-1)' : 'var(--bm-teal)', opacity: 0.8, borderRadius: '2px 2px 0 0' }}></div>
                        ))}
                      </div>
                      <span style={{ flex: '0 0 auto', fontSize: 11.5, color: '#8AA3A1' }}>{r.history[0].ym} → {r.history[r.history.length - 1].ym}</span>
                    </div>
                  );
                })}
            </NotchCard>
          )}
          <NotchCard style={{ padding: '20px 22px', marginTop: 22 }} notch={14}>
            <h3 style={{ margin: '0 0 8px', fontSize: 15, fontWeight: 900 }}>Wat is dat verkeer waard?</h3>
            {[{ domain: comp.lead.domain, etv: comp.lead.etv, paidCost: comp.lead.paidCost, isLead: true },
              ...comp.list.map((c) => ({ domain: c.domain, etv: c.etv, paidCost: c.paidCost, isLead: false }))].map((r) => (
              <div key={r.domain} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, fontSize: 13, padding: '5px 0', borderTop: '1px solid #F0F5F4' }}>
                <span style={{ fontWeight: r.isLead ? 900 : 700, color: r.isLead ? 'var(--bm-cta-2)' : '#2E4A48' }}>{r.domain.replace(/^www\./, '')}{r.isLead ? ' ← jij' : ''}</span>
                <span style={{ color: '#5A7472' }}>
                  {r.etv != null ? `≈ ${fmtNum(r.etv)} bez. p/m` : 'geen data'}
                  {r.paidCost > 0 && ` · advertentiewaarde ≈ € ${fmtNum(r.paidCost)} p/m`}
                </span>
              </div>
            ))}
            <p style={{ margin: '10px 0 0', fontSize: 11.5, color: '#8AA3A1' }}>Advertentiewaarde = wat dit organische verkeer via Google Ads zou kosten.</p>
          </NotchCard>
        </React.Fragment>
      )}
      {!deep && <StepBrug text={s.brug} />}
    </SectionShell>
  );
}

// v10 — Wie scoort waar: keyword × jij en je 2 concurrenten (live posities)
function RankingSection({ data, num, tag }) {
  const s = data.steps.step2;
  const comps = (data.competitorData?.list || []).map((c) => c.domain.replace(/^www\./, ''));
  const kws = data.keywords || [];
  const posCell = (pos) => pos
    ? <span style={{ fontWeight: 800, color: pos <= 3 ? 'var(--bm-teal-ink)' : '#2E4A48' }}>#{pos}</span>
    : <span style={{ color: '#C4441C', fontSize: 12 }}>—</span>;

  return (
    <SectionShell num={num} tag={tag || 'SEO · Ranking'} title="Wie scoort waar op jouw zoektermen?" alt>
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>
      <NotchCard style={{ padding: '4px 0 0', overflow: 'hidden' }} notch={16}>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5, minWidth: 560 }}>
            <thead>
              <tr style={{ textAlign: 'left', color: '#5A7472', fontSize: 11.5, textTransform: 'uppercase', letterSpacing: '0.8px' }}>
                <th style={{ padding: '12px 20px' }}>Zoekterm</th>
                <th style={{ padding: '12px 10px' }}>Volume</th>
                <th style={{ padding: '12px 10px', color: 'var(--bm-cta-2)' }}>Jij</th>
                {comps.map((c) => <th key={c} style={{ padding: '12px 10px' }}>{c}</th>)}
              </tr>
            </thead>
            <tbody>
              {kws.map((k, i) => (
                <tr key={k.kw} style={{ borderTop: '1px solid #E4EDEC', background: i % 2 ? '#FAFCFB' : '#fff' }}>
                  <td style={{ padding: '11px 20px', fontWeight: 700, color: '#12302E' }}>{k.kw}</td>
                  <td style={{ padding: '11px 10px', color: '#5A7472' }}>{k.vol}</td>
                  <td style={{ padding: '11px 10px' }} title={k.ownUrl ? `Je scoort met ${k.ownUrl}` : undefined}>{posCell(k.posRaw)}</td>
                  {comps.map((c) => <td key={c} style={{ padding: '11px 10px' }}>{posCell(k.compPos?.[c])}</td>)}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </NotchCard>
      <p style={{ marginTop: 14, fontSize: 12.5, color: '#8AA3A1' }}>Posities vandaag live gemeten in de top-20; "—" = niet gevonden.</p>
      <StepBrug text={s.brug} />
    </SectionShell>
  );
}

// v11 — Zoektermen per gekozen dienst, met de posities van jou én je twee concurrenten
function KeywordsDienstSection({ data, num, tag }) {
  const s = data.steps.step1;
  const kws = data.keywords || [];
  const comps = (data.competitorData?.list || []).map((c) => c.domain.replace(/^www\./, ''));
  const posCell = (pos) => pos
    ? <span style={{ fontWeight: 800, color: pos <= 3 ? 'var(--bm-teal-ink)' : '#2E4A48' }}>#{pos}</span>
    : <span style={{ color: '#C4441C', fontSize: 12 }}>—</span>;

  // Groepeer per dienst (wizard-koppeling); zonder koppeling één gezamenlijke tabel
  const orde = (s.diensten || []).map((d) => d.dienst.toLowerCase());
  const byDienst = new Map();
  for (const k of kws) {
    const key = k.dienst || '';
    if (!byDienst.has(key)) byDienst.set(key, []);
    byDienst.get(key).push(k);
  }
  const grouped = !(byDienst.size === 1 && byDienst.has(''));
  const groups = [...byDienst.entries()]
    .sort((a, b) => {
      const ia = orde.indexOf(a[0].toLowerCase()); const ib = orde.indexOf(b[0].toLowerCase());
      return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib);
    })
    .map(([dienst, terms]) => ({
      dienst: dienst || (grouped ? 'Overige termen' : 'Jouw zoektermen'),
      terms,
      duiding: dienst ? (s.diensten || []).find((d) => d.dienst.toLowerCase() === dienst.toLowerCase())?.duiding : null,
    }));

  return (
    <SectionShell num={num} tag={tag || 'SEO · Zoektermen & posities'} title="Waar zoekt jouw klant en waar sta jij?">
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>

      {groups.map((g) => {
        const vol = g.terms.reduce((sum, k) => sum + (k.volRaw || 0), 0);
        return (
          <NotchCard key={g.dienst} style={{ padding: '20px 0 0', overflow: 'hidden', marginBottom: 20 }} notch={16}>
            <div style={{ padding: '0 24px', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
              <h3 style={{ margin: 0, fontSize: 17, fontWeight: 900 }}>{g.dienst.charAt(0).toUpperCase() + g.dienst.slice(1)}</h3>
              <span style={{ fontSize: 12.5, color: '#8AA3A1' }}>{g.terms.length} termen · {fmtNum(vol)} zoekopdrachten p/m</span>
            </div>
            <div style={{ overflowX: 'auto', marginTop: 10 }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5, minWidth: 620 }}>
                <thead>
                  <tr style={{ textAlign: 'left', color: '#5A7472', fontSize: 11.5, textTransform: 'uppercase', letterSpacing: '0.8px' }}>
                    <th style={{ padding: '10px 24px' }}>Zoekterm</th>
                    <th style={{ padding: '10px 10px' }}>Volume p/m</th>
                    <th style={{ padding: '10px 10px' }}>Klikprijs</th>
                    <th style={{ padding: '10px 10px', color: 'var(--bm-cta-2)' }}>Jij</th>
                    {comps.map((c) => <th key={c} style={{ padding: '10px 10px' }}>{c}</th>)}
                  </tr>
                </thead>
                <tbody>
                  {g.terms.map((k, i) => (
                    <tr key={k.kw} style={{ borderTop: '1px solid #E4EDEC', background: i % 2 ? '#FAFCFB' : '#fff' }}>
                      <td style={{ padding: '10px 24px' }}>
                        <div style={{ fontWeight: 700, color: '#12302E' }}>{k.kw}</div>
                        {(k.aiOverview || k.localPack || k.infoSerp) && (
                          <div style={{ fontSize: 11, marginTop: 2 }}>
                            {k.aiOverview && <span title={k.aiRefs?.length ? `AI-antwoord aanwezig; citeert o.a. ${k.aiRefs.join(', ')}` : 'AI-antwoord aanwezig'} style={{ marginRight: 8, color: '#6B4FA3', fontWeight: 700 }}>AI-antwoord</span>}
                            {k.localPack && <span title="Google toont hier een lokaal kaartenblok" style={{ marginRight: 8, color: 'var(--bm-teal-ink)', fontWeight: 700 }}>lokaal blok</span>}
                            {k.infoSerp && <span title="De zoekresultaten worden gedomineerd door naslagwerken: hier win je met content, niet met een productpagina" style={{ color: '#B96A12', fontWeight: 700 }}>contentkans</span>}
                          </div>
                        )}
                      </td>
                      <td style={{ padding: '10px 10px', color: '#5A7472' }}>{k.vol}</td>
                      <td style={{ padding: '10px 10px', color: '#5A7472', whiteSpace: 'nowrap' }}>{k.cpc}</td>
                      <td style={{ padding: '10px 10px' }} title={k.ownUrl ? `Je scoort hier met ${k.ownUrl}` : undefined}>{posCell(k.posRaw)}</td>
                      {comps.map((c) => <td key={c} style={{ padding: '10px 10px' }}>{posCell(k.compPos?.[c])}</td>)}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            {g.duiding && (
              <p style={{ margin: 0, padding: '14px 24px', borderTop: '1px solid #E4EDEC', background: '#F4F8F7', fontSize: 13.5, lineHeight: 1.6, color: '#3A5250' }}>{g.duiding}</p>
            )}
          </NotchCard>
        );
      })}

      {!grouped && s.diensten?.length > 0 && (
        <div style={{ margin: '4px 0 0' }}>
          {s.diensten.map((d) => (
            <p key={d.dienst} style={{ margin: '10px 0 0', fontSize: 13.5, lineHeight: 1.6, color: '#3A5250' }}>
              <strong>{d.dienst.charAt(0).toUpperCase() + d.dienst.slice(1)}:</strong> {d.duiding}
            </p>
          ))}
        </div>
      )}

      {kws.some((k) => k.aiOverview) && (
        <p style={{ marginTop: 6, fontSize: 13.5, fontWeight: 700, color: '#6B4FA3' }}>
          Op {kws.filter((k) => k.aiOverview).length} van de {kws.length} termen toont Google een AI-antwoord; wie daarin geciteerd wordt, pakt kliks vóór de gewone zoekresultaten.
        </p>
      )}

      {/* Wat klanten verder aan Google vragen (People Also Ask) */}
      {data.paaQuestions?.length > 0 && (
        <NotchCard style={{ padding: '22px 24px', marginTop: 22 }} notch={14}>
          <h3 style={{ margin: '0 0 4px', fontSize: 15, fontWeight: 900 }}>Dit vraagt jouw klant aan Google</h3>
          <p style={{ margin: '0 0 12px', fontSize: 12.5, color: '#8AA3A1' }}>Echte vervolgvragen uit de zoekresultaten op jouw termen; elke vraag is een pagina- of contentkans.</p>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: '4px 24px' }}>
            {data.paaQuestions.map((q) => (
              <div key={q.vraag} style={{ fontSize: 13.5, color: '#3A5250', padding: '5px 0', borderBottom: '1px solid #F0F5F4' }}>
                “{q.vraag}” <span style={{ fontSize: 11.5, color: '#8AA3A1' }}>bij "{q.kw}"</span>
              </div>
            ))}
          </div>
        </NotchCard>
      )}
      <p style={{ marginTop: 14, fontSize: 12.5, color: '#8AA3A1' }}>
        {data.dataQuality?.positionsLive
          ? 'Posities vandaag live in Google gemeten (regio Nederland, zonder personalisatie); "—" = geen positie in de top 20.'
          : 'Bron: actuele zoekdata (DataForSEO), regio Nederland.'}
        {' '}{kws.some((k) => String(k.cpc).includes('–'))
          ? 'Klikprijs = het lage en hoge topbod volgens Google Ads.'
          : 'Klikprijs = de verwachte kosten per klik in Google Ads.'}
      </p>
      <StepBrug text={s.brug} />
      <SectieCta text="Deze posities verbeteren? Bespreek het in een gratis strategiegesprek" />
    </SectionShell>
  );
}

// Interactieve verkeersgrafiek met twee views: absoluut verkeer per maand
// (lijnen) en het aantal zoektermen per positiegroep (kolommen).
// series: [{ label, color, isLead, points: [{ ym, etv, buckets? }] }]
const BUCKET_META = [
  { key: 't3', label: 'Top 1-3' },
  { key: 't10', label: '4-10' },
  { key: 't20', label: '11-20' },
  { key: 't50', label: '21-50' },
  { key: 't100', label: '51-100' },
];
function TrafficLineChart({ series }) {
  const { useState, useRef } = React;
  const [view, setView] = useState('verkeer');
  const [hover, setHover] = useState(null);
  const svgRef = useRef(null);
  const months = [...new Set(series.flatMap((s) => s.points.map((p) => p.ym)))].sort();
  if (months.length < 2) return null;
  const hasBuckets = series.some((s) => s.points[s.points.length - 1]?.buckets);
  const W = 760, H = 250, PL = 46, PR = 16, PT = 14, PB = 28;

  const legend = (
    <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', marginTop: 8 }}>
      {series.map((l) => (
        <span key={l.label} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12.5, fontWeight: l.isLead ? 900 : 700, color: l.isLead ? 'var(--bm-cta-2)' : '#3A5250' }}>
          <span style={{ width: 14, height: 3, borderRadius: 2, background: l.color, display: 'inline-block' }}></span>
          {l.label}{l.isLead ? ' ← jij' : ''}
        </span>
      ))}
    </div>
  );

  // View 2 — zoektermen per positiegroep (laatste maand), kolommen per domein
  const bucketChart = (() => {
    if (!hasBuckets) return null;
    const bySeries = series.map((s) => ({ ...s, buckets: s.points[s.points.length - 1]?.buckets || null }));
    const maxV = Math.max(...bySeries.flatMap((s) => s.buckets ? BUCKET_META.map((b) => s.buckets[b.key] || 0) : [0]), 1);
    const groupW = (W - PL - PR) / BUCKET_META.length;
    const barW = Math.min(34, (groupW - 24) / bySeries.length);
    const y = (v) => PT + 14 + (1 - v / maxV) * (H - PT - 14 - PB);
    return (
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', display: 'block' }}>
        {[0, 0.5, 1].map((f) => (
          <g key={f}>
            <line x1={PL} x2={W - PR} y1={y(maxV * f)} y2={y(maxV * f)} stroke="#E4EDEC" strokeWidth="1" />
            <text x={PL - 6} y={y(maxV * f) + 3.5} textAnchor="end" fontSize="10" fill="#8AA3A1">{fmtShort(maxV * f)}</text>
          </g>
        ))}
        {BUCKET_META.map((b, gi) => {
          const gx = PL + gi * groupW + groupW / 2;
          return (
            <g key={b.key}>
              {bySeries.map((s, si) => {
                const v = s.buckets ? (s.buckets[b.key] || 0) : 0;
                const bx = gx + (si - (bySeries.length - 1) / 2) * (barW + 4) - barW / 2;
                return (
                  <g key={s.label}>
                    <rect x={bx} y={y(v)} width={barW} height={Math.max(2, (H - PB) - y(v))} rx="3" fill={s.color} opacity={s.isLead ? 1 : 0.85}>
                      <title>{`${s.label} · ${b.label}: ${fmtNum(v)} zoektermen`}</title>
                    </rect>
                    <text x={bx + barW / 2} y={y(v) - 4} textAnchor="middle" fontSize="9.5" fontWeight="700" fill="#5A7472">{v > 0 ? fmtShort(v) : ''}</text>
                  </g>
                );
              })}
              <text x={gx} y={H - 8} textAnchor="middle" fontSize="10.5" fontWeight="700" fill="#5A7472">{b.label}</text>
            </g>
          );
        })}
      </svg>
    );
  })();

  // View 1 — absoluut verkeer per maand (lijnen met hover)
  const lines = series.map((s) => {
    const map = new Map(s.points.map((p) => [p.ym, p.etv]));
    return { ...s, values: months.map((ym) => map.get(ym) ?? null) };
  });
  const maxY = Math.max(...lines.flatMap((l) => l.values.filter((v) => v != null)), 1);
  const x = (i) => PL + (i / (months.length - 1)) * (W - PL - PR);
  const y = (v) => PT + (1 - v / maxY) * (H - PT - PB);
  const pathFor = (vals) => {
    let d = ''; let pen = false;
    vals.forEach((v, i) => {
      if (v == null) { pen = false; return; }
      d += `${pen ? 'L' : 'M'}${x(i).toFixed(1)},${y(v).toFixed(1)}`;
      pen = true;
    });
    return d;
  };
  const onMove = (e) => {
    const rect = svgRef.current?.getBoundingClientRect();
    if (!rect || !rect.width) return;
    const px = ((e.clientX - rect.left) / rect.width) * W;
    const i = Math.round(((px - PL) / (W - PL - PR)) * (months.length - 1));
    setHover(Math.max(0, Math.min(months.length - 1, i)));
  };

  return (
    <div>
      {hasBuckets && (
        <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
          {[['verkeer', 'Verkeer per maand'], ['termen', 'Zoektermen per positie']].map(([m, label]) => (
            <button key={m} onClick={() => { setView(m); setHover(null); }}
              style={{ fontSize: 12, fontWeight: 800, borderRadius: 999, padding: '5px 14px', cursor: 'pointer', border: '1px solid #D8E5E3', background: view === m ? 'var(--bm-dark)' : '#fff', color: view === m ? '#fff' : '#3A5250', fontFamily: "'Lato', sans-serif" }}>
              {label}
            </button>
          ))}
        </div>
      )}
      {view === 'termen' && bucketChart ? bucketChart : (
        <div style={{ position: 'relative' }}>
          <svg ref={svgRef} viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', display: 'block', touchAction: 'pan-y' }}
            onMouseMove={onMove} onMouseLeave={() => setHover(null)}>
            {[0, 0.5, 1].map((f) => (
              <g key={f}>
                <line x1={PL} x2={W - PR} y1={y(maxY * f)} y2={y(maxY * f)} stroke="#E4EDEC" strokeWidth="1" />
                <text x={PL - 6} y={y(maxY * f) + 3.5} textAnchor="end" fontSize="10" fill="#8AA3A1">{fmtShort(maxY * f)}</text>
              </g>
            ))}
            {[0, Math.floor((months.length - 1) / 2), months.length - 1].map((i) => (
              <text key={i} x={x(i)} y={H - 8} textAnchor="middle" fontSize="10" fill="#8AA3A1">{months[i]}</text>
            ))}
            {hover != null && <line x1={x(hover)} x2={x(hover)} y1={PT} y2={H - PB} stroke="#B8CCCA" strokeWidth="1" strokeDasharray="3 3" />}
            {lines.map((l) => (
              <path key={l.label} d={pathFor(l.values)} fill="none" stroke={l.color} strokeWidth={l.isLead ? 3 : 2} strokeLinejoin="round" strokeLinecap="round" opacity={l.isLead ? 1 : 0.85} />
            ))}
            {hover != null && lines.map((l) => l.values[hover] != null && (
              <circle key={l.label} cx={x(hover)} cy={y(l.values[hover])} r="4.5" fill={l.color} stroke="#fff" strokeWidth="1.5" />
            ))}
            {/* brede onzichtbare hover-laag zodat ook touch/kleine bewegingen pakken */}
            <rect x={PL} y={PT} width={W - PL - PR} height={H - PT - PB} fill="transparent" />
          </svg>
          {hover != null && (
            <div style={{ position: 'absolute', top: 6, [hover > (months.length - 1) / 2 ? 'left' : 'right']: 8, background: 'var(--bm-dark)', color: '#fff', borderRadius: 10, padding: '10px 14px', fontSize: 12, pointerEvents: 'none', boxShadow: '0 6px 18px rgba(0,0,0,0.18)', minWidth: 170 }}>
              <div style={{ fontWeight: 800, marginBottom: 4 }}>{months[hover]}</div>
              {lines.map((l) => (
                <div key={l.label} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '1px 0' }}>
                  <span style={{ width: 8, height: 8, borderRadius: 2, background: l.color, display: 'inline-block', flex: '0 0 auto' }}></span>
                  <span style={{ color: '#C6DBD9' }}>{l.label}</span>
                  <span style={{ fontWeight: 800, marginLeft: 'auto', paddingLeft: 10, whiteSpace: 'nowrap' }}>{l.values[hover] == null ? 'geen data' : `≈ ${fmtNum(Math.round(l.values[hover]))} bez.`}</span>
                </div>
              ))}
            </div>
          )}
        </div>
      )}
      {legend}
      <p style={{ margin: '8px 0 0', fontSize: 11.5, color: '#8AA3A1' }}>
        {view === 'termen'
          ? 'Aantal zoektermen waarmee elk domein in deze positiegroepen staat (meest recente maand).'
          : 'Geschatte organische bezoekers per maand. Beweeg over de grafiek voor de cijfers per maand.'}
      </p>
    </div>
  );
}

// v11 — Concurrentievergelijking: domeinscores, verkeersontwikkeling, toppagina's
function CompetitionSection({ data, num, tag }) {
  const s = data.steps.step2;
  const comp = data.competitorData;
  const kws = data.keywords || [];
  const metaAds = data.socialData?.competitorAds || [];
  const gAds = data.googleAds || [];
  const whyFor = (domain) => (s.winners || []).find((w) => domain.replace(/^www\./, '').includes(w.domain.replace(/^www\./, '')) || w.domain.replace(/^www\./, '').includes(domain.replace(/^www\./, '')))?.why;
  const COMP_COLORS = ['var(--bm-teal)', '#4A6FA5'];
  const rows = [
    { dom: comp.lead.domain.replace(/^www\./, ''), etv: comp.lead.etv, paidCost: comp.lead.paidCost, authority: comp.lead.authority, refDomains: comp.lead.refDomains, isLead: true, topPages: data.leadTopPages, history: data.history, color: 'var(--bm-cta-1)' },
    ...comp.list.map((c, i) => ({ dom: c.domain.replace(/^www\./, ''), etv: c.etv, paidCost: c.paidCost, authority: c.authority, refDomains: c.refDomains, isLead: false, noData: !!c.noData, topPages: c.topPages, history: c.history, color: COMP_COLORS[i % COMP_COLORS.length] })),
  ];
  const chartSeries = rows
    .filter((r) => r.history?.length >= 6)
    .map((r) => ({ label: r.dom, color: r.color, isLead: r.isLead, points: r.history }));
  const pagesRows = rows.filter((r) => r.topPages?.length);

  return (
    <SectionShell num={num} tag={tag || 'SEO · Concurrentie'} title="Hoe sta je ervoor tegenover je concurrenten?" alt>
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>

      {/* Domeinscores: autoriteit en links prominent per domein, naast elkaar te vergelijken */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 18, marginBottom: 10 }}>
        {rows.map((r) => (
          <NotchCard key={r.dom} style={{ padding: '20px 22px', borderTop: `3px solid ${r.isLead ? 'var(--bm-cta-1)' : r.color}` }} notch={14}>
            <div style={{ fontSize: 14, fontWeight: 900, color: r.isLead ? 'var(--bm-cta-2)' : '#12302E', marginBottom: 14, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
              {r.dom}{r.isLead ? ' ← jij' : ''}
            </div>
            <div style={{ marginBottom: 14 }}>
              <div style={{ fontSize: 30, fontWeight: 900, color: '#12302E', fontFamily: "'Lato', sans-serif", lineHeight: 1 }}>
                {r.authority != null ? r.authority : '—'}<span style={{ fontSize: 15, color: '#8AA3A1', fontWeight: 700 }}>/100</span>
              </div>
              <div style={{ fontSize: 11.5, color: '#8AA3A1', margin: '3px 0 6px' }}>autoriteitsscore</div>
              <div style={{ height: 8, background: '#EEF4F3', borderRadius: 999 }}>
                <div style={{ width: `${Math.max(2, r.authority || 0)}%`, height: '100%', borderRadius: 999, background: r.isLead ? 'var(--bm-cta-1)' : r.color }}></div>
              </div>
            </div>
            <div style={{ marginBottom: 12 }}>
              <div style={{ fontSize: 30, fontWeight: 900, color: '#12302E', fontFamily: "'Lato', sans-serif", lineHeight: 1 }}>
                {r.refDomains != null ? fmtNum(r.refDomains) : '—'}
              </div>
              <div style={{ fontSize: 11.5, color: '#8AA3A1', marginTop: 3 }}>verwijzende websites</div>
            </div>
            <div style={{ borderTop: '1px solid #F0F5F4', paddingTop: 10, fontSize: 12.5, color: '#5A7472' }}>
              {r.noData ? 'geen meetbaar organisch bezoek' : `≈ ${fmtNum(r.etv || 0)} bez. p/m`}
              {r.paidCost > 0 && <React.Fragment> · waarde ≈ € {fmtNum(r.paidCost)} p/m</React.Fragment>}
            </div>
          </NotchCard>
        ))}
      </div>
      <p style={{ margin: '0 0 22px', fontSize: 11.5, color: '#8AA3A1' }}>
        Autoriteit op een schaal van 0-100 (hoe sterker het linkprofiel, hoe hoger); verwijzende websites = unieke domeinen die naar de site linken. Bezoek = geschat organisch bezoek per maand; waarde = wat dat verkeer via Google Ads zou kosten.
        {data.dataQuality?.semrush ? ' Bron domeincijfers: Semrush (NL).' : ' Gekalibreerd op echt klikgedrag.'}
      </p>

      {/* Interactieve verkeersgrafiek over 12 maanden */}
      {chartSeries.length > 0 && (
        <NotchCard style={{ padding: '20px 24px', marginBottom: 22 }} notch={16}>
          <h3 style={{ margin: '0 0 12px', fontSize: 15, fontWeight: 900 }}>Verkeer en zoektermposities vergeleken</h3>
          <TrafficLineChart series={chartSeries} />
        </NotchCard>
      )}

      {/* Sterkste pagina's per domein */}
      {pagesRows.length > 0 && (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 18, marginBottom: 22 }}>
          {pagesRows.map((r) => (
            <NotchCard key={r.dom} style={{ padding: '18px 20px' }} notch={14}>
              <div style={{ fontSize: 13.5, fontWeight: 900, color: r.isLead ? 'var(--bm-cta-2)' : '#12302E', marginBottom: 8 }}>
                Sterkste pagina's · {r.dom}{r.isLead ? ' ← jij' : ''}
              </div>
              {r.topPages.slice(0, 3).map((p) => (
                <div key={p.path} style={{ display: 'flex', justifyContent: 'space-between', gap: 10, fontSize: 12, padding: '3px 0', color: '#5A7472' }}>
                  <span style={{ fontFamily: 'monospace', fontSize: 11.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.path}</span>
                  <span style={{ flex: '0 0 auto' }}>≈ {fmtNum(p.etv)} bez.</span>
                </div>
              ))}
            </NotchCard>
          ))}
        </div>
      )}

      {/* Duiding per concurrent */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))', gap: 18 }}>
        {comp.list.map((c) => {
          const dom = c.domain.replace(/^www\./, '');
          const topOn = kws.filter((k) => (k.top3 || []).some((d) => d === dom)).map((k) => k.kw);
          const ad = metaAds.find((a) => a.domain.replace(/^www\./, '') === dom);
          const g = gAds.find((x) => x.domain === dom);
          const why = whyFor(c.domain);
          return (
            <NotchCard key={c.domain} style={{ padding: '20px 22px' }} notch={14}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' }}>
                <h3 style={{ margin: 0, fontSize: 16, fontWeight: 900 }}>{dom}</h3>
                <span style={{ fontSize: 10.5, fontWeight: 800, borderRadius: 999, padding: '3px 10px', background: c.userProvided ? '#FDEFD9' : '#E9F2F1', color: c.userProvided ? '#B96A12' : 'var(--bm-teal-ink)' }}>
                  {c.userProvided ? 'door jou opgegeven' : c.serpFound ? 'staat in jouw zoekresultaten' : 'zelfde speelveld'}
                </span>
              </div>
              {topOn.length > 0 && (
                <div style={{ fontSize: 12.5, color: '#3A5250', margin: '10px 0 0' }}>
                  <span style={{ fontWeight: 800 }}>In de top-3 op jouw termen:</span> {topOn.slice(0, 3).join(' · ')}
                </div>
              )}
              {(ad || g) && (
                <div style={{ fontSize: 12.5, color: '#5A7472', margin: '8px 0 0' }}>
                  {ad && <span style={{ color: ad.activeAds > 0 ? '#B96A12' : '#8AA3A1', fontWeight: 700 }}>{ad.activeAds > 0 ? `adverteert op Meta (${ad.activeAds}${ad.cappedAt ? '+' : ''})` : 'geen Meta-advertenties'}</span>}
                  {ad && g && ' · '}
                  {g && <span title={`Adverteert in Google op: ${g.terms.join(', ')}`} style={{ color: '#B96A12', fontWeight: 700 }}>adverteert in Google ({g.terms.length} {g.terms.length === 1 ? 'term' : 'termen'})</span>}
                </div>
              )}
              {why && <p style={{ margin: '12px 0 0', paddingTop: 10, borderTop: '1px solid #F0F5F4', fontSize: 13, lineHeight: 1.55, color: '#3A5250' }}>{why}</p>}
            </NotchCard>
          );
        })}
      </div>
      <StepBrug text={s.brug} />
      <SectieCta text="Weten hoe je dit gat dichtloopt? Plan een gratis strategiegesprek" />
    </SectionShell>
  );
}

// v10/v11 — Google Ads: campagnestructuur & full-circle strategie (interactief)
function AdsStructureSection({ data, num, tag }) {
  const { useState } = React;
  const a = data.steps.ads;
  const [active, setActive] = useState(0);
  const camp = a.campagnes[Math.min(active, a.campagnes.length - 1)];
  const FLOW = [
    { t: 'Advertentie', d: 'op een concrete productterm' },
    { t: 'Landingspagina', d: 'die naadloos aansluit op de zoekvraag' },
    { t: 'Conversie', d: 'aanvraag of bestelling op die pagina' },
    { t: 'Data terug', d: 'conversies sturen de campagne bij' },
  ];

  return (
    <SectionShell num={num} tag={tag || 'Google Ads · Strategie'} title="Zo zet je Google Ads slim in">
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{a.intro}</p>

      {/* De full-circle strategie als visuele kringloop */}
      <div style={{ display: 'flex', alignItems: 'stretch', gap: 8, flexWrap: 'wrap', marginBottom: 30 }}>
        {FLOW.map((f, i) => (
          <React.Fragment key={f.t}>
            <div style={{ flex: '1 1 160px', minWidth: 160, background: i === FLOW.length - 1 ? 'var(--bm-dark)' : '#fff', border: '1px solid #E4EDEC', borderRadius: 14, padding: '14px 16px' }}>
              <div style={{ fontSize: 11, fontWeight: 900, color: i === FLOW.length - 1 ? '#7FD1A8' : 'var(--bm-teal-ink)', letterSpacing: '0.8px' }}>STAP {i + 1}</div>
              <div style={{ fontSize: 14.5, fontWeight: 900, color: i === FLOW.length - 1 ? '#fff' : '#12302E', margin: '2px 0' }}>{f.t}</div>
              <div style={{ fontSize: 11.5, lineHeight: 1.45, color: i === FLOW.length - 1 ? '#8FB5B1' : '#5A7472' }}>{f.d}</div>
            </div>
            {i < FLOW.length - 1 && <span style={{ alignSelf: 'center', color: '#8AA3A1', fontSize: 18, fontWeight: 900, flex: '0 0 auto' }}>→</span>}
          </React.Fragment>
        ))}
        <span title="De conversiedata gaat terug naar stap 1: zo wordt elke advertentie-euro steeds gerichter ingezet" style={{ alignSelf: 'center', color: 'var(--bm-teal-ink)', fontSize: 22, fontWeight: 900, flex: '0 0 auto' }}>↺</span>
      </div>

      {/* Campagnestructuur: tabs per campagne */}
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
        {a.campagnes.map((c, i) => (
          <button key={c.naam} onClick={() => setActive(i)}
            style={{ fontSize: 13, fontWeight: 800, borderRadius: '12px 12px 0 0', padding: '11px 18px', cursor: 'pointer', border: '1px solid #E4EDEC', borderBottom: 'none', background: i === active ? 'var(--bm-dark)' : '#fff', color: i === active ? '#fff' : '#3A5250', fontFamily: "'Lato', sans-serif", transition: 'background 0.15s' }}>
            {c.naam}
          </button>
        ))}
      </div>
      <NotchCard style={{ padding: '22px 24px', borderTopLeftRadius: 0 }} notch={16}>
        <p style={{ margin: '0 0 16px', fontSize: 13.5, lineHeight: 1.6, color: '#5A7472' }}>{camp.doel}</p>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 14 }}>
          {camp.adgroepen.map((g) => (
            <div key={g.naam} style={{ border: '1px solid #EEF4F3', borderRadius: 12, padding: '14px 16px', background: '#FAFCFB' }}>
              <div style={{ fontSize: 13.5, fontWeight: 900, color: '#12302E', marginBottom: 8 }}>{g.naam}</div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
                {g.keywords.map((kw) => (
                  <span key={kw} style={{ fontSize: 11.5, background: '#E9F2F1', color: 'var(--bm-teal-ink)', borderRadius: 999, padding: '3px 10px' }}>{kw}</span>
                ))}
              </div>
              <p style={{ margin: 0, fontSize: 12.5, lineHeight: 1.55, color: '#5A7472' }}>
                <span style={{ fontWeight: 800, color: '#3A5250' }}>Landingspagina:</span> {g.landingspagina}
              </p>
            </div>
          ))}
        </div>
      </NotchCard>
      {a.campagnes.length > 1 && (
        <p style={{ marginTop: 12, fontSize: 12.5, color: '#8AA3A1' }}>Klik op een campagne om de bijbehorende advertentiegroepen en landingspagina's te bekijken.</p>
      )}
    </SectionShell>
  );
}

// v10 — Google Ads: budgetvoorstel, groeiprognose, tracking en concurrent-ads
function AdsBudgetSection({ data, num, tag }) {
  const a = data.steps.ads;
  const plan = data.adsPlan;
  const gact = plan?.googleActivity || [];
  const own = data.competitorData?.lead?.domain?.replace(/^www\./, '');

  return (
    <SectionShell num={num} tag={tag || 'Google Ads · Budget'} title="Wat mag het kosten en wat levert het op?" alt>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 18, marginBottom: 26 }}>
        {plan.scenarios.map((sc) => (
          <NotchCard key={sc.key} style={{ padding: '22px 20px' }} notch={14}>
            <div style={{ fontSize: 12, fontWeight: 800, color: '#8AA3A1', textTransform: 'uppercase', letterSpacing: '0.8px' }}>{sc.label}</div>
            <div style={{ fontSize: 30, fontWeight: 900, color: 'var(--bm-teal-ink)', margin: '4px 0' }}>€ {fmtNum(sc.budget)} <span style={{ fontSize: 14, color: '#8AA3A1', fontWeight: 700 }}>p/m</span></div>
            <div style={{ fontSize: 13.5, color: '#3A5250', fontWeight: 700 }}>≈ {fmtNum(sc.clicks)} kliks · ≈ {sc.leads} {plan.conversie.label} per maand</div>
            <div style={{ fontSize: 12, color: '#8AA3A1', marginTop: 4 }}>~{sc.sharePct}% van de commerciële zoekvraag ({fmtNum(plan.commercieelVolume)}/mnd)</div>
          </NotchCard>
        ))}
        <NotchCard style={{ padding: '22px 20px' }} notch={14}>
          <div style={{ fontSize: 12, fontWeight: 800, color: '#8AA3A1', textTransform: 'uppercase', letterSpacing: '0.8px' }}>Groeiprognose</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 4, alignItems: 'end', height: 60, margin: '12px 0 4px' }}>
            {plan.prognose.map((m) => (
              <div key={m.maand} title={`maand ${m.maand}: ~${Math.round(m.factor * 100)}%`} style={{ height: `${m.factor * 80}%`, background: 'var(--bm-teal)', opacity: 0.5 + m.factor * 0.4, borderRadius: '3px 3px 0 0' }}></div>
            ))}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 4, fontSize: 9.5, color: '#8AA3A1', textAlign: 'center' }}>
            {plan.prognose.map((m) => <span key={m.maand}>m{m.maand}</span>)}
          </div>
          <p style={{ margin: '8px 0 0', fontSize: 11.5, color: '#8AA3A1' }}>Leercurve: eerste maanden onder het gemiddelde, daarna erboven.</p>
        </NotchCard>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(260px, 340px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div>
          <p style={{ margin: '0 0 18px', fontSize: 15, lineHeight: 1.7, color: '#3A5250' }}>{a.budget_duiding}</p>
          {plan.tracking?.length > 0 && (
            <NotchCard style={{ padding: '20px 22px' }} notch={14}>
              <h3 style={{ margin: '0 0 10px', fontSize: 15, fontWeight: 900 }}>Meten is winnen</h3>
              {plan.tracking.map((t) => (
                <div key={t.key} style={{ borderTop: '1px solid #F0F5F4', padding: '8px 0' }}>
                  <div style={{ fontSize: 13.5, fontWeight: 800, color: '#2E4A48' }}>{t.title}</div>
                  <p style={{ margin: '2px 0 0', fontSize: 12.5, lineHeight: 1.55, color: '#5A7472' }}>{t.why}</p>
                </div>
              ))}
              {a.tracking_zin && <p style={{ margin: '10px 0 0', fontSize: 13, lineHeight: 1.55, color: '#3A5250', fontWeight: 700 }}>{a.tracking_zin}</p>}
            </NotchCard>
          )}
        </div>
        <NotchCard style={{ padding: '24px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 12px', fontSize: 15, fontWeight: 900, color: '#fff' }}>Wie adverteert er in Google?</h3>
          {gact.length ? gact.map((g) => (
            <div key={g.domain} style={{ borderTop: '1px solid rgba(255,255,255,0.12)', padding: '8px 0', fontSize: 13 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
                <span style={{ fontWeight: 800, color: g.domain === own ? 'var(--bm-cta-1)' : '#fff' }}>{g.domain}{g.domain === own ? ' ← jij' : ''}</span>
                <span style={{ color: '#8FB5B1' }}>{g.adCount}{g.cappedAt ? '+' : ''} ads</span>
              </div>
              <div style={{ fontSize: 11.5, color: '#8FB5B1', marginTop: 2 }}>
                {g.formats.join(', ') || 'formaat onbekend'}{g.lastShown ? ` · laatst gezien ${g.lastShown}` : ''}
                {' · '}<a href={g.transparencyUrl} target="_blank" rel="noopener noreferrer" style={{ color: '#7FD1A8' }}>bekijk ↗</a>
              </div>
            </div>
          )) : <p style={{ margin: 0, fontSize: 13, color: '#8FB5B1' }}>Geen advertentiedata beschikbaar voor deze domeinen.</p>}
          <p style={{ margin: '12px 0 0', fontSize: 11, color: '#6E8F8C' }}>Bron: Google Ads Transparency Center (regio NL).</p>
        </NotchCard>
      </div>
      <p style={{ marginTop: 26, fontSize: 12.5, color: '#8AA3A1' }}>
        Budgetscenario's: Brandmerck-rekenmodel {plan.edition} op basis van de gemeten klikprijzen en zoekvolumes van jouw termen; conversie-aanname {plan.conversie.ratio * 100}% voor dit bedrijfstype. Indicatie, geen garantie.
      </p>
    </SectionShell>
  );
}

// v11 — Google Ads: sturen op conversies + wie adverteert er al
function AdsConversieSection({ data, num, tag }) {
  const a = data.steps.ads;
  const plan = data.adsPlan;
  const gact = plan?.googleActivity || [];
  const gAds = data.googleAds || [];
  const own = data.competitorData?.lead?.domain?.replace(/^www\./, '');
  const serpTermsFor = (dom) => gAds.find((x) => x.domain === dom)?.terms || [];
  // SERP-adverteerders (bieden op jouw termen) die niet al via Transparency in beeld zijn
  const extraSerp = gAds.filter((x) => !gact.some((g) => g.domain === x.domain)).slice(0, 4);
  const pct = plan?.conversie ? String(plan.conversie.ratio * 100).replace('.', ',') : null;

  return (
    <SectionShell num={num} tag={tag || 'Google Ads · Conversies & concurrentie'} title="Stuur op aanvragen, niet op kliks" alt>
      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(280px, 380px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div>
          <p style={{ margin: '0 0 18px', fontSize: 15, lineHeight: 1.7, color: '#3A5250' }}>{a.conversie_zin}</p>
          {pct && (
            <NotchCard style={{ padding: '20px 22px', marginBottom: 18, display: 'flex', alignItems: 'center', gap: 18 }} notch={14}>
              <div style={{ fontSize: 34, fontWeight: 900, color: 'var(--bm-teal-ink)', fontFamily: "'Lato', sans-serif", flex: '0 0 auto' }}>{pct}%</div>
              <div style={{ fontSize: 13, lineHeight: 1.5, color: '#3A5250' }}>
                van de kliks leidt bij dit bedrijfstype gemiddeld tot een conversie ({plan.conversie.label}). Dát is het getal om op te sturen, niet het aantal kliks.
              </div>
            </NotchCard>
          )}
          {plan?.tracking?.length > 0 && (
            <NotchCard style={{ padding: '20px 22px' }} notch={14}>
              <h3 style={{ margin: '0 0 10px', fontSize: 15, fontWeight: 900 }}>Meten is winnen</h3>
              {plan.tracking.map((t) => (
                <div key={t.key} style={{ borderTop: '1px solid #F0F5F4', padding: '8px 0' }}>
                  <div style={{ fontSize: 13.5, fontWeight: 800, color: '#2E4A48' }}>{t.title}</div>
                  <p style={{ margin: '2px 0 0', fontSize: 12.5, lineHeight: 1.55, color: '#5A7472' }}>{t.why}</p>
                </div>
              ))}
              {a.tracking_zin && <p style={{ margin: '10px 0 0', fontSize: 13, lineHeight: 1.55, color: '#3A5250', fontWeight: 700 }}>{a.tracking_zin}</p>}
            </NotchCard>
          )}
        </div>

        <NotchCard style={{ padding: '24px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 12px', fontSize: 15, fontWeight: 900, color: '#fff' }}>Wie adverteert er in Google?</h3>
          {gact.length || extraSerp.length ? (
            <React.Fragment>
              {gact.map((g) => {
                const terms = serpTermsFor(g.domain);
                return (
                  <div key={g.domain} style={{ borderTop: '1px solid rgba(255,255,255,0.12)', padding: '8px 0', fontSize: 13 }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
                      <span style={{ fontWeight: 800, color: g.domain === own ? 'var(--bm-cta-1)' : '#fff' }}>{g.domain}{g.domain === own ? ' ← jij' : ''}</span>
                      <span style={{ color: '#8FB5B1', flex: '0 0 auto' }}>{g.adCount}{g.cappedAt ? '+' : ''} ads</span>
                    </div>
                    <div style={{ fontSize: 11.5, color: '#8FB5B1', marginTop: 2 }}>
                      {terms.length ? `biedt op: ${terms.slice(0, 3).join(', ')}` : (g.formats.join(', ') || 'formaat onbekend')}
                      {g.lastShown ? ` · laatst gezien ${g.lastShown}` : ''}
                      {' · '}<a href={g.transparencyUrl} target="_blank" rel="noopener noreferrer" style={{ color: '#7FD1A8' }}>bekijk ↗</a>
                    </div>
                  </div>
                );
              })}
              {extraSerp.map((g) => (
                <div key={g.domain} style={{ borderTop: '1px solid rgba(255,255,255,0.12)', padding: '8px 0', fontSize: 13 }}>
                  <div style={{ fontWeight: 800, color: g.domain === own ? 'var(--bm-cta-1)' : '#fff' }}>{g.domain}{g.domain === own ? ' ← jij' : ''}</div>
                  <div style={{ fontSize: 11.5, color: '#8FB5B1', marginTop: 2 }}>gezien in de advertenties op: {g.terms.slice(0, 3).join(', ')}</div>
                </div>
              ))}
            </React.Fragment>
          ) : <p style={{ margin: 0, fontSize: 13, color: '#8FB5B1' }}>Op jouw termen en bij deze domeinen zijn nu geen Google-advertenties gezien. Dat betekent vrij baan: de eerste die hier serieus adverteert, pakt de commerciële kliks.</p>}
          {a.concurrentie_zin && <p style={{ margin: '12px 0 0', fontSize: 13, lineHeight: 1.55, color: '#C6DBD9', fontWeight: 700 }}>{a.concurrentie_zin}</p>}
          <p style={{ margin: '12px 0 0', fontSize: 11, color: '#6E8F8C' }}>Bron: Google Ads Transparency Center (regio NL) en live gemeten advertenties op jouw zoektermen.</p>
        </NotchCard>
      </div>
      {plan?.conversie && (
        <p style={{ marginTop: 26, fontSize: 12.5, color: '#8AA3A1' }}>
          Conversie-aanname {pct}% voor dit bedrijfstype (Brandmerck-rekenmodel {plan.edition}); indicatie, geen garantie.
        </p>
      )}
      <SectieCta text="Je meting en campagnes goed laten inrichten? Plan een gratis strategiegesprek" />
    </SectionShell>
  );
}

// Stap 3 — Waar sta jij nu? (zichtbaarheid per fase + fundament)
function Step3Section({ data, num, tag }) {
  const s = data.steps.step3;
  const kws = data.keywords || [];
  const t = data.techData;
  const lead = data.competitorData?.lead;
  const hist = data.history || null;
  const histDir = hist && hist.length >= 6 ? (() => {
    const f = hist[0].etv || 1;
    const l = hist[hist.length - 1].etv || 0;
    return l > f * 1.15 ? { label: 'stijgend', kleur: '#7FD1A8' } : l < f * 0.85 ? { label: 'dalend', kleur: '#F08A5A' } : { label: 'stabiel', kleur: '#F0C05A' };
  })() : null;
  const maxHist = hist ? Math.max(...hist.map((m) => m.etv), 1) : 1;

  return (
    <SectionShell num={num} tag={tag || "Stap 3 van 5 · Jouw positie"} title="Waar sta jij nu?">
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(280px, 380px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <NotchCard style={{ padding: '24px 24px' }} notch={16}>
          <h3 style={{ margin: '0 0 14px', fontSize: 15, fontWeight: 900 }}>Jouw zichtbaarheid per klantfase</h3>
          {FASE_ORDER.map((f) => {
            const terms = kws.filter((k) => k.fase === f);
            const visible = terms.filter((k) => k.posRaw && k.posRaw <= 20).length;
            const pct = terms.length ? (visible / terms.length) * 100 : 0;
            return (
              <div key={f} style={{ marginBottom: 14 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, marginBottom: 4 }}>
                  <span style={{ fontWeight: 700, color: '#2E4A48' }}>{FASE_META[f].label}</span>
                  <span style={{ color: '#5A7472' }}>{terms.length ? `zichtbaar op ${visible} van ${terms.length} termen` : 'geen termen'}</span>
                </div>
                <div style={{ height: 10, background: '#EEF4F3', borderRadius: 999 }}>
                  <div style={{ width: `${Math.max(pct, 2)}%`, height: '100%', borderRadius: 999, background: pct > 0 ? 'var(--bm-teal)' : '#F0D5C8' }}></div>
                </div>
              </div>
            );
          })}
          {t && !!t.totalIssues && (
            <div style={{ marginTop: 18, paddingTop: 14, borderTop: '1px solid #E4EDEC', fontSize: 12.5, color: '#5A7472' }}>
              <span style={{ fontWeight: 800, color: '#3A5250' }}>Technische verbeterpunten ({fmtNum(t.totalIssues)}):</span>{' '}
              {t.top.map((i) => `${i.label} (${i.count}×)`).join(' · ')}
            </div>
          )}
          {data.localPackBiz?.length > 0 && (
            <div style={{ marginTop: 18, paddingTop: 14, borderTop: '1px solid #E4EDEC' }}>
              <div style={{ fontSize: 13, fontWeight: 800, color: '#3A5250', marginBottom: 6 }}>Wie staat er in het lokale kaartenblok?</div>
              {data.localPackBiz.map((b) => (
                <div key={b.title} style={{ display: 'flex', justifyContent: 'space-between', gap: 10, fontSize: 12.5, color: '#5A7472', padding: '3px 0' }}>
                  <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{b.title}</span>
                  <span style={{ flex: '0 0 auto' }}>{b.rating != null ? `${String(b.rating).replace('.', ',')}★${b.votes != null ? ` · ${fmtNum(b.votes)} reviews` : ''}` : '—'}</span>
                </div>
              ))}
              <p style={{ margin: '8px 0 0', fontSize: 11.5, color: '#8AA3A1' }}>Het kaartenblok pakt bij lokale zoekopdrachten de meeste kliks; je Google-bedrijfsprofiel en reviews bepalen wie erin staat.</p>
            </div>
          )}
        </NotchCard>

        <NotchCard style={{ padding: '26px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 14px', fontSize: 16, fontWeight: 900, color: '#fff' }}>Jouw fundament</h3>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 14 }}>
            {t?.onpageScore != null && (
              <div>
                <div style={{ fontSize: 26, fontWeight: 900, color: t.onpageScore >= 85 ? '#7FD1A8' : t.onpageScore >= 65 ? '#F0C05A' : '#F08A5A', fontFamily: "'Lato', sans-serif" }}>{t.onpageScore}<span style={{ fontSize: 14, color: '#8FB5B1' }}>/100</span></div>
                <div style={{ fontSize: 11.5, color: '#8FB5B1' }}>technische score</div>
              </div>
            )}
            {lead?.authority != null && (
              <div>
                <div style={{ fontSize: 26, fontWeight: 900, color: '#fff', fontFamily: "'Lato', sans-serif" }}>{lead.authority}<span style={{ fontSize: 14, color: '#8FB5B1' }}>/100</span></div>
                <div style={{ fontSize: 11.5, color: '#8FB5B1' }}>autoriteit</div>
              </div>
            )}
            {lead?.refDomains != null && (
              <div>
                <div style={{ fontSize: 26, fontWeight: 900, color: '#fff', fontFamily: "'Lato', sans-serif" }}>{fmtNum(lead.refDomains)}</div>
                <div style={{ fontSize: 11.5, color: '#8FB5B1' }}>verwijzende websites</div>
              </div>
            )}
            {lead?.count != null && (
              <div>
                <div style={{ fontSize: 26, fontWeight: 900, color: '#fff', fontFamily: "'Lato', sans-serif" }}>{fmtNum(lead.count)}</div>
                <div style={{ fontSize: 11.5, color: '#8FB5B1' }}>termen in top-100</div>
              </div>
            )}
          </div>
          <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.6, color: '#C6DBD9' }}>{s.fundament}</p>
          {histDir && (
            <div style={{ marginTop: 16, paddingTop: 14, borderTop: '1px solid rgba(255,255,255,0.12)' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
                <span style={{ fontSize: 12, fontWeight: 700, color: '#8FB5B1' }}>Zichtbaarheid afgelopen {hist.length} maanden</span>
                <span style={{ fontSize: 13, fontWeight: 900, color: histDir.kleur }}>{histDir.label}</span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: `repeat(${hist.length}, 1fr)`, gap: 3, alignItems: 'end', height: 34 }}>
                {hist.map((m) => (
                  <div key={m.ym} title={`${m.ym}: index ${fmtNum(m.etv)}`} style={{ height: `${Math.max(8, (m.etv / maxHist) * 100)}%`, background: histDir.kleur, opacity: 0.85, borderRadius: '2px 2px 0 0' }}></div>
                ))}
              </div>
            </div>
          )}
        </NotchCard>
      </div>
      <StepBrug text={s.brug} />
      <SectieCta text="Je fundament versterken? Plan een gratis strategiegesprek" />
    </SectionShell>
  );
}

// Stap 4 — Wat laat je liggen? (gap + onbenutte termen)
function Step4Section({ data, num, tag }) {
  const s = data.steps.step4;
  const gap = data.competitorData?.gap || [];
  const unused = data.unused;
  const hero = data.serpHero;

  return (
    <SectionShell num={num} tag={tag || "Stap 4 van 5 · Gemiste kansen"} title="Wat laat je liggen?" alt>
      <p style={{ margin: '0 0 26px', fontSize: 15.5, lineHeight: 1.7, color: '#3A5250', maxWidth: 720 }}>{s.intro}</p>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(260px, 340px)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div>
          {gap.length > 0 && (
            <NotchCard style={{ padding: '4px 0 0', overflow: 'hidden' }} notch={16}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5 }}>
                <thead>
                  <tr style={{ textAlign: 'left', color: '#5A7472', fontSize: 11.5, textTransform: 'uppercase', letterSpacing: '0.8px' }}>
                    <th style={{ padding: '12px 20px' }}>Zoekterm</th>
                    <th style={{ padding: '12px 10px' }}>Volume p/m</th>
                    <th style={{ padding: '12px 10px' }}>Fase</th>
                    <th style={{ padding: '12px 20px' }}>Concurrent</th>
                  </tr>
                </thead>
                <tbody>
                  {gap.map((g, i) => (
                    <tr key={g.kw} style={{ borderTop: '1px solid #E4EDEC', background: i % 2 ? '#FAFCFB' : '#fff' }}>
                      <td style={{ padding: '11px 20px', fontWeight: 700, color: '#12302E' }}>{g.kw}</td>
                      <td style={{ padding: '11px 10px' }}>{g.vol}</td>
                      <td style={{ padding: '11px 10px', fontSize: 12, color: '#5A7472' }}>{FASE_META[g.fase]?.label || '—'}</td>
                      <td style={{ padding: '11px 20px', fontSize: 12.5, color: '#5A7472' }}>{g.compDomain.replace(/^www\./, '')} · #{g.compPos}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </NotchCard>
          )}
          {unused && (
            <p style={{ margin: '16px 0 0', fontSize: 13.5, color: '#3A5250' }}>
              Daarnaast zijn er nog <strong>{fmtNum(unused.count)} relevante zoektermen</strong> gevonden met samen {fmtNum(unused.totalVolume)} zoekopdrachten per maand waar je nu niets uithaalt.
            </p>
          )}
        </div>

        <NotchCard style={{ padding: '26px 24px', background: 'var(--bm-dark)', color: '#fff' }} notch={16}>
          <h3 style={{ margin: '0 0 10px', fontSize: 16, fontWeight: 900, color: '#fff' }}>Wat betekent dit?</h3>
          <p style={{ margin: 0, fontSize: 14.5, lineHeight: 1.65, color: '#C6DBD9' }}>{s.insight}</p>
        </NotchCard>
      </div>

      {hero && (
        <div style={{ marginTop: 30 }}>
          <h3 style={{ margin: '0 0 14px', fontSize: 16, fontWeight: 900, color: '#12302E' }}>
            Zo ziet pagina 1 eruit voor "{hero.kw}" ({hero.vol} zoekopdrachten p/m)
          </h3>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {hero.items.slice(0, 9).map((i) => (
              <span key={i.pos} style={{ fontSize: 12.5, background: '#fff', border: '1px solid #E4EDEC', borderRadius: 999, padding: '6px 14px', color: '#3A5250' }}>
                <strong style={{ color: 'var(--bm-teal-ink)' }}>#{i.pos}</strong> {i.domain.replace(/^www\./, '')}
              </span>
            ))}
            <span style={{ fontSize: 12.5, background: '#FBEAE2', borderRadius: 999, padding: '6px 14px', color: '#C4441C', fontWeight: 700 }}>Jij staat er niet tussen</span>
          </div>
        </div>
      )}
      <StepBrug text={s.brug} />
    </SectionShell>
  );
}

// Stap 5 — Wat is dat waard? (potentieel + trend + slotverhaal)
function Step5Section({ data, num, tag }) {
  const s = data.steps.step5;
  const pot = data.potentialData;
  const trend = data.trend;
  const unused = data.unused;
  const maxTrend = trend ? Math.max(...trend.months.map(m => m.volume), 1) : 1;
  const hasField = !!(pot.fmt.totalExtra && pot.fieldClicks > 0);

  const statCards = hasField ? [
    { value: pot.fmt.totalExtra, sub: 'extra bezoekers per maand', label: `Onderzochte termen naar de top-3 én de ${fmtNum(pot.fieldCount)} onbenutte termen naar positie ${pot.fieldPos}` },
    pot.fmt.totalValueMonth && { value: pot.fmt.totalValueMonth, sub: 'advertentiewaarde per maand', label: 'Wat dit verkeer zou kosten via Google Ads' },
    pot.fmt.totalValueYear && { value: pot.fmt.totalValueYear, sub: 'advertentiewaarde per jaar', label: 'De jaarlijkse waarde van deze organische zichtbaarheid' },
    unused && { value: fmtNum(unused.count), sub: `samen ${fmtNum(unused.totalVolume)} zoekopdrachten p/m`, label: 'Relevante zoektermen waar je nu nog niets uithaalt' },
  ].filter(Boolean) : [
    { value: pot.fmt.extraClicks, sub: 'extra bezoekers per maand', label: 'Bij een top-3 positie op de onderzochte zoektermen' },
    pot.fmt.adValueMonth && { value: pot.fmt.adValueMonth, sub: 'advertentiewaarde per maand', label: 'Wat dit verkeer zou kosten via Google Ads' },
    pot.fmt.adValueYear && { value: pot.fmt.adValueYear, sub: 'advertentiewaarde per jaar', label: 'De jaarlijkse waarde van deze organische posities' },
  ].filter(Boolean);

  return (
    <SectionShell num={num} tag={tag || "Stap 5 van 5 · De waarde"} title="Wat is dit waard?">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 18, marginBottom: 34 }}>
        {statCards.map(c => (
          <NotchCard key={c.label} style={{ padding: '22px 20px' }} notch={14}>
            <div style={{ fontSize: 30, fontWeight: 900, color: 'var(--bm-teal-ink)', lineHeight: 1 }}>{c.value}</div>
            <div style={{ fontSize: 12.5, color: '#8AA3A1', margin: '4px 0 10px' }}>{c.sub}</div>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: '#2E4A48', lineHeight: 1.4 }}>{c.label}</div>
          </NotchCard>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.2fr) minmax(0, 0.8fr)', gap: 'clamp(24px, 4vw, 48px)', alignItems: 'start' }} className="gs-two-col">
        <div style={{ fontSize: 15.5, lineHeight: 1.7, color: '#3A5250' }}>
          {s.paragraphs.map((p, i) => (
            <p key={i} style={{ marginTop: i === 0 ? 0 : undefined }}>{p}</p>
          ))}
        </div>

        {trend && (
          <NotchCard style={{ padding: '26px 24px' }} notch={16}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 10, marginBottom: 16 }}>
              <h3 style={{ margin: 0, fontSize: 15, fontWeight: 900 }}>Zoekvraag per maand</h3>
              {trend.peakMonths && (
                <span style={{ fontSize: 11.5, fontWeight: 700, background: '#E9F2F1', color: 'var(--bm-teal-ink)', borderRadius: 999, padding: '3px 10px', whiteSpace: 'nowrap' }}>
                  piek in {trend.peakMonths.join(' & ')}
                </span>
              )}
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', height: 110, flex: '0 0 auto', textAlign: 'right' }}>
                {[maxTrend, maxTrend / 2, 0].map((v, i) => (
                  <span key={i} style={{ fontSize: 9.5, color: '#8AA3A1', lineHeight: 1 }}>{fmtShort(v)}</span>
                ))}
              </div>
              <div style={{ flex: 1, position: 'relative' }}>
                <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
                  <div style={{ position: 'absolute', top: 0, left: 0, right: 0, borderTop: '1px dashed #E4EDEC' }}></div>
                  <div style={{ position: 'absolute', top: '50%', left: 0, right: 0, borderTop: '1px dashed #E4EDEC' }}></div>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: `repeat(${trend.months.length}, 1fr)`, gap: 4, alignItems: 'end', height: 110 }}>
                  {trend.months.map(m => (
                    <div key={`${m.year}-${m.month}`} title={`${NL_MONTHS_SHORT[m.month - 1]}: ${fmtNum(m.volume)}`} style={{
                      height: `${Math.max(4, (m.volume / maxTrend) * 100)}%`,
                      background: 'var(--bm-teal)', opacity: 0.4 + 0.6 * (m.volume / maxTrend), borderRadius: '3px 3px 0 0',
                    }}></div>
                  ))}
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: `repeat(${trend.months.length}, 1fr)`, gap: 4, marginTop: 6 }}>
                  {trend.months.map(m => (
                    <span key={`${m.year}-${m.month}`} style={{ fontSize: 9.5, textAlign: 'center', color: '#8AA3A1' }}>{NL_MONTHS_SHORT[m.month - 1]}</span>
                  ))}
                </div>
              </div>
            </div>
          </NotchCard>
        )}
      </div>

      <p style={{ marginTop: 26, fontSize: 12.5, color: '#8AA3A1' }}>
        Berekend met de gemiddelde klikverdeling per Google-positie en de gemeten zoekvolumes en klikprijzen, gekalibreerd met clickstream-metingen van echt klikgedrag in deze branche{hasField ? `; het scenario telt je onderzochte termen (naar top-3) en het nog onbenutte speelveld (naar positie ${pot.fieldPos}) bij elkaar op` : ''}: een indicatie van de orde van grootte, geen garantie.
      </p>
      <SectieCta text="Dit potentieel verzilveren? Plan een gratis strategiegesprek" />
    </SectionShell>
  );
}

function MidCta({ onCta }) {
  return (
    <section style={{ background: 'var(--bm-dark)', padding: '52px clamp(20px, 6vw, 72px)' }}>
      <div style={{ maxWidth: 1080, margin: '0 auto', display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between', gap: 24 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 22, maxWidth: 680 }}>
          <img src="images/expert-erwin.jpg" alt="Erwin Hoekstra"
            style={{ width: 96, height: 96, flex: '0 0 auto', borderRadius: '50%', objectFit: 'cover', objectPosition: 'center 20%' }} />
          <div>
            <h2 style={{ color: '#fff', fontWeight: 900, fontSize: 'clamp(20px, 2.6vw, 27px)', margin: '0 0 8px' }}>
              Benieuwd wat dit concreet voor jou betekent?
            </h2>
            <p style={{ color: '#B7D2CF', fontSize: 15, margin: 0, lineHeight: 1.6 }}>
              Plan een vrijblijvend gesprek met een van onze 40+ marketingdeskundigen en ontvang een
              échte strategie op maat. Samenwerken kan al vanaf €1.000 per maand.
            </p>
          </div>
        </div>
        <CtaButton big onClick={onCta}>Bespreek dit plan</CtaButton>
      </div>
    </section>
  );
}

function ReviewsSection() {
  const { useEffect, useRef } = React;
  const data = useReviewsData();
  const trackRef = useRef(null);
  const pausedRef = useRef(false);

  // Cap: een handvol sterke reviews overtuigt; een muur van 25 verwatert en
  // vergroot de afstand tot de eind-CTA.
  const reviews = (data?.reviews || REVIEWS_FALLBACK).slice(0, 9);

  function slide(dir) {
    const el = trackRef.current;
    if (!el) return;
    const step = (el.children[0]?.offsetWidth || 320) + 22;
    const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 10;
    if (dir > 0 && atEnd) el.scrollTo({ left: 0, behavior: 'smooth' });
    else el.scrollBy({ left: dir * step, behavior: 'smooth' });
  }

  // Rustig automatisch doorschuiven; pauzeert zolang de muis erop staat
  useEffect(() => {
    const iv = setInterval(() => { if (!pausedRef.current) slide(1); }, 6000);
    return () => clearInterval(iv);
  }, [reviews.length]);

  const arrowStyle = {
    width: 42, height: 42, borderRadius: '50%', border: '1.5px solid #C9DAD8', background: '#fff',
    color: 'var(--bm-teal-ink)', fontSize: 18, fontWeight: 900, cursor: 'pointer',
    display: 'grid', placeItems: 'center', boxShadow: '0 4px 12px rgba(6,40,38,0.10)', flex: '0 0 auto',
  };

  return (
    <section style={{ background: 'var(--bm-mist)', padding: '58px clamp(20px, 6vw, 72px)' }}>
      <div style={{ maxWidth: 1080, margin: '0 auto' }}>
        <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between', gap: 16, marginBottom: 28 }}>
          <div>
            <SectionTag>Klantervaringen</SectionTag>
            <h2 style={{ fontWeight: 900, fontSize: 'clamp(22px, 2.8vw, 30px)', color: '#12302E', margin: '14px 0 0' }}>
              Dit zeggen ondernemers over Brandmerck
            </h2>
          </div>
          <ReviewBadge />
        </div>

        {/* Slider: swipe/scroll-snap + pijlen, alleen positieve reviews */}
        <style>{`.gs-reviews-track { scrollbar-width: none; } .gs-reviews-track::-webkit-scrollbar { display: none; }`}</style>
        <div ref={trackRef} className="gs-reviews-track"
          onMouseEnter={() => { pausedRef.current = true; }}
          onMouseLeave={() => { pausedRef.current = false; }}
          style={{ display: 'flex', gap: 22, overflowX: 'auto', scrollSnapType: 'x mandatory', padding: '4px 2px 10px' }}>
          {reviews.map((r, i) => (
            <NotchCard key={i} style={{
              padding: '26px 24px', display: 'flex', flexDirection: 'column', gap: 14,
              flex: '0 0 auto', width: 'min(320px, 82vw)', scrollSnapAlign: 'start',
            }} notch={14}>
              <div style={{ color: '#F4B400', fontSize: 15, letterSpacing: 2 }}>{'★'.repeat(Math.max(1, Math.round(r.rating5 || 5)))}</div>
              <p style={{
                margin: 0, fontSize: 14.5, lineHeight: 1.65, color: '#3A5250', flex: 1,
                display: '-webkit-box', WebkitLineClamp: 7, WebkitBoxOrient: 'vertical', overflow: 'hidden',
              }}>“{r.text}”</p>
              <div>
                <div style={{ fontWeight: 900, fontSize: 14, color: '#12302E' }}>{r.name}</div>
                <div style={{ fontSize: 12.5, color: '#8AA3A1' }}>{r.source === 'feedbackcompany' ? 'Review via The Feedback Company' : 'Review via Google'}</div>
              </div>
            </NotchCard>
          ))}
        </div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 14 }}>
          <p style={{ margin: 0, fontSize: 13, color: '#8AA3A1' }}>
            Alle beoordelingen zijn afkomstig van klanten via Google en The Feedback Company.
          </p>
          <div style={{ display: 'flex', gap: 10 }}>
            <button type="button" aria-label="Vorige reviews" onClick={() => slide(-1)} style={arrowStyle}>‹</button>
            <button type="button" aria-label="Volgende reviews" onClick={() => slide(1)} style={arrowStyle}>›</button>
          </div>
        </div>
      </div>
    </section>
  );
}

function TeamBand() {
  return (
    <section style={{ position: 'relative', minHeight: 340, display: 'flex', alignItems: 'flex-end', overflow: 'hidden' }}>
      <img src="images/teamfoto.jpg" alt="Het team van Brandmerck"
        style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'center 55%' }} />
      <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(9,43,41,0.15) 30%, rgba(9,43,41,0.85) 100%)' }}></div>
      <div style={{ position: 'relative', width: '100%', maxWidth: 1080, margin: '0 auto', padding: '120px clamp(20px, 6vw, 72px) 34px', display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16 }}>
        <div>
          <SectionTag>Het team</SectionTag>
          <h2 style={{ color: '#fff', fontWeight: 900, fontSize: 'clamp(20px, 2.6vw, 27px)', margin: '12px 0 0', textShadow: '0 2px 12px rgba(0,0,0,0.4)' }}>
            40+ deskundigen, één doel: jouw groei
          </h2>
        </div>
      </div>
    </section>
  );
}

function ChannelsSection({ data, num }) {
  return (
    <SectionShell num={num} tag="Kanaalstrategie" title="Per kanaal: zo pakken we het aan">
      <div style={{ display: 'grid', gap: 22 }}>
        {data.channels.map((c, i) => {
          const expert = EXPERTS[c.key] || EXPERTS.sea;
          return (
            <NotchCard key={c.key} style={{ padding: '30px 30px 26px' }} notch={16}>
              <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 12, marginBottom: 12 }}>
                <span style={{ fontWeight: 900, fontSize: 22, color: 'var(--bm-teal)', fontFamily: "'Lato', sans-serif" }}>{String(i + 1).padStart(2, '0')}</span>
                <h3 style={{ margin: 0, fontSize: 19, fontWeight: 900 }}>{c.name}</h3>
                <span style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: '0.8px', textTransform: 'uppercase', color: 'var(--bm-cta-1)', border: '1.5px solid var(--bm-cta-1)', borderRadius: 999, padding: '4px 12px' }}>{c.tag}</span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: 'clamp(18px, 3vw, 40px)' }} className="gs-two-col">
                <p style={{ margin: 0, fontSize: 15, lineHeight: 1.65, color: '#3A5250' }}>{c.why}</p>
                <div>
                  <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'grid', gap: 8, fontSize: 14.5, color: '#2E4A48' }}>
                    {c.plan.map(p => <li key={p} style={{ display: 'flex', gap: 0 }}><Check /><span>{p}</span></li>)}
                  </ul>
                  <div style={{ marginTop: 14, fontSize: 13, fontWeight: 700, color: '#5A7472' }}>› {c.budget}</div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 16, paddingTop: 14, borderTop: '1px solid #E4EDEC' }}>
                    <img src={expert.photo} alt={expert.name}
                      style={{ width: 48, height: 48, flex: '0 0 auto', borderRadius: '50%', objectFit: 'cover', objectPosition: 'center 20%' }} />
                    <div>
                      <div style={{ fontWeight: 900, fontSize: 13.5, color: '#12302E' }}>{expert.name}</div>
                      <div style={{ fontSize: 12.5, color: '#8AA3A1' }}>{expert.role}</div>
                    </div>
                  </div>
                </div>
              </div>
            </NotchCard>
          );
        })}
      </div>
    </SectionShell>
  );
}

function ContactSection({ lead, scanId, formRef }) {
  const { useState } = React;
  const [name, setName] = useState('');
  const [phone, setPhone] = useState('');
  const [email, setEmail] = useState(lead.email || '');
  const [sent, setSent] = useState(false);
  const [error, setError] = useState('');

  async function submit(e) {
    e.preventDefault();
    if (!name.trim()) { setError('Vul je naam in'); return; }
    if (!/^\S+@\S+\.\S+$/.test(email.trim())) { setError('Vul een geldig e-mailadres in'); return; }
    setError('');
    try {
      const res = await fetch('/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ scanId, name: name.trim(), phone: phone.trim(), email: email.trim() }),
      });
      if (res.ok) gsTrack('contact_requested', { product: 'groeiscan', scan_id: scanId }, scanId);
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setError(d.error || 'Versturen mislukt. Probeer het opnieuw.');
        return;
      }
      setSent(true);
    } catch (err) {
      setError('Versturen mislukt. Controleer je verbinding.');
    }
  }

  return (
    <section id="gs-contact" ref={formRef} style={{ background: 'var(--bm-dark)', padding: '64px clamp(20px, 6vw, 72px) 80px' }}>
      <div style={{ maxWidth: 1080, margin: '0 auto', display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(320px, 420px)', gap: 'clamp(28px, 5vw, 64px)', alignItems: 'center' }} className="gs-two-col">
        <div>
          <SectionTag>Volgende stap</SectionTag>
          <h2 style={{ color: '#fff', fontWeight: 900, fontSize: 'clamp(24px, 3vw, 32px)', margin: '16px 0 14px' }}>
            Van indicatie naar échte strategie
          </h2>
          <p style={{ color: '#C6DBD9', fontSize: 15.5, lineHeight: 1.7, margin: '0 0 18px' }}>
            Deze scan geeft een eerste richting. Een strateeg van Brandmerck vertaalt het naar een
            concreet plan: doelen, budgetverdeling en een aanpak die elke maand beter wordt.
          </p>
          <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'grid', gap: 10, color: '#E4F0EF', fontSize: 15 }}>
            <li><Check />Vrijblijvend gesprek van 30 minuten</li>
            <li><Check />Strategie op maat, geen losse acties</li>
            <li><Check />Volledige marketingafdeling vanaf €1.000 per maand</li>
          </ul>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginTop: 26 }}>
            <img src="images/expert-erwin.jpg" alt="Erwin Hoekstra"
              style={{ width: 64, height: 64, flex: '0 0 auto', borderRadius: '50%', objectFit: 'cover', objectPosition: 'center 20%' }} />
            <div>
              <div style={{ color: '#fff', fontWeight: 900, fontSize: 15 }}>Erwin Hoekstra</div>
              <div style={{ color: '#8FB5B1', fontSize: 13.5 }}>Marketingstrateeg &amp; co-founder</div>
            </div>
          </div>
        </div>
        <NotchCard style={{ padding: '32px 30px 28px' }}>
          {sent ? (
            <div style={{ textAlign: 'center', padding: '24px 0' }}>
              <div style={{ width: 54, height: 54, borderRadius: '50%', background: 'var(--bm-teal)', color: '#fff', display: 'grid', placeItems: 'center', fontSize: 26, margin: '0 auto 14px' }}>✓</div>
              <h3 style={{ margin: '0 0 8px', fontSize: 20, fontWeight: 900 }}>Aanvraag ontvangen</h3>
              <p style={{ margin: 0, color: '#5A7472', fontSize: 14.5, lineHeight: 1.6 }}>
                Een strateeg neemt binnen één werkdag contact met je op om het gesprek in te plannen.
              </p>
            </div>
          ) : (
            <div>
              <h3 style={{ margin: '0 0 4px', fontSize: 20, fontWeight: 900 }}>Plan je gesprek</h3>
              <p style={{ margin: '0 0 18px', color: '#5A7472', fontSize: 13.5 }}>Gratis en vrijblijvend</p>
              <form onSubmit={submit} style={{ display: 'grid', gap: 13 }}>
                <input value={name} onChange={e => setName(e.target.value)} placeholder="Je naam" className="gs-input" />
                <input value={phone} onChange={e => setPhone(e.target.value)} placeholder="Telefoonnummer (optioneel)" className="gs-input" />
                <input value={email} onChange={e => setEmail(e.target.value)} placeholder="E-mailadres" type="email" className="gs-input" />
                {error && <div style={{ color: '#C4441C', fontSize: 13, fontWeight: 700 }}>{error}</div>}
                <CtaButton type="submit" big style={{ width: '100%' }}>Bespreek met een strateeg</CtaButton>
              </form>
            </div>
          )}
        </NotchCard>
      </div>
    </section>
  );
}

function ResultPage({ lead, answers, data, scanId, benchView, onRestart, onResearchDone, onEmail }) {
  const formRef = React.useRef(null);
  function toForm() {
    const el = formRef.current;
    if (el) window.scrollTo({ top: el.offsetTop - 10, behavior: 'smooth' });
  }
  // Sectie 03 is het onderzoeksformulier totdat de research-data binnen is.
  const hasResearch = !!data.research;
  // v8-rapporten hebben de stapsgewijze opbouw (steps); oudere rapporten
  // renderen de losse legacy-secties.
  const hasSteps = hasResearch && !!data.steps;
  const hasAds = hasSteps && !!data.steps.ads;
  // v11-rapporten groeperen de zoektermen per dienst (step1.diensten) en hebben
  // een conversie-gedreven ads-slot; v10-rapporten renderen de oude secties.
  const isV11 = hasAds && Array.isArray(data.steps.step1?.diensten);
  const stepDefs = hasSteps ? (isV11 ? [
    // v11: SEO-deel (4 secties) + Google Ads-deel (2 secties)
    { C: KeywordsDienstSection, props: { tag: 'SEO · Zoektermen & posities' }, ok: !!(data.keywords?.length && data.steps.step1) },
    { C: CompetitionSection, props: { tag: 'SEO · Concurrentie' }, ok: !!(data.competitorData?.list?.length && data.steps.step2) },
    { C: Step3Section, props: { tag: 'SEO · Jouw fundament' }, ok: !!data.steps.step3 },
    { C: Step5Section, props: { tag: 'SEO · De waarde' }, ok: !!(data.potentialData && data.steps.step5) },
    { C: AdsStructureSection, props: {}, ok: !!data.steps.ads?.campagnes?.length },
    { C: AdsConversieSection, props: {}, ok: !!(data.adsPlan || data.googleAds?.length) },
  ] : hasAds ? [
    // v10: SEO-deel (6 secties) + Google Ads-deel (2 secties)
    { C: Step1Section, props: { tag: 'SEO · Jouw zoekwoorden' }, ok: !!(data.keywords?.length && data.steps.step1) },
    { C: RankingSection, props: { tag: 'SEO · Wie scoort waar' }, ok: !!(data.competitorData?.list?.length && data.keywords?.length && data.steps.step2) },
    { C: Step2Section, props: { tag: 'SEO · Concurrentieonderzoek', title: 'Diepgaand concurrentieonderzoek', deep: true }, ok: !!(data.competitorData?.list?.length && data.steps.step2) },
    { C: Step3Section, props: { tag: 'SEO · Jouw fundament' }, ok: !!data.steps.step3 },
    { C: Step4Section, props: { tag: 'SEO · Gemiste kansen' }, ok: !!(data.steps.step4 && (data.competitorData?.gap?.length || data.unused)) },
    { C: Step5Section, props: { tag: 'SEO · De waarde' }, ok: !!(data.potentialData && data.steps.step5) },
    { C: AdsStructureSection, props: {}, ok: !!data.steps.ads?.campagnes?.length },
    { C: AdsBudgetSection, props: {}, ok: !!(data.adsPlan && data.steps.ads) },
  ] : [
    { C: Step1Section, props: {}, ok: !!(data.keywords?.length && data.steps.step1) },
    { C: Step2Section, props: {}, ok: !!(data.competitorData?.list?.length && data.steps.step2) },
    { C: Step3Section, props: {}, ok: !!data.steps.step3 },
    { C: Step4Section, props: {}, ok: !!(data.steps.step4 && (data.competitorData?.gap?.length || data.unused)) },
    { C: Step5Section, props: {}, ok: !!(data.potentialData && data.steps.step5) },
  ]).filter((d) => d.ok) : [];
  // Dynamische sectienummering: secties zonder data verdwijnen zonder gat
  const hasComp = !hasSteps && hasResearch && !!(data.competitorData && data.competitorData.list && data.competitorData.list.length && data.competitors);
  const hasTech = !hasSteps && hasResearch && !!data.techData;
  const hasPot = !hasSteps && hasResearch && !!(data.potentialData && data.investment);
  const hasSocial = hasResearch && !!(data.socialData && data.social);
  let n = hasSteps ? 2 + stepDefs.length : 3;
  const techNum = hasTech ? ++n : null;
  const compNum = hasComp ? ++n : null;
  const potNum = hasPot ? ++n : null;
  const socNum = hasSocial ? ++n : null;
  const chanNum = ++n;
  const pad = (x) => String(x).padStart(2, '0');

  return (
    <div data-screen-label="Resultaat / Groeiplan" style={{ background: '#fff' }}>
      <ResultHeader lead={lead} data={data} />
      <BenchmarkSection answers={answers} benchView={benchView} data={data} num="01" />
      <StrategySection data={data} num="02" />
      <MidCta onCta={toForm} />
      {!hasResearch && <ResearchSection data={data} scanId={scanId} onResearchDone={onResearchDone} num="03" leadEmail={lead?.email || ''} onEmail={onEmail} />}
      {hasSteps
        ? stepDefs.map((d, i) => <d.C key={i} data={data} num={pad(3 + i)} {...d.props} />)
        : hasResearch && <DataSection data={data} num="03" />}
      {hasTech && <TechSection data={data} num={pad(techNum)} onCta={toForm} />}
      {hasComp && <CompetitorsSection data={data} num={pad(compNum)} />}
      {hasPot && <PotentialSection data={data} num={pad(potNum)} />}
      {hasSocial && <SocialSection data={data} num={pad(socNum)} />}
      <ReviewsSection />
      <ChannelsSection data={data} num={pad(chanNum)} />
      <TeamBand />
      <ContactSection lead={lead} scanId={scanId} formRef={formRef} />
      <footer style={{ background: 'var(--bm-darker)', padding: '20px clamp(20px, 6vw, 72px)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
        <span style={{ color: '#6E8F8C', fontSize: 12.5 }}>© Brandmerck · Online marketingbureau in Friesland</span>
        <button onClick={onRestart} style={{ background: 'none', border: 'none', color: '#6E8F8C', fontSize: 12.5, cursor: 'pointer', textDecoration: 'underline', fontFamily: "'Lato', sans-serif" }}>
          Scan opnieuw doen
        </button>
      </footer>
    </div>
  );
}

Object.assign(window, { ResultPage });
