/* ═══════════════════════════════════════════════════════════════════
   SeoTracker.jsx — SEO Tracker overview surface. v1.0.0
   Ported verbatim from the Claude Design v2 package
   (_CLAUDE-DESIGN/_2026-06-12-v2-SaaS-Redesign/seo-tracker.jsx).
   Pricing strings match the LOCKED SEO add-on model (context CLAUDE.md
   §6 #22: daily upgrade Starter $39 / Pro $79 / Agency $149 per month).
   Load order: THIRD (after SeoCharts.jsx + SeoData.jsx).
   Registers: window.WPSB.SeoTracker = { SeoTrackerOverview, Seg,
   SeoStatCard, DailyUpsell, ByokIndicator, AiVisCell, downloadReportPdf }.
   ═══════════════════════════════════════════════════════════════════ */
(function () {
const { useState: useStateT, useEffect: useEffectT } = React;
const tx = (k, v, f) => (window.WPSB && window.WPSB.t) ? window.WPSB.t(k, v, f) : (f != null ? f : k);
const WIcon = window.WIcon;
const { Sparkline, MiniBars, Delta, DifficultyDot, OverlapBar } = window.WPSB.SeoCharts;
const { SEO_KEYWORDS, SEO_COMPETITORS, SEO_SUGGESTIONS, SEO_STATS, SerpFeatures, PositionBadge, ClaudeChip } = window.WPSB.SeoData;

/* honest dash for fields the live /seo/rank/* endpoints don't return
   (search volume, difficulty, AI visibility) — never a fabricated 0. */
function Dash(title) { return React.createElement('span', { title: title || tx('page.seotracker.not_measured_yet', null, 'Not measured yet'), style: { color: 'var(--dim)', fontFamily: 'var(--font-mono)', fontSize: '.8rem' } }, '—'); }
function changeOf(row) { return (row.prev != null && row.pos != null) ? (row.prev - row.pos) : null; }
function PosCell(row, size) { return row.pos == null
  ? React.createElement('span', { title: tx('page.seotracker.awaiting_first_check', null, 'Awaiting first check'), style: { color: 'var(--dim)', fontFamily: 'var(--font-mono)', fontSize: size || '.85rem' } }, tx('page.seotracker.pending', null, 'pending'))
  : React.createElement(PositionBadge, { pos: row.pos, size: size }); }

/* download a minimal valid PDF (mock export — real export wires server-side) */
function downloadReportPdf(filename, title, lines) {
  const safe = (s) => String(s).replace(/[()\\]/g, ' ');
  let content = 'BT /F1 20 Tf 72 740 Td (' + safe(title) + ') Tj ET\n';
  let y = 706;
  (lines || []).forEach(l => { content += 'BT /F1 12 Tf 72 ' + y + ' Td (' + safe(l) + ') Tj ET\n'; y -= 20; });
  const parts = ['%PDF-1.4\n'];
  const offs = [];
  const add = (s) => { offs.push(parts.join('').length); parts.push(s); };
  add('1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n');
  add('2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n');
  add('3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 5 0 R >> >> /Contents 4 0 R >>\nendobj\n');
  add('4 0 obj\n<< /Length ' + content.length + ' >>\nstream\n' + content + 'endstream\nendobj\n');
  add('5 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n');
  const xrefPos = parts.join('').length;
  let xref = 'xref\n0 6\n0000000000 65535 f \n';
  offs.forEach(o => { xref += String(o).padStart(10, '0') + ' 00000 n \n'; });
  parts.push(xref + 'trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n' + xrefPos + '\n%%EOF');
  const url = URL.createObjectURL(new Blob([parts.join('')], { type: 'application/pdf' }));
  const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1500);
}

/* viewport width hook — table on desktop, cards on mobile */
function useNarrow(bp) {
  const [narrow, setNarrow] = useStateT(typeof window !== 'undefined' ? window.innerWidth < bp : false);
  useEffectT(() => {
    const onR = () => setNarrow(window.innerWidth < bp);
    onR(); window.addEventListener('resize', onR);
    return () => window.removeEventListener('resize', onR);
  }, [bp]);
  return narrow;
}

/* ── shared bits ────────────────────────────────────────────────────── */
function Seg({ options, value, onChange, size }) {
  return React.createElement('div', { role: 'tablist', style: { display: 'inline-flex', gap: 2, padding: 3, borderRadius: 'var(--r)',
    background: 'var(--surface-2)', border: '1px solid var(--border)' } },
    options.map(o => {
      const sel = (o.key || o) === value;
      return React.createElement('button', { key: o.key || o, type: 'button', role: 'tab', 'aria-selected': sel ? 'true' : 'false',
        onClick: () => onChange(o.key || o), className: 'wiz-focusable',
        style: { padding: size === 'sm' ? '5px 10px' : '6px 13px', borderRadius: 'var(--r-sm)', border: 'none', cursor: 'pointer',
          background: sel ? 'var(--beam-dim)' : 'transparent', color: sel ? 'var(--beam)' : 'var(--muted)',
          font: 'inherit', fontFamily: 'var(--font-mono)', fontSize: '.72rem', fontWeight: 600, letterSpacing: '.03em', whiteSpace: 'nowrap' } },
        o.label || o);
    }));
}

function SeoStatCard({ icon, label, value, accent, spark, delta, tint }) {
  const c = accent || 'var(--viz-1)';
  const bg = tint ? 'color-mix(in oklch, ' + c + ' 9%, var(--surface))' : 'var(--surface)';
  const bd = tint ? 'color-mix(in oklch, ' + c + ' 32%, transparent)' : 'var(--border)';
  return React.createElement('div', { className: 'wiz-card', style: { background: bg, border: '1px solid ' + bd,
    borderRadius: 'var(--r-lg)', padding: '16px 18px' } },
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 9, marginBottom: 12 } },
      React.createElement('span', { style: { width: 28, height: 28, borderRadius: 'var(--r-sm)', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center',
        background: 'color-mix(in oklch, ' + c + ' 16%, transparent)', color: c, border: '1px solid color-mix(in oklch, ' + c + ' 30%, transparent)' } },
        React.createElement(WIcon, { name: icon, size: 15 })),
      React.createElement('span', { className: 'wiz-eyebrow', style: { fontSize: '.58rem', flex: 1 } }, label)),
    React.createElement('div', { style: { display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 10 } },
      React.createElement('div', { style: { display: 'flex', alignItems: 'baseline', gap: 7 } },
        React.createElement('span', { style: { fontFamily: 'var(--font-brand)', fontWeight: 'var(--fw-bold)', fontSize: '1.7rem', color: tint ? c : 'var(--text)', lineHeight: 1, fontVariantNumeric: 'tabular-nums' } }, value),
        delta != null && React.createElement(Delta, { value: delta, size: '.72rem' })),
      spark && React.createElement('div', { style: { flex: 'none' } }, spark))
  );
}

