// Industry Insights — Full redesign per new design spec (Industry Insights — Standalone).
// Phase 1: Industry chip picker → CTA unlocks on selection.
// Phase 2: Redesigned dashboard — hero + 10 benchmark sections, hand-built SVG charts.
//
// Live data (see docs/industry-insights-api.md):
//   GET  /v1/bi/industries          → shared catalog (picker)
//   POST /v1/bi/industryInsights    → { email, industry } dashboard (no DUNS)
// Gated by RBI_ENV.industryInsightsLive (true = live APIs; false = local sample only).

const { useState: useIndState, useEffect: useIndEffect, useRef: useIndRef, useCallback: useIndCallback } = React;

function indLiveApiEnabled() {
  return !!(window.RBI_ENV && window.RBI_ENV.industryInsightsLive);
}

// ── Industry Data ─────────────────────────────────────────────────────────

const INDUSTRIES = [
  {
    value: "restaurant", label: "Restaurant & Food Services", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2" /><path d="M7 2v20" /><path d="M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7" /></svg>
    )
  },
  {
    value: "retail", label: "Retail", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z" /><path d="M3 6h18" /><path d="M16 10a4 4 0 0 1-8 0" /></svg>
    )
  },
  {
    value: "contractor", label: "Contractor & Construction", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M2 20h20" /><path d="M5 20V8l7-6 7 6v12" /><path d="M9 20v-6h6v6" /></svg>
    )
  },
  {
    value: "healthcare", label: "Healthcare & Wellness", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z" /><path d="M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08v0c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66" /><path d="m18 15-2-2" /><path d="m15 18-2-2" /></svg>
    )
  },
  {
    value: "auto", label: "Auto Services", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M19 17H5a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2Z" /><path d="M3 9 5 4h14l2 5" /><circle cx="7.5" cy="17" r="2.5" /><circle cx="16.5" cy="17" r="2.5" /></svg>
    )
  },
  {
    value: "beauty", label: "Beauty & Personal Care", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z" /><path d="M8 14s1.5 2 4 2 4-2 4-2" /><line x1="9" y1="9" x2="9.01" y2="9" /><line x1="15" y1="9" x2="15.01" y2="9" /></svg>
    )
  },
  {
    value: "logistics", label: "Transportation & Logistics", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M5 17H3a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v3" /><rect x="9" y="11" width="14" height="10" rx="2" /><circle cx="12" cy="21" r="1" /><circle cx="20" cy="21" r="1" /></svg>
    )
  },
  {
    value: "professional", label: "Professional Services", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="7" width="20" height="14" rx="2" /><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2" /><line x1="12" y1="12" x2="12" y2="12" /><path d="M12 12h.01" /><path d="M2 12h20" /></svg>
    )
  },
  {
    value: "other", label: "Other", icon: (
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><path d="M12 8v4" /><path d="M12 16h.01" /></svg>
    )
  },
];

const REVENUE_RANGES = [
  { value: "lt25k", label: "Under $25,000 / mo" },
  { value: "25k_50k", label: "$25,000 – $50,000 / mo" },
  { value: "50k_100k", label: "$50,000 – $100,000 / mo" },
  { value: "100k_250k", label: "$100,000 – $250,000 / mo" },
  { value: "gt250k", label: "Over $250,000 / mo" },
];

const CREDIT_RANGES = [
  { value: "706_799", label: "706 – 799 (High Risk)" },
  { value: "800_839", label: "800 – 839 (Moderate – High Risk)" },
  { value: "840_879", label: "840 – 879 (Moderate Risk)" },
  { value: "880_899", label: "880 – 899 (Low – Moderate Risk)" },
  { value: "900_999", label: "900 – 999 (Low Risk)" },
];

const INDUSTRY_CHALLENGES = {
  restaurant: ["Labor Costs", "Inventory Management", "Seasonality", "Food Waste"],
  retail: ["Inventory Turnover", "Supplier Costs", "E-commerce Competition", "Seasonal Demand"],
  contractor: ["Project Cash Flow", "Material Costs", "Labor Availability", "Payment Delays"],
  healthcare: ["Regulatory Compliance", "Insurance Reimbursement", "Staffing", "Equipment Costs"],
  auto: ["Parts Sourcing", "Labor Costs", "Customer Retention", "Technology Investment"],
  beauty: ["Retail Competition", "Appointment No-shows", "Product Inventory", "Staff Turnover"],
  logistics: ["Fuel Costs", "Equipment Maintenance", "Driver Shortages", "Route Efficiency"],
  professional: ["Client Acquisition", "Billing Cycles", "Talent Retention", "Market Competition"],
  other: ["Cash Flow", "Market Competition", "Operating Costs", "Customer Retention"],
};

const FUNDING_USE_CASES = {
  restaurant: [{ label: "Inventory & Supplies", pct: 38 }, { label: "Equipment", pct: 26 }, { label: "Payroll", pct: 18 }, { label: "Expansion / Renovation", pct: 12 }, { label: "Marketing", pct: 6 }],
  retail: [{ label: "Seasonal Inventory", pct: 42 }, { label: "Equipment", pct: 20 }, { label: "Marketing", pct: 18 }, { label: "Payroll", pct: 14 }, { label: "Build-out", pct: 6 }],
  contractor: [{ label: "Project Cash Flow", pct: 44 }, { label: "Materials", pct: 30 }, { label: "Equipment", pct: 16 }, { label: "Payroll", pct: 10 }],
  healthcare: [{ label: "Equipment", pct: 35 }, { label: "Payroll", pct: 30 }, { label: "Supplies", pct: 20 }, { label: "Expansion", pct: 15 }],
  auto: [{ label: "Parts Inventory", pct: 40 }, { label: "Equipment", pct: 30 }, { label: "Payroll", pct: 18 }, { label: "Marketing", pct: 12 }],
  beauty: [{ label: "Product Inventory", pct: 35 }, { label: "Equipment", pct: 28 }, { label: "Renovation", pct: 22 }, { label: "Marketing", pct: 15 }],
  logistics: [{ label: "Fleet Maintenance", pct: 38 }, { label: "Fuel Costs", pct: 32 }, { label: "Payroll", pct: 20 }, { label: "Equipment", pct: 10 }],
  professional: [{ label: "Technology", pct: 35 }, { label: "Payroll", pct: 30 }, { label: "Marketing", pct: 22 }, { label: "Operations", pct: 13 }],
  other: [{ label: "Operations", pct: 40 }, { label: "Payroll", pct: 30 }, { label: "Equipment", pct: 18 }, { label: "Marketing", pct: 12 }],
};

// ── Default mock-controls values ──────────────────────────────────────────

const IND_MOCK_DEFAULTS = {
  revenue: 25000,
  years: "3",
  credit: "800_839",
  region: "California",
  showHistory: true,
};

/** Fallback month labels when the API does not return `months` (trailing 12). */
const II_MONTHS_FALLBACK = ["Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"];

// ── Benchmark computation ─────────────────────────────────────────────────

// Fixed industry averages — independent of user inputs so comparisons are meaningful
const IND_AVG_REV = {
  restaurant: 42000, retail: 55000, contractor: 68000, healthcare: 72000,
  auto: 38000, beauty: 28000, logistics: 85000, professional: 60000, other: 45000,
};
const IND_AVG_CREDIT = {
  restaurant: 780, retail: 800, contractor: 790, healthcare: 820,
  auto: 795, beauty: 775, logistics: 785, professional: 815, other: 780,
};
const IND_GROWTH = {
  restaurant: "8.4", retail: "9.1", contractor: "11.2", healthcare: "7.8",
  auto: "6.5", beauty: "10.3", logistics: "12.1", professional: "8.9", other: "7.5",
};
const IND_BUFFER_BASE = {
  restaurant: 55, retail: 52, contractor: 58, healthcare: 48,
  auto: 53, beauty: 50, logistics: 60, professional: 45, other: 54,
};
const IND_COHORT_N = {
  restaurant: 3184, retail: 4210, contractor: 1860, healthcare: 1420,
  auto: 2260, beauty: 1980, logistics: 1540, professional: 2040, other: 2600,
};

function computeBenchmarks(form) {
  const creditMap = { "706_799": 752, "800_839": 819, "840_879": 859, "880_899": 889, "900_999": 950 };

  const myRev = typeof form.revenue === "number" ? form.revenue : parseInt(form.revenue) || 25000;
  const myCredit = creditMap[form.credit] || 752;
  const myYears = parseFloat(form.years) || 2;

  const indAvgRev = IND_AVG_REV[form.industry] || 45000;
  const indAvgCredit = IND_AVG_CREDIT[form.industry] || 780;
  const indAvgYears = 3.2;
  const indGrowth = IND_GROWTH[form.industry] || "7.5";
  const myGrowth = (myRev / indAvgRev * parseFloat(indGrowth)).toFixed(1);

  const avgFunding = Math.round(indAvgRev * 1.12 / 1000) * 1000;
  return { myRev, myCredit, myYears, indAvgRev, indAvgCredit, indAvgYears, myGrowth, indGrowth, avgFunding };
}

// ── Deterministic pseudo-random generation (seeded by inputs, so the same
//    mock-control combo always renders the same numbers) ───────────────────

