/* WP Site Beam — Pages 2 (Support, Requests, Scanner) + SA pages */

/* ── DOC DETAIL & SEARCH ARCHIVE (auto-content data sources) ─── */
const DOC_CONTENT = {
  'getting-started': {
    intro: 'A 5-minute walkthrough to scan your first site and read the report. Updated continuously as the platform evolves.',
    sections: [
      { h:'1. Connect a site', body:'Add your domain on the Sites page and install the Beam plugin. Auto-detected platforms: WordPress, Shopify, Wix, Webflow, Squarespace.' },
      { h:'2. Run your first scan', body:'Click "Scan now" — typical scan completes in ~90s. You\'ll receive a brand consistency, SEO, performance, and accessibility score.' },
      { h:'3. Review the brand kit', body:'The scanner extracts logos, colors, fonts, and tone-of-voice into a portable Brand Kit you can export to your designers.' },
    ],
    related: ['scanner-guide','redirects','security'],
  },
  'scanner-guide': {
    intro: 'Deep dive on the scanner: how detection works, export formats, and how to interpret each score band.',
    sections: [
      { h:'Platform detection', body:'Wappalyzer-style fingerprinting + plugin probes. ~120 platforms supported as of v2.4.' },
      { h:'Export formats', body:'JSON, CSV, Figma tokens, Tailwind config, Sketch palette, .ase swatches.' },
      { h:'Score interpretation', body:'Each score is 0–100, weighted by industry vertical. Civic sites weight accessibility 2×.' },
    ],
    related: ['getting-started','api','civic'],
  },
  'changelog': {
    intro: 'Auto-generated from merged PRs and shipped releases. Pulled from GitHub + internal release manager every 15 min.',
    auto: 'changelog',
  },
  'api': {
    intro: 'REST + Webhooks. Auto-generated from OpenAPI spec on every deploy.',
    auto: 'api',
  },
};