/* ── daily-tracking upsell (free→Starter+) / Solo info variant ──────── */
function DailyUpsell({ plan, onCta }) {
  // plan: 'starter-eligible' (can buy) | 'solo' (no purchasable upsell)
  const solo = plan === 'solo';
  const accent = 'var(--wiz-upsell)';
  return React.createElement('div', { className: 'wiz-card', style: {
    background: solo ? 'var(--surface-2)' : 'var(--wiz-upsell-bg)',
    border: '1px solid ' + (solo ? 'var(--border-2)' : 'color-mix(in oklch, var(--wiz-upsell) 34%, transparent)'),
    borderRadius: 'var(--r-lg)', padding: 'var(--sp-5)', display: 'flex', alignItems: 'center', gap: 'var(--sp-5)', flexWrap: 'wrap' } },
    React.createElement('span', { style: { width: 46, height: 46, borderRadius: 'var(--r)', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: solo ? 'var(--surface-3)' : 'color-mix(in oklch, var(--wiz-upsell) 16%, transparent)',
      color: solo ? 'var(--muted)' : accent, border: '1px solid ' + (solo ? 'var(--border)' : 'color-mix(in oklch, var(--wiz-upsell) 30%, transparent)') } },
      React.createElement(WIcon, { name: solo ? 'lock' : 'zap', size: 22 })),
    React.createElement('div', { style: { flex: 1, minWidth: 220 } },
      React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap', marginBottom: 4 } },
        React.createElement('span', { style: { fontWeight: 'var(--fw-label)', fontSize: '1rem', color: 'var(--text)' } }, tx('page.seotracker.upsell.title', null, 'Check every keyword, every day')),
        React.createElement('span', { className: 'wiz-tag wiz-tag-addon' }, tx('page.seotracker.upsell.tag', null, 'Daily Rank Tracking'))),
      React.createElement('p', { style: { margin: 0, fontSize: '.86rem', color: 'var(--text-2)', lineHeight: 1.45 } },
        tx('page.seotracker.upsell.body', null, 'Daily position updates, change alerts, and fresher trend lines. '),
        React.createElement('span', { style: { color: 'var(--muted)' } }, tx('page.seotracker.upsell.weekly_note', null, 'You’re on weekly checks.')))),
    solo
      ? React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.78rem', color: 'var(--muted)', fontWeight: 600, whiteSpace: 'nowrap' } }, tx('page.seotracker.upsell.available', null, 'Available on Starter and above'))
      : React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 'var(--sp-4)', flexWrap: 'wrap' } },
          React.createElement('div', { style: { textAlign: 'right' } },
            React.createElement('div', { style: { fontFamily: 'var(--font-brand)', fontWeight: 'var(--fw-bold)', fontSize: '1.1rem', color: 'var(--text)' } }, tx('page.seotracker.upsell.from_price', null, 'From $39'),
              React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.72rem', color: 'var(--muted)', fontWeight: 400 } }, tx('page.seotracker.upsell.per_mo', null, '/mo'))),
            React.createElement('div', { style: { fontFamily: 'var(--font-mono)', fontSize: '.6rem', color: 'var(--dim)' } }, tx('page.seotracker.upsell.price_breakdown', null, 'Starter $39 · Pro $79 · Agency $149'))),
          React.createElement('button', { type: 'button', className: 'wiz-btn wiz-btn-upsell wiz-focusable', onClick: onCta, style: { padding: '10px 18px' } },
            React.createElement(WIcon, { name: 'arrow-up-right', size: 15 }), tx('page.seotracker.upsell.cta', null, 'Upgrade to Daily Tracking'))));
}

