/* WP Site Beam — Content SEO (ongoing monitoring, auto-fixes, competitors)
   This is the SEMRush-style counterpart to the one-time Brand Asset Extractor.
   Scopes: per-site SEO dashboard, keyword rank tracking, content recommendations,
           auto-fix queue (pushes to WordPress), backlink feed, competitor intel.
*/

function ContentSEO() {
  const { useState, useEffect } = React;
  const [site, setSite] = useState('acme.co');
  const [sub, setSub] = useState('overview');

  // Scanner → Content SEO handoff (2026-05-18 bugfix)
  // Scanner writes 'wpsb-seo-target' to sessionStorage on "Switch to ongoing SEO".
  // Before this fix, no receiver read it — panel always showed acme.co demo data.
  // Now we read on mount, populate the site selector, and store full handoff
  // for downstream sub-panels (Pages, Overview, etc.) to use.
  const [scannerHandoff, setScannerHandoff] = useState(null);
  useEffect(() => {
    try {
      const raw = sessionStorage.getItem('wpsb-seo-target');
      if (!raw) return;
      const h = JSON.parse(raw);
      if (!h || !h.site) return;
      setScannerHandoff(h);
      setSite(h.site);
      const pageCount = Array.isArray(h.pages) ? h.pages.length : 0;
      const seoCount  = Array.isArray(h.perPageSeo) ? h.perPageSeo.length : 0;
      window.wpsbToast?.(`Loaded scan data: ${h.site} — ${pageCount} pages, ${seoCount} with SEO metadata`, 'ok');
    } catch(e) {
      if (typeof console !== 'undefined') console.warn('[ContentSEO] handoff read failed:', e.message);
    }
  }, []);

  // Build site list — scanner site (if any) wins, then defaults
  const sites = scannerHandoff?.site
    ? [scannerHandoff.site, 'acme.co','bramble.com','lincoln.gov'].filter((v,i,a) => a.indexOf(v) === i)
    : ['acme.co','bramble.com','lincoln.gov'];

  const tabs = [
    { id:'overview',     label:'Overview' },
    { id:'keywords',     label:'Keywords' },
    { id:'pages',        label:'Pages & Posts' },
    { id:'content',      label:'Content Recs' },
    { id:'fixes',        label:'Auto-Fix Queue' },
    { id:'backlinks',    label:'Backlinks' },
    { id:'competitors',  label:'Competitors' },
    { id:'schedule',     label:'Schedule' },
  ];

  return (
    <div>
      <PageHead crumb="Operations" title="Content SEO"
        sub="Ongoing SEO & content monitoring. Recurring scans, auto-fixes pushed to WordPress, content recommendations, backlinks, and SEMRush-style competitor analysis."
        actions={<>
          <label className="field" style={{ margin:0, minWidth:180 }}>
            <span className="sr-only">Site</span>
            <select value={site} onChange={e => setSite(e.target.value)} aria-label="Select site to monitor">
              {sites.map(s => <option key={s}>{s}</option>)}
            </select>
          </label>
          <button className="btn btn-ghost btn-sm" onClick={() => window.WPSBD?.switchTab?.('content')} title="Manage pages, posts, and media in Site Content">
            <Icon name="content" size={13}/>Site Content →
          </button>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Recurring scan queued — next run in 6 days', 'ok')}>
            <Icon name="scanner" size={13}/>Scan now
          </button>
          <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast('Auto-fix pushed to WordPress — 7 changes applied', 'ok')}>
            <Icon name="spark" size={13}/>Auto-fix all (7)
          </button>
        </>}
      />

      {/* Sub tabs */}
      <div className="sub-tabs" role="tablist" aria-label="Content SEO sections">
        {tabs.map(t => (
          <button key={t.id} role="tab" aria-selected={sub===t.id} tabIndex={sub===t.id?0:-1}
                  className={'sub-tab' + (sub===t.id?' active':'')} onClick={() => setSub(t.id)}>{t.label}</button>
        ))}
      </div>

      <div style={{ marginTop:16 }}>
        {sub === 'overview'    && <SeoOverview site={site}/>}
        {sub === 'keywords'    && <SeoKeywords/>}
        {sub === 'pages'       && <SeoPagesMonitor/>}
        {sub === 'content'     && <SeoContentRecs/>}
        {sub === 'fixes'       && <SeoAutoFix/>}
        {sub === 'backlinks'   && <SeoBacklinks/>}
        {sub === 'competitors' && <SeoCompetitors/>}
        {sub === 'schedule'    && <SeoSchedule/>}
      </div>
    </div>
  );
}

