// Security & IT Executive Dashboard — v2 components
const { useState, useMemo, useEffect, createContext, useContext } = React;

/* =========================================================
   API DATA LAYER
   Fetches live data from the security-dashboard worker API
   and maps response shapes to component data format.
   Falls back to static mock data when API is unavailable.
   ========================================================= */

// Configure via query param: ?api=https://security-dashboard.shad-5a7.workers.dev&token=YOUR_TOKEN
// Or set window.DASHBOARD_API before loading this script.
const API_CONFIG = (() => {
  const params = new URLSearchParams(window.location.search);
  return {
    baseUrl: params.get('api') || window.DASHBOARD_API || null,
    token: params.get('token') || window.DASHBOARD_TOKEN || null,
  };
})();

const DashboardDataContext = createContext(null);

function useDashboardData() {
  return useContext(DashboardDataContext);
}

async function fetchDashboardData() {
  if (!API_CONFIG.baseUrl) return null;
  const headers = {};
  const url = new URL('/dashboard', API_CONFIG.baseUrl);
  if (API_CONFIG.token) url.searchParams.set('token', API_CONFIG.token);

  // Fetch all 4 pillar APIs in parallel
  const endpoints = ['impact', 'revenue', 'exposure', 'efficiency'];
  const fetches = endpoints.map(ep => {
    const u = new URL(`/api/${ep}`, API_CONFIG.baseUrl);
    if (API_CONFIG.token) u.searchParams.set('token', API_CONFIG.token);
    return fetch(u.toString(), { headers }).then(r => r.ok ? r.json() : null).catch(() => null);
  });
  const [impact, revenue, exposure, efficiency] = await Promise.all(fetches);
  return { impact, revenue, exposure, efficiency };
}

/** Map worker /api/impact → IMPACT component shape */
function mapImpact(api) {
  if (!api?.impact?.headlines) return null;
  const find = (label) => api.impact.headlines.find(h => h.label?.toLowerCase().includes(label));
  const pipeline = find('arr') || find('pipeline') || find('revenue');
  const compliance = find('compliance');
  const exposure = find('exposure');
  const soc = find('automation') || find('soc') || find('assessment');
  const mapOne = (h, defaults) => {
    if (!h) return defaults;
    const numVal = parseFloat(String(h.value).replace(/[^0-9.-]/g, ''));
    const isPercent = String(h.value).includes('%');
    const isCurrency = String(h.value).includes('$');
    const isMillions = String(h.value).toLowerCase().includes('m') && isCurrency;
    return {
      label: h.label,
      value: isMillions ? numVal : isPercent ? numVal : numVal,
      unit: isPercent ? '%' : isMillions ? 'M' : '',
      prefix: isCurrency ? '$' : '',
      delta: defaults.delta,
      deltaDir: defaults.deltaDir,
      sub: h.detail || defaults.sub,
      source: defaults.source,
      spark: defaults.spark,
    };
  };
  return {
    aroPipeline: mapOne(pipeline, IMPACT_DEFAULTS.aroPipeline),
    complianceHealth: mapOne(compliance, IMPACT_DEFAULTS.complianceHealth),
    exposureAvoided: mapOne(exposure, IMPACT_DEFAULTS.exposureAvoided),
    socAutomation: mapOne(soc, IMPACT_DEFAULTS.socAutomation),
  };
}

/** Map worker /api/revenue → FRAMEWORKS component shape */
function mapFrameworks(api) {
  if (!api?.revenue?.byFramework) return null;
  const fw = api.revenue.byFramework;
  return Object.entries(fw).map(([name, data]) => ({
    name,
    pct: Math.round((data.healthScore || 0) * 100),
    controls: `${data.passingControls || 0}/${data.totalControls || 0}`,
    target: name.includes('SOC') ? 95 : name.includes('ISO') ? 90 : 85,
    gaps: data.failingControls || 0,
    source: name.includes('SOC') ? 'Vanta' : 'CCF Sheet',
    status: Math.round((data.healthScore || 0) * 100) >= 90 ? 'ok' : 'warn',
  }));
}

/** Map worker /api/revenue → PIPELINE component shape */
function mapPipeline(api) {
  if (!api?.revenue?.pipeline?.topAccountsByGate) return null;
  const p = api.revenue.pipeline;
  const deals = [];
  const gates = p.topAccountsByGate || {};
  Object.entries(gates).forEach(([gate, accounts]) => {
    (accounts || []).forEach(acct => {
      deals.push({
        name: acct.name,
        seats: gate,
        value: acct.arr >= 1000000 ? `$${(acct.arr / 1000000).toFixed(1)}M` : `$${Math.round(acct.arr / 1000)}K`,
        stage: 2,
        stages: ['Qualify', 'Evidence', 'Review', 'Attested'],
        current: 'Evidence',
        eta: '—',
        owner: '—',
        frameworks: [gate],
        risk: 'Med',
        blocker: '—',
      });
    });
  });
  return deals.length > 0 ? deals : null;
}

/** Map worker /api/exposure → EXPOSURE component shape */
function mapExposure(api) {
  if (!api?.exposure?.namedScenarios?.length) return null;
  return api.exposure.namedScenarios.map(s => ({
    name: s.name,
    desc: s.description,
    inherent: (s.grossExposure || 0) / 1000000,
    mitigated: (s.mitigationDiscount || 0) / 1000000,
    transferred: (s.insuranceCoverage || 0) / 1000000,
    residual: (s.residualExposure || 0) / 1000000,
    source: 'FAIR model',
  }));
}

/** Map worker /api/efficiency → RESPONSE component shape */
function mapResponse(api) {
  if (!api?.efficiency) return null;
  const e = api.efficiency;
  const mttd = e.mttd?.value;
  const mttt = e.mttt?.value;
  const mttr = e.mttr?.caseMttrMinutes;
  return [
    { k: 'MTTA', v: mttd != null ? Math.round(mttd * 10) / 10 : 9.4, unit: 'min', desc: 'Mean time to acknowledge', target: '< 15 min', ok: mttd != null ? mttd < 15 : true, source: 'Datadog Cases' },
    { k: 'MTTT', v: mttt != null ? Math.round(mttt / 60 * 10) / 10 : 2.3, unit: 'hrs', desc: 'Mean time to triage', target: '< 4 hrs', ok: mttt != null ? mttt < 240 : true, source: 'Linear GraphQL' },
    { k: 'MTTR', v: mttd != null ? Math.round(mttd * 10) / 10 : 9.9, unit: 'min', desc: 'Mean time to detect', target: '< 30 min', ok: mttd != null ? mttd < 30 : true, source: 'Datadog Signals' },
  ];
}

/** Map worker /api/efficiency → SAVINGS component shape */
function mapSavings(api) {
  if (!api?.efficiency?.savings?.savingsByInitiative) return null;
  return api.efficiency.savings.savingsByInitiative.map(s => ({
    name: s.name,
    val: Math.round((s.amount || 0) / 1000),
    money: `$${Math.round((s.amount || 0) / 1000)}K`,
    hrs: `${(s.hoursSaved || 0).toLocaleString()} hrs`,
    source: s.id || 'Worker',
  }));
}

/* =========================================================
   STATIC MOCK DATA (fallback when API unavailable)
   All data keyed to the actual worker endpoints so the UI
   acts as a faithful mock of the live dashboard.
   Source badges reference the aggregator that would
   populate each metric.
   ========================================================= */

// Used as fallback defaults for API mapping
const IMPACT_DEFAULTS = {
  aroPipeline: { delta: '+24% QoQ', deltaDir: 'up', sub: '', source: 'SFDC', spark: [9.2,10.4,11.8,12.1,13.4,14.2,15.1,15.8,16.2,16.8,17.4] },
  complianceHealth: { delta: 'flat', deltaDir: 'flat', sub: '', source: 'Vanta', spark: [89,89,87,87,86,86,86,87,88,87,87,82,86,72,55,86,85,85,84,87,85,85,85,86] },
  exposureAvoided: { delta: '65% reduced', deltaDir: 'up', sub: '', source: 'FAIR', spark: [3.6,3.7,3.8,3.9,4.0,4.0,4.1,4.1,4.2,4.2,4.3,4.3] },
  socAutomation: { delta: 'flat', deltaDir: 'flat', sub: '', source: 'Datadog', spark: [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100] },
};