/* ── keyword list — desktop table; SERP chips inline with the keyword ── */
const KW_COLS = '28px minmax(220px,2fr) 64px 66px 76px 96px minmax(170px,1.5fr) 38px';
function KwHead({ aiLocked }) {
  const cells = ['', tx('page.seotracker.col.keyword', null, 'Keyword'), tx('page.seotracker.col.position', null, 'Position'), tx('page.seotracker.col.change', null, 'Change'), tx('page.seotracker.col.volume', null, 'Volume'), tx('page.seotracker.col.difficulty', null, 'Difficulty'), tx('page.seotracker.col.target_url', null, 'Target URL'), tx('page.seotracker.col.ai', null, 'AI')];
  return React.createElement('div', { style: { display: 'grid', gridTemplateColumns: KW_COLS, gap: 'var(--sp-3)',
    padding: '11px var(--sp-5)', background: 'var(--surface-2)', borderBottom: '1px solid var(--border)' } },
    cells.map((h, i) => React.createElement('span', { key: i, className: 'wiz-eyebrow', style: { fontSize: '.55rem', letterSpacing: '.1em', textAlign: 'left' } }, h)));
}
function KwRow({ row, idx, aiLocked, onOpen }) {
  const [hover, setHover] = useStateT(false);
  const zebra = idx % 2 === 1;
  const bg = hover ? 'var(--surface-3)' : (zebra ? 'var(--surface-2)' : 'var(--surface)');
  const cell = { display: 'flex', alignItems: 'center', minWidth: 0 };
  return React.createElement('div', { onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false),
    onClick: () => onOpen(row), role: 'button', tabIndex: 0,
    onKeyDown: (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onOpen(row); } },
    className: 'wiz-focusable',
    style: { display: 'grid', gridTemplateColumns: KW_COLS, gap: 'var(--sp-3)', alignItems: 'center',
      padding: '12px var(--sp-5)', background: bg, borderBottom: '1px solid var(--border)', cursor: 'pointer' } },
    React.createElement('div', { style: cell }, React.createElement('span', { title: tx('page.seotracker.open_keyword_detail', null, 'Open keyword detail'), style: { display: 'inline-flex', color: hover ? 'var(--beam)' : 'var(--dim)', transition: 'color 130ms ease' } }, React.createElement(WIcon, { name: 'external', size: 15 }))),
    // keyword + SERP chips inline to the right (wraps if tight)
    React.createElement('div', { style: { minWidth: 0, display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
      React.createElement('span', { style: { fontWeight: 'var(--fw-medium)', fontSize: '.85rem', color: 'var(--text)' } }, row.kw),
      React.createElement(SerpFeatures, { features: row.serp })),
    React.createElement('div', { style: cell }, PosCell(row, '.95rem')),
    React.createElement('div', { style: cell }, changeOf(row) == null ? Dash() : React.createElement(Delta, { value: changeOf(row) })),
    React.createElement('div', { style: cell }, row.vol == null ? Dash(tx('page.seotracker.pending_search_volume', null, 'Search volume — pending keyword-data API')) : React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.8rem', color: 'var(--text-2)' } }, row.vol.toLocaleString())),
    React.createElement('div', { style: cell }, row.diff == null ? Dash(tx('page.seotracker.pending_difficulty', null, 'Keyword difficulty — pending keyword-data API')) : React.createElement(DifficultyDot, { value: row.diff })),
    React.createElement('div', { style: cell }, React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.74rem', color: 'var(--beam)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, row.url || '—')),
    React.createElement('div', { style: cell }, aiLocked
      ? React.createElement('span', { title: tx('page.seotracker.locked_ai_addon', null, 'Locked — AI visibility add-on'), style: { display: 'inline-flex', color: 'var(--dim)' } }, React.createElement(WIcon, { name: 'lock', size: 14 }))
      : React.createElement(AiVisCell, { row }))
  );
}