function seedFromString(s) {
  let h = 2166136261;
  for (let i = 0; i < s.length; i++) {
    h ^= s.charCodeAt(i);
    h = Math.imul(h, 16777619);
  }
  return h >>> 0;
}
function mulberry32(a) {
  return function () {
    a |= 0; a = (a + 0x6D2B79F5) | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}
// A 12-point series that drifts from base*(1 - drift/2) to base*(1 + drift/2)
// with small period-to-period noise.
function genSeries(rng, base, opts) {
  const o = opts || {};
  const months = o.months || 12, drift = o.drift == null ? 0.08 : o.drift, noise = o.noise == null ? 0.04 : o.noise, floor = o.floor || 0;
  const out = [];
  for (let i = 0; i < months; i++) {
    const trend = base * (1 + drift * (i / (months - 1) - 0.5));
    const wob = base * noise * (rng() - 0.5) * 2;
    out.push(Math.max(floor, Math.round(trend + wob)));
  }
  return out;
}

const CHALLENGE_NOTES = {
  "Labor Costs": "Wages and scheduling typically absorb a large share of monthly revenue.",
  "Inventory Management": "Stock on hand ties up cash and is sensitive to demand swings.",
  "Seasonality": "Most operators see a meaningful swing between peak and slow months.",
  "Food Waste": "Waste of purchased inventory quietly reduces margin every month.",
  "Inventory Turnover": "Slow-moving stock ties up working capital that could fund growth.",
  "Supplier Costs": "Rising supplier pricing compresses margin faster than retail prices adjust.",
  "E-commerce Competition": "Online-only competitors pressure both pricing and foot traffic.",
  "Seasonal Demand": "Revenue is concentrated in a handful of peak-demand months.",
  "Project Cash Flow": "Payment terms on larger jobs create timing gaps between cost and receipt.",
  "Material Costs": "Materials pricing volatility makes job costing harder to lock in.",
  "Labor Availability": "Finding and retaining skilled labor limits how much work can be taken on.",
  "Payment Delays": "Delayed client payments are a common source of short-term cash strain.",
  "Regulatory Compliance": "Compliance requirements add recurring administrative and licensing cost.",
  "Insurance Reimbursement": "Reimbursement timing lags service delivery by weeks or months.",
  "Staffing": "Recruiting and retaining qualified staff is a persistent operating cost.",
  "Equipment Costs": "Specialized equipment requires meaningful up-front and maintenance spend.",
  "Parts Sourcing": "Parts availability and pricing swings affect turnaround time and margin.",
  "Customer Retention": "Repeat business is harder to earn than the first sale.",
  "Technology Investment": "Keeping tools and diagnostics current requires ongoing reinvestment.",
  "Retail Competition": "Big-box and online retailers pressure pricing on product lines.",
  "Appointment No-shows": "Missed appointments create direct, hard-to-recover revenue loss.",
  "Product Inventory": "Retail product lines tie up cash that could otherwise fund services.",
  "Staff Turnover": "Turnover adds hiring and training cost and disrupts client relationships.",
  "Fuel Costs": "Fuel price swings move directly through to operating margin.",
  "Equipment Maintenance": "Fleet upkeep is a large, recurring, and only partly predictable cost.",
  "Driver Shortages": "Limited driver availability caps how much freight can be taken on.",
  "Route Efficiency": "Inefficient routing quietly adds fuel and labor cost across the fleet.",
  "Client Acquisition": "Acquiring new clients typically costs more than retaining existing ones.",
  "Billing Cycles": "Long billing cycles widen the gap between delivering work and getting paid.",
  "Talent Retention": "Losing senior talent disrupts client relationships and delivery capacity.",
  "Market Competition": "Competitive pricing pressure limits how much margin can be protected.",
  "Cash Flow": "Uneven timing between receipts and obligations is a constant balancing act.",
  "Operating Costs": "Day-to-day operating costs typically rise faster than pricing can follow.",
};

// ── Build the full benchmark dataset for the selected industry + inputs ───

function buildInsightsData(industryValue, industryLabel, form, bm) {
  const rng = mulberry32(seedFromString(industryValue + "|" + form.revenue + "|" + form.credit + "|" + form.years));

  const you = {
    inflow: bm.myRev,
    outflow: Math.round(bm.myRev * (0.90 + rng() * 0.08)),
    balance: Math.round(bm.myRev * (0.20 + rng() * 0.10)),
    sbfe: bm.myCredit,
  };
  const ind = {
    inflow: bm.indAvgRev,
    outflow: Math.round(bm.indAvgRev * 0.905),
    balance: Math.round(bm.indAvgRev * 0.34),
    sbfe: bm.indAvgCredit,
  };

  const inflowYou = genSeries(rng, you.inflow, { drift: 0.14, noise: 0.045 });
  const inflowInd = genSeries(rng, ind.inflow, { drift: 0.10, noise: 0.02 });
  const outflowYou = genSeries(rng, you.outflow, { drift: 0.17, noise: 0.045 });
  const outflowInd = genSeries(rng, ind.outflow, { drift: 0.11, noise: 0.02 });

  const balYou = genSeries(rng, you.balance, { drift: -0.10, noise: 0.06, floor: 1000 });
  const balIndMid = genSeries(rng, ind.balance, { drift: 0.02, noise: 0.02, floor: 1000 });
  const balLo = balIndMid.map(v => Math.round(v * 0.62));
  const balHi = balIndMid.map(v => Math.round(v * 1.68));

  const bounceCount = 1 + Math.round(rng() * 4);
  const bouncePrev = bounceCount + 1 + Math.round(rng() * 2);
  const bounceInd = +(1.6 + rng() * 1.2).toFixed(1);
  const bounceSpark = genSeries(rng, Math.max(2, bounceCount), { drift: -0.3, noise: 0.5, floor: 0 }).map(v => Math.min(9, v));

  const repaymentPctInflow = +(9.5 + rng() * 4.5).toFixed(1);
  const repaymentAvg = Math.round(you.inflow * (repaymentPctInflow / 100));
  const repaymentIndPct = +(7.8 + rng() * 2.4).toFixed(1);
  const operatingOutflow = Math.max(0, you.inflow - repaymentAvg - Math.round(you.inflow * 0.04));
  const remainingCash = Math.max(0, you.inflow - operatingOutflow - repaymentAvg);
  const operatingShare = Math.max(0, you.inflow - repaymentAvg - remainingCash);

  const sbfeYouDelta = 12 + Math.round(rng() * 22);
  const sbfeIndDelta = 5 + Math.round(rng() * 8);
  const sbfeYouHist = genSeries(rng, you.sbfe - sbfeYouDelta / 2, { drift: 0, noise: 0.006, floor: 300 });
  sbfeYouHist[sbfeYouHist.length - 1] = you.sbfe;
  const sbfeIndHist = genSeries(rng, ind.sbfe - sbfeIndDelta / 2, { drift: 0, noise: 0.004, floor: 300 });
  sbfeIndHist[sbfeIndHist.length - 1] = ind.sbfe;

  const flexLineInd = bm.avgFunding;
  const flexLineYou = Math.round(flexLineInd * (1.08 + rng() * 0.28));
  const flexRange = [Math.round(flexLineInd * 0.46), Math.round(flexLineInd * 1.9)];

  const bufferBase = IND_BUFFER_BASE[industryValue] || 54;
  const bufferInd = Math.round(bufferBase + (rng() - 0.5) * 6);
  const bufferYou = Math.min(96, Math.max(8, Math.round(bufferInd + (rng() - 0.35) * 22)));
  const bufferRange = [Math.max(5, bufferInd - 27), Math.min(99, bufferInd + 23)];

  const industryBuffer = genSeries(rng, bufferInd, { drift: 0.10, noise: 0.05, floor: 5 }).map(v => Math.min(99, v));

  const cohortN = IND_COHORT_N[industryValue] || (1200 + Math.round(rng() * 3000));

  const snapshot = [
    { key: "inflow", label: "Monthly Cash Inflow", you: you.inflow, ind: ind.inflow, unit: "$", trend: (inflowYou[11] >= inflowYou[0] ? "+" : "−") + Math.abs(((inflowYou[11] - inflowYou[0]) / inflowYou[0]) * 100).toFixed(1) + "%", trendDir: inflowYou[11] >= inflowYou[0] ? "up" : "down", status: you.inflow >= ind.inflow ? "above" : "below", note: "vs. industry average" },
    { key: "outflow", label: "Monthly Cash Outflow", you: you.outflow, ind: ind.outflow, unit: "$", trend: (outflowYou[11] >= outflowYou[0] ? "+" : "−") + Math.abs(((outflowYou[11] - outflowYou[0]) / outflowYou[0]) * 100).toFixed(1) + "%", trendDir: "up", status: you.outflow <= ind.outflow ? "above" : "below", note: you.outflow <= ind.outflow ? "leaner than peers" : "higher spend than peers" },
    { key: "balance", label: "Avg Starting Balance", you: you.balance, ind: ind.balance, unit: "$", trend: (balYou[11] >= balYou[0] ? "+" : "−") + Math.abs(((balYou[11] - balYou[0]) / balYou[0]) * 100).toFixed(1) + "%", trendDir: balYou[11] >= balYou[0] ? "up" : "down", status: you.balance >= ind.balance ? "above" : "below", note: you.balance >= ind.balance ? "healthy cash cushion" : "thinner cash cushion" },
    { key: "sbfe", label: "SBFE Score", you: you.sbfe, ind: ind.sbfe, unit: "", trend: "+" + sbfeYouDelta + " pts", trendDir: "up", status: you.sbfe >= ind.sbfe ? "above" : "below", note: "last 12 months" },
    { key: "buffer", label: "Cash Buffer Utilization", you: bufferYou, ind: bufferInd, unit: "%", trend: (bufferYou >= bufferInd ? "+" : "−") + Math.abs(bufferYou - bufferInd) + " pts", trendDir: bufferYou >= bufferInd ? "up" : "down", status: bufferYou <= bufferInd + 5 ? "near" : "below", note: "of available capital used" },
  ];

  const consistencyPct = Math.min(98, Math.max(58, Math.round(70 + (you.inflow >= ind.inflow ? 12 : -6) + rng() * 12)));
  const factors = [
    { key: "consistency", label: "Cash Flow Consistency", status: consistencyPct >= 88 ? "strong" : consistencyPct >= 75 ? "moderate" : "attention", you: consistencyPct + "% of months positive", ind: "Industry " + Math.max(70, consistencyPct - 8) + "%", note: "Your deposits have been " + (consistencyPct >= 85 ? "steady across most of the last 12 months." : "somewhat uneven over the last 12 months."), why: "Lenders look for predictable deposit patterns rather than one strong month.", link: "" },
    { key: "buffer", label: "Cash Buffer", status: you.balance >= ind.balance ? "strong" : you.balance >= ind.balance * 0.8 ? "moderate" : "attention", you: iiUSD(you.balance, true) + " avg balance", ind: "Industry " + iiUSD(ind.balance, true), note: you.balance >= ind.balance ? "Your average starting cash balance is above similar businesses." : "Your average starting cash balance is below similar businesses.", why: "A larger cash cushion absorbs slow weeks without missed payments.", link: "" },
    { key: "credit", label: "Credit Profile", status: you.sbfe >= ind.sbfe + 20 ? "strong" : you.sbfe >= ind.sbfe ? "moderate" : "attention", you: "SBFE " + you.sbfe, ind: "Industry " + ind.sbfe, note: "Your SBFE score is " + Math.abs(you.sbfe - ind.sbfe) + " points " + (you.sbfe >= ind.sbfe ? "above" : "below") + " the industry average.", why: "Business credit reporting reflects how reliably you pay trade and lending obligations.", link: "" },
    { key: "repayment", label: "Repayment Burden", status: repaymentPctInflow <= repaymentIndPct ? "strong" : repaymentPctInflow <= repaymentIndPct + 3 ? "moderate" : "attention", you: repaymentPctInflow + "% of inflow", ind: "Industry " + repaymentIndPct + "%", note: repaymentPctInflow > repaymentIndPct ? "Repayment deductions take a larger share of inflow than peers." : "Repayment deductions take a smaller share of inflow than peers.", why: "The share of revenue committed to existing repayments limits room for new financing.", link: "" },
    { key: "reliability", label: "Payment Reliability", status: bounceCount <= bounceInd ? "strong" : bounceCount <= bounceInd + 1.5 ? "moderate" : "attention", you: bounceCount + " bounces / 90 days", ind: "Industry " + bounceInd, note: "Bounced payments are " + (bounceCount < bouncePrev ? "down from " + bouncePrev + ", " : "") + (bounceCount <= bounceInd ? "in line with peers." : "still slightly above peers."), why: "Returned payments are read as a short-term liquidity signal.", link: "" },
  ];

  const palette = ["#0040BA", "#3366C8", "#04C49E", "#68DCC5", "#A4C3FF"];
  const fundingUse = (FUNDING_USE_CASES[industryValue] || FUNDING_USE_CASES.other).map((u, i) => ({ label: u.label, value: u.pct, color: palette[i % palette.length] }));

  const challenges = (INDUSTRY_CHALLENGES[industryValue] || INDUSTRY_CHALLENGES.other).map(label => ({
    label, note: CHALLENGE_NOTES[label] || `A common pressure point for ${industryLabel} businesses, and one that shows up directly in cash flow patterns.`
  }));

  const topPerformers = [
    { metric: "Average Credit Profile", top: (ind.sbfe + 75) + "+ SBFE", ind: ind.sbfe + " SBFE" },
    { metric: "Cash Flow Consistency", top: "94% positive months", ind: Math.max(70, consistencyPct - 10) + "% positive months" },
    { metric: "Customer Retention", top: "72% repeat customers", ind: "58% repeat customers" },
    { metric: "Cash Flow Stability", top: "Low volatility", ind: "Moderate volatility" },
    { metric: "Time in Business", top: "6+ years", ind: bm.indAvgYears.toFixed(1) + " years" },
  ];

  const education = [
    { tag: "Cash flow", title: "Improve Cash Flow", note: "Practical steps to stabilize deposits and shorten the gap between payables and receivables." },
    { tag: "Credit", title: "Understand Your SBFE Score", note: "How small business credit exchange data is built, what moves it, and how to review yours." },
    { tag: "Funding", title: "Prepare for Funding", note: "What lenders commonly evaluate and how to organize your financials before applying." },
  ];

  return {
    cohort: { n: cohortN, spec: `${industryLabel} · benchmark cohort · 12-month trailing` },
    snapshot,
    inflow: { you: inflowYou, ind: inflowInd },
    outflow: { you: outflowYou, ind: outflowInd },
    balance: { you: balYou, lo: balLo, hi: balHi },
    bounce: { count: bounceCount, prev: bouncePrev, ind: bounceInd, spark: bounceSpark },
    repayment: {
      avg: repaymentAvg, pctInflow: repaymentPctInflow, indPct: repaymentIndPct, inflow: you.inflow,
      composition: [
        { label: "Operating outflow", value: operatingShare, color: "var(--gg-100)" },
        { label: "Repayment deductions", value: repaymentAvg, color: "var(--color-warning)" },
        { label: "Remaining cash", value: remainingCash, color: "var(--fp-100)" },
      ],
    },
    sbfe: { you: you.sbfe, ind: ind.sbfe, min: 300, max: 1000, youDelta: sbfeYouDelta, indDelta: sbfeIndDelta, youHist: sbfeYouHist, indHist: sbfeIndHist, indRange: [Math.max(300, ind.sbfe - 120), Math.min(1000, ind.sbfe + 140)] },
    flexLine: { you: flexLineYou, ind: flexLineInd, range: flexRange },
    buffer: { you: bufferYou, ind: bufferInd, range: bufferRange },
    factors,
    industryBuffer,
    fundingUse,
    challenges,
    topPerformers,
    education,
  };
}

// ── Live API helpers (docs/industry-insights-api.md) ───────────────────────

const IND_ICON_BY_KEY = {};
INDUSTRIES.forEach((ind) => { IND_ICON_BY_KEY[ind.value] = ind.icon; });

function indIconFor(iconKey, value) {
  return IND_ICON_BY_KEY[iconKey] || IND_ICON_BY_KEY[value] || IND_ICON_BY_KEY.other;
}

function indFallbackCatalog() {
  return INDUSTRIES.map((ind, i) => ({
    value: ind.value,
    label: ind.label,
    cohort_n: IND_COHORT_N[ind.value] || 0,
    sort_order: i + 1,
    icon_key: ind.value,
  }));
}

function indSortCatalog(list) {
  return (list || []).slice().sort((a, b) => (a.sort_order || 0) - (b.sort_order || 0));
}

/** Login / profile email used to identify the customer (not DUNS). */
function indCustomerEmail(user) {
  const fromProfile = user && (user.email || user.emailAdd);
  if (fromProfile && String(fromProfile).indexOf("@") >= 0) return String(fromProfile).trim();
  const loginId = window.RBI_API && window.RBI_API.getLoginId && window.RBI_API.getLoginId();
  if (loginId && String(loginId).indexOf("@") >= 0) return String(loginId).trim();
  return "";
}

function indBusinessDisplayName(user) {
  const name = user && user.business_name && String(user.business_name).trim();
  return name || "Your Business";
}

function indOwnerDisplayName(user) {
  if (!user) return "Your Account";
  const full = (user.owner_name || [user.first_name, user.last_name].filter(Boolean).join(" ")).trim();
  return full || "Your Account";
}

function indCityDisplay(user) {
  const city = user && user.city && String(user.city).trim();
  return city || "";
}

/** Map profile/signup industry labels → Industry Insights catalog `value`. */
const PROFILE_TO_INSIGHTS_INDUSTRY = {
  food: "restaurant",
  restaurant: "restaurant",
  "restaurant & food services": "restaurant",
  retail: "retail",
  fintech: "other",
  healthcare: "healthcare",
  "healthcare & wellness": "healthcare",
  construction: "contractor",
  contractor: "contractor",
  "contractor & construction": "contractor",
  "auto services": "auto",
  auto: "auto",
  "beauty & personal care": "beauty",
  beauty: "beauty",
  "transportation & logistics": "logistics",
  logistics: "logistics",
  "professional services": "professional",
  professional: "professional",
  manufacturing: "other",
  hospitality: "other",
  other: "other",
};

function indValueFromProfile(user, catalog) {
  const raw = user && (user.industry || user.Industry);
  if (!raw) return null;
  const key = String(raw).trim().toLowerCase();
  const mapped = PROFILE_TO_INSIGHTS_INDUSTRY[key] || null;
  const list = catalog && catalog.length ? catalog : indFallbackCatalog();
  if (mapped && list.some((i) => i.value === mapped)) return mapped;
  // Direct match on catalog value or label
  const byValue = list.find((i) => i.value === key || String(i.value).toLowerCase() === key);
  if (byValue) return byValue.value;
  const byLabel = list.find((i) => String(i.label).toLowerCase() === key);
  return byLabel ? byLabel.value : null;
}

function indTopbarBusiness(user, profileLoaded) {
  return {
    name: indBusinessDisplayName(user),
    owner: indOwnerDisplayName(user),
    city: indCityDisplay(user),
    duns: (user && (user.duns || user.duns_number)) || "",
    dunsLoading: !profileLoaded,
    bank: "",
  };
}

/** True when the list-industries payload is usable. */
function isValidIndustriesPayload(raw) {
  const list = raw && (raw.industries || raw.data && raw.data.industries);
  return Array.isArray(list) && list.length > 0;
}

/** True when the insights payload has the minimum fields the dashboard needs. */
function isValidInsightsPayload(raw) {
  return !!(
    raw &&
    Array.isArray(raw.snapshot) &&
    raw.snapshot.length &&
    raw.inflow &&
    Array.isArray(raw.inflow.you) &&
    raw.inflow.you.length === 12 &&
    raw.outflow &&
    Array.isArray(raw.outflow.you) &&
    raw.balance &&
    Array.isArray(raw.balance.you)
  );
}

/** Normalize snake_case API payload → shape expected by ii-* components. */
function normalizeInsightsData(raw) {
  if (!raw) return null;
  const snapshot = (raw.snapshot || []).map((m) => ({
    ...m,
    trendDir: m.trendDir || m.trend_dir,
  }));
  const sbfeRaw = raw.sbfe || {};
  const repaymentRaw = raw.repayment || {};
  return {
    cohort: raw.cohort || { n: 0, spec: "" },
    snapshot,
    inflow: raw.inflow,
    outflow: raw.outflow,
    balance: raw.balance,
    bounce: raw.bounce || { count: 0, prev: 0, ind: 0, spark: [] },
    repayment: {
      avg: repaymentRaw.avg,
      pctInflow: repaymentRaw.pctInflow != null ? repaymentRaw.pctInflow : repaymentRaw.pct_inflow,
      indPct: repaymentRaw.indPct != null ? repaymentRaw.indPct : repaymentRaw.ind_pct,
      inflow: repaymentRaw.inflow,
      composition: repaymentRaw.composition || [],
    },
    sbfe: {
      you: sbfeRaw.you,
      ind: sbfeRaw.ind,
      min: sbfeRaw.min != null ? sbfeRaw.min : 300,
      max: sbfeRaw.max != null ? sbfeRaw.max : 1000,
      youDelta: sbfeRaw.youDelta != null ? sbfeRaw.youDelta : sbfeRaw.you_delta,
      indDelta: sbfeRaw.indDelta != null ? sbfeRaw.indDelta : sbfeRaw.ind_delta,
      youHist: sbfeRaw.youHist || sbfeRaw.you_hist || [],
      indHist: sbfeRaw.indHist || sbfeRaw.ind_hist || [],
      indRange: sbfeRaw.indRange || sbfeRaw.ind_range || [300, 1000],
    },
    flexLine: raw.flexLine || raw.flex_line || { you: 0, ind: 0, range: [0, 0] },
    buffer: raw.buffer || { you: 0, ind: 0, range: [0, 0] },
    factors: raw.factors || [],
    industryBuffer: raw.industryBuffer || raw.industry_buffer || [],
    fundingUse: raw.fundingUse || raw.funding_use || [],
    challenges: raw.challenges || [],
    topPerformers: raw.topPerformers || raw.top_performers || [],
    education: raw.education || [],
    months: Array.isArray(raw.months) && raw.months.length === 12 ? raw.months : null,
    industries: indSortCatalog(raw.industries || []),
    selectedIndustry: raw.selected_industry || raw.selectedIndustry || null,
    defaultIndustry: raw.default_industry || raw.defaultIndustry || null,
    asOf: raw.as_of || raw.asOf || null,
  };
}

function normalizeIndustriesResponse(raw) {
  const src = raw && raw.industries ? raw : (raw && raw.data) || raw || {};
  const list = indSortCatalog(src.industries || []);
  return {
    industries: list,
    defaultIndustry: src.default_industry || src.defaultIndustry || (list[0] && list[0].value) || null,
  };
}

function buildMockInsightsBundle(industryValue, formOverrides) {
  const fallbackList = indFallbackCatalog();
  const industry = industryValue || fallbackList[0].value;
  const industryLabel = (fallbackList.find((i) => i.value === industry) || fallbackList[0]).label;
  const form = { ...IND_MOCK_DEFAULTS, ...(formOverrides || {}), industry };
  const bm = computeBenchmarks(form);
  const D = buildInsightsData(industry, industryLabel, form, bm);
  return {
    ...D,
    months: II_MONTHS_FALLBACK.slice(),
    industries: fallbackList,
    selectedIndustry: industry,
    defaultIndustry: fallbackList[0].value,
    asOf: new Date().toISOString().slice(0, 10),
  };
}

async function fetchIndustriesCatalog() {
  if (!indLiveApiEnabled()) {
    return {
      ok: false,
      data: null,
      error: "Live Industry Insights API is off (RBI_ENV.industryInsightsLive).",
    };
  }
  if (!window.RBI_API || !window.RBI_API.listIndustries) {
    return { ok: false, data: null, error: "API unavailable" };
  }
  try {
    const res = await window.RBI_API.listIndustries();
    if (res.ok && isValidIndustriesPayload(res.data)) {
      return { ok: true, data: normalizeIndustriesResponse(res.data), error: null };
    }
    const msg =
      (res.data && (res.data.errorMessage || res.data.message || res.data.error)) ||
      "Unable to load industries.";
    return { ok: false, data: null, error: msg };
  } catch (err) {
    return { ok: false, data: null, error: (err && err.message) || "Network error" };
  }
}

async function fetchIndustryInsights(email, industry) {
  if (!indLiveApiEnabled()) {
    return {
      ok: false,
      data: null,
      error: "Live Industry Insights API is off (RBI_ENV.industryInsightsLive).",
    };
  }
  if (!window.RBI_API || !window.RBI_API.industryInsights) {
    return { ok: false, data: null, error: "API unavailable" };
  }
  if (!email || !industry) {
    return { ok: false, data: null, error: "Email and industry are required." };
  }
  try {
    const res = await window.RBI_API.industryInsights({ email, industry });
    if (res.ok && isValidInsightsPayload(res.data)) {
      return { ok: true, data: normalizeInsightsData(res.data), error: null };
    }
    const msg =
      (res.data && (res.data.errorMessage || res.data.message || res.data.error)) ||
      "Unable to load industry insights.";
    return { ok: false, data: null, error: msg };
  } catch (err) {
    return { ok: false, data: null, error: (err && err.message) || "Network error" };
  }
}

// ── Chart-format helpers ───────────────────────────────────────────────────

const iiUSD = (n, short) => short
  ? (Math.abs(n) >= 1000 ? "$" + (n / 1000).toFixed(n % 1000 === 0 ? 0 : 1) + "K" : "$" + Math.round(n))
  : "$" + Math.round(n).toLocaleString("en-US");
const iiFmt = (n, unit, short) => unit === "$" ? iiUSD(n, short) : unit === "%" ? Math.round(n) + "%" : Math.round(n).toLocaleString("en-US");

function niceBounds(vals, pad) {
  pad = pad == null ? 0.12 : pad;
  const lo = Math.min(...vals), hi = Math.max(...vals);
  const span = hi - lo || 1;
  return [lo - span * pad, hi + span * pad];
}
function linePath(vals, W, H, lo, hi, pl, pr, pt, pb) {
  const iw = W - pl - pr, ih = H - pt - pb;
  return vals.map((v, i) => {
    const x = pl + (iw * i) / (vals.length - 1);
    const y = pt + ih - ((v - lo) / (hi - lo)) * ih;
    return (i ? "L" : "M") + x.toFixed(1) + " " + y.toFixed(1);
  }).join(" ");
}
const ptAt = (vals, i, W, H, lo, hi, pl, pr, pt, pb) => {
  const iw = W - pl - pr, ih = H - pt - pb;
  return [pl + (iw * i) / (vals.length - 1), pt + ih - ((vals[i] - lo) / (hi - lo)) * ih];
};

// ── Chart primitives (hand-built SVG, no chart library) ───────────────────

function IIDualLine({ months, a, b, labelA, labelB, colorA, colorB, unit, height, summary }) {
  colorA = colorA || "var(--gg-100)"; colorB = colorB || "var(--tt-40)"; unit = unit == null ? "$" : unit; height = height || 250;
  const [hi_, setHi] = useIndState(null);
  const W = 900, H = height, pl = 62, pr = 16, pt = 16, pb = 34;
  const [lo, hi] = niceBounds([...a, ...b]);
  const ticks = [0, 0.25, 0.5, 0.75, 1].map(f => lo + (hi - lo) * f);
  const iw = W - pl - pr;
  return (
    <div className="ii-chart">
      <div className="ii-legend">
        <span className="ii-lg"><i style={{ background: colorA }} />{labelA}</span>
        {/* <span className="ii-lg"><i style={{ background: colorB }} className="dash" />{labelB}</span> */}
        {/* {summary ? <span className={"ii-trend " + (summary.dir || "up")}>{summary.dir === "down" ? "▾" : "▴"} {summary.text}</span> : null} */}
      </div>
      <div className="ii-chart-wrap" onMouseLeave={() => setHi(null)}>
        <svg viewBox={`0 0 ${W} ${H}`} className="ii-svg" preserveAspectRatio="none"
          onMouseMove={(e) => {
            const r = e.currentTarget.getBoundingClientRect();
            const x = ((e.clientX - r.left) / r.width) * W;
            const i = Math.round(((x - pl) / iw) * (a.length - 1));
            setHi(Math.max(0, Math.min(a.length - 1, i)));
          }}>
          {ticks.map((t, i) => {
            const y = pt + (H - pt - pb) * (1 - i / 4);
            return <g key={i}><line x1={pl} x2={W - pr} y1={y} y2={y} className="ii-grid" /><text x={pl - 10} y={y + 4} className="ii-axis" textAnchor="end">{iiFmt(t, unit, true)}</text></g>;
          })}
          {months.map((m, i) => <text key={m} x={pl + (iw * i) / (months.length - 1)} y={H - 10} className="ii-axis" textAnchor="middle">{m}</text>)}
          {/* <path d={linePath(b, W, H, lo, hi, pl, pr, pt, pb)} fill="none" stroke={colorB} strokeWidth="2" strokeDasharray="5 4" /> */}
          <path d={linePath(a, W, H, lo, hi, pl, pr, pt, pb)} fill="none" stroke={colorA} strokeWidth="2.6" strokeLinejoin="round" />
          {hi_ != null ? (() => {
            const [xa, ya] = ptAt(a, hi_, W, H, lo, hi, pl, pr, pt, pb);
            const [, yb] = ptAt(b, hi_, W, H, lo, hi, pl, pr, pt, pb);
            return <g><line x1={xa} x2={xa} y1={pt} y2={H - pb} className="ii-guide" />
              <circle cx={xa} cy={yb} r="4.5" fill="var(--infinity)" stroke={colorB} strokeWidth="2" />
              <circle cx={xa} cy={ya} r="5" fill={colorA} stroke="var(--infinity)" strokeWidth="2" /></g>;
          })() : null}
        </svg>
        {hi_ != null ? (
          <div className="ii-tip" style={{ left: `calc(${((pl + (iw * hi_) / (a.length - 1)) / W) * 100}% )`, transform: hi_ > a.length / 2 ? "translate(-104%,0)" : "translate(4%,0)" }}>
            <div className="ii-tip-m">{months[hi_]}</div>
            <div className="ii-tip-r"><span style={{ background: colorA }} />{labelA}<b>{iiFmt(a[hi_], unit)}</b></div>
            <div className="ii-tip-r"><span style={{ background: colorB }} />{labelB}<b>{iiFmt(b[hi_], unit)}</b></div>
          </div>
        ) : null}
      </div>
    </div>
  );
}

function IIAreaBand({ months, series, lo: bandLo, hi: bandHi, label, bandLabel }) {
  const [hi_, setHi] = useIndState(null);
  const W = 900, H = 250, pl = 62, pr = 16, pt = 16, pb = 34;
  const [lo, hi] = niceBounds([...series, ...bandLo, ...bandHi]);
  const iw = W - pl - pr, ih = H - pt - pb;
  const yOf = v => pt + ih - ((v - lo) / (hi - lo)) * ih;
  const xOf = i => pl + (iw * i) / (months.length - 1);
  const band = bandHi.map((v, i) => `${i ? "L" : "M"}${xOf(i)} ${yOf(v)}`).join(" ") + " " + bandLo.slice().reverse().map((v, i) => `L${xOf(bandLo.length - 1 - i)} ${yOf(v)}`).join(" ") + " Z";
  return (
    <div className="ii-chart">
      <div className="ii-legend">
        <span className="ii-lg"><i style={{ background: "var(--fp-100)" }} />{label}</span>
        {/* <span className="ii-lg"><i className="band" />{bandLabel}</span> */}
      </div>
      <div className="ii-chart-wrap" onMouseLeave={() => setHi(null)}>
        <svg viewBox={`0 0 ${W} ${H}`} className="ii-svg" preserveAspectRatio="none"
          onMouseMove={(e) => { const r = e.currentTarget.getBoundingClientRect(); const x = ((e.clientX - r.left) / r.width) * W; setHi(Math.max(0, Math.min(months.length - 1, Math.round(((x - pl) / iw) * (months.length - 1))))); }}>
          <defs><linearGradient id="iiAreaG" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stopColor="#04C49E" stopOpacity="0.28" /><stop offset="100%" stopColor="#04C49E" stopOpacity="0.02" /></linearGradient></defs>
          {[0, 0.25, 0.5, 0.75, 1].map((f, i) => { const y = pt + ih * (1 - f); return <g key={i}><line x1={pl} x2={W - pr} y1={y} y2={y} className="ii-grid" /><text x={pl - 10} y={y + 4} className="ii-axis" textAnchor="end">{iiUSD(lo + (hi - lo) * f, true)}</text></g>; })}
          {months.map((m, i) => <text key={m} x={xOf(i)} y={H - 10} className="ii-axis" textAnchor="middle">{m}</text>)}
          {/* <path d={band} fill="var(--gg-10)" stroke="var(--gg-20)" strokeWidth="1" /> */}
          <path d={series.map((v, i) => `${i ? "L" : "M"}${xOf(i)} ${yOf(v)}`).join(" ") + ` L${xOf(series.length - 1)} ${pt + ih} L${pl} ${pt + ih} Z`} fill="url(#iiAreaG)" />
          <path d={series.map((v, i) => `${i ? "L" : "M"}${xOf(i)} ${yOf(v)}`).join(" ")} fill="none" stroke="var(--fp-100)" strokeWidth="2.6" />
          {hi_ != null ? <g><line x1={xOf(hi_)} x2={xOf(hi_)} y1={pt} y2={pt + ih} className="ii-guide" /><circle cx={xOf(hi_)} cy={yOf(series[hi_])} r="5" fill="var(--fp-100)" stroke="var(--infinity)" strokeWidth="2" /></g> : null}
        </svg>
        {hi_ != null ? (
          <div className="ii-tip" style={{ left: `${(xOf(hi_) / W) * 100}%`, transform: hi_ > months.length / 2 ? "translate(-104%,0)" : "translate(4%,0)" }}>
            <div className="ii-tip-m">{months[hi_]}</div>
            <div className="ii-tip-r"><span style={{ background: "var(--fp-100)" }} />{label}<b>{iiUSD(series[hi_])}</b></div>
            {/* <div className="ii-tip-r"><span className="band" />Typical range<b>{iiUSD(bandLo[hi_], true)}–{iiUSD(bandHi[hi_], true)}</b></div> */}
          </div>
        ) : null}
      </div>
    </div>
  );
}

function IISpark({ values, color, w, h }) {
  color = color || "var(--gg-100)"; w = w || 120; h = h || 34;
  const [lo, hi] = niceBounds(values, 0.2);
  return <svg viewBox={`0 0 ${w} ${h}`} className="ii-spark" preserveAspectRatio="none"><path d={linePath(values, w, h, lo, hi, 2, 2, 4, 4)} fill="none" stroke={color} strokeWidth="2" /></svg>;
}

function IIGauge({ value, min, max, marker, markerLabel }) {
  const W = 340, H = 196, cx = W / 2, cy = 172, r = 132;
  const ang = v => Math.PI * (1 - (v - min) / (max - min));
  const pol = (a, rr) => [cx + rr * Math.cos(a), cy - rr * Math.sin(a)];
  const arc = (from, to, rr) => { const p1 = pol(ang(from), rr), p2 = pol(ang(to), rr); return `M${p1[0]} ${p1[1]} A${rr} ${rr} 0 0 1 ${p2[0]} ${p2[1]}`; };
  const mp = pol(ang(marker), r);
  const mp2 = pol(ang(marker), r - 26);
  return (
    <div className="ii-gauge">
      <svg viewBox={`0 0 ${W} ${H}`}>
        <defs><linearGradient id="iiGaugeG" x1="0" y1="0" x2="1" y2="0"><stop offset="0%" stopColor="#0040BA" /><stop offset="100%" stopColor="#04C49E" /></linearGradient></defs>
        <path d={arc(min, max, r)} fill="none" stroke="var(--tt-10)" strokeWidth="18" strokeLinecap="round" />
        <path d={arc(min, value, r)} fill="none" stroke="url(#iiGaugeG)" strokeWidth="18" strokeLinecap="round" />
        <line x1={mp[0]} y1={mp[1]} x2={mp2[0]} y2={mp2[1]} stroke="var(--trust-tech)" strokeWidth="2.5" />
        <text x={cx} y={cy - 44} textAnchor="middle" className="ii-gauge-val">{value}</text>
        <text x={cx} y={cy - 18} textAnchor="middle" className="ii-gauge-cap">SBFE Score</text>
        <text x={cx - r} y={cy + 22} textAnchor="middle" className="ii-axis">{min}</text>
        <text x={cx + r} y={cy + 22} textAnchor="middle" className="ii-axis">{max}</text>
      </svg>
      {/* <p className="ii-gauge-note"><b>{markerLabel}</b></p> */}
    </div>
  );
}

function IIBullet({ min, max, you, ind, unit, youLabel, indLabel, bandLabel, band }) {
  unit = unit || ""; youLabel = youLabel || "Your business"; indLabel = indLabel || "Industry average";
  const pct = v => ((v - min) / (max - min)) * 100;
  return (
    <div className="ii-bullet">
      {bandLabel ? <div className="ii-bullet-bandcap">{bandLabel} {iiFmt(band[0], unit, true)}–{iiFmt(band[1], unit, true)}</div> : null}
      <div className="ii-bullet-tier">
        {you != null ? <span className="ii-bullet-pill you" style={{ left: pct(you) + "%" }}>{youLabel} {iiFmt(you, unit, true)}</span> : null}
      </div>
      <div className="ii-bullet-track">
        {band ? <div className="ii-bullet-band" style={{ left: pct(band[0]) + "%", width: (pct(band[1]) - pct(band[0])) + "%" }} /> : null}
        {you != null ? <div className="ii-bullet-fill" style={{ width: pct(you) + "%" }} /> : null}
        {/* <div className="ii-bullet-ind" style={{ left: pct(ind) + "%" }} /> */}
        {you != null ? <div className="ii-bullet-you" style={{ left: pct(you) + "%" }} /> : null}
      </div>
      {/* <div className="ii-bullet-tier">
        <span className="ii-bullet-pill ind" style={{ left: pct(ind) + "%" }}>{indLabel} {iiFmt(ind, unit, true)}</span>
      </div> */}
      <div className="ii-bullet-scale"><span>{iiFmt(min, unit, true)}</span><span>{iiFmt(max, unit, true)}</span></div>
    </div>
  );
}

function IIHBars({ rows, unit, max }) {
  unit = unit || "$";
  const m = max || Math.max(...rows.map(r => r.value)) * 1.15;
  return (
    <div className="ii-hbars">
      {rows.map(r => (
        <div key={r.label} className="ii-hbar">
          <div className="ii-hbar-lab">{r.label}</div>
          <div className="ii-hbar-track"><div className="ii-hbar-fill" style={{ width: (r.value / m) * 100 + "%", background: r.color || "var(--gg-100)" }} /></div>
          <div className="ii-hbar-val">{iiFmt(r.value, unit, true)}</div>
        </div>
      ))}
    </div>
  );
}

function IIStackBar({ total, parts }) {
  return (
    <div className="ii-stack">
      <div className="ii-stack-bar">
        {parts.map(p => <div key={p.label} className="ii-stack-seg" style={{ width: Math.max(0, (p.value / total) * 100) + "%", background: p.color }} title={`${p.label} · ${iiUSD(p.value)}`} />)}
      </div>
      <div className="ii-stack-key">
        {parts.map(p => <span key={p.label} className="ii-stack-k"><i style={{ background: p.color }} />{p.label}<b>{iiUSD(p.value, true)}</b><em>{Math.round((p.value / total) * 100)}%</em></span>)}
      </div>
    </div>
  );
}

function IIDonut({ slices }) {
  const total = slices.reduce((s, x) => s + x.value, 0);
  const R = 84, r = 54, cx = 100, cy = 100;
  let acc = -Math.PI / 2;
  return (
    <div className="ii-donut">
      <svg viewBox="0 0 200 200">
        {slices.map(s => {
          const a0 = acc, a1 = acc + (s.value / total) * Math.PI * 2; acc = a1;
          const large = a1 - a0 > Math.PI ? 1 : 0;
          const p = (rr, a) => [cx + rr * Math.cos(a), cy + rr * Math.sin(a)];
          const p1 = p(R, a0), p2 = p(R, a1), p3 = p(r, a1), p4 = p(r, a0);
          return <path key={s.label} d={`M${p1[0]} ${p1[1]} A${R} ${R} 0 ${large} 1 ${p2[0]} ${p2[1]} L${p3[0]} ${p3[1]} A${r} ${r} 0 ${large} 0 ${p4[0]} ${p4[1]} Z`} fill={s.color} />;
        })}
      </svg>
      <div className="ii-donut-key">
        {slices.map(s => <div key={s.label} className="ii-donut-k"><i style={{ background: s.color }} /><span>{s.label}</span><b>{s.value}%</b></div>)}
      </div>
    </div>
  );
}

function IIColumns({ months, values, unit, color }) {
  unit = unit || "%"; color = color || "var(--gg-60)";
  const max = Math.max(...values) * 1.15;
  return (
    <div className="ii-cols">
      {values.map((v, i) => (
        <div key={i} className="ii-col">
          <div className="ii-col-bar" style={{ height: (v / max) * 100 + "%", background: color }}><span>{v}{unit}</span></div>
          <div className="ii-col-lab">{months[i]}</div>
        </div>
      ))}
    </div>
  );
}

// ── Icons for challenge / education tiles ─────────────────────────────────

const InsIcon = ({ d, size }) => <svg width={size || 18} height={size || 18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">{d}</svg>;
const IND_ICONS = {
  labor: <><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M23 21v-2a4 4 0 0 0-3-3.87" /></>,
  inventory: <><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" /><path d="M3.3 7 12 12l8.7-5" /><path d="M12 22V12" /></>,
  bolt: <><circle cx="12" cy="12" r="4" /><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2" /></>,
  flag: <><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6" /><path d="M10 11v5M14 11v5" /></>,
  cash: <><path d="M12 1v22" /><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" /></>,
  score: <><path d="M3 3v18h18" /><path d="M7 15l4-4 3 3 5-6" /></>,
  funding: <><rect x="2" y="7" width="20" height="14" rx="2" /><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2" /><path d="M2 12h20" /></>,
};

// ── MOCK CONTROLS PANEL ───────────────────────────────────────────────────

function IndMockControls({ controls, onChange, onClose }) {
  const revPct = (controls.revenue / 500000 * 100).toFixed(2);
  const sliderBg = `linear-gradient(to right, var(--growth-galaxy) 0%, var(--growth-galaxy) ${revPct}%, var(--border-strong) ${revPct}%, var(--border-strong) 100%)`;

  return (
    <div className="ind-mock-overlay" onMouseDown={e => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="ind-mock-panel">
        <div className="ind-mock-header">
          <span className="ind-mock-title">Mock Controls</span>
          <button className="ind-mock-close" onClick={onClose}>✕</button>
        </div>
        <div className="ind-mock-body">
          <div className="ind-mock-section-label">Business Profile</div>

          <div className="ind-mock-field">
            <label className="ind-mock-label">Monthly Revenue — <strong>${Number(controls.revenue).toLocaleString()}</strong></label>
            <input className="ind-mock-range" type="range" min="0" max="500000" step="1000"
              value={controls.revenue}
              style={{ background: sliderBg }}
              onChange={e => onChange("revenue", Number(e.target.value))} />
            <div className="ind-mock-range-bounds"><span>$0</span><span>$500K</span></div>
          </div>

          <div className="ind-mock-field">
            <label className="ind-mock-label">Years in Business</label>
            <input className="ind-mock-input" type="number" min="0" max="50" step="0.5"
              value={controls.years} onChange={e => onChange("years", e.target.value)} />
          </div>

          <div className="ind-mock-field">
            <label className="ind-mock-label">Business Credit Score</label>
            <select className="ind-mock-select" value={controls.credit} onChange={e => onChange("credit", e.target.value)}>
              {CREDIT_RANGES.map(r => <option key={r.value} value={r.value}>{r.label}</option>)}
            </select>
          </div>

          <div className="ind-mock-field">
            <label className="ind-mock-label">Business Region</label>
            <input className="ind-mock-input" type="text" placeholder="e.g. California"
              value={controls.region} onChange={e => onChange("region", e.target.value)} />
          </div>

          <div className="ind-mock-section-label">Sections</div>
          <div className="ind-mock-field">
            <label className="ind-mock-label" style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }}>
              <input type="checkbox" checked={controls.showHistory} onChange={e => onChange("showHistory", e.target.checked)} />
              Show SBFE score history
            </label>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Hero ───────────────────────────────────────────────────────────────────

function InsHero({ industry, industryLabel, onChangeIndustry, onBack, cohortN, industries, isSample }) {
  const options = industries && industries.length ? industries : indFallbackCatalog();
  return (
    <div className="ii-hero">
      <div>
        <p className="ii-eb">Industry insights &amp; benchmarking </p>
        {/* · cohort of {(cohortN || 0).toLocaleString("en-US")}</p> */}
        <h1 className="ii-h1">Your Business vs. the <em>{industryLabel}</em> Industry</h1>
        <p className="ii-sub">Understand how your business financial factors that may influence funding readiness.</p>
      </div>
      {/* <div className="ii-hero-right">
        {isSample ? <span className="ii-demo-pill"><i />Sample data · illustrative</span> : null}
        <div className="ii-select">
          <select value={industry} onChange={e => onChangeIndustry(e.target.value)} aria-label="Change industry">
            {options.map(ind => <option key={ind.value} value={ind.value}>{ind.label}</option>)}
          </select>
        </div>
        <button className="ind-reset-btn" onClick={onBack}>← All Industries</button>
      </div> */}
    </div>
  );
}

// ── Section 1 — snapshot ──────────────────────────────────────────────────

function InsSnapshot({ D }) {
  const badgeLabel = { above: "Above Average", near: "Near Average", below: "Below Average" };
  return (
    <div className="ii-stack-v">
      <div className="ii-sec-hd" style={{ marginBottom: 0 }}>
        <span className="ii-scope you">Your business · vs industry</span>
        <h2>Your Business Snapshot</h2>
        {/* <h2>Business vs. Industry Snapshot</h2> */}
        {/* <p>{D.cohort.spec} · n = {(D.cohort.n || 0).toLocaleString("en-US")}.</p> */}
      </div>
      <div className="ii-kpis">
        {D.snapshot.slice(0, 4).map(m => {
          const diff = m.you - m.ind;
          const sign = diff > 0 ? "+" : "−";
          const diffTxt = m.unit === "$" ? sign + iiUSD(Math.abs(diff), true) : m.unit === "%" ? sign + Math.abs(diff) + " pts" : sign + Math.abs(diff) + " points";
          return (
            <div key={m.key} className="ii-kpi">
              <div className="ii-kpi-lab">{m.label}</div>
              <div className="ii-kpi-val">{iiFmt(m.you, m.unit)}</div>

              {/* Hidden for now */}
              {/* <div className="ii-kpi-row"><span>Industry average</span><b>{iiFmt(m.ind, m.unit, true)}</b></div>
              <div className="ii-kpi-foot">
                <span className={"ii-delta " + (m.status === "below" ? "down" : "up")}>{diffTxt}</span>
                <span className={"ii-badge " + m.status}>{badgeLabel[m.status]}</span>
              </div>
              <div className="ii-kpi-row" style={{ borderTop: "none", paddingTop: 0, fontSize: 11.5, color: "var(--fg-3)" }}>
                <span>{m.note}</span><span className={"ii-delta " + m.trendDir}>{m.trendDir === "up" ? "▴" : "▾"} {m.trend}</span>
              </div> */}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ── Section 2 — cash flow health ──────────────────────────────────────────

function InsCashFlow({ D, months }) {
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope you">Your business · vs industry</span>
        <h2>How Is Your Cash Flow?</h2>
        {/* <h2>How Your Cash Flow Compares</h2> */}
        {/* <p>See how your business's cash flow patterns flows in your industry.</p> */}
        {/* <p>See how your business's cash flow patterns compare with similar businesses in your industry.</p> */}
      </div>
      <div className="ii-stack-v">
        <div className="ii-panel">
          <div className="ii-panel-hd"><div>
            <h3>Monthly cash inflow</h3>
            <p>Total deposits per month of your business.</p>
            {/* <p>Total deposits per month, your business against the cohort average.</p> */}
          </div>
          </div>
          <IIDualLine months={months} a={D.inflow.you} b={D.inflow.ind} labelA="Your business" labelB="Industry average"
            summary={{
              text: `${D.inflow.you[11] >= D.inflow.you[0] ? "Up" : "Down"} ${Math.abs(((D.inflow.you[11] - D.inflow.you[0]) / D.inflow.you[0]) * 100).toFixed(1)}% over 12 months`,
              dir: D.inflow.you[11] >= D.inflow.you[0] ? "up" : "down"
            }} />
        </div>
        <div className="ii-panel">
          <div className="ii-panel-hd">
            <div>
              <h3>Monthly cash outflow</h3>
              <p>Total spend per month.</p>
              {/* <p>Total spend per month, your business against the cohort average.</p> */}
            </div>
          </div>
          <IIDualLine months={months} a={D.outflow.you} b={D.outflow.ind} labelA="Your business" labelB="Industry average" colorA="var(--color-warning)"
            summary={{
              text: `${D.outflow.you[11] >= D.outflow.you[0] ? "Up" : "Down"} ${Math.abs(((D.outflow.you[11] - D.outflow.you[0]) / D.outflow.you[0]) * 100).toFixed(1)}% over 12 months`,
              dir: "down"
            }} />
        </div>
        <div className="ii-panel">
          <div className="ii-panel-hd"><div><h3>Average monthly starting balance</h3>
            <p>Your month-opening balance</p>
            {/* <p>Your month-opening balance against the typical industry range.</p> */}
          </div>
          </div>
          <IIAreaBand months={months} series={D.balance.you} lo={D.balance.lo} hi={D.balance.hi} label="Your starting balance" bandLabel="Typical industry range" />
          <p className="ii-note">{D.balance.you[11] < D.balance.lo[11]
            ? "Your starting balance has recently dipped below the bottom of the typical industry range — a key driver of the Cash Buffer flag below."
            : "Your starting balance has tracked within the typical industry range over the last 12 months."}</p>
        </div>

        {/* Hidden for now */}
        {false &&
          <div className="ii-grid2">
            <div className="ii-panel">
              <div className="ii-panel-hd">
                <div><h3>Bounce payments</h3><p>Returned or failed payments in the last 90 days.</p></div>
                <span className={"ii-badge " + (D.bounce.count <= D.bounce.ind ? "above" : "near")}>{D.bounce.count <= D.bounce.ind ? "Above Average" : "Near Average"}</span>
              </div>
              <div className="ii-mini-row">
                <div className="ii-mini-val">{D.bounce.count}</div>
                <IISpark values={D.bounce.spark} color="var(--color-warning)" />
              </div>
              <div className="ii-defs">
                <div className="ii-def"><span>Change from prior period</span><b style={{ color: D.bounce.count <= D.bounce.prev ? "#0A7D67" : "#B85C1E" }}>{D.bounce.count - D.bounce.prev >= 0 ? "+" : "−"}{Math.abs(D.bounce.count - D.bounce.prev)} vs. {D.bounce.prev}</b></div>
                <div className="ii-def"><span>Industry average</span><b>{D.bounce.ind}</b></div>
              </div>
              <p className="ii-note">{D.bounce.count < D.bounce.prev ? `Down from ${D.bounce.prev} last quarter. ` : ""}Returned payments are read as a short-term liquidity signal, so the trend matters more than the count.</p>
            </div>
            <div className="ii-panel">
              <div className="ii-panel-hd">
                <div><h3>Repayment deductions</h3><p>Average monthly repayments as a share of inflow.</p></div>
                <span className={"ii-badge " + (D.repayment.pctInflow > D.repayment.indPct ? "below" : "above")}>{D.repayment.pctInflow > D.repayment.indPct ? "Above Average" : "Below Average"}</span>
              </div>
              <div className="ii-mini-row">
                <div className="ii-mini-val">{iiUSD(D.repayment.avg)}</div>
                <div style={{ textAlign: "right", fontSize: 12, color: "var(--fg-2)" }}><b style={{ fontSize: 15, color: "var(--fg-1)" }}>{D.repayment.pctInflow}%</b><br />of monthly inflow</div>
              </div>
              <div className="ii-defs"><div className="ii-def"><span>Industry average share of inflow</span><b>{D.repayment.indPct}%</b></div></div>
              <div style={{ marginTop: 16 }}>
                <div className="ii-kpi-lab" style={{ marginBottom: 10 }}>Where your monthly inflow goes</div>
                <IIStackBar total={D.repayment.inflow} parts={D.repayment.composition} />
              </div>
              <p className="ii-note">Monthly inflow {iiUSD(D.repayment.inflow)} · a higher repayment share leaves less room for new financing.</p>
            </div>
          </div>
        }
      </div>
    </section>
  );
}

// ── Section 3 — credit / SBFE ─────────────────────────────────────────────

function InsCredit({ D, months, showHistory }) {
  const S = D.sbfe;
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope you">Your business · vs industry</span>
        <h2>Your Business Credit</h2>
        {/* <h2>Your Business Credit vs. Your Industry</h2> */}
        {/* <p>Understand how your business credit profile compares with similar businesses.</p> */}
      </div>
      <div className="ii-grid2">
        <div className="ii-panel">
          <IIGauge value={S.you} min={S.min} max={S.max} marker={S.ind} markerLabel={`${S.you >= S.ind ? "+" : "−"}${Math.abs(S.you - S.ind)} points ${S.you >= S.ind ? "above" : "below"} the industry average of ${S.ind}`} />
        </div>
        <div className="ii-panel">
          <div className="ii-panel-hd"><div><h3>Where you sit on the scale</h3><p>SBFE scores run {S.min}–{S.max}. The shaded area is the typical industry range.</p></div></div>
          <IIBullet min={S.min} max={S.max} you={S.you} ind={S.ind} band={S.indRange} bandLabel="Typical industry range" />
          <div className="ii-defs" style={{ marginTop: 26 }}>
            <div className="ii-def"><span>Your 12-month change</span><b style={{ color: "#0A7D67" }}>+{S.youDelta} points</b></div>
            {/* Hidden for now */}
            {/* <div className="ii-def"><span>Industry 12-month change</span><b>+{S.indDelta} points</b></div> */}
          </div>
          {/* {S.youDelta >= S.indDelta ? (
            <div className="ii-callout"><span>▴</span><span>Your score improved <b>{S.youDelta - S.indDelta} points more</b> than similar businesses over the same period.</span></div>
          ) : (
            <div className="ii-callout info"><span>ⓘ</span><span>Industry scores rose <b>+{S.indDelta} points</b> on average, {S.indDelta - S.youDelta} more than your business, over the last 12 months.</span></div>
          )} */}
        </div>
      </div>
      {/* {showHistory ? (
        <div className="ii-panel" style={{ marginTop: 20 }}>
          <div className="ii-panel-hd"><div><h3>Score trend, last 12 months</h3><p>Your SBFE score against the industry average.</p></div></div>
          <IIDualLine months={months} a={S.youHist} b={S.indHist} labelA="Your SBFE score" labelB="Industry average" unit=""
            summary={{ text: `+${S.youDelta} points · ${S.youDelta >= S.indDelta ? "widening gap vs. industry" : "narrowing gap vs. industry"}`, dir: "up" }} />
        </div>
      ) : null} */}
    </section>
  );
}

// ── Section 4 — working capital ───────────────────────────────────────────

function InsWorkingCapital({ D }) {
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope you">Your business · vs industry</span>
        <h2>How Businesses Use Available Working Capital</h2>
        <p>Understand how your working capital usage compares with similar businesses.</p>
      </div>
      <div className="ii-grid2">
        <div className="ii-panel">
          <div className="ii-panel-hd"><div><h3>Average flex line amount</h3><p>Available working capital line, you against the industry average.</p></div></div>
          <IIHBars rows={[{ label: "Your business", value: D.flexLine.you, color: "var(--gg-100)" }, { label: "Industry average", value: D.flexLine.ind, color: "var(--tt-40)" }]} />
          <div className="ii-defs">
            <div className="ii-def"><span>Industry typical range</span><b>{iiUSD(D.flexLine.range[0], true)}–{iiUSD(D.flexLine.range[1], true)}</b></div>
            <div className="ii-def"><span>Difference vs. industry</span><b style={{ color: D.flexLine.you >= D.flexLine.ind ? "#0A7D67" : "#B85C1E" }}>{D.flexLine.you >= D.flexLine.ind ? "+" : "−"}{iiUSD(Math.abs(D.flexLine.you - D.flexLine.ind), true)}</b></div>
          </div>
        </div>
        <div className="ii-panel">
          <div className="ii-panel-hd">
            <div><h3>Cash buffer utilization</h3><p>Share of available working capital currently in use.</p></div>
            <span className={"ii-badge " + (D.buffer.you <= D.buffer.ind + 5 ? "near" : "below")}>{D.buffer.you <= D.buffer.ind + 5 ? "Near Average" : "Above Average"}</span>
          </div>
          <div className="ii-mini-row" style={{ marginBottom: 10 }}>
            <div className="ii-mini-val">{D.buffer.you}%</div>
            <div style={{ fontSize: 12, color: "var(--fg-2)", textAlign: "right" }}>Industry average <b style={{ color: "var(--fg-1)" }}>{D.buffer.ind}%</b></div>
          </div>
          <IIBullet min={0} max={100} you={D.buffer.you} ind={D.buffer.ind} unit="%" band={D.buffer.range} bandLabel="Typical range" />
          <p className="ii-note">Higher utilization may indicate greater reliance on available working capital to cover day-to-day operations. It is not automatically negative — but sustained high usage alongside a thin cash buffer is a pattern lenders notice.</p>
        </div>
      </div>
    </section>
  );
}

// ── Section 5 — funding readiness factors ─────────────────────────────────

function InsFactors({ D }) {
  const statusLabel = { strong: "Strong", moderate: "Moderate", attention: "Needs Attention" };
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope you">Your business · vs industry</span>
        <h2>What May Influence Your Funding Readiness</h2>
        <p>These are the financial factors lenders most often review.</p>
        {/* <p>Each is compared with similar businesses in your industry — none is a score or a decision.</p> */}
      </div>
      <div className="ii-factors">
        {D.factors.map(f => (
          <div key={f.key} className="ii-factor" onClick={() => window.open(f.link, "_blank", "noopener,noreferrer")}>
            <h4>{f.label}</h4>
            <span className={"ii-badge " + f.status} style={{ alignSelf: "flex-start" }}>{statusLabel[f.status]}</span>
            <p>{f.note}</p>
            {/* Hidden for now */}
            {/* <div className="ii-factor-cmp">
              <b>{f.you}</b>
              <span>{f.ind}</span>
            </div> */}
            <span className="ii-tile-cta" onClick={() => window.open(f.link, "_blank", "noopener,noreferrer")}>Learn More →</span>
          </div>
        ))}
      </div>
      <div className="ii-callout info">
        <span>ⓘ</span>
        <span>These factors are shown for education. Revenued does not publish a single overall funding readiness score, because no approved scoring model combines these signals.</span>
      </div>
    </section>
  );
}

// ── Section 6 — industry performance ──────────────────────────────────────

function InsIndustryPerformance({ D, months, industryLabel }) {
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope ind">Industry only</span>
        <h2>How the Industry Is Performing</h2>
        <p>Aggregate trends across {(D.cohort.n || 0).toLocaleString("en-US")} {industryLabel} businesses over the last 12 months.</p>
      </div>
      <div className="ii-stack-v">
        <div className="ii-grid2">
          <div className="ii-panel">
            <div className="ii-panel-hd"><div><h3>Industry cash inflow</h3><p>Average monthly deposits across the cohort.</p></div></div>
            <IIDualLine months={months} a={D.inflow.ind} b={D.inflow.ind.map(v => v * 0.9)} labelA="Industry average" labelB="Prior year" colorA="var(--gg-100)" summary={{ text: `+${Math.abs(((D.inflow.ind[11] - D.inflow.ind[0]) / D.inflow.ind[0]) * 100).toFixed(1)}% vs. 12 months ago`, dir: "up" }} />
          </div>
          <div className="ii-panel">
            <div className="ii-panel-hd"><div><h3>Industry cash outflow</h3><p>Average monthly spend across the cohort.</p></div></div>
            <IIDualLine months={months} a={D.outflow.ind} b={D.outflow.ind.map(v => v * 0.9)} labelA="Industry average" labelB="Prior year" colorA="var(--color-warning)" summary={{ text: `+${Math.abs(((D.outflow.ind[11] - D.outflow.ind[0]) / D.outflow.ind[0]) * 100).toFixed(1)}% vs. 12 months ago`, dir: "down" }} />
          </div>
        </div>
        <div className="ii-grid2">
          <div className="ii-panel">
            <div className="ii-panel-hd"><div><h3>Industry average cash buffer</h3><p>Share of available working capital held in reserve.</p></div></div>
            <IIColumns months={months} values={D.industryBuffer} unit="%" />
          </div>
          <div className="ii-panel">
            <div className="ii-panel-hd"><div><h3>How businesses use funding</h3><p>Most common working capital use cases.</p></div></div>
            <IIDonut slices={D.fundingUse} />
          </div>
        </div>
      </div>
    </section>
  );
}

// ── Section 7 — common challenges ─────────────────────────────────────────

function InsChallenges({ D, industryLabel, onNav }) {
  const icons = [IND_ICONS.labor, IND_ICONS.inventory, IND_ICONS.bolt, IND_ICONS.flag];
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope ind">Industry only</span>
        <h2>Common Industry Challenges</h2>
        <p>Pressures that most {industryLabel} operators manage, and that show up in cash flow patterns.</p>
      </div>
      <div className="ii-grid4">
        {D.challenges.map((c, i) => (
          <div key={c.label} className="ii-tile">
            <div className="ii-tile-ic"><InsIcon d={icons[i % icons.length]} /></div>
            <h4>{c.label}</h4>
            <p>{c.note}</p>
          </div>
        ))}
      </div>
      {/* <button className="ii-inline-cta" onClick={onNav}>Learn How Businesses Overcome These Challenges <span>→</span></button> */}
    </section>
  );
}

// ── Section 8 — top performers ─────────────────────────────────────────────

function InsTopPerformers({ D }) {
  return (
    <section className="ii-sec">
      <div className="ii-sec-hd">
        <span className="ii-scope ind">Industry only · anonymized</span>
        <h2>What Top-Performing Businesses Do Differently</h2>
        <p>Aggregated characteristics of the strongest-performing quartile compared with the industry average. No individual business is identified.</p>
      </div>
      <table className="ii-table">
        <thead><tr><th>Metric</th><th>Top performers</th><th>Industry average</th></tr></thead>
        <tbody>{D.topPerformers.map(r => <tr key={r.metric}><td>{r.metric}</td><td className="top">{r.top}</td><td>{r.ind}</td></tr>)}</tbody>
      </table>
    </section>
  );
}

// ── Section 9 — education ─────────────────────────────────────────────────

function InsEducation({ D, onNav }) {
  const icons = [IND_ICONS.cash, IND_ICONS.score, IND_ICONS.funding];
  return (
    <section className="ii-sec" style={{ marginBottom: 30 }}>
      <div className="ii-sec-hd">
        <h2>Improve Your Business Financial Profile</h2>
        <p>Short, practical guides on the factors above — written for owners, not analysts.</p>
      </div>
      <div className="ii-grid3">
        {D.education.map((e, i) => (
          <div key={e.title} className="ii-tile teal">
            <div className="ii-tile-ic"><InsIcon d={icons[i]} /></div>
            <span className="ii-tag">{e.tag}</span>
            <h4>{e.title}</h4>
            <p>{e.note}</p>
            {/* <span className="ii-tile-cta" onClick={onNav}>Learn More →</span> */}
          </div>
        ))}
      </div>
    </section>
  );
}

// ── Section 10 — final CTA ────────────────────────────────────────────────

function InsFinalCTA({ onPrimary, onSecondary }) {
  return (
    <section className="ii-cta">
      <div>
        <h2>Understand Your Financial Profile Before Your Next Funding Decision</h2>
        <p>Review the full credit report behind these benchmarks, then work through what moves each factor.</p>
      </div>
      <div className="ii-cta-btns">
        <button className="ii-btn onnavy" onClick={onPrimary}>View Full Credit Report</button>
        <button className="ii-btn onnavy-ghost" onClick={onSecondary}>Learn How to Improve Your Business Profile</button>
      </div>
    </section>
  );
}

// ── Page footer (shared look with other RBI pages) ────────────────────────

function Footer() {
  return (
    <footer className="cs-page-footer">
      <div className="cs-footer-left">
        <span>+1 877-662-3489 (M-F 9am – 7pm)</span>
      </div>
      <div className="cs-footer-center">
        <span>©2026 Revenued (Business Intelligence)</span>
        <span className="cs-footer-sep">|</span>
        <a href="#">All Rights Reserved</a>
        <span className="cs-footer-sep">|</span>
        <a href="#">Terms of Service</a>
        <span className="cs-footer-sep">|</span>
        <a href="#" onClick={(e) => { e.preventDefault(); window.RBI_NAV("privacy"); }}>Privacy Policy</a>
      </div>
      <div className="cs-footer-social">
        <a href="https://www.youtube.com/@revenuedcard" aria-label="YouTube" className="cs-footer-icon" target="_blank" rel="noopener noreferrer">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
            <path d="M22.54 6.42a2.78 2.78 0 0 0-1.95-1.96C18.88 4 12 4 12 4s-6.88 0-8.59.46A2.78 2.78 0 0 0 1.46 6.42 29 29 0 0 0 1 12a29 29 0 0 0 .46 5.58a2.78 2.78 0 0 0 1.95 1.96C5.12 20 12 20 12 20s6.88 0 8.59-.46a2.78 2.78 0 0 0 1.95-1.96A29 29 0 0 0 23 12a29 29 0 0 0-.46-5.58z" />
            <polygon points="9.75 15.02 15.5 12 9.75 8.98 9.75 15.02" fill="#00122B" />
          </svg>
        </a>
        <a href="https://www.facebook.com/revenued/" aria-label="Facebook" className="cs-footer-icon" target="_blank" rel="noopener noreferrer">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
            <path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
          </svg>
        </a>
        <a href="https://www.linkedin.com/company/revenued" aria-label="LinkedIn" className="cs-footer-icon" target="_blank" rel="noopener noreferrer">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
            <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" />
            <rect x="2" y="9" width="4" height="12" /><circle cx="4" cy="4" r="2" />
          </svg>
        </a>
        <a href="https://www.instagram.com/revenuedcard/" aria-label="Instagram" className="cs-footer-icon" target="_blank" rel="noopener noreferrer">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <rect x="2" y="2" width="20" height="20" rx="5" /><circle cx="12" cy="12" r="4" />
            <circle cx="17.5" cy="6.5" r="1" fill="currentColor" stroke="none" />
          </svg>
        </a>
        <a href="https://twitter.com/revenuedcard" aria-label="X / Twitter" className="cs-footer-icon" target="_blank" rel="noopener noreferrer">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
            <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.746l7.73-8.835L2.25 2.25H8.08l4.253 5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
          </svg>
        </a>
      </div>
    </footer>
  );
}

// ── INDUSTRY PICKER (Phase 1, unchanged) ──────────────────────────────────

function IndustryPicker({ industries, loading, error, onRetry, onSelect, initialSelected }) {
  const [selected, setSelected] = useIndState(initialSelected || "");
  const list = industries && industries.length ? industries : indFallbackCatalog();

  useIndEffect(() => {
    if (initialSelected && !selected) setSelected(initialSelected);
  }, [initialSelected]);

  if (loading) {
    return (
      <div className="ind-picker-outer">
        <div className="ind-picker-card ii-state-card">
          <div className="ii-state-spinner" aria-hidden="true" />
          <p className="ii-state-title">Loading industries…</p>
          <p className="ii-state-sub">Fetching your benchmark catalog.</p>
        </div>
      </div>
    );
  }

  if (error && !(industries && industries.length)) {
    return (
      <div className="ind-picker-outer">
        <div className="ind-picker-card ii-state-card">
          <p className="ii-state-title">Unable to load industries</p>
          <p className="ii-state-sub">{error}</p>
          {onRetry ? (
            <button className="ind-picker-cta ind-picker-cta-enabled" type="button" onClick={onRetry}>
              Retry
            </button>
          ) : null}
        </div>
      </div>
    );
  }

  return (
    <div className="ind-picker-outer">
      <div className="ind-picker-card">
        <div className="ind-picker-hero">
          <div className="ind-intake-badge">Industry Insights & Benchmarking</div>
          <h1 className="ind-intake-title">What industry are you in?</h1>
          <p className="ind-intake-sub">Select your industry to unlock personalized benchmarks, peer comparisons, and funding insights. You can only choose once.</p>
        </div>

        <div className="ind-chip-grid">
          {list.map(ind => (
            <button
              key={ind.value}
              type="button"
              className={"ind-chip" + (selected === ind.value ? " ind-chip-active" : "")}
              onClick={() => setSelected(ind.value)}
            >
              <span className="ind-chip-icon">{indIconFor(ind.icon_key, ind.value)}</span>
              <span className="ind-chip-label">{ind.label}</span>
            </button>
          ))}
        </div>

        <div className="ind-picker-footer">
          <button
            type="button"
            className={"ind-picker-cta" + (selected ? " ind-picker-cta-enabled" : "")}
            disabled={!selected}
            onClick={() => selected && onSelect(selected)}
          >
            View Industry Insights →
          </button>
        </div>
      </div>
    </div>
  );
}

// ── DASHBOARD (Phase 2 — redesigned) ──────────────────────────────────────

function IndDashboard({ industry, onSelectIndustry, onBack, email, profileLoaded, industryCatalog, catalogIsSample, profileUser }) {
  const [controls, setControls] = useIndState(IND_MOCK_DEFAULTS);
  const [showMock, setShowMock] = useIndState(false);
  const [loading, setLoading] = useIndState(false);
  const [error, setError] = useIndState(null);
  const [isSample, setIsSample] = useIndState(true);
  const [bundle, setBundle] = useIndState(() => {
    const mock = buildMockInsightsBundle(industry, IND_MOCK_DEFAULTS);
    if (industryCatalog && industryCatalog.length) mock.industries = industryCatalog;
    return mock;
  });
  const reqIdRef = useIndRef(0);
  const controlsRef = useIndRef(controls);
  controlsRef.current = controls;

  const applyMock = useIndCallback((indValue, form) => {
    const mock = buildMockInsightsBundle(indValue, form || controlsRef.current);
    if (industryCatalog && industryCatalog.length) mock.industries = industryCatalog;
    setBundle(mock);
    setIsSample(true);
    setLoading(false);
  }, [industryCatalog]);

  const loadDashboard = useIndCallback(() => {
    const reqId = ++reqIdRef.current;

    // BE not ready — stay on sample data (no network calls).
    if (!indLiveApiEnabled()) {
      applyMock(industry, controlsRef.current);
      setError(null);
      return;
    }

    if (!email && !profileLoaded) {
      setLoading(true);
      setError(null);
      return;
    }

    if (!email) {
      if (reqId !== reqIdRef.current) return;
      applyMock(industry, controlsRef.current);
      setError(null);
      return;
    }

    setLoading(true);
    setError(null);
    fetchIndustryInsights(email, industry).then((res) => {
      if (reqId !== reqIdRef.current) return;
      if (res.ok && res.data) {
        if ((!res.data.industries || !res.data.industries.length) && industryCatalog && industryCatalog.length) {
          res.data.industries = industryCatalog;
        }
        setBundle(res.data);
        setIsSample(false);
        setError(null);
        if (res.data.selectedIndustry && res.data.selectedIndustry !== industry) {
          const locked = window.RBI_API && window.RBI_API.isIndustryLocked && window.RBI_API.isIndustryLocked(profileUser);
          if (!locked) onSelectIndustry(res.data.selectedIndustry);
        }
      } else {
        applyMock(industry, controlsRef.current);
        setError(res.error || "Unable to load industry insights.");
      }
      setLoading(false);
    });
  }, [email, profileLoaded, industry, industryCatalog, onSelectIndustry, applyMock]);

  useIndEffect(() => { loadDashboard(); }, [loadDashboard]);

  // When mock controls change and we're on sample data, rebuild locally.
  useIndEffect(() => {
    if (!isSample) return;
    applyMock(industry, controls);
  }, [controls.revenue, controls.years, controls.credit, controls.region, isSample, industry, applyMock]);

  const updateControl = (key, val) => setControls((p) => ({ ...p, [key]: val }));
  const goToCreditReport = () => window.RBI_NAV("creditscore");

  const industriesForUi = (bundle && bundle.industries && bundle.industries.length)
    ? bundle.industries
    : (industryCatalog && industryCatalog.length ? industryCatalog : indFallbackCatalog());
  const industryLabel =
    (industriesForUi.find((i) => i.value === industry) || {}).label ||
    (bundle && bundle.cohort && bundle.cohort.label) ||
    industry;
  const D = bundle;
  const months = (D && D.months) || II_MONTHS_FALLBACK;

  return (
    <div className="rbi-app">
      <window.RBITopbar
        business={indTopbarBusiness(profileUser, profileLoaded)}
        activeView="insights"
        onTweaks={isSample ? () => setShowMock(true) : undefined}
      />

      {showMock && isSample && (
        <IndMockControls
          controls={controls}
          onChange={updateControl}
          onClose={() => setShowMock(false)}
        />
      )}

      <div className="ii-body ind-dashboard-body">
        {loading || !D ? (
          <div className="ii-state-card ii-state-inline">
            <div className="ii-state-spinner" aria-hidden="true" />
            <p className="ii-state-title">Loading industry insights…</p>
            <p className="ii-state-sub">Comparing your business to the {industryLabel} cohort.</p>
          </div>
        ) : (
          <>
            {error && isSample && indLiveApiEnabled() ? (
              <div className="ii-inline-banner" role="status">
                <span>Showing sample data — {error}</span>
                <button type="button" onClick={loadDashboard}>Retry live data</button>
              </div>
            ) : null}
            <InsHero
              industry={industry}
              industryLabel={industryLabel}
              onChangeIndustry={onSelectIndustry}
              onBack={onBack}
              cohortN={D.cohort && D.cohort.n}
              industries={industriesForUi}
              isSample={isSample}
            />
            <InsSnapshot D={D} />
            <InsCashFlow D={D} months={months} />
            <InsCredit D={D} months={months} showHistory={isSample ? controls.showHistory : true} />
            {/* <InsWorkingCapital D={D} /> */}
            <InsFactors D={D} />
            {/* <InsIndustryPerformance D={D} months={months} industryLabel={industryLabel} /> */}
            <InsChallenges D={D} industryLabel={industryLabel} onNav={goToCreditReport} />
            {/* <InsTopPerformers D={D} /> */}
            <InsEducation D={D} onNav={goToCreditReport} />
            {/* <InsFinalCTA onPrimary={goToCreditReport} onSecondary={goToCreditReport} /> */}
          </>
        )}
      </div>

      <Footer />
    </div>
  );
}

// ── Root ──────────────────────────────────────────────────────────────────

function useIndProfile() {
  // Local profile hook only — do not call app.jsx useProfile (separate Babel scope / hooks rules).
  const [state, setState] = useIndState(() => {
    const p = (window.RBI_API && window.RBI_API.profile()) || {};
    return { profile: p, settled: !!(p && p.email) };
  });
  useIndEffect(() => {
    let alive = true;
    function onProfile(e) {
      if (alive) setState({ profile: (e.detail && e.detail.profile) || {}, settled: true });
    }
    window.addEventListener("rbi:profile", onProfile);
    if (window.RBI_API && window.RBI_API.ensureProfile) {
      window.RBI_API.ensureProfile()
        .then((p) => { if (alive) setState({ profile: p || {}, settled: true }); })
        .catch(() => { if (alive) setState({ profile: {}, settled: true }); });
    } else {
      setState((s) => ({ ...s, settled: true }));
    }
    return () => { alive = false; window.removeEventListener("rbi:profile", onProfile); };
  }, []);
  return [state.profile, state.settled];
}

function InsApp() {
  const [industry, setIndustry] = useIndState(null);
  const [user, profileLoaded] = useIndProfile();
  const email = indCustomerEmail(user);
  const [catalog, setCatalog] = useIndState(() => indFallbackCatalog());
  const [defaultIndustry, setDefaultIndustry] = useIndState(() => {
    const list = indFallbackCatalog();
    return (list[0] && list[0].value) || "restaurant";
  });
  const [catalogLoading, setCatalogLoading] = useIndState(false);
  const [catalogError, setCatalogError] = useIndState(null);
  const [isSampleCatalog, setIsSampleCatalog] = useIndState(true);

  const profileIndustry = indValueFromProfile(user, catalog);
  const isDeclinedUser = !!(window.RBI_API && window.RBI_API.isDeclinedUser && window.RBI_API.isDeclinedUser(user));
  const declinedIndustry = (window.RBI_ENV && window.RBI_ENV.declinedDefaultIndustry) || "restaurant";
  const industryLocked = !!(window.RBI_API && window.RBI_API.isIndustryLocked && window.RBI_API.isIndustryLocked(user));
  const lockedIndustry = isDeclinedUser
    ? (profileIndustry || declinedIndustry)
    : (profileIndustry || (window.RBI_API && window.RBI_API.getLockedIndustry && window.RBI_API.getLockedIndustry()) || "");
  // Declined users are pre-filled; other users must pick (no catalog default).
  const pickerInitial = isDeclinedUser ? (profileIndustry || declinedIndustry) : (profileIndustry || "");
  const autoOpenedLocked = useIndRef(false);

  const loadCatalog = useIndCallback(() => {
    // Instant local catalog — never leave the picker empty while the live call runs.
    const fallback = indFallbackCatalog();
    setCatalog(fallback);
    setDefaultIndustry((fallback[0] && fallback[0].value) || "restaurant");
    setIsSampleCatalog(true);

    if (!indLiveApiEnabled()) {
      setCatalogLoading(false);
      setCatalogError(null);
      return;
    }

    setCatalogLoading(true);
    setCatalogError(null);
    fetchIndustriesCatalog().then((res) => {
      if (res.ok && res.data) {
        setCatalog(res.data.industries);
        setDefaultIndustry(res.data.defaultIndustry || (res.data.industries[0] && res.data.industries[0].value) || "restaurant");
        setIsSampleCatalog(false);
        setCatalogError(null);
      } else {
        setCatalog(fallback);
        setDefaultIndustry((fallback[0] && fallback[0].value) || "restaurant");
        setIsSampleCatalog(true);
        setCatalogError(res.error || "Unable to load industries.");
      }
      setCatalogLoading(false);
    });
  }, []);

  useIndEffect(() => { loadCatalog(); }, [loadCatalog]);

  // Once an industry is locked (declined default, or a one-time pick), open
  // that dashboard and never return to the picker.
  useIndEffect(() => {
    if (autoOpenedLocked.current || industry || !profileLoaded || !lockedIndustry) return;
    autoOpenedLocked.current = true;
    setIndustry(lockedIndustry);
  }, [lockedIndustry, profileLoaded, industry]);

  const handleSelect = (ind) => {
    if (industryLocked) return;
    if (window.RBI_API && window.RBI_API.lockIndustry) window.RBI_API.lockIndustry(ind);
    setIndustry(ind);
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  const handleBack = () => {
    if (industryLocked) return;
    setIndustry(null);
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  const handleChangeIndustry = (ind) => {
    if (industryLocked) return;
    setIndustry(ind);
  };

  if (industry) {
    return (
      <IndDashboard
        industry={industry}
        onSelectIndustry={handleChangeIndustry}
        onBack={handleBack}
        email={email}
        profileLoaded={profileLoaded}
        industryCatalog={catalog}
        catalogIsSample={isSampleCatalog}
        profileUser={user}
      />
    );
  }

  return (
    <div className="rbi-app">
      <window.RBITopbar
        business={indTopbarBusiness(user, profileLoaded)}
        activeView="insights"
      />
      <IndustryPicker
        industries={catalog}
        loading={catalogLoading}
        error={catalogError}
        onRetry={loadCatalog}
        onSelect={handleSelect}
        initialSelected={pickerInitial}
      />
      <Footer />
    </div>
  );
}

window.InsApp = InsApp;