function DocDetail({ slug, docs, onBack }) {
  const meta = docs.find(d => d.slug === slug) || { emoji:'📄', t:slug, d:'' };
  const content = DOC_CONTENT[slug] || { intro: 'Documentation auto-generated from product schema, AI synthesis, and recent ticket patterns. This article will populate as content is indexed.', sections: [{ h:'Overview', body:'(Auto-content placeholder — connected source: docs DB + AI summarizer.)'}] };

  // mock auto-generated changelog
  const changelog = [
    { v:'v2.4.1', ts:'Apr 18, 2026', notes:['Estimator: fixed rounding above $9,999','Scanner: added shop.commerce platform fingerprint','UI: improved mobile sidebar collapse'] },
    { v:'v2.4.0', ts:'Apr 12, 2026', notes:['New: Brand Profile module','New: Plan Comparison view in Hosting Plans','Scanner: 12 new plugin signatures'] },
    { v:'v2.3.7', ts:'Apr 04, 2026', notes:['Tickets: SLA timer respect business hours','Marketing: A/B variant analytics'] },
  ];
  const apiEndpoints = [
    { m:'GET',  p:'/v1/sites',           d:'List sites accessible to this token' },
    { m:'POST', p:'/v1/sites/:id/scan',  d:'Trigger a scan; returns job id' },
    { m:'GET',  p:'/v1/scans/:id',       d:'Fetch scan results JSON' },
    { m:'POST', p:'/v1/estimates',       d:'Create an estimate from a scan + tier' },
    { m:'POST', p:'/v1/webhooks',        d:'Register a webhook endpoint' },
  ];

  return (
    <div>
      <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:'.78rem', color:'var(--dim)', marginTop:8, marginBottom:14 }}>
        <a href="#" onClick={e => { e.preventDefault(); onBack(); }} style={{ color:'var(--beam)' }}>← All documentation</a>
        <span>·</span>
        <span>Last synced 4 min ago</span>
        <span>·</span>
        <span>Auto-updates from product DB + AI summarizer</span>
      </div>

      <div className="card">
        <div className="card-body" style={{ display:'flex', alignItems:'flex-start', gap:18, padding:24 }}>
          <div style={{ fontSize:'2.4rem', lineHeight:1 }}>{meta.emoji}</div>
          <div style={{ flex:1 }}>
            <h2 style={{ margin:'0 0 6px', fontFamily:'var(--font-brand)', fontSize:'1.6rem' }}>{meta.t}</h2>
            <div style={{ color:'var(--muted)', fontSize:'.92rem' }}>{content.intro}</div>
            <div style={{ display:'flex', gap:8, marginTop:14, flexWrap:'wrap' }}>
              <span className="tag beam">AUTO-UPDATING</span>
              <span className="tag">v2.4.1</span>
              <span className="tag">{Math.floor(Math.random()*8)+3} sources</span>
              <button className="btn btn-ghost btn-sm"><Icon name="download" size={12}/>PDF</button>
              <button className="btn btn-ghost btn-sm"><Icon name="copy" size={12}/>Share link</button>
            </div>
          </div>
        </div>
      </div>

      {/* Article body (manual + AI-synthesized sections) */}
      {content.sections && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-head"><h2 className="card-title">📖 Article</h2><span className="tag">EDITORIAL + AI</span></div>
          <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:18 }}>
            {content.sections.map(s => (
              <div key={s.h}>
                <h4 style={{ margin:'0 0 6px', fontSize:'.98rem' }}>{s.h}</h4>
                <p style={{ margin:0, color:'var(--muted)', fontSize:'.88rem', lineHeight:1.6 }}>{s.body}</p>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Auto: changelog stream */}
      {(content.auto === 'changelog' || slug === 'getting-started' || slug === 'scanner-guide') && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-head"><h2 className="card-title">📋 Recent changes</h2><span className="tag beam">AUTO · GitHub + Releases</span></div>
          <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:14, padding:0 }}>
            {changelog.map((c, i) => (
              <div key={c.v} style={{ padding:'14px 18px', borderBottom: i<changelog.length-1 ? '1px solid var(--border)' : 'none' }}>
                <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:6 }}>
                  <span className="mono" style={{ fontWeight:700, color:'var(--beam)' }}>{c.v}</span>
                  <span className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{c.ts}</span>
                </div>
                <ul style={{ margin:0, paddingLeft:18, color:'var(--muted)', fontSize:'.84rem', lineHeight:1.6 }}>
                  {c.notes.map(n => <li key={n}>{n}</li>)}
                </ul>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Auto: API reference */}
      {content.auto === 'api' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-head"><h2 className="card-title">🔌 Endpoints</h2><span className="tag beam">AUTO · OpenAPI</span></div>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col" style={{ width:80 }}>Method</th><th scope="col">Path</th><th scope="col">Description</th></tr></thead>
              <tbody>
                {apiEndpoints.map(e => (
                  <tr key={e.p}>
                    <td><span className={`tag ${e.m==='GET'?'ok':'beam'}`}>{e.m}</span></td>
                    <td className="mono" style={{ fontSize:'.78rem' }}>{e.p}</td>
                    <td style={{ color:'var(--muted)', fontSize:'.84rem' }}>{e.d}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* AI assistant in context */}
      <div className="card" style={{ marginTop:16 }}>
        <div className="card-head"><h2 className="card-title">🤖 Ask AI about this article</h2><span className="tag beam">SUPPORT BRAIN</span></div>
        <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
            {['Summarize for my team','Show a code example','What changed in the last 30 days?','Open a related ticket'].map(s => (
              <button key={s} className="btn btn-ghost btn-sm" style={{ fontSize:'.74rem' }}>{s}</button>
            ))}
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <input placeholder={`Ask anything about ${meta.t}…`} style={{ flex:1 }}/>
            <button className="btn btn-primary"><Icon name="spark" size={13}/>Ask</button>
          </div>
        </div>
      </div>

      {/* Training videos */}
      <div className="card" style={{ marginTop:16 }}>
        <div className="card-head"><h2 className="card-title">🎓 Trainings</h2><span className="tag">VIDEO LIBRARY</span></div>
        <div className="card-body">
          <div className="grid grid-3">
            {[1,2,3].map(i => (
              <div key={i} style={{ borderRadius:8, overflow:'hidden', background:'var(--surface-3)', border:'1px solid var(--border)' }}>
                <div style={{ aspectRatio:'16/9', background:'linear-gradient(135deg, var(--beam-dim), var(--surface-2))', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'1.6rem' }}>▶</div>
                <div style={{ padding:10 }}>
                  <div style={{ fontSize:'.84rem', fontWeight:600 }}>{meta.t} · Part {i}</div>
                  <div style={{ fontSize:'.72rem', color:'var(--dim)' }}>{4 + i} min · auto-captioned</div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Related / community */}
      <div className="grid grid-2" style={{ marginTop:16 }}>
        <div className="card">
          <div className="card-head"><h2 className="card-title">🔗 Related articles</h2></div>
          <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:8 }}>
            {(content.related || ['getting-started','api','changelog']).filter(r => r !== slug).map(r => {
              const rd = docs.find(d => d.slug === r) || { emoji:'📄', t:r, d:'' };
              return (
                <a key={r} href="#" onClick={e => { e.preventDefault(); window.scrollTo(0,0); /* navigate */ }} style={{ display:'flex', gap:10, padding:'10px 12px', borderRadius:8, border:'1px solid var(--border)', textDecoration:'none', color:'inherit' }}>
                  <span style={{ fontSize:'1.2rem' }}>{rd.emoji}</span>
                  <div>
                    <div style={{ fontWeight:600, fontSize:'.86rem' }}>{rd.t}</div>
                    <div style={{ fontSize:'.74rem', color:'var(--dim)' }}>{rd.d}</div>
                  </div>
                </a>
              );
            })}
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h2 className="card-title">💬 Community Q&amp;A</h2><span className="tag">COMMUNITY</span></div>
          <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:10 }}>
            {[
              { q:'Can I export the brand kit to Sketch?', a:3, ts:'2 days ago' },
              { q:'Why does my scan miss subdomains?', a:5, ts:'1 week ago' },
              { q:'How to disable AI suggestions?', a:1, ts:'2 weeks ago' },
            ].map(qa => (
              <div key={qa.q} style={{ padding:'10px 12px', borderRadius:8, border:'1px solid var(--border)' }}>
                <div style={{ fontSize:'.86rem', fontWeight:500 }}>{qa.q}</div>
                <div style={{ fontSize:'.72rem', color:'var(--dim)', marginTop:4 }}>{qa.a} answers · {qa.ts}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function DocSearchArchive({ initialQuery, docs, onBack, onOpenDoc }) {
  const { useState, useMemo } = React;
  const [q, setQ] = useState(initialQuery || '');
  const [type, setType] = useState('all');

  // Build a unified archive feed across content types
  const archive = useMemo(() => {
    const items = [];
    docs.forEach(d => items.push({ kind:'article', emoji:d.emoji, title:d.t, snippet:d.d, slug:d.slug, ts:'updated 2d ago' }));
    [
      { kind:'changelog', emoji:'📋', title:'v2.4.1 — Estimator rounding fix', snippet:'Fixed rounding above $9,999 in totals; scanner platform additions.', ts:'Apr 18, 2026' },
      { kind:'changelog', emoji:'📋', title:'v2.4.0 — Brand Profile module', snippet:'New module for centralized brand identity used across portal, billing, marketing.', ts:'Apr 12, 2026' },
      { kind:'training',  emoji:'🎓', title:'Scanner deep dive (12 min)', snippet:'Walkthrough of platform detection, export formats, and score interpretation.', ts:'Mar 30, 2026' },
      { kind:'training',  emoji:'🎓', title:'Estimator best practices', snippet:'How to scope migrations and avoid common pricing mistakes.', ts:'Mar 22, 2026' },
      { kind:'community', emoji:'💬', title:'Subdomains in scanner', snippet:'Q&A · 5 answers · how to add subdomains to a scan.', ts:'1 week ago' },
      { kind:'community', emoji:'💬', title:'Export to Sketch', snippet:'Q&A · 3 answers · brand kit export options.', ts:'2 days ago' },
      { kind:'api',       emoji:'🔌', title:'POST /v1/sites/:id/scan', snippet:'Trigger a scan; returns job id.', ts:'auto' },
      { kind:'api',       emoji:'🔌', title:'GET /v1/scans/:id', snippet:'Fetch scan results JSON.', ts:'auto' },
      { kind:'wiki',      emoji:'📓', title:'Internal: how we vet a partner application', snippet:'Process doc · 4 reviewers · SLA 5 business days.', ts:'updated last month' },
    ].forEach(x => items.push(x));
    return items;
  }, [docs]);

  const filtered = archive.filter(it => {
    if (type !== 'all' && it.kind !== type) return false;
    if (!q) return true;
    return (it.title + ' ' + it.snippet).toLowerCase().includes(q.toLowerCase());
  });

  const counts = archive.reduce((acc, it) => { acc[it.kind] = (acc[it.kind] || 0) + 1; acc.all++; return acc; }, { all: 0 });
  const kindStyle = { article:'beam', changelog:'', training:'warn', community:'ok', api:'beam', wiki:'' };

  return (
    <div>
      <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:'.78rem', color:'var(--dim)', marginTop:8, marginBottom:14 }}>
        <a href="#" onClick={e => { e.preventDefault(); onBack(); }} style={{ color:'var(--beam)' }}>← Back to documentation</a>
        <span>·</span>
        <span>Search archive · WordPress-style cross-content browse</span>
      </div>

      <div className="card">
        <div className="card-body" style={{ display:'flex', alignItems:'center', gap:14, padding:20 }}>
          <div style={{ width:48, height:48, borderRadius:10, background:'var(--orange-dim)', color:'var(--orange)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'1.4rem' }}>🔎</div>
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search across articles, changelogs, trainings, community, API, wiki…" autoFocus style={{ flex:1, fontSize:'.92rem' }}/>
          <span className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{filtered.length} results</span>
        </div>
      </div>

      <div className="sub-tabs" style={{ marginTop:14 }}>
        {[
          ['all',       `All (${counts.all})`],
          ['article',   `📚 Articles (${counts.article || 0})`],
          ['changelog', `📋 Changelog (${counts.changelog || 0})`],
          ['training',  `🎓 Training (${counts.training || 0})`],
          ['community', `💬 Community (${counts.community || 0})`],
          ['api',       `🔌 API (${counts.api || 0})`],
          ['wiki',      `📓 Wiki (${counts.wiki || 0})`],
        ].map(([id, lbl]) => (
          <button key={id} role="tab" aria-selected={(type===id)} tabIndex={(type===id)?0:-1} className={'sub-tab' + ((type===id)?' active':'')} onClick={() => setType(id)}>{lbl}</button>
        ))}
      </div>

      <div className="card" style={{ marginTop:14 }}>
        <div className="card-body" style={{ padding:0 }}>
          {filtered.length === 0 && (
            <div style={{ padding:40, textAlign:'center', color:'var(--dim)' }}>No results for "{q}". Try a broader term, or browse the categories above.</div>
          )}
          {filtered.map((it, i) => (
            <a key={i} href="#" onClick={e => { e.preventDefault(); if (it.kind === 'article') onOpenDoc(it.slug); }}
              style={{ display:'flex', gap:14, padding:'16px 18px', borderBottom: i<filtered.length-1 ? '1px solid var(--border)' : 'none', textDecoration:'none', color:'inherit' }}>
              <div style={{ fontSize:'1.6rem', lineHeight:1 }}>{it.emoji}</div>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
                  <span className={`tag ${kindStyle[it.kind] || ''}`}>{it.kind.toUpperCase()}</span>
                  <span className="mono" style={{ fontSize:'.7rem', color:'var(--dim)' }}>{it.ts}</span>
                </div>
                <div style={{ fontWeight:600, fontSize:'.92rem' }}>{it.title}</div>
                <div style={{ fontSize:'.8rem', color:'var(--dim)', marginTop:2 }}>{it.snippet}</div>
              </div>
              <div style={{ alignSelf:'center', color:'var(--beam)', fontSize:'.78rem', fontWeight:600 }}>Open →</div>
            </a>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ── SUPPORT ─────────────────────────────────────────────────── */
function Support() {
  const { useState } = React;
  const [supTab, setSupTab] = useState('docs');
  const [docView, setDocView] = useState(null);   // null | slug
  const [searchView, setSearchView] = useState(null); // null | query
  const tickets = [
    { id: 'T-124', subj: 'Scan timeout on shop.acme.co', status: 'open',   pri: 'high', created:'2 hrs ago', updated:'18 min ago' },
    { id: 'T-120', subj: 'Plugin not auto-updating',     status: 'waiting',pri: 'med',  created:'Yesterday',  updated:'3 hrs ago' },
    { id: 'T-118', subj: 'Invoice PDF 404',              status: 'closed', pri: 'low',  created:'3 days ago', updated:'2 days ago' },
    { id: 'T-115', subj: 'DNS propagation stuck',        status: 'open',   pri: 'high', created:'5 hrs ago',  updated:'32 min ago' },
  ];
  const bugs = [
    { id:'BUG-88', t:'Scanner fails on sites with self-signed certs', sev:'high',  votes:12, status:'triage' },
    { id:'BUG-84', t:'Estimator total rounds incorrectly over $9,999', sev:'med',  votes:7,  status:'fixed-staging' },
    { id:'BUG-81', t:'Dark mode: accent swatches lose contrast',       sev:'low',  votes:4,  status:'triage' },
  ];
  const tone = { open: 'warn', waiting: 'beam', closed: 'ok', triage:'warn', 'fixed-staging':'beam' };

  const docs = [
    { emoji:'🚀', t:'Getting Started',        d:'Setup guide & first scan walkthrough',       slug:'getting-started' },
    { emoji:'🔍', t:'Scanner Guide',          d:'Exports, platform detection, brand kit',     slug:'scanner-guide' },
    { emoji:'🔀', t:'Redirects & Migration',  d:'301 rules, file map, import/export',         slug:'redirects' },
    { emoji:'💰', t:'WP Scope Estimator',     d:'Build proposals & migration scoping',        slug:'estimator' },
    { emoji:'🔒', t:'Security Overview',      d:'SSL, login hardening, plugin audit',         slug:'security' },
    { emoji:'📋', t:'Changelog',              d:'Latest updates & fixes by version',          slug:'changelog' },
    { emoji:'🎓', t:'LMS & Memberships',      d:'LearnDash, MemberPress integrations',        slug:'lms' },
    { emoji:'🏛️', t:'Civic Sites',            d:'ADA, doc libraries, commission tools',       slug:'civic' },
    { emoji:'🔌', t:'API Reference',          d:'REST endpoints, webhooks, auth',             slug:'api' },
  ];

  return (
    <div>
      <PageHead crumb="Operations" title="🎧 Support"
        sub="Docs, AI chat, tickets & bug reports"
        actions={<>
          <button className="btn btn-ghost btn-sm" onClick={() => { setSupTab('docs'); setSearchView(''); }}><Icon name="search" size={13}/>Search docs…</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>Submit a Ticket</button>
        </>}/>

      <div className="sub-tabs" role="tablist">
        {[
          ['docs',    '📚 Documentation'],
          ['ai',      '🤖 AI Chat'],
          ['tickets', `🎫 My Tickets (${tickets.filter(t => t.status !== 'closed').length})`],
          ['bugs',    '🐞 Report a Bug'],
        ].map(([id, lbl]) => (
          <button key={id} className={'sub-tab' + (supTab === id ? ' active' : '')} onClick={() => setSupTab(id)}>{lbl}</button>
        ))}
      </div>

      {supTab === 'docs' && docView === null && searchView === null && (
        <>
          <div className="card" style={{ marginTop:16 }}>
            <div className="card-body" style={{ display:'flex', alignItems:'center', gap:14, padding:20 }}>
              <div style={{ width:48, height:48, borderRadius:10, background:'var(--orange-dim)', color:'var(--orange)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'1.4rem' }}>🔎</div>
              <div style={{ flex:1 }}>
                <input placeholder="Search 124 articles, guides, and API docs… (press Enter)"
                  onKeyDown={e => { if (e.key === 'Enter') setSearchView(e.target.value || ''); }}
                  style={{ width:'100%', fontSize:'.92rem' }}/>
              </div>
              <button className="btn btn-primary btn-sm" onClick={() => setSearchView('')}>Browse archive →</button>
            </div>
          </div>
          <h3 style={{ margin:'20px 0 10px', fontSize:'.88rem', color:'var(--text-2)', fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.08em' }}>📚 Documentation &amp; Resources</h3>
          <div className="grid" style={{ gridTemplateColumns:'repeat(auto-fill, minmax(240px, 1fr))', alignItems:'stretch' }}>
            {docs.map(d => (
              <a key={d.slug} href="#" onClick={e => { e.preventDefault(); setDocView(d.slug); }} className="card" style={{ textDecoration:'none', cursor:'pointer', transition:'border-color .15s, transform .15s', display:'flex' }}>
                <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:8, flex:1, width:'100%' }}>
                  <div style={{ fontSize:'1.8rem', lineHeight:1, height:32 }}>{d.emoji}</div>
                  <div style={{ fontWeight:700, fontSize:'.94rem', color:'var(--text)', minHeight:'2.6em', lineHeight:1.3 }}>{d.t}</div>
                  <div style={{ fontSize:'.78rem', color:'var(--dim)', lineHeight:1.5, flex:1 }}>{d.d}</div>
                  <div style={{ color:'var(--beam)', fontSize:'.78rem', fontWeight:600, marginTop:'auto', paddingTop:6 }}>Open →</div>
                </div>
              </a>
            ))}
          </div>
        </>
      )}

      {supTab === 'docs' && docView !== null && (
        <DocDetail slug={docView} docs={docs} onBack={() => setDocView(null)}/>
      )}

      {supTab === 'docs' && searchView !== null && docView === null && (
        <DocSearchArchive initialQuery={searchView} docs={docs} onBack={() => setSearchView(null)} onOpenDoc={slug => { setSearchView(null); setDocView(slug); }}/>
      )}

      {supTab === 'ai' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-head">
            <h2 className="card-title">🤖 AI Support Chat</h2>
            <span className="tag beam">SUPPORT BRAIN</span>
          </div>
          <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:12, minHeight:320 }}>
            <div style={{ display:'flex', gap:10 }}>
              <div style={{ width:28, height:28, borderRadius:'50%', background:'var(--beam-dim)', color:'var(--beam)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'.8rem' }}>🤖</div>
              <div style={{ flex:1, padding:'10px 14px', background:'var(--surface-3)', borderRadius:'12px 12px 12px 2px', fontSize:'.86rem', lineHeight:1.55 }}>
                Hi Jordan — I'm your AI support agent. I can help with scanning, estimator, DNS, billing questions, and can open a ticket for complex issues. What's up?
              </div>
            </div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
              {['Why did my scan fail?','How do I export the brand kit?','Set up a redirect','Upgrade my plan'].map(s => (
                <button key={s} className="btn btn-ghost btn-sm" style={{ fontSize:'.74rem' }}>{s}</button>
              ))}
            </div>
            <div style={{ flex:1 }}/>
            <div style={{ display:'flex', gap:8 }}>
              <input placeholder="Ask anything…" style={{ flex:1 }}/>
              <button className="btn btn-primary"><Icon name="spark" size={13}/>Send</button>
            </div>
            <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)', textAlign:'center' }}>Powered by Support Brain · If AI can't resolve, you'll be offered to open a ticket</div>
          </div>
        </div>
      )}

      {supTab === 'tickets' && (
        <>
          <div className="box info" style={{ marginTop:16, marginBottom:16 }}>
            <Icon name="info" size={16}/>
            <div>Our team responds within <strong>1 business day</strong>. For urgent production issues, mark the ticket High and we'll page on-call.</div>
          </div>
          <div className="card">
            <div className="card-head">
              <h2 className="card-title">My Tickets</h2>
              <div style={{ display:'flex', gap:6 }}>
                <button className="btn btn-ghost btn-sm">Filter</button>
                <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>Submit a Ticket</button>
              </div>
            </div>
            <div className="card-body" style={{ padding:0 }}>
              <table className="table">
                <thead><tr><th scope="col">Ticket</th><th scope="col">Subject</th><th scope="col">Priority</th><th scope="col">Status</th><th scope="col">Created</th><th scope="col">Updated</th><th scope="col"></th></tr></thead>
                <tbody>
                  {tickets.map(t => (
                    <tr key={t.id}>
                      <td className="mono" style={{ color:'var(--muted)', fontSize:'.74rem' }}>{t.id}</td>
                      <td style={{ fontWeight:500 }}>{t.subj}</td>
                      <td><span className={`tag ${t.pri==='high'?'bad':t.pri==='med'?'warn':''}`}>{t.pri.toUpperCase()}</span></td>
                      <td><span className={`tag ${tone[t.status]}`}>{t.status.toUpperCase()}</span></td>
                      <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{t.created}</td>
                      <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{t.updated}</td>
                      <td><a href="#" onClick={e=>e.preventDefault()}>Open</a></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </>
      )}

      {supTab === 'bugs' && (
        <>
          <div className="card" style={{ marginTop:16 }}>
            <div className="card-head"><h2 className="card-title">🐞 Report a Bug</h2></div>
            <div className="card-body">
              <div className="grid grid-2" style={{ gridAutoRows:'auto' }}>
                <Field label="Title"><input placeholder="Short summary"/></Field>
                <Field label="Severity">
              <div className="tw-seg" role="group" aria-label="Severity">
                    {['Low','Medium','High','Critical'].map(s => <button key={s} className={s==='Medium'?'active':''}>{s}</button>)}
                  </div>
            </Field>
                <Field label="Where did it happen?">
              <select><option>Scanner</option><option>Estimator</option><option>Sites</option><option>Billing</option><option>Other</option></select>
            </Field>
                <Field label="Browser / OS"><input placeholder="Chrome 128 · macOS 14.5"/></Field>
              </div>
              <Field label="Steps to reproduce">
              <textarea rows={4} placeholder="1. Go to…&#10;2. Click…&#10;3. Expected vs actual"/>
            </Field>
              <Field label="Attach screenshot">
                <div style={{ padding:18, border:'1px dashed var(--border-2)', borderRadius:8, textAlign:'center', color:'var(--dim)', fontSize:'.8rem' }}>
                  Drop image or paste from clipboard
                </div>
              </Field>
              <button className="btn btn-primary"><Icon name="check" size={13}/>Submit Bug Report</button>
            </div>
          </div>

          <div className="card" style={{ marginTop:16 }}>
            <div className="card-head"><h2 className="card-title">Recent bugs</h2><span className="tag">{bugs.length} OPEN</span></div>
            <div className="card-body" style={{ padding:0 }}>
              <table className="table">
                <thead><tr><th scope="col">ID</th><th scope="col">Title</th><th scope="col">Severity</th><th scope="col" style={{textAlign:'right'}}>Votes</th><th scope="col">Status</th></tr></thead>
                <tbody>
                  {bugs.map(b => (
                    <tr key={b.id}>
                      <td className="mono" style={{ fontSize:'.74rem', color:'var(--muted)' }}>{b.id}</td>
                      <td style={{ fontWeight:500 }}>{b.t}</td>
                      <td><span className={`tag ${b.sev==='high'?'bad':b.sev==='med'?'warn':''}`}>{b.sev.toUpperCase()}</span></td>
                      <td className="mono" style={{ textAlign:'right' }}>▲ {b.votes}</td>
                      <td><span className={`tag ${tone[b.status] || ''}`}>{b.status.replace('-',' ').toUpperCase()}</span></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ── FEATURE REQUESTS ──────────────────────────────────────────
   Votes are persistent per-user (localStorage). Submit-idea opens a
   modal that routes to the SA "Requests" backend queue for triage. */
function Requests() {
  const { useState, useEffect } = React;
  const s = window.WPSBD?.state || { role: 'customer' };
  const isSA = s.role === 'sa';
  const isAdmin = s.role === 'admin' || isSA;

  /* Real WPSiteBeam roadmap items — seeded with actual features at their
     current development status. Customers vote to influence priority of
     planned items. Updated 2026-05-19. */
  const seed = [
    /* SHIPPED — major recent ones, builds trust that we deliver */
    { id:'shipped-scanner',      t:'Multi-platform site scanner',         baseVotes:0, status:'shipped',    submitters:0, desc:'Scans 10 platforms (WordPress, Squarespace, Wix, Webflow, Shopify, Joomla, Drupal, Ghost, Duda, Weebly) for health, brand, SEO, and accessibility.' },
    { id:'shipped-ada',          t:'WCAG 2.1 AA accessibility audits',    baseVotes:0, status:'shipped',    submitters:0, desc:'Full accessibility scans with axe-core + custom rules, PDF reports, and remediation checklists.' },
    { id:'shipped-brand',        t:'Automated brand extraction',          baseVotes:0, status:'shipped',    submitters:0, desc:'Pulls logo, colors, fonts, and contact info from any site URL — used for kit generation and proposals.' },
    { id:'shipped-plugin',       t:'WordPress plugin write-back',         baseVotes:0, status:'shipped',    submitters:0, desc:'Apply changes back to connected WP sites: redirects, alt text, Elementor kits, content migration.' },
    { id:'shipped-kit-gen',      t:'Elementor kit generation from brand', baseVotes:0, status:'shipped',    submitters:0, desc:'Generate a downloadable Elementor kit (colors + typography) from any brand profile — one click.' },
    { id:'shipped-dashboard',    t:'Real-time multi-site dashboard',      baseVotes:0, status:'shipped',    submitters:0, desc:'See all connected sites, plugin versions, last sync, and recent activity in one place.' },

    /* IN REVIEW — code exists, polish/testing remaining */
    { id:'review-2fa',           t:'Two-factor authentication (TOTP)',    baseVotes:18, status:'in-review',  submitters:6,  desc:'Authenticator app support (1Password, Google Authenticator, Authy) with recovery codes. Required for admin roles.' },
    { id:'review-stripe',        t:'Self-serve billing portal',           baseVotes:14, status:'in-review',  submitters:4,  desc:'Update payment method, download invoices, manage subscription — all via Stripe Customer Portal.' },
    { id:'review-content-mig',   t:'Cross-site content migration',        baseVotes:11, status:'in-review',  submitters:3,  desc:'Move posts/pages between WordPress sites with one click — preserves featured images, taxonomies, metadata.' },

    /* PLANNED — designed, on the dev queue */
    { id:'planned-stats',        t:'Platform metrics + embeddable widgets', baseVotes:22, status:'planned',  submitters:5,  desc:'Track plugin installs, scans, migrations, etc. Embeddable counter widgets for agency marketing sites.' },
    { id:'planned-passkeys',     t:'Passkey / biometric login',           baseVotes:17, status:'planned',    submitters:4,  desc:'Face ID / Touch ID / Windows Hello support. No passwords, no codes, just your device.' },
    { id:'planned-rag',          t:'AI assistant trained on your sites',  baseVotes:31, status:'planned',    submitters:9,  desc:'Ask questions like "what plugins need updating?" or "draft an estimate for a Squarespace migration". Knows your portfolio.' },
    { id:'planned-acquisition',  t:'Acquisition mode for agency growth',  baseVotes:13, status:'planned',    submitters:3,  desc:'Find + score prospective clients by scanning their sites, brand maturity, and tech stack.' },
    { id:'planned-slack',        t:'Slack / Discord scan notifications',  baseVotes:24, status:'planned',    submitters:8,  desc:'Real-time DMs when scheduled scans fail, plugin updates land, or SSL expiring soon.' },

    /* UNDER REVIEW — community-suggested, evaluating feasibility */
    { id:'review-team-roles',    t:'Team-level role permissions',         baseVotes:19, status:'in-review',  submitters:3,  desc:'Granular per-team role overrides without creating full custom roles.' },
    { id:'review-lighthouse',    t:'Auto-resolve Lighthouse perf issues', baseVotes:15, status:'under-consideration', submitters:4, desc:'One-click auto-fix for common Lighthouse perf flags (image compression, lazy-load, defer).' },
    { id:'review-staging-diff',  t:'Staging site diff mode',              baseVotes:28, status:'under-consideration', submitters:12, desc:'Side-by-side visual diff between staging and production.' },
  ];
  const tone = { planned:'beam', 'in-review':'warn', shipped:'ok', 'under-consideration':'tag' };
  const statusLbl = { planned:'PLANNED', 'in-review':'IN REVIEW', shipped:'SHIPPED', 'under-consideration':'UNDER REVIEW' };

  /* Per-user vote state: { [id]: true } */
  const [votes, setVotes] = useState(() => {
    try { return JSON.parse(localStorage.getItem('wpsbd-req-votes') || '{}'); } catch { return {}; }
  });
  /* User-submitted ideas — persisted, show on top with UNDER REVIEW status */
  const [submitted, setSubmitted] = useState(() => {
    try { return JSON.parse(localStorage.getItem('wpsbd-req-submitted') || '[]'); } catch { return []; }
  });
  useEffect(() => { localStorage.setItem('wpsbd-req-votes', JSON.stringify(votes)); }, [votes]);
  useEffect(() => { localStorage.setItem('wpsbd-req-submitted', JSON.stringify(submitted)); }, [submitted]);

  const [modalOpen, setModalOpen] = useState(false);
  const [sort, setSort] = useState('votes');  /* 'votes' | 'newest' | 'status' */
  const [filter, setFilter] = useState('all');

  const items = [...submitted, ...seed].map(it => ({
    ...it,
    votes: (it.baseVotes || 0) + (votes[it.id] ? 1 : 0),
  }));
  const filtered = items.filter(it => filter === 'all' || it.status === filter);
  const sorted = [...filtered].sort((a, b) => {
    if (sort === 'votes')  return b.votes - a.votes;
    if (sort === 'newest') return b.id.localeCompare(a.id);
    return a.status.localeCompare(b.status);
  });

  function toggleVote(id) {
    setVotes(v => ({ ...v, [id]: !v[id] }));
    const live = document.getElementById('wpsbd-live');
    if (live) live.textContent = votes[id] ? 'Vote removed' : 'Vote recorded';
  }
  function submitIdea(draft) {
    const newItem = {
      id: `req-user-${Date.now()}`,
      t: draft.title,
      desc: draft.desc,
      category: draft.category,
      baseVotes: 1,
      status: 'under-consideration',
      submitters: 1,
      submittedBy: 'You',
      submittedAt: new Date().toISOString(),
    };
    setSubmitted(prev => [newItem, ...prev]);
    setVotes(v => ({ ...v, [newItem.id]: true }));
    setModalOpen(false);
    const live = document.getElementById('wpsbd-live');
    if (live) live.textContent = `Idea submitted: ${draft.title}. Routed to product triage.`;
  }

  return (
    <div>
      <PageHead crumb="Product" title="🗺️ Roadmap"
        sub="What we're building, what's coming, and what's shipped. Submit ideas, vote on what matters, track status from triage to ship."
        actions={<button className="btn btn-primary btn-sm" onClick={() => setModalOpen(true)}>
          <Icon name="plus" size={14}/>Submit idea
        </button>}/>

      {/* Routing explainer — confirms feedback loop into SA/Admin backend */}
      <div className="box info" style={{ marginBottom:16 }}>
        <Icon name="info" size={16}/>
        <div>
          <strong>How this works.</strong> Your idea routes to <span className="tag sa" style={{ fontSize:'.62rem' }}>SA · REQUESTS</span> queue
          where product triage reviews weekly. Votes count toward prioritization.
          Status updates post back here automatically, and you'll get an email when your idea ships.
        </div>
      </div>

      {/* ── SA ROADMAP MANAGEMENT PANEL ─────────────────────── */}
      {isSA && <SARoadmapPanel items={items} />}

      {/* Filter + sort bar */}
      <div className="card" style={{ marginBottom:12 }}>
        <div className="card-body" style={{ display:'flex', gap:10, alignItems:'center', flexWrap:'wrap', padding:'10px 14px' }}>
          <div style={{ display:'flex', gap:4 }}>
            {[['all','All'],['under-consideration','New'],['in-review','Review'],['planned','Planned'],['shipped','Shipped']].map(([v,l]) => (
              <button key={v} className={'btn btn-sm ' + (filter===v ? 'btn-primary' : 'btn-ghost')} onClick={() => setFilter(v)}>{l}</button>
            ))}
          </div>
          <div style={{ flex:1 }}/>
          <span className="mono" style={{ fontSize:'.68rem', color:'var(--dim)' }}>SORT BY</span>
          <select value={sort} onChange={e => setSort(e.target.value)} style={{ padding:'4px 8px', fontSize:'.78rem' }}>
            <option value="votes">Most votes</option>
            <option value="newest">Newest</option>
            <option value="status">Status</option>
          </select>
          <span className="mono" style={{ fontSize:'.68rem', color:'var(--dim)' }}>{sorted.length} REQUESTS</span>
        </div>
      </div>

      <div className="card">
        <div className="card-body" style={{ padding: 0 }}>
          {sorted.length === 0 && (
            <div style={{ padding:'40px 20px', textAlign:'center', color:'var(--dim)' }}>
              <div style={{ fontSize:'.9rem', fontWeight:600 }}>No requests match this filter.</div>
            </div>
          )}
          {sorted.map((it, i) => {
            const voted = !!votes[it.id];
            return (
              <div key={it.id} style={{ display:'flex', alignItems:'flex-start', gap:14, padding:'16px 18px', borderBottom: i<sorted.length-1 ? '1px solid var(--border)' : 'none' }}>
                <button
                  onClick={() => toggleVote(it.id)}
                  aria-pressed={voted}
                  aria-label={`${voted ? 'Remove vote from' : 'Vote for'} ${it.t}, currently ${it.votes} votes`}
                  style={{
                    display:'flex', flexDirection:'column', alignItems:'center', gap:2,
                    padding:'8px 12px', minWidth:56,
                    border: `1.5px solid ${voted ? 'var(--orange)' : 'var(--border)'}`,
                    background: voted ? 'var(--warn-dim)' : 'var(--surface-2)',
                    color: voted ? 'var(--orange)' : 'var(--text)',
                    borderRadius:6, cursor:'pointer', transition:'all .15s ease',
                    fontFamily:'var(--font-mono)',
                  }}>
                  <Icon name="chevron" size={11} style={{ transform:'rotate(180deg)' }}/>
                  <span style={{ fontSize:'.82rem', fontWeight:700 }}>{it.votes}</span>
                </button>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontWeight:600, fontSize:'.9rem', marginBottom:3 }}>{it.t}</div>
                  {it.desc && <div style={{ fontSize:'.76rem', color:'var(--dim)', marginBottom:5, lineHeight:1.45 }}>{it.desc}</div>}
                  <div style={{ fontSize:'.7rem', color:'var(--dim)', display:'flex', gap:8, flexWrap:'wrap' }}>
                    <span>Submitted by {it.submitters || 1} {it.submitters === 1 ? 'customer' : 'customers'}</span>
                    {it.submittedBy && <span>· {it.submittedBy}</span>}
                    {it.category && <span>· {it.category}</span>}
                  </div>
                </div>
                <span className={`tag ${tone[it.status] || 'tag'}`} style={{ flexShrink:0, marginTop:2 }}>{statusLbl[it.status] || it.status.toUpperCase()}</span>
              </div>
            );
          })}
        </div>
      </div>

      {modalOpen && <SubmitIdeaModal onClose={() => setModalOpen(false)} onSubmit={submitIdea}/>}
    </div>
  );
}

/* ── SA ROADMAP MANAGEMENT PANEL ─────────────────────────────
   SA-only view: move items between buckets (New / Review / Planned /
   Building / Shipped), add internal dev notes, bulk-promote.
*/
function SARoadmapPanel({ items }) {
  const { useState } = React;
  const [collapsed, setCollapsed] = useState(false);
  const [view, setView] = useState('buckets'); // 'buckets' | 'devqueue'

  const byStatus = (st) => items.filter(it => it.status === st);
  const buckets = [
    { id:'under-consideration', lbl:'INBOX',    tone:'',      count: byStatus('under-consideration').length, color:'var(--dim)' },
    { id:'in-review',           lbl:'REVIEW',   tone:'warn',  count: byStatus('in-review').length,           color:'var(--warn)' },
    { id:'planned',             lbl:'PLANNED',  tone:'beam',  count: byStatus('planned').length,             color:'var(--beam)' },
    { id:'building',            lbl:'BUILDING', tone:'sa',    count: items.filter(i => i.status === 'building').length, color:'var(--rose)' },
    { id:'shipped',             lbl:'SHIPPED',  tone:'ok',    count: byStatus('shipped').length,             color:'var(--ok)' },
  ];

  const devQueue = [
    { t:'T-086: Partner/ads section promo cards',     pr:'p2', owner:'@cd',   eta:'v0.7.1' },
    { t:'T-085: Support tab redesign + smart search', pr:'p1', owner:'@cd',   eta:'v0.7.0' },
    { t:'T-084: Plugin theme sync with SaaS profile', pr:'p2', owner:'@ai',   eta:'v0.7.2' },
    { t:'T-083: White-label cover theme picker',      pr:'p1', owner:'@cd',   eta:'v0.7.0' },
    { t:'T-058: Brand package ZIP download',          pr:'p1', owner:'@cd',   eta:'v0.7.1' },
    { t:'T-057: SSO — agency team member login',      pr:'p1', owner:'@ai',   eta:'v0.7.0' },
  ];
  const prTone = { p0:'bad', p1:'warn', p2:'', p3:'' };

  return (
    <div className="card sa" style={{ marginBottom:14, borderColor:'var(--rose)', borderWidth:1.5 }}>
      <div className="card-head" style={{ background:'var(--rose-dim)' }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, flex:1 }}>
          <span className="tag sa">SA ONLY</span>
          <h2 className="card-title" style={{ fontSize:'.88rem' }}>🗺️ Roadmap Management</h2>
          <span style={{ fontSize:'.72rem', color:'var(--dim)' }}>· Triage inbox, promote ideas, view dev queue</span>
        </div>
        <div style={{ display:'flex', gap:4 }}>
          <button className={'btn btn-sm ' + (view === 'buckets' ? 'btn-primary' : 'btn-ghost')} onClick={() => setView('buckets')}>Kanban</button>
          <button className={'btn btn-sm ' + (view === 'devqueue' ? 'btn-primary' : 'btn-ghost')} onClick={() => setView('devqueue')}>Dev queue</button>
          <button className="btn btn-ghost btn-sm" onClick={() => setCollapsed(c => !c)}>
            <Icon name="chevron" size={12} style={{ transform: collapsed ? 'rotate(0deg)' : 'rotate(180deg)' }}/>
          </button>
        </div>
      </div>
      {!collapsed && (
        <div className="card-body">
          {view === 'buckets' && (
            <>
              <div className="grid grid-5" style={{ gap:8 }}>
                {buckets.map(b => (
                  <div key={b.id} style={{
                    padding:'12px 10px', borderRadius:8,
                    background:'var(--surface-2)',
                    border:'1px solid var(--border)',
                    borderTop:`3px solid ${b.color}`,
                  }}>
                    <div style={{ fontSize:'.66rem', color:'var(--muted)', letterSpacing:1, fontFamily:'var(--font-mono)', marginBottom:4 }}>{b.lbl}</div>
                    <div style={{ fontSize:'1.5rem', fontWeight:800, color: b.color }}>{b.count}</div>
                    <div style={{ fontSize:'.68rem', color:'var(--dim)', marginTop:2 }}>items</div>
                  </div>
                ))}
              </div>
              <div style={{ marginTop:12, display:'flex', gap:6, flexWrap:'wrap' }}>
                <button className="btn btn-ghost btn-sm"><Icon name="check" size={12}/>Triage inbox ({byStatus('under-consideration').length})</button>
                <button className="btn btn-ghost btn-sm"><Icon name="refresh" size={12}/>Auto-promote by votes (≥10)</button>
                <button className="btn btn-ghost btn-sm"><Icon name="external" size={12}/>Open full roadmap admin</button>
                <button className="btn btn-ghost btn-sm"><Icon name="download" size={12}/>Export CSV</button>
              </div>
            </>
          )}
          {view === 'devqueue' && (
            <div style={{ padding:0 }}>
              <div style={{ fontSize:'.72rem', color:'var(--muted)', marginBottom:10 }}>
                Internal dev queue · linked to <strong>Teamwork → WPSB / Dev</strong> project · <span className="tag">6 ACTIVE</span>
              </div>
              <table className="table">
                <thead>
                  <tr>
                    <th style={{ width:60 }}>Priority</th>
                    <th>Task</th>
                    <th style={{ width:80 }}>Owner</th>
                    <th style={{ width:80 }}>Target</th>
                    <th style={{ width:60 }}></th>
                  </tr>
                </thead>
                <tbody>
                  {devQueue.map((task, i) => (
                    <tr key={i}>
                      <td><span className={'tag ' + prTone[task.pr]} style={{ fontSize:'.62rem' }}>{task.pr.toUpperCase()}</span></td>
                      <td style={{ fontSize:'.82rem' }}>{task.t}</td>
                      <td className="mono" style={{ fontSize:'.74rem' }}>{task.owner}</td>
                      <td className="mono" style={{ fontSize:'.72rem', color:'var(--beam)' }}>{task.eta}</td>
                      <td><button className="btn btn-ghost btn-sm" style={{ padding:'2px 8px', fontSize:'.7rem' }}>Edit</button></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function SubmitIdeaModal({ onClose, onSubmit }) {
  const { useState } = React;
  const [title, setTitle] = useState('');
  const [desc, setDesc]   = useState('');
  const [cat, setCat]     = useState('general');

  function submit(e) {
    e.preventDefault();
    if (!title.trim()) return;
    onSubmit({ title: title.trim(), desc: desc.trim(), category: cat });
  }

  return (
    <div role="dialog" aria-modal="true" aria-labelledby="submit-idea-title"
      onClick={onClose}
      style={{
        position:'fixed', inset:0, background:'rgba(0,0,0,0.6)', zIndex:1000,
        display:'flex', alignItems:'center', justifyContent:'center', padding:20,
      }}>
      <form onClick={e => e.stopPropagation()} onSubmit={submit}
        style={{
          background:'var(--surface)', border:'1px solid var(--border)', borderRadius:10,
          maxWidth:560, width:'100%', boxShadow:'0 20px 48px rgba(0,0,0,.6)',
        }}>
        <div style={{ padding:'16px 20px', borderBottom:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
          <h2 id="submit-idea-title" style={{ margin:0, fontSize:'1rem', fontWeight:700 }}>Submit an idea</h2>
          <button type="button" className="icon-btn" onClick={onClose} aria-label="Close dialog"><Icon name="x" size={14}/></button>
        </div>
        <div style={{ padding:'16px 20px', display:'flex', flexDirection:'column', gap:12 }}>
          <div className="box" style={{ background:'var(--surface-2)', fontSize:'.76rem', color:'var(--dim)' }}>
            <Icon name="info" size={13}/>
            <span>Your idea routes to the <strong>SA Requests queue</strong>. You'll be auto-subscribed and notified on status changes.</span>
          </div>
          <Field label="Title" required hint="Keep it concise — one clear sentence">
            <input value={title} onChange={e => setTitle(e.target.value)} placeholder="e.g. Auto-resolve Lighthouse perf flags" autoFocus/>
          </Field>
          <Field label="Category">
            <select value={cat} onChange={e => setCat(e.target.value)}>
              <option value="general">General</option>
              <option value="scanner">Scanner / Audit</option>
              <option value="estimator">Estimator</option>
              <option value="dashboard">Dashboard / Reporting</option>
              <option value="integrations">Integrations</option>
              <option value="billing">Billing / Plans</option>
              <option value="brand">Brand tools</option>
            </select>
          </Field>
          <Field label="Description" hint="What problem does this solve? Who benefits?">
            <textarea value={desc} onChange={e => setDesc(e.target.value)} rows={4} placeholder="Give us context — use case, why it matters, how you'd use it…"/>
          </Field>
        </div>
        <div style={{ padding:'14px 20px', borderTop:'1px solid var(--border)', display:'flex', justifyContent:'flex-end', gap:8 }}>
          <button type="button" className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
          <button type="submit" className="btn btn-primary btn-sm" disabled={!title.trim()}>
            <Icon name="check" size={13}/>Submit idea
          </button>
        </div>
      </form>
    </div>
  );
}

/* ── SCANNER ─────────────────────────────────────────────────── */
function Scanner() {
  const [url, setUrl] = useState('https://acme.co');
  const [scanning, setScanning] = useState(false);
  const [done, setDone] = useState(false);
  function run() {
    setScanning(true); setDone(false);
    setTimeout(() => { setScanning(false); setDone(true); }, 1400);
  }
  const scores = [
    { lbl: 'Brand consistency', v: 87, t: 'ok' },
    { lbl: 'Performance',       v: 72, t: 'warn' },
    { lbl: 'SEO basics',        v: 94, t: 'ok' },
    { lbl: 'Accessibility',     v: 68, t: 'warn' },
  ];
  return (
    <div>
      <PageHead crumb="Operations" title="Brand Scanner" sub="AI-powered audit of brand, performance, and SEO — powered by WPSiteBeam Brain."/>
      <div className="card">
        <div className="card-body" style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
          <div className="field" style={{ flex:'1 1 300px', margin:0 }}>
            <label>Site URL</label>
            <input value={url} onChange={e => setUrl(e.target.value)}/>
          </div>
          <div style={{ alignSelf:'flex-end' }}>
            <button className="btn btn-primary" onClick={run} disabled={scanning}>
              <Icon name={scanning ? 'activity' : 'scanner'} size={14}/>
              {scanning ? 'Scanning…' : 'Run scan'}
            </button>
          </div>
        </div>
      </div>

      {(scanning || done) && (
        <>
          <div className="grid grid-4" style={{ marginTop: 16 }}>
            {scores.map(s => (
              <div key={s.lbl} className="stat">
                <div className="stat-lbl">{s.lbl}</div>
                <div className={`stat-val ${s.t}`}>{scanning ? '—' : s.v}</div>
                <div style={{ height: 4, background:'var(--surface-3)', borderRadius:2, marginTop:4, overflow:'hidden' }}>
                  <div style={{ height:'100%', width: (scanning ? 0 : s.v) + '%', background: `var(--${s.t === 'warn' ? 'warn' : 'green'})`, transition:'width .8s ease' }}/>
                </div>
              </div>
            ))}
          </div>
          {done && (
            <div className="card" style={{ marginTop: 16 }}>
              <div className="card-head"><h2 className="card-title">Top recommendations</h2><span className="tag beam">AI</span></div>
              <div className="card-body">
                {[
                  ['Compress hero image (saves 1.2MB)',  'Performance'],
                  ['Increase button contrast on /pricing', 'Accessibility'],
                  ['Align footer logo lockup with brand spec', 'Brand consistency'],
                ].map(([txt, cat]) => (
                  <div key={txt} style={{ display:'flex', gap:12, padding:'10px 0', borderBottom:'1px solid var(--border)' }}>
                    <div style={{ width:26, height:26, borderRadius:6, background:'var(--beam-dim)', color:'var(--beam)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                      <Icon name="spark" size={14}/>
                    </div>
                    <div style={{ flex:1 }}>
                      <div style={{ fontSize:'.88rem', fontWeight:600 }}>{txt}</div>
                      <div style={{ fontSize:'.72rem', color:'var(--dim)' }}>{cat}</div>
                    </div>
                    <button className="btn btn-ghost btn-sm">View fix</button>
                  </div>
                ))}
              </div>
            </div>
          )}
        </>
      )}
    </div>
  );
}

/* ── WORKSPACE (team) ────────────────────────────────────────
   PM integrations (Teamwork primary, Monday/Asana/Basecamp/ClickUp/Trello/Jira secondary),
   Slack + Freshdesk chat, and a live demo of CD's actual projects.
*/
function Workspace() {
  const { useState } = React;
  const [tab, setTab] = useState('integrations');
  const [connected, setConnected] = useState({ teamwork: true, slack: false, freshdesk: false });

  const pmTools = [
    { id:'teamwork',  name:'Teamwork',   icon:'📋', color:'#ff6b45', status:'CONNECTED',  desc:'Primary PM · Projects, tasks, milestones, time', url:'https://wpsitebeam.teamwork.com', projects:18, openTasks:142 },
    { id:'monday',    name:'Monday.com', icon:'📊', color:'#ff3d57', status:'AVAILABLE',   desc:'Visual workflows, boards, automations' },
    { id:'asana',     name:'Asana',      icon:'✅', color:'#f06a6a', status:'AVAILABLE',   desc:'Lists, timelines, portfolio tracking' },
    { id:'basecamp',  name:'Basecamp',   icon:'🏕️', color:'#5ac058', status:'AVAILABLE',   desc:'To-dos, messages, schedules, docs' },
    { id:'clickup',   name:'ClickUp',    icon:'⚡', color:'#7b68ee', status:'AVAILABLE',   desc:'All-in-one productivity suite' },
    { id:'trello',    name:'Trello',     icon:'📌', color:'#0079bf', status:'AVAILABLE',   desc:'Kanban boards, cards, power-ups' },
    { id:'jira',      name:'Jira',       icon:'🎯', color:'#2684ff', status:'AVAILABLE',   desc:'Agile sprints, epics, tickets (dev-heavy)' },
    { id:'notion',    name:'Notion',     icon:'📝', color:'#000',    status:'AVAILABLE',   desc:'Docs + lightweight project tracking' },
    { id:'linear',    name:'Linear',     icon:'📐', color:'#5e6ad2', status:'AVAILABLE',   desc:'Modern issue tracking for software teams' },
    { id:'slack',     name:'Slack',      icon:'💬', color:'#4a154b', status:connected.slack ? 'CONNECTED' : 'AVAILABLE', desc:'Team chat + notifications' },
    { id:'freshdesk', name:'Freshdesk',  icon:'🎧', color:'#25c16f', status:connected.freshdesk ? 'CONNECTED' : 'AVAILABLE', desc:'Ticket sync to customer portal' },
    { id:'ghl',       name:'GoHighLevel',icon:'🔗', color:'#00c48c', status:'CONNECTED',   desc:'CRM · proposals · email automation' },
  ];

  // Demo projects from CD's Teamwork workspace
  const cdProjects = [
    { name:'Riverway Health Portal',     client:'Riverway Health',  status:'active',  progress:68, tasks:{ open:14, done:38 }, due:'Dec 18', team:['KJ','MR','SP'] },
    { name:'Oakline Civic Site Rebuild', client:'Oakline Township', status:'active',  progress:42, tasks:{ open:22, done:16 }, due:'Jan 15', team:['KJ','AT'] },
    { name:'Studio Amberleaf Rebrand',   client:'Studio Amberleaf', status:'review',  progress:88, tasks:{ open:3,  done:27 }, due:'Dec 12', team:['MR','SP'] },
    { name:'Grove Academy LMS',          client:'Grove Academy',    status:'active',  progress:31, tasks:{ open:28, done:13 }, due:'Feb 07', team:['KJ','AT','MR','SP'] },
    { name:'Mint & Fern eCommerce',      client:'Mint & Fern',      status:'paused',  progress:55, tasks:{ open:8,  done:22 }, due:'TBD',    team:['MR'] },
    { name:'Harbor Finance Blog',        client:'Harbor Finance',   status:'complete',progress:100,tasks:{ open:0,  done:45 }, due:'Nov 28', team:['KJ','AT'] },
  ];
  const statusTone = { active:'ok', review:'warn', paused:'', complete:'beam' };

  const activity = [
    { u:'Kara (KJ)',    t:'moved task', x:'Homepage hero variant B → Done',            w:'Riverway Health Portal',       ago:'12m' },
    { u:'Maya (MR)',    t:'commented',  x:'"Need client feedback on the logo colors"', w:'Studio Amberleaf Rebrand',     ago:'38m' },
    { u:'Austin (AT)',  t:'logged',     x:'2.5 hrs · Municipal form builder',          w:'Oakline Civic Site Rebuild',   ago:'1h' },
    { u:'Sam (SP)',     t:'completed',  x:'Mobile nav accessibility audit',            w:'Grove Academy LMS',            ago:'2h' },
    { u:'Kara (KJ)',    t:'created',    x:'New milestone: "Launch Week"',              w:'Riverway Health Portal',       ago:'3h' },
    { u:'Maya (MR)',    t:'uploaded',   x:'3 files to Brand assets',                   w:'Studio Amberleaf Rebrand',     ago:'5h' },
  ];

  return (
    <div>
      <PageHead crumb="Workspace" title="💬 Team Workspace"
        sub="Project management, team chat, and integration hub. Teamwork is primary PM — sync projects, tasks, and time tracking directly."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="refresh" size={13}/>Sync all</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>New project</button>
        </>}/>

      <div className="sub-tabs" role="tablist">
        {[
          ['integrations','🔌 Integrations'],
          ['projects',    '📋 Projects (6 active)'],
          ['chat',        '💬 Team Chat'],
          ['activity',    '📊 Activity'],
        ].map(([id,lbl]) => (
          <button key={id} role="tab" aria-selected={tab===id} className={'sub-tab' + (tab===id?' active':'')} onClick={()=>setTab(id)}>{lbl}</button>
        ))}
      </div>

      {tab === 'integrations' && (
        <div style={{ marginTop:16 }}>
          <div className="box info" style={{ marginBottom:14 }}>
            <Icon name="info" size={16}/>
            <div>Connect your team's existing PM tool — we'll sync projects, tasks, time logs, and comments. <strong>Teamwork</strong> has deepest integration (2-way sync). Others are read-only until we build 2-way adapters.</div>
          </div>

          <div className="grid grid-3" style={{ gap:12 }}>
            {pmTools.map(tool => {
              const isConnected = tool.status === 'CONNECTED';
              return (
                <div key={tool.id} className="card" style={{
                  borderColor: isConnected ? 'var(--ok)' : 'var(--border)',
                  background: isConnected ? 'rgba(52, 211, 153, 0.04)' : 'var(--surface-2)',
                }}>
                  <div className="card-body" style={{ padding:14 }}>
                    <div style={{ display:'flex', alignItems:'flex-start', gap:12 }}>
                      <div style={{
                        width:44, height:44, borderRadius:10, flexShrink:0,
                        background: tool.color + '20', color: tool.color,
                        display:'flex', alignItems:'center', justifyContent:'center',
                        fontSize:'1.4rem',
                      }}>{tool.icon}</div>
                      <div style={{ flex:1, minWidth:0 }}>
                        <div style={{ display:'flex', alignItems:'center', gap:6, justifyContent:'space-between' }}>
                          <strong style={{ fontSize:'.9rem' }}>{tool.name}</strong>
                          <span className={'tag ' + (isConnected?'ok':'')} style={{ fontSize:'.62rem' }}>{tool.status}</span>
                        </div>
                        <div style={{ fontSize:'.72rem', color:'var(--muted)', marginTop:2, lineHeight:1.4 }}>{tool.desc}</div>
                      </div>
                    </div>
                    {isConnected && tool.projects && (
                      <div style={{ display:'flex', gap:12, marginTop:10, paddingTop:10, borderTop:'1px solid var(--border)', fontSize:'.74rem' }}>
                        <span><strong style={{ color:'var(--ok)' }}>{tool.projects}</strong> <span style={{ color:'var(--dim)' }}>projects</span></span>
                        <span><strong style={{ color:'var(--warn)' }}>{tool.openTasks}</strong> <span style={{ color:'var(--dim)' }}>open tasks</span></span>
                      </div>
                    )}
                    <div style={{ display:'flex', gap:6, marginTop:12 }}>
                      {isConnected ? (
                        <>
                          {tool.url && <button className="btn btn-ghost btn-sm" style={{ flex:1 }} onClick={() => window.open(tool.url, '_blank')}>Open <Icon name="external" size={11}/></button>}
                          <button className="btn btn-ghost btn-sm">Configure</button>
                        </>
                      ) : (
                        <button className="btn btn-primary btn-sm" style={{ flex:1 }} onClick={() => {
                          if (tool.id === 'slack') setConnected(c => ({ ...c, slack: true }));
                          if (tool.id === 'freshdesk') setConnected(c => ({ ...c, freshdesk: true }));
                          window.wpsbToast?.(tool.name + ' connected (demo)', 'ok');
                        }}>Connect</button>
                      )}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {tab === 'projects' && (
        <div style={{ marginTop:16 }}>
          <div className="box beam" style={{ marginBottom:14 }}>
            <Icon name="info" size={16}/>
            <div>Live sync from <strong>Teamwork → wpsitebeam.teamwork.com</strong>. Click any project to open in Teamwork. Last synced: <strong>2 min ago</strong>.</div>
          </div>

          <div className="grid grid-2" style={{ gap:12 }}>
            {cdProjects.map((p, i) => (
              <div key={i} className="card" style={{ cursor:'pointer' }} onClick={() => window.wpsbToast?.('Opening ' + p.name + ' in Teamwork…')}>
                <div className="card-body" style={{ padding:16 }}>
                  <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', gap:10, marginBottom:8 }}>
                    <div style={{ flex:1, minWidth:0 }}>
                      <div style={{ fontWeight:700, fontSize:'.92rem' }}>{p.name}</div>
                      <div style={{ fontSize:'.74rem', color:'var(--muted)', marginTop:2 }}>{p.client} · Due {p.due}</div>
                    </div>
                    <span className={'tag ' + statusTone[p.status]} style={{ fontSize:'.64rem' }}>{p.status.toUpperCase()}</span>
                  </div>
                  <div style={{ display:'flex', alignItems:'center', gap:10, marginTop:10 }}>
                    <div style={{ flex:1, height:6, background:'var(--surface-3)', borderRadius:3, overflow:'hidden' }}>
                      <div style={{ width: p.progress+'%', height:'100%', background: p.progress===100?'var(--beam)':'var(--ok)', transition:'width .3s' }}/>
                    </div>
                    <span className="mono" style={{ fontSize:'.72rem', color:'var(--muted)', minWidth:32, textAlign:'right' }}>{p.progress}%</span>
                  </div>
                  <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginTop:12, fontSize:'.74rem' }}>
                    <div style={{ display:'flex', gap:10, color:'var(--dim)' }}>
                      <span><strong style={{ color:'var(--warn)' }}>{p.tasks.open}</strong> open</span>
                      <span><strong style={{ color:'var(--ok)' }}>{p.tasks.done}</strong> done</span>
                    </div>
                    <div style={{ display:'flex', gap:-4 }}>
                      {p.team.map((t, j) => (
                        <div key={j} style={{
                          width:22, height:22, borderRadius:'50%',
                          background:'var(--beam-dim)', color:'var(--beam)',
                          display:'flex', alignItems:'center', justifyContent:'center',
                          fontSize:'.66rem', fontWeight:700,
                          border:'2px solid var(--surface-2)',
                          marginLeft: j>0 ? -6 : 0,
                        }}>{t}</div>
                      ))}
                    </div>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      {tab === 'chat' && (
        <div style={{ marginTop:16 }}>
          <div className="grid grid-2">
            <div className="card">
              <div className="card-head">
                <h2 className="card-title">💬 Slack</h2>
                <span className={'tag ' + (connected.slack ? 'ok':'')}>{connected.slack ? 'CONNECTED' : 'NOT CONNECTED'}</span>
              </div>
              <div className="card-body">
                {connected.slack ? (
                  <>
                    <div style={{ fontSize:'.82rem', marginBottom:10 }}>Workspace: <strong>WPSiteBeam</strong> · 24 channels · 12 members</div>
                    <div className="grid grid-2" style={{ gap:8, fontSize:'.76rem' }}>
                      <div style={{ padding:'8px 10px', background:'var(--surface-3)', borderRadius:6, border:'1px solid var(--border)' }}>#general<div style={{ color:'var(--dim)', fontSize:'.7rem' }}>3 new</div></div>
                      <div style={{ padding:'8px 10px', background:'var(--surface-3)', borderRadius:6, border:'1px solid var(--border)' }}>#projects<div style={{ color:'var(--dim)', fontSize:'.7rem' }}>7 new</div></div>
                      <div style={{ padding:'8px 10px', background:'var(--surface-3)', borderRadius:6, border:'1px solid var(--border)' }}>#client-riverway<div style={{ color:'var(--dim)', fontSize:'.7rem' }}>1 new</div></div>
                      <div style={{ padding:'8px 10px', background:'var(--surface-3)', borderRadius:6, border:'1px solid var(--border)' }}>#dev-wpsb<div style={{ color:'var(--dim)', fontSize:'.7rem' }}>12 new</div></div>
                    </div>
                    <button className="btn btn-ghost btn-sm" style={{ marginTop:12 }}>Open Slack <Icon name="external" size={12}/></button>
                  </>
                ) : (
                  <button className="btn btn-primary btn-sm" onClick={() => setConnected(c => ({...c, slack:true}))}>Connect Slack workspace</button>
                )}
              </div>
            </div>
            <div className="card">
              <div className="card-head">
                <h2 className="card-title">🎧 Freshdesk</h2>
                <span className={'tag ' + (connected.freshdesk ? 'ok':'')}>{connected.freshdesk ? 'CONNECTED' : 'NOT CONNECTED'}</span>
              </div>
              <div className="card-body">
                {connected.freshdesk ? (
                  <>
                    <div style={{ fontSize:'.82rem', marginBottom:10 }}>Portal: <strong>support.wpsitebeam.io</strong></div>
                    <div style={{ display:'flex', gap:12, fontSize:'.76rem', marginBottom:10 }}>
                      <div><strong style={{ color:'var(--warn)' }}>8</strong> <span style={{ color:'var(--dim)' }}>open</span></div>
                      <div><strong style={{ color:'var(--ok)' }}>142</strong> <span style={{ color:'var(--dim)' }}>resolved (30d)</span></div>
                      <div><strong>2.4h</strong> <span style={{ color:'var(--dim)' }}>avg response</span></div>
                    </div>
                    <button className="btn btn-ghost btn-sm">Open Freshdesk <Icon name="external" size={12}/></button>
                  </>
                ) : (
                  <button className="btn btn-primary btn-sm" onClick={() => setConnected(c => ({...c, freshdesk:true}))}>Connect Freshdesk</button>
                )}
              </div>
            </div>
          </div>
        </div>
      )}

      {tab === 'activity' && (
        <div style={{ marginTop:16 }}>
          <div className="card">
            <div className="card-head">
              <h2 className="card-title">Recent team activity</h2>
              <span className="tag">LIVE</span>
            </div>
            <div className="card-body" style={{ padding:0 }}>
              {activity.map((a, i) => (
                <div key={i} style={{
                  display:'flex', alignItems:'flex-start', gap:12, padding:'12px 16px',
                  borderBottom: i < activity.length-1 ? '1px solid var(--border)' : 'none',
                }}>
                  <div style={{ width:32, height:32, borderRadius:'50%', background:'var(--beam-dim)', color:'var(--beam)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'.7rem', fontWeight:700, flexShrink:0 }}>
                    {a.u.match(/\(([^)]+)\)/)?.[1] || a.u.slice(0,2)}
                  </div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:'.82rem' }}>
                      <strong>{a.u.replace(/\s*\([^)]+\)/,'')}</strong> <span style={{ color:'var(--muted)' }}>{a.t}</span> <span>{a.x}</span>
                    </div>
                    <div style={{ fontSize:'.7rem', color:'var(--dim)', marginTop:2 }}>in <em>{a.w}</em> · {a.ago} ago</div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ── SA: MODULES ─────────────────────────────────────────────── */
function Modules() {
  const mods = [
    { n: 'Brand Scanner',    stage: 'live',     desc: 'AI audit of brand + perf + SEO' },
    { n: 'Estimator',        stage: 'beta',     desc: 'Build & hosting cost estimator' },
    { n: 'Slack Integration',stage: 'dev',      desc: 'Two-way Slack notifications' },
    { n: 'Freshdesk Bridge', stage: 'internal', desc: 'Sync tickets with Freshdesk' },
    { n: 'AI Auto-Fix',      stage: 'hidden',   desc: 'One-click apply recommended fixes' },
  ];
  const tone = { live: 'ok', beta: 'warn', dev: 'beam', internal: 'sa', hidden: '' };
  return (
    <div>
      <PageHead sa crumb="SA · System" title="Module Activation"
        sub="Toggle modules from hidden → dev → internal → beta → live. SA approval required before any module goes live."/>
      <div className="card">
        <div className="card-body" style={{ padding: 0 }}>
          {mods.map((m, i) => (
            <div key={m.n} style={{ display:'flex', alignItems:'center', gap:14, padding:'14px 18px', borderBottom: i<mods.length-1 ? '1px solid var(--border)' : 'none' }}>
              <div style={{ width:34, height:34, borderRadius:8, background:'var(--rose-dim)', color:'var(--rose)', display:'flex', alignItems:'center', justifyContent:'center' }}>
                <Icon name="modules" size={16}/>
              </div>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontWeight:700, fontSize:'.9rem' }}>{m.n}</div>
                <div style={{ fontSize:'.74rem', color:'var(--muted)' }}>{m.desc}</div>
              </div>
              <span className={`tag ${tone[m.stage]}`}>{m.stage.toUpperCase()}</span>
              <button className="btn btn-ghost btn-sm">Manage</button>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ── SA: PERMISSIONS ─────────────────────────────────────────── */
function Permissions() {
  const rows = [
    { f: 'View dashboard',              c: true,  p: true,  a: true,  sa: true },
    { f: 'Manage billing',              c: true,  p: false, a: true,  sa: true },
    { f: 'Run scan',                    c: true,  p: true,  a: true,  sa: true },
    { f: 'Image Tools — compress/resize', c: true, p: true, a: true, sa: true },
    { f: 'Image Tools — bulk upload to WP', c: false, p: true, a: true, sa: true },
    { f: 'Image Tools — auto-optimize on scan', c: false, p: false, a: true, sa: true },
    { f: 'Site Builder — run detector & generate blueprint', c: true, p: true, a: true, sa: true },
    { f: 'Site Builder — launch / provision new site',        c: false, p: true, a: true, sa: true },
    { f: 'Toggle modules',              c: false, p: false, a: false, sa: true },
    { f: 'Impersonate customer',        c: false, p: false, a: false, sa: true },
    { f: 'Push brand config',           c: false, p: false, a: false, sa: true },
  ];
  const y = <Icon name="check" size={14} />;
  const n = <span style={{ color:'var(--dim)' }}>—</span>;
  return (
    <div>
      <PageHead sa crumb="SA · Security" title="Brain & Feature Permissions"
        sub="Defines what each role can access. SA can override any notice or permission at any time. All overrides are logged."/>
      <div className="card">
        <div className="card-body" style={{ padding: 0, overflowX:'auto' }}>
          <table className="table" style={{ minWidth: 600 }}>
            <thead>
              <tr><th scope="col">Feature</th><th scope="col" style={{ textAlign:'center' }}>Customer</th><th scope="col" style={{ textAlign:'center' }}>Partner</th><th scope="col" style={{ textAlign:'center' }}>Admin</th><th scope="col" style={{ textAlign:'center' }}>SA</th></tr>
            </thead>
            <tbody>
              {rows.map(r => (
                <tr key={r.f}>
                  <td style={{ color:'var(--text)', fontWeight:500 }}>{r.f}</td>
                  <td style={{ textAlign:'center', color:'var(--green)' }}>{r.c ? y : n}</td>
                  <td style={{ textAlign:'center', color:'var(--green)' }}>{r.p ? y : n}</td>
                  <td style={{ textAlign:'center', color:'var(--green)' }}>{r.a ? y : n}</td>
                  <td style={{ textAlign:'center', color:'var(--rose)' }}>{r.sa ? y : n}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

/* ── SA: NOTICES ─────────────────────────────────────────────── */
function Notices() {
  const { useState } = React;
  const [filter, setFilter] = useState('all');
  const [vis, setVis] = useState('all');
  const notices = [
    { id:'N-042', type:'security',  sev:'critical', vis:'private',  t:'Suspicious login attempts from Belarus IP block',                    ts:'12 min ago',   target:'All SA',          state:'unread' },
    { id:'N-041', type:'launch',    sev:'info',     vis:'public',   t:'Module "Slack Integration" promoted from dev → internal',            ts:'1 hr ago',     target:'All customers',   state:'read' },
    { id:'N-040', type:'brain',     sev:'warn',     vis:'internal', t:'WPSB Brain token usage at 82% of monthly budget',                    ts:'3 hrs ago',    target:'SA + Admins',     state:'unread' },
    { id:'N-039', type:'internal',  sev:'info',     vis:'internal', t:'T-014 (Brain wiring) marked complete by @cd',                        ts:'Yesterday',    target:'Partner team',    state:'read' },
    { id:'N-038', type:'security',  sev:'warn',     vis:'private',  t:'TLS certificate for api.wpsitebeam.io expires in 14 days',           ts:'Yesterday',    target:'All SA',          state:'unread' },
    { id:'N-037', type:'launch',    sev:'info',     vis:'public',   t:'Estimator v2 rolled out to 100% of partners',                        ts:'2 days ago',   target:'All partners',    state:'read' },
    { id:'N-036', type:'brain',     sev:'critical', vis:'private',  t:'Claude API rate limit hit — 47 scans queued',                        ts:'2 days ago',   target:'All SA',          state:'read' },
    { id:'N-035', type:'internal',  sev:'info',     vis:'internal', t:'Weekly ops digest — 142 scans · 18 new sites · 3 churn events',      ts:'3 days ago',   target:'SA + Admins',     state:'archived' },
  ];
  const types = ['all','security','launch','brain','internal'];
  const counts = Object.fromEntries(types.map(t => [t, t === 'all' ? notices.length : notices.filter(n => n.type === t).length]));
  let filtered = filter === 'all' ? notices : notices.filter(n => n.type === filter);
  if (vis !== 'all') filtered = filtered.filter(n => n.vis === vis);
  const sevTone = { critical: 'bad', warn: 'warn', info: 'beam' };
  const typeIcon = { security: 'shield', launch: 'spark', brain: 'ai', internal: 'flag' };
  const visMeta = {
    public:   { lbl:'PUBLIC',   tone:'ok',   icon:'🌐', desc:'Visible to all customers + partners' },
    internal: { lbl:'INTERNAL', tone:'beam', icon:'🏢', desc:'Visible to SA + Admins only' },
    private:  { lbl:'PRIVATE',  tone:'sa',   icon:'🔒', desc:'SA-only · never broadcast' },
  };
  const stateMeta = {
    unread:   { lbl:'UNREAD',   tone:'warn' },
    read:     { lbl:'READ',     tone:'' },
    archived: { lbl:'ARCHIVED', tone:'' },
  };

  return (
    <div>
      <PageHead sa crumb="SA · Command" title="System Notices"
        sub="Security, launch, brain, and internal notices. Visibility controls who sees a notice (Public, Internal, Private). Critical notices page the on-call."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="check" size={13}/>Mark all read</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>Broadcast notice</button>
        </>}/>

      <div className="grid grid-4">
        <div className="stat"><div className="stat-lbl">Critical unread</div><div className="stat-val warn">{notices.filter(n => n.sev === 'critical' && n.state === 'unread').length}</div></div>
        <div className="stat"><div className="stat-lbl">Total unread</div><div className="stat-val">{notices.filter(n => n.state === 'unread').length}</div></div>
        <div className="stat"><div className="stat-lbl">Public broadcasts</div><div className="stat-val ok">{notices.filter(n => n.vis === 'public').length}</div></div>
        <div className="stat"><div className="stat-lbl">Pager on-call</div><div className="stat-val" style={{ fontSize:'1.2rem' }}>@cd</div></div>
      </div>

      <div className="box sa" style={{ marginTop:16, marginBottom:0 }}>
        <Icon name="shield" size={16}/>
        <div><strong>Visibility model.</strong> 🌐 <strong>Public</strong> notices appear in customer/partner shells. 🏢 <strong>Internal</strong> shows to SA + Admins. 🔒 <strong>Private</strong> stays SA-only and is never broadcast. Deleting a notice is permanent and audit-logged.</div>
      </div>

      <div className="sub-tabs" style={{ marginTop:16 }}>
        {types.map(t => (
          <button key={t} className={'sub-tab' + (filter === t ? ' active' : '')} onClick={() => setFilter(t)}>
            {t === 'all' ? 'All' : t.charAt(0).toUpperCase() + t.slice(1)} ({counts[t]})
          </button>
        ))}
      </div>

      <div style={{ display:'flex', gap:8, alignItems:'center', marginTop:10, fontSize:'.74rem', color:'var(--dim)' }}>
        <span style={{ fontFamily:'var(--font-mono)', textTransform:'uppercase', letterSpacing:'.06em' }}>Visibility:</span>
        {[['all','All'],['public','🌐 Public'],['internal','🏢 Internal'],['private','🔒 Private']].map(([id,lbl]) => (
          <button key={id} onClick={() => setVis(id)}
            className={'btn btn-ghost btn-sm' + (vis===id ? ' active' : '')}
            style={{ background: vis===id ? 'var(--surface-3)' : 'transparent' }}>
            {lbl}
          </button>
        ))}
      </div>

      <div className="card" style={{ marginTop:14 }}>
        <div className="card-body" style={{ padding: 0 }}>
          {filtered.map((n, i) => {
            const v = visMeta[n.vis];
            const st = stateMeta[n.state];
            return (
              <div key={n.id} style={{ display:'flex', gap:14, padding:'14px 18px', borderBottom: i<filtered.length-1 ? '1px solid var(--border)' : 'none', alignItems:'center', opacity: n.state === 'archived' ? .55 : 1, background: n.state === 'unread' ? 'var(--surface-3)' : 'transparent' }}>
                <div style={{ width:34, height:34, borderRadius:8, background:`var(--${sevTone[n.sev]==='bad'?'rose':sevTone[n.sev]==='warn'?'warn':'beam'}-dim)`, color:`var(--${sevTone[n.sev]==='bad'?'rose':sevTone[n.sev]==='warn'?'warn':'beam'})`, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                  <Icon name={typeIcon[n.type] || 'bell'} size={15}/>
                </div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
                    <span className="mono" style={{ fontSize:'.66rem', color:'var(--muted)' }}>{n.id}</span>
                    <span className={`tag ${sevTone[n.sev]}`}>{n.sev.toUpperCase()}</span>
                    <span className="tag">{n.type.toUpperCase()}</span>
                    <span className={`tag ${v.tone}`} title={v.desc}>{v.icon} {v.lbl}</span>
                    {n.state !== 'read' && <span className={`tag ${st.tone}`}>{st.lbl}</span>}
                  </div>
                  <div style={{ fontWeight:600, fontSize:'.88rem', marginTop:3 }}>{n.t}</div>
                  <div className="mono" style={{ fontSize:'.68rem', color:'var(--dim)', marginTop:2 }}>{n.ts} · Audience: {n.target}</div>
                </div>
                <div style={{ display:'flex', gap:6, flexShrink:0, alignItems:'stretch' }}>
                  {n.state === 'unread' && (
                    <Tooltip text="Mark this notice as read — clears the unread badge for you only.">
                      <button className="btn btn-ghost btn-sm" aria-label="Mark as read" style={{ gap:4 }}>
                        <Icon name="check" size={14}/><span style={{ fontSize:'.72rem' }}>Read</span>
                      </button>
                    </Tooltip>
                  )}
                  <Tooltip text="Edit which roles and users can see this notice, and when it's visible.">
                    <button className="btn btn-ghost btn-sm" aria-label="Edit visibility and audience" style={{ gap:4 }}>
                      <Icon name="edit" size={14}/><span style={{ fontSize:'.72rem' }}>Edit</span>
                    </button>
                  </Tooltip>
                  <Tooltip text="Archive this notice — hidden from main feed but retrievable from the archive tab.">
                    <button className="btn btn-ghost btn-sm" aria-label="Archive notice" style={{ gap:4 }}>
                      <Icon name="archive" size={14}/><span style={{ fontSize:'.72rem' }}>Archive</span>
                    </button>
                  </Tooltip>
                  <Tooltip text="Permanently delete this notice. Logged in audit trail — cannot be undone.">
                    <button className="btn btn-ghost btn-sm" aria-label="Delete notice permanently" style={{ color:'var(--rose)', gap:4 }}>
                      <Icon name="trash" size={14}/><span style={{ fontSize:'.72rem' }}>Delete</span>
                    </button>
                  </Tooltip>
                </div>
              </div>
            );
          })}
          {filtered.length === 0 && (
            <div style={{ padding:40, textAlign:'center', color:'var(--dim)' }}>No notices match the current filters.</div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ── SA: BRAIN AI ────────────────────────────────────────────── */
function Brains() {
  const [tab, setTab] = React.useState('overview'); // overview | analytics | relay
  const BrainsRelay = window.BrainsRelay;
  const brains = [
    { n:'WPSB Brain',     model:'claude-sonnet-4.5',   use:'Scan analysis, recommendations',   calls:'12,847', cost:'$342.11', status:'live' },
    { n:'Haiku Fast',     model:'claude-haiku-4.5',    use:'Quick classification, tags',       calls:'48,203', cost:'$87.42',  status:'live' },
    { n:'Support Brain',  model:'claude-sonnet-4.5',   use:'Ticket triage + suggested replies',calls:'1,290',  cost:'$31.50',  status:'beta' },
    { n:'Estimator Brain',model:'claude-sonnet-4.5',   use:'Proposal copy generation',         calls:'342',    cost:'$12.80',  status:'beta' },
    { n:'Brand Scanner',  model:'gpt-4o',              use:'Vision: logo/color extraction',    calls:'2,140',  cost:'$64.20',  status:'live' },
  ];
  const tone = { live: 'ok', beta: 'warn', dev: 'beam', hidden: '' };

  return (
    <div>
      <PageHead sa crumb="SA · AI" title="Brain AI Systems"
        sub="AI systems that power scans, support, and automation. Keys are server-side only; never exposed to client."
        actions={<>
          <button className="btn btn-ghost btn-sm" onClick={() => setTab(tab==='analytics'?'overview':'analytics')}><Icon name="chart" size={13}/>{tab==='analytics'?'Back to Overview':'Open Analytics'}</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>Register Brain</button>
        </>}/>

      {/* Tabs */}
      <div className="tw-seg" role="tablist" style={{ marginBottom:14, display:'inline-flex' }}>
        <button role="tab" aria-selected={tab==='overview'}  className={tab==='overview' ?'active':''} onClick={()=>setTab('overview')}>Overview</button>
        <button role="tab" aria-selected={tab==='analytics'} className={tab==='analytics'?'active':''} onClick={()=>setTab('analytics')}>Analytics</button>
        <button role="tab" aria-selected={tab==='relay'}     className={tab==='relay'    ?'active':''} onClick={()=>setTab('relay')}>Relay</button>
      </div>

      {tab === 'analytics' ? <BrainAnalytics brains={brains}/> : tab === 'relay' ? <BrainsRelay/> : (
      <>
      <div className="grid grid-4">
        <div className="stat"><div className="stat-lbl">Active brains</div><div className="stat-val ok">5</div></div>
        <div className="stat"><div className="stat-lbl">Calls this month</div><div className="stat-val">64,822</div></div>
        <div className="stat"><div className="stat-lbl">Token spend</div><div className="stat-val">$538.03</div>
          <div className="mono" style={{ fontSize:'.62rem', color:'var(--green)', marginTop:4 }}>▲ 14.2% vs last 30d</div>
        </div>
        <div className="stat"><div className="stat-lbl">Budget used</div><div className="stat-val warn">82%</div></div>
      </div>

      <div className="card" style={{ marginTop:16 }}>
        <div className="card-head"><h2 className="card-title">Registered Brains</h2></div>
        <div className="card-body" style={{ padding: 0 }}>
          <table className="table">
            <thead><tr><th scope="col">Name</th><th scope="col">Model</th><th scope="col">Use case</th><th scope="col" style={{textAlign:'right'}}>Calls</th><th scope="col" style={{textAlign:'right'}}>Spend</th><th scope="col">Status</th><th scope="col"></th></tr></thead>
            <tbody>
              {brains.map(b => (
                <tr key={b.n}>
                  <td style={{ fontWeight:700 }}>{b.n}</td>
                  <td className="mono" style={{ fontSize:'.72rem', color:'var(--beam)' }}>{b.model}</td>
                  <td style={{ fontSize:'.78rem', color:'var(--muted)' }}>{b.use}</td>
                  <td className="mono" style={{ textAlign:'right', fontSize:'.76rem' }}>{b.calls}</td>
                  <td className="mono" style={{ textAlign:'right', fontSize:'.76rem', color:'var(--orange)' }}>{b.cost}</td>
                  <td><span className={`tag ${tone[b.status]}`}>{b.status.toUpperCase()}</span></td>
                  <td><a href="#" onClick={e=>e.preventDefault()}>Configure</a></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <div className="grid grid-2" style={{ marginTop:16 }}>
        <div className="card">
          <div className="card-head"><h2 className="card-title">System prompts</h2><span className="tag sa">SA ONLY</span></div>
          <div className="card-body">
            <Field label="WPSB Brain — Scanner">
              <textarea rows={5} defaultValue={`You are the WPSB Scanner Brain. Analyze the extracted site data and return structured brand, performance, and SEO insights. Return JSON only.`} style={{ fontFamily:'var(--font-mono)', fontSize:'.74rem' }}/>
            </Field>
            <button className="btn btn-primary btn-sm">Save & deploy</button>
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h2 className="card-title">Cost guardrails</h2></div>
          <div className="card-body">
            <Field label="Monthly budget cap"><input defaultValue="$650.00"/></Field>
            <Field label="Alert threshold"><input defaultValue="80%"/></Field>
            <Field label="Hard kill threshold"><input defaultValue="100%"/></Field>
            <div className="box warn" style={{ marginTop:8 }}>
              <Icon name="warn" size={14}/>
              <div>Hitting 100% auto-disables all non-critical brains until next billing cycle.</div>
            </div>
          </div>
        </div>
      </div>
      </>
      )}
    </div>
  );
}

/* ── BRAIN AI: STRIPE-STYLE ANALYTICS ────────────────────────── */
function BrainAnalytics({ brains }) {
  const [range, setRange]   = React.useState('30d');        // today|7d|30d|90d|12m|all
  const [gran,  setGran]    = React.useState('day');        // day|month|year
  const [metric, setMetric] = React.useState('spend');      // spend|calls|tokens|latency|errors
  const [compare, setCompare] = React.useState(true);
  const [view, setView]     = React.useState('overview');   // overview|spend|usage|models|anomalies

  /* Mock analytics series — deterministic seeded values so demo feels real */
  const seriesFor = (key, len, base, jitter=0.3) => {
    const out = [];
    for (let i=0; i<len; i++) {
      const seed = (i*13 + key.length*7) % 100;
      const wave = Math.sin(i * 0.6 + key.length) * 0.25;
      const spike = (i===Math.floor(len*0.72)) ? 1.8 : 1; // known spike
      out.push(Math.round(base * (1 + wave + (seed/100 - 0.5) * jitter) * spike));
    }
    return out;
  };

  const ranges = [
    { id:'today', lbl:'Today',    len:24, unit:'h' },
    { id:'7d',    lbl:'Last 7d',  len:7,  unit:'d' },
    { id:'30d',   lbl:'Last 30d', len:30, unit:'d' },
    { id:'90d',   lbl:'Last 90d', len:13, unit:'w' },
    { id:'12m',   lbl:'Last 12m', len:12, unit:'m' },
    { id:'all',   lbl:'All time', len:24, unit:'m' },
  ];
  const r = ranges.find(x => x.id === range);
  const labels = (() => {
    if (r.unit === 'h') return Array.from({length:24}, (_,i)=> `${i.toString().padStart(2,'0')}`);
    if (r.unit === 'd') return Array.from({length:r.len}, (_,i)=> `${r.len-i}d`).reverse();
    if (r.unit === 'w') return Array.from({length:r.len}, (_,i)=> `w${i+1}`);
    if (r.unit === 'm') { const m=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; return Array.from({length:r.len},(_,i)=> m[(new Date().getMonth()-r.len+1+i+12)%12]); }
    return [];
  })();

  /* Per-metric series + totals + compare */
  const metricSpec = {
    spend:   { lbl:'Token spend',  unit:'$',   color:'var(--orange)', base: r.unit==='h' ? 8 : r.unit==='m' ? 340 : 18 },
    calls:   { lbl:'API calls',    unit:'',    color:'var(--beam)',   base: r.unit==='h' ? 900 : r.unit==='m' ? 62000 : 2200 },
    tokens:  { lbl:'Tokens',       unit:'',    color:'var(--purple)', base: r.unit==='h' ? 120000 : r.unit==='m' ? 8200000 : 280000 },
    latency: { lbl:'Avg latency',  unit:'ms',  color:'var(--green)',  base: 420, jitter:0.15 },
    errors:  { lbl:'Errors',       unit:'',    color:'var(--rose)',   base: r.unit==='h' ? 1 : 4, jitter:0.6 },
  };
  const spec = metricSpec[metric];
  const curr = seriesFor(metric+range, labels.length, spec.base, spec.jitter ?? 0.3);
  const prev = seriesFor('prev'+metric+range, labels.length, spec.base * 0.87, spec.jitter ?? 0.3);

  const sum = arr => arr.reduce((a,b)=>a+b,0);
  const avg = arr => Math.round(sum(arr)/arr.length);
  const fmtN = n => metric==='spend' ? `$${(n).toFixed(2)}` : n >= 1000 ? `${(n/1000).toFixed(n>10000?0:1)}k` : `${n}`;
  const pct = (cur, prev) => { if(!prev) return 0; return Math.round(((cur-prev)/prev)*1000)/10; };

  const totalCurr = metric==='latency' ? avg(curr) : sum(curr);
  const totalPrev = metric==='latency' ? avg(prev) : sum(prev);
  const delta = pct(totalCurr, totalPrev);

  /* Per-brain color mapping */
  const palette = ['var(--beam)','var(--orange)','var(--purple)','var(--green)','var(--rose)'];
  const brainSeries = brains.map((b, i) => ({
    name: b.n,
    color: palette[i % palette.length],
    data: seriesFor(b.n+metric+range, labels.length, (parseFloat(b.cost.replace('$','')) || 50) / (r.len||30) * (r.unit==='h'?1:r.unit==='m'?30:1), 0.35),
    model: b.model,
    cost: b.cost,
    calls: b.calls,
  }));

  /* Detected anomalies (dates derived from the spike index) */
  const spikeIdx = Math.floor(labels.length * 0.72);
  const anomalies = [
    { date: labels[spikeIdx], brain:'WPSB Brain', metric:'Token spend', change:'+182%', severity:'critical', reason:'Scanner retry-loop detected on site #142 — resolved 23m later' },
    { date: labels[Math.floor(labels.length*0.45)], brain:'Haiku Fast', metric:'API calls', change:'+64%', severity:'warn',     reason:'Bulk tagging run on 2,400 pages for Partner: Lighthaus' },
    { date: labels[Math.floor(labels.length*0.25)], brain:'Support Brain', metric:'Errors', change:'+42%', severity:'warn',     reason:'Intermittent 529s from Anthropic (upstream) — auto-retried' },
    { date: labels[Math.floor(labels.length*0.1)],  brain:'Brand Scanner', metric:'Latency', change:'+28%', severity:'info',     reason:'Vision model cold starts during low-traffic window' },
  ];

  /* Top spend table per-brain */
  const topBrains = [...brainSeries]
    .map(b => ({ ...b, total: sum(b.data) }))
    .sort((a,b) => b.total - a.total);

  return (
    <div>
      {/* Note */}
      <div className="box info" style={{ marginBottom:14 }}>
        <Icon name="info" size={14}/>
        <div>
          <strong>Stripe-style analytics for Brain AI usage.</strong>&nbsp;
          Filter by range, granularity, and metric to explore spend, volume, latency, and anomalies across all registered brains. As this grows we may promote it to a dedicated SA page under <span className="mono">SA · Analytics</span>, but for now it lives under <span className="mono">Brain AI</span> so it sits next to the systems it tracks.
        </div>
      </div>

      {/* Filter bar */}
      <div className="card" style={{ marginBottom:14 }}>
        <div className="card-body" style={{ display:'flex', gap:12, alignItems:'center', flexWrap:'wrap' }}>
          {/* Range segmented */}
          <div className="tw-seg" role="group" aria-label="Time range">
            {ranges.map(x => (
              <button key={x.id} className={range===x.id?'active':''} onClick={()=>setRange(x.id)} aria-pressed={range===x.id}>{x.lbl}</button>
            ))}
          </div>
          {/* Granularity */}
          <div className="tw-seg" role="group" aria-label="Granularity">
            {['day','month','year'].map(g => (
              <button key={g} className={gran===g?'active':''} onClick={()=>setGran(g)} aria-pressed={gran===g}>{g[0].toUpperCase()+g.slice(1)}</button>
            ))}
          </div>
          {/* Compare toggle */}
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:'.78rem', color:'var(--muted)', cursor:'pointer' }}>
            <input type="checkbox" checked={compare} onChange={e=>setCompare(e.target.checked)}/>
            Compare to previous period
          </label>
          <div style={{ flex:1 }}/>
          <button className="btn btn-ghost btn-sm"><Icon name="calendar" size={12}/>Custom range</button>
          <button className="btn btn-ghost btn-sm"><Icon name="download" size={12}/>Export CSV</button>
        </div>
      </div>

      {/* KPI row — clickable to switch primary metric */}
      <div className="grid grid-4" style={{ marginBottom:14 }}>
        {[
          { k:'spend',  lbl:'Token spend',  val:`$${sum(seriesFor('spend'+range,labels.length,metricSpec.spend.base)).toFixed(2)}`, prev:`$${sum(seriesFor('prevspend'+range,labels.length,metricSpec.spend.base*0.87)).toFixed(2)}`, color:'var(--orange)' },
          { k:'calls',  lbl:'API calls',    val: fmtCompact(sum(seriesFor('calls'+range,labels.length,metricSpec.calls.base))),       prev: fmtCompact(sum(seriesFor('prevcalls'+range,labels.length,metricSpec.calls.base*0.87))),  color:'var(--beam)' },
          { k:'tokens', lbl:'Tokens',       val: fmtCompact(sum(seriesFor('tokens'+range,labels.length,metricSpec.tokens.base))),     prev: fmtCompact(sum(seriesFor('prevtokens'+range,labels.length,metricSpec.tokens.base*0.87))),color:'var(--purple)' },
          { k:'latency',lbl:'Avg latency',  val: `${avg(seriesFor('latency'+range,labels.length,metricSpec.latency.base,0.15))}ms`,    prev: `${avg(seriesFor('prevlatency'+range,labels.length,metricSpec.latency.base*0.97,0.15))}ms`, color:'var(--green)' },
        ].map(k => {
          const numCur = parseFloat(String(k.val).replace(/[^0-9.-]/g,'')) || 0;
          const numPrev = parseFloat(String(k.prev).replace(/[^0-9.-]/g,'')) || 0;
          const d = pct(numCur, numPrev);
          const positive = (k.k==='latency' || k.k==='errors') ? d < 0 : d > 0;
          const arrow = d === 0 ? '·' : d > 0 ? '▲' : '▼';
          const tone = positive ? 'var(--green)' : 'var(--orange)';
          return (
            <button key={k.k} className={`stat ${metric===k.k?'active':''}`}
              onClick={()=>setMetric(k.k)}
              style={{
                textAlign:'left', cursor:'pointer', border: metric===k.k ? `2px solid ${k.color}` : '1px solid var(--border)',
                background: metric===k.k ? 'var(--surface-3)' : 'var(--surface-2)',
                padding:'14px 16px', borderRadius:8, width:'100%'
              }}
              aria-pressed={metric===k.k}
            >
              <div className="stat-lbl" style={{ display:'flex', alignItems:'center', gap:6 }}>
                <span style={{ width:6, height:6, borderRadius:'50%', background:k.color, display:'inline-block' }}/>
                {k.lbl}
              </div>
              <div className="stat-val" style={{ fontSize:'1.55rem' }}>{k.val}</div>
              {compare && (
                <div className="mono" style={{ fontSize:'.62rem', color: tone, marginTop:4 }}>
                  {arrow} {Math.abs(d)}% vs prev period <span style={{ color:'var(--dim)' }}>({k.prev})</span>
                </div>
              )}
            </button>
          );
        })}
      </div>

      {/* View segmented */}
      <div className="tw-seg" role="tablist" style={{ marginBottom:14, display:'inline-flex' }}>
        {['overview','spend','usage','models','anomalies'].map(v => (
          <button key={v} role="tab" aria-selected={view===v} className={view===v?'active':''} onClick={()=>setView(v)}>
            {v[0].toUpperCase()+v.slice(1)}
          </button>
        ))}
      </div>

      {/* Main chart card */}
      <div className="card" style={{ marginBottom:14 }}>
        <div className="card-head" style={{ justifyContent:'space-between' }}>
          <h2 className="card-title">
            {spec.lbl} <span style={{ color:'var(--muted)', fontWeight:400, fontSize:'.82rem' }}>· {r.lbl.toLowerCase()} · by {gran}</span>
          </h2>
          <div style={{ display:'flex', gap:10, alignItems:'center' }}>
            <div style={{ fontFamily:'var(--font-brand)', fontSize:'1.4rem', color:spec.color }}>
              {metric==='spend' ? `$${totalCurr.toFixed(2)}` : fmtCompact(totalCurr)}
              {spec.unit==='ms' && 'ms'}
            </div>
            {compare && (
              <span className="mono" style={{
                fontSize:'.66rem', padding:'3px 8px', borderRadius:999,
                background: (metric==='latency'||metric==='errors') ? (delta<0?'var(--green-dim)':'var(--rose-dim)') : (delta>0?'var(--green-dim)':'var(--rose-dim)'),
                color: (metric==='latency'||metric==='errors') ? (delta<0?'var(--green)':'var(--rose)') : (delta>0?'var(--green)':'var(--rose)')
              }}>
                {delta>0?'▲':delta<0?'▼':'·'} {Math.abs(delta)}%
              </span>
            )}
          </div>
        </div>
        <div className="card-body">
          <AreaChart
            datasets={compare
              ? [{ data: prev, color: 'var(--muted)', label: 'Previous' }, { data: curr, color: spec.color, label: 'Current' }]
              : [{ data: curr, color: spec.color, label: spec.lbl }]
            }
            labels={labels.filter((_,i)=> i % Math.ceil(labels.length/8) === 0)}
            height={200}
          />
          {compare && (
            <div style={{ display:'flex', gap:16, marginTop:10, fontSize:'.72rem' }}>
              <span style={{ display:'flex', alignItems:'center', gap:6 }}><span style={{ width:10, height:3, background:spec.color, borderRadius:2 }}/>Current</span>
              <span style={{ display:'flex', alignItems:'center', gap:6 }}><span style={{ width:10, height:3, background:'var(--muted)', borderRadius:2 }}/>Previous ({r.lbl.toLowerCase()})</span>
            </div>
          )}
        </div>
      </div>

      {/* VIEW CONTENT */}
      {view === 'overview' && (
        <div className="grid grid-2">
          {/* Per-brain spend breakdown */}
          <div className="card">
            <div className="card-head"><h2 className="card-title">Spend by brain</h2></div>
            <div className="card-body" style={{ padding: 0 }}>
              <table className="table">
                <thead><tr><th scope="col">Brain</th><th scope="col" style={{textAlign:'right'}}>Trend</th><th scope="col" style={{textAlign:'right'}}>Total</th><th scope="col" style={{textAlign:'right'}}>% of spend</th></tr></thead>
                <tbody>
                  {topBrains.map(b => {
                    const t = sum(topBrains.flatMap(x => x.data));
                    const share = Math.round((b.total/t)*100);
                    return (
                      <tr key={b.name}>
                        <td>
                          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                            <span style={{ width:8, height:8, borderRadius:2, background:b.color }}/>
                            <div>
                              <div style={{ fontWeight:600, fontSize:'.82rem' }}>{b.name}</div>
                              <div className="mono" style={{ fontSize:'.62rem', color:'var(--dim)' }}>{b.model}</div>
                            </div>
                          </div>
                        </td>
                        <td style={{ textAlign:'right', minWidth:120 }}><Sparkline data={b.data} color={b.color} height={24}/></td>
                        <td className="mono" style={{ textAlign:'right' }}>{metric==='spend' ? `$${b.total.toFixed(2)}` : fmtCompact(b.total)}</td>
                        <td className="mono" style={{ textAlign:'right', color:'var(--muted)' }}>{share}%</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>

          {/* Latency + error rate mini */}
          <div className="card">
            <div className="card-head"><h2 className="card-title">Health signals</h2></div>
            <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:16 }}>
              <MiniSignal label="p50 latency" color="var(--green)" value="312ms" delta="-4.2%" data={seriesFor('p50',labels.length,310,0.1)}/>
              <MiniSignal label="p95 latency" color="var(--beam)" value="842ms" delta="+1.8%" data={seriesFor('p95',labels.length,820,0.15)}/>
              <MiniSignal label="Error rate"  color="var(--rose)" value="0.42%" delta="-18%" invertTone data={seriesFor('err',labels.length,0.4,0.4)}/>
              <MiniSignal label="Cache hit"   color="var(--purple)" value="67.4%" delta="+3.1%" data={seriesFor('cache',labels.length,65,0.08)}/>
            </div>
          </div>
        </div>
      )}

      {view === 'spend' && (
        <div className="card">
          <div className="card-head"><h2 className="card-title">Spend — stacked by brain</h2></div>
          <div className="card-body">
            <StackedBars series={brainSeries} labels={labels.filter((_,i)=> i % Math.ceil(labels.length/12) === 0)} height={220}/>
            <div style={{ display:'flex', flexWrap:'wrap', gap:14, marginTop:12, fontSize:'.72rem' }}>
              {brainSeries.map(b => (
                <span key={b.name} style={{ display:'flex', alignItems:'center', gap:6 }}>
                  <span style={{ width:10, height:10, background:b.color, borderRadius:2 }}/>{b.name}
                </span>
              ))}
            </div>
          </div>
        </div>
      )}

      {view === 'usage' && (
        <div className="grid grid-2">
          <div className="card">
            <div className="card-head"><h2 className="card-title">Calls by hour of day</h2></div>
            <div className="card-body">
              <BarChart
                data={Array.from({length:24},(_,i)=> Math.round(400 + Math.sin(i/24*Math.PI*2 - 1) * 280 + (i>8&&i<18?180:0)))}
                labels={['0','','','','4','','','','8','','','','12','','','','16','','','','20','','','23']}
                color="var(--beam)" height={160}
              />
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Calls by day of week</h2></div>
            <div className="card-body">
              <BarChart
                data={[3400, 4200, 4800, 5100, 4700, 2100, 1800]}
                labels={['Mon','Tue','Wed','Thu','Fri','Sat','Sun']}
                color="var(--purple)" height={160}
              />
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Top endpoints</h2></div>
            <div className="card-body" style={{ padding: 0 }}>
              <table className="table">
                <thead><tr><th scope="col">Endpoint</th><th scope="col" style={{textAlign:'right'}}>Calls</th><th scope="col" style={{textAlign:'right'}}>Avg cost</th><th scope="col" style={{textAlign:'right'}}>p95</th></tr></thead>
                <tbody>
                  {[
                    { e:'/brain/scan',    c:'12,847', a:'$0.026', p:'812ms' },
                    { e:'/brain/tag',     c:'48,203', a:'$0.002', p:'198ms' },
                    { e:'/brain/triage',  c:'1,290',  a:'$0.024', p:'1.2s' },
                    { e:'/brain/estimate',c:'342',    a:'$0.037', p:'1.4s' },
                    { e:'/brain/vision',  c:'2,140',  a:'$0.030', p:'1.6s' },
                  ].map(x => (
                    <tr key={x.e}><td className="mono" style={{ fontSize:'.74rem' }}>{x.e}</td><td className="mono" style={{ textAlign:'right' }}>{x.c}</td><td className="mono" style={{ textAlign:'right' }}>{x.a}</td><td className="mono" style={{ textAlign:'right', color:'var(--muted)' }}>{x.p}</td></tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Top consumers</h2></div>
            <div className="card-body" style={{ padding: 0 }}>
              <table className="table">
                <thead><tr><th scope="col">Account</th><th scope="col">Role</th><th scope="col" style={{textAlign:'right'}}>Calls</th><th scope="col" style={{textAlign:'right'}}>Spend</th></tr></thead>
                <tbody>
                  {[
                    { n:'Lighthaus Agency',   r:'partner',  c:'18,402', s:'$142.80' },
                    { n:'Riverway Health',    r:'customer', c:'6,890',  s:'$48.22' },
                    { n:'Oakline Civic',      r:'customer', c:'4,120',  s:'$31.10' },
                    { n:'Studio Amberleaf',   r:'partner',  c:'3,840',  s:'$28.90' },
                    { n:'Grove Academy',      r:'customer', c:'2,210',  s:'$18.40' },
                  ].map(x => (
                    <tr key={x.n}><td>{x.n}</td><td><span className="tag">{x.r.toUpperCase()}</span></td><td className="mono" style={{ textAlign:'right' }}>{x.c}</td><td className="mono" style={{ textAlign:'right', color:'var(--orange)' }}>{x.s}</td></tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      )}

      {view === 'models' && (
        <div className="grid grid-2">
          <div className="card">
            <div className="card-head"><h2 className="card-title">Model mix</h2></div>
            <div className="card-body">
              <ProportionBar items={[
                { lbl:'claude-sonnet-4.5', v:62, c:'var(--beam)' },
                { lbl:'claude-haiku-4.5',  v:24, c:'var(--purple)' },
                { lbl:'gpt-4o',            v:10, c:'var(--orange)' },
                { lbl:'claude-opus-4.5',   v:4,  c:'var(--rose)' },
              ]}/>
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Cost per 1K tokens</h2></div>
            <div className="card-body" style={{ padding: 0 }}>
              <table className="table">
                <thead><tr><th scope="col">Model</th><th scope="col" style={{textAlign:'right'}}>In</th><th scope="col" style={{textAlign:'right'}}>Out</th><th scope="col" style={{textAlign:'right'}}>Vol (mo)</th></tr></thead>
                <tbody>
                  <tr><td className="mono" style={{ fontSize:'.74rem', color:'var(--beam)' }}>claude-sonnet-4.5</td><td className="mono" style={{ textAlign:'right' }}>$0.003</td><td className="mono" style={{ textAlign:'right' }}>$0.015</td><td className="mono" style={{ textAlign:'right', color:'var(--muted)' }}>5.1M</td></tr>
                  <tr><td className="mono" style={{ fontSize:'.74rem', color:'var(--purple)' }}>claude-haiku-4.5</td><td className="mono" style={{ textAlign:'right' }}>$0.0008</td><td className="mono" style={{ textAlign:'right' }}>$0.004</td><td className="mono" style={{ textAlign:'right', color:'var(--muted)' }}>2.0M</td></tr>
                  <tr><td className="mono" style={{ fontSize:'.74rem', color:'var(--orange)' }}>gpt-4o</td><td className="mono" style={{ textAlign:'right' }}>$0.005</td><td className="mono" style={{ textAlign:'right' }}>$0.015</td><td className="mono" style={{ textAlign:'right', color:'var(--muted)' }}>0.8M</td></tr>
                  <tr><td className="mono" style={{ fontSize:'.74rem', color:'var(--rose)' }}>claude-opus-4.5</td><td className="mono" style={{ textAlign:'right' }}>$0.015</td><td className="mono" style={{ textAlign:'right' }}>$0.075</td><td className="mono" style={{ textAlign:'right', color:'var(--muted)' }}>0.3M</td></tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      )}

      {view === 'anomalies' && (
        <div className="card">
          <div className="card-head" style={{ justifyContent:'space-between' }}>
            <h2 className="card-title">Detected anomalies <span className="tag warn">{anomalies.length}</span></h2>
            <div style={{ display:'flex', gap:8 }}>
              <button className="btn btn-ghost btn-sm"><Icon name="filter" size={12}/>Filter</button>
              <button className="btn btn-ghost btn-sm"><Icon name="refresh" size={12}/>Re-scan</button>
            </div>
          </div>
          <div className="card-body" style={{ padding: 0 }}>
            {anomalies.map((a,i) => {
              const sevTone = { critical:'bad', warn:'warn', info:'beam' };
              const sevColor = { critical:'var(--rose)', warn:'var(--orange)', info:'var(--beam)' };
              return (
                <div key={i} style={{ padding:'14px 18px', borderBottom: i<anomalies.length-1 ? '1px solid var(--border)' : 'none', display:'flex', gap:12, alignItems:'flex-start' }}>
                  <div style={{ width:30, height:30, borderRadius:6, background:`color-mix(in srgb, ${sevColor[a.severity]} 18%, transparent)`, color:sevColor[a.severity], display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                    <Icon name="warn" size={14}/>
                  </div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ display:'flex', gap:10, alignItems:'center', flexWrap:'wrap' }}>
                      <strong style={{ fontSize:'.88rem' }}>{a.brain} — {a.metric} spike</strong>
                      <span className={`tag ${sevTone[a.severity]}`}>{a.severity.toUpperCase()}</span>
                      <span className="mono" style={{ fontSize:'.72rem', color: a.change.startsWith('+') ? 'var(--rose)' : 'var(--green)', fontWeight:700 }}>{a.change}</span>
                      <span className="mono" style={{ fontSize:'.68rem', color:'var(--dim)' }}>· {a.date}</span>
                    </div>
                    <div style={{ fontSize:'.78rem', color:'var(--dim)', marginTop:4 }}>{a.reason}</div>
                  </div>
                  <div style={{ display:'flex', gap:6, flexShrink:0 }}>
                    <button className="btn btn-ghost btn-sm">Investigate</button>
                    <button className="btn btn-ghost btn-sm">Mute</button>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

/* Mini trend signal row */
function MiniSignal({ label, value, delta, color, data, invertTone }) {
  const up = delta.startsWith('+');
  const tone = invertTone ? (up ? 'var(--rose)' : 'var(--green)') : (up ? 'var(--green)' : 'var(--rose)');
  return (
    <div style={{ display:'flex', alignItems:'center', gap:14 }}>
      <div style={{ flex:'0 0 130px' }}>
        <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)' }}>{label.toUpperCase()}</div>
        <div style={{ display:'flex', alignItems:'baseline', gap:8 }}>
          <span style={{ fontSize:'1.2rem', fontWeight:700 }}>{value}</span>
          <span className="mono" style={{ fontSize:'.66rem', color: tone }}>{delta}</span>
        </div>
      </div>
      <div style={{ flex:1 }}><Sparkline data={data} color={color} height={34}/></div>
    </div>
  );
}

/* Horizontal proportion bar (for model mix) */
function ProportionBar({ items }) {
  const total = items.reduce((a,b)=>a+b.v,0);
  return (
    <div>
      <div style={{ display:'flex', height:32, borderRadius:6, overflow:'hidden', border:'1px solid var(--border)' }}>
        {items.map(it => (
          <div key={it.lbl} style={{ flex: it.v, background: it.c, display:'flex', alignItems:'center', justifyContent:'center', fontSize:'.66rem', color:'#fff', fontWeight:700 }}>
            {Math.round(it.v/total*100)}%
          </div>
        ))}
      </div>
      <div style={{ display:'flex', flexDirection:'column', gap:8, marginTop:14 }}>
        {items.map(it => (
          <div key={it.lbl} style={{ display:'flex', alignItems:'center', gap:10, fontSize:'.78rem' }}>
            <span style={{ width:10, height:10, background:it.c, borderRadius:2 }}/>
            <span className="mono" style={{ color:'var(--muted)' }}>{it.lbl}</span>
            <span style={{ flex:1 }}/>
            <span className="mono" style={{ color:'var(--dim)' }}>{Math.round(it.v/total*100)}%</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* Stacked bars per label (columns = time buckets, stack = brains) */
function StackedBars({ series, labels, height = 200 }) {
  const buckets = series[0]?.data.length || 0;
  const totals  = Array.from({length: buckets}, (_, i) => series.reduce((a,s)=> a + s.data[i], 0));
  const max = Math.max(...totals) || 1;
  return (
    <div style={{ display:'flex', alignItems:'flex-end', gap:4, height, paddingBottom:22, position:'relative' }} aria-hidden="true">
      {Array.from({length: buckets}).map((_, i) => (
        <div key={i} style={{ flex:1, display:'flex', flexDirection:'column', justifyContent:'flex-end', height:'100%', gap:1 }}>
          {series.map((s, si) => {
            const v = s.data[i];
            const h = (v/max) * (height - 22);
            return <div key={si} style={{ height: h, background: s.color, borderRadius: si===series.length-1 ? '3px 3px 0 0' : 0, opacity:.9 }} title={`${s.name}: ${v}`}/>;
          })}
        </div>
      ))}
      {labels && (
        <div style={{ position:'absolute', left:0, right:0, bottom:0, display:'flex', justifyContent:'space-between', fontSize:'.6rem', fontFamily:'var(--font-mono)', color:'var(--dim)' }}>
          {labels.map(l => <span key={l}>{l}</span>)}
        </div>
      )}
    </div>
  );
}

/* Compact number format */
function fmtCompact(n) {
  if (n >= 1e9) return `${(n/1e9).toFixed(1)}B`;
  if (n >= 1e6) return `${(n/1e6).toFixed(1)}M`;
  if (n >= 1e3) return `${(n/1e3).toFixed(1)}k`;
  return `${Math.round(n)}`;
}

function Roles({ api }) {
  const roles = [
    { id:'customer',       lbl:'Customer',            icon:'account',   members:142, permCount:8,  built:true,  color:'var(--beam)',   desc:'End-customer access: own sites, scans, billing, support' },
    { id:'partner',        lbl:'Partner Agency',      icon:'partners',  members:4,   permCount:14, built:true,  color:'var(--orange)', desc:'White-label agency: manages multiple client accounts' },
    { id:'partner_ops',    lbl:'Partner Ops',         icon:'team',      members:8,   permCount:12, built:false, color:'var(--purple)', desc:'Partner staff with scoped site access' },
    { id:'admin',          lbl:'Agency Admin',        icon:'shield',    members:2,   permCount:18, built:true,  color:'var(--green)',  desc:'Agency-side admin: billing, team, white-label config' },
    { id:'support',        lbl:'Support Tech',        icon:'support',   members:3,   permCount:10, built:false, color:'var(--purple)', desc:'Read-only + ticket access; no billing' },
    { id:'sa',             lbl:'Super Admin (SA)',    icon:'crown',     members:2,   permCount:42, built:true,  color:'var(--rose)',   desc:'God mode: all modules, all overrides, all audit logs' },
  ];
  return (
    <div>
      <PageHead sa crumb="SA · Security" title="Role Manager"
        sub="Create, edit, and assign custom roles. Every role maps to a permission set in the Permissions table."
        actions={<button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>New role</button>}/>

      <div className="box sa" style={{ marginBottom:16 }}>
        <Icon name="shield" size={16}/>
        <div><strong>Role changes propagate instantly.</strong> All users matching this role will have permissions re-evaluated on their next request. Audit log entry is created.</div>
      </div>

      <div className="grid" style={{ gridTemplateColumns:'repeat(auto-fill, minmax(320px, 1fr))' }}>
        {roles.map(r => (
          <div key={r.id} className="card">
            <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:12 }}>
              {/* Header row — fixed min-height so all tops align */}
              <div style={{ display:'flex', alignItems:'center', gap:10, minHeight:44 }}>
                <div style={{ width:36, height:36, borderRadius:8, background: r.color, opacity:.2, position:'relative', flexShrink:0 }}>
                  <div style={{ position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center', color: r.color, opacity: 5 }}>
                    <Icon name={r.icon || 'shield'} size={16}/>
                  </div>
                </div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontWeight:700, fontSize:'.94rem' }}>{r.lbl}</div>
                  <div className="mono" style={{ fontSize:'.66rem', color:'var(--muted)' }}>role.{r.id}</div>
                </div>
                {r.built ? <span className="tag">SYSTEM</span> : <span className="tag beam">CUSTOM</span>}
              </div>
              {/* Description — reserve exactly 2 lines so all mid-sections align */}
              <div style={{
                fontSize:'.78rem', color:'var(--dim)', lineHeight:1.5,
                minHeight: 'calc(.78rem * 1.5 * 2)',
                display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical',
                overflow:'hidden'
              }}>{r.desc}</div>
              <div style={{ display:'flex', gap:8 }}>
                <div style={{ flex:1, padding:'8px 10px', background:'var(--surface-3)', borderRadius:6, textAlign:'center' }}>
                  <div className="mono" style={{ fontSize:'.66rem', color:'var(--muted)' }}>MEMBERS</div>
                  <div style={{ fontWeight:700, fontSize:'1.1rem', marginTop:2 }}>{r.members}</div>
                </div>
                <div style={{ flex:1, padding:'8px 10px', background:'var(--surface-3)', borderRadius:6, textAlign:'center' }}>
                  <div className="mono" style={{ fontSize:'.66rem', color:'var(--muted)' }}>PERMS</div>
                  <div style={{ fontWeight:700, fontSize:'1.1rem', marginTop:2 }}>{r.permCount}</div>
                </div>
              </div>
              <div className="row-actions" style={{ display:'flex', gap:6 }}>
                <button className="btn btn-ghost btn-sm" style={{ flex:1, justifyContent:'center', textAlign:'center' }}
                  onClick={() => api.switchTab('permissions')}
                  aria-label={`Edit permissions for ${r.lbl} role`}>Edit perms</button>
                <button className="btn btn-ghost btn-sm" style={{ flex:1, justifyContent:'center', textAlign:'center' }}
                  onClick={() => api.switchTab('team')}
                  aria-label={`View ${r.members} ${r.lbl} members`}>Members</button>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ── SA: TEAM / EMPLOYEES ─────────────────────────────────────── */
function Team() {
  const people = [
    { n:'WPSiteBeam',            e:'team@wpsitebeam.io',                role:'Partner Agency', tenure:'Founder',    last:'Active now',     mfa:true,  status:'active', phone:'(316) 555-0101', loc:'Wichita, KS',    joined:'2021-03-14', sessions:3, apiKeys:2 },
    { n:'Jordan Davis',          e:'jordan@wpsitebeam.io',      role:'Agency Admin',   tenure:'2y 4mo',     last:'2 min ago',      mfa:true,  status:'active', phone:'(818) 555-0144', loc:'Burbank, CA',     joined:'2023-06-02', sessions:2, apiKeys:1 },
    { n:'Priya Malik',           e:'priya@wpsitebeam.io',       role:'Support Tech',   tenure:'11 mo',      last:'18 min ago',     mfa:true,  status:'active', phone:'(669) 555-0188', loc:'San Jose, CA',    joined:'2024-11-08', sessions:1, apiKeys:0 },
    { n:'Marcus Lee',            e:'marcus@wpsitebeam.io',      role:'Partner Ops',    tenure:'6 mo',       last:'1 hr ago',       mfa:false, status:'active', phone:'(213) 555-0133', loc:'Los Angeles, CA', joined:'2025-04-22', sessions:1, apiKeys:0 },
    { n:'Ana Torres',            e:'ana@wpsitebeam.io',         role:'Support Tech',   tenure:'3 mo',       last:'Yesterday',      mfa:true,  status:'active', phone:'(760) 555-0121', loc:'San Diego, CA',   joined:'2025-07-11', sessions:0, apiKeys:0 },
    { n:'Super Admin',           e:'root@wpsitebeam.io',                 role:'Super Admin (SA)',tenure:'—',          last:'Active now',     mfa:true,  status:'active', phone:'—',              loc:'—',                joined:'2021-01-01', sessions:1, apiKeys:5 },
    { n:'Dana Whitfield',        e:'dana@wpsitebeam.io',        role:'Partner Ops',    tenure:'2 mo',       last:'Invite sent',    mfa:false, status:'invited', phone:'—',              loc:'—',                joined:'Pending',     sessions:0, apiKeys:0 },
  ];
  const tone = { active: 'ok', invited: 'warn', suspended: 'bad' };
  const [openEmail, setOpenEmail] = React.useState(null);
  const [profileTab, setProfileTab] = React.useState('profile'); // profile | role | security | activity
  return (
    <div>
      <PageHead sa crumb="SA · People" title="Employee Directory"
        sub="Internal team accounts with role assignments. MFA is mandatory for all SA and Admin roles."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="download" size={13}/>Export</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>Invite member</button>
        </>}/>

      <div className="grid grid-4">
        <div className="stat"><div className="stat-lbl">Total employees</div><div className="stat-val">{people.length}</div></div>
        <div className="stat"><div className="stat-lbl">Active</div><div className="stat-val ok">{people.filter(p => p.status === 'active').length}</div></div>
        <div className="stat"><div className="stat-lbl">Invited</div><div className="stat-val warn">{people.filter(p => p.status === 'invited').length}</div></div>
        <div className="stat"><div className="stat-lbl">MFA enabled</div><div className={'stat-val ' + (people.filter(p => p.mfa).length === people.length ? 'ok' : 'warn')}>{people.filter(p => p.mfa).length}/{people.length}</div></div>
      </div>

      <div className="card" style={{ marginTop:16 }}>
        <div className="card-head">
          <h2 className="card-title">Directory</h2>
          <div style={{ display:'flex', gap:6 }}>
            <button className="btn btn-ghost btn-sm">Filter: Role</button>
            <button className="btn btn-ghost btn-sm">Filter: Status</button>
          </div>
        </div>
        <div className="card-body" style={{ padding: 0 }}>
          <table className="table">
            <thead><tr><th scope="col">Name</th><th scope="col">Email</th><th scope="col">Role</th><th scope="col">Tenure</th><th scope="col">Last seen</th><th scope="col">MFA</th><th scope="col">Status</th><th scope="col" style={{textAlign:'right'}}>Actions</th></tr></thead>
            <tbody>
              {people.map(p => {
                const open = openEmail === p.e;
                return (
                <React.Fragment key={p.e}>
                <tr>
                  <td>
                    <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                      <div style={{ width:28, height:28, borderRadius:'50%', background:'linear-gradient(135deg, var(--orange), var(--beam))', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'.7rem', fontWeight:700, color:'#000', flexShrink:0 }}>
                        {p.n.split(' ').map(x => x[0]).join('').slice(0,2)}
                      </div>
                      <span style={{ fontWeight:600, fontSize:'.86rem' }}>{p.n}</span>
                    </div>
                  </td>
                  <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{p.e}</td>
                  <td><span className={`tag ${p.role === 'Super Admin (SA)' ? 'sa' : ''}`}>{p.role}</span></td>
                  <td style={{ fontSize:'.78rem', color:'var(--muted)' }}>{p.tenure}</td>
                  <td className="mono" style={{ fontSize:'.72rem', color: p.last === 'Active now' ? 'var(--green)' : 'var(--dim)' }}>{p.last}</td>
                  <td>{p.mfa ? <Icon name="check" size={14}/> : <span className="tag bad">OFF</span>}</td>
                  <td><span className={`tag ${tone[p.status]}`}>{p.status.toUpperCase()}</span></td>
                  <td style={{ textAlign:'right' }}>
                    <div style={{ display:'inline-flex', gap:4 }}>
                      <button
                        className={`btn btn-sm ${open ? 'btn-primary' : 'btn-ghost'}`}
                        onClick={() => { setOpenEmail(open ? null : p.e); setProfileTab('profile'); }}
                        aria-expanded={open}
                        aria-controls={`prof-${p.e}`}
                        title="Edit profile, role, permissions, security"
                      >
                        <Icon name="edit" size={11}/>{open ? 'Close' : 'Manage'}
                      </button>
                      <button className="btn btn-ghost btn-sm" title="More actions" aria-label="More actions for this user">
                        <Icon name="sliders" size={11}/>
                      </button>
                    </div>
                  </td>
                </tr>
                {open && (
                  <tr id={`prof-${p.e}`} className="user-profile-row">
                    <td colSpan={8} style={{ background:'var(--surface-3)', padding:0, borderTop:'2px solid var(--beam)' }}>
                      <UserProfileEditor person={p} tab={profileTab} setTab={setProfileTab} onClose={() => setOpenEmail(null)}/>
                    </td>
                  </tr>
                )}
                </React.Fragment>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      <div className="grid grid-3" style={{ marginTop:16 }}>
        <div className="card"><div className="card-body">
          <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)' }}>QUICK LINKS</div>
          <div style={{ fontWeight:700, fontSize:'.94rem', marginTop:6 }}>Role Manager</div>
          <div style={{ fontSize:'.76rem', color:'var(--muted)', marginTop:4 }}>Edit role definitions, permission sets, and role-based routing.</div>
          <button className="btn btn-ghost btn-sm" style={{ marginTop:10 }} onClick={() => window.WPSBD.switchTab('roles')}>Open →</button>
        </div></div>
        <div className="card"><div className="card-body">
          <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)' }}>QUICK LINKS</div>
          <div style={{ fontWeight:700, fontSize:'.94rem', marginTop:6 }}>Permissions Matrix</div>
          <div style={{ fontSize:'.76rem', color:'var(--muted)', marginTop:4 }}>Feature-by-role grid: who can see what and do what.</div>
          <button className="btn btn-ghost btn-sm" style={{ marginTop:10 }} onClick={() => window.WPSBD.switchTab('permissions')}>Open →</button>
        </div></div>
        <div className="card"><div className="card-body">
          <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)' }}>QUICK LINKS</div>
          <div style={{ fontWeight:700, fontSize:'.94rem', marginTop:6 }}>Audit Log</div>
          <div style={{ fontSize:'.76rem', color:'var(--muted)', marginTop:4 }}>Every role change, permission grant, and profile edit is logged.</div>
          <button className="btn btn-ghost btn-sm" style={{ marginTop:10 }} onClick={() => window.WPSBD.switchTab('audit')}>Open →</button>
        </div></div>
      </div>
    </div>
  );
}

/* ── USER PROFILE EDITOR (inline under a Team row) ──────────────── */
function UserProfileEditor({ person, tab, setTab, onClose }) {
  const tabs = [
    { id:'profile',  lbl:'Profile',          icon:'account' },
    { id:'role',     lbl:'Role & Permissions', icon:'shield' },
    { id:'security', lbl:'Security & Sessions', icon:'lock' },
    { id:'activity', lbl:'Activity',         icon:'activity' },
  ];
  return (
    <div style={{ padding:'18px 22px' }}>
      {/* Header strip */}
      <div style={{ display:'flex', alignItems:'center', gap:14, marginBottom:14 }}>
        <div style={{ width:46, height:46, borderRadius:'50%', background:'linear-gradient(135deg, var(--orange), var(--beam))', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'1rem', fontWeight:700, color:'#000', flexShrink:0 }}>
          {person.n.split(' ').map(x => x[0]).join('').slice(0,2)}
        </div>
        <div style={{ flex:1, minWidth:0 }}>
          <div style={{ fontWeight:700, fontSize:'1rem' }}>{person.n}</div>
          <div className="mono" style={{ fontSize:'.7rem', color:'var(--dim)' }}>{person.e} · {person.role} · Joined {person.joined}</div>
        </div>
        <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`Sent password reset to ${person.e}`, 'ok')}><Icon name="refresh" size={11}/>Reset password</button>
        <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`Impersonating ${person.n} (audit logged)`, 'warn')}>Impersonate</button>
        <button className="btn btn-ghost btn-sm" onClick={onClose} aria-label="Close profile editor"><Icon name="x" size={12}/></button>
      </div>

      {/* Tabs */}
      <div className="tw-seg" role="tablist" style={{ marginBottom:14, display:'inline-flex' }}>
        {tabs.map(t => (
          <button key={t.id} role="tab" aria-selected={tab===t.id} className={tab===t.id?'active':''} onClick={() => setTab(t.id)}>
            <Icon name={t.icon} size={11}/>&nbsp;{t.lbl}
          </button>
        ))}
      </div>

      {tab === 'profile' && (
        <div className="grid grid-2">
          <div>
            <Field label="Full name"><input defaultValue={person.n}/></Field>
            <Field label="Email (login)"><input defaultValue={person.e} type="email"/></Field>
            <Field label="Phone"><input defaultValue={person.phone}/></Field>
            <Field label="Location"><input defaultValue={person.loc}/></Field>
          </div>
          <div>
            <Field label="Title / position"><input defaultValue={person.role.includes('SA')?'Platform Owner':person.role}/></Field>
            <Field label="Tenure"><input defaultValue={person.tenure} disabled/></Field>
            <Field label="Time zone"><select defaultValue="America/Los_Angeles"><option>America/Los_Angeles</option><option>America/New_York</option><option>America/Chicago</option><option>Europe/London</option></select></Field>
            <Field label="Avatar">
              <div style={{ display:'flex', gap:8 }}>
                <button className="btn btn-ghost btn-sm">Upload</button>
                <button className="btn btn-ghost btn-sm">Use initials</button>
              </div>
            </Field>
          </div>
          <div style={{ gridColumn:'1 / -1', display:'flex', justifyContent:'flex-end', gap:8, marginTop:8 }}>
            <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
            <button className="btn btn-primary btn-sm" onClick={() => { window.wpsbToast(`Saved profile for ${person.n}`, 'ok'); }}><Icon name="check" size={12}/>Save changes</button>
          </div>
        </div>
      )}

      {tab === 'role' && (
        <div className="grid grid-2">
          <div>
            <Field label="Role">
              <select defaultValue={person.role}>
                <option>Customer</option><option>Partner Agency</option><option>Partner Ops</option>
                <option>Agency Admin</option><option>Support Tech</option><option>Super Admin (SA)</option>
              </select>
            </Field>
            <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)', marginBottom:10 }}>
              Inherits permissions from role → <a href="#" onClick={(e)=>{e.preventDefault();window.WPSBD.switchTab('roles');}}>Edit role definition</a>
            </div>
            <Field label="Scoped accounts">
              <select defaultValue="all"><option value="all">All accounts (Partner admin)</option><option>Lighthaus only</option><option>Riverway Health only</option></select>
            </Field>
          </div>
          <div>
            <Field label="Permission overrides (user-level)">
              <div style={{ display:'flex', flexDirection:'column', gap:6, padding:'10px', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:8 }}>
                {[
                  { k:'Manage billing',        grant:'inherit' },
                  { k:'View audit log',        grant:'allow' },
                  { k:'Delete sites',          grant:'deny' },
                  { k:'Push to Railway',       grant:'inherit' },
                  { k:'Impersonate customers', grant: person.role.includes('SA') ? 'allow' : 'deny' },
                ].map(ov => (
                  <div key={ov.k} style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <span style={{ flex:1, fontSize:'.78rem' }}>{ov.k}</span>
                    <div className="tw-seg" role="group" aria-label={`${ov.k} override`}>
                      {['inherit','allow','deny'].map(g => (
                        <button key={g} className={ov.grant===g?'active':''}>{g}</button>
                      ))}
                    </div>
                  </div>
                ))}
              </div>
            </Field>
          </div>
          <div className="box info" style={{ gridColumn:'1 / -1' }}>
            <Icon name="info" size={14}/><div>Role changes propagate instantly. The user will be re-evaluated on next request and an audit log entry is recorded.</div>
          </div>
          <div style={{ gridColumn:'1 / -1', display:'flex', justifyContent:'flex-end', gap:8 }}>
            <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
            <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast(`Role + permissions saved for ${person.n}`, 'ok')}><Icon name="shield" size={12}/>Save role</button>
          </div>
        </div>
      )}

      {tab === 'security' && (
        <div className="grid grid-2">
          <div className="card"><div className="card-head"><h3 className="card-title">Account security</h3></div>
            <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:10 }}>
              <Field label="Multi-factor">
                <div style={{ display:'flex', gap:8, alignItems:'center' }}>
                  {person.mfa ? <span className="tag ok">ENABLED — Authenticator app</span> : <span className="tag bad">DISABLED</span>}
                  <button className="btn btn-ghost btn-sm">{person.mfa?'Reset MFA':'Require MFA'}</button>
                </div>
              </Field>
              <Field label="Password"><button className="btn btn-ghost btn-sm" style={{ width:'fit-content' }}><Icon name="refresh" size={11}/>Send reset link</button></Field>
              <Field label="Email-login (passwordless)"><div className="tw-seg"><button className="active">Enabled</button><button>Disabled</button></div></Field>
              <Field label="SSO binding"><div className="mono" style={{ fontSize:'.72rem', color:'var(--muted)' }}>Not linked · <a href="#" onClick={e=>e.preventDefault()}>Link Google Workspace</a></div></Field>
            </div>
          </div>
          <div className="card"><div className="card-head"><h3 className="card-title">Active sessions <span className="tag">{person.sessions}</span></h3></div>
            <div className="card-body" style={{ padding:0 }}>
              <table className="table">
                <thead><tr><th scope="col">Device</th><th scope="col">Location</th><th scope="col">Last seen</th><th scope="col"></th></tr></thead>
                <tbody>
                  {person.sessions > 0 ? [
                    { d:'MacBook Pro · Chrome', l:person.loc, t:person.last },
                    ...(person.sessions>1?[{ d:'iPhone 15 · Safari', l:person.loc, t:'3 hr ago' }]:[]),
                    ...(person.sessions>2?[{ d:'iPad · Safari', l:person.loc, t:'Yesterday' }]:[]),
                  ].map((s,i) => (
                    <tr key={i}>
                      <td style={{ fontSize:'.8rem' }}>{s.d}</td>
                      <td className="mono" style={{ fontSize:'.7rem', color:'var(--muted)' }}>{s.l}</td>
                      <td className="mono" style={{ fontSize:'.7rem', color:'var(--dim)' }}>{s.t}</td>
                      <td><button className="btn btn-ghost btn-sm">Revoke</button></td>
                    </tr>
                  )) : (
                    <tr><td colSpan={4} style={{ padding:'18px', textAlign:'center', color:'var(--dim)', fontSize:'.78rem' }}>No active sessions</td></tr>
                  )}
                </tbody>
              </table>
              {person.sessions > 0 && (
                <div style={{ padding:'10px 14px', borderTop:'1px solid var(--border)', textAlign:'right' }}>
                  <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`All sessions revoked — ${person.n} signed out everywhere`, 'warn')}>Revoke all sessions</button>
                </div>
              )}
            </div>
          </div>
          <div className="card" style={{ gridColumn:'1 / -1' }}>
            <div className="card-head" style={{ justifyContent:'space-between' }}>
              <h3 className="card-title">Danger zone</h3>
              <span className="tag bad">IRREVERSIBLE</span>
            </div>
            <div className="card-body" style={{ display:'flex', flexDirection:'column', gap:10 }}>
              <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'10px 12px', border:'1px solid var(--border)', borderRadius:8 }}>
                <div><strong style={{ fontSize:'.84rem' }}>Suspend account</strong>
                  <div style={{ fontSize:'.74rem', color:'var(--dim)' }}>User can't log in. Data retained. Reversible.</div>
                </div>
                <button className="btn btn-ghost btn-sm">Suspend</button>
              </div>
              <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'10px 12px', border:'1px solid var(--border)', borderRadius:8 }}>
                <div><strong style={{ fontSize:'.84rem' }}>Delete account</strong>
                  <div style={{ fontSize:'.74rem', color:'var(--dim)' }}>Hard-deletes profile and transfers ownership of their sites.</div>
                </div>
                <button className="btn btn-ghost btn-sm" style={{ color:'var(--rose)' }}>Delete</button>
              </div>
            </div>
          </div>
        </div>
      )}

      {tab === 'activity' && (
        <div className="card">
          <div className="card-head"><h3 className="card-title">Recent activity</h3><span className="tag">{person.n === 'Dana Whitfield' ? '0' : '42'} events</span></div>
          <div className="card-body" style={{ padding:0 }}>
            {person.n === 'Dana Whitfield' ? (
              <div style={{ padding:'32px', textAlign:'center', color:'var(--dim)', fontSize:'.82rem' }}>
                <Icon name="clock" size={24}/><div style={{ marginTop:8 }}>No activity — invite is still pending.</div>
              </div>
            ) : (
              [
                { when:person.last, what:'Logged in', detail:'via SSO · MacBook Pro · '+person.loc, tone:'ok' },
                { when:'Today',       what:'Changed role',  detail:'Support Tech → Partner Ops (by root@wpsitebeam.io)', tone:'warn' },
                { when:'Yesterday',   what:'Ran scan',      detail:'Site: acme.co — 14 findings', tone:'beam' },
                { when:'2 days ago',  what:'Reset MFA',     detail:'Old authenticator removed, new one enrolled', tone:'warn' },
                { when:'1 week ago',  what:'Accessed billing', detail:'Viewed invoice INV-1428', tone:'' },
                { when:'2 weeks ago', what:'Joined team',   detail:'Account created by Jordan Davis', tone:'beam' },
              ].map((e,i,a) => (
                <div key={i} style={{ padding:'12px 16px', borderBottom: i<a.length-1 ? '1px solid var(--border)':'none', display:'flex', gap:12, alignItems:'flex-start' }}>
                  <div className="mono" style={{ fontSize:'.66rem', color:'var(--dim)', width:90, flexShrink:0 }}>{e.when}</div>
                  <div style={{ flex:1 }}>
                    <div style={{ fontSize:'.82rem', fontWeight:600 }}>{e.what}</div>
                    <div style={{ fontSize:'.74rem', color:'var(--muted)' }}>{e.detail}</div>
                  </div>
                  {e.tone && <span className={`tag ${e.tone}`}>{e.tone.toUpperCase()}</span>}
                </div>
              ))
            )}
          </div>
        </div>
      )}
    </div>
  );
}

/* ── SA: BRAND MANAGER ───────────────────────────────────────── */
function Brand() {
  const { useState } = React;
  const [target, setTarget] = useState('production');
  const envs = [
    { id:'production', lbl:'Production',  sites:142, lastPush:'6 days ago', color:'var(--green)' },
    { id:'staging',    lbl:'Staging',     sites:3,   lastPush:'2 hrs ago',  color:'var(--warn)' },
    { id:'dev',        lbl:'Development', sites:1,   lastPush:'Just now',   color:'var(--beam)' },
  ];
  return (
    <div>
      <PageHead sa crumb="SA · Brand" title="Brand Manager"
        sub="Push logos, colors, and fonts to Railway Remote Config — live without a code deploy. All pushes are logged and revertable."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="clock" size={13}/>History</button>
          <button className="btn btn-primary btn-sm"><Icon name="spark" size={13}/>Push to {envs.find(e => e.id === target).lbl}</button>
        </>}/>

      <div className="box sa" style={{ marginBottom:16 }}>
        <Icon name="flag" size={16}/>
        <div><strong>Remote Config is live.</strong> Changes pushed here take effect within ~30s across all targeted sites. WPSB chrome is never shown on customer-facing pages — only the agency's white-labeled brand.</div>
      </div>

      <div className="sub-tabs" style={{ marginBottom:0 }}>
        {envs.map(e => (
          <button key={e.id} className={'sub-tab' + (target === e.id ? ' active' : '')} onClick={() => setTarget(e.id)}>
            {e.lbl} ({e.sites})
          </button>
        ))}
      </div>

      <div className="grid grid-3" style={{ marginTop:16 }}>
        {envs.map(e => (
          <div key={e.id} className="card" style={{ borderColor: target === e.id ? e.color : 'var(--border)' }}>
            <div className="card-body">
              <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                <div style={{ width:8, height:8, borderRadius:'50%', background: e.color }}/>
                <div style={{ fontWeight:700, fontSize:'.9rem' }}>{e.lbl}</div>
              </div>
              <div style={{ marginTop:8, fontSize:'.76rem', color:'var(--muted)' }}>{e.sites} sites receiving config</div>
              <div className="mono" style={{ fontSize:'.7rem', color:'var(--dim)', marginTop:4 }}>Last push: {e.lastPush}</div>
            </div>
          </div>
        ))}
      </div>

      <div className="grid" style={{ gridTemplateColumns:'1fr 360px', marginTop:16, alignItems:'start', gridAutoRows:'auto' }}>
        <div className="card">
          <div className="card-head">
            <h2 className="card-title">Brand Configuration · {envs.find(e => e.id === target).lbl}</h2>
            <span className="tag beam">LIVE</span>
          </div>
          <div className="card-body">
            <div className="grid grid-2" style={{ gridAutoRows:'auto' }}>
              <Field label="Agency name"><input defaultValue="WPSiteBeam"/></Field>
              <Field label="Product tagline"><input defaultValue="WordPress care done right"/></Field>
              <Field label="Primary color (hex)"><input className="mono" defaultValue="#f0a830"/></Field>
              <Field label="Accent color (hex)"><input className="mono" defaultValue="#00cfef"/></Field>
              <Field label="Brand font (heading)"><input defaultValue="Orbitron"/></Field>
              <Field label="Body font"><input defaultValue="DM Sans"/></Field>
            </div>

            <div className="field" style={{ marginTop:8 }}>
              <label>Logo assets</label>
              <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
                {['Primary SVG','Dark SVG','Favicon','Email header'].map(l => (
                  <div key={l} style={{ padding:'14px 16px', background:'var(--surface-3)', border:'1px dashed var(--border-2)', borderRadius:8, display:'flex', flexDirection:'column', alignItems:'center', gap:6, minWidth:120 }}>
                    <div style={{ width:40, height:40, borderRadius:6, background:'linear-gradient(135deg, var(--orange), var(--beam))', display:'flex', alignItems:'center', justifyContent:'center', color:'#000', fontWeight:800, fontFamily:'var(--font-brand)' }}>CD</div>
                    <div className="mono" style={{ fontSize:'.64rem', color:'var(--dim)' }}>{l}</div>
                    <button className="btn btn-ghost btn-sm" style={{ padding:'4px 8px', fontSize:'.7rem' }}>Replace</button>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>

        <div className="card" style={{ position:'sticky', top:16 }}>
          <div className="card-head"><h2 className="card-title">Live preview</h2><span className="tag">CLIENT VIEW</span></div>
          <div className="card-body" style={{ padding:0 }}>
            <div style={{ background:'#fff', padding:18, borderBottom:'1px solid var(--border)' }}>
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <div style={{ width:30, height:30, borderRadius:6, background:'linear-gradient(135deg, #f0a830, #00cfef)', display:'flex', alignItems:'center', justifyContent:'center', color:'#000', fontWeight:800, fontFamily:'Orbitron,sans-serif' }}>CD</div>
                <div style={{ fontFamily:'Orbitron,sans-serif', fontWeight:700, fontSize:'.88rem', color:'#0F172A' }}>CONCEPTUALIZED DESIGN</div>
              </div>
              <div style={{ marginTop:14, fontFamily:'DM Sans,sans-serif', fontSize:'1.1rem', fontWeight:700, color:'#0F172A' }}>Good morning, Jordan</div>
              <div style={{ fontFamily:'DM Sans,sans-serif', fontSize:'.78rem', color:'var(--dim)', marginTop:2 }}>WordPress care done right</div>
              <button style={{ marginTop:12, padding:'8px 16px', background:'var(--orange)', color:'#000', border:'none', borderRadius:6, fontFamily:'DM Sans,sans-serif', fontWeight:600, fontSize:'.78rem' }}>Run a scan</button>
            </div>
            <div style={{ padding:12, fontSize:'.7rem', color:'var(--dim)', fontFamily:'var(--font-mono)', textAlign:'center' }}>
              No WPSB branding visible to customers ✓
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── SA: STUB for remaining ──────────────────────────────────── */
function SAStub({ title, sub }) {
  return (
    <div>
      <PageHead sa crumb="SA · Command" title={title} sub={sub}/>
      <div className="box sa">
        <Icon name="info" size={16}/>
        <div><strong>{title}</strong> — wired in from the real app. This prototype keeps the layout + nav consistent; full content comes from the live module.</div>
      </div>
    </div>
  );
}

/* ── TASK BOARD (Customer / Partner / SA) ────────────────────── */
function Tasks() {
  const { useState } = React;
  const [view, setView] = useState('kanban');
  const cols = [
    { id:'backlog', title:'Backlog',     tone:'',     count:5 },
    { id:'todo',    title:'To Do',       tone:'beam', count:3 },
    { id:'doing',   title:'In Progress', tone:'warn', count:2 },
    { id:'review',  title:'Review',      tone:'beam', count:2 },
    { id:'done',    title:'Done',        tone:'ok',   count:8 },
  ];
  const cards = {
    backlog: [
      { id:'TSK-051', t:'Add page-speed alerts to dashboard', site:'acme.co', pri:'low',  tags:['idea'] },
      { id:'TSK-050', t:'Migrate blog from Medium → WP',     site:'shop.acme.co', pri:'med', tags:['migration'] },
    ],
    todo: [
      { id:'TSK-049', t:'Run Q4 brand-asset scan',           site:'acme.co', pri:'med',  tags:['scan'], assignee:'JM', due:'Fri' },
      { id:'TSK-048', t:'Renew SSL on shop.acme.co',         site:'shop.acme.co', pri:'high', tags:['security'], assignee:'CD', due:'Today' },
      { id:'TSK-047', t:'Approve homepage hero copy',        site:'acme.co', pri:'med',  tags:['content'], assignee:'JM', due:'Mon' },
    ],
    doing: [
      { id:'TSK-046', t:'Build proposal for County of Lincoln', site:'—',    pri:'high', tags:['estimator'], assignee:'CD', due:'Wed' },
      { id:'TSK-045', t:'301 redirect map for blog migration',  site:'acme.co', pri:'med', tags:['migration'], assignee:'JM', due:'Thu' },
    ],
    review: [
      { id:'TSK-044', t:'Plugin audit: 18 plugins flagged',     site:'shop.acme.co', pri:'high', tags:['security'], assignee:'CD' },
      { id:'TSK-043', t:'Footer redesign — 3 variants',         site:'acme.co', pri:'low', tags:['design'], assignee:'JM' },
    ],
    done: [
      { id:'TSK-042', t:'Site speed audit — 87 → 94 PageSpeed', site:'acme.co', pri:'med', tags:['performance'], assignee:'CD' },
      { id:'TSK-041', t:'Add cookie banner', site:'acme.co', pri:'low', tags:['compliance'], assignee:'JM' },
    ],
  };
  const priTone = { high:'bad', med:'warn', low:'' };

  return (
    <div>
      <PageHead crumb="Workflow" title="📋 Task Board"
        sub="Track work across all sites. Sync with Workspace threads, Estimator proposals, and Scanner findings."
        actions={<>
          <div className="tw-seg">
            {[['kanban','Kanban'],['list','List'],['gantt','Timeline']].map(([id,lbl]) => (
              <button key={id} className={view===id?'active':''} onClick={()=>setView(id)}>{lbl}</button>
            ))}
          </div>
          <button className="btn btn-ghost btn-sm"><Icon name="search" size={13}/>Filter</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>New task</button>
        </>}/>

      <div className="grid grid-4" style={{ marginBottom:16 }}>
        <div className="stat"><div className="stat-lbl">Open</div><div className="stat-val">12</div></div>
        <div className="stat"><div className="stat-lbl">Due this week</div><div className="stat-val warn">5</div></div>
        <div className="stat"><div className="stat-lbl">Overdue</div><div className="stat-val bad">1</div></div>
        <div className="stat"><div className="stat-lbl">Completed (30d)</div><div className="stat-val ok">28</div></div>
      </div>

      {view === 'kanban' && (
        <div className="kanban" style={{ gridTemplateColumns:`repeat(${cols.length}, minmax(0, 1fr))` }}>
          {cols.map(c => (
            <div key={c.id} className="card" style={{ background:'var(--surface-2)' }}>
              <div className="card-head" style={{ padding:'10px 12px' }}>
                <div style={{ display:'flex', alignItems:'center', gap:6 }}>
                  <span className={`tag ${c.tone}`}>{c.title}</span>
                  <span className="mono" style={{ fontSize:'.7rem', color:'var(--dim)' }}>{(cards[c.id]||[]).length}</span>
                </div>
                <button className="card-action" title="Add"><Icon name="plus" size={12}/></button>
              </div>
              <div className="card-body" style={{ padding:8, display:'flex', flexDirection:'column', gap:8 }}>
                {(cards[c.id] || []).map(card => (
                  <div key={card.id} style={{
                    background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, padding:10,
                    display:'flex', flexDirection:'column', gap:6, cursor:'pointer'
                  }}>
                    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center' }}>
                      <span className="mono" style={{ fontSize:'.66rem', color:'var(--muted)' }}>{card.id}</span>
                      <span className={`tag ${priTone[card.pri]}`} style={{ fontSize:'.62rem', padding:'1px 6px' }}>{card.pri.toUpperCase()}</span>
                    </div>
                    <div style={{ fontSize:'.82rem', fontWeight:500, lineHeight:1.4 }}>{card.t}</div>
                    {card.site !== '—' && <div style={{ fontSize:'.7rem', color:'var(--dim)' }}>🌐 {card.site}</div>}
                    <div style={{ display:'flex', gap:4, flexWrap:'wrap' }}>
                      {card.tags.map(t => <span key={t} className="tag" style={{ fontSize:'.62rem', padding:'1px 5px' }}>{t}</span>)}
                    </div>
                    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginTop:2 }}>
                      {card.assignee
                        ? <div style={{ width:20, height:20, borderRadius:'50%', background:'var(--beam-dim)', color:'var(--beam)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'.62rem', fontWeight:700 }}>{card.assignee}</div>
                        : <span/>}
                      {card.due && <span className="mono" style={{ fontSize:'.66rem', color: card.due==='Today' ? 'var(--bad)' : 'var(--dim)' }}>📅 {card.due}</span>}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      )}

      {view === 'list' && (
        <div className="card">
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">ID</th><th scope="col">Title</th><th scope="col">Site</th><th scope="col">Status</th><th scope="col">Priority</th><th scope="col">Assignee</th><th scope="col">Due</th></tr></thead>
              <tbody>
                {cols.flatMap(c => (cards[c.id]||[]).map(card => (
                  <tr key={card.id}>
                    <td className="mono" style={{ fontSize:'.74rem', color:'var(--muted)' }}>{card.id}</td>
                    <td style={{ fontWeight:500 }}>{card.t}</td>
                    <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{card.site}</td>
                    <td><span className={`tag ${c.tone}`}>{c.title}</span></td>
                    <td><span className={`tag ${priTone[card.pri]}`}>{card.pri.toUpperCase()}</span></td>
                    <td>{card.assignee || '—'}</td>
                    <td className="mono" style={{ fontSize:'.74rem' }}>{card.due || '—'}</td>
                  </tr>
                )))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {view === 'gantt' && (
        <div className="card">
          <div className="card-head"><h2 className="card-title">This week</h2></div>
          <div className="card-body">
            {[...cards.todo, ...cards.doing, ...cards.review].slice(0,6).map((t, i) => (
              <div key={t.id} style={{ display:'grid', gridTemplateColumns:'180px 1fr 80px', gap:10, alignItems:'center', padding:'8px 0', borderBottom:'1px solid var(--border)' }}>
                <div style={{ fontSize:'.82rem', fontWeight:500 }}>{t.t.slice(0,30)}{t.t.length>30?'…':''}</div>
                <div style={{ height:8, background:'var(--surface-3)', borderRadius:4, position:'relative' }}>
                  <div style={{ position:'absolute', left:`${i*8}%`, width:`${20+i*5}%`, height:'100%', background:'var(--beam)', borderRadius:4 }}/>
                </div>
                <span className="mono" style={{ fontSize:'.7rem', color:'var(--dim)', textAlign:'right' }}>{t.due || 'TBD'}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

/* ── CONTENT (Customer / Partner / SA) ───────────────────────── */
function Content() {
  const { useState } = React;
  const [tab, setTab] = useState('pages');
  const pages = [
    { t:'Home',          path:'/',              status:'published', site:'acme.co',      mod:'2 days ago',   author:'JM' },
    { t:'About Us',      path:'/about',         status:'published', site:'acme.co',      mod:'1 week ago',   author:'JM' },
    { t:'Pricing',       path:'/pricing',       status:'draft',     site:'acme.co',      mod:'3 hrs ago',    author:'CD' },
    { t:'Shop · All',    path:'/shop',          status:'published', site:'shop.acme.co', mod:'Yesterday',    author:'JM' },
    { t:'Privacy Policy',path:'/privacy',       status:'published', site:'acme.co',      mod:'2 months ago', author:'JM' },
    { t:'Contact',       path:'/contact',       status:'review',    site:'acme.co',      mod:'30 min ago',   author:'CD' },
  ];
  const posts = [
    { t:'AI in 2026: What Finance Leaders Need to Know', cat:'Insights', status:'published', site:'acme.co', mod:'4 days ago' },
    { t:'New product launch — coming Nov 1',             cat:'News',     status:'scheduled', site:'acme.co', mod:'in 6 days' },
    { t:'Q3 retrospective',                              cat:'Company',  status:'draft',     site:'acme.co', mod:'2 hrs ago' },
  ];
  const media = 142, blocks = 28;
  const tone = { published:'ok', draft:'', review:'warn', scheduled:'beam' };

  return (
    <div>
      <PageHead crumb="Workflow" title="Site Content"
        sub="Manage pages, posts, media, and reusable blocks across all sites. For SEO performance, keyword tracking, and auto-fixes, see Content SEO."
        actions={<>
          <select style={{ padding:'6px 10px' }}><option>All sites</option><option>acme.co</option><option>shop.acme.co</option></select>
          <button className="btn btn-ghost btn-sm" onClick={() => window.WPSBD?.switchTab?.('seo')} title="Open Content SEO for monitoring, auto-fixes, and keywords">
            <Icon name="spark" size={13}/>Open Content SEO →
          </button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>New content</button>
        </>}/>

      <div className="grid grid-4" style={{ marginBottom:16 }}>
        <div className="stat"><div className="stat-lbl">Pages</div><div className="stat-val">{pages.length}</div></div>
        <div className="stat"><div className="stat-lbl">Posts</div><div className="stat-val">{posts.length}</div></div>
        <div className="stat"><div className="stat-lbl">Media library</div><div className="stat-val">{media}</div></div>
        <div className="stat"><div className="stat-lbl">Reusable blocks</div><div className="stat-val">{blocks}</div></div>
      </div>

      <div className="sub-tabs" role="tablist">
        {[['pages',`Pages (${pages.length})`],['posts',`Posts (${posts.length})`],['media',`Media (${media})`],['blocks',`Blocks (${blocks})`],['policies','Policy Pages']].map(([id,lbl]) => (
          <button key={id} role="tab" aria-selected={(tab===id)} tabIndex={(tab===id)?0:-1} className={'sub-tab' + ((tab===id)?' active':'')} onClick={()=>setTab(id)}>{lbl}</button>
        ))}
      </div>

      {(tab === 'pages' || tab === 'posts') && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Title</th><th scope="col">Path / Category</th><th scope="col">Site</th><th scope="col">Status</th><th scope="col">Modified</th><th scope="col">Author</th><th scope="col"></th></tr></thead>
              <tbody>
                {(tab==='pages'?pages:posts).map(p => (
                  <tr key={p.t}>
                    <td style={{ fontWeight:600 }}>{p.t}</td>
                    <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{p.path || p.cat}</td>
                    <td className="mono" style={{ fontSize:'.74rem' }}>{p.site}</td>
                    <td><span className={`tag ${tone[p.status]}`}>{p.status.toUpperCase()}</span></td>
                    <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{p.mod}</td>
                    <td>{p.author || '—'}</td>
                    <td><a href="#" onClick={e=>e.preventDefault()}>Edit</a></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {tab === 'media' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-head">
            <h2 className="card-title">Media Library</h2>
            <button className="btn btn-primary btn-sm"><Icon name="download" size={13}/>Upload</button>
          </div>
          <div className="card-body">
            <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(120px, 1fr))', gap:10 }}>
              {Array.from({length:18}).map((_, i) => (
                <div key={i} style={{ aspectRatio:'1/1', background:`linear-gradient(135deg, oklch(70% .12 ${(i*22)%360}), oklch(55% .14 ${(i*22+45)%360}))`, borderRadius:8, position:'relative' }}>
                  <span style={{ position:'absolute', bottom:4, left:4, fontSize:'.62rem', color:'#fff', textShadow:'0 1px 2px rgba(0,0,0,.5)' }}>img-{(i+1).toString().padStart(3,'0')}.png</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}

      {tab === 'blocks' && (
        <div className="grid grid-2" style={{ marginTop:16 }}>
          {['Hero — Centered','Hero — Split','CTA Banner','Pricing Table','Testimonial Carousel','FAQ Accordion','Footer · Standard','Newsletter Signup'].map(b => (
            <div key={b} className="card">
              <div className="card-body">
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:8 }}>
                  <div style={{ fontWeight:600 }}>🧱 {b}</div>
                  <span className="tag ok">SYNCED</span>
                </div>
                <div style={{ height:80, background:'var(--surface-3)', borderRadius:6, display:'flex', alignItems:'center', justifyContent:'center', fontSize:'.7rem', color:'var(--dim)' }}>Preview</div>
                <div style={{ fontSize:'.72rem', color:'var(--dim)', marginTop:8 }}>Used on 3 sites · Updated 2 days ago</div>
              </div>
            </div>
          ))}
        </div>
      )}

      {tab === 'policies' && (
        <>
          <div className="box info" style={{ marginTop:16, marginBottom:16 }}>
            <Icon name="info" size={16}/>
            <div>Web policy pages (Privacy, Terms, Cookies, Accessibility) are <strong>included free</strong> with every site build via Estimator. Auto-generated and kept current.</div>
          </div>
          <div className="card">
            <div className="card-body" style={{ padding:0 }}>
              <table className="table">
                <thead><tr><th scope="col">Policy</th><th scope="col">Site</th><th scope="col">Last reviewed</th><th scope="col">Auto-update</th><th scope="col"></th></tr></thead>
                <tbody>
                  {['Privacy Policy','Terms of Service','Cookie Policy','Accessibility Statement','GDPR / CCPA Notice'].map(p => (
                    <tr key={p}>
                      <td style={{ fontWeight:500 }}>📋 {p}</td>
                      <td className="mono" style={{ fontSize:'.74rem' }}>acme.co</td>
                      <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>2 weeks ago</td>
                      <td><span className="tag ok">ON</span></td>
                      <td><a href="#" onClick={e=>e.preventDefault()}>Review</a></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ── RESOURCES & OFFERS (shared) ───────────────────────────────
   Catalog of affiliate/partner tools (hosting, SEO, forms, etc.)
   that agencies can surface to their customers via the plugin.
   Used by Marketing (primary home) and the old PartnersSA view.
   SA-only content — editable catalog, sync-to-plugin action. ── */
function ResourcesAndOffers() {
  const { useState } = React;
  const [resCat, setResCat] = useState('all');
  const [resAssoc, setResAssoc] = useState(new Set(['gravity-forms','wpmu-dev','wp-engine','yoast','acf-pro']));
  const RESOURCES = [
    { id:'wp-engine',     name:'WP Engine',         cat:'hosting',    desc:'Managed WordPress hosting trusted by agencies. 4 months free on annual plans.',           offer:'4 mo free',    cta:'Get hosting',    badge:'Premier' },
    { id:'kinsta',        name:'Kinsta',            cat:'hosting',    desc:'Premium managed WordPress on Google Cloud. Free migrations + 2 mo free.',                offer:'2 mo free',    cta:'Try Kinsta' },
    { id:'cloudways',     name:'Cloudways',         cat:'hosting',    desc:'Managed cloud hosting on DO/Vultr/AWS. 30% off first 3 months for WPSB users.',          offer:'30% off 3mo',  cta:'Start trial' },
    { id:'yoast',         name:'Yoast SEO Premium', cat:'seo',        desc:'On-page SEO toolset. Auto-imports redirects into the WPSB Redirect Manager.',            offer:'$10 off',      cta:'Get Yoast',      badge:'Importable' },
    { id:'rank-math',     name:'Rank Math Pro',     cat:'seo',        desc:'AI-driven SEO with built-in schema, redirects, and 404 monitor. Imports into WPSB.',     offer:'15% off',      cta:'Get Rank Math',  badge:'Importable' },
    { id:'smartcrawl',    name:'WPMU SmartCrawl',   cat:'seo',        desc:'Lightweight SEO from WPMU DEV. Sitemap, schema, and redirect rules.',                    offer:'Free trial',   cta:'Try SmartCrawl' },
    { id:'gravity-forms', name:'Gravity Forms',     cat:'forms',      desc:'Advanced form builder. Conditional logic, payments, integrations.',                      offer:'25% off',      cta:'Get Gravity',    badge:'Top pick' },
    { id:'fluentforms',   name:'Fluent Forms Pro',  cat:'forms',      desc:'Fast, lightweight form builder with conversational forms and CRM integrations.',         offer:'$20 off',      cta:'Get Fluent' },
    { id:'formidable',    name:'Formidable Forms',  cat:'forms',      desc:'Solution-focused forms: views, calculators, directories.',                              offer:'10% off',      cta:'Try Formidable' },
    { id:'wp-rocket',     name:'WP Rocket',         cat:'performance', desc:'Caching with lazy load, file optimization, database cleanup.',                          offer:'10% off',      cta:'Get WP Rocket', badge:'Top pick' },
    { id:'perfmatters',   name:'Perfmatters',       cat:'performance', desc:'Lightweight performance plugin to disable bloat & speed up WordPress.',                 offer:'10% off',      cta:'Get Perfmatters' },
    { id:'imagify',       name:'Imagify',           cat:'performance', desc:'Image compression by the WP Rocket team. Free WebP conversion.',                        offer:'15% off',      cta:'Try Imagify' },
    { id:'wordfence',     name:'Wordfence Premium', cat:'security',   desc:'Endpoint firewall, malware scanner, real-time IP blocking, 2FA.',                        offer:'10% off',      cta:'Get Wordfence' },
    { id:'sucuri',        name:'Sucuri Platform',   cat:'security',   desc:'CDN-fronted WAF + malware cleanup with response SLA.',                                   offer:'$30 off',      cta:'Get Sucuri' },
    { id:'edge-security', name:'WPE Global Edge',   cat:'security',   desc:'Cloudflare-powered edge security bundled into WP Engine plans.',                         offer:'Bundle',       cta:'Add to plan' },
    { id:'acf-pro',       name:'ACF Pro',           cat:'dev',        desc:'Advanced Custom Fields Pro — the standard for custom data in WordPress.',               offer:'15% off',      cta:'Get ACF Pro',   badge:'Essential' },
    { id:'jetengine',     name:'JetEngine',         cat:'dev',        desc:'Dynamic content, CPTs, taxonomies, and listings for Elementor/Bricks/Gutenberg.',       offer:'20% off',      cta:'Get JetEngine' },
    { id:'metabox',       name:'Meta Box',          cat:'dev',        desc:'Powerful custom fields & meta data framework. Free + Pro extensions.',                  offer:'Free + Pro',   cta:'Get Meta Box' },
    { id:'woocommerce',   name:'WooCommerce',       cat:'ecom',       desc:'The eCommerce engine for WordPress. Free core + paid extensions.',                      offer:'Free',         cta:'Get Woo',       badge:'Essential' },
    { id:'surecart',      name:'SureCart',          cat:'ecom',       desc:'Modern checkout & subscriptions — hosted, no plugin bloat.',                            offer:'30 days free', cta:'Try SureCart' },
    { id:'wpmu-dev',      name:'WPMU DEV',          cat:'bundle',     desc:'Hosting + Smush + SmartCrawl + Defender + Hummingbird in one membership.',              offer:'1 mo free',    cta:'Get WPMU DEV',  badge:'All-in-one' },
  ];
  const RES_CATS = [
    ['all',         'All',         RESOURCES.length],
    ['hosting',     'Hosting',     RESOURCES.filter(r=>r.cat==='hosting').length],
    ['seo',         'SEO',         RESOURCES.filter(r=>r.cat==='seo').length],
    ['forms',       'Forms',       RESOURCES.filter(r=>r.cat==='forms').length],
    ['performance', 'Performance', RESOURCES.filter(r=>r.cat==='performance').length],
    ['security',    'Security',    RESOURCES.filter(r=>r.cat==='security').length],
    ['dev',         'Dev',         RESOURCES.filter(r=>r.cat==='dev').length],
    ['ecom',        'eCommerce',   RESOURCES.filter(r=>r.cat==='ecom').length],
    ['bundle',      'Bundles',     RESOURCES.filter(r=>r.cat==='bundle').length],
  ];
  const toggleAssoc = (id) => {
    const next = new Set(resAssoc);
    if (next.has(id)) next.delete(id); else next.add(id);
    setResAssoc(next);
  };

  const filtered = RESOURCES.filter(r => resCat === 'all' || r.cat === resCat);
  const sorted = [...filtered].sort((a,b) => (resAssoc.has(b.id)?1:0) - (resAssoc.has(a.id)?1:0));
  const activeInView = Array.from(resAssoc).filter(id => filtered.find(r=>r.id===id)).length;

  return (
    <div style={{ marginTop:16 }}>
      {/* Affiliate disclosure */}
      <div style={{ background:'var(--warn-dim)', border:'1px solid var(--warn-dim)', borderRadius:6, padding:'10px 14px', marginBottom:14, display:'flex', alignItems:'flex-start', gap:8, fontSize:'.78rem', color:'var(--text-2)', lineHeight:1.5 }}>
        <Icon name="info" size={14}/>
        <div>
          Some links below are affiliate or partner links. We may earn a commission if you purchase through them, at no extra cost to you. We only feature tools we believe are genuinely useful for WordPress professionals.
        </div>
      </div>

      {/* Category filter pills */}
      <div style={{ display:'flex', gap:6, flexWrap:'wrap', marginBottom:14 }} role="tablist" aria-label="Resource category">
        {RES_CATS.map(([id,lbl,count]) => (
          <button key={id} role="tab" aria-selected={resCat===id}
                  className={'sub-tab' + (resCat===id ? ' active' : '')}
                  style={{ fontSize:'.72rem', padding:'5px 10px' }}
                  onClick={() => setResCat(id)}>
            {lbl} <span style={{ color:'var(--dim)', marginLeft:4 }}>{count}</span>
          </button>
        ))}
      </div>

      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10, fontSize:'.74rem', color:'var(--dim)' }}>
        <div>
          <strong style={{ color:'var(--text-2)' }}>{activeInView}</strong> active in {resCat === 'all' ? 'all categories' : RES_CATS.find(c=>c[0]===resCat)[1]} · shown first · click ☆ to associate
        </div>
        <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast && window.wpsbToast(`${resAssoc.size} associations synced to plugin`, 'ok')}>
          <Icon name="refresh" size={11}/>Sync to plugin
        </button>
      </div>

      {/* Resource cards */}
      {sorted.length === 0 ? (
        <div style={{ textAlign:'center', padding:'40px 20px', color:'var(--dim)' }}>
          No resources in this category yet.
        </div>
      ) : (
        <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(280px, 1fr))', gap:12 }}>
          {sorted.map(r => {
            const associated = resAssoc.has(r.id);
            return (
              <div key={r.id}
                   style={{ background:'var(--surface)', border:'1px solid', borderColor: associated ? 'var(--orange-dim)' : 'var(--border)', borderRadius:8, padding:14, display:'flex', flexDirection:'column', gap:8, opacity: associated ? 1 : 0.55, transition:'opacity .15s, border-color .15s', position:'relative' }}>
                {associated && <div style={{ position:'absolute', top:0, left:0, right:0, height:2, background:'var(--orange)', borderRadius:'8px 8px 0 0' }}/>}
                <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:8 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:8, minWidth:0 }}>
                    <div style={{ width:32, height:32, borderRadius:6, background:'var(--surface-3)', border:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'center', fontFamily:'var(--font-brand)', fontWeight:700, fontSize:'.82rem', color:'var(--text-2)', flexShrink:0 }}>
                      {r.name.charAt(0)}
                    </div>
                    <div style={{ minWidth:0 }}>
                      <div style={{ fontWeight:600, fontSize:'.86rem', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.name}</div>
                      <div style={{ fontSize:'.62rem', color:'var(--dim)', textTransform:'uppercase', letterSpacing:'.1em', fontFamily:'var(--font-mono)' }}>{(RES_CATS.find(c=>c[0]===r.cat) || [])[1] || r.cat}</div>
                    </div>
                  </div>
                  <button onClick={() => toggleAssoc(r.id)} aria-label={associated ? 'Unassociate' : 'Associate'}
                          style={{ background:'transparent', border:'none', color: associated ? 'var(--orange)' : 'var(--dim)', cursor:'pointer', fontSize:'1.1rem', lineHeight:1, padding:2 }}>
                    {associated ? '★' : '☆'}
                  </button>
                </div>
                <div style={{ fontSize:'.74rem', color:'var(--text-2)', lineHeight:1.45, flex:1 }}>{r.desc}</div>
                <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:8, marginTop:4, paddingTop:8, borderTop:'1px solid var(--border)' }}>
                  <div style={{ display:'flex', gap:4, alignItems:'center', flexWrap:'wrap' }}>
                    <span style={{ background:'var(--green-dim)', color:'var(--green)', padding:'2px 7px', borderRadius:3, fontFamily:'var(--font-mono)', fontSize:'.62rem', letterSpacing:'.04em', border:'1px solid var(--green-dim)' }}>
                      {r.offer}
                    </span>
                    {r.badge && <span style={{ background:'var(--surface-3)', color:'var(--dim)', padding:'2px 7px', borderRadius:3, fontFamily:'var(--font-mono)', fontSize:'.6rem', letterSpacing:'.04em', border:'1px solid var(--border)' }}>{r.badge}</span>}
                  </div>
                  <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast && window.wpsbToast(`Opening ${r.name} (affiliate link)`, 'info')}>
                    {r.cta} ↗
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

/* ── MARKETING (Partner / SA) ────────────────────────────────── */
function Marketing() {
  const { useState } = React;
  const [tab, setTab] = useState('campaigns');
  const campaigns = [
    { n:'Q4 Site Audits Promo',     ch:'Email',   status:'live',     sent:'2,140', open:'34%', click:'8.2%', conv:'42 leads' },
    { n:'Civic ADA Webinar',        ch:'LinkedIn',status:'scheduled',sent:'—',     open:'—',   click:'—',    conv:'—' },
    { n:'Care Plan upsell',         ch:'Email',   status:'live',     sent:'418',   open:'52%', click:'14%',  conv:'7 upgrades' },
    { n:'Holiday eCom checklist',   ch:'Blog',    status:'draft',    sent:'—',     open:'—',   click:'—',    conv:'—' },
  ];
  const leads = [
    { n:'Maple County Council',     src:'Webinar',     stage:'Qualified',  est:'$28k', owner:'CD' },
    { n:'Bramble & Co (eCom)',      src:'Scanner CTA', stage:'Discovery',  est:'$14k', owner:'JM' },
    { n:'Lincoln Public Library',   src:'Referral',    stage:'Proposal',   est:'$22k', owner:'CD' },
  ];
  const tone = { live:'ok', scheduled:'beam', draft:'' };

  return (
    <div>
      <PageHead crumb="Agency" title="📣 Marketing"
        sub="Campaigns, leads, automation, and white-label client outreach."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="download" size={13}/>Export leads</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>New campaign</button>
        </>}/>

      <div className="grid grid-4" style={{ marginBottom:16 }}>
        <div className="stat"><div className="stat-lbl">Active campaigns</div><div className="stat-val">3</div></div>
        <div className="stat"><div className="stat-lbl">Leads (30d)</div><div className="stat-val ok">+47</div></div>
        <div className="stat"><div className="stat-lbl">Pipeline</div><div className="stat-val">$184k</div></div>
        <div className="stat"><div className="stat-lbl">Avg. open rate</div><div className="stat-val">38%</div></div>
      </div>

      <div className="sub-tabs" role="tablist">
        {[['campaigns','Campaigns'],['leads','Leads & Pipeline'],['ghl','GHL Ad Manager'],['pixels','Pixels & Tags'],['automation','Automation'],['templates','Email Templates'],['resources','Resources & Offers']].map(([id,lbl]) => (
          <button key={id} role="tab" aria-selected={(tab===id)} tabIndex={(tab===id)?0:-1} className={'sub-tab' + ((tab===id)?' active':'')} onClick={()=>setTab(id)}>{lbl}</button>
        ))}
      </div>

      {tab === 'ghl' && <GHLAdManager/>}
      {tab === 'pixels' && <PixelsAndTags/>}
      {tab === 'resources' && <ResourcesAndOffers/>}


      {tab === 'campaigns' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Campaign</th><th scope="col">Channel</th><th scope="col">Status</th><th scope="col">Sent</th><th scope="col">Open</th><th scope="col">Click</th><th scope="col">Conversions</th></tr></thead>
              <tbody>
                {campaigns.map(c => (
                  <tr key={c.n}>
                    <td style={{ fontWeight:600 }}>{c.n}</td>
                    <td>{c.ch}</td>
                    <td><span className={`tag ${tone[c.status]}`}>{c.status.toUpperCase()}</span></td>
                    <td className="mono">{c.sent}</td>
                    <td className="mono">{c.open}</td>
                    <td className="mono">{c.click}</td>
                    <td className="mono ok">{c.conv}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {tab === 'leads' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Lead</th><th scope="col">Source</th><th scope="col">Stage</th><th scope="col">Est. value</th><th scope="col">Owner</th><th scope="col"></th></tr></thead>
              <tbody>
                {leads.map(l => (
                  <tr key={l.n}>
                    <td style={{ fontWeight:600 }}>{l.n}</td>
                    <td>{l.src}</td>
                    <td><span className="tag beam">{l.stage}</span></td>
                    <td className="mono ok">{l.est}</td>
                    <td>{l.owner}</td>
                    <td><a href="#" onClick={e=>e.preventDefault()}>Open</a></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {tab === 'automation' && (
        <div className="grid grid-2" style={{ marginTop:16 }}>
          {[
            { n:'Scanner CTA → Lead', desc:'When a public scan finishes, capture email and create lead', status:'on' },
            { n:'Care Plan reminder', desc:'30 days before renewal, send upsell email', status:'on' },
            { n:'Stale proposal bump', desc:'7 days after proposal sent, send polite follow-up', status:'off' },
            { n:'Civic event recap',  desc:'After webinar, send recording + estimator link to attendees', status:'on' },
          ].map(a => (
            <div key={a.n} className="card">
              <div className="card-body">
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:6 }}>
                  <div style={{ fontWeight:600 }}>⚡ {a.n}</div>
                  <span className={`tag ${a.status==='on'?'ok':''}`}>{a.status.toUpperCase()}</span>
                </div>
                <div style={{ fontSize:'.78rem', color:'var(--dim)' }}>{a.desc}</div>
              </div>
            </div>
          ))}
        </div>
      )}

      {tab === 'templates' && (
        <div className="grid grid-2" style={{ marginTop:16 }}>
          {['Welcome — New Site Launch','Care Plan Renewal Reminder','Quarterly Site Health Report','Estimator Proposal Cover','Webinar Invite — Civic','Win-back · 90 days inactive'].map(t => (
            <div key={t} className="card">
              <div className="card-body">
                <div style={{ display:'flex', justifyContent:'space-between' }}>
                  <div style={{ fontWeight:600 }}>✉ {t}</div>
                  <button className="btn btn-ghost btn-sm">Edit</button>
                </div>
                <div style={{ fontSize:'.74rem', color:'var(--dim)', marginTop:6 }}>Used 3× this month · Last sent 4 days ago</div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ── PARTNERS (SA-only) — internal tracking: clients, sub-agencies, commissions, partner program.
      The Resources & Offers tab here is the SA admin view for managing which affiliate offers
      surface in the customer/partner-facing Partner Resources section. ── */
function PartnersSA() {
  const { useState } = React;
  const [tab, setTab] = useState('clients');
  const [resCat, setResCat] = useState('all');
  const [resAssoc, setResAssoc] = useState(new Set(['gravity-forms','wpmu-dev','wp-engine','yoast','acf-pro']));
  const RESOURCES = [
    { id:'wp-engine',     name:'WP Engine',         cat:'hosting',    desc:'Managed WordPress hosting trusted by agencies. 4 months free on annual plans.',           offer:'4 mo free',    cta:'Get hosting',    badge:'Premier' },
    { id:'kinsta',        name:'Kinsta',            cat:'hosting',    desc:'Premium managed WordPress on Google Cloud. Free migrations + 2 mo free.',                offer:'2 mo free',    cta:'Try Kinsta' },
    { id:'cloudways',     name:'Cloudways',         cat:'hosting',    desc:'Managed cloud hosting on DO/Vultr/AWS. 30% off first 3 months for WPSB users.',          offer:'30% off 3mo',  cta:'Start trial' },
    { id:'yoast',         name:'Yoast SEO Premium', cat:'seo',        desc:'On-page SEO toolset. Auto-imports redirects into the WPSB Redirect Manager.',            offer:'$10 off',      cta:'Get Yoast',      badge:'Importable' },
    { id:'rank-math',     name:'Rank Math Pro',     cat:'seo',        desc:'AI-driven SEO with built-in schema, redirects, and 404 monitor. Imports into WPSB.',     offer:'15% off',      cta:'Get Rank Math',  badge:'Importable' },
    { id:'smartcrawl',    name:'WPMU SmartCrawl',   cat:'seo',        desc:'Lightweight SEO from WPMU DEV. Sitemap, schema, and redirect rules.',                    offer:'Free trial',   cta:'Try SmartCrawl' },
    { id:'gravity-forms', name:'Gravity Forms',     cat:'forms',      desc:'Advanced form builder. Conditional logic, payments, integrations.',                      offer:'25% off',      cta:'Get Gravity',    badge:'Top pick' },
    { id:'fluentforms',   name:'Fluent Forms Pro',  cat:'forms',      desc:'Fast, lightweight form builder with conversational forms and CRM integrations.',         offer:'$20 off',      cta:'Get Fluent' },
    { id:'formidable',    name:'Formidable Forms',  cat:'forms',      desc:'Solution-focused forms: views, calculators, directories.',                              offer:'10% off',      cta:'Try Formidable' },
    { id:'wp-rocket',     name:'WP Rocket',         cat:'performance', desc:'Caching with lazy load, file optimization, database cleanup.',                          offer:'10% off',      cta:'Get WP Rocket', badge:'Top pick' },
    { id:'perfmatters',   name:'Perfmatters',       cat:'performance', desc:'Lightweight performance plugin to disable bloat & speed up WordPress.',                 offer:'10% off',      cta:'Get Perfmatters' },
    { id:'imagify',       name:'Imagify',           cat:'performance', desc:'Image compression by the WP Rocket team. Free WebP conversion.',                        offer:'15% off',      cta:'Try Imagify' },
    { id:'wordfence',     name:'Wordfence Premium', cat:'security',   desc:'Endpoint firewall, malware scanner, real-time IP blocking, 2FA.',                        offer:'10% off',      cta:'Get Wordfence' },
    { id:'sucuri',        name:'Sucuri Platform',   cat:'security',   desc:'CDN-fronted WAF + malware cleanup with response SLA.',                                   offer:'$30 off',      cta:'Get Sucuri' },
    { id:'edge-security', name:'WPE Global Edge',   cat:'security',   desc:'Cloudflare-powered edge security bundled into WP Engine plans.',                         offer:'Bundle',       cta:'Add to plan' },
    { id:'acf-pro',       name:'ACF Pro',           cat:'dev',        desc:'Advanced Custom Fields Pro — the standard for custom data in WordPress.',               offer:'15% off',      cta:'Get ACF Pro',   badge:'Essential' },
    { id:'jetengine',     name:'JetEngine',         cat:'dev',        desc:'Dynamic content, CPTs, taxonomies, and listings for Elementor/Bricks/Gutenberg.',       offer:'20% off',      cta:'Get JetEngine' },
    { id:'metabox',       name:'Meta Box',          cat:'dev',        desc:'Powerful custom fields & meta data framework. Free + Pro extensions.',                  offer:'Free + Pro',   cta:'Get Meta Box' },
    { id:'woocommerce',   name:'WooCommerce',       cat:'ecom',       desc:'The eCommerce engine for WordPress. Free core + paid extensions.',                      offer:'Free',         cta:'Get Woo',       badge:'Essential' },
    { id:'surecart',      name:'SureCart',          cat:'ecom',       desc:'Modern checkout & subscriptions — hosted, no plugin bloat.',                            offer:'30 days free', cta:'Try SureCart' },
    { id:'wpmu-dev',      name:'WPMU DEV',          cat:'bundle',     desc:'Hosting + Smush + SmartCrawl + Defender + Hummingbird in one membership.',              offer:'1 mo free',    cta:'Get WPMU DEV',  badge:'All-in-one' },
  ];
  const RES_CATS = [
    ['all',         'All',         RESOURCES.length],
    ['hosting',     'Hosting',     RESOURCES.filter(r=>r.cat==='hosting').length],
    ['seo',         'SEO',         RESOURCES.filter(r=>r.cat==='seo').length],
    ['forms',       'Forms',       RESOURCES.filter(r=>r.cat==='forms').length],
    ['performance', 'Performance', RESOURCES.filter(r=>r.cat==='performance').length],
    ['security',    'Security',    RESOURCES.filter(r=>r.cat==='security').length],
    ['dev',         'Dev',         RESOURCES.filter(r=>r.cat==='dev').length],
    ['ecom',        'eCommerce',   RESOURCES.filter(r=>r.cat==='ecom').length],
    ['bundle',      'Bundles',     RESOURCES.filter(r=>r.cat==='bundle').length],
  ];
  const toggleAssoc = (id) => {
    const next = new Set(resAssoc);
    if (next.has(id)) next.delete(id); else next.add(id);
    setResAssoc(next);
  };
  const clients = [
    { n:'Acme Holdings',         sites:3, plan:'Agency Pro', mrr:'$1,240', since:'Mar 2024', status:'active' },
    { n:'Northwind Trading',     sites:2, plan:'Agency',     mrr:'$680',   since:'Aug 2024', status:'active' },
    { n:'Maple County',          sites:1, plan:'Civic',      mrr:'$875',   since:'Jan 2025', status:'active' },
    { n:'Bramble & Co',          sites:1, plan:'eCom',       mrr:'$595',   since:'Sep 2024', status:'trial' },
    { n:'Lincoln Public Library',sites:1, plan:'Civic',      mrr:'$425',   since:'Feb 2025', status:'active' },
  ];
  const subAgencies = [
    { n:'Pixel Forge Studios',   clients:8,  rev:'$4,820', tier:'Gold',   joined:'Jan 2024' },
    { n:'Beam Digital Co.',      clients:14, rev:'$8,140', tier:'Platinum', joined:'Sep 2023' },
    { n:'Studio North',          clients:3,  rev:'$1,210', tier:'Silver', joined:'Aug 2024' },
  ];
  const tone = { active:'ok', trial:'warn', churned:'bad' };
  const tierTone = { Platinum:'beam', Gold:'warn', Silver:'' };

  return (
    <div>
      <PageHead crumb="Agency" title="🤝 Partners"
        sub="Manage client accounts, sub-agencies, commissions, and the partner program."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="download" size={13}/>Export</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>Invite client</button>
        </>}/>

      <div className="grid grid-4" style={{ marginBottom:16 }}>
        <div className="stat"><div className="stat-lbl">Active clients</div><div className="stat-val">{clients.filter(c=>c.status==='active').length}</div></div>
        <div className="stat"><div className="stat-lbl">Sub-agencies</div><div className="stat-val">{subAgencies.length}</div></div>
        <div className="stat"><div className="stat-lbl">Total MRR</div><div className="stat-val ok">$3,815</div></div>
        <div className="stat"><div className="stat-lbl">Commission (mo)</div><div className="stat-val ok">$762</div></div>
      </div>

      <div className="sub-tabs" role="tablist">
        {[['clients',`Clients (${clients.length})`],['subagencies',`Sub-Agencies (${subAgencies.length})`],['commissions','Commissions'],['program','Partner Program']].map(([id,lbl]) => (
          <button key={id} role="tab" aria-selected={(tab===id)} tabIndex={(tab===id)?0:-1} className={'sub-tab' + ((tab===id)?' active':'')} onClick={()=>setTab(id)}>{lbl}</button>
        ))}
      </div>

      {tab === 'clients' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Client</th><th scope="col">Sites</th><th scope="col">Plan</th><th scope="col">MRR</th><th scope="col">Since</th><th scope="col">Status</th><th scope="col"></th></tr></thead>
              <tbody>
                {clients.map(c => (
                  <tr key={c.n}>
                    <td style={{ fontWeight:600 }}>{c.n}</td>
                    <td className="mono">{c.sites}</td>
                    <td>{c.plan}</td>
                    <td className="mono ok">{c.mrr}</td>
                    <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{c.since}</td>
                    <td><span className={`tag ${tone[c.status]}`}>{c.status.toUpperCase()}</span></td>
                    <td><a href="#" onClick={e=>e.preventDefault()}>Manage</a></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {tab === 'subagencies' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Sub-Agency</th><th scope="col">Clients</th><th scope="col">Monthly Rev</th><th scope="col">Tier</th><th scope="col">Joined</th></tr></thead>
              <tbody>
                {subAgencies.map(s => (
                  <tr key={s.n}>
                    <td style={{ fontWeight:600 }}>{s.n}</td>
                    <td className="mono">{s.clients}</td>
                    <td className="mono ok">{s.rev}</td>
                    <td><span className={`tag ${tierTone[s.tier]}`}>{s.tier}</span></td>
                    <td className="mono" style={{ fontSize:'.74rem', color:'var(--dim)' }}>{s.joined}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {tab === 'commissions' && (
        <>
          <div className="grid grid-2" style={{ marginTop:16 }}>
            <div className="card">
              <div className="card-head"><h2 className="card-title">This month</h2></div>
              <div className="card-body">
                <div style={{ fontSize:'2rem', fontWeight:700, color:'var(--ok)' }}>$762.40</div>
                <div style={{ fontSize:'.78rem', color:'var(--dim)' }}>20% of $3,815 MRR · paid 1st of next month</div>
              </div>
            </div>
            <div className="card">
              <div className="card-head"><h2 className="card-title">Year to date</h2></div>
              <div className="card-body">
                <div style={{ fontSize:'2rem', fontWeight:700 }}>$6,824.10</div>
                <div style={{ fontSize:'.78rem', color:'var(--dim)' }}>9 monthly payouts · Avg $758/mo</div>
              </div>
            </div>
          </div>
          <div className="card" style={{ marginTop:16 }}>
            <div className="card-head"><h2 className="card-title">Recent payouts</h2></div>
            <div className="card-body" style={{ padding:0 }}>
              <table className="table">
                <thead><tr><th scope="col">Period</th><th scope="col">Clients billed</th><th scope="col">MRR base</th><th scope="col">Rate</th><th scope="col">Payout</th><th scope="col">Status</th></tr></thead>
                <tbody>
                  {[['Sep 2025',5,'$3,710','20%','$742.00','paid'],['Aug 2025',5,'$3,580','20%','$716.00','paid'],['Jul 2025',4,'$3,140','20%','$628.00','paid']].map(([p,cl,b,r,pay,st]) => (
                    <tr key={p}>
                      <td style={{ fontWeight:500 }}>{p}</td>
                      <td className="mono">{cl}</td>
                      <td className="mono">{b}</td>
                      <td className="mono">{r}</td>
                      <td className="mono ok">{pay}</td>
                      <td><span className="tag ok">{st.toUpperCase()}</span></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </>
      )}

      {tab === 'program' && (
        <div className="grid grid-3" style={{ marginTop:16 }}>
          {[
            { tier:'Silver',   req:'1+ clients',   rate:'15%', perks:['White-label proposals','Partner badge','Email support'] },
            { tier:'Gold',     req:'5+ clients',   rate:'20%', perks:['Priority support','Co-marketing','Quarterly bonus'] },
            { tier:'Platinum', req:'15+ clients',  rate:'25%', perks:['Dedicated AM','Custom Brain training','Conference invites'] },
          ].map(t => (
            <div key={t.tier} className="card" style={{ borderColor: t.tier==='Gold' ? 'var(--warn)' : t.tier==='Platinum' ? 'var(--beam)' : 'var(--border)' }}>
              <div className="card-head">
                <h2 className="card-title">{t.tier}</h2>
                <span className={`tag ${tierTone[t.tier]}`}>{t.tier === 'Gold' ? 'YOU ARE HERE' : ''}</span>
              </div>
              <div className="card-body">
                <div style={{ fontSize:'2rem', fontWeight:700 }}>{t.rate}</div>
                <div style={{ fontSize:'.78rem', color:'var(--dim)', marginBottom:10 }}>commission · {t.req}</div>
                <ul style={{ paddingLeft:18, margin:0, fontSize:'.82rem', display:'flex', flexDirection:'column', gap:4 }}>
                  {t.perks.map(p => <li key={p}>{p}</li>)}
                </ul>
              </div>
            </div>
          ))}
        </div>
      )}
      {tab === 'resources' && (() => {
        const filtered = RESOURCES.filter(r => resCat === 'all' || r.cat === resCat);
        // associated ones float to top, others greyed out
        const sorted = [...filtered].sort((a,b) => (resAssoc.has(b.id)?1:0) - (resAssoc.has(a.id)?1:0));
        const activeInView = Array.from(resAssoc).filter(id => filtered.find(r=>r.id===id)).length;
        return (
          <div style={{ marginTop:16 }}>
            {/* Affiliate disclosure */}
            <div style={{ background:'var(--warn-dim)', border:'1px solid var(--warn-dim)', borderRadius:6, padding:'10px 14px', marginBottom:14, display:'flex', alignItems:'flex-start', gap:8, fontSize:'.78rem', color:'var(--text-2)', lineHeight:1.5 }}>
              <Icon name="info" size={14}/>
              <div>
                Some links below are affiliate or partner links. We may earn a commission if you purchase through them, at no extra cost to you. We only feature tools we believe are genuinely useful for WordPress professionals.
              </div>
            </div>

            {/* Category filter pills */}
            <div style={{ display:'flex', gap:6, flexWrap:'wrap', marginBottom:14 }} role="tablist" aria-label="Resource category">
              {RES_CATS.map(([id,lbl,count]) => (
                <button key={id} role="tab" aria-selected={resCat===id}
                        className={'btn btn-ghost btn-sm' + (resCat===id?' active':'')}
                        style={resCat===id ? { background:'var(--orange)', color:'#1a0d00', borderColor:'var(--orange)', fontWeight:600 } : null}
                        onClick={() => setResCat(id)}>
                  {lbl}
                  <span style={{ marginLeft:6, opacity:.7, fontSize:'.7em' }}>{count}</span>
                </button>
              ))}
            </div>

            {/* Sub-header showing associations */}
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10, fontSize:'.74rem', color:'var(--dim)' }}>
              <div>
                <strong style={{ color:'var(--text-2)' }}>{activeInView}</strong> active in {resCat === 'all' ? 'all categories' : RES_CATS.find(c=>c[0]===resCat)[1]} · shown first · click ☆ to associate
              </div>
              <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast(`${resAssoc.size} associations synced to plugin`, 'ok')}>
                <Icon name="refresh" size={11}/>Sync to plugin
              </button>
            </div>

            {/* Resource cards */}
            {sorted.length === 0 ? (
              <div style={{ textAlign:'center', padding:'40px 20px', color:'var(--dim)' }}>
                No resources in this category yet.
              </div>
            ) : (
              <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(280px, 1fr))', gap:12 }}>
                {sorted.map(r => {
                  const associated = resAssoc.has(r.id);
                  return (
                    <div key={r.id}
                         style={{ background:'var(--surface)', border:'1px solid', borderColor: associated ? 'var(--orange-dim)' : 'var(--border)', borderRadius:8, padding:14, display:'flex', flexDirection:'column', gap:8, opacity: associated ? 1 : 0.55, transition:'opacity .15s, border-color .15s', position:'relative' }}>
                      {associated && <div style={{ position:'absolute', top:0, left:0, right:0, height:2, background:'var(--orange)', borderRadius:'8px 8px 0 0' }}/>}
                      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:8 }}>
                        <div style={{ display:'flex', alignItems:'center', gap:8, minWidth:0 }}>
                          <div style={{ width:32, height:32, borderRadius:6, background:'var(--surface-3)', border:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'center', fontFamily:'var(--font-brand)', fontWeight:700, fontSize:'.82rem', color:'var(--text-2)', flexShrink:0 }}>
                            {r.name.charAt(0)}
                          </div>
                          <div style={{ minWidth:0 }}>
                            <div style={{ fontWeight:600, fontSize:'.86rem', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.name}</div>
                            <div style={{ fontSize:'.62rem', color:'var(--dim)', textTransform:'uppercase', letterSpacing:'.1em', fontFamily:'var(--font-mono)' }}>{(RES_CATS.find(c=>c[0]===r.cat) || [])[1] || r.cat}</div>
                          </div>
                        </div>
                        <button onClick={() => toggleAssoc(r.id)} aria-label={associated ? 'Unassociate' : 'Associate'}
                                style={{ background:'transparent', border:'none', color: associated ? 'var(--orange)' : 'var(--dim)', cursor:'pointer', fontSize:'1.1rem', lineHeight:1, padding:2 }}>
                          {associated ? '★' : '☆'}
                        </button>
                      </div>
                      <div style={{ fontSize:'.74rem', color:'var(--text-2)', lineHeight:1.45, flex:1 }}>{r.desc}</div>
                      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:8, marginTop:4, paddingTop:8, borderTop:'1px solid var(--border)' }}>
                        <div style={{ display:'flex', gap:4, alignItems:'center', flexWrap:'wrap' }}>
                          <span style={{ background:'var(--green-dim)', color:'var(--green)', padding:'2px 7px', borderRadius:3, fontFamily:'var(--font-mono)', fontSize:'.62rem', letterSpacing:'.04em', border:'1px solid var(--green-dim)' }}>
                            {r.offer}
                          </span>
                          {r.badge && <span style={{ background:'var(--surface-3)', color:'var(--dim)', padding:'2px 7px', borderRadius:3, fontFamily:'var(--font-mono)', fontSize:'.6rem', letterSpacing:'.04em', border:'1px solid var(--border)' }}>{r.badge}</span>}
                        </div>
                        <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast(`Opening ${r.name} (affiliate link)`, 'info')}>
                          {r.cta} ↗
                        </button>
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        );
      })()}
    </div>
  );
}

/* ── DOCS & WIKI (Partner / SA) ──────────────────────────────── */
function Wiki() {
  const { useState } = React;
  const [tab, setTab] = useState('browse');
  const spaces = [
    { n:'Onboarding',     icon:'🚀', count:14, desc:'New client + new team member playbooks' },
    { n:'SOPs',           icon:'📐', count:23, desc:'Standard ops: scans, builds, migrations, support' },
    { n:'Brand & Voice',  icon:'🎨', count:8,  desc:'Logo use, copy guidelines, brand kit per client' },
    { n:'Engineering',    icon:'⚙️', count:31, desc:'Codebase, deployment, plugin internals' },
    { n:'Sales & Pricing',icon:'💰', count:11, desc:'Estimator playbook, objection handling, scripts' },
    { n:'Legal & Policy', icon:'⚖️', count:6,  desc:'MSA, DPA, privacy templates' },
  ];
  const recent = [
    { t:'How to run a brand-asset scan',         space:'SOPs',         author:'CD', mod:'2 hrs ago' },
    { t:'Civic ADA compliance checklist',        space:'SOPs',         author:'JM', mod:'Yesterday' },
    { t:'Estimator: building Civic proposals',   space:'Sales & Pricing', author:'CD', mod:'2 days ago' },
    { t:'Plugin audit playbook',                 space:'Engineering',  author:'CD', mod:'3 days ago' },
    { t:'New employee — first 14 days',          space:'Onboarding',   author:'JM', mod:'1 week ago' },
  ];

  return (
    <div>
      <PageHead crumb="Agency" title="📖 Docs &amp; Wiki"
        sub="Internal knowledge base. SOPs, playbooks, and team docs."
        actions={<>
          <button className="btn btn-ghost btn-sm"><Icon name="search" size={13}/>Search</button>
          <button className="btn btn-primary btn-sm"><Icon name="plus" size={13}/>New doc</button>
        </>}/>

      <div className="card" style={{ marginBottom:16 }}>
        <div className="card-body" style={{ display:'flex', gap:12, alignItems:'center', padding:18 }}>
          <div style={{ width:44, height:44, borderRadius:10, background:'var(--beam-dim)', color:'var(--beam)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'1.3rem' }}>🔎</div>
          <input placeholder="Search 93 docs across 6 spaces…" style={{ flex:1, fontSize:'.92rem' }}/>
          <span className="tag beam">AI-POWERED</span>
        </div>
      </div>

      <div className="sub-tabs" role="tablist">
        {[['browse','Browse Spaces'],['recent','Recent'],['favorites','Favorites'],['drafts','My Drafts']].map(([id,lbl]) => (
          <button key={id} role="tab" aria-selected={(tab===id)} tabIndex={(tab===id)?0:-1} className={'sub-tab' + ((tab===id)?' active':'')} onClick={()=>setTab(id)}>{lbl}</button>
        ))}
      </div>

      {tab === 'browse' && (
        <div className="grid grid-3" style={{ marginTop:16 }}>
          {spaces.map(s => (
            <div key={s.n} className="card" style={{ cursor:'pointer' }}>
              <div className="card-body">
                <div style={{ fontSize:'1.8rem', marginBottom:6 }}>{s.icon}</div>
                <div style={{ fontWeight:700, fontSize:'.95rem' }}>{s.n}</div>
                <div style={{ fontSize:'.74rem', color:'var(--dim)', margin:'4px 0 8px', lineHeight:1.5 }}>{s.desc}</div>
                <div style={{ fontSize:'.72rem', color:'var(--beam)', fontWeight:600 }}>{s.count} docs →</div>
              </div>
            </div>
          ))}
        </div>
      )}

      {tab === 'recent' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Title</th><th scope="col">Space</th><th scope="col">Author</th><th scope="col">Modified</th><th scope="col"></th></tr></thead>
              <tbody>
                {recent.map(d => (
                  <tr key={d.t}>
                    <td style={{ fontWeight:600 }}>📄 {d.t}</td>
                    <td><span className="tag">{d.space}</span></td>
                    <td>{d.author}</td>
                    <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{d.mod}</td>
                    <td><a href="#" onClick={e=>e.preventDefault()}>Open</a></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {tab === 'favorites' && (
        <div className="box info" style={{ marginTop:16 }}>
          <Icon name="info" size={16}/>
          <div>Star any doc to add it here for quick access.</div>
        </div>
      )}

      {tab === 'drafts' && (
        <div className="card" style={{ marginTop:16 }}>
          <div className="card-body" style={{ padding:0 }}>
            <table className="table">
              <thead><tr><th scope="col">Title</th><th scope="col">Space</th><th scope="col">Modified</th><th scope="col"></th></tr></thead>
              <tbody>
                <tr><td style={{ fontWeight:600 }}>✏ Migration runbook v3</td><td><span className="tag">SOPs</span></td><td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>32 min ago</td><td><a href="#" onClick={e=>e.preventDefault()}>Continue</a></td></tr>
                <tr><td style={{ fontWeight:600 }}>✏ Brand voice — finance vertical</td><td><span className="tag">Brand &amp; Voice</span></td><td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>Yesterday</td><td><a href="#" onClick={e=>e.preventDefault()}>Continue</a></td></tr>
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
}

/* ── BRAND PROFILE (Customer / Partner / SA) ─────────────────── */
/* 2026-05-20 — Renamed from exportBrandKitPdf to exportBrandProfilePdf to
   eliminate a global-scope collision. The scanner has its own
   exportBrandKitPdf (in design/scanner/core.jsx, IIFE-scoped) which takes
   data and produces a real per-scan PDF. When tab-brand.jsx (also IIFE)
   looked up `exportBrandKitPdf`, JS fell through to this module-scope
   function, which has hardcoded ACME placeholder branding and ignores
   any data arg. That bug caused real tms-inc.us scans to download a PDF
   full of Acme/Sequoia/YC placeholder. Scanner now reads from
   `window.WPSB.Scanner.exportBrandKitPdf` explicitly; this Brand-Profile
   page function is renamed defensively. */
function exportBrandProfilePdf() {
  // Build a print-optimized standalone HTML doc styled like a Canva brand kit
  // and open it in a new window with auto-print dialog → Save as PDF.
  const brand = {
    name: 'Acme',
    legal: 'Acme Holdings, LLC',
    tagline: 'Finance ops for the AI era',
    about: 'Acme builds AI-powered finance tooling for modern operators. Founded 2021. Backed by Sequoia and Y Combinator.',
    primary: '#ff7a1a',
    colors: [
      { name:'Ember',   hex:'#FF7A1A', role:'Primary'   },
      { name:'Ink',     hex:'#0F172A', role:'Text'      },
      { name:'Mist',    hex:'#F1F5F9', role:'Surface'   },
      { name:'Beam',    hex:'var(--beam)', role:'Accent'    },
      { name:'Forest',  hex:'var(--green)', role:'Success'   },
      { name:'Rose',    hex:'#E11D48', role:'Alert'     },
    ],
    fonts: [
      { name:'Inter',         usage:'UI & Body',      weights:'400 / 500 / 600 / 700' },
      { name:'Orbitron',      usage:'Display / Logo', weights:'700' },
      { name:'JetBrains Mono',usage:'Code & Data',    weights:'400 / 500' },
    ],
    contact: { email:'hello@acme.co', phone:'+1 (415) 555-0123', web:'https://acme.co', addr:'500 Market Street, San Francisco, CA 94105' },
    social:  [ ['LinkedIn','linkedin.com/company/acme'], ['X','@acmehq'], ['Instagram','@acme'], ['YouTube','youtube.com/@acme'] ],
  };

  const swatches = brand.colors.map(c => `
    <div class="sw">
      <div class="chip" style="background:${c.hex}"></div>
      <div class="nm">${c.name}</div>
      <div class="hx">${c.hex}</div>
      <div class="ro">${c.role}</div>
    </div>`).join('');

  const fonts = brand.fonts.map(f => `
    <div class="ft" style="font-family:${f.name==='Orbitron'?'Orbitron':f.name==='JetBrains Mono'?'JetBrains Mono':'Inter'}, system-ui, sans-serif">
      <div class="big">${f.name}</div>
      <div class="sm">${f.usage} · ${f.weights}</div>
      <div class="ab">Aa Bb Cc 0123 — The quick brown fox jumps over the lazy dog.</div>
    </div>`).join('');

  const social = brand.social.map(([k,v]) => `<div class="kv"><span>${k}</span><b>${v}</b></div>`).join('');

  const html = `<!doctype html><html><head><meta charset="utf-8">
    <title>${brand.name} — Brand Kit</title>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Orbitron:wght@700&display=swap" rel="stylesheet">
    <style>
      @page { size: letter; margin: 0; }
      :root { --ink:#0F172A; --dim:#64748B; --mist:#F1F5F9; --pri:${brand.primary}; }
      * { box-sizing: border-box; }
      body { margin:0; font-family: Inter, system-ui, sans-serif; color:var(--ink); background:#fff; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
      .pg { width: 8.5in; min-height: 11in; padding: .75in; page-break-after: always; position:relative; }
      .pg:last-child { page-break-after: auto; }
      .hd { display:flex; align-items:center; justify-content:space-between; border-bottom:1.5px solid var(--ink); padding-bottom:10px; margin-bottom:24px; }
      .hd .mark { font-family: Orbitron, sans-serif; font-size:20px; letter-spacing:2px; }
      .hd .kit  { font-size:11px; letter-spacing:3px; color:var(--dim); text-transform:uppercase; }
      h1 { font-family: Orbitron, sans-serif; font-size: 48px; letter-spacing:-1px; margin: 0 0 6px; }
      h2 { font-family: Orbitron, sans-serif; font-size: 22px; letter-spacing:1px; margin: 0 0 18px; text-transform:uppercase; }
      p  { line-height:1.55; color:var(--ink); }
      .tag { color:var(--pri); font-size:18px; font-weight:600; }
      .cover { height: 9in; display:flex; flex-direction:column; justify-content:space-between; background: linear-gradient(135deg, #fff 0%, #fff 55%, ${brand.primary}14 100%); }
      .cover .hero { flex:1; display:flex; align-items:center; }
      .cover .mark-lg { font-family: Orbitron, sans-serif; font-size: 120px; letter-spacing:-2px; }
      .cover .foot { font-size:11px; color:var(--dim); letter-spacing:2px; text-transform:uppercase; }
      .grid { display:grid; gap:14px; }
      .c3 { grid-template-columns: repeat(3,1fr); }
      .c2 { grid-template-columns: repeat(2,1fr); }
      .sw .chip { aspect-ratio: 1.5; border-radius:10px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.06); }
      .sw .nm { font-weight:700; margin-top:10px; font-size:14px; }
      .sw .hx { font-family: 'JetBrains Mono', monospace; font-size:12px; color:var(--dim); margin-top:2px; }
      .sw .ro { font-size:10px; letter-spacing:1.5px; color:var(--dim); text-transform:uppercase; margin-top:4px; }
      .ft { padding:16px; border:1px solid #E2E8F0; border-radius:10px; margin-bottom:12px; }
      .ft .big { font-size:36px; font-weight:700; line-height:1; }
      .ft .sm  { font-size:11px; color:var(--dim); letter-spacing:1px; text-transform:uppercase; margin-top:6px; }
      .ft .ab  { font-size:16px; color:#334155; margin-top:10px; }
      .logos { display:grid; grid-template-columns: 1fr 1fr; gap:12px; }
      .logo-tile { aspect-ratio:1.6; border:1px solid #E2E8F0; border-radius:10px; display:flex; align-items:center; justify-content:center; font-family:Orbitron; font-size:32px; letter-spacing:-1px; }
      .logo-tile.inv { background:var(--ink); color:#fff; }
      .logo-tile.pri { background:var(--pri); color:#fff; }
      .logo-tile.mist { background:var(--mist); }
      .kv { display:flex; justify-content:space-between; padding:10px 0; border-bottom:1px dashed #CBD5E1; font-size:14px; }
      .kv span { color:var(--dim); }
      .do-dont { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:14px; }
      .do-dont .box { border:1px solid #E2E8F0; border-radius:10px; padding:14px; }
      .do-dont .box h3 { margin:0 0 8px; font-size:13px; letter-spacing:2px; text-transform:uppercase; }
      .do-dont .do  h3 { color:#16A34A; }
      .do-dont .dnt h3 { color:#E11D48; }
      .do-dont li { font-size:12px; line-height:1.6; }
      .ft-stamp { position:absolute; bottom:.5in; left:.75in; right:.75in; display:flex; justify-content:space-between; font-size:10px; color:var(--dim); letter-spacing:1.5px; text-transform:uppercase; }
      @media print { .noprint { display:none !important; } }
      .noprint { position:fixed; top:16px; right:16px; z-index:99; background:var(--ink); color:#fff; border:0; padding:10px 16px; border-radius:8px; font-weight:600; cursor:pointer; font-family:Inter; }
    </style></head><body>

    <button class="noprint" onclick="window.print()">⇩ Save as PDF</button>

    <!-- COVER -->
    <div class="pg cover">
      <div class="hd"><div class="mark">${brand.name.toUpperCase()}</div><div class="kit">Brand Kit · v1.0</div></div>
      <div class="hero"><div class="mark-lg">${brand.name}</div></div>
      <div>
        <div class="tag">${brand.tagline}</div>
        <div class="foot" style="margin-top:30px">${brand.legal} · Generated ${new Date().toLocaleDateString('en-US',{month:'long',day:'numeric',year:'numeric'})} · WP Site Beam</div>
      </div>
    </div>

    <!-- LOGO -->
    <div class="pg">
      <div class="hd"><div class="mark">${brand.name.toUpperCase()}</div><div class="kit">01 · Logo & Marks</div></div>
      <h1>Logo</h1>
      <p style="max-width:520px;color:var(--dim)">Always preserve clear space equal to the height of the logomark on all sides. Never stretch, recolor outside the palette, or apply effects.</p>
      <div class="logos" style="margin-top:24px">
        <div class="logo-tile">${brand.name}</div>
        <div class="logo-tile inv">${brand.name}</div>
        <div class="logo-tile pri">${brand.name}</div>
        <div class="logo-tile mist">${brand.name}</div>
      </div>
      <div class="do-dont">
        <div class="box do"><h3>✓ Do</h3>
          <ul><li>Use primary color on light backgrounds</li><li>Use white logomark on dark/photo backgrounds</li><li>Maintain minimum size 24px digital / 0.5in print</li></ul>
        </div>
        <div class="box dnt"><h3>✗ Don't</h3>
          <ul><li>Rotate, skew, or distort the mark</li><li>Place on low-contrast backgrounds</li><li>Apply drop shadows, gradients, or outlines</li></ul>
        </div>
      </div>
      <div class="ft-stamp"><span>${brand.name} Brand Kit</span><span>Page 2</span></div>
    </div>

    <!-- COLORS -->
    <div class="pg">
      <div class="hd"><div class="mark">${brand.name.toUpperCase()}</div><div class="kit">02 · Color Palette</div></div>
      <h1>Colors</h1>
      <p style="max-width:520px;color:var(--dim)">The palette below is canonical. Hex values are the source of truth; RGB/CMYK derive from these. Always meet WCAG AA contrast (4.5:1 text).</p>
      <div class="grid c3" style="margin-top:28px">${swatches}</div>
      <div class="ft-stamp"><span>${brand.name} Brand Kit</span><span>Page 3</span></div>
    </div>

    <!-- TYPE -->
    <div class="pg">
      <div class="hd"><div class="mark">${brand.name.toUpperCase()}</div><div class="kit">03 · Typography</div></div>
      <h1>Typography</h1>
      <p style="max-width:520px;color:var(--dim)">Pair Orbitron for display with Inter for body text. Reserve JetBrains Mono for code, data, and technical context.</p>
      <div style="margin-top:28px">${fonts}</div>
      <div class="ft-stamp"><span>${brand.name} Brand Kit</span><span>Page 4</span></div>
    </div>

    <!-- CONTACT & SOCIAL -->
    <div class="pg">
      <div class="hd"><div class="mark">${brand.name.toUpperCase()}</div><div class="kit">04 · Contact & Identity</div></div>
      <h1>Identity</h1>
      <p style="max-width:520px;color:var(--dim)">${brand.about}</p>
      <div class="grid c2" style="margin-top:28px">
        <div>
          <h2>Contact</h2>
          <div class="kv"><span>Email</span><b>${brand.contact.email}</b></div>
          <div class="kv"><span>Phone</span><b>${brand.contact.phone}</b></div>
          <div class="kv"><span>Website</span><b>${brand.contact.web}</b></div>
          <div class="kv"><span>Address</span><b style="text-align:right;max-width:180px">${brand.contact.addr}</b></div>
        </div>
        <div>
          <h2>Social</h2>
          ${social}
        </div>
      </div>
      <div class="ft-stamp"><span>${brand.name} Brand Kit</span><span>Page 5 · End</span></div>
    </div>

    <script>window.addEventListener('load',()=>setTimeout(()=>window.print(),400));</script>
    </body></html>`;

  const w = window.open('', '_blank');
  if (!w) { window.wpsbToast('Pop-up blocked — allow pop-ups to export PDF', 'err'); return; }
  w.document.open(); w.document.write(html); w.document.close();
  window.wpsbToast('Brand kit PDF ready — use the print dialog to save', 'ok');
}

/* Global brand profile — source of truth consumed by Site Builder,
   Estimator, Marketing campaigns, invoices. Matches the Brand Profile
   form defaults below. Real product reads this from an API. */
window.BRAND_PROFILE = {
  legalName:  'Acme Holdings, LLC',
  displayName:'Acme',
  tagline:    'Finance ops for the AI era',
  about:      'Acme builds AI-powered finance tooling for modern operators. Founded 2021. Backed by Sequoia and Y Combinator.',
  industry:   'finance',
  palette: {
    primary:   'var(--green)',
    secondary: '#6366F1',
    accent:    'var(--rose)',
    neutral:   'var(--border-2)',
  },
  typography: {
    headline: 'Playfair Display',
    body:     'Inter',
    mono:     'JetBrains Mono',
  },
  voice: {
    tone:       'Confident · Direct',
    reading:    'Standard',
    aiNotes:    'Speak like a sharp analyst, not a marketer. Avoid hype words. Use numbers.',
  },
  logo: { primary:'/brand/acme-mark.svg', wordmark:'/brand/acme-wordmark.svg' },
};

function BrandProfile() {
  const { useState, useEffect } = React;
  const [tab, setTab] = useState('identity');
  const [scanState, setScanState] = useState(() => {
    try { return localStorage.getItem('wpsb-brand-scanned') === '1' ? 'done' : 'idle'; } catch(e){ return 'idle'; }
  });
  const [scanUrl, setScanUrl] = useState('https://acme.co');
  const [scanStep, setScanStep] = useState(0);
  // Form hydration key — bump to force-reset defaultValues when a scan completes
  const [formKey, setFormKey] = useState(0);
  // T1.3 (2026-05-18): real /brand/extract response. null = pending or never ran.
  // {__error} = API failed, fall through to fixture. Otherwise = actual API JSON.
  const [apiResult, setApiResult] = useState(null);
  const SCAN_STEPS = [
    'Fetching homepage & sitemap',
    'Extracting logo variants (light/dark/square)',
    'Detecting color palette from CSS',
    'Identifying typography (Google Fonts + system)',
    'Scanning NAP, legal, social profiles',
    'Indexing tone & voice from copy',
    'Compiling Brand Kit',
  ];

  // Scan data shape — starts empty, fills on scan
  const EMPTY_BRAND = {
    legal:'', dba:'', tagline:'', about:'', industry:'other',
    website:'', senderName:'', senderEmail:'', replyTo:'', tz:'ET',
    phoneMain:'', phoneSupport:'', street:'', city:'', state:'', zip:'', country:'US',
    salesEmail:'', supportEmail:'', billingEmail:'', marketingEmail:'', legalEmail:'',
    linkedin:'', twitter:'', instagram:'', youtube:'', github:'', facebook:'',
    entity:'llc', ein:'', tax:'', vat:'',
    privacyOfficer:'', dpa:'', a11yCoord:'',
    colorPrimary:'var(--green)', colorSecondary:'#6366F1', colorAccent:'var(--rose)', colorNeutral:'var(--border-2)',
    fontHead:'', fontBody:'', fontMono:'',
    voice:'confident', readingLevel:'standard', voiceNotes:'',
    company:'ACME',
  };
  // Default to Acme seed so existing demo stays hydrated on fresh loads that were already 'done'
  const ACME_SEED = {
    legal:'Acme Holdings, LLC', dba:'Acme', tagline:'Finance ops for the AI era',
    about:'Acme builds AI-powered finance tooling for modern operators. Founded 2021. Backed by Sequoia and Y Combinator.',
    industry:'finance',
    website:'https://acme.co', senderName:'Acme Team', senderEmail:'hello@acme.co', replyTo:'support@acme.co', tz:'ET',
    phoneMain:'+1 (555) 234-1100', phoneSupport:'+1 (555) 234-1199',
    street:'412 Market St, Suite 800', city:'San Francisco', state:'CA', zip:'94103', country:'US',
    salesEmail:'sales@acme.co', supportEmail:'support@acme.co', billingEmail:'billing@acme.co',
    marketingEmail:'press@acme.co', legalEmail:'legal@acme.co',
    linkedin:'https://linkedin.com/company/acme', twitter:'https://x.com/acme',
    instagram:'https://instagram.com/acme', youtube:'https://youtube.com/@acme', github:'https://github.com/acme', facebook:'',
    entity:'llc', ein:'**-***1234', tax:'', vat:'',
    privacyOfficer:'Jordan Mata · privacy@acme.co', dpa:'legal@acme.co',
    a11yCoord:'Casey Devlin · accessibility@acme.co',
    colorPrimary:'var(--green)', colorSecondary:'#6366F1', colorAccent:'var(--rose)', colorNeutral:'var(--border-2)',
    fontHead:'Playfair Display', fontBody:'Inter', fontMono:'JetBrains Mono',
    voice:'confident', readingLevel:'standard',
    voiceNotes:'Speak like a sharp analyst, not a marketer. Avoid hype words. Use numbers.',
    voiceSrc: 'GPT analysis of homepage copy',
    aboutSrc: 'schema.org/Organization/description',
    taglineSrc: '<meta property="og:description">',
    colorSrc: 'tailwind.config.js tokens',
    fontSrc: 'Google Fonts link tag',
    phoneSrc: 'Google Business Profile · schema.org/PostalAddress',
    addressSrc: 'Google Business Profile · footer NAP',
    emailSrc: 'mailto: links on /contact',
    socialSrc: 'footer icon links + schema.org/Organization/sameAs',
    logoStatus: 'found',
    logoSrc: 'header img.site-logo (800×200 SVG)',
    logoSvg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 60" style="max-width:100%;max-height:100%"><g><circle cx="24" cy="30" r="16" fill="#34D399"/><path d="M 17 30 L 22 35 L 31 24" stroke="#0a0a0a" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/><text x="56" y="40" font-family="Playfair Display, serif" font-size="32" font-weight="700" fill="#0a0a0a" letter-spacing="-1">Acme</text></g></svg>`,
    company:'ACME',
  };

  // Known-brand scan fixtures — used so the demo reflects realistic extraction
  // for domains the user actually types. Real impl: backend scraper.
  const SCAN_FIXTURES = {
    'wpsitebeam.io': {
      legal: 'WPSiteBeam LLC',
      dba: 'WPSiteBeam',
      company: 'WPSITEBEAM',
      senderName: 'WPSiteBeam',
      tagline: 'Web design & development partners for brands that care about the details.',
      taglineSrc: '<meta property="og:description">',
      about: 'WPSiteBeam is the agency time-saving SaaS built for WordPress professionals — scan, migrate, estimate, and report on client sites from one dashboard.',
      aboutSrc: '<meta name="description"> · schema.org/Organization/description',
      industry: 'agency',
      senderEmail: 'hello@wpsitebeam.io',
      replyTo: 'support@wpsitebeam.io',
      phoneMain: '(850) 532-1580', phoneSupport: '(850) 532-1580',
      phoneSrc: 'Google Business Profile · footer NAP',
      street: '4000 Commons Dr W', city: 'Destin', state: 'FL', zip: '32541',
      addressSrc: 'Google Business Profile · schema.org/LocalBusiness/address',
      salesEmail: 'hello@wpsitebeam.io',
      supportEmail: 'support@wpsitebeam.io',
      billingEmail: '',
      marketingEmail: 'marketing@wpsitebeam.io',
      legalEmail: '',
      emailSrc: 'mailto: links on /contact + footer',
      linkedin: 'https://linkedin.com/company/wpsitebeam',
      facebook: 'https://facebook.com/wpsitebeam',
      instagram: 'https://instagram.com/wpsitebeam',
      twitter: '', youtube: '', github: '',
      socialSrc: 'footer icon links + schema.org/Organization/sameAs',
      colorPrimary:'#0F3B5F', colorSecondary:'#F7941D', colorAccent:'#F4D03F', colorNeutral:'#1A2530',
      colorSrc: 'styles.css/:root tokens + logo.svg dominant color',
      fontHead: 'Fraunces', fontBody: 'Inter', fontMono: 'JetBrains Mono',
      fontSrc: 'Google Fonts link tag',
      voice: 'confident',
      voiceNotes: 'Crafted, precise language. Avoid jargon. Emphasize long-term partnership.',
      voiceSrc: 'GPT analysis of homepage + /about copy',
      logoStatus: 'found',
      logoSrc: 'header img.site-logo (1280×320 SVG)',
      // Inline SVG wordmark for WPSiteBeam
      logoSvg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 80" style="max-width:100%;max-height:100%"><text x="0" y="52" font-family="Orbitron,sans-serif" font-size="36" font-weight="700" fill="#F0A830">WPSite</text><text x="162" y="52" font-family="Orbitron,sans-serif" font-size="36" font-weight="700" fill="#00CFEF">Beam</text></svg>`,
    },
    'acme.co': {
      legal: 'Acme Holdings, LLC',
      dba: 'Acme',
      tagline: 'Finance ops for the AI era',
      about: 'Acme builds AI-powered finance tooling for modern operators. Founded 2021. Backed by Sequoia and Y Combinator.',
      aboutSrc: 'schema.org/Organization/description',
      industry: 'finance',
      colorPrimary:'var(--green)', colorSecondary:'#6366F1', colorAccent:'var(--rose)', colorNeutral:'var(--border-2)',
      colorSrc: 'tailwind.config.js tokens',
      fontHead: 'Playfair Display', fontBody: 'Inter', fontMono: 'JetBrains Mono',
      fontSrc: 'Google Fonts link tag',
      voice: 'confident',
      voiceNotes: 'Speak like a sharp analyst, not a marketer. Avoid hype words. Use numbers.',
      voiceSrc: 'GPT analysis of homepage copy',
    },
  };
  function scanResultFor(url) {
    try {
      const host = new URL(/^https?:/.test(url) ? url : 'https://' + url).hostname.replace(/^www\./,'');
      const root = host.split('.').slice(0, -1).join('-') || host;
      // Split concatenated-lowercase words using a common word list (best-effort heuristic)
      const splitWords = (s) => {
        const WORDS = ['conceptualized','design','designs','studio','studios','agency','digital','creative','marketing','brand','branding','web','works','works','group','partners','labs','lab','tech','media','ventures','collective','consulting','solutions','software','systems','holdings','industries','enterprises','capital','global','house','works','space','hub','works'];
        // try greedy longest-match segmentation
        let out = []; let i = 0; const lc = s.toLowerCase();
        while (i < lc.length) {
          let matched = null;
          for (const w of WORDS) { if (lc.startsWith(w, i) && (!matched || w.length > matched.length)) matched = w; }
          if (matched) { out.push(matched); i += matched.length; }
          else {
            // gather one unrecognized chunk up to the next recognized word start
            let j = i + 1;
            while (j < lc.length && !WORDS.some(w => lc.startsWith(w, j))) j++;
            out.push(lc.slice(i, j)); i = j;
          }
        }
        return out.join(' ');
      };
      const rootPhrase = root.replace(/[-_]/g,' ');
      // If root has no word separator but looks like a concatenated name, try splitting
      const needsSplit = !/[-_ ]/.test(root) && root.length > 9;
      const brand = (needsSplit ? splitWords(rootPhrase) : rootPhrase).replace(/\b\w/g, c => c.toUpperCase()).trim();
      const COMPANY = brand.toUpperCase();
      let h = 0; for (const c of root) h = (h*31 + c.charCodeAt(0)) >>> 0;
      const hue = h % 360;
      const toHex = (hue, s, l) => {
        s/=100; l/=100;
        const k = n => (n + hue/30) % 12;
        const a = s * Math.min(l, 1 - l);
        const f = n => Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))));
        return '#' + [f(0),f(8),f(4)].map(v => v.toString(16).padStart(2,'0')).join('');
      };
      // Template fallback (unknown domains)
      const templated = {
        legal: `${brand}, LLC`,
        dba: brand,
        tagline: ``,
        taglineSrc: '⚠ No og:description or h1.tagline detected',
        voiceNotes: ``,
        about: ``,
        aboutSrc: '⚠ Not found — searched: <meta name="description">, schema.org/Organization, /about h1+p, footer bio. Add your own 2–3 sentence bio.',
        industry: 'agency',
        colorPrimary:   toHex(hue, 62, 52),
        colorSecondary: toHex((hue+210)%360, 58, 56),
        colorAccent:    toHex((hue+45)%360, 75, 62),
        colorNeutral:   toHex(hue, 8, 18),
        colorSrc: `⚠ No CSS tokens found — synthesized from domain hash (hue ${hue}°). Replace with real brand colors.`,
        fontHead: 'Inter',
        fontBody: 'Inter',
        fontMono: 'ui-monospace',
        fontSrc: '⚠ No Google Fonts link detected — defaulted to Inter',
        voice: 'confident', readingLevel: 'standard',
        voiceNotes: ``,
        voiceSrc: '⚠ GPT tone analysis (low confidence — review)',
        logoStatus: 'missing',
        logoSrc: '',
      };
      // Overlay any known-brand fixture values (check common variants)
      const fixture = SCAN_FIXTURES[host] || SCAN_FIXTURES[host.replace(/^www\./,'')] || SCAN_FIXTURES[root + '.com'] || {};
      return {
        // Base computed fields
        website: `https://${host}`,
        senderName: `${brand} Team`,
        senderEmail: '',
        replyTo: '',
        tz: 'ET',
        phoneMain: '',
        phoneSupport: '',
        phoneSrc: '⚠ No tel: links or schema.org/PostalAddress detected',
        street: '', city: '', state: '', zip: '', country: 'US',
        addressSrc: '⚠ No address found in footer, GBP, or schema.org',
        salesEmail: '',
        supportEmail: '',
        billingEmail: '',
        marketingEmail: '',
        legalEmail: '',
        emailSrc: '⚠ No mailto: links found',
        linkedin: '',
        twitter: '',
        instagram: '',
        youtube: '',
        github: '',
        facebook: '',
        socialSrc: '⚠ No footer icons or schema.org/Organization/sameAs detected',
        entity: 'llc', ein: '', tax: '', vat: '',
        privacyOfficer: '',
        dpa: '',
        a11yCoord: '',
        company: COMPANY,
        // Templated (overridden by fixture if available)
        ...templated,
        ...fixture,
      };
    } catch(e) {
      return { ...ACME_SEED };
    }
  }

  // T1.3 (2026-05-18): map real /brand/extract response shape → BrandProfile form fields.
  // Starts from a fallback (fixture or templated) so fields the API doesn't cover
  // (EIN, billing email, voice notes, etc.) are preserved. Overlays API findings
  // where present. Each field also updates its *Src indicator so the user knows
  // where the value came from.
  function mapApiToBrandData(api, fallback) {
    const merged = { ...fallback };
    if (!api || api.__error) return merged;

    if (api.company?.name) {
      merged.dba = api.company.name;
      merged.legal = api.company.name + ', LLC';
      merged.company = String(api.company.name).toUpperCase();
      merged.senderName = api.company.name + ' Team';
    }
    if (api.company?.tagline) {
      merged.tagline = api.company.tagline;
      merged.taglineSrc = 'h1 on homepage';
    }
    if (api.company?.about) {
      merged.about = api.company.about;
      merged.aboutSrc = '<meta name="description">';
    }
    if (api.company?.website) merged.website = api.company.website;

    if (Array.isArray(api.logos) && api.logos.length > 0) {
      merged.logoStatus = 'found';
      merged.logoSrc = `${api.logos[0].source} (${api.logos.length} candidate${api.logos.length>1?'s':''} found)`;
      merged.logoUrl = api.logos[0].url;
      merged.logoCandidates = api.logos.slice(0, 8);
    } else {
      merged.logoStatus = 'missing';
      merged.logoSrc = '⚠ No logo found in favicon, og:image, header img, or class="logo" tags.';
    }

    if (api.colors?.primary) {
      merged.colorPrimary = api.colors.primary;
      const src = api.colors.source;
      merged.colorSrc =
        src === 'elementor_globals' ? 'Elementor --e-global-color-*' :
        src === 'css_root_vars'     ? ':root { --primary: ... } CSS variables' :
        src === 'frequency_rank'    ? 'Frequency-ranked from CSS files' :
        'CSS extraction';
    }
    if (api.colors?.secondary) merged.colorSecondary = api.colors.secondary;
    if (api.colors?.accent)    merged.colorAccent    = api.colors.accent;
    if (api.colors?.neutrals?.[0]) merged.colorNeutral = api.colors.neutrals[0];

    if (api.fonts?.heading) {
      merged.fontHead = api.fonts.heading;
      merged.fontSrc =
        api.fonts.source === 'google_fonts_only' ? 'Google Fonts link tag' :
        api.fonts.source === 'css_parsed'        ? 'CSS font-family declarations' :
        'Font extraction';
    }
    if (api.fonts?.body) merged.fontBody = api.fonts.body;
    if (api.fonts?.mono) merged.fontMono = api.fonts.mono;

    if (api.contact?.phones?.[0]) {
      merged.phoneMain = api.contact.phones[0];
      merged.phoneSrc = 'tel: links + footer NAP';
    }
    if (api.contact?.emails?.[0]) {
      merged.senderEmail = api.contact.emails[0];
      merged.emailSrc = 'mailto: links + /contact page';
    }
    if (api.contact?.address) {
      const a = api.contact.address;
      if (a.street) merged.street = a.street;
      if (a.city)   merged.city   = a.city;
      if (a.state)  merged.state  = a.state;
      if (a.zip)    merged.zip    = a.zip;
      merged.addressSrc = 'footer NAP + schema.org/PostalAddress';
    }
    if (Array.isArray(api.contact?.socials)) {
      for (const s of api.contact.socials) {
        if (!s || !s.url) continue;
        const p = String(s.platform || '').toLowerCase();
        if (p === 'linkedin')  merged.linkedin  = s.url;
        if (p === 'facebook')  merged.facebook  = s.url;
        if (p === 'instagram') merged.instagram = s.url;
        if (p === 'twitter' || p === 'x') merged.twitter = s.url;
        if (p === 'youtube')   merged.youtube   = s.url;
        if (p === 'github')    merged.github    = s.url;
      }
      if (api.contact.socials.length > 0) merged.socialSrc = 'footer icons + schema.org/Organization/sameAs';
    }

    merged.__extracted_at = api.extracted_at;
    merged.__elapsed_ms = api.elapsed_ms;
    return merged;
  }

  const [brandData, setBrandData] = useState(() => {
    try {
      const saved = localStorage.getItem('wpsb-brand-data-v4');
      if (saved) return JSON.parse(saved);
    } catch(e){}
    return scanState === 'done' ? { ...ACME_SEED } : { ...ACME_SEED }; // seed preview with Acme
  });
  const saveBrandData = (d) => {
    setBrandData(d);
    try { localStorage.setItem('wpsb-brand-data-v4', JSON.stringify(d)); } catch(e){}
    setFormKey(k => k + 1);
  };

  useEffect(() => {
    const fn = (e) => { if (e.detail) setTab(e.detail); };
    window.addEventListener('wpsb:brand-subtab', fn);
    return () => window.removeEventListener('wpsb:brand-subtab', fn);
  }, []);
  useEffect(() => {
    if (scanState !== 'running') return;
    if (scanStep >= SCAN_STEPS.length) {
      // Visual stepper has finished its 7 fake steps. Now wait for the real
      // API to come back (if still pending). When apiResult lands, this effect
      // re-fires because apiResult is in the deps array.
      if (apiResult === null) return;
      // Both visual + API done. Merge.
      const fixture = scanResultFor(scanUrl);
      const usingApi = apiResult && !apiResult.__error;
      const result = usingApi ? mapApiToBrandData(apiResult, fixture) : fixture;
      saveBrandData(result);
      setScanState('done');
      try { localStorage.setItem('wpsb-brand-scanned', '1'); } catch(e){}
      const msg = usingApi
        ? `Brand Scan complete — live extraction from ${scanUrl} (${apiResult.elapsed_ms||'?'}ms)`
        : `Brand Scan complete — fallback (API: ${apiResult?.__error || 'unavailable'}). Review fields and update.`;
      window.wpsbToast?.(msg, usingApi ? 'ok' : 'warn');
      return;
    }
    const t = setTimeout(() => setScanStep(s => s + 1), 550);
    return () => clearTimeout(t);
  }, [scanState, scanStep, apiResult]);
  const startScan = () => {
    setScanStep(0);
    setScanState('running');
    setApiResult(null);
    // Kick off real backend extraction in parallel with visual stepper.
    // Visual stepper takes ~3.85s (7 × 550ms). API call typically 3-8s.
    // useEffect waits for the LATER of the two to complete before finalizing.
    (async () => {
      const url = /^https?:\/\//.test(scanUrl) ? scanUrl : 'https://' + scanUrl;
      const apiBase = window.WPSB_API_BASE || 'https://wpsitebeam-railway-api-production.up.railway.app';
      try {
        const token = window.WPSB?.getToken?.();
        const r = await fetch(apiBase + '/brand/extract', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            ...(token ? { 'Authorization': 'Bearer ' + token } : {}),
          },
          body: JSON.stringify({ url }),
        });
        const json = await r.json();
        if (!r.ok) {
          setApiResult({ __error: json.error || ('HTTP ' + r.status) });
        } else {
          setApiResult(json);
        }
      } catch(e) {
        setApiResult({ __error: e.message || 'Network error' });
      }
    })();
  };
  const resetScan = () => {
    try {
      localStorage.removeItem('wpsb-brand-scanned');
      localStorage.removeItem('wpsb-brand-data-v4');
    } catch(e){}
    setScanState('idle'); setScanStep(0);
    saveBrandData({ ...ACME_SEED });
  };
  const b = brandData;

  return (
    <div>
      <PageHead crumb="Account" title="🎨 Brand Profile"
        sub="Your company's brand identity. Used across invoices, estimator proposals, marketing emails, automations, and the customer portal."
        actions={<>
          <button className="btn btn-ghost btn-sm" onClick={exportBrandProfilePdf}><Icon name="download" size={13}/>Export brand kit</button>
          <button className="btn btn-primary btn-sm"><Icon name="check" size={13}/>Save changes</button>
        </>}/>

      <div className="box info" style={{ marginBottom:16 }}>
        <Icon name="info" size={16}/>
        <div>This profile is the source of truth for branding everywhere — billing emails, proposal PDFs, marketing campaigns, white-label client portals. Changes propagate within ~5 minutes.</div>
      </div>

      {/* ── Brand Scan — auto-populate from live website ───────── */}
      {scanState !== 'done' && (
        <div className="card" style={{
          marginBottom:16, padding:0, overflow:'hidden', position:'relative',
          background:'linear-gradient(135deg, var(--orange-dim), rgba(80,200,200,.08))',
          borderColor:'var(--orange-soft)',
        }}>
          {/* ornamental scanning beam */}
          <div aria-hidden="true" style={{
            position:'absolute', inset:0, pointerEvents:'none',
            background:'radial-gradient(600px 180px at 50% 0%, var(--orange-dim), transparent 70%)',
          }}/>
          <div style={{ padding:'22px 24px 20px', position:'relative' }}>
            {scanState === 'idle' && (
              <div style={{ display:'grid', gridTemplateColumns:'auto 1fr auto', gap:20, alignItems:'center' }}>
                <div style={{
                  width:56, height:56, borderRadius:14,
                  background:'linear-gradient(135deg, var(--orange), var(--beam))',
                  display:'flex', alignItems:'center', justifyContent:'center',
                  boxShadow:'0 8px 24px -8px var(--orange-dim)',
                }}>
                  <Icon name="scanner" size={26} style={{ color:'#0a0a0a' }}/>
                </div>
                <div style={{ minWidth:0 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
                    <div style={{ fontSize:'1.1rem', fontWeight:700, color:'var(--text)' }}>Start with a Brand Scan</div>
                    <span className="tag" style={{ background:'var(--orange-soft)', color:'var(--orange)', border:'1px solid var(--orange-soft)', fontSize:'.6rem' }}>RECOMMENDED</span>
                    <span style={{ fontSize:'.62rem', color:'var(--dim)', fontFamily:'var(--font-mono)', letterSpacing:'.1em', textTransform:'uppercase' }}>~90 seconds</span>
                  </div>
                  <div style={{ fontSize:'.84rem', color:'var(--muted)', marginBottom:10, lineHeight:1.5 }}>
                    Enter your website and we'll extract your logo, colors, fonts, contact info, and socials automatically — then you can customize anything below.
                  </div>
                  <div style={{ display:'flex', gap:8, alignItems:'stretch' }}>
                    <div style={{ flex:1, position:'relative', maxWidth:420 }}>
                      <Icon name="globe" size={14} style={{ position:'absolute', left:12, top:'50%', transform:'translateY(-50%)', color:'var(--dim)' }}/>
                      <input
                        value={scanUrl}
                        onChange={e => setScanUrl(e.target.value)}
                        placeholder="https://your-company.com"
                        style={{
                          width:'100%', padding:'10px 12px 10px 34px', fontSize:'.88rem',
                          background:'var(--surface)', border:'1px solid var(--border-2)',
                          borderRadius:8, color:'var(--text)', fontFamily:'var(--font-mono)',
                        }}
                      />
                    </div>
                    <button className="btn btn-primary" onClick={startScan} style={{ padding:'0 20px', fontSize:'.86rem', whiteSpace:'nowrap' }}>
                      <Icon name="spark" size={14}/>Scan my website
                    </button>
                  </div>
                  <div style={{ marginTop:10, display:'flex', gap:14, flexWrap:'wrap', fontSize:'.68rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>
                    <span><Icon name="check" size={10} style={{ color:'var(--green)' }}/> Logo + 4 variants</span>
                    <span><Icon name="check" size={10} style={{ color:'var(--green)' }}/> Color palette</span>
                    <span><Icon name="check" size={10} style={{ color:'var(--green)' }}/> Typography</span>
                    <span><Icon name="check" size={10} style={{ color:'var(--green)' }}/> NAP + socials</span>
                    <span><Icon name="check" size={10} style={{ color:'var(--green)' }}/> Tone of voice</span>
                  </div>
                </div>
                <button className="btn btn-ghost btn-sm" onClick={() => setScanState('skipped')} style={{ alignSelf:'start', whiteSpace:'nowrap' }}>
                  Skip — I'll fill manually
                </button>
              </div>
            )}
            {scanState === 'running' && (
              <div>
                <div style={{ display:'flex', alignItems:'center', gap:12, marginBottom:14 }}>
                  <div className="spinner" style={{ width:22, height:22, borderWidth:3 }}/>
                  <div style={{ minWidth:0, flex:1 }}>
                    <div style={{ fontSize:'.98rem', fontWeight:700, color:'var(--text)', marginBottom:2 }}>
                      Scanning <span className="mono" style={{ color:'var(--orange)' }}>{scanUrl}</span>…
                    </div>
                    <div style={{ fontSize:'.78rem', color:'var(--muted)' }}>
                      Step {Math.min(scanStep + 1, SCAN_STEPS.length)} of {SCAN_STEPS.length}: {SCAN_STEPS[Math.min(scanStep, SCAN_STEPS.length - 1)]}
                    </div>
                  </div>
                  <div style={{ fontSize:'.7rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>
                    {Math.round((scanStep / SCAN_STEPS.length) * 100)}%
                  </div>
                </div>
                <div style={{ height:6, background:'var(--surface-2)', borderRadius:3, overflow:'hidden', marginBottom:12 }}>
                  <div style={{
                    width: `${(scanStep / SCAN_STEPS.length) * 100}%`, height:'100%',
                    background:'linear-gradient(90deg, var(--orange), var(--beam))',
                    transition:'width .4s ease-out',
                  }}/>
                </div>
                <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(180px, 1fr))', gap:6, fontSize:'.72rem', fontFamily:'var(--font-mono)' }}>
                  {SCAN_STEPS.map((s, i) => (
                    <div key={i} style={{
                      display:'flex', alignItems:'center', gap:6, padding:'4px 8px', borderRadius:4,
                      background: i < scanStep ? 'var(--green-dim)' : i === scanStep ? 'var(--orange-dim)' : 'transparent',
                      color: i < scanStep ? 'var(--green)' : i === scanStep ? 'var(--orange)' : 'var(--dim)',
                    }}>
                      {i < scanStep ? <Icon name="check" size={11}/> : i === scanStep ? <span style={{ display:'inline-block', width:8, height:8, borderRadius:'50%', background:'var(--orange)', animation:'wpsbdpulse 1s infinite' }}/> : <span style={{ width:8, height:8, borderRadius:'50%', border:'1px solid var(--border-2)' }}/>}
                      <span style={{ fontSize:'.66rem' }}>{s}</span>
                    </div>
                  ))}
                </div>
              </div>
            )}
            {scanState === 'skipped' && (
              <div style={{ display:'flex', alignItems:'center', gap:12 }}>
                <Icon name="info" size={18} style={{ color:'var(--muted)' }}/>
                <div style={{ flex:1, fontSize:'.84rem', color:'var(--muted)' }}>
                  You're filling out your brand profile manually. Change your mind?
                </div>
                <button className="btn btn-ghost btn-sm" onClick={() => setScanState('idle')}>
                  <Icon name="scanner" size={13}/>Run Brand Scan
                </button>
              </div>
            )}
          </div>
        </div>
      )}

      {scanState === 'done' && (
        <div className="card" style={{
          marginBottom:16, padding:'10px 14px',
          background:'linear-gradient(135deg, var(--green-dim), rgba(80,200,200,.06))',
          borderColor:'var(--green-dim)',
          display:'flex', alignItems:'center', gap:12,
        }}>
          <div style={{
            width:24, height:24, borderRadius:6, flexShrink:0,
            background:'var(--green-dim)', display:'flex', alignItems:'center', justifyContent:'center',
            border:'1px solid var(--green-dim)',
          }}>
            <Icon name="check" size={14} style={{ color:'var(--green)' }}/>
          </div>
          <div style={{ flex:1, minWidth:0, fontSize:'.8rem', color:'var(--muted)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
            <strong style={{ color:'var(--text)', fontWeight:700 }}>Brand Scan complete</strong>
            {' · '}<span className="mono" style={{ color:'var(--green)' }}>{scanUrl}</span>
            {' · '}37 fields auto-populated. Review + customize each step below.
          </div>
          <button className="btn btn-ghost btn-sm" onClick={resetScan} style={{ flexShrink:0 }}>
            <Icon name="refresh" size={12}/>Re-scan
          </button>
        </div>
      )}

      {/* ── Step layout: left stepper + right content ─────────── */}
      {(() => {
        const STEPS = [
          { id:'identity',   lbl:'Company Identity', icon:'building',  desc:'Legal, DBA, tagline' },
          { id:'whitelabel', lbl:'White Label',      icon:'crown',     desc:'Portal customization' },
          { id:'vault',      lbl:'Credential Vault', icon:'lock',      desc:'Licenses & API keys' },
          { id:'logo',       lbl:'Logo & Marks',     icon:'brand',     desc:'4 logo variants' },
          { id:'colors',     lbl:'Colors & Type',    icon:'spark',     desc:'Palette, fonts, tone' },
          { id:'contact',    lbl:'Contact Info',     icon:'support',   desc:'Phone, address, emails' },
          { id:'social',     lbl:'Social & Links',   icon:'globe',     desc:'External profiles' },
          { id:'legal',      lbl:'Legal & Tax',      icon:'shield',    desc:'EIN, entity, DPA' },
          { id:'preview',    lbl:'Preview',          icon:'check',     desc:'How it renders' },
        ];
        const curIdx = Math.max(0, STEPS.findIndex(s => s.id === tab));
        const go = (i) => setTab(STEPS[Math.max(0, Math.min(STEPS.length - 1, i))].id);

        // Demo completeness — in real impl this would reflect actual field fill
        const completed = new Set(['identity','logo','colors','contact']);

        return (
          <div style={{ display:'grid', gridTemplateColumns:'260px 1fr', gap:20, alignItems:'start' }}>
            {/* ── Left rail stepper ─────────────────────────── */}
            <div className="card" style={{ position:'sticky', top:16 }}>
              <div style={{ padding:'14px 16px 8px', borderBottom:'1px solid var(--border)' }}>
                <div style={{ fontSize:'.6rem', color:'var(--dim)', fontFamily:'var(--font-mono)', letterSpacing:'.14em', textTransform:'uppercase', marginBottom:4, fontWeight:700 }}>Setup progress</div>
                <div style={{ display:'flex', alignItems:'baseline', gap:6 }}>
                  <span style={{ fontSize:'1.4rem', fontWeight:800, color:'var(--text)' }}>{completed.size}</span>
                  <span style={{ fontSize:'.78rem', color:'var(--dim)' }}>/ {STEPS.length} complete</span>
                </div>
                <div style={{ marginTop:8, height:4, background:'var(--surface-2)', borderRadius:2, overflow:'hidden' }}>
                  <div style={{ width: `${(completed.size / STEPS.length) * 100}%`, height:'100%', background:'linear-gradient(90deg, var(--orange), var(--beam))' }}/>
                </div>
              </div>
              <div style={{ padding:'8px 0' }} role="tablist" aria-label="Brand profile sections">
                {STEPS.map((st, i) => {
                  const active = st.id === tab;
                  const done = completed.has(st.id);
                  return (
                    <button key={st.id} role="tab" aria-selected={active} tabIndex={active ? 0 : -1}
                      onClick={() => setTab(st.id)}
                      style={{
                        display:'flex', alignItems:'center', gap:12, width:'100%',
                        padding:'10px 14px', background: active ? 'var(--orange-dim)' : 'transparent',
                        border:'none', borderLeft: active ? '3px solid var(--orange)' : '3px solid transparent',
                        color: active ? 'var(--text)' : 'var(--muted)',
                        cursor:'pointer', textAlign:'left', fontFamily:'inherit',
                        borderRadius:0, transition:'background .12s, color .12s',
                      }}>
                      {/* step number badge */}
                      <div style={{
                        width:26, height:26, borderRadius:'50%', flexShrink:0,
                        background: done ? 'var(--green)' : (active ? 'var(--orange)' : 'var(--surface-2)'),
                        color: (done || active) ? '#0a0a0a' : 'var(--muted)',
                        display:'flex', alignItems:'center', justifyContent:'center',
                        fontSize:'.72rem', fontWeight:700, fontFamily:'var(--font-mono)',
                        border: active ? 'none' : '1px solid var(--border)',
                      }}>
                        {done ? <Icon name="check" size={13}/> : (i + 1)}
                      </div>
                      <div style={{ minWidth:0, flex:1 }}>
                        <div style={{ fontSize:'.8rem', fontWeight:active?700:500, lineHeight:1.2, marginBottom:2 }}>{st.lbl}</div>
                        <div style={{ fontSize:'.66rem', color:'var(--dim)', lineHeight:1.3, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{st.desc}</div>
                      </div>
                    </button>
                  );
                })}
              </div>
              <div style={{ padding:'10px 14px', borderTop:'1px solid var(--border)', display:'flex', gap:6 }}>
                <button className="btn btn-ghost btn-sm" style={{ flex:1, opacity: curIdx === 0 ? .4 : 1 }} disabled={curIdx === 0} onClick={() => go(curIdx - 1)}>
                  <Icon name="chevron-left" size={12}/>Back
                </button>
                <button className="btn btn-primary btn-sm" style={{ flex:1, opacity: curIdx === STEPS.length - 1 ? .4 : 1 }} disabled={curIdx === STEPS.length - 1} onClick={() => go(curIdx + 1)}>
                  Next<Icon name="chevron-right" size={12}/>
                </button>
              </div>
            </div>

            {/* ── Right content panel ───────────────────────── */}
            <div>
              <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:12, paddingBottom:10, borderBottom:'1px solid var(--border)' }}>
                <div style={{ fontSize:'.62rem', color:'var(--dim)', fontFamily:'var(--font-mono)', letterSpacing:'.1em', textTransform:'uppercase' }}>Step {curIdx + 1} of {STEPS.length}</div>
                <span style={{ color:'var(--dim)' }}>·</span>
                <div style={{ fontSize:'1.05rem', fontWeight:700, color:'var(--text)' }}>{STEPS[curIdx].lbl}</div>
                <div style={{ flex:1 }}/>
                {completed.has(tab) && (
                  <span style={{ fontSize:'.66rem', color:'var(--green)', background:'var(--green-dim)', padding:'3px 9px', borderRadius:4, border:'1px solid var(--green-dim)', fontWeight:700, display:'inline-flex', alignItems:'center', gap:4 }}>
                    <Icon name="check" size={10}/>Complete
                  </span>
                )}
              </div>

              <div>

      {tab === 'identity' && (
        <div className="grid grid-2" style={{ marginTop:16 }} key={`id-${formKey}`}>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Company</h2></div>
            <div className="card-body">
              <Field label="Legal name"><input defaultValue={b.legal}/></Field>
              <Field label="Display name (DBA)"><input defaultValue={b.dba}/></Field>
              <Field label="Tagline" hint={b.taglineSrc ? `↳ Source: ${b.taglineSrc}` : undefined}><input defaultValue={b.tagline}/></Field>
              <Field label="About / short bio" hint={b.aboutSrc ? `↳ Source: ${b.aboutSrc}` : undefined}>
                <textarea rows={4} defaultValue={b.about}/>
              </Field>
              <Field label="Industry">
              <select defaultValue={b.industry}><option value="finance">Finance / Fintech</option><option value="ecom">eCommerce</option><option value="lms">Education / LMS</option><option value="civic">Civic / Government</option><option value="agency">Agency</option><option value="other">Other</option></select>
            </Field>
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Platform defaults &amp; sender identity</h2></div>
            <div className="card-body">
              <Field label="Primary website"><input defaultValue={b.website} type="url" autoComplete="url"/></Field>
              <Field label="Default sender name"><input defaultValue={b.senderName}/></Field>
              <Field label="Default sender email"><input defaultValue={b.senderEmail}/></Field>
              <Field label="Reply-to"><input defaultValue={b.replyTo}/></Field>
              <Field label="Time zone">
              <select defaultValue={b.tz}><option>America/New_York (ET)</option><option>America/Chicago (CT)</option><option>America/Denver (MT)</option><option>America/Los_Angeles (PT)</option></select>
            </Field>
            </div>
          </div>
        </div>
      )}

      {tab === 'whitelabel' && (window.BrandWhiteLabelTab ? <window.BrandWhiteLabelTab/> : <div style={{padding:24,color:'var(--dim)'}}>Loading White Label...</div>)}

      {tab === 'vault' && (window.CredentialVaultTab ? <window.CredentialVaultTab/> : <div style={{padding:24,color:'var(--dim)'}}>Loading Credential Vault...</div>)}

      {tab === 'logo' && (
        <div key={`logo-${formKey}`} style={{ marginTop:16 }}>
          {/* Source strip: show where these logos came from */}
          <div className="card" style={{ marginBottom:16, background: b.logoStatus === 'found' ? 'rgba(52,211,153,0.06)' : b.logoStatus === 'missing' ? 'rgba(240,168,48,0.08)' : 'var(--surface-2)' }}>
            <div className="card-body" style={{ display:'flex', alignItems:'center', gap:14, padding:14 }}>
              <div style={{ width:44, height:44, borderRadius:10, background: b.logoStatus === 'found' ? 'rgba(52,211,153,0.18)' : 'rgba(240,168,48,0.18)', display:'flex', alignItems:'center', justifyContent:'center', flex:'0 0 auto' }}>
                <Icon name={b.logoStatus === 'found' ? 'check' : 'info'} size={20} color={b.logoStatus === 'found' ? 'var(--green)' : 'var(--orange)'}/>
              </div>
              <div style={{ flex:1, minWidth:0 }}>
                {b.logoStatus === 'found' && (<>
                  <div style={{ fontWeight:600, fontSize:'.88rem' }}>Logo extracted from {b.website.replace(/^https?:\/\//,'')}</div>
                  <div style={{ fontSize:'.72rem', color:'var(--dim)', fontFamily:'var(--font-mono)', marginTop:3 }}>↳ Source: {b.logoSrc}</div>
                </>)}
                {b.logoStatus === 'missing' && (<>
                  <div style={{ fontWeight:600, fontSize:'.88rem' }}>No logo detected on {b.website.replace(/^https?:\/\//,'') || 'this site'}</div>
                  <div style={{ fontSize:'.72rem', color:'var(--dim)', marginTop:3 }}>We searched: header img, <span style={{fontFamily:'var(--font-mono)'}}>link rel="icon"</span>, og:image, schema.org/Organization/logo. Upload your own, or generate one.</div>
                </>)}
                {b.logoStatus === 'none' && (<>
                  <div style={{ fontWeight:600, fontSize:'.88rem' }}>No site scan URL provided</div>
                  <div style={{ fontSize:'.72rem', color:'var(--dim)', marginTop:3 }}>Enter a website on step 1 to auto-extract logos, or upload / generate from scratch.</div>
                </>)}
              </div>
              {(b.logoStatus === 'missing' || b.logoStatus === 'none') && (
                <div style={{ display:'flex', gap:8, flex:'0 0 auto' }}>
                  <button className="btn btn-ghost btn-sm"><Icon name="upload" size={13}/>Upload</button>
                  <button className="btn btn-primary btn-sm" onClick={()=>window.__WPSB_NAV?.('kitbuilder')}><Icon name="sparkles" size={13}/>Generate with Kit Builder</button>
                </div>
              )}
            </div>
          </div>

          <div className="grid grid-2">
            {[
              { lbl:'Primary logo (light bg)',  bg:'#fff',    fg:'#0a0a0a', variant:'primary' },
              { lbl:'Inverted (dark bg)',       bg:'#0a0a0a', fg:'#fff',    variant:'inverted' },
              { lbl:'Square mark / favicon',    bg:'#fff',    fg:'#0a0a0a', sq:true, variant:'mark' },
              { lbl:'Email signature mark',     bg:'#fff',    fg:'#0a0a0a', small:true, variant:'signature' },
            ].map(l => {
              const hasLogo = b.logoStatus === 'found' && b.logoUrl;
              const boxHeight = l.small ? 96 : l.sq ? 160 : 140;
              return (
                <div key={l.lbl} className="card">
                  <div className="card-head"><h2 className="card-title">{l.lbl}</h2><span className="tag">{hasLogo ? 'PNG · SVG · WebP' : 'Not set'}</span></div>
                  <div className="card-body">
                    <div style={{
                      background:l.bg, color:l.fg, height:boxHeight, borderRadius:8,
                      display:'flex', alignItems:'center', justifyContent:'center',
                      border:'1px solid var(--border)', overflow:'hidden', padding:16,
                      position:'relative'
                    }}>
                      {hasLogo ? (
                        // Render the extracted logo — use SVG wordmark from fixture, else <img>
                        b.logoSvg ? (
                          <div
                            style={{
                              maxWidth:'100%', maxHeight:'100%', display:'flex',
                              alignItems:'center', justifyContent:'center',
                              filter: l.variant === 'inverted' ? 'invert(1) hue-rotate(180deg)' : 'none'
                            }}
                            dangerouslySetInnerHTML={{ __html: b.logoSvg }}
                          />
                        ) : (
                          <img src={b.logoUrl} alt={b.dba + ' logo'}
                            style={{ maxWidth:'100%', maxHeight:'100%', objectFit:'contain',
                              filter: l.variant === 'inverted' ? 'invert(1)' : 'none' }}/>
                        )
                      ) : (
                        // No logo — show placeholder wordmark or icon
                        l.sq ? (
                          <div style={{
                            fontFamily:'var(--font-brand)', fontWeight:700,
                            fontSize:'3rem', color:'var(--dim)',
                            border:'2px dashed var(--border)', borderRadius:8,
                            width:88, height:88, display:'flex', alignItems:'center', justifyContent:'center'
                          }}>{(b.dba && b.dba[0]) || '?'}</div>
                        ) : (
                          <div style={{ textAlign:'center', color:'var(--dim)' }}>
                            <div style={{ fontFamily:'var(--font-brand)', fontSize:l.small?'1.1rem':'1.4rem', fontWeight:700, letterSpacing:1, opacity:.4 }}>{b.dba || b.company || 'No logo'}</div>
                            <div style={{ fontSize:'.66rem', marginTop:6, fontFamily:'var(--font-mono)' }}>⚠ placeholder — {b.logoStatus === 'missing' ? 'not found on scan' : 'no scan URL'}</div>
                          </div>
                        )
                      )}
                    </div>
                    <div style={{ display:'flex', gap:6, marginTop:10 }} className="row-actions">
                      <button className="btn btn-ghost btn-sm"><Icon name="upload" size={12}/>{hasLogo ? 'Replace' : 'Upload'}</button>
                      {hasLogo && <button className="btn btn-ghost btn-sm"><Icon name="download" size={12}/>Download</button>}
                      {!hasLogo && <button className="btn btn-ghost btn-sm" onClick={()=>window.__WPSB_NAV?.('kitbuilder')}><Icon name="sparkles" size={12}/>Generate</button>}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {tab === 'colors' && (
        <div key={`colors-${formKey}`}>
          <div className="card" style={{ marginTop:16 }}>
            <div className="card-head"><h2 className="card-title">Color palette</h2><span className="tag">Auto-extracted from {b.website.replace(/^https?:\/\//,'') || 'brand scan'}</span></div>
            <div className="card-body">
              <div className="grid grid-4">
                {[
                  { lbl:'Primary',    hex:b.colorPrimary },
                  { lbl:'Secondary',  hex:b.colorSecondary },
                  { lbl:'Accent',     hex:b.colorAccent },
                  { lbl:'Neutral',    hex:b.colorNeutral },
                ].map(c => (
                  <div key={c.lbl} style={{ display:'flex', flexDirection:'column', gap:6 }}>
                    <div style={{ height:80, borderRadius:10, background:c.hex, border:'1px solid var(--border)' }}/>
                    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', fontSize:'.78rem' }}>
                      <strong>{c.lbl}</strong>
                      <span className="mono" style={{ color:'var(--dim)' }}>{c.hex}</span>
                    </div>
                  </div>
                ))}
              </div>
              <button className="btn btn-ghost btn-sm" style={{ marginTop:14 }}><Icon name="plus" size={13}/>Add color</button>
              {b.colorSrc && <div style={{ fontSize:'.62rem', color: b.colorSrc.startsWith('⚠') ? 'var(--warn)' : 'var(--dim)', fontFamily:'var(--font-mono)', marginTop:10 }}>↳ Source: {b.colorSrc}</div>}
            </div>
          </div>
          <div className="grid grid-2" style={{ marginTop:16 }}>
            <div className="card">
              <div className="card-head"><h2 className="card-title">Typography</h2></div>
              <div className="card-body">
                <Field label="Headline font"><input defaultValue={b.fontHead}/></Field>
                <Field label="Body font"><input defaultValue={b.fontBody}/></Field>
                <Field label="Mono font"><input defaultValue={b.fontMono}/></Field>
                {b.fontSrc && <div style={{ fontSize:'.62rem', color: b.fontSrc.startsWith('⚠') ? 'var(--warn)' : 'var(--dim)', fontFamily:'var(--font-mono)', marginTop:4 }}>↳ Source: {b.fontSrc}</div>}
              </div>
            </div>
            <div className="card">
              <div className="card-head"><h2 className="card-title">Tone &amp; voice</h2></div>
              <div className="card-body">
                <Field label="Brand voice">
              <select defaultValue={b.voice}><option value="confident">Confident · Direct</option><option value="friendly">Friendly · Conversational</option><option value="formal">Formal · Professional</option><option value="playful">Playful · Bold</option></select>
            </Field>
                <Field label="Reading level">
              <div className="tw-seg" role="group" aria-label="Reading level">
                <button className={b.readingLevel==='casual'?'active':''}>Casual</button>
                <button className={b.readingLevel==='standard'?'active':''}>Standard</button>
                <button className={b.readingLevel==='technical'?'active':''}>Technical</button>
              </div>
            </Field>
                <Field label="AI voice notes" hint={b.voiceSrc ? `↳ Source: ${b.voiceSrc}` : undefined}>
              <textarea rows={3} defaultValue={b.voiceNotes}/>
            </Field>
              </div>
            </div>
          </div>
        </div>
      )}

      {tab === 'contact' && (
        <div className="grid grid-2" style={{ marginTop:16 }} key={`contact-${formKey}`}>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Phone &amp; address</h2>{b.phoneSrc && <span className="tag" style={{ color: b.phoneSrc.startsWith('⚠') ? 'var(--warn)' : 'var(--dim)' }}>↳ {b.phoneSrc.startsWith('⚠') ? 'Not found' : 'Found'}</span>}</div>
            <div className="card-body">
              <Field label="Main phone" hint={b.phoneSrc ? `↳ Source: ${b.phoneSrc}` : undefined}><input defaultValue={b.phoneMain} placeholder={b.phoneSrc && b.phoneSrc.startsWith('⚠') ? 'Not found — add manually' : ''}/></Field>
              <Field label="Support phone"><input defaultValue={b.phoneSupport}/></Field>
              <Field label="Street address" hint={b.addressSrc ? `↳ Source: ${b.addressSrc}` : undefined}><input defaultValue={b.street} placeholder={b.addressSrc && b.addressSrc.startsWith('⚠') ? 'Not found — add manually' : ''}/></Field>
              <div className="grid grid-3" style={{ gap:8 }}>
                <Field label="City"><input defaultValue={b.city}/></Field>
                <Field label="State"><input defaultValue={b.state}/></Field>
                <Field label="Zip"><input defaultValue={b.zip}/></Field>
              </div>
              <Field label="Country"><select defaultValue={b.country}><option value="US">United States</option><option value="CA">Canada</option><option value="UK">United Kingdom</option><option value="OTHER">Other</option></select></Field>
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Email aliases</h2>{b.emailSrc && <span className="tag" style={{ color: b.emailSrc.startsWith('⚠') ? 'var(--warn)' : 'var(--dim)' }}>↳ {b.emailSrc.startsWith('⚠') ? 'Not found' : 'Found'}</span>}</div>
            <div className="card-body">
              <Field label="Sales" hint={b.emailSrc ? `↳ Source: ${b.emailSrc}` : undefined}><input defaultValue={b.salesEmail} placeholder={b.emailSrc && b.emailSrc.startsWith('⚠') ? 'Not found — add manually' : ''}/></Field>
              <Field label="Support"><input defaultValue={b.supportEmail} placeholder="Leave blank if not found"/></Field>
              <Field label="Billing"><input defaultValue={b.billingEmail} placeholder="Leave blank if not found"/></Field>
              <Field label="Marketing"><input defaultValue={b.marketingEmail} placeholder="Leave blank if not found"/></Field>
              <Field label="Legal / DPA"><input defaultValue={b.legalEmail} placeholder="Leave blank if not found"/></Field>
            </div>
          </div>
        </div>
      )}

      {tab === 'social' && (
        <div className="card" style={{ marginTop:16 }} key={`social-${formKey}`}>
          <div className="card-head"><h2 className="card-title">Social &amp; external links</h2>{b.socialSrc && <span className="tag" style={{ color: b.socialSrc.startsWith('⚠') ? 'var(--warn)' : 'var(--dim)' }}>↳ {b.socialSrc.startsWith('⚠') ? 'Not found' : 'Found'}</span>}</div>
          <div className="card-body">
            <div className="grid grid-2">
              {[
                ['LinkedIn',    b.linkedin],
                ['X / Twitter', b.twitter],
                ['Instagram',   b.instagram],
                ['YouTube',     b.youtube],
                ['GitHub',      b.github],
                ['Facebook',    b.facebook],
              ].map(([k,v]) => (
                <div key={k} className="field"><label>{k}</label><input defaultValue={v} placeholder="https:// — leave blank if not found"/></div>
              ))}
            </div>
            {b.socialSrc && <div style={{ fontSize:'.7rem', color: b.socialSrc.startsWith('⚠') ? 'var(--warn)' : 'var(--dim)', fontFamily:'var(--font-mono)', marginTop:12, paddingTop:10, borderTop:'1px solid var(--border)' }}>↳ Source: {b.socialSrc}</div>}
          </div>
        </div>
      )}

      {tab === 'legal' && (
        <div className="grid grid-2" style={{ marginTop:16 }} key={`legal-${formKey}`}>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Tax &amp; entity</h2></div>
            <div className="card-body">
              <Field label="Entity type">
              <select defaultValue={b.entity}><option value="llc">LLC</option><option value="corp">C-Corp</option><option value="scorp">S-Corp</option><option value="sole">Sole Prop</option><option value="nonprofit">Non-profit</option><option value="gov">Government</option></select>
            </Field>
              <Field label="EIN / Tax ID"><input defaultValue={b.ein} placeholder="XX-XXXXXXX"/></Field>
              <Field label="Sales tax registration #"><input defaultValue={b.tax} placeholder="(optional)"/></Field>
              <Field label="VAT / GST (intl)"><input defaultValue={b.vat} placeholder="(optional)"/></Field>
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h2 className="card-title">Compliance contacts</h2></div>
            <div className="card-body">
              <Field label="Privacy officer"><input defaultValue={b.privacyOfficer}/></Field>
              <Field label="Data protection (DPA)"><input defaultValue={b.dpa}/></Field>
              <Field label="Accessibility coordinator"><input defaultValue={b.a11yCoord}/></Field>
            </div>
          </div>
        </div>
      )}

      {tab === 'preview' && (
        <>
          <div className="box info" style={{ marginTop:16, marginBottom:16 }}>
            <Icon name="spark" size={16}/>
            <div>Live preview of how your brand renders across the platform. These templates pull from the fields above.</div>
          </div>
          <div className="grid grid-2">
            <div className="card">
              <div className="card-head"><h2 className="card-title">Invoice email</h2><span className="tag">BILLING</span></div>
              <div className="card-body">
                <div style={{ border:'1px solid var(--border)', borderRadius:8, padding:14, background:'#fff', color:'#0a0a0a' }}>
                  <div style={{ fontFamily:'var(--font-brand)', fontSize:'1.4rem', fontWeight:700, color:'#0a0a0a', marginBottom:10 }}>ACME</div>
                  <div style={{ fontSize:'.84rem', marginBottom:8 }}>Invoice #INV-1042 · April 19, 2026</div>
                  <div style={{ fontSize:'.78rem', color:'#444' }}>Hi Jordan, your monthly invoice is ready. Total due: $39.00.</div>
                  <button style={{ marginTop:10, padding:'8px 14px', borderRadius:6, background:'var(--green)', color:'#0a0a0a', fontWeight:600, fontSize:'.78rem', border:'none' }}>View invoice →</button>
                  <div style={{ fontSize:'.66rem', color:'#888', marginTop:14 }}>Acme Holdings, LLC · 412 Market St, San Francisco CA 94103 · billing@acme.co</div>
                </div>
              </div>
            </div>
            <div className="card">
              <div className="card-head"><h2 className="card-title">Estimator proposal cover</h2><span className="tag">ESTIMATOR</span></div>
              <div className="card-body">
                <div style={{ border:'1px solid var(--border)', borderRadius:8, padding:14, background:'linear-gradient(135deg,#34D399,#6366F1)', color:'#fff', minHeight:160, display:'flex', flexDirection:'column', justifyContent:'space-between' }}>
                  <div style={{ fontFamily:'var(--font-brand)', fontSize:'1.4rem', fontWeight:700 }}>ACME</div>
                  <div>
                    <div style={{ fontSize:'1.1rem', fontWeight:700, marginBottom:4 }}>Website Build Proposal</div>
                    <div style={{ fontSize:'.8rem', opacity:.9 }}>Prepared for Maple County · April 2026</div>
                  </div>
                </div>
              </div>
            </div>
            <div className="card">
              <div className="card-head"><h2 className="card-title">Marketing email header</h2><span className="tag">MARKETING</span></div>
              <div className="card-body">
                <div style={{ border:'1px solid var(--border)', borderRadius:8, overflow:'hidden', background:'#fff' }}>
                  <div style={{ background:'#0a0a0a', padding:14 }}>
                    <div style={{ fontFamily:'var(--font-brand)', fontSize:'1.2rem', fontWeight:700, color:'var(--green)' }}>ACME</div>
                  </div>
                  <div style={{ padding:14, color:'#0a0a0a', fontSize:'.84rem' }}>
                    <strong>Q4 site audits — book before Nov 15</strong>
                    <p style={{ margin:'6px 0 0', color:'#444', fontSize:'.78rem' }}>Free brand-asset extraction + speed audit for active care-plan clients.</p>
                  </div>
                </div>
              </div>
            </div>
            <div className="card">
              <div className="card-head"><h2 className="card-title">Client portal header</h2><span className="tag">PORTAL</span></div>
              <div className="card-body">
                <div style={{ border:'1px solid var(--border)', borderRadius:8, padding:14, background:'#0a0a0a', color:'#fff' }}>
                  <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
                    <div style={{ fontFamily:'var(--font-brand)', fontSize:'1.1rem', fontWeight:700, color:'var(--green)' }}>ACME</div>
                    <div style={{ fontSize:'.74rem', color:'#888' }}>support@acme.co · +1 (555) 234-1199</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </>
      )}
              </div>
            </div>
          </div>
        );
      })()}
    </div>
  );
}

/* ─────────────────────────────────────────────────────────────
   GHL Ad Manager — tab inside Marketing
   Thin rollup of GoHighLevel Ad Manager data pulled via OAuth.
   Edits and deep management happen in GHL ("Open in GHL ↗").
   ───────────────────────────────────────────────────────────── */
function GHLAdManager() {
  const { useState } = React;
  const [subAcct, setSubAcct] = useState('wpsb-prod');
  const SUB_ACCOUNTS = [
    { id:'wpsb-prod',   name:'WP Site Beam (Prod)',    loc:'loc_WPSBProd01',   status:'connected' },
    { id:'wpsb',        name:'WPSiteBeam',  loc:'loc_WPSB2026',   status:'connected' },
    { id:'maple',       name:'Maple County Council',   loc:'loc_MapleCnty884', status:'connected' },
    { id:'bramble',     name:'Bramble & Co (eCom)',    loc:'loc_Bramble2099',  status:'connected' },
    { id:'demo',        name:'Demo Customer Site',     loc:'—',                status:'not-connected' },
  ];
  const cur = SUB_ACCOUNTS.find(s => s.id === subAcct);

  // Demo data per sub-account (spend, campaigns, revenue attribution)
  const DATA = {
    'wpsb-prod':  { kpi:{ spend:4280,  rev:38420, conv:94, ctr:3.1, cpl:45.5, roas:8.98 },
      channels:[{ p:'Google Ads', spend:2840, conv:62, ctr:3.4 }, { p:'Meta Ads', spend:1180, conv:26, ctr:2.6 }, { p:'LinkedIn', spend:260, conv:6, ctr:1.9 }],
      campaigns:[
        { n:'WPSB — Agency leads (Search)',   p:'Google Ads', st:'active', spend:1820, conv:42, rev:21400, cpl:43.3, status:'ok' },
        { n:'Scanner CTA — Retargeting',      p:'Meta Ads',   st:'active', spend: 820, conv:18, rev: 9800, cpl:45.5, status:'ok' },
        { n:'Civic audits — LinkedIn',        p:'LinkedIn',   st:'active', spend: 260, conv: 6, rev: 4200, cpl:43.3, status:'ok' },
        { n:'Care Plan — Prospecting',        p:'Meta Ads',   st:'paused', spend: 360, conv: 8, rev: 3020, cpl:45.0, status:'paused' },
        { n:'Brand — Google Ads',             p:'Google Ads', st:'active', spend:1020, conv:20, rev:nothing(), cpl:51.0, status:'warn' },
      ],
    },
    'cd':  { kpi:{ spend:1820, rev:12840, conv:38, ctr:2.7, cpl:47.9, roas:7.06 },
      channels:[{ p:'Google Ads', spend:1120, conv:24, ctr:2.9 }, { p:'Meta Ads', spend:520, conv:10, ctr:2.4 }, { p:'Pinterest', spend:180, conv:4, ctr:1.8 }],
      campaigns:[
        { n:'CD — Web design leads (Search)', p:'Google Ads', st:'active', spend:820, conv:18, rev:7200, cpl:45.6, status:'ok' },
        { n:'CD — Retargeting',               p:'Meta Ads',   st:'active', spend:420, conv: 8, rev:3240, cpl:52.5, status:'warn' },
        { n:'CD — Pinterest creative',        p:'Pinterest',  st:'active', spend:180, conv: 4, rev:1440, cpl:45.0, status:'ok' },
        { n:'CD — Display (Brand)',           p:'Google Ads', st:'active', spend:300, conv: 6, rev:  960, cpl:50.0, status:'warn' },
        { n:'CD — Meta prospecting',          p:'Meta Ads',   st:'paused', spend:100, conv: 2, rev:    0, cpl:50.0, status:'paused' },
      ],
    },
    'maple': { kpi:{ spend:1240, rev:0, conv:58, ctr:4.2, cpl:21.4, roas:null },
      channels:[{ p:'Google Ads', spend:980, conv:46, ctr:4.6 }, { p:'Meta Ads', spend:260, conv:12, ctr:3.0 }],
      campaigns:[
        { n:'Maple — Civic engagement (Search)', p:'Google Ads', st:'active', spend:620, conv:28, rev:0, cpl:22.1, status:'ok' },
        { n:'Maple — ADA webinar signups',       p:'Google Ads', st:'active', spend:360, conv:18, rev:0, cpl:20.0, status:'ok' },
        { n:'Maple — Event retargeting',         p:'Meta Ads',   st:'active', spend:260, conv:12, rev:0, cpl:21.7, status:'ok' },
      ],
    },
    'bramble': { kpi:{ spend:3120, rev:28440, conv:142, ctr:2.9, cpl:22.0, roas:9.12 },
      channels:[{ p:'Meta Ads', spend:1680, conv:84, ctr:3.3 }, { p:'Google Ads', spend:1140, conv:48, ctr:2.7 }, { p:'TikTok', spend:300, conv:10, ctr:2.1 }],
      campaigns:[
        { n:'Bramble — DPA (Meta)',           p:'Meta Ads',   st:'active', spend:980, conv:52, rev:14840, cpl:18.8, status:'ok' },
        { n:'Bramble — Shopping (Google)',    p:'Google Ads', st:'active', spend:820, conv:34, rev:10240, cpl:24.1, status:'ok' },
        { n:'Bramble — TikTok creative',      p:'TikTok',     st:'active', spend:300, conv:10, rev: 2200, cpl:30.0, status:'warn' },
        { n:'Bramble — Meta retargeting',     p:'Meta Ads',   st:'active', spend:700, conv:32, rev: 1160, cpl:21.9, status:'warn' },
        { n:'Bramble — Brand (Google)',       p:'Google Ads', st:'active', spend:320, conv:14, rev:    0, cpl:22.9, status:'ok' },
      ],
    },
  };

  function nothing(){ return 0; }

  const d = DATA[subAcct];
  const isConnected = cur.status === 'connected';

  return (
    <div style={{ marginTop:16, display:'grid', gap:16 }}>
      {/* Sub-account picker + connection meta */}
      <div className="card">
        <div className="card-body" style={{ display:'grid', gridTemplateColumns:'1fr auto auto', gap:14, alignItems:'center' }}>
          <div>
            <div style={{ fontSize:'.66rem', color:'var(--dim)', textTransform:'uppercase', letterSpacing:'.14em', fontFamily:'var(--font-mono)', marginBottom:4 }}>GHL sub-account</div>
            <select className="input" value={subAcct} onChange={e=>setSubAcct(e.target.value)} style={{ maxWidth:360 }}>
              {SUB_ACCOUNTS.map(s => <option key={s.id} value={s.id}>{s.name}{s.status!=='connected'?' — not connected':''}</option>)}
            </select>
            <div style={{ marginTop:4, fontSize:'.68rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>
              Location ID: {cur.loc} · OAuth 2.0 (scopes: <code>locations.readonly opportunities.readonly ads.readonly contacts.readonly</code>)
            </div>
          </div>
          <div style={{ display:'flex', alignItems:'center', gap:6, padding:'6px 12px', borderRadius:12, background: isConnected ? 'var(--green-dim)' : 'var(--warn-dim)', border:`1px solid ${isConnected ? 'var(--green-dim)' : 'var(--warn-dim)'}`, color: isConnected ? 'var(--green)' : 'var(--warn)', fontSize:'.7rem', fontFamily:'var(--font-mono)', letterSpacing:'.08em', textTransform:'uppercase' }}>
            <span style={{ width:6, height:6, borderRadius:'50%', background: isConnected ? 'var(--green)' : 'var(--warn)' }}/>
            {isConnected ? 'Connected' : 'Not connected'}
          </div>
          <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast('Opening GHL Ad Manager in new tab', 'info')}>Open in GHL ↗</button>
        </div>
      </div>

      {!isConnected ? (
        <div className="card">
          <div className="card-body" style={{ textAlign:'center', padding:'28px 16px' }}>
            <div style={{ fontSize:'2rem', marginBottom:8 }}>🔌</div>
            <div style={{ fontWeight:600, marginBottom:4 }}>Connect this site's GHL sub-account</div>
            <div style={{ fontSize:'.8rem', color:'var(--dim)', marginBottom:14, maxWidth:520, margin:'0 auto 14px' }}>
              Authorize WP Site Beam to read Ad Manager data (Google + Meta + LinkedIn + TikTok aggregated inside GHL), contacts, and pipelines. We'll never write changes — edits happen in GHL.
            </div>
            <button className="btn btn-primary btn-sm" onClick={() => window.wpsbToast('Connecting GHL via OAuth', 'info')}>Connect GoHighLevel</button>
          </div>
        </div>
      ) : (
        <>
          {/* Headline KPIs */}
          <div className="grid grid-4" style={{ gap:10 }}>
            <div className="stat"><div className="stat-lbl">Ad spend (30d)</div><div className="stat-val">${d.kpi.spend.toLocaleString()}</div></div>
            <div className="stat"><div className="stat-lbl">Attributed revenue</div><div className="stat-val ok">{d.kpi.rev ? '$'+d.kpi.rev.toLocaleString() : '—'}</div></div>
            <div className="stat"><div className="stat-lbl">Conversions</div><div className="stat-val">{d.kpi.conv}</div></div>
            <div className="stat"><div className="stat-lbl">ROAS</div><div className={'stat-val ' + (d.kpi.roas && d.kpi.roas >= 4 ? 'ok' : d.kpi.roas ? 'warn' : '')}>{d.kpi.roas ? d.kpi.roas.toFixed(2)+'x' : 'n/a'}</div></div>
          </div>

          {/* Channel breakdown */}
          <div className="card">
            <div className="card-head"><h2 className="card-title">Channel breakdown · 30d</h2><span style={{ fontSize:'.66rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>Aggregated via GHL Ad Manager</span></div>
            <div className="card-body">
              <div style={{ display:'grid', gap:8 }}>
                {d.channels.map(c => {
                  const pct = (c.spend / d.kpi.spend) * 100;
                  return (
                    <div key={c.p} style={{ display:'grid', gridTemplateColumns:'140px 1fr 60px 70px 70px', gap:12, alignItems:'center', padding:'6px 0' }}>
                      <div style={{ fontSize:'.82rem', fontWeight:600 }}>{c.p}</div>
                      <div style={{ height:10, background:'var(--surface-2)', borderRadius:5, overflow:'hidden', position:'relative' }}>
                        <div style={{ height:'100%', width: pct+'%', background: c.p.includes('Google') ? 'var(--beam)' : c.p.includes('Meta') ? '#5b8def' : c.p.includes('LinkedIn') ? '#0a66c2' : c.p.includes('TikTok') ? '#ff0050' : '#e60023' }}/>
                      </div>
                      <div className="mono" style={{ fontSize:'.78rem', textAlign:'right' }}>${c.spend.toLocaleString()}</div>
                      <div className="mono" style={{ fontSize:'.78rem', textAlign:'right', color:'var(--green)' }}>{c.conv} conv</div>
                      <div className="mono" style={{ fontSize:'.74rem', color:'var(--dim)', textAlign:'right' }}>{c.ctr}% CTR</div>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>

          {/* Campaigns table */}
          <div className="card">
            <div className="card-head"><h2 className="card-title">Top campaigns</h2><a href="#" onClick={e=>{e.preventDefault(); window.wpsbToast('Opening GHL Ad Manager', 'info');}} style={{ fontSize:'.74rem' }}>Manage in GHL ↗</a></div>
            <div className="card-body" style={{ padding:0 }}>
              <table className="table">
                <thead><tr>
                  <th>Campaign</th><th>Platform</th><th>Status</th>
                  <th style={{ textAlign:'right' }}>Spend</th>
                  <th style={{ textAlign:'right' }}>Conv</th>
                  <th style={{ textAlign:'right' }}>Revenue</th>
                  <th style={{ textAlign:'right' }}>CPL</th>
                  <th style={{ textAlign:'right' }}>ROAS</th>
                </tr></thead>
                <tbody>
                  {d.campaigns.map(c => {
                    const roas = c.rev && c.spend ? c.rev / c.spend : null;
                    return (
                      <tr key={c.n}>
                        <td style={{ fontWeight:500 }}>{c.n}</td>
                        <td style={{ fontSize:'.78rem', color:'var(--dim)' }}>{c.p}</td>
                        <td><span className={'tag ' + (c.st==='active'?'ok':c.st==='paused'?'':'warn')}>{c.st.toUpperCase()}</span></td>
                        <td className="mono" style={{ textAlign:'right' }}>${c.spend.toLocaleString()}</td>
                        <td className="mono ok" style={{ textAlign:'right' }}>{c.conv}</td>
                        <td className="mono" style={{ textAlign:'right', color: c.rev ? 'var(--text-2)' : 'var(--dim)' }}>{c.rev ? '$'+c.rev.toLocaleString() : '—'}</td>
                        <td className="mono" style={{ textAlign:'right', color: c.cpl > 50 ? 'var(--warn)' : 'var(--text-2)' }}>${c.cpl.toFixed(2)}</td>
                        <td className="mono" style={{ textAlign:'right', color: roas && roas >= 4 ? 'var(--green)' : roas ? 'var(--warn)' : 'var(--dim)' }}>{roas ? roas.toFixed(1)+'x' : '—'}</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
            <div className="card-body" style={{ borderTop:'1px solid var(--border)', fontSize:'.68rem', color:'var(--dim)', fontFamily:'var(--font-mono)', lineHeight:1.55 }}>
              ↳ Revenue attribution joins <code style={{ background:'var(--surface-3)', padding:'1px 4px', borderRadius:2 }}>utm_campaign</code> on Woo orders &amp; Stripe charges against GHL campaign names ·
              ROAS = attributed revenue / spend · Deep edits, A/B tests, creative swaps, and bid changes live in GoHighLevel.
            </div>
          </div>

          {/* Revenue attribution sources */}
          <div className="card">
            <div className="card-head"><h2 className="card-title">Revenue attribution sources</h2></div>
            <div className="card-body" style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
              <div style={{ display:'flex', gap:10, alignItems:'center', padding:'10px 12px', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:6 }}>
                <div style={{ width:28, height:28, borderRadius:6, background:'rgba(99,91,255,.15)', border:'1px solid rgba(99,91,255,.3)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--beam)', fontWeight:700, fontSize:'.78rem' }}>S</div>
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:'.78rem', fontWeight:600 }}>Stripe · connected</div>
                  <div style={{ fontSize:'.66rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>Charges in last 30d matched by metadata.utm_campaign</div>
                </div>
                <button className="btn btn-ghost btn-sm">Manage</button>
              </div>
              <div style={{ display:'flex', gap:10, alignItems:'center', padding:'10px 12px', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:6 }}>
                <div style={{ width:28, height:28, borderRadius:6, background:'var(--green-dim)', border:'1px solid var(--green-dim)', display:'flex', alignItems:'center', justifyContent:'center', color:'var(--green)', fontWeight:700, fontSize:'.78rem' }}>W</div>
                <div style={{ flex:1 }}>
                  <div style={{ fontSize:'.78rem', fontWeight:600 }}>WooCommerce · connected</div>
                  <div style={{ fontSize:'.66rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>Orders joined via _wc_order_attribution_utm_campaign</div>
                </div>
                <button className="btn btn-ghost btn-sm">Manage</button>
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

/* ─────────────────────────────────────────────────────────────
   Pixels & Tags — cross-site rollup (Marketing tab)
   ───────────────────────────────────────────────────────────── */
function PixelsAndTags() {
  const SITES = [
    { site:'WPSiteBeam (Prod)',       gtm:'✓', ga4:'✓', gads:'✓', meta:'✓', li:'✓', tt:'—', pin:'—', clarity:'✓', ghl:'✓' },
    { site:'WPSiteBeam',   gtm:'✓', ga4:'✓', gads:'✓', meta:'✓', li:'—', tt:'—', pin:'✓', clarity:'✓', ghl:'✓' },
    { site:'Dev WPSiteBeam',          gtm:'✓', ga4:'✓', gads:'✓', meta:'✓', li:'⚠', tt:'—', pin:'—', clarity:'✓', ghl:'—' },
    { site:'Maple County Council',    gtm:'✓', ga4:'✓', gads:'✓', meta:'⚠', li:'—', tt:'—', pin:'—', clarity:'—', ghl:'—' },
    { site:'Bramble & Co (eCom)',     gtm:'✓', ga4:'✓', gads:'✓', meta:'✓', li:'—', tt:'✓', pin:'✓', clarity:'—', ghl:'✓' },
  ];
  const cell = (v) => {
    if (v === '✓') return <span style={{ color:'var(--green)' }}>✓</span>;
    if (v === '⚠') return <span style={{ color:'var(--warn)' }}>⚠</span>;
    return <span style={{ color:'var(--dim)' }}>—</span>;
  };
  return (
    <>
    <div style={{ marginTop:16, display:'grid', gap:16 }}>
      <div className="card">
        <div className="card-head"><h2 className="card-title">Pixel coverage — all client sites</h2><span style={{ fontSize:'.66rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>Scanned hourly · last pass 12m ago</span></div>
        <div className="card-body" style={{ padding:0 }}>
          <table className="table">
            <thead><tr>
              <th>Site</th><th>GTM</th><th>GA4</th><th>GAds</th><th>Meta</th><th>LinkedIn</th><th>TikTok</th><th>Pinterest</th><th>Clarity</th><th>GHL</th>
            </tr></thead>
            <tbody>
              {SITES.map(s => (
                <tr key={s.site}>
                  <td style={{ fontWeight:500 }}>{s.site}</td>
                  <td className="mono">{cell(s.gtm)}</td>
                  <td className="mono">{cell(s.ga4)}</td>
                  <td className="mono">{cell(s.gads)}</td>
                  <td className="mono">{cell(s.meta)}</td>
                  <td className="mono">{cell(s.li)}</td>
                  <td className="mono">{cell(s.tt)}</td>
                  <td className="mono">{cell(s.pin)}</td>
                  <td className="mono">{cell(s.clarity)}</td>
                  <td className="mono">{cell(s.ghl)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="card-body" style={{ borderTop:'1px solid var(--border)', fontSize:'.68rem', color:'var(--dim)', fontFamily:'var(--font-mono)', lineHeight:1.55 }}>
          ↳ Detection runs a headless render and watches for <code>gtag/fbq/lintrk/ttq/_linkedin_data_partner_ids/pintrk/clarity</code> + WP plugin scan (PixelYourSite, Pixel Manager for WooCommerce, MonsterInsights, Advanced Ads, Site Kit).
          Per-site detail lives on <strong style={{ color:'var(--text-2)' }}>WP Health → Reports → Tracking Pixels</strong>.
        </div>
      </div>
    </div>
      {/* Roles quick-reference panel (design review 2026-05-26 colocation) */}
      <div style={{ marginTop:24 }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
          <h2 className="card-title">Role definitions</h2>
          <button className="btn btn-ghost btn-sm" onClick={() => window.WPSBD?.switchTab?.('roles')}>Manage permissions →</button>
        </div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(240px,1fr))', gap:10 }}>
          {[
            { id:'customer', lbl:'Customer',      color:'var(--cyan,#06b6d4)', desc:'Own sites, scans, billing, support' },
            { id:'admin',    lbl:'Agency Admin',   color:'var(--green)',        desc:'Billing, team, white-label config' },
            { id:'support',  lbl:'Support Tech',   color:'var(--purple)',       desc:'Read-only + ticket access; no billing' },
            { id:'partner',  lbl:'Partner Agency', color:'var(--orange)',       desc:'White-label: manages multiple accounts' },
            { id:'sa',       lbl:'Super Admin',    color:'var(--rose)',         desc:'God mode: all modules and overrides' },
          ].map(function(role) { return (
            <div key={role.id} className="card" style={{ padding:'10px 12px' }}>
              <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
                <div style={{ width:8, height:8, borderRadius:'50%', background:role.color, flexShrink:0 }}/>
                <span style={{ fontWeight:600, fontSize:'.84rem' }}>{role.lbl}</span>
                <code style={{ fontSize:'.62rem', color:'var(--dim)', marginLeft:'auto' }}>role.{role.id}</code>
              </div>
              <div style={{ fontSize:'.74rem', color:'var(--dim)', lineHeight:1.4 }}>{role.desc}</div>
            </div>
          ); })}
        </div>
      </div>
    </>
  );
}

window.Pages2 = { Support, Requests, Scanner, Workspace, Modules, Permissions, Notices, Brains, Roles, Team, Brand, SAStub, Tasks, Content, Marketing, PartnersSA, Wiki, BrandProfile };