/* ── MOBILE CARD — full data, single-column reflow (fallback < breakpoint) ── */
function MetaItem({ label, children }) {
  return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 5, minWidth: 0 } },
    React.createElement('span', { className: 'wiz-eyebrow', style: { fontSize: '.54rem', letterSpacing: '.12em' } }, label),
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', minWidth: 0 } }, children));
}

function KeywordCard({ row, idx, aiLocked, onOpen }) {
  const [hover, setHover] = useStateT(false);
  const change = changeOf(row);
  const improved = change == null ? true : change >= 0;
  return React.createElement('div', { onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false),
    onClick: () => onOpen(row), role: 'button', tabIndex: 0,
    onKeyDown: (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onOpen(row); } },
    className: 'wiz-focusable',
    style: { padding: 'var(--sp-5)', background: hover ? 'var(--surface-2)' : 'var(--surface)',
      borderBottom: '1px solid var(--border)', cursor: 'pointer', transition: 'background 120ms ease' } },
    // top line: keyword + SERP chips (left) | position + change (right)
    React.createElement('div', { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 'var(--sp-4)', flexWrap: 'wrap' } },
      React.createElement('div', { style: { flex: '1 1 240px', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 8 } },
        React.createElement('span', { style: { fontWeight: 'var(--fw-label)', fontSize: '.95rem', color: 'var(--text)', lineHeight: 1.3, textWrap: 'pretty' } }, row.kw),
        React.createElement(SerpFeatures, { features: row.serp })),
      React.createElement('div', { style: { flex: 'none', display: 'flex', alignItems: 'center', gap: 'var(--sp-4)' } },
        React.createElement('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2 } },
          React.createElement('span', { className: 'wiz-eyebrow', style: { fontSize: '.52rem' } }, tx('page.seotracker.col.position', null, 'Position')),
          PosCell(row, '1.25rem')),
        React.createElement('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 } },
          React.createElement('span', { className: 'wiz-eyebrow', style: { fontSize: '.52rem' } }, tx('page.seotracker.col.change', null, 'Change')),
          change == null ? Dash() : React.createElement(Delta, { value: change })))),
    // meta strip — reflows multi-col → single-col
    React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(116px, 1fr))', gap: 'var(--sp-4)',
      marginTop: 'var(--sp-4)', paddingTop: 'var(--sp-4)', borderTop: '1px solid var(--border)' } },
      React.createElement(MetaItem, { label: tx('page.seotracker.col.trend', null, 'Trend') }, (row.trend && row.trend.length > 1) ? React.createElement(Sparkline, { data: row.trend, invert: true, w: 88, h: 24, color: improved ? 'var(--viz-up)' : 'var(--viz-down)' }) : Dash(tx('page.seotracker.awaiting_checks', null, 'Awaiting checks'))),
      React.createElement(MetaItem, { label: tx('page.seotracker.col.volume', null, 'Volume') }, row.vol == null ? Dash(tx('page.seotracker.pending_search_volume', null, 'Search volume — pending keyword-data API')) : React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.84rem', color: 'var(--text)' } }, row.vol.toLocaleString())),
      React.createElement(MetaItem, { label: tx('page.seotracker.col.difficulty', null, 'Difficulty') }, row.diff == null ? Dash(tx('page.seotracker.pending_difficulty', null, 'Keyword difficulty — pending keyword-data API')) : React.createElement(DifficultyDot, { value: row.diff })),
      React.createElement(MetaItem, { label: tx('page.seotracker.col.target_url', null, 'Target URL') }, React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.78rem', color: 'var(--beam)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, row.url || '—')),
      React.createElement(MetaItem, { label: tx('page.seotracker.col.ai_visibility', null, 'AI visibility') }, aiLocked
        ? React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 5, color: 'var(--dim)', fontFamily: 'var(--font-mono)', fontSize: '.76rem' } }, React.createElement(WIcon, { name: 'lock', size: 12 }), tx('page.seotracker.locked', null, 'Locked'))
        : React.createElement(AiVisCell, { row })))
  );
}