// Program Impact — GET /api/impact (real data as of 2026-04-20)
const IMPACT = {
  aroPipeline: {
    label: 'Pipeline Gated on Security',
    value: 17.4, unit: 'M', prefix: '$',
    delta: '+24% QoQ', deltaDir: 'up',
    sub: '<b>$17.4M</b> pipeline gated on security compliance · <b>35</b> enterprise deals across 7 frameworks',
    source: 'SFDC › Coefficient › Sheets',
    spark: [9.2, 10.4, 11.8, 12.1, 13.4, 14.2, 15.1, 15.8, 16.2, 16.8, 17.4],
  },
  complianceHealth: {
    label: 'Compliance Health',
    value: 86, unit: '%',
    delta: 'flat', deltaDir: 'flat',
    sub: '<b>150/175</b> controls passing across <b>SOC 2, ISO 27001, PCI DSS</b> · 25 gaps',
    source: 'Vanta › /v1/controls',
    spark: [89, 89, 87, 87, 86, 86, 86, 87, 88, 87, 87, 82, 86, 72, 55, 86, 85, 85, 84, 87, 85, 85, 85, 86],
  },
  exposureAvoided: {
    label: 'Exposure Mitigated',
    value: 4.27, unit: 'M', prefix: '$',
    delta: '65% reduced', deltaDir: 'up',
    sub: 'Controls + insurance reduce <b>$6.6M inherent</b> to <b>$2.3M residual</b> · 7 scenarios grounded in Vanta risk register',
    source: 'FAIR · Vanta risks',
    spark: [3.6, 3.7, 3.8, 3.9, 4.0, 4.0, 4.1, 4.1, 4.2, 4.2, 4.3, 4.3],
  },
  socAutomation: {
    label: 'SOC AI Assessment Rate',
    value: 100, unit: '%',
    delta: 'flat', deltaDir: 'flat',
    sub: '<b>120</b> Datadog signals auto-triaged · <b>0</b> escalations to analyst · 100% assessment rate',
    source: 'Datadog › Signals + KV',
    spark: [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
  },
};

// Revenue Protection — GET /api/revenue (real data as of 2026-04-20)
const FRAMEWORKS = [
  { name: 'SOC 2',     pct: 86, controls: '150/175', target: 95, gaps: 25, source: 'Vanta', status: 'warn' },
  { name: 'ISO 27001', pct: 87, controls: '112/129', target: 90, gaps: 17, source: 'CCF Sheet', status: 'warn' },
  { name: 'PCI DSS',   pct: 84, controls: '117/140', target: 85, gaps: 23, source: 'CCF Sheet', status: 'warn' },
];

// Pipeline — real accounts from SFDC via Coefficient (2026-04-20)
const PIPELINE = [
  { name: 'Royal Bank of Canada (RBC)', seats: 'Banking', value: '$2.0M', stage: 1, stages: ['Qualify','Evidence','Review','Attested'], current: 'Demo', eta: '—', owner: 'Sales', frameworks: ['SOC 2'], risk: 'Med', blocker: 'SOC 2 attestation required' },
  { name: 'National Bank of Canada', seats: 'Banking', value: '$1.5M', stage: 2, stages: ['Qualify','Evidence','Review','Attested'], current: 'Testing', eta: '—', owner: 'Sales', frameworks: ['SOC 2'], risk: 'Low', blocker: 'In testing phase' },
  { name: 'Experian', seats: 'Financial Services', value: '$1.5M', stage: 2, stages: ['Qualify','Evidence','Review','Attested'], current: 'Testing', eta: '—', owner: 'Sales', frameworks: ['SOC 2'], risk: 'Low', blocker: 'In testing phase' },
  { name: 'BMO', seats: 'Banking', value: '$1.0M', stage: 2, stages: ['Qualify','Evidence','Review','Attested'], current: 'Proposal', eta: '—', owner: 'Sales', frameworks: ['SOC 2', 'PCI', 'BC/DR Plan'], risk: 'Med', blocker: 'Multi-framework requirement' },
  { name: 'Sardine', seats: 'Fintech', value: '$600K', stage: 3, stages: ['Qualify','Evidence','Review','Attested'], current: 'Negotiation', eta: '—', owner: 'Sales', frameworks: ['SOC 2'], risk: 'Low', blocker: 'In negotiation' },
  { name: 'FINBOA', seats: 'Fintech', value: '$50K', stage: 2, stages: ['Qualify','Evidence','Review','Attested'], current: 'Testing', eta: '—', owner: 'Sales', frameworks: ['BC/DR Plan'], risk: 'Low', blocker: 'BC/DR plan requirement' },
  { name: 'Unify', seats: 'Fintech', value: '$50K', stage: 1, stages: ['Qualify','Evidence','Review','Attested'], current: 'Demo', eta: '—', owner: 'Sales', frameworks: ['BC/DR Plan'], risk: 'Low', blocker: 'BC/DR plan requirement' },
];

// Financial Exposure — FAIR scenarios grounded in Vanta risk register + live operational data
//
// Vanta risk register: 37 active scenarios, 17/18 NIST CSF categories covered
// Scenarios below map to documented risk categories with mitigations derived from:
//   - Vanta: 150/175 controls passing (86%), 100% treatment rate
//   - Vendors: 83 managed, 78% reviewed, 1 critical unreviewed
//   - Vulns: 2 critical reachable, 34 high (220 total Vanta)
//   - SOC: 100% auto-triage, 9.4 min MTTD
//   - Insurance: $5M aggregate, $10K retention, $1M PCI/BI/extortion sublimits
//
// Base SLE: $2.98M (IBM 2025 small-company median)
// Insurance payout assumption: 60-75% (conservative, not 100%)
const EXPOSURE = [
  // Vanta categories: Incident Response, Recovery Planning, Business Environment, System Integrity
  // 37 Vanta scenarios include BC/DR, ransomware, and outage risks
  // Mitigation: 100% SOC triage, 9.4 min MTTD, IR plan tested (Q1 tabletop), DR plan documented
  // Gap: No 24/7 SOC yet (Q3 roadmap), single-person response capacity
  { name: 'Ransomware / Business Disruption',
    desc: 'Encryption, 72-hr outage, extortion — IR plan tested but no 24/7 SOC yet',
    inherent: 1.80, mitigated: 0.72, transferred: 0.54, residual: 0.54, source: 'Vanta IR · SOC worker' },

  // Vanta categories: Access Control, Identity Management
  // Mitigations: MFA enforced (Okta), quarterly access reviews, RBAC in progress
  // Gap: RBAC rollout partial (Identity & Access project at 45%), 18 unreviewed vendor accounts
  { name: 'Identity Compromise / Credential Theft',
    desc: 'Privilege escalation via stolen creds — MFA enforced, RBAC 45% rolled out',
    inherent: 1.20, mitigated: 0.58, transferred: 0.31, residual: 0.31, source: 'Vanta access · Okta' },

  // Vanta categories: Supply Chain Risk
  // Mitigations: 83 vendors managed in Vanta, 65 reviewed (78%), DPAs in place
  // Gap: 18 unreviewed vendors (1 critical), vendor monitoring cadence not yet automated (Q3)
  { name: 'Vendor / Supply Chain Breach',
    desc: '83 vendors managed, 78% reviewed — 1 critical unreviewed, monitoring manual',
    inherent: 0.90, mitigated: 0.27, transferred: 0.27, residual: 0.36, source: 'Vanta vendors · 83 managed' },

  // Vanta categories: Software Security, Vulnerability Management
  // Mitigations: SAST in CI, container scanning, vuln worker (56% auto-resolved)
  // Gap: 2 critical reachable + 34 high vulns, DAST not yet deployed, 23 vulns need human fix
  { name: 'Application Vulnerability Exploitation',
    desc: '2 critical reachable CVEs, 34 high — SAST/container scanning active, no DAST yet',
    inherent: 0.85, mitigated: 0.30, transferred: 0.22, residual: 0.33, source: 'Vuln worker · 220 total' },

  // Vanta categories: Data Security, Information Protection, Personnel Security
  // Mitigations: Access reviews, DLP partial, security awareness training
  // Gap: No DLP tooling beyond access controls, GenAI data-loss detection in scoping (Q3)
  { name: 'Data Exfiltration / Insider Threat',
    desc: 'No DLP tooling yet — access reviews + awareness training only, GenAI risk unmonitored',
    inherent: 0.75, mitigated: 0.19, transferred: 0.19, residual: 0.37, source: 'Vanta data sec · reviews' },

  // Vanta categories: Risk Assessment (SOC 2/PCI/GDPR controls)
  // Mitigations: 86% control health, automated evidence (166 tests, 86% pass), continuous Vanta monitoring
  // Gap: 25 failing controls, PCI formal assessment not started, GDPR readiness Q3
  { name: 'Regulatory Non-Compliance',
    desc: '86% control health, 25 gaps — PCI assessment pending, GDPR readiness Q3',
    inherent: 0.65, mitigated: 0.33, transferred: 0.06, residual: 0.26, source: 'Vanta · 150/175 controls' },

  // Vanta categories: Network Security, Maintenance
  // Mitigations: AWS security groups audited, Tailscale zero-trust, Cloudflare WAF
  // Gap: NACL audit findings, no network segmentation project until Q3
  { name: 'Infrastructure / Cloud Misconfiguration',
    desc: 'AWS audit findings, no network segmentation yet — Cloudflare WAF + Tailscale active',
    inherent: 0.45, mitigated: 0.18, transferred: 0.11, residual: 0.16, source: 'AWS audit · Vanta infra' },
];

// Operational Efficiency — GET /api/efficiency (real data as of 2026-04-20)
const RESPONSE = [
  { k: 'MTTD', v: 9.4, unit: 'min', desc: 'Mean time to detect', target: '< 15 min', ok: true,  source: 'Datadog Signals' },
  { k: 'MTTT', v: 9.9, unit: 'min', desc: 'Mean time to triage', target: '< 30 min', ok: true,  source: 'Datadog Cases' },
  { k: 'MTTR', v: 96, unit: 'min', desc: 'Mean time to resolve (cases)', target: '< 240 min', ok: true,  source: 'Datadog Cases' },
];

// Savings — real data from compute/cost-efficiency.js (2026-04-20)
const SAVINGS = [
  { name: 'Evidence Automation',       val: 75, money: '$75K', hrs: '332 hrs', source: 'Vanta automated tests' },
  { name: 'SOC Triage Automation',     val: 37, money: '$37K', hrs: '165 hrs', source: 'Datadog › PROCESSED_SIGNALS' },
  { name: 'Vuln Reachability Analysis', val: 20, money: '$20K', hrs: '87 hrs',  source: 'Vuln worker /stats' },
];

/* =========================================================
   PRIMITIVES
   ========================================================= */

function Spark({ data, color, height = 32, fill = true }) {
  const w = 280, h = height;
  const c = color || 'var(--accent-strong)';
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const pts = data.map((d, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((d - min) / range) * (h - 6) - 3;
    return [x, y];
  });
  const path = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const area = path + ` L${w},${h} L0,${h} Z`;
  const last = pts[pts.length - 1];
  const gid = 'sg-' + Math.random().toString(36).slice(2, 7);
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ display: 'block', overflow: 'visible' }}>
      <defs>
        <linearGradient id={gid} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor={c} stopOpacity="0.25" />
          <stop offset="1" stopColor={c} stopOpacity="0" />
        </linearGradient>
      </defs>
      {fill && <path d={area} fill={`url(#${gid})`} />}
      <path d={path} fill="none" stroke={c} strokeWidth="1.75" strokeLinejoin="round" strokeLinecap="round" />
      <circle cx={last[0]} cy={last[1]} r="3" fill={c} />
    </svg>
  );
}

