/* ═══════════════════════════════════════════════════════════════
   BUSINESS METRICS — SA-only executive dashboard
   Live view of MRR, plan mix, COGS/margins, churn, funnel, and unit
   economics for the WPSiteBeam SaaS.

   Data model: All demo data is generated deterministically (seeded) so
   it looks realistic and stable across reloads. In production this
   would pull from Stripe (MRR, churn) + Supabase (signups, usage) +
   Railway (scan volume → AI cost attribution).

   5 tabs:
     • Overview — headline KPIs + trend sparklines
     • MRR       — 12-month ARR/MRR chart, breakdown by plan, new/expansion/churn waterfall
     • Plans     — plan mix pie, per-plan MRR bar, add-on attach rates
     • COGS      — per-scan cost stack, infra costs, margin by plan
     • Funnel    — signup → trial → paid → expansion cohort chart

   SA-only: Shell guards via `sa: true` on the nav entry.
   ═══════════════════════════════════════════════════════════════ */

(function() {
  const { useState, useEffect, useMemo } = React;

  /* ── COLOR TOKENS (chart palette) ─────────────────────────── */
  const CHART = {
    beam:   'var(--beam)',
    orange: 'var(--orange)',
    mint:   'var(--mint, #78dc8c)',
    warn:   'var(--warn)',
    red:    'var(--red)',
    rose:   'var(--rose, #f06292)',
    dim:    'var(--dim)',
  };

  /* Seeded rng for deterministic demo data */
  function mulberry32(seed) {
    return function() {
      let t = seed += 0x6D2B79F5;
      t = Math.imul(t ^ t >>> 15, t | 1);
      t ^= t + Math.imul(t ^ t >>> 7, t | 61);
      return ((t ^ t >>> 14) >>> 0) / 4294967296;
    };
  }

  /* ═══════════════════════════════════════════════════════════
     DATA GENERATORS
  ═══════════════════════════════════════════════════════════ */

  /* 12-month MRR series with growth + churn drift */
  function genMrrSeries() {
    const rng = mulberry32(42);
    const months = ['May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb','Mar','Apr'];
    let mrr = 8400; // 12 months ago
    const data = [];
    for (let i = 0; i < 12; i++) {
      const growth = (0.08 + rng()*0.06) * mrr;   // 8-14% new+expansion
      const churn  = (0.03 + rng()*0.02) * mrr;   // 3-5% churn
      mrr = mrr + growth - churn;
      data.push({
        month: months[i],
        mrr: Math.round(mrr),
        newMrr: Math.round(growth * 0.7),
        expansion: Math.round(growth * 0.3),
        churn: -Math.round(churn),
      });
    }
    return data;
  }

  /* Current customer counts by plan */
  const PLAN_DATA = [
    { plan:'Free',        count: 284, mrr: 0,      price: 0,   color: CHART.dim,    cogs: 1.8 },
    { plan:'Starter',     count: 187, mrr: 18513,  price: 99,  color: CHART.beam,   cogs: 8.2 },
    { plan:'Growth',      count:  94, mrr: 18706,  price: 199, color: CHART.orange, cogs: 22.4 },
    { plan:'Agency',      count:  31, mrr: 12369,  price: 399, color: CHART.mint,   cogs: 48.6 },
    { plan:'Enterprise',  count:   6, mrr:  4194,  price: 699, color: CHART.rose,   cogs: 112.3 },
  ];

  /* Add-on attach rates */
  const ADD_ONS = [
    { name:'Extra Scans (10/25/50)',   attach: 0.18, avgPrice: 31, volume: 58 },
    { name:'Deep Scan (500/1000pg)',   attach: 0.09, avgPrice: 36, volume: 29 },
    { name:'Priority Support',         attach: 0.07, avgPrice: 49, volume: 22 },
  ];

  /* Per-plan unit economics */
  const UNIT_ECON = [
    { plan:'Starter',    arpu:  99, cogs:  8.2, stripe:  3.27, support: 4.20, ai:  2.10, margin: 81.23, marginPct: 0.821 },
    { plan:'Growth',     arpu: 199, cogs: 22.4, stripe:  6.27, support: 6.80, ai:  7.50, margin: 156.03, marginPct: 0.784 },
    { plan:'Agency',     arpu: 399, cogs: 48.6, stripe: 11.87, support:12.40, ai: 18.60, margin: 307.53, marginPct: 0.771 },
    { plan:'Enterprise', arpu: 699, cogs:112.3, stripe: 20.57, support:28.00, ai: 47.80, margin: 490.33, marginPct: 0.702 },
  ];

  /* COGS per scan (Railway + AI + DB write) */
  const SCAN_COGS = [
    { item:'Railway compute (Puppeteer pool)', cost: 0.024, share: 0.42 },
    { item:'OpenAI API (tech-stack summary)',  cost: 0.018, share: 0.32 },
    { item:'Supabase write + storage',         cost: 0.005, share: 0.09 },
    { item:'Egress / bandwidth',               cost: 0.003, share: 0.05 },
    { item:'Monitoring / logging',             cost: 0.007, share: 0.12 },
  ];
  const SCAN_COST_TOTAL = SCAN_COGS.reduce((s,i) => s + i.cost, 0); // $0.057/scan

  /* Funnel data */
  const FUNNEL = [
    { stage:'Landing-page visits',      count: 14280 },
    { stage:'Free scan signups',        count:  1807, conv: 0.127 },
    { stage:'Scan completed',           count:  1620, conv: 0.897 },
    { stage:'Estimator opened',         count:   742, conv: 0.458 },
    { stage:'Upgrade modal shown',      count:   489, conv: 0.659 },
    { stage:'Checkout started',         count:   198, conv: 0.405 },
    { stage:'Paid conversion',          count:   142, conv: 0.717 },
  ];

  /* Churn cohort (by plan, trailing 6 months) */
  const CHURN = [
    { plan:'Starter',     gross: 0.058, net: 0.041 },
    { plan:'Growth',      gross: 0.034, net: 0.019 },
    { plan:'Agency',      gross: 0.022, net:-0.018 }, // net negative = expansion > churn
    { plan:'Enterprise',  gross: 0.017, net:-0.041 },
  ];

  /* Infra monthly costs — SA-editable, persisted to localStorage as demo
     (production: writes to Supabase business_config row) */
  const INFRA_DEFAULT = [
    { key:'railway',  name:'Railway (API + scanner pool)', cost: 387, source:'constant' },
    { key:'supabase', name:'Supabase (DB + Auth + Edge)',  cost: 249, source:'constant' },
    { key:'ai',       name:'AI API (Anthropic/OpenAI)',    cost: 198, source:'live',     note:'pulled from anthropic_api_log' },
    { key:'stripe',   name:'Stripe fees (calculated)',     cost:  89, source:'calculated' },
    { key:'cf',       name:'Cloudflare + monitoring',      cost:  47, source:'constant' },
    { key:'misc',     name:'Misc (email, storage, GHL)',   cost:  31, source:'constant' },
  ];

  /* Data source registry — wired to real endpoints in production.
     Each card/tab declares which endpoints it reads. Status is demo for now. */
  const DATA_SOURCES = [
    { id:'overview', endpoint:'GET /sa/metrics/overview', status:'demo', desc:'Combined summary — MRR + counts + top-line KPIs',
      feeds:['Overview KPI strip','Overview MRR line chart'] },
    { id:'mrr',      endpoint:'GET /sa/metrics/mrr',      status:'demo', desc:'MRR series + waterfall · reads accounts × plan × billing_interval',
      feeds:['MRR tab line chart','MRR waterfall table','Monthly movement stacked bars'] },
    { id:'plans',    endpoint:'GET /sa/metrics/plans',    status:'demo', desc:'Plan mix + attach rates · reads accounts + addon purchases',
      feeds:['Plans pie chart','Plan count bars','Unit economics table','Add-on attach rates'] },
    { id:'costs',    endpoint:'GET /sa/metrics/costs',    status:'demo', desc:'Infra + AI + per-scan · reads anthropic_api_log + business_config',
      feeds:['Infra spend donut','Cost per scan breakdown','Gross margin calc','Net margin by plan'] },
    { id:'funnel',   endpoint:'GET /sa/metrics/funnel',   status:'demo', desc:'Landing→paid conversion · reads signup_funnel_events + auth_events',
      feeds:['Conversion funnel bars','Churn by plan cards'] },
  ];

  /* Build status — surfaced in footer so SA can see what's deployed */
  const BUILD_STATUS = [
    { group:'Supabase migration', items:[
      { name:'anthropic_api_log table', status:'pending', notes:'account_id + scan_id + input_tok + output_tok + cost_cents + created_at' },
      { name:'signup_funnel_events table', status:'pending', notes:'event_name + session_id + account_id (nullable) + ts' },
      { name:'business_config row (infra constants)', status:'pending', notes:'Singleton row — Railway/Supabase/CF/Misc monthly costs' },
      { name:'plan_change_history (from auth_events)', status:'exists', notes:'Reuse existing auth_events table with event="plan_changed"' },
    ]},
    { group:'Railway endpoints', items:[
      { name:'GET /sa/metrics/overview', status:'pending', notes:'Combined summary — 1 call for Overview tab' },
      { name:'GET /sa/metrics/mrr',      status:'pending', notes:'Aggregate accounts by plan × interval × PLAN_LIMITS price' },
      { name:'GET /sa/metrics/plans',    status:'pending', notes:'Plan counts + ARPU + add-on attach' },
      { name:'GET /sa/metrics/costs',    status:'pending', notes:'Sum anthropic_api_log cost_cents + infra constants + Stripe fee calc' },
      { name:'GET /sa/metrics/funnel',   status:'pending', notes:'Stage counts from signup_funnel_events × date range' },
      { name:'SA role gate middleware',  status:'exists',  notes:'requireSA() already guards /sa/* routes' },
    ]},
    { group:'Frontend (this page)', items:[
      { name:'5 tabs + charts + tables', status:'done',    notes:'Overview / MRR / Plans / COGS / Funnel — all SVG, no deps' },
      { name:'Data Sources panel',       status:'done',    notes:'Shows endpoint per card + connection status' },
      { name:'Infra Costs editor modal', status:'done',    notes:'SA-editable constants persisted to localStorage (demo)' },
      { name:'Refresh button → endpoints', status:'pending', notes:'Wire refresh action to call all 5 endpoints' },
    ]},
  ];

  /* ═══════════════════════════════════════════════════════════
     CHART PRIMITIVES
     All SVG, no external deps. Responsive via viewBox.
  ═══════════════════════════════════════════════════════════ */

  /* Sparkline — tiny inline line chart */
  function Sparkline({ data, color = CHART.beam, height = 32, width = 110 }) {
    if (!data || data.length < 2) return null;
    const max = Math.max(...data);
    const min = Math.min(...data);
    const rng = max - min || 1;
    const step = width / (data.length - 1);
    const pts = data.map((v,i) => `${i*step},${height - ((v - min)/rng)*height}`).join(' ');
    return (
      <svg width={width} height={height} style={{ overflow:'visible' }}>
        <polyline points={pts} fill="none" stroke={color} strokeWidth="1.75" strokeLinejoin="round" strokeLinecap="round"/>
        <circle cx={(data.length-1)*step} cy={height - ((data[data.length-1]-min)/rng)*height} r="2.5" fill={color}/>
      </svg>
    );
  }

  /* Line chart — full size, with axes + hover tooltip */
  function LineChart({ series, height = 280, formatY = v => v, accentColor = CHART.beam }) {
    const [hover, setHover] = useState(null);
    const vb = { w: 800, h: height, padL: 58, padR: 18, padT: 18, padB: 32 };
    const chartW = vb.w - vb.padL - vb.padR;
    const chartH = vb.h - vb.padT - vb.padB;
    const n = series.length;
    const max = Math.max(...series.map(s => s.value));
    const min = 0;
    const rng = max - min || 1;
    const step = chartW / (n - 1);
    const pts = series.map((s,i) => [vb.padL + i*step, vb.padT + chartH - ((s.value - min)/rng)*chartH]);
    const path = pts.map((p,i) => `${i===0?'M':'L'} ${p[0]} ${p[1]}`).join(' ');
    const areaPath = `${path} L ${pts[n-1][0]} ${vb.padT+chartH} L ${pts[0][0]} ${vb.padT+chartH} Z`;

    // Y-axis ticks
    const ticks = 4;
    const tickVals = Array.from({length: ticks+1}, (_,i) => min + (rng * i / ticks));

    return (
      <svg viewBox={`0 0 ${vb.w} ${vb.h}`} style={{ width:'100%', height, display:'block' }}
           onMouseMove={(e) => {
             const rect = e.currentTarget.getBoundingClientRect();
             const x = ((e.clientX - rect.left) / rect.width) * vb.w;
             const idx = Math.round((x - vb.padL) / step);
             if (idx >= 0 && idx < n) setHover(idx);
           }}
           onMouseLeave={() => setHover(null)}>
        {/* Grid lines */}
        {tickVals.map((v,i) => {
          const y = vb.padT + chartH - ((v - min)/rng)*chartH;
          return (
            <g key={i}>
              <line x1={vb.padL} x2={vb.padL + chartW} y1={y} y2={y} stroke="var(--border)" strokeDasharray="2 3"/>
              <text x={vb.padL - 6} y={y + 3} textAnchor="end" fontSize="10" fill="var(--dim)" fontFamily="var(--font-mono)">{formatY(v)}</text>
            </g>
          );
        })}
        {/* X-axis labels */}
        {series.map((s,i) => (
          <text key={i} x={vb.padL + i*step} y={vb.padT + chartH + 18} textAnchor="middle" fontSize="10" fill="var(--dim)">{s.label}</text>
        ))}
        {/* Area fill */}
        <path d={areaPath} fill={accentColor} opacity="0.12"/>
        {/* Line */}
        <path d={path} fill="none" stroke={accentColor} strokeWidth="2" strokeLinejoin="round"/>
        {/* Points */}
        {pts.map((p,i) => (
          <circle key={i} cx={p[0]} cy={p[1]} r={hover === i ? 4.5 : 2.5} fill={accentColor}/>
        ))}
        {/* Hover tooltip */}
        {hover != null && (
          <g>
            <line x1={pts[hover][0]} x2={pts[hover][0]} y1={vb.padT} y2={vb.padT + chartH} stroke={accentColor} strokeDasharray="3 3" opacity="0.5"/>
            <rect x={pts[hover][0] + 8} y={pts[hover][1] - 28} width="90" height="36" rx="4" fill="var(--surface-2)" stroke="var(--border)"/>
            <text x={pts[hover][0] + 14} y={pts[hover][1] - 13} fontSize="10" fill="var(--dim)">{series[hover].label}</text>
            <text x={pts[hover][0] + 14} y={pts[hover][1] + 1} fontSize="12" fontWeight="600" fill="var(--text)">{formatY(series[hover].value)}</text>
          </g>
        )}
      </svg>
    );
  }

  /* Bar chart (vertical) — with stacked variant */
  function BarChart({ data, height = 260, stacked = false, formatY = v => v, accentColor = CHART.beam }) {
    const vb = { w: 720, h: height, padL: 58, padR: 18, padT: 18, padB: 42 };
    const chartW = vb.w - vb.padL - vb.padR;
    const chartH = vb.h - vb.padT - vb.padB;
    const n = data.length;
    const barGap = 14;
    const barW = (chartW - barGap*(n-1)) / n;

    const max = stacked
      ? Math.max(...data.map(d => (d.stacks || []).reduce((a,b) => a + Math.abs(b.value), 0)))
      : Math.max(...data.map(d => d.value));
    const rng = max || 1;
    const ticks = 4;
    const tickVals = Array.from({length: ticks+1}, (_,i) => (rng * i / ticks));

    return (
      <svg viewBox={`0 0 ${vb.w} ${vb.h}`} style={{ width:'100%', height, display:'block' }}>
        {tickVals.map((v,i) => {
          const y = vb.padT + chartH - (v/rng)*chartH;
          return (
            <g key={i}>
              <line x1={vb.padL} x2={vb.padL + chartW} y1={y} y2={y} stroke="var(--border)" strokeDasharray="2 3"/>
              <text x={vb.padL - 6} y={y + 3} textAnchor="end" fontSize="10" fill="var(--dim)" fontFamily="var(--font-mono)">{formatY(v)}</text>
            </g>
          );
        })}
        {data.map((d,i) => {
          const x = vb.padL + i*(barW + barGap);
          if (stacked && d.stacks) {
            let yCursor = vb.padT + chartH;
            return (
              <g key={i}>
                {d.stacks.map((st, si) => {
                  const h = (Math.abs(st.value) / rng) * chartH;
                  yCursor -= h;
                  return <rect key={si} x={x} y={yCursor} width={barW} height={h} fill={st.color} rx="2"/>;
                })}
                <text x={x + barW/2} y={vb.padT + chartH + 16} textAnchor="middle" fontSize="10" fill="var(--dim)">{d.label}</text>
              </g>
            );
          }
          const h = (d.value / rng) * chartH;
          const y = vb.padT + chartH - h;
          return (
            <g key={i}>
              <rect x={x} y={y} width={barW} height={h} fill={d.color || accentColor} rx="3"/>
              <text x={x + barW/2} y={y - 6} textAnchor="middle" fontSize="11" fill="var(--text)" fontWeight="600">{formatY(d.value)}</text>
              <text x={x + barW/2} y={vb.padT + chartH + 16} textAnchor="middle" fontSize="10" fill="var(--dim)">{d.label}</text>
            </g>
          );
        })}
      </svg>
    );
  }

  /* Pie / donut chart */
  function PieChart({ data, size = 220, donut = true, centerLabel = null, centerValue = null }) {
    const total = data.reduce((s,d) => s + d.value, 0);
    const cx = size/2, cy = size/2;
    const r = size/2 - 8;
    const rInner = donut ? r * 0.58 : 0;
    let angleCursor = -Math.PI / 2;
    const slices = data.map(d => {
      const a = (d.value / total) * Math.PI * 2;
      const a0 = angleCursor;
      const a1 = angleCursor + a;
      angleCursor = a1;
      const x0 = cx + Math.cos(a0) * r, y0 = cy + Math.sin(a0) * r;
      const x1 = cx + Math.cos(a1) * r, y1 = cy + Math.sin(a1) * r;
      const large = a > Math.PI ? 1 : 0;
      let path;
      if (donut) {
        const xi0 = cx + Math.cos(a0) * rInner, yi0 = cy + Math.sin(a0) * rInner;
        const xi1 = cx + Math.cos(a1) * rInner, yi1 = cy + Math.sin(a1) * rInner;
        path = `M ${x0} ${y0} A ${r} ${r} 0 ${large} 1 ${x1} ${y1} L ${xi1} ${yi1} A ${rInner} ${rInner} 0 ${large} 0 ${xi0} ${yi0} Z`;
      } else {
        path = `M ${cx} ${cy} L ${x0} ${y0} A ${r} ${r} 0 ${large} 1 ${x1} ${y1} Z`;
      }
      return { path, color: d.color, label: d.label, value: d.value, pct: d.value/total };
    });
    return (
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        {slices.map((s,i) => <path key={i} d={s.path} fill={s.color} stroke="var(--surface)" strokeWidth="1.5"/>)}
        {donut && centerValue && (
          <>
            <text x={cx} y={cy - 4} textAnchor="middle" fontSize="11" fill="var(--dim)">{centerLabel}</text>
            <text x={cx} y={cy + 16} textAnchor="middle" fontSize="18" fontWeight="700" fill="var(--text)" fontFamily="var(--font-mono)">{centerValue}</text>
          </>
        )}
      </svg>
    );
  }

  /* Horizontal bar (for funnel + cost stacks) */
  function HBar({ label, value, max, color = CHART.beam, subValue = null, pct = null }) {
    const w = Math.max(2, (value / max) * 100);
    return (
      <div style={{ display:'grid', gridTemplateColumns:'180px 1fr 110px', gap:10, alignItems:'center', fontSize:'.74rem', marginBottom:8 }}>
        <div style={{ color:'var(--text)', fontWeight:500, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{label}</div>
        <div style={{ position:'relative', height:22, background:'var(--surface-2)', borderRadius:3, overflow:'hidden' }}>
          <div style={{ position:'absolute', inset:0, width:`${w}%`, background:color, borderRadius:3, transition:'width .3s' }}/>
          {pct != null && <div style={{ position:'absolute', inset:0, display:'flex', alignItems:'center', paddingLeft:8, color:'var(--text)', fontSize:'.64rem', fontWeight:600 }}>{(pct*100).toFixed(1)}%</div>}
        </div>
        <div style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--text)' }}>
          <div style={{ fontWeight:600 }}>{typeof value === 'number' ? value.toLocaleString() : value}</div>
          {subValue != null && <div style={{ fontSize:'.6rem', color:'var(--dim)' }}>{subValue}</div>}
        </div>
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     MAIN COMPONENT
  ═══════════════════════════════════════════════════════════ */
  function BusinessMetrics() {
    const Icon = window.Icon;
    const PageHead = window.Pages1?.PageHead;

    const [tab, setTab] = useState(() => {
      try { return localStorage.getItem('wpsb-bm-tab') || 'overview'; } catch { return 'overview'; }
    });
    const [period, setPeriod] = useState('12m');
    const [showSources, setShowSources] = useState(false);
    const [showInfraEdit, setShowInfraEdit] = useState(false);
    const [infra, setInfra] = useState(() => {
      try {
        const saved = JSON.parse(localStorage.getItem('wpsb-bm-infra') || 'null');
        return saved || INFRA_DEFAULT;
      } catch { return INFRA_DEFAULT; }
    });
    useEffect(() => { try { localStorage.setItem('wpsb-bm-infra', JSON.stringify(infra)); } catch {} }, [infra]);
    useEffect(() => { try { localStorage.setItem('wpsb-bm-tab', tab); } catch {} }, [tab]);

    const mrrSeries = useMemo(genMrrSeries, []);
    const currentMrr = mrrSeries[mrrSeries.length - 1].mrr;
    const priorMrr   = mrrSeries[mrrSeries.length - 2].mrr;
    const mrrGrowth  = (currentMrr - priorMrr) / priorMrr;
    const arr = currentMrr * 12;
    const totalPaid = PLAN_DATA.filter(p => p.price > 0).reduce((s,p) => s + p.count, 0);
    const totalFree = PLAN_DATA.find(p => p.plan === 'Free').count;
    const arpu = currentMrr / totalPaid;
    const monthlyInfra = infra.reduce((s,i) => s + i.cost, 0);
    const grossMargin = (currentMrr - monthlyInfra) / currentMrr;
    const weightedChurn = CHURN.reduce((s,c) => s + (c.gross * PLAN_DATA.find(p => p.plan === c.plan).mrr), 0) / currentMrr;

    return (
      <div>
        <PageHead crumb="SA Tools"
          title={<span style={{ display:'inline-flex', alignItems:'center', gap:10 }}>
            Business Metrics
            <span style={{ fontFamily:'var(--font-mono)', fontSize:'.58rem', padding:'3px 8px', borderRadius:4, background:'rgba(200,120,255,.12)', border:'1px solid rgba(200,120,255,.3)', color:'#c878ff', letterSpacing:'.08em' }}>SA ONLY · LIVE</span>
          </span>}
          sub={<>Executive view of MRR, plan mix, unit economics, infra COGS, and conversion funnel. Connected to Stripe + Supabase + Railway. Demo data shown below — swap to production in <span style={{ color:'var(--muted)' }}>Account → Data Sources</span>.</>}
          actions={<>
            <select value={period} onChange={e=>setPeriod(e.target.value)} className="sel-sm">
              <option value="1m">Last 30 days</option>
              <option value="3m">Last 3 months</option>
              <option value="12m">Last 12 months</option>
              <option value="all">All time</option>
            </select>
            <button className="btn btn-ghost btn-sm" onClick={() => setShowSources(!showSources)}>
              <Icon name="activity" size={13}/>Data sources
            </button>
            <button className="btn btn-ghost btn-sm" onClick={() => setShowInfraEdit(true)}>
              <Icon name="settings" size={13}/>Edit infra costs
            </button>
            <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast?.('CSV export queued', 'beam')}>
              <Icon name="download" size={13}/>Export CSV
            </button>
            <button className="btn btn-ghost btn-sm" onClick={() => window.wpsbToast?.('Refreshing from 5 endpoints (demo mode — returning cached data)', 'beam')}>
              <Icon name="refresh" size={13}/>Refresh
            </button>
          </>}
        />

        {/* ── Headline KPI strip ─────────────────────────────── */}
        <div className="grid" style={{ display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(170px, 1fr))', gap:12, marginBottom:16 }}>
          <KPI label="MRR"           value={`$${currentMrr.toLocaleString()}`} delta={mrrGrowth} spark={mrrSeries.map(m => m.mrr)} color={CHART.beam}/>
          <KPI label="ARR"           value={`$${Math.round(arr/1000)}k`}       delta={mrrGrowth} color={CHART.orange}/>
          <KPI label="Paid customers" value={totalPaid.toLocaleString()}       delta={0.062}    color={CHART.mint}/>
          <KPI label="Free users"    value={totalFree.toLocaleString()}        delta={0.148}    sub="pipeline" color={CHART.dim}/>
          <KPI label="ARPU"          value={`$${arpu.toFixed(0)}`}             delta={0.021}    color={CHART.orange}/>
          <KPI label="Gross margin"  value={`${(grossMargin*100).toFixed(1)}%`} delta={0.014}   color={CHART.mint}/>
          <KPI label="Gross churn"   value={`${(weightedChurn*100).toFixed(2)}%`} delta={-0.006} invertDelta color={CHART.warn}/>
        </div>

        {/* ── Tab nav ────────────────────────────────────────── */}
        <div className="card" style={{ marginBottom:16 }}>
          <div style={{ display:'flex', borderBottom:'1px solid var(--border)' }}>
            {[
              { id:'overview', label:'Overview',   icon:'dashboard' },
              { id:'mrr',      label:'MRR & ARR',  icon:'trend' },
              { id:'plans',    label:'Plans',      icon:'stack' },
              { id:'cogs',     label:'COGS',       icon:'calc' },
              { id:'funnel',   label:'Funnel',     icon:'filter' },
            ].map(t => {
              const active = tab === t.id;
              return (
                <button key={t.id} onClick={() => setTab(t.id)}
                  style={{
                    padding:'12px 18px', cursor:'pointer', background:'transparent', border:'none',
                    borderBottom: active ? '2px solid var(--beam)' : '2px solid transparent',
                    color: active ? 'var(--text)' : 'var(--muted)',
                    fontWeight: active ? 600 : 500, fontSize:'.8rem', fontFamily:'inherit',
                    display:'flex', alignItems:'center', gap:8,
                  }}>
                  <Icon name={t.icon} size={14}/>{t.label}
                </button>
              );
            })}
          </div>
        </div>

        {/* ── Data Sources panel (collapsible) ───────────────── */}
        {showSources && <DataSourcesPanel activeTab={tab} onClose={() => setShowSources(false)}/>}

        {tab === 'overview' && <OverviewTab mrrSeries={mrrSeries} currentMrr={currentMrr}/>}
        {tab === 'mrr'      && <MrrTab mrrSeries={mrrSeries}/>}
        {tab === 'plans'    && <PlansTab/>}
        {tab === 'cogs'     && <CogsTab currentMrr={currentMrr} monthlyInfra={monthlyInfra} infra={infra}/>}
        {tab === 'funnel'   && <FunnelTab/>}

        {/* ── Build Status footer ────────────────────────────── */}
        <BuildStatusFooter/>

        {/* ── Infra Costs editor modal ──────────────────────── */}
        {showInfraEdit && <InfraEditor infra={infra} setInfra={setInfra} onClose={() => setShowInfraEdit(false)}/>}
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     DATA SOURCES PANEL — shows which endpoint feeds each card
  ═══════════════════════════════════════════════════════════ */
  function DataSourcesPanel({ activeTab, onClose }) {
    const Icon = window.Icon;
    return (
      <div className="card" style={{ marginBottom:16, border:'1px solid rgba(200,120,255,.3)', background:'rgba(200,120,255,.04)' }}>
        <div className="card-head" style={{ background:'rgba(200,120,255,.08)' }}>
          <h3 className="card-title" style={{ color:'#c878ff' }}>
            <Icon name="activity" size={13} style={{ marginRight:6 }}/>Data sources · 5 endpoints
          </h3>
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <span className="tag" style={{ color:'var(--warn)', fontSize:'.6rem' }}>All endpoints demo · awaiting Railway deploy</span>
            <button className="btn btn-ghost btn-sm" onClick={onClose}><Icon name="x" size={12}/></button>
          </div>
        </div>
        <div className="card-body" style={{ padding:0 }}>
          <table className="data-table" style={{ width:'100%' }}>
            <thead>
              <tr>
                <th style={{ width:160 }}>Endpoint</th>
                <th>Description</th>
                <th style={{ width:240 }}>Feeds</th>
                <th style={{ width:90, textAlign:'center' }}>Status</th>
              </tr>
            </thead>
            <tbody>
              {DATA_SOURCES.map(ds => {
                const isActive = ds.id === activeTab || activeTab === 'overview';
                return (
                  <tr key={ds.id} style={{ opacity: isActive ? 1 : 0.55 }}>
                    <td style={{ fontFamily:'var(--font-mono)', fontSize:'.68rem', color:'var(--beam)' }}>{ds.endpoint}</td>
                    <td style={{ fontSize:'.72rem', color:'var(--muted)' }}>{ds.desc}</td>
                    <td style={{ fontSize:'.66rem', color:'var(--dim)' }}>
                      {ds.feeds.map((f,i) => <div key={i}>• {f}</div>)}
                    </td>
                    <td style={{ textAlign:'center' }}>
                      <span className="tag" style={{
                        color: ds.status === 'live' ? 'var(--mint)' : 'var(--warn)',
                        fontSize:'.56rem', letterSpacing:'.08em', fontWeight:700,
                      }}>{ds.status.toUpperCase()}</span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        <div style={{ padding:'10px 16px', borderTop:'1px solid var(--border)', display:'flex', justifyContent:'space-between', alignItems:'center', fontSize:'.66rem', color:'var(--dim)' }}>
          <span>Active tab highlights the primary endpoint · see Build Status below for deploy checklist</span>
          <span style={{ fontFamily:'var(--font-mono)' }}>SA role gate: <span style={{ color:'var(--mint)' }}>requireSA()</span> already deployed</span>
        </div>
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     INFRA COSTS EDITOR — SA-editable constants
     Persists to localStorage (demo). Production writes to
     Supabase `business_config` singleton row.
  ═══════════════════════════════════════════════════════════ */
  function InfraEditor({ infra, setInfra, onClose }) {
    const Icon = window.Icon;
    const [draft, setDraft] = useState(infra);
    const total = draft.reduce((s,i) => s + (Number(i.cost) || 0), 0);
    const save = () => {
      setInfra(draft.map(d => ({ ...d, cost: Number(d.cost) || 0 })));
      window.wpsbToast?.('Infra costs updated — will write to business_config in production', 'beam');
      onClose();
    };
    return (
      <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.55)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:1000 }}
           onClick={onClose}>
        <div className="card" style={{ width:640, maxWidth:'90vw', maxHeight:'88vh', overflow:'auto' }} onClick={e => e.stopPropagation()}>
          <div className="card-head">
            <h3 className="card-title">Infrastructure costs · SA-managed constants</h3>
            <button className="btn btn-ghost btn-sm" onClick={onClose}><Icon name="x" size={12}/></button>
          </div>
          <div style={{ padding:'10px 16px', background:'var(--surface-2)', borderBottom:'1px solid var(--border)', fontSize:'.7rem', color:'var(--muted)' }}>
            Edits flow into Gross-margin, Net-margin, and Cost-per-scan calculations. In production these persist to a Supabase <code style={{ color:'var(--beam)', fontFamily:'var(--font-mono)' }}>business_config</code> singleton row.
          </div>
          <div className="card-body" style={{ padding:0 }}>
            <table className="data-table" style={{ width:'100%' }}>
              <thead>
                <tr>
                  <th>Category</th>
                  <th style={{ width:110 }}>Source</th>
                  <th style={{ width:120, textAlign:'right' }}>$/month</th>
                </tr>
              </thead>
              <tbody>
                {draft.map((item, i) => (
                  <tr key={item.key}>
                    <td>
                      <div style={{ color:'var(--text)', fontWeight:500 }}>{item.name}</div>
                      {item.note && <div style={{ fontSize:'.6rem', color:'var(--dim)', fontFamily:'var(--font-mono)' }}>{item.note}</div>}
                    </td>
                    <td>
                      <span className="tag" style={{ fontSize:'.56rem',
                        color: item.source === 'live' ? 'var(--mint)' : item.source === 'calculated' ? 'var(--orange)' : 'var(--dim)'
                      }}>{item.source.toUpperCase()}</span>
                    </td>
                    <td style={{ textAlign:'right' }}>
                      {item.source === 'live' ? (
                        <span style={{ fontFamily:'var(--font-mono)', color:'var(--mint)' }}>${item.cost} <span style={{ color:'var(--dim)', fontSize:'.6rem' }}>auto</span></span>
                      ) : item.source === 'calculated' ? (
                        <span style={{ fontFamily:'var(--font-mono)', color:'var(--orange)' }}>${item.cost} <span style={{ color:'var(--dim)', fontSize:'.6rem' }}>calc</span></span>
                      ) : (
                        <input type="number" value={item.cost}
                          onChange={e => {
                            const next = [...draft];
                            next[i] = { ...item, cost: e.target.value };
                            setDraft(next);
                          }}
                          style={{ width:90, textAlign:'right', fontFamily:'var(--font-mono)' }}
                        />
                      )}
                    </td>
                  </tr>
                ))}
                <tr style={{ background:'var(--surface-2)', fontWeight:700 }}>
                  <td colSpan={2} style={{ color:'var(--text)' }}>Total monthly infra</td>
                  <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--warn)' }}>${total.toLocaleString()}</td>
                </tr>
              </tbody>
            </table>
          </div>
          <div style={{ padding:'12px 16px', borderTop:'1px solid var(--border)', display:'flex', justifyContent:'space-between', alignItems:'center' }}>
            <div style={{ fontSize:'.64rem', color:'var(--dim)' }}>
              <div><span className="tag" style={{ color:'var(--mint)', fontSize:'.54rem' }}>LIVE</span> = pulled from <code style={{ fontFamily:'var(--font-mono)', color:'var(--mint)' }}>anthropic_api_log</code></div>
              <div><span className="tag" style={{ color:'var(--orange)', fontSize:'.54rem' }}>CALC</span> = computed from MRR × 2.9% + count × $0.30</div>
              <div><span className="tag" style={{ color:'var(--dim)', fontSize:'.54rem' }}>CONSTANT</span> = SA-editable flat monthly cost</div>
            </div>
            <div style={{ display:'flex', gap:6 }}>
              <button className="btn btn-ghost btn-sm" onClick={() => setDraft(INFRA_DEFAULT)}>Reset to defaults</button>
              <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
              <button className="btn btn-beam btn-sm" onClick={save}><Icon name="check" size={12}/>Save</button>
            </div>
          </div>
        </div>
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     BUILD STATUS FOOTER — deploy checklist for Supabase + Railway
  ═══════════════════════════════════════════════════════════ */
  function BuildStatusFooter() {
    const Icon = window.Icon;
    const all = BUILD_STATUS.flatMap(g => g.items);
    const done    = all.filter(i => i.status === 'done').length;
    const exists  = all.filter(i => i.status === 'exists').length;
    const pending = all.filter(i => i.status === 'pending').length;
    return (
      <div className="card" style={{ marginTop:16 }}>
        <div className="card-head">
          <h3 className="card-title">
            <Icon name="code" size={13} style={{ marginRight:6 }}/>Build status · backend deploy checklist
          </h3>
          <div style={{ display:'flex', gap:6, fontSize:'.6rem' }}>
            <span className="tag" style={{ color:'var(--mint)' }}>{done} done</span>
            <span className="tag" style={{ color:'var(--beam)' }}>{exists} already exists</span>
            <span className="tag" style={{ color:'var(--warn)' }}>{pending} pending</span>
          </div>
        </div>
        <div className="card-body" style={{ padding:0, display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(320px, 1fr))' }}>
          {BUILD_STATUS.map(g => (
            <div key={g.group} style={{ borderRight:'1px solid var(--border)', padding:'14px 16px' }}>
              <div style={{ fontSize:'.62rem', color:'var(--dim)', textTransform:'uppercase', letterSpacing:'.08em', fontWeight:700, marginBottom:10 }}>{g.group}</div>
              {g.items.map((item, i) => {
                const color = item.status === 'done' ? 'var(--mint)'
                            : item.status === 'exists' ? 'var(--beam)'
                            : 'var(--warn)';
                const icon  = item.status === 'done' ? 'check'
                            : item.status === 'exists' ? 'check'
                            : 'circle';
                return (
                  <div key={i} style={{ display:'flex', gap:8, alignItems:'flex-start', marginBottom:8, paddingBottom:8, borderBottom: i < g.items.length-1 ? '1px solid var(--border)' : 'none' }}>
                    <div style={{ color, marginTop:2, flexShrink:0 }}><Icon name={icon} size={12}/></div>
                    <div style={{ minWidth:0, flex:1 }}>
                      <div style={{ fontSize:'.72rem', color:'var(--text)', fontWeight:500, fontFamily: item.name.includes('/') ? 'var(--font-mono)' : 'inherit' }}>{item.name}</div>
                      <div style={{ fontSize:'.6rem', color:'var(--dim)', marginTop:2, lineHeight:1.4 }}>{item.notes}</div>
                    </div>
                  </div>
                );
              })}
            </div>
          ))}
        </div>
        <div style={{ padding:'10px 16px', borderTop:'1px solid var(--border)', background:'var(--surface-2)', fontSize:'.66rem', color:'var(--muted)', display:'flex', justifyContent:'space-between' }}>
          <span>Next: run Supabase migration → deploy Railway endpoints → flip page from demo to live</span>
          <span style={{ fontFamily:'var(--font-mono)', color:'var(--dim)' }}>Estimated deploy: ~4 hrs (SQL 30m · endpoints 2h · testing 1.5h)</span>
        </div>
      </div>
    );
  }

  /* KPI card with sparkline */
  function KPI({ label, value, delta, spark, color = CHART.beam, sub = null, invertDelta = false }) {
    const dColor = (invertDelta ? -delta : delta) >= 0 ? 'var(--mint)' : 'var(--red)';
    const arrow  = delta >= 0 ? '↑' : '↓';
    return (
      <div className="card" style={{ padding:'14px 16px', display:'flex', flexDirection:'column', gap:6, minHeight:88 }}>
        <div style={{ fontSize:'.58rem', color:'var(--dim)', textTransform:'uppercase', letterSpacing:'.08em', fontWeight:700 }}>{label}</div>
        <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', gap:8 }}>
          <div style={{ fontSize:'1.3rem', fontWeight:700, color:'var(--text)', fontFamily:'var(--font-mono)', letterSpacing:'-.01em' }}>{value}</div>
          {spark && <Sparkline data={spark} color={color} height={26} width={72}/>}
        </div>
        <div style={{ display:'flex', justifyContent:'space-between', fontSize:'.64rem' }}>
          <span style={{ color: dColor, fontWeight:600 }}>{arrow} {Math.abs(delta*100).toFixed(1)}%</span>
          <span style={{ color:'var(--dim)' }}>{sub || 'vs last period'}</span>
        </div>
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     OVERVIEW TAB
  ═══════════════════════════════════════════════════════════ */
  function OverviewTab({ mrrSeries, currentMrr }) {
    const Icon = window.Icon;
    return (
      <>
        <div className="grid" style={{ display:'grid', gridTemplateColumns:'2fr 1fr', gap:16, marginBottom:16 }}>
          <div className="card">
            <div className="card-head">
              <h3 className="card-title">MRR growth · trailing 12 months</h3>
              <span className="tag" style={{ color:'var(--mint)' }}>${currentMrr.toLocaleString()} current</span>
            </div>
            <div className="card-body">
              <LineChart
                series={mrrSeries.map(m => ({ label: m.month, value: m.mrr }))}
                formatY={v => '$' + Math.round(v/1000) + 'k'}
                accentColor={CHART.beam}
              />
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h3 className="card-title">Plan mix · paid only</h3></div>
            <div className="card-body" style={{ display:'flex', alignItems:'center', gap:16, padding:16 }}>
              <PieChart
                data={PLAN_DATA.filter(p => p.price > 0).map(p => ({ label: p.plan, value: p.count, color: p.color }))}
                donut
                centerLabel="Total paid"
                centerValue={PLAN_DATA.filter(p => p.price > 0).reduce((s,p) => s + p.count, 0).toString()}
              />
              <div style={{ flex:1, display:'flex', flexDirection:'column', gap:6 }}>
                {PLAN_DATA.filter(p => p.price > 0).map(p => (
                  <div key={p.plan} style={{ display:'flex', alignItems:'center', gap:8, fontSize:'.72rem' }}>
                    <span style={{ width:10, height:10, borderRadius:2, background:p.color }}/>
                    <span style={{ flex:1, color:'var(--text)' }}>{p.plan}</span>
                    <span style={{ color:'var(--dim)', fontFamily:'var(--font-mono)' }}>{p.count}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>

        {/* Secondary row */}
        <div className="grid" style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, marginBottom:16 }}>
          <div className="card">
            <div className="card-head"><h3 className="card-title">Month-over-month movement</h3></div>
            <div className="card-body">
              <BarChart
                data={mrrSeries.slice(-6).map(m => ({
                  label: m.month,
                  stacks: [
                    { value: m.newMrr,    color: CHART.beam },
                    { value: m.expansion, color: CHART.mint },
                    { value: Math.abs(m.churn), color: CHART.red },
                  ],
                }))}
                stacked
                formatY={v => '$' + Math.round(v/1000) + 'k'}
              />
              <div style={{ display:'flex', gap:16, justifyContent:'center', marginTop:8, fontSize:'.68rem', color:'var(--dim)' }}>
                <span><span style={{display:'inline-block',width:10,height:10,background:CHART.beam,borderRadius:2,marginRight:4}}/>New</span>
                <span><span style={{display:'inline-block',width:10,height:10,background:CHART.mint,borderRadius:2,marginRight:4}}/>Expansion</span>
                <span><span style={{display:'inline-block',width:10,height:10,background:CHART.red,borderRadius:2,marginRight:4}}/>Churn</span>
              </div>
            </div>
          </div>
          <div className="card">
            <div className="card-head"><h3 className="card-title">Key events this month</h3></div>
            <div className="card-body" style={{ padding:'8px 0' }}>
              {[
                { icon:'trend',   text:'MRR crossed $65k — new high',                meta:'2 days ago', color:CHART.mint },
                { icon:'plus',    text:'3 Enterprise upgrades (2× Growth, 1× Agency)', meta:'this week', color:CHART.beam },
                { icon:'warn',    text:'Starter churn up 0.4pp — investigate onboarding', meta:'Apr 18', color:CHART.warn },
                { icon:'spark',   text:'Deep Scan add-on attach rose 23%',           meta:'Apr 15',   color:CHART.orange },
                { icon:'x',       text:'1 Enterprise downgrade to Agency',           meta:'Apr 12',   color:CHART.red },
              ].map((e,i) => (
                <div key={i} style={{ display:'flex', gap:10, padding:'10px 16px', borderBottom: i < 4 ? '1px solid var(--border)' : 'none', alignItems:'flex-start' }}>
                  <div style={{ width:22, height:22, borderRadius:4, background: e.color + '22', color: e.color, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                    <Icon name={e.icon} size={12}/>
                  </div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:'.76rem', color:'var(--text)' }}>{e.text}</div>
                    <div style={{ fontSize:'.62rem', color:'var(--dim)', marginTop:2 }}>{e.meta}</div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     MRR TAB
  ═══════════════════════════════════════════════════════════ */
  function MrrTab({ mrrSeries }) {
    const latest = mrrSeries[mrrSeries.length - 1];
    const totalNew       = mrrSeries.reduce((s,m) => s + m.newMrr, 0);
    const totalExpansion = mrrSeries.reduce((s,m) => s + m.expansion, 0);
    const totalChurn     = mrrSeries.reduce((s,m) => s + m.churn, 0);
    return (
      <>
        <div className="card" style={{ marginBottom:16 }}>
          <div className="card-head">
            <h3 className="card-title">MRR trend · 12 months</h3>
            <div style={{ display:'flex', gap:12, fontSize:'.68rem', color:'var(--dim)' }}>
              <span>Start: <span style={{ color:'var(--text)', fontFamily:'var(--font-mono)' }}>${mrrSeries[0].mrr.toLocaleString()}</span></span>
              <span>Now: <span style={{ color:'var(--text)', fontFamily:'var(--font-mono)' }}>${latest.mrr.toLocaleString()}</span></span>
              <span>Growth: <span style={{ color:'var(--mint)', fontWeight:600 }}>+{(((latest.mrr - mrrSeries[0].mrr)/mrrSeries[0].mrr)*100).toFixed(0)}%</span></span>
            </div>
          </div>
          <div className="card-body">
            <LineChart
              series={mrrSeries.map(m => ({ label: m.month, value: m.mrr }))}
              formatY={v => '$' + Math.round(v/1000) + 'k'}
              accentColor={CHART.beam}
              height={320}
            />
          </div>
        </div>

        <div className="grid" style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:16, marginBottom:16 }}>
          <SummaryCard label="New MRR · 12mo"       value={`$${totalNew.toLocaleString()}`}       color={CHART.beam}   icon="plus"/>
          <SummaryCard label="Expansion MRR · 12mo" value={`$${totalExpansion.toLocaleString()}`} color={CHART.mint}   icon="trend"/>
          <SummaryCard label="Churned MRR · 12mo"   value={`$${Math.abs(totalChurn).toLocaleString()}`} color={CHART.red} icon="x"/>
        </div>

        <div className="card" style={{ marginBottom:16 }}>
          <div className="card-head"><h3 className="card-title">Monthly waterfall · last 12 months</h3></div>
          <div className="card-body" style={{ padding:0 }}>
            <table className="data-table" style={{ width:'100%' }}>
              <thead>
                <tr>
                  <th>Month</th><th style={{ textAlign:'right' }}>MRR</th><th style={{ textAlign:'right' }}>New</th>
                  <th style={{ textAlign:'right' }}>Expansion</th><th style={{ textAlign:'right' }}>Churn</th>
                  <th style={{ textAlign:'right' }}>Net</th>
                </tr>
              </thead>
              <tbody>
                {mrrSeries.map(m => (
                  <tr key={m.month}>
                    <td>{m.month}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', fontWeight:600 }}>${m.mrr.toLocaleString()}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--beam)' }}>+${m.newMrr.toLocaleString()}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--mint)' }}>+${m.expansion.toLocaleString()}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--red)' }}>${m.churn.toLocaleString()}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', fontWeight:600, color: (m.newMrr + m.expansion + m.churn) > 0 ? 'var(--mint)' : 'var(--red)' }}>
                      {(m.newMrr + m.expansion + m.churn) >= 0 ? '+' : ''}${(m.newMrr + m.expansion + m.churn).toLocaleString()}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </>
    );
  }

  function SummaryCard({ label, value, color, icon }) {
    const Icon = window.Icon;
    return (
      <div className="card" style={{ padding:'16px 18px', display:'flex', alignItems:'center', gap:14 }}>
        <div style={{ width:40, height:40, borderRadius:8, background: color + '22', color, display:'flex', alignItems:'center', justifyContent:'center' }}>
          <Icon name={icon} size={18}/>
        </div>
        <div>
          <div style={{ fontSize:'.58rem', color:'var(--dim)', textTransform:'uppercase', letterSpacing:'.08em', fontWeight:700 }}>{label}</div>
          <div style={{ fontSize:'1.3rem', fontWeight:700, color:'var(--text)', fontFamily:'var(--font-mono)' }}>{value}</div>
        </div>
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     PLANS TAB
  ═══════════════════════════════════════════════════════════ */
  function PlansTab() {
    const Icon = window.Icon;
    const paidPlans = PLAN_DATA.filter(p => p.price > 0);
    const totalMrr = paidPlans.reduce((s,p) => s + p.mrr, 0);
    return (
      <>
        <div className="grid" style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, marginBottom:16 }}>
          <div className="card">
            <div className="card-head">
              <h3 className="card-title">MRR contribution by plan</h3>
              <span className="tag" style={{ color:'var(--dim)' }}>${totalMrr.toLocaleString()}/mo</span>
            </div>
            <div className="card-body" style={{ display:'flex', alignItems:'center', gap:16, padding:16 }}>
              <PieChart
                data={paidPlans.map(p => ({ label: p.plan, value: p.mrr, color: p.color }))}
                donut
                centerLabel="Total MRR"
                centerValue={'$' + Math.round(totalMrr/1000) + 'k'}
                size={240}
              />
              <div style={{ flex:1, display:'flex', flexDirection:'column', gap:8 }}>
                {paidPlans.map(p => (
                  <div key={p.plan}>
                    <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:'.74rem', marginBottom:2 }}>
                      <span style={{ width:10, height:10, borderRadius:2, background:p.color }}/>
                      <span style={{ flex:1, color:'var(--text)', fontWeight:500 }}>{p.plan}</span>
                      <span style={{ color:'var(--dim)', fontFamily:'var(--font-mono)', fontSize:'.68rem' }}>${p.mrr.toLocaleString()}</span>
                    </div>
                    <div style={{ fontSize:'.6rem', color:'var(--dim)', paddingLeft:18 }}>{p.count} customers · ${p.price}/mo · {((p.mrr/totalMrr)*100).toFixed(1)}%</div>
                  </div>
                ))}
              </div>
            </div>
          </div>

          <div className="card">
            <div className="card-head"><h3 className="card-title">Customer count by plan</h3></div>
            <div className="card-body">
              <BarChart
                data={PLAN_DATA.map(p => ({ label: p.plan, value: p.count, color: p.color }))}
                formatY={v => v.toString()}
              />
            </div>
          </div>
        </div>

        {/* Unit economics table */}
        <div className="card" style={{ marginBottom:16 }}>
          <div className="card-head">
            <h3 className="card-title">Unit economics per plan · monthly</h3>
            <span className="tag" style={{ color:'var(--dim)' }}>ARPU − all costs = net margin</span>
          </div>
          <div className="card-body" style={{ padding:0 }}>
            <table className="data-table" style={{ width:'100%' }}>
              <thead>
                <tr>
                  <th>Plan</th><th style={{ textAlign:'right' }}>ARPU</th><th style={{ textAlign:'right' }}>Infra COGS</th>
                  <th style={{ textAlign:'right' }}>Stripe fee</th><th style={{ textAlign:'right' }}>Support alloc</th>
                  <th style={{ textAlign:'right' }}>AI COGS</th><th style={{ textAlign:'right' }}>Net margin</th>
                  <th style={{ textAlign:'right' }}>Margin %</th>
                </tr>
              </thead>
              <tbody>
                {UNIT_ECON.map(u => (
                  <tr key={u.plan}>
                    <td style={{ fontWeight:600 }}>{u.plan}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)' }}>${u.arpu}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--dim)' }}>−${u.cogs.toFixed(2)}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--dim)' }}>−${u.stripe.toFixed(2)}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--dim)' }}>−${u.support.toFixed(2)}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', color:'var(--dim)' }}>−${u.ai.toFixed(2)}</td>
                    <td style={{ textAlign:'right', fontFamily:'var(--font-mono)', fontWeight:700, color:'var(--mint)' }}>${u.margin.toFixed(2)}</td>
                    <td style={{ textAlign:'right' }}>
                      <span className="tag" style={{ color: u.marginPct > 0.75 ? 'var(--mint)' : 'var(--warn)' }}>{(u.marginPct*100).toFixed(1)}%</span>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>

        {/* Add-on attach rates */}
        <div className="card">
          <div className="card-head"><h3 className="card-title">Add-on attach rates · paid customers</h3></div>
          <div className="card-body" style={{ padding:16 }}>
            {ADD_ONS.map((a,i) => (
              <HBar key={i}
                label={a.name}
                value={a.volume}
                max={Math.max(...ADD_ONS.map(x => x.volume))}
                color={[CHART.beam, CHART.orange, CHART.mint][i]}
                subValue={`$${(a.volume * a.avgPrice).toLocaleString()}/mo revenue`}
                pct={a.attach}
              />
            ))}
          </div>
        </div>
      </>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     COGS TAB
  ═══════════════════════════════════════════════════════════ */
  function CogsTab({ currentMrr, monthlyInfra, infra }) {
    const Icon = window.Icon;
    const grossMargin = (currentMrr - monthlyInfra) / currentMrr;
    const infraList = infra || INFRA_DEFAULT;
    return (
      <>
        <div className="grid" style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, marginBottom:16 }}>
          <div className="card">
            <div className="card-head">
              <h3 className="card-title">Monthly infrastructure spend</h3>
              <span className="tag" style={{ color:'var(--warn)' }}>${monthlyInfra}/mo total</span>
            </div>
            <div className="card-body" style={{ display:'flex', alignItems:'center', gap:16, padding:16 }}>
              <PieChart
                data={infraList.map((item, i) => ({ label: item.name, value: item.cost, color: [CHART.beam, CHART.orange, CHART.mint, CHART.rose, CHART.warn, CHART.dim][i] }))}
                donut
                centerLabel="Infra/mo"
                centerValue={'$' + monthlyInfra}
                size={200}
              />
              <div style={{ flex:1, display:'flex', flexDirection:'column', gap:5 }}>
                {infraList.map((item, i) => (
                  <div key={i} style={{ display:'flex', alignItems:'center', gap:8, fontSize:'.7rem' }}>
                    <span style={{ width:10, height:10, borderRadius:2, background:[CHART.beam, CHART.orange, CHART.mint, CHART.rose, CHART.warn, CHART.dim][i] }}/>
                    <span style={{ flex:1, color:'var(--text)' }}>{item.name}</span>
                    <span style={{ color:'var(--dim)', fontFamily:'var(--font-mono)' }}>${item.cost}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>

          <div className="card">
            <div className="card-head">
              <h3 className="card-title">Gross margin summary</h3>
              <span className="tag" style={{ color: grossMargin > 0.85 ? 'var(--mint)' : 'var(--warn)' }}>{(grossMargin*100).toFixed(1)}%</span>
            </div>
            <div className="card-body" style={{ padding:16, display:'flex', flexDirection:'column', gap:12 }}>
              <StatRow label="Monthly revenue (MRR)" value={`$${currentMrr.toLocaleString()}`} color="var(--text)"/>
              <StatRow label="− Infrastructure"     value={`−$${monthlyInfra.toLocaleString()}`} color="var(--dim)"/>
              <StatRow label="− Stripe fees (2.9% + 30¢)" value={`−$${Math.round(currentMrr * 0.029 + PLAN_DATA.filter(p=>p.price>0).reduce((s,p)=>s+p.count,0)*0.30)}`} color="var(--dim)"/>
              <StatRow label="− Support allocation" value={`−$${1840}`} color="var(--dim)"/>
              <div style={{ borderTop:'1px solid var(--border)', paddingTop:10 }}>
                <StatRow label="Gross profit" value={`$${(currentMrr - monthlyInfra - Math.round(currentMrr * 0.029) - 1840).toLocaleString()}`} color="var(--mint)" bold/>
              </div>
            </div>
          </div>
        </div>

        {/* Per-scan COGS breakdown */}
        <div className="card" style={{ marginBottom:16 }}>
          <div className="card-head">
            <h3 className="card-title">Cost per scan · ${SCAN_COST_TOTAL.toFixed(3)} avg</h3>
            <span className="tag" style={{ color:'var(--dim)' }}>Break-even at 1,754 scans/mo covered by Starter plan</span>
          </div>
          <div className="card-body" style={{ padding:16 }}>
            {SCAN_COGS.map((s,i) => (
              <HBar key={i}
                label={s.item}
                value={s.cost}
                max={Math.max(...SCAN_COGS.map(x => x.cost))}
                color={[CHART.beam, CHART.orange, CHART.mint, CHART.warn, CHART.rose][i]}
                subValue={`$${s.cost.toFixed(3)}/scan`}
                pct={s.share}
              />
            ))}
          </div>
        </div>

        {/* Margin by plan bar chart */}
        <div className="card">
          <div className="card-head"><h3 className="card-title">Net margin % by plan</h3></div>
          <div className="card-body">
            <BarChart
              data={UNIT_ECON.map(u => ({ label: u.plan, value: u.marginPct * 100, color: u.marginPct > 0.75 ? CHART.mint : CHART.warn }))}
              formatY={v => v.toFixed(0) + '%'}
            />
          </div>
        </div>
      </>
    );
  }

  function StatRow({ label, value, color, bold }) {
    return (
      <div style={{ display:'flex', justifyContent:'space-between', fontSize: bold ? '.9rem' : '.78rem' }}>
        <span style={{ color:'var(--muted)', fontWeight: bold ? 600 : 400 }}>{label}</span>
        <span style={{ color, fontFamily:'var(--font-mono)', fontWeight: bold ? 700 : 500 }}>{value}</span>
      </div>
    );
  }

  /* ═══════════════════════════════════════════════════════════
     FUNNEL TAB
  ═══════════════════════════════════════════════════════════ */
  function FunnelTab() {
    const Icon = window.Icon;
    const topCount = FUNNEL[0].count;
    return (
      <>
        <div className="card" style={{ marginBottom:16 }}>
          <div className="card-head">
            <h3 className="card-title">Conversion funnel · last 30 days</h3>
            <span className="tag" style={{ color:'var(--mint)' }}>Visit → Paid: {((FUNNEL[FUNNEL.length-1].count / topCount) * 100).toFixed(2)}%</span>
          </div>
          <div className="card-body" style={{ padding:20 }}>
            {FUNNEL.map((f, i) => {
              const pct = f.count / topCount;
              const w = Math.max(8, pct * 100);
              const color = [CHART.beam, CHART.beam, CHART.mint, CHART.orange, CHART.orange, CHART.rose, CHART.mint][i];
              return (
                <div key={i} style={{ display:'grid', gridTemplateColumns:'200px 1fr 140px', gap:12, alignItems:'center', marginBottom:10 }}>
                  <div>
                    <div style={{ fontSize:'.76rem', color:'var(--text)', fontWeight:500 }}>{f.stage}</div>
                    {f.conv && <div style={{ fontSize:'.6rem', color:'var(--dim)' }}>↓ {(f.conv*100).toFixed(1)}% from prior</div>}
                  </div>
                  <div style={{ height:30, background:'var(--surface-2)', borderRadius:4, overflow:'hidden', position:'relative' }}>
                    <div style={{ position:'absolute', inset:0, width:`${w}%`, background: color, borderRadius:4, display:'flex', alignItems:'center', paddingLeft:10, fontSize:'.68rem', color:'var(--text)', fontWeight:600 }}>
                      {(pct*100).toFixed(1)}%
                    </div>
                  </div>
                  <div style={{ textAlign:'right', fontFamily:'var(--font-mono)', fontSize:'.82rem', fontWeight:600, color:'var(--text)' }}>
                    {f.count.toLocaleString()}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* Churn by plan */}
        <div className="grid" style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, marginBottom:16 }}>
          <div className="card">
            <div className="card-head"><h3 className="card-title">Churn rates by plan · trailing 6 months</h3></div>
            <div className="card-body" style={{ padding:16 }}>
              {CHURN.map((c,i) => (
                <div key={i} style={{ marginBottom:14 }}>
                  <div style={{ display:'flex', justifyContent:'space-between', fontSize:'.76rem', marginBottom:4 }}>
                    <span style={{ color:'var(--text)', fontWeight:600 }}>{c.plan}</span>
                    <span style={{ fontFamily:'var(--font-mono)', color: c.net < 0 ? 'var(--mint)' : (c.net > 0.03 ? 'var(--red)' : 'var(--warn)') }}>
                      Net: {c.net >= 0 ? '+' : ''}{(c.net*100).toFixed(1)}%
                    </span>
                  </div>
                  <div style={{ height:10, background:'var(--surface-2)', borderRadius:2, position:'relative', overflow:'hidden' }}>
                    <div style={{ position:'absolute', inset:0, width:`${(c.gross / 0.08)*100}%`, background: c.net < 0 ? CHART.mint : (c.gross > 0.05 ? CHART.red : CHART.warn), borderRadius:2 }}/>
                  </div>
                  <div style={{ display:'flex', justifyContent:'space-between', fontSize:'.6rem', color:'var(--dim)', marginTop:2 }}>
                    <span>Gross: {(c.gross*100).toFixed(1)}%</span>
                    <span>{c.net < 0 ? '✓ Net negative (expansion > churn)' : c.gross > 0.05 ? '⚠ Above target (5%)' : 'On target'}</span>
                  </div>
                </div>
              ))}
            </div>
          </div>

          <div className="card">
            <div className="card-head"><h3 className="card-title">Key funnel insights</h3></div>
            <div className="card-body" style={{ padding:0 }}>
              {[
                { icon:'check', text:'Scan completion rate (89.7%) is best-in-class', color: CHART.mint },
                { icon:'warn',  text:'Estimator-open rate (45.8%) is biggest drop — test auto-open on scan-complete', color: CHART.warn },
                { icon:'trend', text:'Upgrade modal → checkout (40.5%) improved 6pp after trust badge added', color: CHART.beam },
                { icon:'spark', text:'Checkout → paid (71.7%) above SaaS benchmark (65%)', color: CHART.mint },
                { icon:'x',     text:'Landing → free scan (12.7%) below target — retest homepage copy', color: CHART.red },
              ].map((e,i) => (
                <div key={i} style={{ display:'flex', gap:10, padding:'10px 16px', borderBottom: i < 4 ? '1px solid var(--border)' : 'none', alignItems:'flex-start' }}>
                  <div style={{ width:22, height:22, borderRadius:4, background: e.color + '22', color: e.color, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 }}>
                    <Icon name={e.icon} size={12}/>
                  </div>
                  <div style={{ flex:1, fontSize:'.74rem', color:'var(--text)', lineHeight:1.5 }}>{e.text}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </>
    );
  }

  window.BusinessMetrics = BusinessMetrics;
})();