function AiVisCell({ row }) {
  const map = { cited: { c: 'var(--viz-up)', t: tx('page.seotracker.ai.cited', { pos: row.aiPos }, 'Cited #{pos}') }, mentioned: { c: 'var(--viz-1)', t: tx('page.seotracker.ai.mentioned', null, 'Mentioned') }, absent: { c: 'var(--dim)', t: tx('page.seotracker.ai.absent', null, 'Absent') } };
  const m = map[row.ai];
  if (!m) return Dash(tx('page.seotracker.pending_ai_visibility', null, 'AI visibility — pending GEO/LLM-mentions API'));
  return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: '.74rem', color: m.c } },
    React.createElement('span', { style: { width: 7, height: 7, borderRadius: '50%', background: m.c, flex: 'none' } }), m.t);
}

/* ── competitor watch + AI suggestions cards ────────────────────────── */
/* honest "data not served yet" panel for api-gap features */
function PendingPanel({ eyebrow, icon, text }) {
  return React.createElement('div', { className: 'wiz-card', style: { background: 'var(--surface)', border: '1px dashed var(--border-2)', borderRadius: 'var(--r-lg)', padding: 'var(--sp-5)' } },
    React.createElement('span', { className: 'wiz-eyebrow', style: { display: 'block', marginBottom: 'var(--sp-4)' } }, eyebrow),
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 10, color: 'var(--muted)' } },
      React.createElement(WIcon, { name: icon || 'clock', size: 16 }),
      React.createElement('span', { style: { fontSize: '.82rem', lineHeight: 1.45 } }, text)));
}
function CompetitorCard({ items }) {
  const data = items || SEO_COMPETITORS;
  if (!data || !data.length) return React.createElement(PendingPanel, { eyebrow: tx('page.seotracker.competitor_watch', null, 'Competitor watch'), icon: 'users',
    text: tx('page.seotracker.competitor_pending', null, 'Competitor share-of-voice arrives with a later API increment — not yet served by rank tracking.') });
  return React.createElement('div', { className: 'wiz-card', style: { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-lg)', padding: 'var(--sp-5)' } },
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 'var(--sp-5)' } },
      React.createElement('span', { className: 'wiz-eyebrow' }, tx('page.seotracker.competitor_watch', null, 'Competitor watch')),
      React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.66rem', color: 'var(--muted)' } }, tx('page.seotracker.share_of_voice', null, 'share of voice'))),
    React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 'var(--sp-4)' } },
      data.map((c, i) => {
        const tier = c.overlap >= 60 ? 'var(--v-poor-fill)' : c.overlap >= 40 ? 'var(--v-warn-band)' : 'var(--v-good-fill)';
        return React.createElement('div', { key: i, style: { display: 'grid', gridTemplateColumns: 'minmax(170px,1.7fr) 116px 46px', gap: 'var(--sp-3)', alignItems: 'center' } },
          React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 8, fontFamily: 'var(--font-mono)', fontSize: '.8rem', color: 'var(--text)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } },
            React.createElement('span', { style: { width: 9, height: 9, borderRadius: 2, background: tier, flex: 'none' } }), c.domain),
          React.createElement(OverlapBar, { value: c.overlap, color: tier }),
          React.createElement('span', { style: { textAlign: 'right' } }, React.createElement(Delta, { value: c.delta, size: '.74rem' })));
      }))
  );
}