function SourceBadge({ children }) {
  return <span className="source" title={`Data source: ${children}`}>{children}</span>;
}

function Delta({ text, dir = 'up' }) {
  const arrow = dir === 'up' ? '↑' : dir === 'down' ? '↓' : '→';
  const cls = dir === 'flat' ? 'flat' : (dir === 'down' ? 'neg' : '');
  return <span className={`delta ${cls}`}>{arrow} {text}</span>;
}

/* =========================================================
   NAVIGATION + CHROME
   ========================================================= */

function Sidebar({ activeNav, onNav, collapsed, onToggle }) {
  const items = [
    { k: 'dashboard', label: 'Executive Overview', count: null, icon: <g><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></g> },
    { k: 'trends', label: 'Security Trends', count: null, icon: <polyline points="3 17 9 11 13 15 21 7"/> },
  ];
  const pillars = [
    { k: 'impact',     label: 'Program Impact',         count: '4', icon: <g><circle cx="12" cy="12" r="3"/><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1"/></g> },
    { k: 'revenue',    label: 'Revenue Protection',     count: '7', icon: <g><path d="M3 12l4 4 14-14"/></g> },
    { k: 'exposure',   label: 'Financial Exposure',     count: '4', icon: <g><path d="M12 2l9 4v6c0 5-3.5 9-9 10-5.5-1-9-5-9-10V6l9-4z"/></g> },
    { k: 'efficiency', label: 'Operational Efficiency', count: null, icon: <g><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></g> },
    { k: 'initiatives',label: 'Roadmap',                count: '14', icon: <g><path d="M3 6h18M3 12h18M3 18h12"/></g> },
  ];
  const admin = [
    { k: 'sources', label: 'Data Sources', count: '9', icon: <g><rect x="3" y="3" width="18" height="4" rx="1"/><rect x="3" y="10" width="18" height="4" rx="1"/><rect x="3" y="17" width="18" height="4" rx="1"/></g> },
    { k: 'logs',    label: 'Audit Trail', count: null, icon: <g><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6"/></g> },
  ];
  const NavItem = ({ it }) => (
    <a href="#" className={activeNav === it.k ? 'active' : ''} onClick={e => { e.preventDefault(); onNav(it.k); }} title={collapsed ? it.label : undefined}>
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round">{it.icon}</svg>
      {!collapsed && <span>{it.label}</span>}
      {!collapsed && it.count && <span className="count">{it.count}</span>}
    </a>
  );
  return (
    <aside className={`sidebar ${collapsed ? 'collapsed' : ''}`}>
      <div className="brand-row">
        <img src="assets/spade-logo.png" alt="Spade" className="brand-logo" />
        {!collapsed && <div className="brand-word">Spade</div>}
        <button className="sidebar-toggle" onClick={onToggle} title={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}>
          <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            {collapsed
              ? <polyline points="9 18 15 12 9 6" />
              : <polyline points="15 18 9 12 15 6" />}
          </svg>
        </button>
      </div>
      {!collapsed && <div className="brand-tagline">Security & IT Platform</div>}
      <nav className="nav">
        {items.map(it => <NavItem key={it.k} it={it} />)}
        {!collapsed && <div className="nav-section">Filter by pillar</div>}
        {pillars.map(it => <NavItem key={it.k} it={it} />)}
        {!collapsed && <div className="nav-section">System</div>}
        {admin.map(it => <NavItem key={it.k} it={it} />)}
      </nav>
      {!collapsed && (
        <div className="sidebar-foot">
          <div className="avatar">SR</div>
          <div>
            <div style={{ color: 'var(--fg-strong)', fontWeight: 500, fontSize: 13 }}>Shadman Rahman</div>
            <div style={{ fontSize: 11 }}>Security Lead</div>
          </div>
        </div>
      )}
      {collapsed && (
        <div className="sidebar-foot" style={{ justifyContent: 'center' }}>
          <div className="avatar">SR</div>
        </div>
      )}
    </aside>
  );
}

function Topbar({ period, onPeriod, onGoTrends, breadcrumb }) {
  return (
    <div className="topbar">
      <div className="topbar-left">
        <div className="breadcrumb">
          <span>Security</span>
          <span className="sep">/</span>
          <span className="cur">{breadcrumb || 'Executive Overview'}</span>
        </div>
      </div>
      <div className="topbar-right">
        <div className="period-switch">
          {['7D', '30D', 'QTD', 'YTD'].map(p => (
            <button key={p} className={period === p ? 'active' : ''} onClick={() => onPeriod(p)}>{p}</button>
          ))}
        </div>
        <div className="live-pill">Live · refreshed <b style={{ color: 'var(--fg)', fontWeight: 500, marginLeft: 3 }}>4m ago</b></div>
        <button className="btn" onClick={onGoTrends}>
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="3 17 9 11 13 15 21 7"/></svg>
          Trends
        </button>
        <button className="btn primary">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 5v14M5 12l7 7 7-7"/></svg>
          Export
        </button>
      </div>
    </div>
  );
}

/* =========================================================
   PROGRAM IMPACT (Hero)
   ========================================================= */

function HeroCard({ metric, primary = false }) {
  const dir = metric.deltaDir;
  return (
    <div className={`card hero-card ${primary ? 'primary' : ''}`}>
      <div className="hero-row-top">
        <span className="caps">{metric.label}</span>
        <SourceBadge>{metric.source}</SourceBadge>
      </div>
      <div className={`hero-value ${!primary ? 'md' : ''}`}>
        {metric.prefix}{metric.value}
        <span className="unit">{metric.unit}</span>
        <Delta text={metric.delta} dir={dir} />
      </div>
      <div className="hero-sub" dangerouslySetInnerHTML={{ __html: metric.sub }} />
      <div className="hero-spark">
        <Spark data={metric.spark} color={primary ? 'var(--accent)' : 'var(--accent-strong)'} />
      </div>
    </div>
  );
}

function ProgramImpact() {
  const apiData = useDashboardData();
  const impact = (apiData && mapImpact(apiData)) || IMPACT;
  return (
    <div className="section">
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">01</span>
          <h2>Program Impact</h2>
          <span className="note">Four numbers the board asked for</span>
        </div>
        <div className="section-actions">
          <span className="chip ok"><span className="dot"></span>Program on track</span>
          <span className="chip warn"><span className="dot"></span>2 items for board</span>
        </div>
      </div>
      <div className="hero-grid">
        <HeroCard metric={impact.aroPipeline} primary />
        <HeroCard metric={impact.complianceHealth} />
        <HeroCard metric={impact.exposureAvoided} />
        <HeroCard metric={impact.socAutomation} />
      </div>
    </div>
  );
}

/* =========================================================
   REVENUE PROTECTION
   ========================================================= */

function RevenueProtection() {
  const [open, setOpen] = useState(null);
  const apiData = useDashboardData();
  const frameworks = (apiData && mapFrameworks(apiData)) || FRAMEWORKS;
  const pipeline = (apiData && mapPipeline(apiData)) || PIPELINE;
  const pipelineTotal = pipeline.reduce((s, p) => {
    const v = parseFloat(p.value.replace(/[^0-9.]/g, ''));
    return s + (p.value.includes('K') ? v * 0.001 : v);
  }, 0);

  return (
    <div className="section">
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">02</span>
          <h2>Revenue Protection & Enablement</h2>
          <span className="note">Compliance posture translated into revenue</span>
        </div>
        <div className="section-actions">
          <SourceBadge>Vanta · CCF · SFDC</SourceBadge>
        </div>
      </div>

      <div className="kpi-row" style={{ marginBottom: 16 }}>
        <div className="card kpi">
          <div className="hero-row-top">
            <span className="caps">Pipeline Gated on Security</span>
            <SourceBadge>SFDC</SourceBadge>
          </div>
          <div className="kpi-value" style={{ color: 'var(--accent-strong)' }}>
            ${pipelineTotal.toFixed(1)}<span className="unit">M</span>
          </div>
          <div className="kpi-sub">
            <b>35 gated deals</b> requiring attestations across <b>7 frameworks</b>
          </div>
        </div>
        <div className="card kpi">
          <div className="hero-row-top">
            <span className="caps">ARR Under Compliance SLAs</span>
            <SourceBadge>SFDC</SourceBadge>
          </div>
          <div className="kpi-value">$5.5<span className="unit">M</span></div>
          <div className="kpi-sub">
            <b>42 active accounts</b> · compliance renewal rate <b>96%</b> · zero compliance churn YTD
          </div>
        </div>
        <div className="card kpi">
          <div className="hero-row-top">
            <span className="caps">Framework Weighted Health</span>
            <SourceBadge>Vanta · CCF</SourceBadge>
          </div>
          <div className="kpi-value">86<span className="unit">%</span></div>
          <div className="kpi-sub">
            150/175 controls passing · <b>25 open gaps</b> across SOC 2, ISO, PCI
          </div>
        </div>
      </div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="card-head">
          <div>
            <div className="card-title">Compliance by Framework</div>
            <div className="card-sub">Target lines show agreement-level commitments · 176 controls checked daily</div>
          </div>
          <SourceBadge>Vanta /v1/controls · 6min refresh</SourceBadge>
        </div>
        <div className="card-pad">
          {frameworks.map(f => (
            <div key={f.name} className="fw-row">
              <div className="fw-name">
                {f.name}
                <span className="badge">{f.source}</span>
              </div>
              <div className="fw-bar">
                <div className={`fw-fill ${f.status === 'warn' ? 'warn' : ''}`} style={{ width: `${f.pct}%` }} />
                <div className="fw-target" style={{ left: `${f.target}%` }} />
              </div>
              <div className="fw-pct">{f.pct}%</div>
              <div className="fw-meta">{f.controls} · {f.gaps} gaps</div>
            </div>
          ))}
        </div>
        <div className="bm">
          <span className="tag">Benchmark</span>
          <span>Peer median for SaaS: <b>SOC 2 89%</b> · <b>ISO 27001 82%</b> · <b>PCI 78%</b></span>
          <span style={{ marginLeft: 'auto' }}>Drata State of Trust, 2025</span>
        </div>
      </div>

      <div className="card">
        <div className="card-head">
          <div>
            <div className="card-title">Deals Gated on Framework Attestation</div>
            <div className="card-sub">Click a row for deal dependency + blocker detail</div>
          </div>
          <SourceBadge>SFDC › Coefficient › Pipeline tab</SourceBadge>
        </div>
        {pipeline.map((p, i) => (
          <React.Fragment key={p.name}>
            <div className={`pipe-row ${open === i ? 'open' : ''}`} onClick={() => setOpen(open === i ? null : i)}>
              <div className="pipe-chev">›</div>
              <div className="pipe-name">
                {p.name}
                <span className="seats">{p.seats}</span>
              </div>
              <div className="pipe-value">{p.value}</div>
              <div>
                <div className="pipe-stages">
                  {p.stages.map((_, s) => (
                    <div key={s} className={`pipe-stage ${s < p.stage ? 'done' : s === p.stage ? 'current' : ''}`} />
                  ))}
                </div>
                <div className="pipe-stage-label">{p.current}</div>
              </div>
              <div className="pipe-eta">{p.eta}</div>
              <div>
                <span className={`pipe-risk ${p.risk.toLowerCase()}`}>{p.risk}</span>
              </div>
            </div>
            {open === i && (
              <div className="pipe-detail">
                <div><div className="k">Account Owner</div><div className="v">{p.owner}</div></div>
                <div><div className="k">Frameworks Required</div><div className="v">{p.frameworks.join(' · ')}</div></div>
                <div><div className="k">Blocker</div><div className="v">{p.blocker}</div></div>
                <div><div className="k">Value Lost if Slip</div><div className="v" style={{ color: 'var(--neg)' }}>{p.value}</div></div>
              </div>
            )}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

/* =========================================================
   FINANCIAL EXPOSURE
   ========================================================= */

function FinancialExposure() {
  const apiData = useDashboardData();
  const exposure = (apiData && mapExposure(apiData)) || EXPOSURE;
  const totals = exposure.reduce((a, e) => ({
    inherent: a.inherent + e.inherent,
    mitigated: a.mitigated + e.mitigated,
    transferred: a.transferred + e.transferred,
    residual: a.residual + e.residual,
  }), { inherent: 0, mitigated: 0, transferred: 0, residual: 0 });

  const reduction = totals.inherent > 0 ? ((1 - totals.residual / totals.inherent) * 100) : 0;
  const maxInh = Math.max(...exposure.map(e => e.inherent));

  const waterfall = [
    { k: 'Inherent ALE', v: totals.inherent, color: 'var(--clay)', isEnd: false },
    { k: 'Mitigated', v: -totals.mitigated, color: 'var(--green-400)', isEnd: false },
    { k: 'Transferred', v: -totals.transferred, color: 'var(--lagoon)', isEnd: false },
    { k: 'Residual', v: totals.residual, color: 'var(--accent-strong)', isEnd: true },
  ];
  const wfMax = totals.inherent;

  return (
    <div className="section">
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">03</span>
          <h2>Financial Exposure Protection</h2>
          <span className="note">FAIR-based cyber risk quantification</span>
        </div>
        <div className="section-actions">
          <span className="chip warn"><span className="dot"></span>Residual above $1.5M tolerance</span>
          <SourceBadge>FAIR · Vanta risk scenarios</SourceBadge>
        </div>
      </div>

      <div className="exp-summary" style={{ marginBottom: 16 }}>
        <div className="exp-sum-cell">
          <span className="caps">Inherent Annualized Loss</span>
          <div className="exp-sum-v inherent">${totals.inherent.toFixed(1)}<span className="unit">M</span></div>
          <div className="exp-sum-s">Before controls · <b>IBM 2025 small-co median</b> ($2.98M) · 7 scenarios from Vanta register</div>
        </div>
        <div className="exp-sum-cell">
          <span className="caps">Controls + Insurance Reduction</span>
          <div className="exp-sum-v reduced">−${(totals.mitigated + totals.transferred).toFixed(1)}<span className="unit">M</span></div>
          <div className="exp-sum-s"><b>{reduction.toFixed(0)}% reduction</b> · cyber insurance <b>$5M aggregate</b>, $10K retention · conservative payout</div>
        </div>
        <div className="exp-sum-cell">
          <span className="caps">Residual Risk</span>
          <div className="exp-sum-v residual">${totals.residual.toFixed(1)}<span className="unit">M</span></div>
          <div className="exp-sum-s">Board tolerance <b>$1.5M</b> · {totals.residual <= 1.5 ? <b style={{color:'var(--pos)'}}>within tolerance</b> : <b style={{color:'var(--neg)'}}>exceeds tolerance</b>} · reviewed quarterly</div>
        </div>
      </div>

      <div className="grid-exp">
        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Exposure by Risk Scenario</div>
              <div className="card-sub">Annualized Loss Expectancy ($M) · modeled via FAIR</div>
            </div>
            <SourceBadge>compute/fair-assessment.js</SourceBadge>
          </div>
          <div className="exp-table-head">
            <div>Scenario</div>
            <div>Inherent</div>
            <div>Mitigated</div>
            <div>Transferred</div>
            <div>Residual</div>
            <div>Reduction</div>
          </div>
          {exposure.map(e => {
            const red = e.inherent > 0 ? ((1 - e.residual / e.inherent) * 100) : 0;
            return (
              <div key={e.name} className="exp-table-row">
                <div>
                  <div className="exp-scenario-name">{e.name}</div>
                  <div className="exp-scenario-desc">{e.desc}</div>
                </div>
                <div className="exp-num">
                  <span className="exp-bar-inline" style={{ width: `${(e.inherent / maxInh) * 60}px` }} />
                  ${e.inherent.toFixed(2)}M
                </div>
                <div className="exp-num dim">${e.mitigated.toFixed(2)}M</div>
                <div className="exp-num dim">${e.transferred.toFixed(2)}M</div>
                <div className="exp-num residual">${e.residual < 0.1 ? (e.residual * 1000).toFixed(0) + 'K' : e.residual.toFixed(2) + 'M'}</div>
                <div className="exp-num" style={{ color: 'var(--pos)', fontWeight: 600 }}>{red.toFixed(1)}%</div>
              </div>
            );
          })}
          <div className="exp-table-row total">
            <div className="exp-scenario-name">Portfolio total</div>
            <div className="exp-num">${totals.inherent.toFixed(2)}M</div>
            <div className="exp-num">${totals.mitigated.toFixed(2)}M</div>
            <div className="exp-num">${totals.transferred.toFixed(2)}M</div>
            <div className="exp-num residual">${totals.residual < 0.1 ? (totals.residual * 1000).toFixed(0) + 'K' : totals.residual.toFixed(2) + 'M'}</div>
            <div className="exp-num" style={{ color: 'var(--pos)', fontWeight: 600 }}>{(totals.inherent > 0 ? (1 - totals.residual / totals.inherent) * 100 : 0).toFixed(1)}%</div>
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Risk Waterfall</div>
              <div className="card-sub">How <b>${totals.inherent.toFixed(1)}M</b> becomes <b>${totals.residual.toFixed(1)}M</b></div>
            </div>
          </div>
          <div className="wf">
            {(() => {
              let running = 0;
              return waterfall.map((b, i) => {
                let leftPct, widthPct;
                if (b.v > 0) {
                  if (i === 0) { leftPct = 0; widthPct = (b.v / wfMax) * 100; }
                  else { leftPct = 0; widthPct = (b.v / wfMax) * 100; }
                  running += b.v;
                } else {
                  leftPct = ((running + b.v) / wfMax) * 100;
                  widthPct = (Math.abs(b.v) / wfMax) * 100;
                  running += b.v;
                }
                return (
                  <div key={b.k} className="wf-row">
                    <div className={`wf-label ${b.isEnd ? 'total' : ''}`}>{b.k}</div>
                    <div className="wf-track">
                      <div className="wf-bar" style={{ left: `${leftPct}%`, width: `${widthPct}%`, background: b.color }} />
                    </div>
                    <div className="wf-value">
                      {b.v > 0 ? '$' : '−$'}{Math.abs(b.v).toFixed(1)}M
                    </div>
                  </div>
                );
              });
            })()}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0, borderTop: '1px solid var(--border)' }}>
            <div style={{ padding: '14px 20px', borderRight: '1px solid var(--border)' }}>
              <span className="caps">Cyber Insurance</span>
              <div className="kpi-value" style={{ fontSize: 22, marginTop: 6 }}>$5.0<span className="unit">M</span></div>
              <div className="kpi-sub" style={{ marginTop: 6 }}>Aggregate · <b>$10K retention</b> · PCI $1M sublimit</div>
            </div>
            <div style={{ padding: '14px 20px' }}>
              <span className="caps">Critical Attack Surface</span>
              <div className="kpi-value" style={{ fontSize: 22, marginTop: 6 }}>2<span className="unit">crit</span></div>
              <div className="kpi-sub" style={{ marginTop: 6 }}>Reachable · <b>34 high</b> · 220 total from Vanta</div>
            </div>
          </div>
          <div className="bm">
            <span className="tag">Benchmark</span>
            <span>IBM 2025 avg breach cost: <b>$4.88M</b> · Small co median: <b>$2.98M</b></span>
          </div>
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   OPERATIONAL EFFICIENCY
   ========================================================= */

function OperationalEfficiency() {
  const apiData = useDashboardData();
  const response = (apiData && mapResponse(apiData)) || RESPONSE;
  const savings = (apiData && mapSavings(apiData)) || SAVINGS;
  return (
    <div className="section">
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">04</span>
          <h2>Operational Cost Efficiency</h2>
          <span className="note">How SecOps scales without adding headcount</span>
        </div>
        <div className="section-actions">
          <span className="chip ok"><span className="dot"></span>100% auto-triage</span>
          <span className="chip ok"><span className="dot"></span>56% auto-resolve</span>
        </div>
      </div>

      <div className="kpi-row" style={{ marginBottom: 16 }}>
        <div className="card kpi">
          <div className="hero-row-top">
            <span className="caps">SOC AI Assessment Rate</span>
            <SourceBadge>Datadog + KV</SourceBadge>
          </div>
          <div className="kpi-value" style={{ color: 'var(--accent-strong)' }}>100<span className="unit">%</span></div>
          <div className="kpi-sub"><b>120</b> Datadog signals auto-triaged · <b>0</b> escalations to analyst · 165 hrs reclaimed</div>
          <div style={{ marginTop: 14, height: 32 }}><Spark data={[100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100]} /></div>
        </div>
        <div className="card kpi">
          <div className="hero-row-top">
            <span className="caps">Vuln Signal-to-Noise</span>
            <SourceBadge>Linear · Vuln worker</SourceBadge>
          </div>
          <div className="kpi-value">56<span className="unit">%</span></div>
          <div className="kpi-sub"><b>29 of 52</b> auto-resolved · only <b>23</b> need human remediation</div>
          <div style={{ marginTop: 14, height: 32 }}><Spark data={[30,34,38,40,42,44,46,48,50,52,54,56]} /></div>
        </div>
        <div className="card kpi">
          <div className="hero-row-top">
            <span className="caps">Evidence Automation</span>
            <SourceBadge>Vanta</SourceBadge>
          </div>
          <div className="kpi-value">166</div>
          <div className="kpi-sub"><b>143/166</b> automated tests passing · <b>86%</b> pass rate</div>
          <div style={{ marginTop: 14, height: 32 }}><Spark data={[140,145,148,150,152,155,157,160,162,164,166]} /></div>
        </div>
      </div>

      <div className="card" style={{ marginBottom: 16 }}>
        <div className="card-head">
          <div>
            <div className="card-title">Response Metrics</div>
            <div className="card-sub">Median across P1/P2 incidents · last 90 days · target lines committed to board</div>
          </div>
          <SourceBadge>Datadog Cases · Linear GraphQL</SourceBadge>
        </div>
        <div className="resp-grid">
          {response.map(r => {
            // Pct toward target (lower is better)
            const targetNum = parseFloat(r.target.match(/[\d.]+/)[0]);
            const pct = Math.max(0.15, Math.min(1, r.v / targetNum));
            const ok = r.v < targetNum;
            return (
              <div key={r.k} className="resp-cell">
                <ResponseDial pct={pct} ok={ok} />
                <div>
                  <div className="resp-label">{r.k}</div>
                  <div className="resp-val">{r.v}<span className="unit">{r.unit}</span></div>
                  <div className="resp-desc">{r.desc}</div>
                  <div className={`resp-target ${!ok ? 'warn' : ''}`}>◂ Target {r.target}</div>
                </div>
              </div>
            );
          })}
        </div>
        <div className="bm">
          <span className="tag">Benchmark</span>
          <span>IBM 2025 industry median: <b>MTTD 194 days</b>, <b>MTTR 64 days</b> · Spade tracks <b>10–100× faster</b></span>
        </div>
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Savings by Initiative</div>
              <div className="card-sub">Labor cost reclaimed · quarter to date</div>
            </div>
            <SourceBadge>Compute · trends.js</SourceBadge>
          </div>
          <div className="card-pad">
            {(() => {
              const max = Math.max(...savings.map(s => s.val));
              return savings.map(s => (
                <div key={s.name} className="sv-row">
                  <div className="sv-name">
                    {s.name}
                    <span className="src">src · {s.source}</span>
                  </div>
                  <div className="sv-bar"><div className="sv-fill" style={{ width: `${(s.val / max) * 100}%` }} /></div>
                  <div className="sv-val">{s.money}</div>
                  <div className="sv-sub">{s.hrs}</div>
                </div>
              ));
            })()}
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-title">Budget Allocation</div>
              <div className="card-sub">FY 2026 · security & IT ops · <b>$971K total</b></div>
            </div>
            <SourceBadge>Google Sheets · Budget</SourceBadge>
          </div>
          <div style={{ padding: 22 }}>
            <BudgetDonut />
          </div>
        </div>
      </div>
    </div>
  );
}

function ResponseDial({ pct, ok }) {
  const r = 32, c = 2 * Math.PI * r;
  const color = ok ? 'var(--accent-strong)' : 'var(--warn)';
  return (
    <svg width="76" height="76" viewBox="0 0 76 76" style={{ transform: 'rotate(-90deg)' }}>
      <circle cx="38" cy="38" r={r} fill="none" stroke="var(--bg-hover)" strokeWidth="6" />
      <circle cx="38" cy="38" r={r} fill="none" stroke={color} strokeWidth="6" strokeLinecap="round"
        strokeDasharray={c} strokeDashoffset={c * (1 - pct)} style={{ transition: 'stroke-dashoffset 0.8s' }} />
    </svg>
  );
}

function BudgetDonut() {
  // Real budget data from Google Sheets (2026-04-20)
  const segs = [
    { k: 'Current Spend', v: 337, c: 'var(--green-700)' },
    { k: 'Next Priority', v: 120, c: 'var(--accent-strong)' },
    { k: 'Future (1+ yr)', v: 259, c: 'var(--accent)' },
    { k: 'Optional', v: 255, c: 'var(--sage-4)' },
  ];
  const total = segs.reduce((s, x) => s + x.v, 0);
  let acc = 0;
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '140px 1fr', gap: 24, alignItems: 'center' }}>
      <svg width="140" height="140" viewBox="0 0 140 140" style={{ transform: 'rotate(-90deg)' }}>
        {segs.map((s, i) => {
          const r = 52, C = 2 * Math.PI * r;
          const pct = s.v / total;
          const dash = `${C * pct} ${C}`;
          const offset = -C * acc;
          acc += pct;
          return <circle key={i} cx="70" cy="70" r={r} fill="none" stroke={s.c} strokeWidth="22" strokeDasharray={dash} strokeDashoffset={offset} />;
        })}
        <g transform="rotate(90 70 70)">
          <text x="70" y="68" textAnchor="middle" fill="var(--fg-strong)" fontSize="22" fontWeight="500"
            style={{ fontFamily: 'var(--font-display)' }}>
            ${total}K
          </text>
          <text x="70" y="86" textAnchor="middle" fill="var(--fg-muted)" fontSize="10"
            style={{ fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>
            Q2 TOTAL
          </text>
        </g>
      </svg>
      <div>
        {segs.map(s => (
          <div key={s.k} style={{ display: 'grid', gridTemplateColumns: '12px 1fr auto', gap: 10, alignItems: 'center', padding: '8px 0', borderBottom: '1px solid var(--border)' }}>
            <span style={{ width: 10, height: 10, background: s.c, borderRadius: 2 }} />
            <div style={{ fontSize: 13, color: 'var(--fg)' }}>{s.k}</div>
            <div style={{ fontSize: 13, fontFamily: 'var(--font-mono)', fontVariantNumeric: 'tabular-nums', fontWeight: 500, color: 'var(--fg-strong)' }}>
              ${s.v}K
              <span style={{ color: 'var(--fg-muted)', fontSize: 11, marginLeft: 6 }}>{Math.round((s.v / total) * 100)}%</span>
            </div>
          </div>
        ))}
        <div style={{ marginTop: 12, fontSize: 11, color: 'var(--fg-muted)' }}>
          Committed: <b style={{ color: 'var(--pos)' }}>$457K</b> of $971K total · 47% committed
        </div>
      </div>
    </div>
  );
}

/* =========================================================
   TRENDS PAGE
   ========================================================= */

function TrendsPage({ onBack }) {
  // Real trend data from /api/trends (2026-04-20)
  const trends = [
    { section: 'Revenue Protection', items: [
      { k: 'Compliance Health', v: '86%', delta: 'flat', dir: 'flat',
        data: [89,89,87,87,86,86,86,87,88,87,87,82,86,72,55,86,85,85,84,87,85,85,85,86],
        target: 95, h: 160, dateLabel: 'Mar 22 – Apr 20' },
      { k: 'Pipeline Gated on Security', v: '$17.4M', delta: '+24%', dir: 'up',
        data: [13.4,13.6,13.8,13.9,14.0,14.2,14.3,14.5,14.8,15.0,15.2,15.5,15.7,15.9,16.0,16.2,16.3,16.5,16.6,16.8,16.9,17.0,17.0,17.1,17.2,17.2,17.3,17.3,17.3,17.4,17.4],
        target: 18, h: 160, dateLabel: 'Mar 22 – Apr 20' },
      { k: 'Current ARR', v: '$5.5M', delta: 'flat', dir: 'flat',
        data: [5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5],
        target: 5.5, h: 160, dateLabel: 'Mar 22 – Apr 20' },
    ]},
    { section: 'Financial Exposure', items: [
      { k: 'Critical Reachable Vulns', v: '2', delta: '+2', dir: 'down',
        data: [0,0,0,2,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2],
        target: 0, h: 160, dateLabel: 'Mar 22 – Apr 20' },
      { k: 'Annualized Loss Expectancy', v: '$3.0M', delta: '+$2.1M', dir: 'down',
        data: [0.89,0.89,0.30,1.94,2.09,0.30,0.30,2.98,2.98,2.23,2.98,2.09,2.38,2.53,2.53,0.30,0.30,2.23,2.53,0.30,2.53,2.53,2.53,2.53,0.30,2.98,2.98,2.98,2.98,2.98],
        target: 1.5, h: 160, dateLabel: 'Mar 22 – Apr 20' },
      { k: 'Risk Treatment Rate', v: '100%', delta: 'flat', dir: 'flat',
        data: [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100],
        target: 95, h: 160, dateLabel: 'Mar 22 – Apr 20' },
    ]},
    { section: 'Operational Efficiency', items: [
      { k: 'SOC AI Assessment Rate', v: '100%', delta: 'flat', dir: 'flat',
        data: [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100],
        target: 100, h: 180, dateLabel: 'Mar 22 – Apr 20' },
      { k: 'Mean Time to Triage', v: '9.9 min', delta: '-90%', dir: 'up',
        data: [99.2,99.2,91.6,91.6,91.6,99.2,99.2,99.2,91.6,91.6,91.6,91.6,91.6,91.6,91.6,91.6,91.6,99.2,99.2,99.2,99.2,99.2,99.2,99.2,99.2,9.9,9.9,9.9,9.9,9.9],
        target: 15, h: 180, dateLabel: 'Mar 22 – Apr 20' },
    ]},
  ];

  return (
    <div className="main">
      <div className="page-hdr">
        <div>
          <h1>Security Trends</h1>
          <div className="sub">30-day trendline across all program metrics · <b>last updated Apr 20, 6:52 PM EST</b></div>
        </div>
        <div style={{ display: 'flex', gap: 10 }}>
          <div className="period-switch">
            {['Daily', 'Weekly', 'Monthly', 'Quarterly'].map(p => (
              <button key={p} className={p === 'Daily' ? 'active' : ''}>{p}</button>
            ))}
          </div>
          <button className="btn" onClick={onBack}>← Dashboard</button>
        </div>
      </div>

      {trends.map(group => (
        <div key={group.section} className="section" style={{ marginTop: 32 }}>
          <div className="section-hdr">
            <div className="section-title">
              <h2 style={{ fontSize: 20 }}>{group.section}</h2>
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: group.items.length === 2 ? '1fr 1fr' : 'repeat(3, 1fr)', gap: 16 }}>
            {group.items.map(it => (
              <TrendCard key={it.k} {...it} isHero={false} />
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

function TrendCard({ k, v, delta, dir, data, target, h, dateLabel, isHero }) {
  return (
    <div className="card">
      <div className="card-head-plain">
        <div>
          <div className="caps">{k}</div>
          <div className="kpi-value" style={{ fontSize: isHero ? 34 : 26, marginTop: 4 }}>{v}</div>
        </div>
        <Delta text={delta} dir={dir} />
      </div>
      <div style={{ padding: '0 20px 8px' }}>
        <TrendChart data={data} target={target} h={h} />
      </div>
      <div style={{ padding: '8px 20px 14px', fontSize: 11, color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)', borderTop: '1px solid var(--border)' }}>
        {dateLabel}
      </div>
    </div>
  );
}

function TrendChart({ data, target, h = 180 }) {
  const w = 560;
  const min = Math.min(0, ...data);
  const max = Math.max(target * 1.1, ...data);
  const range = max - min || 1;
  const x = i => (i / (data.length - 1)) * (w - 40) + 32;
  const y = v => h - 20 - ((v - min) / range) * (h - 40);
  const path = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${x(i)},${y(d)}`).join(' ');
  const area = path + ` L${x(data.length - 1)},${h - 20} L${x(0)},${h - 20} Z`;
  const ticks = [max, max * 0.5, 0];
  const labels = ['Mar 21', 'Mar 30', 'Apr 5', 'Apr 13', 'Apr 20'];
  const last = [x(data.length - 1), y(data[data.length - 1])];
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <defs>
        <linearGradient id={`tg-${w}-${h}-${target}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor="var(--accent-strong)" stopOpacity="0.3" />
          <stop offset="1" stopColor="var(--accent-strong)" stopOpacity="0" />
        </linearGradient>
      </defs>
      {/* grid */}
      {ticks.map((t, i) => (
        <g key={i}>
          <line x1="32" y1={y(t)} x2={w - 8} y2={y(t)} stroke="var(--border)" strokeWidth="1" strokeDasharray={i === 0 ? '' : '2 4'} />
          <text x="26" y={y(t) + 4} textAnchor="end" fontSize="10" fill="var(--fg-muted)" fontFamily="var(--font-mono)">
            {t >= 1000000 ? `${(t/1000000).toFixed(1)}M` : t >= 1000 ? `${(t/1000).toFixed(0)}k` : Number.isInteger(t) ? t : t.toFixed(1)}{typeof target === 'number' && target > 50 && target < 101 ? '%' : ''}
          </text>
        </g>
      ))}
      {/* target line */}
      {target > 0 && target < max && (
        <line x1="32" y1={y(target)} x2={w - 8} y2={y(target)} stroke="var(--ochre)" strokeWidth="1" strokeDasharray="4 3" opacity="0.6" />
      )}
      <path d={area} fill={`url(#tg-${w}-${h}-${target})`} />
      <path d={path} fill="none" stroke="var(--accent-strong)" strokeWidth="1.75" />
      <circle cx={last[0]} cy={last[1]} r="4" fill="var(--accent-strong)" stroke="var(--bg-elevated)" strokeWidth="2" />
      {/* x labels */}
      {labels.map((l, i) => (
        <text key={l} x={32 + (i / (labels.length - 1)) * (w - 40)} y={h - 4} textAnchor="middle" fontSize="10" fill="var(--fg-muted)" fontFamily="var(--font-mono)">
          {l}
        </text>
      ))}
    </svg>
  );
}

/* =========================================================
   ROADMAP PAGE
   ========================================================= */

// Real Linear projects for Security team (2026-04-20)
const ROADMAP = [
  // Active — In Progress
  { id: 'PRJ-01', title: 'Customer Trust & Revenue Enablement', pillar: 'Revenue', status: 'In Progress', progress: 65, owner: 'S. Rahman', eta: 'Jun 30', value: 'Questionnaire SLA ≤2 days', priority: 'P0' },
  { id: 'PRJ-02', title: 'SOC 2 Audit Readiness', pillar: 'Revenue', status: 'In Progress', progress: 70, owner: 'S. Rahman', eta: 'Jun 30', value: 'Aug 2026 Type II report', priority: 'P1' },
  { id: 'PRJ-03', title: 'Identity & Access Essentials', pillar: 'Exposure', status: 'In Progress', progress: 45, owner: 'S. Rahman', eta: 'Dec 31', value: 'SSO + MFA + RBAC rollout', priority: 'P0' },
  { id: 'PRJ-04', title: 'Security Engineering Integration', pillar: 'Exposure', status: 'In Progress', progress: 40, owner: 'S. Rahman', eta: 'Sep 30', value: 'SDLC shift-left controls', priority: 'P1' },
  { id: 'PRJ-05', title: 'AI & Model Risk Governance', pillar: 'Revenue', status: 'In Progress', progress: 15, owner: 'S. Rahman', eta: 'Mar 2027', value: 'SR 11-7 / E-23 / EU AI Act', priority: 'P1' },
  // Shipped
  { id: 'PRJ-06', title: 'Detection & Response — Foundations & IR', pillar: 'Efficiency', status: 'Shipped', progress: 100, owner: 'S. Rahman', eta: 'Shipped Q1', value: 'IR plan + tabletop + SIEM', priority: 'P1' },
  // Backlog — Q2 targets
  { id: 'PRJ-07', title: 'IT Operations — MSP Transition', pillar: 'Efficiency', status: 'Scoping', progress: 5, owner: 'S. Rahman', eta: 'Jun 30', value: '80+ hrs/mo capacity freed', priority: 'P0' },
  { id: 'PRJ-08', title: 'Vendor Risk — Priority Reviews', pillar: 'Exposure', status: 'Scoping', progress: 10, owner: 'S. Rahman', eta: 'Jun 30', value: '10 H/C vendor reviews', priority: 'P2' },
  // Backlog — Q3+ targets
  { id: 'PRJ-09', title: 'PCI & GDPR Readiness', pillar: 'Revenue', status: 'Scoping', progress: 0, owner: 'S. Rahman', eta: 'Dec 31', value: 'PCI DSS 4.0 + GDPR', priority: 'P1' },
  { id: 'PRJ-10', title: 'SOC Capability & Maturity', pillar: 'Efficiency', status: 'Scoping', progress: 0, owner: 'S. Rahman', eta: 'Sep 30', value: '24/7 SOC + MSSP', priority: 'P1' },
  { id: 'PRJ-11', title: 'Strategic Security Governance', pillar: 'Exposure', status: 'Scoping', progress: 0, owner: 'S. Rahman', eta: 'Dec 31', value: 'Risk register + steering', priority: 'P2' },
  { id: 'PRJ-12', title: 'Vendor Risk — Cadence & Monitoring', pillar: 'Exposure', status: 'Scoping', progress: 0, owner: 'S. Rahman', eta: 'Dec 31', value: 'Continuous vendor monitoring', priority: 'P2' },
  { id: 'PRJ-13', title: 'Compliance — Continuous & Post-Audit', pillar: 'Revenue', status: 'Scoping', progress: 0, owner: 'S. Rahman', eta: 'Dec 31', value: 'PCI QSA + annual cadence', priority: 'P1' },
  { id: 'PRJ-14', title: 'ISO 27001 Certification', pillar: 'Revenue', status: 'Scoping', progress: 0, owner: 'S. Rahman', eta: 'Q2 2027', value: 'Enterprise procurement gate', priority: 'P3' },
];

function RoadmapPage() {
  const [filter, setFilter] = useState('All');
  const pillars = ['All', 'Revenue', 'Exposure', 'Efficiency'];
  const filtered = filter === 'All' ? ROADMAP : ROADMAP.filter(r => r.pillar === filter);
  const statusColor = {
    'Shipped': 'ok', 'In Review': 'ok', 'In Progress': 'warn', 'Scoping': 'neg',
  };
  return (
    <div className="section" style={{ marginTop: 0 }}>
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">—</span>
          <h2>Roadmap · {ROADMAP.length} projects</h2>
          <span className="note">Linear projects · Security team</span>
        </div>
        <div className="section-actions">
          <div className="period-switch">
            {pillars.map(p => (
              <button key={p} className={filter === p ? 'active' : ''} onClick={() => setFilter(p)}>{p}</button>
            ))}
          </div>
        </div>
      </div>
      <div className="kpi-row" style={{ marginBottom: 16 }}>
        <div className="card kpi">
          <span className="caps">Shipped QTD</span>
          <div className="kpi-value">{ROADMAP.filter(r => r.status === 'Shipped').length}</div>
          <div className="kpi-sub">Initiatives completed this quarter</div>
        </div>
        <div className="card kpi">
          <span className="caps">In Flight</span>
          <div className="kpi-value">{ROADMAP.filter(r => r.status === 'In Progress' || r.status === 'In Review').length}</div>
          <div className="kpi-sub">Active execution · <b>{Math.round(ROADMAP.filter(r => r.status === 'In Progress').reduce((s,r)=>s+r.progress,0) / ROADMAP.filter(r => r.status === 'In Progress').length)}%</b> avg progress</div>
        </div>
        <div className="card kpi">
          <span className="caps">Value Unlocked</span>
          <div className="kpi-value" style={{ color: 'var(--accent-strong)' }}>$131<span className="unit">K</span></div>
          <div className="kpi-sub">Annual savings from shipped automation work</div>
        </div>
      </div>
      <div className="card">
        <div className="card-head">
          <div>
            <div className="card-title">Initiative Tracker</div>
            <div className="card-sub">Linear IDs clickable in production · synced every 10 min</div>
          </div>
          <SourceBadge>Linear GraphQL</SourceBadge>
        </div>
        <div className="roadmap-head">
          <div>ID</div>
          <div>Project</div>
          <div>Pillar</div>
          <div>Priority</div>
          <div>Progress</div>
          <div>Owner</div>
          <div>ETA</div>
        </div>
        {filtered.map(r => (
          <div key={r.id} className="roadmap-row">
            <div className="mono" style={{ color: 'var(--accent-strong)', fontWeight: 500 }}>{r.id}</div>
            <div>
              <div className="exp-scenario-name">{r.title}</div>
              <div className="exp-scenario-desc" style={{ color: 'var(--accent-strong)' }}>{r.value}</div>
            </div>
            <div>
              <span className="chip" style={{ fontSize: 11 }}>{r.pillar}</span>
            </div>
            <div>
              <span className={`chip ${r.priority === 'P0' ? 'neg' : r.priority === 'P1' ? 'warn' : r.priority === 'P3' ? '' : 'ok'}`} style={{ fontSize: 11 }}>
                {r.priority}
              </span>
            </div>
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <div className="fw-bar" style={{ flex: 1 }}>
                  <div className={`fw-fill ${r.progress === 100 ? '' : r.progress < 15 ? 'neg' : ''}`} style={{ width: `${r.progress}%` }} />
                </div>
                <div className="mono" style={{ fontSize: 11, color: 'var(--fg-muted)', minWidth: 28, textAlign: 'right' }}>{r.progress}%</div>
              </div>
              <div style={{ fontSize: 10, color: 'var(--fg-muted)', marginTop: 4, textTransform: 'uppercase', letterSpacing: '0.06em', fontFamily: 'var(--font-mono)' }}>{r.status}</div>
            </div>
            <div style={{ color: 'var(--fg)' }}>{r.owner}</div>
            <div className="mono">{r.eta}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* =========================================================
   SOURCES PAGE
   ========================================================= */

const SOURCES = [
  { name: 'Vanta',     desc: 'Compliance controls + vendors + risks',   endpoint: '/v1/controls', refresh: '6m',   records: '348', status: 'ok',   last: '4m ago', used: ['Revenue', 'Impact'] },
  { name: 'Datadog',   desc: 'SIEM signals + cases + security findings', endpoint: '/api/v2/security_monitoring', refresh: '2m', records: '12.4K', status: 'ok',   last: '1m ago', used: ['Efficiency', 'Exposure'] },
  { name: 'Linear',    desc: 'Vulnerability tickets + roadmap + MTTR',   endpoint: 'GraphQL /issues',     refresh: '10m',  records: '1,840', status: 'ok',   last: '8m ago', used: ['Efficiency', 'Roadmap'] },
  { name: 'Salesforce',desc: 'Pipeline + ARR gated by compliance',       endpoint: 'via Coefficient',     refresh: '1h',   records: '42',    status: 'ok',   last: '22m ago', used: ['Revenue'] },
  { name: 'Coefficient', desc: 'Google Sheets ↔ SFDC sync',             endpoint: 'Sheets webhook',      refresh: '1h',   records: '—',     status: 'ok',   last: '22m ago', used: ['Revenue'] },
  { name: 'Google Sheets', desc: 'CCF · Budget · Savings trackers',     endpoint: 'Sheets API v4',       refresh: '30m',  records: '6 sheets', status: 'ok', last: '14m ago', used: ['Revenue', 'Efficiency'] },
  { name: 'Cloudflare KV', desc: 'Signal counters + timeseries cache',  endpoint: 'Workers KV',          refresh: 'live', records: '—',     status: 'ok',   last: 'live', used: ['Efficiency', 'Impact'] },
  { name: 'FAIR Engine',   desc: 'Risk quantification (local compute)', endpoint: 'compute/fair-assessment.js', refresh: 'on-demand', records: '4 scenarios', status: 'ok', last: 'live', used: ['Exposure'] },
  { name: 'Okta',          desc: 'Identity events + MFA enrollment',    endpoint: '/api/v1/events',      refresh: '15m',  records: '8,200', status: 'warn', last: '34m ago', used: ['Exposure', 'Revenue'] },
];

function SourcesPage() {
  return (
    <div className="section" style={{ marginTop: 0 }}>
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">—</span>
          <h2>9 Data Sources</h2>
          <span className="note">Cloudflare Worker aggregates and caches · single unified API</span>
        </div>
        <div className="section-actions">
          <span className="chip ok"><span className="dot"></span>8 healthy</span>
          <span className="chip warn"><span className="dot"></span>1 delayed</span>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
        {SOURCES.map(s => (
          <div key={s.name} className="card" style={{ padding: 18 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 10 }}>
              <div className="card-title" style={{ fontSize: 14 }}>{s.name}</div>
              <span className={`chip ${s.status}`} style={{ fontSize: 10, padding: '2px 8px' }}><span className="dot"></span>{s.status === 'ok' ? 'Healthy' : 'Delayed'}</span>
            </div>
            <div style={{ fontSize: 12, color: 'var(--fg-muted)', lineHeight: 1.5, minHeight: 36 }}>{s.desc}</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginTop: 14, paddingTop: 12, borderTop: '1px solid var(--border)', fontSize: 11 }}>
              <div><span style={{ color: 'var(--fg-muted)' }}>Endpoint</span><div className="mono" style={{ color: 'var(--fg)' }}>{s.endpoint}</div></div>
              <div><span style={{ color: 'var(--fg-muted)' }}>Refresh</span><div className="mono" style={{ color: 'var(--fg)' }}>{s.refresh}</div></div>
              <div><span style={{ color: 'var(--fg-muted)' }}>Records</span><div className="mono" style={{ color: 'var(--fg)' }}>{s.records}</div></div>
              <div><span style={{ color: 'var(--fg-muted)' }}>Last sync</span><div className="mono" style={{ color: 'var(--fg)' }}>{s.last}</div></div>
            </div>
            <div style={{ marginTop: 12, display: 'flex', gap: 4, flexWrap: 'wrap' }}>
              {s.used.map(u => (
                <span key={u} style={{ fontSize: 10, padding: '2px 7px', borderRadius: 4, background: 'var(--accent-bg)', color: 'var(--accent-strong)', fontFamily: 'var(--font-mono)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{u}</span>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* =========================================================
   AUDIT TRAIL
   ========================================================= */

const AUDIT = [
  { t: 'Apr 20, 6:48 PM', user: 'Shadman Rahman', action: 'Viewed Financial Exposure', obj: 'pillar/exposure', ip: '10.0.4.22' },
  { t: 'Apr 20, 6:42 PM', user: 'system:cron',    action: 'Refreshed controls',       obj: 'vanta.controls', ip: 'cf-worker' },
  { t: 'Apr 20, 6:30 PM', user: 'Shadman Rahman', action: 'Exported board report',    obj: 'report/q2-2026.pdf', ip: '10.0.4.22' },
  { t: 'Apr 20, 5:14 PM', user: 'K. Tanaka',      action: 'Approved SEC-142 review',  obj: 'linear/SEC-142',     ip: '10.0.4.18' },
  { t: 'Apr 20, 4:52 PM', user: 'system:cron',    action: 'Refreshed FAIR scenarios', obj: 'fair.scenarios',     ip: 'cf-worker' },
  { t: 'Apr 20, 3:21 PM', user: 'M. Rivera',      action: 'Updated risk tolerance',   obj: 'board.tolerance',    ip: '10.0.4.31' },
  { t: 'Apr 20, 2:04 PM', user: 'J. Park',        action: 'Closed ticket SEC-139',    obj: 'linear/SEC-139',     ip: '10.0.4.27' },
  { t: 'Apr 20, 1:18 PM', user: 'Shadman Rahman', action: 'Signed in · MFA',          obj: 'auth/session',       ip: '10.0.4.22' },
];

function AuditPage() {
  return (
    <div className="section" style={{ marginTop: 0 }}>
      <div className="section-hdr">
        <div className="section-title">
          <span className="idx">—</span>
          <h2>Audit Trail</h2>
          <span className="note">Last 24 hours · immutable log · retained 7 years</span>
        </div>
        <div className="section-actions">
          <SourceBadge>Workers KV · audit.log</SourceBadge>
        </div>
      </div>
      <div className="card">
        <div className="exp-table-head" style={{ gridTemplateColumns: '160px 180px 1fr 1.2fr 120px' }}>
          <div>Timestamp</div>
          <div>User</div>
          <div>Action</div>
          <div>Object</div>
          <div>IP</div>
        </div>
        {AUDIT.map((a, i) => (
          <div key={i} className="exp-table-row" style={{ gridTemplateColumns: '160px 180px 1fr 1.2fr 120px', textAlign: 'left' }}>
            <div className="mono" style={{ color: 'var(--fg-muted)' }}>{a.t}</div>
            <div style={{ color: 'var(--fg-strong)', fontWeight: 500 }}>{a.user}</div>
            <div>{a.action}</div>
            <div className="mono" style={{ color: 'var(--accent-strong)' }}>{a.obj}</div>
            <div className="mono" style={{ color: 'var(--fg-muted)' }}>{a.ip}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

Object.assign(window, {
  Sidebar, Topbar, ProgramImpact, RevenueProtection, FinancialExposure, OperationalEfficiency, TrendsPage,
  RoadmapPage, SourcesPage, AuditPage,
  DashboardDataContext, fetchDashboardData,
});