/* ── OVERVIEW ─────────────────────────────────────────────────── */
function SeoOverview({ site }) {
  return (
    <>
      {/* 2026-05-18 v2 per Jordan: WP integration banner + Monitoring status
          now side-by-side (50/50) instead of vertically stacked. Frees vertical
          real estate and pairs the two "what's connected + when does it scan"
          pieces visually. */}
      <div className="grid grid-2" style={{ marginBottom:14 }}>
        <div className="card" style={{ background:'var(--beam-dim)', border:'1px solid var(--beam-dim)' }}>
          <div className="card-body" style={{ display:'flex', gap:14, alignItems:'center', flexWrap:'wrap' }}>
            <div style={{ width:36, height:36, borderRadius:8, background:'var(--beam)', color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', fontWeight:800, flexShrink:0 }}>W</div>
            <div style={{ flex:1, minWidth:140 }}>
              <div style={{ fontWeight:700, fontSize:'.88rem' }}>WordPress · Yoast SEO · RankMath</div>
              <div style={{ fontSize:'.7rem', color:'var(--muted)', marginTop:2 }}>Auto-fixes push via WPSB Beam plugin.</div>
            </div>
            <span className="tag ok">CONNECTED</span>
            <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Opening WP admin in new tab', 'info')} style={{ flexShrink:0 }}>
              Open WP admin →
            </button>
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h2 className="card-title">Monitoring · {site}</h2><span className="tag ok">ACTIVE</span></div>
          <div className="card-body" style={{ display:'flex', gap:14, flexWrap:'wrap', fontSize:'.78rem' }}>
            <Kv k="Last scan" v="2 days ago"/>
            <Kv k="Next scan" v="In 5 days"/>
            <Kv k="Auto-fix" v={<span style={{ color:'var(--green)' }}>Low-risk on</span>}/>
            <Kv k="Changes/mo" v="27 auto · 4 manual"/>
          </div>
        </div>
      </div>

      {/* KPIs */}
      <div className="grid grid-4">
        <div className="stat"><div className="stat-lbl">Avg SEO score</div><div className="stat-val ok">84</div><div style={{ fontSize:'.66rem', color:'var(--green)', marginTop:2 }}>▲ 6 vs last scan</div></div>
        <div className="stat"><div className="stat-lbl">Keywords tracked</div><div className="stat-val">142</div><div style={{ fontSize:'.66rem', color:'var(--dim)', marginTop:2 }}>38 in top 10</div></div>
        <div className="stat"><div className="stat-lbl">Issues open</div><div className="stat-val warn">7</div><div style={{ fontSize:'.66rem', color:'var(--warn)', marginTop:2 }}>3 high priority</div></div>
        <div className="stat"><div className="stat-lbl">Organic sessions (30d)</div><div className="stat-val">24.8k</div><div style={{ fontSize:'.66rem', color:'var(--green)', marginTop:2 }}>▲ 12% MoM</div></div>
      </div>

      {/* Trend + issues split */}
      <div className="grid grid-2" style={{ marginTop:16 }}>
        <div className="card">
          <div className="card-head">
            <h2 className="card-title">Organic traffic · last 30 days</h2>
            <span className="tag beam">GSC + GA4</span>
          </div>
          {/* 2026-05-18: overflow:hidden so wide MiniAreaChart SVGs clip to the
              card rather than bleeding outside on narrow viewports. */}
          <div className="card-body" style={{ overflow:'hidden', maxWidth:'100%' }}>
            <MiniAreaChart/>
          </div>
        </div>
        <div className="card">
          <div className="card-head">
            <h2 className="card-title">Issues overview</h2>
            <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Opening Auto-Fix queue', 'info')}>View queue →</button>
          </div>
          <div className="card-body" style={{ padding:0 }}>
            {[
              ['Missing meta descriptions',   3, 'high'],
              ['Thin content (<300 words)',   2, 'high'],
              ['Broken internal links',       1, 'med'],
              ['Missing alt text (14 imgs)',  1, 'med'],
              ['No canonical tag',            1, 'low'],
            ].map(([lbl, n, pri], i, a) => (
              <div key={lbl} style={{ display:'flex', alignItems:'center', gap:12, padding:'12px 18px', borderBottom: i<a.length-1 ? '1px solid var(--border)' : 'none' }}>
                <span className={`tag ${pri==='high'?'bad':pri==='med'?'warn':''}`}>{pri.toUpperCase()}</span>
                <div style={{ flex:1, fontSize:'.86rem' }}>{lbl}</div>
                <span className="mono" style={{ fontSize:'.8rem', color:'var(--dim)' }}>{n} {n===1?'page':'pages'}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

/* ── KEYWORDS ─────────────────────────────────────────────────── */
function SeoKeywords() {
  const { useState } = React;
  const [q, setQ] = useState('');
  const rows = [
    { kw:'accounting software small business', pos:4,  prev:6,  vol:14500, diff:68, url:'/',            intent:'commercial' },
    { kw:'ai bookkeeping tool',                 pos:2,  prev:3,  vol:3400,  diff:54, url:'/features/ai', intent:'commercial' },
    { kw:'close the books 3x faster',           pos:1,  prev:1,  vol:480,   diff:22, url:'/',            intent:'branded'    },
    { kw:'quickbooks alternative 2026',         pos:12, prev:8,  vol:8900,  diff:72, url:'/compare',     intent:'comparison' },
    { kw:'cfo dashboard software',              pos:18, prev:24, vol:1900,  diff:61, url:'/features',    intent:'informational' },
    { kw:'multi entity consolidation',          pos:7,  prev:9,  vol:2100,  diff:55, url:'/features/consolidation', intent:'commercial' },
    { kw:'expense reconciliation automation',   pos:5,  prev:4,  vol:1200,  diff:48, url:'/features',    intent:'commercial' },
    { kw:'real time cashflow dashboard',        pos:22, prev:28, vol:720,   diff:42, url:'/features/cashflow', intent:'informational' },
  ];
  const filtered = rows.filter(r => r.kw.toLowerCase().includes(q.toLowerCase()));

  function intentTone(i) { return i==='commercial'?'beam':i==='branded'?'ok':i==='comparison'?'warn':''; }
  function delta(pos, prev) {
    const d = prev - pos;
    if (d===0) return <span style={{ color:'var(--dim)' }}>—</span>;
    return <span style={{ color: d>0 ? 'var(--green)' : 'var(--rose)' }}>{d>0?'▲':'▼'} {Math.abs(d)}</span>;
  }

  return (
    <div className="card">
      <div className="card-head">
        <h2 className="card-title">Keyword rank tracking · {filtered.length} of {rows.length}</h2>
        <div style={{ display:'flex', gap:6, alignItems:'center' }}>
          <input className="input-inline" placeholder="Filter keywords…" value={q} onChange={e => setQ(e.target.value)} style={{ minWidth:180, fontSize:'.78rem' }}/>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Added 12 suggested keywords from Brain', 'ok')}>
            <Icon name="plus" size={12}/>Add keywords
          </button>
          <button className="btn btn-ghost btn-sm" onClick={() => {
            const header = 'keyword,position,prev,volume,difficulty,url,intent\n';
            const body = rows.map(r => `"${r.kw}",${r.pos},${r.prev},${r.vol},${r.diff},"${r.url}","${r.intent}"`).join('\n');
            window.wpsbDownload('keywords.csv', header + body, 'text/csv');
          }}><Icon name="download" size={12}/>CSV</button>
        </div>
      </div>
      <div className="card-body" style={{ padding:0, overflowX:'auto' }}>
        <table className="table" style={{ minWidth:720 }}>
          <thead>
            <tr>
              <th scope="col">Keyword</th>
              <th scope="col" style={{ textAlign:'right' }}>Pos</th>
              <th scope="col" style={{ textAlign:'right' }}>Δ</th>
              <th scope="col" style={{ textAlign:'right' }}>Volume</th>
              <th scope="col" style={{ textAlign:'right' }}>KD</th>
              <th scope="col">Landing URL</th>
              <th scope="col">Intent</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(r => (
              <tr key={r.kw}>
                <td style={{ fontWeight:500 }}>{r.kw}</td>
                <td className="mono" style={{ textAlign:'right', fontWeight:700, color: r.pos<=3 ? 'var(--green)' : r.pos<=10 ? 'var(--warn)' : 'var(--dim)' }}>{r.pos}</td>
                <td className="mono" style={{ textAlign:'right', fontSize:'.76rem' }}>{delta(r.pos, r.prev)}</td>
                <td className="mono" style={{ textAlign:'right', fontSize:'.76rem', color:'var(--dim)' }}>{r.vol.toLocaleString()}</td>
                <td className="mono" style={{ textAlign:'right', fontSize:'.76rem', color: r.diff>60?'var(--rose)':r.diff>40?'var(--warn)':'var(--green)' }}>{r.diff}</td>
                <td className="mono" style={{ fontSize:'.76rem', color:'var(--beam)' }}>{r.url}</td>
                <td><span className={`tag ${intentTone(r.intent)}`}>{r.intent.toUpperCase()}</span></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ── PAGES MONITOR ────────────────────────────────────────────── */
function SeoPagesMonitor() {
  const pages = [
    { url:'/',            score:94, traffic:8420, issues:0, status:'healthy'     },
    { url:'/features',    score:91, traffic:4210, issues:1, status:'healthy'     },
    { url:'/blog/ai-in-2026', score:96, traffic:3800, issues:0, status:'healthy' },
    { url:'/pricing',     score:62, traffic:2140, issues:3, status:'needs-work'  },
    { url:'/about',       score:88, traffic:1620, issues:1, status:'healthy'     },
    { url:'/features/ai', score:32, traffic:240,  issues:6, status:'critical'    },
    { url:'/contact',     score:78, traffic:980,  issues:1, status:'healthy'     },
  ];
  const statusTone = s => s==='critical'?'bad':s==='needs-work'?'warn':'ok';
  return (
    <div className="card">
      <div className="card-head">
        <h2 className="card-title">Pages & Posts · {pages.length} tracked</h2>
        <div style={{ display:'flex', gap:6 }}>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Re-scanned all pages — 3 new issues found', 'info')}>
            <Icon name="scanner" size={12}/>Re-scan
          </button>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Pushed bulk fixes to WP — 7 pages updated', 'ok')}>
            <Icon name="spark" size={12}/>Auto-fix all
          </button>
        </div>
      </div>
      <div className="card-body" style={{ padding:0, overflowX:'auto' }}>
        <table className="table" style={{ minWidth:640 }}>
          <thead><tr>
            <th scope="col">URL</th>
            <th scope="col" style={{ textAlign:'right' }}>Score</th>
            <th scope="col" style={{ textAlign:'right' }}>30d sessions</th>
            <th scope="col" style={{ textAlign:'right' }}>Issues</th>
            <th scope="col">Status</th>
            <th scope="col"></th>
          </tr></thead>
          <tbody>
            {pages.map(p => (
              <tr key={p.url}>
                <td className="mono" style={{ fontSize:'.82rem' }}>{p.url}</td>
                <td className="mono" style={{ textAlign:'right', fontWeight:700, color: p.score>=80?'var(--green)':p.score>=60?'var(--warn)':'var(--rose)' }}>{p.score}</td>
                <td className="mono" style={{ textAlign:'right' }}>{p.traffic.toLocaleString()}</td>
                <td className="mono" style={{ textAlign:'right', color: p.issues>0 ? 'var(--warn)' : 'var(--dim)' }}>{p.issues}</td>
                <td><span className={`tag ${statusTone(p.status)}`}>{p.status.toUpperCase()}</span></td>
                <td style={{ textAlign:'right' }}>
                  <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`Opening ${p.url} in WP editor`, 'info')}>Edit in WP</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ── CONTENT RECOMMENDATIONS ──────────────────────────────────── */
function SeoContentRecs() {
  const recs = [
    { url:'/features/ai', kind:'Rewrite',     why:'Page is too short (84 words) — add 300+ words covering "AI reconciliation" intent.', eff:'med'  },
    { url:'/pricing',     kind:'Meta desc',   why:'Missing meta description — generate one based on current page content (155 chars).', eff:'low' },
    { url:'/about',       kind:'Internal link', why:'No links to /features — add 2-3 contextual internal links.',                       eff:'low'  },
    { url:'/blog',        kind:'New post',    why:'Keyword gap: "cfo dashboard best practices" (1.9k/mo, KD 42) — no covering post.',   eff:'high' },
    { url:'/features',    kind:'Schema',      why:'Add FAQ schema — 4 Q&A blocks detected in content.',                                  eff:'low'  },
  ];
  const effTone = e => e==='high'?'bad':e==='med'?'warn':'';
  return (
    <div className="card">
      <div className="card-head"><h2 className="card-title">Content recommendations</h2><span className="tag beam">AI · WPSB BRAIN</span></div>
      <div className="card-body" style={{ padding:0 }}>
        {recs.map((r, i) => (
          <div key={i} style={{ padding:'14px 18px', borderBottom: i<recs.length-1 ? '1px solid var(--border)' : 'none', display:'flex', gap:12, alignItems:'flex-start' }}>
            <div style={{ width:30, height:30, borderRadius:6, background:'var(--beam-dim)', color:'var(--beam)', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
              <Icon name="spark" size={14}/>
            </div>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ display:'flex', gap:8, alignItems:'center', marginBottom:3 }}>
                <span className="tag">{r.kind.toUpperCase()}</span>
                <span className="mono" style={{ fontSize:'.76rem', color:'var(--beam)' }}>{r.url}</span>
              </div>
              <div style={{ fontSize:'.86rem', color:'var(--text-2)', lineHeight:1.5 }}>{r.why}</div>
            </div>
            <span className={`tag ${effTone(r.eff)}`}>{r.eff.toUpperCase()}</span>
            <div style={{ display:'flex', gap:6, flexDirection:'column' }}>
              <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast(`AI-drafted fix queued for ${r.url}`, 'ok')}>Draft with AI</button>
              <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Dismissed', 'info')}>Dismiss</button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ── AUTO-FIX QUEUE ───────────────────────────────────────────── */
function SeoAutoFix() {
  const { useState } = React;
  const [autoApply, setAutoApply] = useState(true);
  const queue = [
    { id:1, kind:'Meta description',  target:'/pricing',       diff:'+ "Simple pricing for teams 1–5,000."', risk:'low',    status:'ready'     },
    { id:2, kind:'Alt text (14 imgs)',target:'multiple',       diff:'+ AI-generated alt text on 14 imgs',    risk:'low',    status:'ready'     },
    { id:3, kind:'H1 tag',            target:'/features/ai',   diff:'+ <h1>AI-Powered Features</h1>',        risk:'low',    status:'ready'     },
    { id:4, kind:'Canonical URL',     target:'/features/ai',   diff:'+ <link rel="canonical" href="…">',     risk:'low',    status:'applied'   },
    { id:5, kind:'Rewrite thin content', target:'/features/ai',diff:'+ 420 words AI-drafted',                 risk:'high',   status:'pending-approval' },
    { id:6, kind:'301 redirect',      target:'/old-pricing → /pricing', diff:'+ redirect rule',                 risk:'med',    status:'ready'     },
    { id:7, kind:'Schema FAQ',        target:'/features',      diff:'+ FAQPage JSON-LD block',                risk:'low',    status:'ready'     },
  ];
  const riskTone = r => r==='high'?'bad':r==='med'?'warn':'ok';
  const statTone = s => s==='applied'?'ok':s==='pending-approval'?'warn':'beam';

  return (
    <>
      <div className="card" style={{ marginBottom:14 }}>
        <div className="card-body" style={{ display:'flex', gap:14, alignItems:'center', flexWrap:'wrap' }}>
          <label className="opt-check" style={{ margin:0 }}>
            <input type="checkbox" checked={autoApply} onChange={e => setAutoApply(e.target.checked)}/>
            <span>Auto-apply <strong style={{ color:'var(--green)' }}>low-risk</strong> fixes</span>
          </label>
          <span style={{ fontSize:'.76rem', color:'var(--dim)', flex:1 }}>
            Medium / high-risk fixes always require approval. Changes pushed via WPSB Beam plugin to WP REST.
          </span>
          <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast('6 low-risk fixes applied to WP', 'ok')}>
            <Icon name="spark" size={13}/>Apply all ready
          </button>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><h2 className="card-title">Auto-fix queue · {queue.length} items</h2></div>
        <div className="card-body" style={{ padding:0, overflowX:'auto' }}>
          <table className="table" style={{ minWidth:720 }}>
            <thead><tr>
              <th scope="col">Kind</th>
              <th scope="col">Target</th>
              <th scope="col">Diff</th>
              <th scope="col">Risk</th>
              <th scope="col">Status</th>
              <th scope="col"></th>
            </tr></thead>
            <tbody>
              {queue.map(f => (
                <tr key={f.id}>
                  <td style={{ fontWeight:600 }}>{f.kind}</td>
                  <td className="mono" style={{ fontSize:'.76rem', color:'var(--beam)' }}>{f.target}</td>
                  <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{f.diff}</td>
                  <td><span className={`tag ${riskTone(f.risk)}`}>{f.risk.toUpperCase()}</span></td>
                  <td><span className={`tag ${statTone(f.status)}`}>{f.status.replace(/-/g,' ').toUpperCase()}</span></td>
                  <td style={{ textAlign:'right' }}>
                    {f.status==='applied' ? (
                      <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Rolled back', 'info')}>Rollback</button>
                    ) : (
                      <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`Applied ${f.kind}`, 'ok')}>Apply</button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
}

/* ── BACKLINKS ────────────────────────────────────────────────── */
function SeoBacklinks() {
  const backlinks = [
    { from:'techcrunch.com/acme-series-b',      da:94, anchor:'Acme Corp',                  type:'follow',   first:'Apr 2, 2026',  status:'new' },
    { from:'hackernews.ycombinator.com',        da:91, anchor:'acme.co',                    type:'follow',   first:'Mar 28, 2026', status:'new' },
    { from:'producthunt.com/posts/acme',        da:81, anchor:'Acme - finance for teams',   type:'follow',   first:'Mar 14, 2026', status:'existing' },
    { from:'medium.com/@cfo-weekly',            da:72, anchor:'modern accounting',          type:'follow',   first:'Feb 22, 2026', status:'existing' },
    { from:'blog.spammy-site.co',               da:18, anchor:'click here',                 type:'nofollow', first:'Apr 10, 2026', status:'toxic' },
    { from:'reddit.com/r/startups',             da:90, anchor:'this AI tool',               type:'nofollow', first:'Feb 18, 2026', status:'existing' },
  ];
  const statTone = s => s==='toxic'?'bad':s==='new'?'beam':'';
  return (
    <div className="card">
      <div className="card-head">
        <h2 className="card-title">Backlinks · {backlinks.length}</h2>
        <div style={{ display:'flex', gap:6 }}>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Disavow file downloaded', 'ok')}>
            <Icon name="download" size={12}/>Disavow file
          </button>
        </div>
      </div>
      <div className="card-body" style={{ padding:0, overflowX:'auto' }}>
        <table className="table" style={{ minWidth:720 }}>
          <thead><tr>
            <th scope="col">From</th>
            <th scope="col" style={{ textAlign:'right' }}>DA</th>
            <th scope="col">Anchor</th>
            <th scope="col">Type</th>
            <th scope="col">First seen</th>
            <th scope="col">Status</th>
          </tr></thead>
          <tbody>
            {backlinks.map(b => (
              <tr key={b.from}>
                <td className="mono" style={{ fontSize:'.78rem', color:'var(--beam)' }}>{b.from}</td>
                <td className="mono" style={{ textAlign:'right', fontWeight:700, color: b.da>=70?'var(--green)':b.da>=40?'var(--warn)':'var(--rose)' }}>{b.da}</td>
                <td style={{ fontSize:'.82rem' }}>{b.anchor}</td>
                <td><span className={`tag ${b.type==='nofollow'?'':'ok'}`}>{b.type}</span></td>
                <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{b.first}</td>
                <td><span className={`tag ${statTone(b.status)}`}>{b.status.toUpperCase()}</span></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ── COMPETITORS (SEMRush-style) ──────────────────────────────── */
function SeoCompetitors() {
  const comps = [
    { dom:'quickbooks.com',    overlap:34, gap:128, da:92, traffic:'2.4M', authority:98 },
    { dom:'xero.com',          overlap:42, gap:84,  da:89, traffic:'1.1M', authority:91 },
    { dom:'freshbooks.com',    overlap:28, gap:56,  da:82, traffic:'480k', authority:78 },
    { dom:'waveapps.com',      overlap:18, gap:24,  da:74, traffic:'210k', authority:65 },
  ];
  const gaps = [
    { kw:'quickbooks online login',          comp:'quickbooks.com', vol:165000, opp:'low'    },
    { kw:'best accounting software for CPAs', comp:'xero.com',       vol:8900,   opp:'high'   },
    { kw:'invoice template',                 comp:'freshbooks.com', vol:60500,  opp:'med'    },
    { kw:'ai tax deductions',                comp:'— nobody —',     vol:2400,   opp:'high'   },
    { kw:'multi currency accounting',        comp:'xero.com',       vol:3600,   opp:'high'   },
  ];
  const oppTone = o => o==='high'?'ok':o==='med'?'warn':'';

  // Share-of-voice data (derived from traffic & authority)
  const yourSite = { dom:'acme.co', traffic:'89k', sovPct:4, authority:52, color:'var(--beam)' };
  const sovTotal = 4 + 42 + 20 + 8 + 4; // you + 4 comps = 78; rest = other
  const sovSlices = [
    { name:'quickbooks.com', pct:42, color:'var(--purple)' },
    { name:'xero.com',        pct:20, color:'#f59e0b' },
    { name:'freshbooks.com',  pct:8,  color:'#ec4899' },
    { name:'waveapps.com',    pct:4,  color:'var(--green)' },
    { name:'acme.co (you)',   pct:4,  color:'var(--beam)' },
    { name:'other / long tail', pct:22, color:'var(--dim)' },
  ];
  // Rank comparison for 8 shared keywords
  const rankData = [
    { kw:'accounting software',       you:14, comp:[{d:'quickbooks.com',r:1},{d:'xero.com',r:3},{d:'freshbooks.com',r:6}] },
    { kw:'invoice generator',         you:8,  comp:[{d:'freshbooks.com',r:1},{d:'waveapps.com',r:2},{d:'xero.com',r:5}] },
    { kw:'small business bookkeeping', you:22, comp:[{d:'quickbooks.com',r:2},{d:'xero.com',r:4},{d:'freshbooks.com',r:9}] },
    { kw:'expense tracking app',      you:11, comp:[{d:'quickbooks.com',r:3},{d:'xero.com',r:7},{d:'freshbooks.com',r:12}] },
    { kw:'cash flow forecast',        you:6,  comp:[{d:'xero.com',r:2},{d:'quickbooks.com',r:4},{d:'freshbooks.com',r:14}] },
    { kw:'1099 contractor payments',  you:9,  comp:[{d:'quickbooks.com',r:1},{d:'waveapps.com',r:6}] },
  ];

  return (
    <>
      {/* Charts row */}
      <div className="grid" style={{ gridTemplateColumns:'1.4fr 1fr', gap:12, marginBottom:14 }}>
        {/* Keyword rank comparison */}
        <div className="card">
          <div className="card-head" style={{ alignItems:'flex-start' }}>
            <div>
              <h2 className="card-title">Rank comparison · top shared keywords</h2>
              <div style={{ fontSize:'.68rem', color:'var(--dim)', marginTop:3 }}>Lower is better — position 1 is the top Google result</div>
            </div>
            <div style={{ display:'flex', gap:12, fontSize:'.66rem', color:'var(--dim)' }}>
              <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'var(--beam)', borderRadius:2 }}/>acme.co</span>
              <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'var(--purple)', borderRadius:2 }}/>qb</span>
              <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'#f59e0b', borderRadius:2 }}/>xero</span>
              <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'#ec4899', borderRadius:2 }}/>fb</span>
              <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'var(--green)', borderRadius:2 }}/>wave</span>
            </div>
          </div>
          <div className="card-body" style={{ padding:'14px 18px' }}>
            {rankData.map(row => {
              const markers = [
                { r: row.you, c: 'var(--beam)', lbl:'You' },
                ...row.comp.map(x => ({
                  r: x.r,
                  c: x.d.startsWith('quick') ? 'var(--purple)' : x.d.startsWith('xero') ? '#f59e0b' : x.d.startsWith('fresh') ? '#ec4899' : 'var(--green)',
                  lbl: x.d.replace('.com','').slice(0,2).toUpperCase(),
                })),
              ];
              return (
                <div key={row.kw} style={{ marginBottom:11 }}>
                  <div style={{ display:'flex', justifyContent:'space-between', fontSize:'.72rem', marginBottom:3 }}>
                    <span style={{ fontWeight:500 }}>{row.kw}</span>
                    <span className="mono" style={{ color:'var(--dim)', fontSize:'.66rem' }}>you: #{row.you}</span>
                  </div>
                  <div style={{ position:'relative', height:22, background:'var(--surface-2)', borderRadius:4, border:'1px solid var(--border)' }}>
                    {/* Tick marks at 1, 10, 20, 30 */}
                    {[1,10,20,30].map(t => (
                      <div key={t} style={{ position:'absolute', left:`${(t/30)*100}%`, top:0, bottom:0, width:1, background:'var(--border)' }}/>
                    ))}
                    {/* Markers */}
                    {markers.map((m, i) => (
                      <div key={i} title={`${m.lbl}: #${m.r}`}
                           style={{
                             position:'absolute',
                             left:`calc(${Math.min(m.r/30, 1)*100}% - 7px)`,
                             top:3, width:14, height:14, borderRadius:'50%',
                             background: m.c, border:'2px solid var(--surface)',
                             boxShadow:'0 0 0 1px rgba(0,0,0,.25)',
                             display:'flex', alignItems:'center', justifyContent:'center',
                             fontSize:'.48rem', fontWeight:700, color:'#fff',
                             zIndex: m.lbl === 'You' ? 3 : 2,
                           }}/>
                    ))}
                  </div>
                </div>
              );
            })}
            <div style={{ display:'flex', justifyContent:'space-between', fontSize:'.64rem', color:'var(--dim)', fontFamily:'var(--font-mono)', marginTop:4 }}>
              <span>#1</span><span>#10</span><span>#20</span><span>#30+</span>
            </div>
          </div>
        </div>

        {/* Share of Voice donut */}
        <div className="card">
          <div className="card-head" style={{ alignItems:'flex-start' }}>
            <div>
              <h2 className="card-title">Share of voice</h2>
              <div style={{ fontSize:'.68rem', color:'var(--dim)', marginTop:3 }}>% of organic clicks in your keyword universe</div>
            </div>
          </div>
          <div className="card-body" style={{ display:'flex', gap:16, alignItems:'center', padding:'16px 18px' }}>
            <svg viewBox="-60 -60 120 120" style={{ width:140, height:140, flexShrink:0 }}>
              {(() => {
                let angle = -90;
                return sovSlices.map(s => {
                  const sweep = (s.pct / 100) * 360;
                  const a0 = angle * Math.PI / 180;
                  const a1 = (angle + sweep) * Math.PI / 180;
                  const r = 50, ri = 26;
                  const x0 = r*Math.cos(a0), y0 = r*Math.sin(a0);
                  const x1 = r*Math.cos(a1), y1 = r*Math.sin(a1);
                  const x2 = ri*Math.cos(a1), y2 = ri*Math.sin(a1);
                  const x3 = ri*Math.cos(a0), y3 = ri*Math.sin(a0);
                  const large = sweep > 180 ? 1 : 0;
                  const d = `M ${x0} ${y0} A ${r} ${r} 0 ${large} 1 ${x1} ${y1} L ${x2} ${y2} A ${ri} ${ri} 0 ${large} 0 ${x3} ${y3} Z`;
                  angle += sweep;
                  return <path key={s.name} d={d} fill={s.color} stroke="var(--surface)" strokeWidth="1.5">
                    <title>{s.name}: {s.pct}%</title>
                  </path>;
                });
              })()}
              <text x="0" y="-2" textAnchor="middle" style={{ fontSize:'11px', fontWeight:700, fill:'var(--text)', fontFamily:'var(--font-mono)' }}>{yourSite.sovPct}%</text>
              <text x="0" y="10" textAnchor="middle" style={{ fontSize:'6px', fill:'var(--dim)', letterSpacing:'.1em' }}>YOU</text>
            </svg>
            <div style={{ flex:1, minWidth:0, fontSize:'.72rem' }}>
              {sovSlices.map(s => (
                <div key={s.name} style={{ display:'flex', alignItems:'center', gap:6, padding:'3px 0' }}>
                  <span style={{ width:10, height:10, background:s.color, borderRadius:2, flexShrink:0 }}/>
                  <span style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{s.name}</span>
                  <span className="mono" style={{ color:'var(--dim)' }}>{s.pct}%</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* Keyword coverage gap visualization */}
      <div className="card" style={{ marginBottom:14 }}>
        <div className="card-head">
          <div>
            <h2 className="card-title">Keyword coverage by competitor</h2>
            <div style={{ fontSize:'.68rem', color:'var(--dim)', marginTop:3 }}>How many keywords each competitor owns that you don't — the gap is your content opportunity</div>
          </div>
        </div>
        <div className="card-body" style={{ padding:'14px 18px' }}>
          {comps.map(c => {
            const maxGap = Math.max(...comps.map(x => x.gap));
            const gapPct = (c.gap / maxGap) * 100;
            const overlapPct = (c.overlap / 100) * 100;
            return (
              <div key={c.dom} style={{ marginBottom:10 }}>
                <div style={{ display:'flex', justifyContent:'space-between', fontSize:'.74rem', marginBottom:3 }}>
                  <span style={{ fontWeight:500 }}>{c.dom}</span>
                  <span style={{ fontSize:'.68rem', color:'var(--dim)' }}>
                    <span className="mono" style={{ color:'var(--beam)' }}>{c.overlap}% overlap</span>
                    {' · '}
                    <span className="mono" style={{ color:'var(--warn)' }}>{c.gap} gap</span>
                  </span>
                </div>
                <div style={{ display:'flex', height:16, borderRadius:3, overflow:'hidden', background:'var(--surface-2)', border:'1px solid var(--border)' }}>
                  <div style={{ width:`${overlapPct*0.4}%`, background:'var(--beam)', opacity:.8 }} title={`Shared: ${c.overlap}%`}/>
                  <div style={{ width:`${gapPct*0.6}%`, background:'var(--warn)', opacity:.7 }} title={`Their keywords you're missing: ${c.gap}`}/>
                </div>
              </div>
            );
          })}
          <div style={{ display:'flex', gap:14, fontSize:'.66rem', color:'var(--dim)', marginTop:8, borderTop:'1px solid var(--border)', paddingTop:8 }}>
            <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'var(--beam)', opacity:.8, borderRadius:2 }}/>Shared with you</span>
            <span style={{ display:'flex', alignItems:'center', gap:5 }}><span style={{ width:10, height:10, background:'var(--warn)', opacity:.7, borderRadius:2 }}/>Their keywords (gap opportunity)</span>
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-head">
          <h2 className="card-title">Your competitors · {comps.length} tracked</h2>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Enter competitor domain in new dialog (demo)', 'info')}>
            <Icon name="plus" size={12}/>Add competitor
          </button>
        </div>
        <div className="card-body" style={{ padding:0, overflowX:'auto' }}>
          <table className="table" style={{ minWidth:720 }}>
            <thead><tr>
              <th scope="col">Domain</th>
              <th scope="col" style={{ textAlign:'right' }}>KW overlap</th>
              <th scope="col" style={{ textAlign:'right' }}>Keyword gap</th>
              <th scope="col" style={{ textAlign:'right' }}>DA</th>
              <th scope="col" style={{ textAlign:'right' }}>Est. traffic</th>
              <th scope="col" style={{ textAlign:'right' }}>Authority</th>
            </tr></thead>
            <tbody>
              {comps.map(c => (
                <tr key={c.dom}>
                  <td style={{ fontWeight:600, fontSize:'.88rem' }}>{c.dom}</td>
                  <td className="mono" style={{ textAlign:'right' }}>{c.overlap}%</td>
                  <td className="mono" style={{ textAlign:'right', fontWeight:700, color:'var(--warn)' }}>{c.gap}</td>
                  <td className="mono" style={{ textAlign:'right' }}>{c.da}</td>
                  <td className="mono" style={{ textAlign:'right', color:'var(--dim)' }}>{c.traffic}</td>
                  <td className="mono" style={{ textAlign:'right' }}>{c.authority}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="card" style={{ marginTop:16 }}>
        <div className="card-head"><h2 className="card-title">Keyword gaps · content opportunities</h2><span className="tag beam">SEMRUSH-STYLE</span></div>
        <div className="card-body" style={{ padding:0 }}>
          <table className="table">
            <thead><tr>
              <th scope="col">Keyword</th>
              <th scope="col">Leader</th>
              <th scope="col" style={{ textAlign:'right' }}>Volume</th>
              <th scope="col">Opportunity</th>
              <th scope="col"></th>
            </tr></thead>
            <tbody>
              {gaps.map(g => (
                <tr key={g.kw}>
                  <td style={{ fontWeight:500 }}>{g.kw}</td>
                  <td className="mono" style={{ fontSize:'.76rem', color:'var(--beam)' }}>{g.comp}</td>
                  <td className="mono" style={{ textAlign:'right' }}>{g.vol.toLocaleString()}</td>
                  <td><span className={`tag ${oppTone(g.opp)}`}>{g.opp.toUpperCase()}</span></td>
                  <td style={{ textAlign:'right' }}>
                    <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast(`Brief drafted for "${g.kw}"`, 'ok')}>
                      <Icon name="spark" size={11}/>Brief with AI
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
}

/* ── SCHEDULE ─────────────────────────────────────────────────── */
function SeoSchedule() {
  const { useState } = React;
  const [freq, setFreq] = useState('weekly');
  const [autoFix, setAutoFix] = useState('low-risk-only');
  return (
    <div className="grid grid-2">
      <div className="card">
        <div className="card-head"><h2 className="card-title">Scan schedule</h2></div>
        <div className="card-body">
          <div className="field"><label>Scan frequency</label>
            <select value={freq} onChange={e => setFreq(e.target.value)}>
              <option value="daily">Daily</option>
              <option value="weekly">Weekly (recommended)</option>
              <option value="biweekly">Every 2 weeks</option>
              <option value="monthly">Monthly</option>
            </select>
          </div>
          <div className="field"><label>Auto-fix policy</label>
            <select value={autoFix} onChange={e => setAutoFix(e.target.value)}>
              <option value="none">Never — I'll approve each change</option>
              <option value="low-risk-only">Low-risk only (recommended)</option>
              <option value="low-med">Low + medium risk</option>
              <option value="all">Everything — full autonomy</option>
            </select>
          </div>
          <div className="field"><label>Notification emails</label>
            <input defaultValue="casey@acme.co, ops@acme.co"/>
          </div>
          <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast('Schedule saved', 'ok')}>Save schedule</button>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><h2 className="card-title">Integrations</h2></div>
        <div className="card-body" style={{ padding:0 }}>
          {[
            ['WordPress (Beam plugin)', 'Connected · v2.4.1', 'ok'],
            ['Google Search Console',   'Connected · acme.co property', 'ok'],
            ['Google Analytics 4',      'Connected · GA4-XXXX', 'ok'],
            ['Yoast SEO',               'Detected on 44 pages', 'ok'],
            ['RankMath',                'Not detected', ''],
            ['Semrush API',             'Connect to pull live KW data', 'warn'],
            ['Ahrefs API',              'Optional — adds backlink intel', ''],
          ].map(([n, s, tone], i, a) => (
            <div key={n} style={{ display:'flex', gap:12, padding:'12px 18px', borderBottom: i<a.length-1 ? '1px solid var(--border)' : 'none', alignItems:'center' }}>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontWeight:600, fontSize:'.86rem' }}>{n}</div>
                <div style={{ fontSize:'.72rem', color:'var(--dim)', marginTop:2 }}>{s}</div>
              </div>
              {tone === 'ok'   && <span className="tag ok">CONNECTED</span>}
              {tone === 'warn' && <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`Connecting ${n}…`, 'info')}>Connect</button>}
              {tone === ''     && <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`${n} — setup opened`, 'info')}>Setup</button>}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ── Small shared bits ───────────────────────────────────────── */
function Kv({ k, v }) {
  return (
    <div style={{ minWidth:160 }}>
      <div style={{ fontSize:'.66rem', color:'var(--muted)', fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.5px' }}>{k}</div>
      <div style={{ fontSize:'.88rem', fontWeight:600, marginTop:3 }}>{v}</div>
    </div>
  );
}

function MiniAreaChart() {
  const { useState, useMemo, useRef } = React;
  const [metric, setMetric] = useState('clicks');         // clicks | impressions | ctr | position | sessions | users
  const [range, setRange]   = useState('30d');           // 7d | 30d | 90d | 12m
  const [compare, setCompare] = useState(true);          // previous period overlay
  const [hover, setHover]   = useState(null);            // { i, x, y, cx, cy }
  const wrapRef = useRef(null);

  const METRICS = [
    { id:'clicks',      label:'Clicks',      src:'GSC', unit:'',  fmt:(v)=>v.toLocaleString(),        color:'var(--beam)' },
    { id:'impressions', label:'Impressions', src:'GSC', unit:'',  fmt:(v)=>(v/1000).toFixed(1)+'k',   color:'#7c5cff'     },
    { id:'ctr',         label:'CTR',         src:'GSC', unit:'%', fmt:(v)=>v.toFixed(2)+'%',          color:'var(--warn)' },
    { id:'position',    label:'Avg. position',src:'GSC',unit:'',  fmt:(v)=>v.toFixed(1),              color:'var(--rose)', inverted:true },
    { id:'sessions',    label:'Sessions',    src:'GA4', unit:'',  fmt:(v)=>v.toLocaleString(),        color:'var(--green)' },
    { id:'users',       label:'Users',       src:'GA4', unit:'',  fmt:(v)=>v.toLocaleString(),        color:'#00d2ff'     },
  ];
  const RANGES = [
    { id:'7d',  label:'7d',          days:7,    compareLbl:'vs prev. 7 days' },
    { id:'30d', label:'30d',         days:30,   compareLbl:'vs prev. 30 days' },
    { id:'90d', label:'90d',         days:90,   compareLbl:'vs prev. 90 days' },
    { id:'12m', label:'12m',         days:365,  compareLbl:'vs prev. year' },
  ];
  const curMetric = METRICS.find(m => m.id === metric);
  const curRange  = RANGES.find(r  => r.id === range);

  // Deterministic synthetic series — same shape every render for a given metric/range.
  function seed(n){ let x=1779+n*37; return ()=>{ x=(x*9301+49297)%233280; return x/233280; }; }
  function baseFor(metric, daysBack){
    // Base values — realistic shape: growing over time for clicks/sessions/impressions, declining (improving) for position
    const base = { clicks: 280, impressions: 9400, ctr: 3.0, position: 14, sessions: 820, users: 640 }[metric];
    const growth = { clicks: 0.35, impressions: 0.20, ctr: 0.02, position: -0.12, sessions: 0.30, users: 0.28 }[metric];
    return base * (1 + growth * (1 - daysBack/365));
  }
  const series = useMemo(() => {
    const days = curRange.days;
    const step = days <= 30 ? 1 : days <= 90 ? 3 : 7;         // bucket size in days
    const buckets = Math.floor(days / step);
    const rnd = seed(metric.charCodeAt(0) * 13 + days);
    const rndPrev = seed(metric.charCodeAt(0) * 13 + days + 99);
    const now = new Date('2026-04-20T00:00:00Z');
    const curr = [], prev = [];
    for (let i = buckets - 1; i >= 0; i--) {
      const daysBack = i * step;
      const base = baseFor(metric, daysBack);
      const noise = (rnd() - 0.5) * base * (metric==='position' ? 0.2 : 0.22);
      const trendWobble = Math.sin((buckets - i) / buckets * Math.PI * 2) * base * 0.08;
      const date = new Date(now); date.setUTCDate(date.getUTCDate() - daysBack);
      const prevDate = new Date(date); prevDate.setUTCDate(prevDate.getUTCDate() - days);
      const prevBase = baseFor(metric, daysBack + days);
      const prevNoise = (rndPrev() - 0.5) * prevBase * (metric==='position' ? 0.2 : 0.22);
      curr.push({ date, v: Math.max(0.1, base + noise + trendWobble) });
      prev.push({ date: prevDate, v: Math.max(0.1, prevBase + prevNoise) });
    }
    return { curr, prev, step };
  }, [metric, range]);

  const totalCurr = series.curr.reduce((a,b)=>a+b.v, 0) * (metric==='ctr' || metric==='position' ? 1/series.curr.length : 1);
  const totalPrev = series.prev.reduce((a,b)=>a+b.v, 0) * (metric==='ctr' || metric==='position' ? 1/series.prev.length : 1);
  const delta = totalPrev ? ((totalCurr - totalPrev) / totalPrev) * 100 : 0;
  const isGood = curMetric.inverted ? delta < 0 : delta > 0;

  // SVG geometry
  const w = 720, h = 220, padL = 48, padR = 12, padT = 14, padB = 30;
  const innerW = w - padL - padR, innerH = h - padT - padB;
  const allVals = compare ? [...series.curr, ...series.prev].map(d=>d.v) : series.curr.map(d=>d.v);
  const vMin = curMetric.inverted ? Math.min(...allVals) * 0.8 : 0;
  const vMax = curMetric.inverted ? Math.max(...allVals) * 1.05 : Math.max(...allVals) * 1.15;
  const sx = (i, arr) => padL + (i / (arr.length - 1 || 1)) * innerW;
  const sy = (v) => padT + innerH - ((v - vMin) / (vMax - vMin || 1)) * innerH;

  const buildPath = (arr) => arr.map((d, i) => (i===0?'M':'L') + sx(i, arr).toFixed(1) + ',' + sy(d.v).toFixed(1)).join(' ');
  const currPath = buildPath(series.curr);
  const prevPath = buildPath(series.prev);
  const currArea = currPath + ` L ${padL + innerW},${padT + innerH} L ${padL},${padT + innerH} Z`;

  // Y-axis ticks (4)
  const yTicks = [0, .33, .66, 1].map(f => vMin + f * (vMax - vMin));
  const xTicks = [0, Math.floor(series.curr.length/4), Math.floor(series.curr.length/2), Math.floor(3*series.curr.length/4), series.curr.length-1];
  const xLabel = (d) => d.toLocaleDateString('en-US', { month:'short', day:'numeric' });

  function onMove(e) {
    const rect = wrapRef.current.getBoundingClientRect();
    const px = ((e.clientX - rect.left) / rect.width) * w;
    if (px < padL || px > padL + innerW) { setHover(null); return; }
    const frac = (px - padL) / innerW;
    const i = Math.round(frac * (series.curr.length - 1));
    if (i < 0 || i >= series.curr.length) { setHover(null); return; }
    setHover({ i, cx: sx(i, series.curr), cyC: sy(series.curr[i].v), cyP: sy(series.prev[i].v) });
  }

  return (
    <div>
      {/* Controls row */}
      <div style={{ display:'flex', flexWrap:'wrap', alignItems:'center', gap:8, marginBottom:14 }}>
        <div className="tw-seg" style={{ display:'inline-flex', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:6, padding:2 }}>
          {METRICS.map(m => (
            <button key={m.id} onClick={()=>setMetric(m.id)}
              style={{ padding:'5px 10px', fontSize:'.72rem', background: metric===m.id ? 'var(--surface)' : 'transparent', border:'none', borderRadius:4, color: metric===m.id ? 'var(--text)' : 'var(--dim)', cursor:'pointer', fontWeight: metric===m.id?600:400, display:'inline-flex', alignItems:'center', gap:5 }}>
              <span style={{ width:6, height:6, borderRadius:'50%', background: m.color }}/>
              {m.label}<span style={{ fontFamily:'var(--font-mono)', fontSize:'.62rem', opacity:.6 }}>·{m.src}</span>
            </button>
          ))}
        </div>
        <div style={{ flex:1 }}/>
        <div className="tw-seg" style={{ display:'inline-flex', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:6, padding:2 }}>
          {RANGES.map(r => (
            <button key={r.id} onClick={()=>setRange(r.id)}
              style={{ padding:'5px 10px', fontSize:'.72rem', background: range===r.id ? 'var(--surface)' : 'transparent', border:'none', borderRadius:4, color: range===r.id ? 'var(--text)' : 'var(--dim)', cursor:'pointer', fontWeight: range===r.id?600:400 }}>
              {r.label}
            </button>
          ))}
        </div>
        <label style={{ display:'inline-flex', alignItems:'center', gap:6, fontSize:'.72rem', color:'var(--dim)', cursor:'pointer' }}>
          <input type="checkbox" checked={compare} onChange={e=>setCompare(e.target.checked)} style={{ accentColor:'var(--beam)' }}/>
          Compare
        </label>
      </div>

      {/* Headline */}
      <div style={{ display:'flex', alignItems:'baseline', gap:14, marginBottom:8, flexWrap:'wrap' }}>
        <div style={{ fontSize:'1.6rem', fontWeight:600, color:'var(--text)', fontFamily:'var(--font-mono)' }}>
          {curMetric.fmt(totalCurr)}
        </div>
        <div style={{ fontSize:'.76rem', color:'var(--dim)' }}>
          {metric==='ctr' || metric==='position' ? 'avg' : 'total'} · {curRange.days} {curRange.days===365?'days':'days'}
        </div>
        {compare && (
          <div style={{ fontSize:'.78rem', display:'inline-flex', alignItems:'center', gap:6 }}>
            <span style={{ color: isGood ? 'var(--green)' : 'var(--rose)', fontWeight:600 }}>
              {delta > 0 ? '▲' : '▼'} {Math.abs(delta).toFixed(1)}%
            </span>
            <span style={{ color:'var(--dim)' }}>{curRange.compareLbl} ({curMetric.fmt(totalPrev)})</span>
          </div>
        )}
      </div>

      {/* Chart */}
      <div ref={wrapRef} style={{ position:'relative' }}
           onMouseMove={onMove} onMouseLeave={()=>setHover(null)}>
        <svg viewBox={`0 0 ${w} ${h}`} style={{ width:'100%', height:220, display:'block' }} aria-label={`${curMetric.label} trend over ${curRange.label}`} role="img">
          <defs>
            <linearGradient id={'seo-grad-'+metric} x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%"   stopColor={curMetric.color} stopOpacity=".35"/>
              <stop offset="100%" stopColor={curMetric.color} stopOpacity="0"/>
            </linearGradient>
          </defs>

          {/* Y-axis gridlines + labels */}
          {yTicks.map((v, i) => {
            const y = sy(v);
            return (
              <g key={i}>
                <line x1={padL} x2={w-padR} y1={y} y2={y} stroke="var(--border)" strokeDasharray="2 3" strokeWidth="1"/>
                <text x={padL-8} y={y+3} textAnchor="end" fontSize="9" fill="var(--dim)" fontFamily="var(--font-mono)">{curMetric.fmt(v)}</text>
              </g>
            );
          })}

          {/* X-axis labels */}
          {xTicks.map(i => (
            <text key={i} x={sx(i, series.curr)} y={h-padB+16} textAnchor="middle" fontSize="9" fill="var(--dim)" fontFamily="var(--font-mono)">
              {xLabel(series.curr[i].date)}
            </text>
          ))}
          <line x1={padL} x2={w-padR} y1={h-padB} y2={h-padB} stroke="var(--border)" strokeWidth="1"/>

          {/* Comparison line (previous period) — dashed, gray */}
          {compare && <path d={prevPath} fill="none" stroke="var(--dim)" strokeWidth="1.5" strokeDasharray="3 3" opacity=".7"/>}

          {/* Current area + line */}
          <path d={currArea} fill={`url(#seo-grad-${metric})`}/>
          <path d={currPath} fill="none" stroke={curMetric.color} strokeWidth="2"/>

          {/* Hover marker */}
          {hover && (
            <g>
              <line x1={hover.cx} x2={hover.cx} y1={padT} y2={h-padB} stroke="var(--text-2)" strokeWidth="1" strokeDasharray="2 2" opacity=".5"/>
              {compare && <circle cx={hover.cx} cy={hover.cyP} r="3.5" fill="var(--surface)" stroke="var(--dim)" strokeWidth="1.5"/>}
              <circle cx={hover.cx} cy={hover.cyC} r="4" fill={curMetric.color} stroke="var(--surface)" strokeWidth="2"/>
            </g>
          )}
        </svg>

        {/* Tooltip */}
        {hover && (() => {
          const curr = series.curr[hover.i], prev = series.prev[hover.i];
          const tipX = (hover.cx / w) * 100;
          const flip = tipX > 70;
          return (
            <div style={{
              position:'absolute',
              left: flip ? 'auto' : `calc(${tipX}% + 12px)`,
              right: flip ? `calc(${100 - tipX}% + 12px)` : 'auto',
              top: 10,
              background:'var(--surface)', border:'1px solid var(--border)', borderRadius:6,
              padding:'8px 10px', fontSize:'.72rem', minWidth:160, pointerEvents:'none',
              boxShadow:'0 8px 20px rgba(0,0,0,.3)', zIndex:2,
            }}>
              <div style={{ fontFamily:'var(--font-mono)', color:'var(--dim)', fontSize:'.66rem', marginBottom:4 }}>
                {curr.date.toLocaleDateString('en-US', { weekday:'short', month:'short', day:'numeric', year:'numeric' })}
              </div>
              <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:2 }}>
                <span style={{ width:8, height:8, borderRadius:'50%', background: curMetric.color }}/>
                <span style={{ color:'var(--dim)' }}>{curMetric.label}:</span>
                <span style={{ marginLeft:'auto', fontWeight:600, color:'var(--text)', fontFamily:'var(--font-mono)' }}>{curMetric.fmt(curr.v)}</span>
              </div>
              {compare && (
                <div style={{ display:'flex', alignItems:'center', gap:6 }}>
                  <span style={{ width:8, height:8, borderRadius:'50%', background: 'var(--dim)' }}/>
                  <span style={{ color:'var(--dim)' }}>Previous:</span>
                  <span style={{ marginLeft:'auto', fontWeight:500, color:'var(--text-2)', fontFamily:'var(--font-mono)' }}>{curMetric.fmt(prev.v)}</span>
                </div>
              )}
            </div>
          );
        })()}
      </div>

      {/* Legend + lineage */}
      <div style={{ marginTop:10, display:'flex', alignItems:'center', gap:14, flexWrap:'wrap', fontSize:'.66rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>
        <span style={{ display:'inline-flex', alignItems:'center', gap:5 }}>
          <span style={{ width:14, height:2, background: curMetric.color }}/>
          Current period
        </span>
        {compare && (
          <span style={{ display:'inline-flex', alignItems:'center', gap:5 }}>
            <span style={{ width:14, height:1.5, background:'var(--dim)', borderTop:'1.5px dashed var(--dim)' }}/>
            Previous period
          </span>
        )}
        <span style={{ marginLeft:'auto' }}>
          ↳ Source: {curMetric.src === 'GSC' ? 'Google Search Console API' : 'Google Analytics 4 Data API'} · hover chart for daily values
        </span>
      </div>
    </div>
  );
}

window.ContentSEO = ContentSEO;