function AiSuggestCard({ locked, onCta, items }) {
  const data = items || SEO_SUGGESTIONS;
  if (!data || !data.length) return React.createElement(PendingPanel, { eyebrow: tx('page.seotracker.ai_suggestions_title', null, 'AI content suggestions'), icon: 'sparkles',
    text: tx('page.seotracker.ai_suggestions_pending', null, 'AI content suggestions arrive with a later increment — generated from your findings, not yet wired to rank tracking.') });
  return React.createElement('div', { className: 'wiz-card', style: { background: 'var(--surface)',
    border: '1px solid color-mix(in oklch, var(--beam) 22%, var(--border))', borderRadius: 'var(--r-lg)', padding: 'var(--sp-5)' } },
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 'var(--sp-5)', gap: 10, flexWrap: 'wrap' } },
      React.createElement('span', { className: 'wiz-eyebrow' }, tx('page.seotracker.ai_suggestions_title', null, 'AI content suggestions')),
      React.createElement(ClaudeChip)),
    React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 'var(--sp-3)' } },
      data.map((s, i) => {
        const tints = ['var(--viz-1)', 'var(--viz-2)', 'var(--viz-3)', 'var(--viz-5)'];
        const c = tints[i % tints.length];
        return React.createElement('div', { key: i, style: { display: 'flex', alignItems: 'flex-start', gap: 'var(--sp-3)',
          padding: 'var(--sp-3)', borderRadius: 'var(--r)', background: 'color-mix(in oklch, ' + c + ' 8%, var(--surface-2))',
          border: '1px solid color-mix(in oklch, ' + c + ' 28%, transparent)', borderLeft: '3px solid ' + c } },
          React.createElement('span', { style: { width: 26, height: 26, borderRadius: 'var(--r-sm)', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center',
            background: 'color-mix(in oklch, ' + c + ' 16%, transparent)', color: c } }, React.createElement(WIcon, { name: 'sparkles', size: 14 })),
          React.createElement('div', { style: { flex: 1, minWidth: 0 } },
            React.createElement('div', { style: { fontWeight: 'var(--fw-medium)', fontSize: '.84rem', color: 'var(--text)', marginBottom: 2 } }, s.title),
            React.createElement('div', { style: { fontSize: '.78rem', color: 'var(--text-2)', lineHeight: 1.4 } }, s.why)),
          React.createElement('span', { className: 'wiz-tag wiz-tag-' + (s.impact === 'high' ? 'new' : 'locked'), style: { flex: 'none' } }, s.impact === 'high' ? tx('page.seotracker.impact_high', null, 'High') : tx('page.seotracker.impact_med', null, 'Med')));
      }))
  );
}

function SeoTrackerOverview(props) {
  const { layout, plan, aiLocked, onOpenKeyword, onUpsell, range, setRange, onTrackKeyword, onRefresh, refreshing } = props;
  // live data via props; fall back to the sample set only when not supplied
  const KW = props.keywords || SEO_KEYWORDS;
  const ST = props.stats || SEO_STATS;
  const meta = props.meta || {};
  const domain = meta.domain || tx('page.seotracker.your_site', null, 'your site');
  const checkedRel = meta.checkedRel || null;
  const narrow = useNarrow(820);
  const showUpsell = plan !== 'daily';
  const upsellPlan = plan === 'solo' ? 'solo' : 'starter-eligible';

  const exportLines = [tx('page.seotracker.export.site', { domain: domain }, 'Site: {domain}'),
    KW.length === 1 ? tx('page.seotracker.export.keywords_tracked_one', { n: KW.length }, '{n} keyword tracked') : tx('page.seotracker.export.keywords_tracked_many', { n: KW.length }, '{n} keywords tracked'),
    tx('page.seotracker.export.avg_position', { v: (ST.avgPos == null ? tx('page.seotracker.na', null, 'n/a') : '#' + ST.avgPos) }, 'Avg position: {v}'),
    tx('page.seotracker.export.top10', { v: (ST.top10 == null ? tx('page.seotracker.na', null, 'n/a') : ST.top10) }, 'Top 10: {v}'),
    tx('page.seotracker.export.generated_by', null, 'Generated by WPSiteBeam SEO Tracker')];

  const table = React.createElement('div', { className: 'wiz-card', style: { background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-xl)', overflow: 'hidden' } },
    React.createElement('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 'var(--sp-4)', flexWrap: 'wrap', padding: 'var(--sp-5) var(--sp-5) var(--sp-4)' } },
      React.createElement('div', null,
        React.createElement('div', { style: { fontWeight: 'var(--fw-label)', fontSize: '1rem', color: 'var(--text)' } }, tx('page.seotracker.keyword_positions', null, 'Keyword Positions')),
        React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', flexWrap: 'wrap', marginTop: 5 } },
          React.createElement('span', { style: { fontFamily: 'var(--font-mono)', fontSize: '.72rem', color: 'var(--muted)' } }, tx('page.seotracker.tracked_cadence', { n: KW.length, cadence: (plan === 'daily' ? tx('page.seotracker.updated_daily', null, 'updated daily') : tx('page.seotracker.updated_weekly', null, 'updated weekly')) }, '{n} tracked · {cadence}')),
          React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: '.72rem',
            color: 'var(--text-2)', background: 'var(--surface-2)', border: '1px solid var(--border)', borderRadius: 999, padding: '3px 10px', whiteSpace: 'nowrap' } },
            React.createElement(WIcon, { name: 'clock', size: 12, style: { color: 'var(--beam)' } }), checkedRel ? tx('page.seotracker.checked_rel', { rel: checkedRel }, 'Checked {rel}') : tx('page.seotracker.awaiting_first_check', null, 'Awaiting first check')))),
      React.createElement('div', { style: { display: 'flex', gap: 'var(--sp-2)' } },
        onRefresh && React.createElement('button', { type: 'button', disabled: refreshing, className: 'wiz-btn wiz-btn-tool wiz-focusable', style: { fontSize: '.74rem' }, onClick: onRefresh, title: tx('page.seotracker.refresh_title', null, 'Re-check all keyword positions now') }, React.createElement(WIcon, { name: 'refresh-cw', size: 14 }), refreshing ? tx('page.seotracker.checking', null, 'Checking…') : tx('page.seotracker.refresh', null, 'Refresh')),
        React.createElement('button', { type: 'button', className: 'wiz-btn wiz-btn-tool wiz-focusable', style: { fontSize: '.74rem' }, onClick: () => downloadReportPdf('seo-keyword-report.pdf', tx('page.seotracker.report_title', null, 'WPSiteBeam — Keyword Report'), exportLines) }, React.createElement(WIcon, { name: 'download', size: 14 }), tx('page.seotracker.export_to_report', null, 'Export to report')))),
    React.createElement('div', { style: { borderTop: '1px solid var(--border)' } },
      narrow
        ? KW.map((r, i) => React.createElement(KeywordCard, { key: i, row: r, idx: i, aiLocked, onOpen: onOpenKeyword }))
        : React.createElement(React.Fragment, null,
            React.createElement(KwHead, { aiLocked }),
            KW.map((r, i) => React.createElement(KwRow, { key: i, row: r, idx: i, aiLocked, onOpen: onOpenKeyword })))));

  const charts = React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'minmax(0,1.5fr) minmax(0,1fr)', gap: 'var(--sp-5)' } },
    React.createElement(CompetitorCard, { items: props.competitors }), React.createElement(AiSuggestCard, { onCta: onUpsell, items: props.suggestions }));

  return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 'var(--sp-5)' } },
    // header
    React.createElement('div', { style: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 'var(--sp-4)', flexWrap: 'wrap' } },
      React.createElement('div', null,
        React.createElement('div', { className: 'wiz-eyebrow', style: { marginBottom: 6 } }, tx('page.seotracker.eyebrow', null, 'SEO · Rank tracking')),
        React.createElement('h1', { className: 'wiz-title', style: { margin: 0, fontSize: '1.6rem' } }, tx('page.seotracker.title', null, 'SEO Tracker')),
        React.createElement('p', { style: { margin: '6px 0 0', color: 'var(--text-2)', fontSize: '.9rem' } },
          React.createElement('span', { style: { fontFamily: 'var(--font-mono)' } }, domain))),
      React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', flexWrap: 'wrap' } },
        React.createElement(Seg, { options: [{ key: '7d', label: tx('page.seotracker.range.7d', null, '7d') }, { key: '30d', label: tx('page.seotracker.range.30d', null, '30d') }, { key: '90d', label: tx('page.seotracker.range.90d', null, '90d') }, { key: '1y', label: tx('page.seotracker.range.1y', null, '1y') }], value: range, onChange: setRange }),
        React.createElement('button', { type: 'button', className: 'wiz-btn wiz-btn-primary wiz-focusable', style: { fontSize: '.78rem' }, onClick: onTrackKeyword || undefined }, React.createElement(WIcon, { name: 'search', size: 15 }), tx('page.seotracker.track_keyword', null, 'Track keyword')))),

    // stat row — live; null metrics render '—', never a fabricated 0/trend
    React.createElement('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(210px,1fr))', gap: 'var(--sp-4)' } },
      React.createElement(SeoStatCard, { icon: 'search', label: tx('page.seotracker.stat.tracked', null, 'Tracked keywords'), value: ST.tracked == null ? '—' : ST.tracked, tint: true, accent: 'var(--viz-1)' }),
      React.createElement(SeoStatCard, { icon: 'gauge', label: tx('page.seotracker.stat.avg_position', null, 'Avg position'), value: ST.avgPos == null ? '—' : '#' + ST.avgPos, tint: true, accent: 'var(--viz-2)' }),
      React.createElement(SeoStatCard, { icon: 'star', label: tx('page.seotracker.stat.top10', null, 'Top 10'), value: ST.top10 == null ? '—' : ST.top10, tint: true, accent: 'var(--viz-3)' }),
      React.createElement(SeoStatCard, { icon: 'arrow-up-right', label: tx('page.seotracker.stat.est_traffic', null, 'Est. traffic / mo'), value: ST.traffic == null ? '—' : ST.traffic, tint: true, accent: 'var(--viz-4)' })),

    // daily upsell (gated state) — shown for non-daily plans
    showUpsell && React.createElement(DailyUpsell, { plan: upsellPlan, onCta: onUpsell }),

    // layout variation: table-first vs charts-first
    layout === 'charts-first'
      ? React.createElement(React.Fragment, null, charts, table)
      : React.createElement(React.Fragment, null, table, charts)
  );
}

function ByokIndicator({ present }) {
  return React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-mono)', fontSize: '.72rem',
    color: present ? 'var(--viz-up)' : 'var(--muted)' } },
    React.createElement('span', { style: { width: 7, height: 7, borderRadius: '50%', background: present ? 'var(--viz-up)' : 'var(--dim)' } }),
    present ? tx('page.seotracker.byok.active', null, 'BYOK key active') : tx('page.seotracker.byok.none', null, 'No API key'));
}

window.WPSB = window.WPSB || {};
window.WPSB.SeoTracker = { SeoTrackerOverview, Seg, SeoStatCard, DailyUpsell, ByokIndicator, AiVisCell, downloadReportPdf };
console.log('[WPSB] SeoTracker v1.0.0 loaded');
})();
