/* global React, Chart */
// components-fdic.jsx — FDIC Bank Intelligence Dashboard

const {
  useState, useEffect, useRef, useCallback, useMemo,
  Component: ReactComponent
} = React;

//  ERROR BOUNDARY 
class FDICErrorBoundary extends ReactComponent {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  render() {
    if (this.state.hasError) {
      return (
        <div className="fdic-error-banner" style={{ margin: 20 }}>
          Something went wrong rendering this section:{" "}
          {this.state.error && this.state.error.message}
        </div>
      );
    }
    return this.props.children;
  }
}

//  FDIC API 
const FDIC_BASE = "https://api.fdic.gov/banks";

async function fdicGet(endpoint, params, retries = 2) {
  const url = new URL(FDIC_BASE + endpoint);
  Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  const res = await fetch(url.toString());
  if (res.status === 429 && retries > 0) {
    await new Promise(r => setTimeout(r, 1500));
    return fdicGet(endpoint, params, retries - 1);
  }
  if (!res.ok) throw new Error("FDIC API error: " + res.status);
  return res.json();
}

async function searchInstitutions(query) {
  const q = query.trim();
  const isNum = /^\d+$/.test(q);
  if (isNum) {
    const json = await fdicGet("/institutions", {
      filters: `CERT:${q}`,
      fields: "NAME,CERT,CITY,STNAME,ASSET",
      limit: 10
    });
    return (json.data || []).map(d => d.data);
  }
  // Prefix search on the first word (Solr wildcard); ACTIVE:1 scopes to open banks
  const firstWord = q.split(/\s+/)[0];
  const json = await fdicGet("/institutions", {
    filters: `ACTIVE:1 AND NAME:${firstWord}*`,
    fields: "NAME,CERT,CITY,STNAME,ASSET",
    sort_by: "ASSET",
    sort_order: "DESC",
    limit: 20
  });
  const rows = (json.data || []).map(d => d.data);
  // For multi-word queries, narrow client-side
  if (q.includes(" ")) {
    const lq = q.toLowerCase();
    return rows.filter(r => (r.NAME || "").toLowerCase().includes(lq)).slice(0, 10);
  }
  return rows.slice(0, 10);
}

async function fetchInstitution(cert) {
  const json = await fdicGet("/institutions", {
    filters: `CERT:${cert}`,
    fields: "NAME,CERT,RSSDID,CITY,STNAME,WEBADDR,ESTYMD,OFFICES,CHRTAGNT,HCTMULT,STALP,ASSET,ACTIVE",
    limit: 1
  });
  return json.data?.[0]?.data || null;
}

async function fetchFinancials(cert, limit = 8) {
  const fields = [
    "REPDTE","ASSET","DEP","EQ","NETINC","ROA","ROE","NIMY","EEFFR",
    "RBCT1CER","RBC1RWAJ","RBCRWAJ","LNLSRES","LNLSNET",
    "LNRE","LNRECONS","LNREMULT","LNCI","LNCON","LNAUTO",
    "LNRENRES","LNRENROW","LNRENRN",
    "P3ASSET","P9ASSET","LNLSNTV","NTLNLS","NTLNLSR","FREPO","NTRE",
    "P3RE","P9RE",
    "P3RENRES","P9RENRES","NTRENRES",
    "P3RECONS","P9RECONS","NTRECONS",
    "P3REMULT","P9REMULT","NTREMULT",
    "P3CI","P9CI","NTLNCI",
    "LNLS",
    "BRO","SC","SCMTGBK","INTINC","EINTEXP","NONII","NONIX"
  ].join(",");
  const json = await fdicGet("/financials", {
    filters: `CERT:${cert}`,
    fields,
    sort_by: "REPDTE",
    sort_order: "DESC",
    limit
  });
  return (json.data || []).map(d => d.data);
}

async function fetchBranches(cert) {
  const json = await fdicGet("/locations", {
    filters: `CERT:${cert}`,
    fields: "OFFNAME,OFFNUM,MAINOFF,SERVTYPE,SERVTYPE_DESC,ADDRESS,CITY,STALP,ZIP,ESTYMD,STNAME",
    sort_by: "OFFNUM",
    sort_order: "ASC",
    limit: 500
  });
  return (json.data || []).map(d => d.data);
}



async function fetchAllStressedBanks(stateFilter = "") {
  // Parallel: all active institutions + latest financials for all banks
  const instParams = {
    fields: "CERT,NAME,CITY,STALP,STNAME,ASSET",
    limit: 10000,
    filters: "ACTIVE:1" + (stateFilter ? ` AND STALP:${stateFilter}` : "")
  };
  const finParams = {
    fields: "CERT,ASSET,P9ASSET,LNLSNTV,EQ,LNLSRES,FREPO,LNLS,RBCRWAJ,RBCT1CER,NETCHARGE,REPDTE,LNRENRES,LNRE,LNREMULT,LNRECONS,P9RE,NTRE",
    sort_by: "REPDTE",
    sort_order: "DESC",
    limit: 10000
  };

  const [instJson, finJson] = await Promise.all([
    fdicGet("/institutions", instParams),
    fdicGet("/financials", finParams)
  ]);

  // Build institution lookup by CERT
  const instMap = {};
  (instJson.data || []).forEach(d => { instMap[String(d.data.CERT)] = d.data; });

  // Deduplicate financials: latest row per CERT
  const seen = {};
  const latestFin = [];
  for (const row of (finJson.data || [])) {
    const r = row.data;
    if (!seen[r.CERT]) { seen[r.CERT] = true; latestFin.push(r); }
  }

  // Join + calculate Texas Ratio for every bank that has both records
  return latestFin
    .filter(r => instMap[String(r.CERT)])
    .map(r => {
      const inst = instMap[String(r.CERT)];
      const npl = (Number(r.P9ASSET) || 0) + (Number(r.LNLSNTV) || 0);
      const reo = Number(r.FREPO) || 0;
      const denom = (Number(r.EQ) || 0) + (Number(r.LNLSRES) || 0);
      const texas = denom > 0 ? ((npl + reo) / denom) * 100 : null;
      return {
        ...r,
        NAME:   inst.NAME,
        CITY:   inst.CITY,
        STALP:  inst.STALP,
        STNAME: inst.STNAME,
        _texas: texas
      };
    })
    .filter(r => r._texas !== null)
    .sort((a, b) => b._texas - a._texas);
}

async function fetchPeerBanks(cert, assetSize) {
  // tier buckets in thousands
  let minAsset, maxAsset, tierLabel;
  if (assetSize < 100000)        { minAsset = 0;        maxAsset = 100000;    tierLabel = "Under $100M"; }
  else if (assetSize < 1000000)  { minAsset = 100000;   maxAsset = 1000000;   tierLabel = "$100M–$1B"; }
  else if (assetSize < 10000000) { minAsset = 1000000;  maxAsset = 10000000;  tierLabel = "$1B–$10B"; }
  else if (assetSize < 100000000){ minAsset = 10000000; maxAsset = 100000000; tierLabel = "$10B–$100B"; }
  else                           { minAsset = 100000000;maxAsset = 9999999999;tierLabel = "Over $100B"; }

  const json = await fdicGet("/financials", {
    filters: `ASSET:[${minAsset} TO ${maxAsset}]`,
    fields: "ROA,ROE,NIMY,RBCT1CER,RBCRWAJ,P9ASSET,LNLSNTV,ASSET,NTLNLSR",
    sort_by: "REPDTE",
    sort_order: "DESC",
    limit: 100
  });
  const rows = (json.data || []).map(d => d.data);
  return { rows, tierLabel };
}

//  FORMATTING HELPERS 
function fmtDollars(val, decimals = 1, zeroFallback = false) {
  if (val == null || val === "" || isNaN(Number(val))) return zeroFallback ? "$0" : "—";
  const n = Number(val) * 1000; // FDIC reports in $thousands
  const abs = Math.abs(n);
  if (abs >= 1e12) return "$" + (n / 1e12).toFixed(decimals) + "T";
  if (abs >= 1e9)  return "$" + (n / 1e9).toFixed(decimals) + "B";
  if (abs >= 1e6)  return "$" + (n / 1e6).toFixed(decimals) + "M";
  if (abs >= 1e3)  return "$" + (n / 1e3).toFixed(decimals) + "K";
  return "$" + n.toFixed(0);
}

function fmtPct(val, decimals = 2) {
  if (val == null || val === "" || isNaN(Number(val))) return "—";
  return Number(val).toFixed(decimals) + "%";
}

function fmtDate(raw) {
  if (!raw) return "";
  const s = String(raw).trim();
  const mo = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  // YYYY-MM-DD (ISO — what FDIC /failures returns)
  const iso = s.match(/^(\d{4})-(\d{2})-(\d{2})/);
  if (iso) return (mo[parseInt(iso[2],10)-1] || iso[2]) + " " + iso[3] + ", " + iso[1];
  // YYYYMMDD
  if (/^\d{8}$/.test(s)) {
    const y=s.slice(0,4),m=s.slice(4,6),d=s.slice(6,8);
    return (mo[parseInt(m,10)-1] || m) + " " + d + ", " + y;
  }
  // MM/DD/YYYY
  const us = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})/);
  if (us) return (mo[parseInt(us[1],10)-1] || us[1]) + " " + us[2].padStart(2,"0") + ", " + us[3];
  return s;
}

function reptdateToQuarter(repdte) {
  if (!repdte) return "";
  const s = String(repdte);
  const y = s.slice(0, 4);
  const m = parseInt(s.slice(4, 6), 10);
  const q = Math.ceil(m / 3);
  return `${y} Q${q}`;
}

function trendArrow(current, previous, inverseGood = false) {
  if (current == null || previous == null || previous === 0) return null;
  const pct = ((current - previous) / Math.abs(previous)) * 100;
  const up = pct > 0;
  const good = inverseGood ? !up : up;
  const cls = good ? "fdic-trend-up" : "fdic-trend-down";
  const arrow = up ? "▲" : "▼";
  return { cls, arrow, pct: Math.abs(pct).toFixed(1) };
}

function calcTexasRatio(fin) {
  if (!fin) return null;
  const npl = (Number(fin.P9ASSET) || 0) + (Number(fin.LNLSNTV) || 0);
  const reo = Number(fin.FREPO) || 0;
  const eq  = Number(fin.EQ) || 0;
  const alll = Number(fin.LNLSRES) || 0;
  const denom = eq + alll;
  if (denom <= 0) return null;
  return ((npl + reo) / denom) * 100;
}

function texasBand(ratio) {
  if (ratio >= 100) return { label: "Danger",   cls: "danger",   color: "var(--status-negative)", bg: "var(--status-negative-bg)", pop: "#FF6B6B" };
  if (ratio >= 75)  return { label: "Stressed", cls: "stressed", color: "var(--status-caution)", bg: "var(--status-caution-bg)", pop: "#FFB44D" };
  if (ratio >= 50)  return { label: "Watch",    cls: "watch",    color: "var(--status-caution)", bg: "var(--status-caution-bg)", pop: "#FFD166" };
  return                   { label: "Healthy",  cls: "healthy",  color: "var(--status-positive)", bg: "var(--status-positive-bg)", pop: "#4ADE80" };
}

function capitalColor(field, value) {
  const v = Number(value);
  if (isNaN(v)) return "blue";
  const thresholds = {
    RBCT1CER: { red: 4, yellow: 5 },
    RBC1RWAJ: { red: 6, yellow: 8 },
    RBCRWAJ: { red: 8, yellow: 10 }
  };
  const t = thresholds[field];
  if (!t) return "blue";
  if (v < t.red) return "red";
  if (v < t.yellow) return "yellow";
  return "green";
}

function nplPctColor(pct) {
  if (pct >= 5) return "high";
  if (pct >= 2) return "mid";
  return "low";
}

function peerMedian(rows, field) {
  const vals = rows.map(r => Number(r[field])).filter(v => !isNaN(v) && v !== 0);
  if (!vals.length) return null;
  vals.sort((a, b) => a - b);
  const mid = Math.floor(vals.length / 2);
  return vals.length % 2 === 0 ? (vals[mid - 1] + vals[mid]) / 2 : vals[mid];
}

const US_STATES = [
  "","AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA",
  "KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ",
  "NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT",
  "VA","WA","WV","WI","WY","DC","PR","VI","GU"
];

const US_STATE_NAMES = {
  AL:"Alabama", AK:"Alaska", AZ:"Arizona", AR:"Arkansas", CA:"California",
  CO:"Colorado", CT:"Connecticut", DE:"Delaware", FL:"Florida", GA:"Georgia",
  HI:"Hawaii", ID:"Idaho", IL:"Illinois", IN:"Indiana", IA:"Iowa",
  KS:"Kansas", KY:"Kentucky", LA:"Louisiana", ME:"Maine", MD:"Maryland",
  MA:"Massachusetts", MI:"Michigan", MN:"Minnesota", MS:"Mississippi",
  MO:"Missouri", MT:"Montana", NE:"Nebraska", NV:"Nevada", NH:"New Hampshire",
  NJ:"New Jersey", NM:"New Mexico", NY:"New York", NC:"North Carolina",
  ND:"North Dakota", OH:"Ohio", OK:"Oklahoma", OR:"Oregon", PA:"Pennsylvania",
  RI:"Rhode Island", SC:"South Carolina", SD:"South Dakota", TN:"Tennessee",
  TX:"Texas", UT:"Utah", VT:"Vermont", VA:"Virginia", WA:"Washington",
  WV:"West Virginia", WI:"Wisconsin", WY:"Wyoming", DC:"District of Columbia",
  PR:"Puerto Rico", VI:"Virgin Islands", GU:"Guam"
};

//  STATE DROPDOWN 
function StateSelect({ value, onChange }) {
  const [open, setOpen] = useState(false);
  const wrapRef = useRef(null);

  useEffect(() => {
    const handler = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  return (
    <div ref={wrapRef} className="fdic-state-select">
      <button
        className={"fdic-state-btn" + (value ? " active" : "")}
        onClick={() => setOpen(o => !o)}
      >
        {value ? <><span className="fdic-state-btn-abbr">{value}</span><span className="fdic-state-btn-name">{US_STATE_NAMES[value]}</span></> : "All States"}
        <span className="fdic-state-arrow">{open ? <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg> : <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>}</span>
      </button>
      {open && (
        <div className="fdic-state-dropdown">
          <div
            className={"fdic-state-option fdic-state-all" + (!value ? " active" : "")}
            onMouseDown={() => { onChange(""); setOpen(false); }}
          >
            All States
          </div>
          {US_STATES.filter(Boolean).map(s => (
            <div
              key={s}
              className={"fdic-state-option" + (value === s ? " active" : "")}
              onMouseDown={() => { onChange(s); setOpen(false); }}
            >
              <span className="fdic-state-abbr">{s}</span>
              <span className="fdic-state-name">{US_STATE_NAMES[s] || s}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

//  SEARCH BAR 
function FDICSearch({ onSelect }) {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const [searchError, setSearchError] = useState(null);
  const timerRef = useRef(null);
  const wrapRef = useRef(null);

  useEffect(() => {
    const handler = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const handleChange = (e) => {
    const val = e.target.value;
    setQuery(val);
    setSearchError(null);
    clearTimeout(timerRef.current);
    if (val.trim().length < 2) { setResults([]); setOpen(false); return; }
    timerRef.current = setTimeout(async () => {
      setLoading(true);
      setOpen(true);
      try {
        const res = await searchInstitutions(val);
        setResults(res);
      } catch(e) {
        setResults([]);
        setSearchError("Search unavailable — try again");
      }
      finally { setLoading(false); }
    }, 320);
  };

  const handleSelect = (item) => {
    setQuery(item.NAME);
    setOpen(false);
    onSelect(item.CERT);
  };

  return (
    <div ref={wrapRef} className="fdic-search-wrap">
      <span className="fdic-search-icon"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg></span>
      <input
        className="fdic-search-input"
        type="text"
        placeholder="Search by bank name or FDIC certificate #…"
        value={query}
        onChange={handleChange}
        onFocus={() => (results.length || query.length >= 2) && setOpen(true)}
        autoComplete="off"
        spellCheck="false"
      />
      {open && (
        <div className="fdic-search-dropdown">
          {loading && (
            <div className="fdic-search-loading">
              <span className="fdic-search-spinner" /> Searching…
            </div>
          )}
          {!loading && searchError && (
            <div className="fdic-search-error">{searchError}</div>
          )}
          {!loading && !searchError && results.length === 0 && query.length >= 2 && (
            <div className="fdic-search-loading">No institutions found for "{query}"</div>
          )}
          {!loading && results.map(r => (
            <div key={r.CERT} className="fdic-search-item" onMouseDown={() => handleSelect(r)}>
              <div className="fdic-search-item-main">
                <div className="fdic-search-item-name">{r.NAME}</div>
                <div className="fdic-search-item-meta">{r.CITY}, {r.STNAME}</div>
              </div>
              <div className="fdic-search-item-right">
                <div className="fdic-search-item-meta">FDIC #{r.CERT}</div>
                <div className="fdic-search-item-assets">{fmtDollars(r.ASSET)}</div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

//  SKELETON CARD 
function SkeletonCard({ height = 100 }) {
  return <div className="fdic-skeleton fdic-skeleton-card" style={{ height }} />;
}

function SkeletonRow({ cols = 3 }) {
  return (
    <div className={`fdic-stat-row fdic-stat-row-${cols}`}>
      {Array.from({ length: cols }).map((_, i) => <SkeletonCard key={i} height={90} />)}
    </div>
  );
}

//  TREND ARROW COMPONENT 
function TrendBadge({ current, previous, inverseGood = false }) {
  const t = trendArrow(current, previous, inverseGood);
  if (!t) return null;
  return (
    <span className={`fdic-trend ${t.cls}`}>
      {t.arrow} {t.pct}% QoQ
    </span>
  );
}

//  WATCHLIST 
function useWatchlist() {
  const KEY = "vrb_fdic_watchlist";
  const load = () => { try { return JSON.parse(localStorage.getItem(KEY) || "[]"); } catch(e) { return []; } };
  const [list, setList] = useState(load);

  const add = useCallback((bank) => {
    setList(prev => {
      const next = prev.some(b => b.CERT === bank.CERT) ? prev : [...prev, bank];
      localStorage.setItem(KEY, JSON.stringify(next));
      return next;
    });
  }, []);

  const remove = useCallback((cert) => {
    setList(prev => {
      const next = prev.filter(b => b.CERT !== cert);
      localStorage.setItem(KEY, JSON.stringify(next));
      return next;
    });
  }, []);

  const isWatched = useCallback((cert) => list.some(b => b.CERT === cert), [list]);
  return { list, add, remove, isWatched };
}

function WatchlistPanel({ watchlist, onSelect, onRemove }) {
  const [open, setOpen] = useState(true);
  if (watchlist.length === 0) return null;
  return (
    <div className="fdic-watchlist-strip">
      <div className="fdic-watchlist-strip-header" onClick={() => setOpen(o => !o)}>
        <span>Watchlist ({watchlist.length})</span>
        <span style={{ fontSize: "0.75rem", color: "var(--vrb-ink-400)" }}>{open ? <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg> : <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>}</span>
      </div>
      {open && (
        <div className="fdic-watchlist-chips">
          {watchlist.map(b => (
            <div key={b.CERT} className="fdic-watchlist-chip">
              <span onClick={() => onSelect(b.CERT)} className="fdic-watchlist-chip-name">{b.NAME}</span>
              <span style={{ fontSize: "0.68rem", color: "var(--vrb-ink-400)", marginLeft: 4 }}>{b.STALP}</span>
              <button className="fdic-watchlist-chip-x" onClick={() => onRemove(b.CERT)}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

//  LEADERBOARD (ALL BANKS, PAGINATED) 
const LEADERBOARD_PAGE_SIZE = 50;

// Seller Signal Score color — Navy/Royal Blue/Sky Blue escalation (no red/amber)
function sellerColor(label) {
  if (label === "Hot") return "var(--vrb-navy)";
  if (label === "Priority") return "var(--vrb-blue)";
  if (label === "Watch") return "var(--vrb-blue)";
  return "var(--vrb-sky)"; // Monitor
}
// Fill treatment for the seller-signal pill: Priority/Hot get a solid fill + white text;
// Monitor/Watch stay as an outline on white.
function sellerFill(label) {
  if (label === "Hot")      return { bg: "var(--vrb-navy)", color: "#fff", border: "var(--vrb-navy)" };
  if (label === "Priority") return { bg: "var(--vrb-blue)", color: "#fff", border: "var(--vrb-blue)" };
  if (label === "Watch")    return { bg: "transparent", color: "var(--vrb-blue)", border: "var(--vrb-blue)" };
  return { bg: "transparent", color: "var(--vrb-sky)", border: "var(--vrb-sky)" }; // Monitor
}
const BADGE_STYLE = {
  "HFS":              { color: "var(--vrb-blue)",       bg: "rgba(46,117,182,.12)" },
  "Sold":             { color: "var(--vrb-green)",      bg: "var(--vrb-green-tint)" },
  "NPL Outlier":      { color: "#fff", bg: "var(--vrb-navy)" },
  "CO Spike":         { color: "var(--status-caution)",  bg: "var(--status-caution-bg)" },
  "OREO Heavy":       { color: "#fff", bg: "var(--vrb-blue)" },
  "Texas Danger":     { color: "#fff", bg: "var(--vrb-navy)" },
  "Capital Pressure": { color: "#fff", bg: "var(--vrb-navy)" },
};
function SignalBadges({ badges }) {
  if (!badges || !badges.length) return <span className="fdic-rt-nobadge">—</span>;
  return (
    <div className="fdic-badge-row">
      {badges.map(b => {
        const s = BADGE_STYLE[b] || { color: "var(--vrb-ink-500)", bg: "var(--vrb-ink-100)" };
        return <span key={b} className="fdic-sig-badge" style={{ color: s.color, background: s.bg }}>{b}</span>;
      })}
    </div>
  );
}

// signal-overview card definitions (count + ranking metric). Every distress
// signal lives in ONE consistent card grid — previously HFS/sold/npl/co were
// shown as big cards while OREO/Texas/Capital were duplicated as separate small
// chips AND a third time as a "Signal Type" dropdown, which is why clicking a
// filter looked broken (three controls silently fighting over the same state).
const OVERVIEW_CARDS = [
  { id: "npl",  title: "NPL / Loans Outliers", desc: "Distress intensity",
    threshold: "NPL / loans ≥ 3.0%", metricLabel: "NPL / Loans", sortKey: "npl",
    status: "Live", statusNote: "Live · FDIC Call Report",
    test: s => s.isNplOutlier, rank: s => s.nplRatio || 0,
    fmt: s => (s.nplRatio != null ? s.nplRatio.toFixed(1) + "%" : "—") },
  { id: "hfs",  title: "Held For Sale Signals", desc: "Sale pipeline",
    threshold: "Severe HFS > 0 · live RC-N only", metricLabel: "Severe HFS", sortKey: "hfs",
    status: "Live", statusNote: "Live · FFIEC CDR, weekly cache (top ~175 distress candidates)",
    test: s => s.isHfsSignal, rank: s => s.severeHFS || 0,
    fmt: s => fmtDollars(s.severeHFS) },
  { id: "sold", title: "Sold Nonaccruals", desc: "Proven seller behavior",
    threshold: "Sold > 0 · live RC-N only", metricLabel: "Sold NAs", sortKey: "sold",
    status: "Live", statusNote: "Live · FFIEC CDR, weekly cache (top ~175 distress candidates)",
    test: s => s.isSoldSignal, rank: s => s.soldNonaccrual || 0,
    fmt: s => fmtDollars(s.soldNonaccrual) },
  { id: "co",   title: "RE Charge-Off Signals", desc: "Realized losses",
    threshold: "RE net CO ratio ≥ 0.5%", metricLabel: "RE NCO", sortKey: "co",
    status: "Derived", statusNote: "Derived · live FDIC fields",
    test: s => s.isCoSpike, rank: s => s.reNcoRatio || 0,
    fmt: s => (s.reNcoRatio != null ? s.reNcoRatio.toFixed(2) + "%" : "—") },
  { id: "oreo",  title: "OREO Accumulators", desc: "REO burden",
    threshold: "OREO / assets or equity elevated", metricLabel: "OREO", sortKey: "oreo",
    status: "Derived", statusNote: "Derived · live FDIC fields",
    test: s => s.isOreoHeavy, rank: s => s.oreo || 0,
    fmt: s => (s.oreo > 0 ? fmtDollars(s.oreo) : "$0") },
  { id: "texas", title: "Texas Danger", desc: "Balance-sheet stress",
    threshold: "Texas ratio ≥ 100%", metricLabel: "Texas Ratio", sortKey: "texas",
    status: "Derived", statusNote: "Derived · live FDIC fields",
    test: s => s.isTexasDanger, rank: s => s.texas || 0,
    fmt: s => (s.texas != null ? s.texas.toFixed(0) + "%" : "—") },
  { id: "capital", title: "Capital Pressure", desc: "Near regulatory minimums",
    threshold: "Tier 1 leverage < 5% or total RBC < 10.5%", metricLabel: "Seller Score", sortKey: null,
    status: "Live", statusNote: "Live · FDIC Call Report",
    test: s => s.isCapitalPressure, rank: s => s.sellerScore || 0,
    fmt: s => (s.sellerScore != null ? s.sellerScore + "/100" : "—") },
];
const SORT_LABELS = {
  seller: "Seller Signal Score", npl: "NPL / Loans", hfs: "Severe HFS",
  sold: "Sold Nonaccruals", co: "RE Charge-Off Ratio", oreo: "OREO",
  texas: "Texas Ratio", assets: "Assets",
};

function StressLeaderboard({ onSelect, watchlist, stateFilter, assetFilter, targetType, signalType, sellerSignal, sortBy, onSignalType, onSortChange }) {
  const [banks, setBanks]   = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError]   = useState(null);
  const [page, setPage]     = useState(0);
  const [showAllColumns, setShowAllColumns] = useState(false);

  // Clicking a signal card both filters AND re-sorts by that signal's own
  // magnitude, so the (small, gated) preview visibly changes on click instead
  // of silently reordering within a sort the user never asked for.
  const selectSignal = (id, sortKey) => {
    const turningOn = signalType !== id;
    onSignalType(turningOn ? id : "");
    if (turningOn && sortKey && onSortChange) onSortChange(sortKey);
  };

  useEffect(() => {
    setLoading(true);
    setError(null);
    setPage(0);
    fetchAllStressedBanks(stateFilter)
      .then(rows => window.FFIECFeed && window.FFIECFeed.loadLiveCache
        ? window.FFIECFeed.loadLiveCache().then(() => rows)
        : rows)
      .then(rows => setBanks(rows.map(r => ({ ...r, _sig: window.BankSignals.compute(r, null, r.CERT) }))))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }, [stateFilter]);

  useEffect(() => { setPage(0); }, [assetFilter, targetType, signalType, sellerSignal, sortBy]);

  // Scope = state + asset-size only (signal-overview counts are computed on this)
  const scoped = useMemo(() => {
    let rows = banks;
    if (assetFilter === "small") rows = rows.filter(b => Number(b.ASSET) < 100000);
    if (assetFilter === "mid")   rows = rows.filter(b => Number(b.ASSET) >= 100000 && Number(b.ASSET) < 1000000);
    if (assetFilter === "large") rows = rows.filter(b => Number(b.ASSET) >= 1000000);
    return rows;
  }, [banks, assetFilter]);

  // Apply target-asset, signal-type and seller-signal filters, then sort
  const sorted = useMemo(() => {
    let rows = scoped;
    if (targetType) rows = rows.filter(b => window.BankSignals.targetAssetClass(b).id === targetType);
    if (signalType) {
      const t = {
        npl: s => s.isNplOutlier, hfs: s => s.isHfsSignal, sold: s => s.isSoldSignal,
        co: s => s.isCoSpike, oreo: s => s.isOreoHeavy, texas: s => s.isTexasDanger,
        capital: s => s.isCapitalPressure,
      }[signalType];
      if (t) rows = rows.filter(b => t(b._sig));
    }
    if (sellerSignal) rows = rows.filter(b => b._sig.sellerClass === sellerSignal);

    const cmp = {
      assets: (a, b) => (Number(b.ASSET) || 0) - (Number(a.ASSET) || 0),
      npl:    (a, b) => (b._sig.nplRatio || 0) - (a._sig.nplRatio || 0),
      hfs:    (a, b) => (b._sig.severeHFS || 0) - (a._sig.severeHFS || 0),
      sold:   (a, b) => (b._sig.soldNonaccrual || 0) - (a._sig.soldNonaccrual || 0),
      co:     (a, b) => (b._sig.reNcoRatio || 0) - (a._sig.reNcoRatio || 0),
      oreo:   (a, b) => b._sig.oreo - a._sig.oreo,
      texas:  (a, b) => (b._sig.texas || 0) - (a._sig.texas || 0),
      seller: (a, b) => b._sig.sellerScore - a._sig.sellerScore
        || (b._sig.severeHFS || 0) - (a._sig.severeHFS || 0)
        || (b._sig.soldNonaccrual || 0) - (a._sig.soldNonaccrual || 0)
        || (b._sig.nplRatio || 0) - (a._sig.nplRatio || 0)
        || (b._sig.reNcoRatio || 0) - (a._sig.reNcoRatio || 0),
    }[sortBy] || null;
    return cmp ? [...rows].sort(cmp) : rows;
  }, [scoped, targetType, signalType, sellerSignal, sortBy]);

  // Signal-overview card data (counts + top 3) from the scoped set
  const overview = useMemo(() => OVERVIEW_CARDS.map(card => {
    const hits = scoped.filter(b => card.test(b._sig));
    const top3 = [...hits].sort((a, b) => card.rank(b._sig) - card.rank(a._sig)).slice(0, 3);
    return { ...card, count: hits.length, top3 };
  }), [scoped]);

  const LANDING_PREVIEW = 10; // gated preview — top 10 banks, then the investor CTA
  const totalPages = 1;
  const pageData   = sorted.slice(0, LANDING_PREVIEW);
  const goPage = (n) => { setPage(n); window.scrollTo({ top: 0, behavior: "smooth" }); };

  const toggleWatch = (e, b) => {
    e.stopPropagation();
    if (watchlist.isWatched(b.CERT)) watchlist.remove(b.CERT);
    else watchlist.add({ CERT: b.CERT, NAME: b.NAME, CITY: b.CITY, STALP: b.STALP });
  };

  // CSV export of the current (filtered + sorted) ranking — spec §17.
  const exportCSV = () => {
    if (!sorted.length) return;
    const cols = [
      "rank","bank_name","fdic_certificate","city","state","total_assets","total_loans",
      "target_re_loans","primary_signal","signal_badges","seller_signal_score","seller_signal_label",
      "data_status","npl_loans_ratio","total_npl","target_re_problem_loans","severe_hfs",
      "severe_hfs_loans_ratio","nonaccrual_assets_sold","sold_nonaccrual_reporting_window",
      "re_net_chargeoff_ratio","bankwide_net_chargeoffs","oreo","oreo_assets_ratio","oreo_equity_ratio",
      "texas_ratio","capital_pressure_flag","liquidity_pressure_flag","brokered_deposits_ratio",
      "deposit_qoq_change","uninsured_deposits_ratio","borrowings_assets_ratio","latest_quarter",
      "npl_data_status","hfs_data_status","sold_nonaccrual_data_status","chargeoff_data_status",
      "oreo_data_status","capital_liquidity_data_status",
    ];
    const K = (v) => (v == null || isNaN(Number(v))) ? "" : Math.round(Number(v) * 1000); // $thousands → $
    const P = (v, d = 2) => (v == null || isNaN(Number(v))) ? "" : Number(v).toFixed(d);
    const esc = (v) => {
      const s = v == null ? "" : String(v);
      return /[",\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
    };
    const lines = [cols.join(",")];
    sorted.forEach((b, i) => {
      const s = b._sig;
      const row = [
        i + 1, b.NAME, b.CERT, b.CITY, b.STALP || b.STNAME, K(b.ASSET), K(s.totalLoans),
        K(s.targetReLoans), s.primarySignal, s.badges.join("; "), s.sellerScore, s.sellerLabel,
        s.dataStatusOverall, P(s.nplRatio, 1), K(s.totalNPL), K(s.reProblem), K(s.severeHFS),
        P(s.severeHfsToLoans * 100, 2), K(s.soldNonaccrual), s.rcnAsOf || "",
        P(s.reNcoRatio, 2), "", K(s.oreo), P(s.oreoToAssets * 100, 2), P(s.oreoToEquity * 100, 1),
        P(s.texas, 0), s.isCapitalPressure ? "Y" : "N", "", "", "", "", "",
        reptdateToQuarter(b.REPDTE),
        s.dataStatus.npl, s.dataStatus.hfs, s.dataStatus.sold, s.dataStatus.co, s.dataStatus.oreo, "Partial",
      ];
      lines.push(row.map(esc).join(","));
    });
    const blob = new Blob(["\ufeff" + lines.join("\n")], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "vrb-bank-intel-ranking-" + new Date().toISOString().slice(0, 10) + ".csv";
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  return (
    <div className="fdic-leaderboard-wrap">
      {/* Signal Overview cards — one consistent grid for all 7 distress signals */}
      {!loading && scoped.length > 0 && (
        <div className="fdic-signal-overview">
          {overview.map(c => (
            <button key={c.id}
              className={"fdic-signal-card" + (signalType === c.id ? " active" : "")}
              onClick={() => selectSignal(c.id, c.sortKey)}>
              <div className="fdic-signal-card-head">
                <span className="fdic-signal-card-title">{c.title}</span>
                <span className="fdic-signal-card-count">{c.count.toLocaleString()}</span>
              </div>
              <div className="fdic-signal-card-desc">{c.desc}</div>
              <div className="fdic-signal-card-thresh">{c.threshold}</div>
              <div className="fdic-signal-card-status" style={{
                display: "inline-flex", alignItems: "center", gap: 5, marginTop: 6,
                fontSize: 10.5, fontWeight: 600, letterSpacing: ".04em", textTransform: "uppercase",
                color: c.status === "Live" ? "var(--status-positive)" : c.status === "Derived" ? "var(--vrb-blue)" : "var(--status-caution)",
              }}>
                <span style={{ width: 6, height: 6, borderRadius: "50%", background: "currentColor", display: "inline-block" }}></span>
                {c.statusNote}
              </div>
              <div className="fdic-signal-card-top">
                {c.top3.length ? c.top3.map(b => (
                  <div key={b.CERT} className="fdic-signal-top-row"
                    onClick={(e) => { e.stopPropagation(); onSelect(b.CERT); }}>
                    <span className="fdic-signal-top-name">{b.NAME}</span>
                    <span className="fdic-signal-top-metric">{c.fmt(b._sig)}</span>
                  </div>
                )) : <div className="fdic-signal-top-empty">{(c.id === "hfs" || c.id === "sold") ? "No banks in the live FFIEC cache (top ~175 distress candidates) currently clear this threshold" : "No banks above threshold in scope"}</div>}
              </div>
            </button>
          ))}
        </div>
      )}

      <div className="fdic-lb-count" style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
        <span>{loading ? "Loading banks…" : `Top ${Math.min(pageData.length, sorted.length).toLocaleString()} of ${sorted.length.toLocaleString()} banks · ranked by ${SORT_LABELS[sortBy] || "Seller Signal"}`}</span>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          {!loading && sorted.length > 0 && (
            <button className="fdic-btn fdic-btn-outline fdic-csv-btn" onClick={() => setShowAllColumns(v => !v)}>
              {showAllColumns ? "Fewer columns" : "Show all columns"}
            </button>
          )}
          {!loading && sorted.length > 0 && (
            <button className="fdic-btn fdic-btn-outline fdic-csv-btn" onClick={exportCSV}>Export CSV</button>
          )}
        </div>
      </div>

      {error && <div className="fdic-error-banner" style={{ margin: "0 0 16px" }}>Failed to load: {error}</div>}

      {loading ? (
        <div className="fdic-lb-loading">
          <div className="fdic-lb-spinner" />
          <div>Loading FDIC bank data…</div>
        </div>
      ) : (
        <>
          <div className={"fdic-rank-table-scroll fdic-rt-desktop-only" + (showAllColumns ? "" : " fdic-rank-table-scroll--lean")}>
            <table className="fdic-rank-table">
              <thead>
                <tr>
                  <th className="fdic-rt-rank">#</th>
                  <th className="fdic-rt-watch" aria-label="Watch"></th>
                  <th className="fdic-rt-bank">Bank</th>
                  <th className="fdic-rt-primary">Primary Signal</th>
                  <th className="fdic-rt-badges" data-col="extra">Signal Badges</th>
                  <th className="fdic-rt-num" data-col="extra">Target RE Loans</th>
                  <th className="fdic-rt-num" data-col="extra">NPL / Loans</th>
                  <th className="fdic-rt-num" data-col="extra">Severe HFS</th>
                  <th className="fdic-rt-num" data-col="extra">Sold NAs</th>
                  <th className="fdic-rt-num" data-col="extra">RE NCO</th>
                  <th className="fdic-rt-num" data-col="extra">OREO</th>
                  <th className="fdic-rt-num" data-col="extra">Texas</th>
                  <th className="fdic-rt-seller">Seller Signal</th>
                  <th className="fdic-rt-status">Data Status</th>
                </tr>
              </thead>
              <tbody>
                {pageData.map((b, i) => {
                  const rank = page * LEADERBOARD_PAGE_SIZE + i + 1;
                  const s = b._sig;
                  const watched = watchlist.isWatched(b.CERT);
                  return (
                    <tr key={b.CERT || i} className="fdic-rt-row" onClick={() => onSelect(b.CERT)}>
                      <td className="fdic-rt-rank">{rank}</td>
                      <td className="fdic-rt-watch">
                        <button className={"fdic-rt-star" + (watched ? " on" : "")} onClick={(e) => toggleWatch(e, b)} aria-label="Watch">
                          <svg width="15" height="15" viewBox="0 0 24 24" fill={watched ? "currentColor" : "none"} stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>
                        </button>
                      </td>
                      <td className="fdic-rt-bank">
                        <div className="fdic-rt-name">{b.NAME}</div>
                        <div className="fdic-rt-sub">{[b.CITY, b.STALP || b.STNAME].filter(Boolean).join(", ")} · #{b.CERT} · {fmtDollars(b.ASSET)}</div>
                      </td>
                      <td className="fdic-rt-primary">{s.primarySignal}</td>
                      <td className="fdic-rt-badges" data-col="extra"><SignalBadges badges={s.badges} /></td>
                      <td className="fdic-rt-num" data-col="extra">{s.targetReLoans > 0 ? fmtDollars(s.targetReLoans) : "—"}</td>
                      <td className="fdic-rt-num" data-col="extra">{s.nplRatio != null ? s.nplRatio.toFixed(1) + "%" : "—"}</td>
                      <td className="fdic-rt-num" data-col="extra">{fmtDollars(s.severeHFS)}</td>
                      <td className="fdic-rt-num" data-col="extra">{fmtDollars(s.soldNonaccrual)}</td>
                      <td className="fdic-rt-num" data-col="extra">{s.reNcoRatio != null ? s.reNcoRatio.toFixed(2) + "%" : "—"}</td>
                      <td className="fdic-rt-num" data-col="extra">{s.oreo > 0 ? fmtDollars(s.oreo) : "$0"}</td>
                      <td className="fdic-rt-num" data-col="extra" style={s.texas != null ? (s.texas >= 75 ? { color: "var(--vrb-navy)", fontWeight: 700 } : { color: "var(--vrb-ink-500)" }) : null}>{s.texas != null ? s.texas.toFixed(0) + "%" : "—"}</td>
                      <td className="fdic-rt-seller">
                        <span className="fdic-seller-pill" style={{ color: sellerFill(s.sellerLabel).color, borderColor: sellerFill(s.sellerLabel).border, background: sellerFill(s.sellerLabel).bg }}>
                          {s.sellerScore} · {s.sellerLabel}
                        </span>
                      </td>
                      <td className="fdic-rt-status">
                        <span className="fdic-status-pill" style={{
                          color: s.dataStatusOverall === "Live" ? "var(--status-positive)" : "var(--vrb-ink-400)",
                          background: s.dataStatusOverall === "Live" ? "transparent" : "var(--vrb-ink-50)",
                        }}>{s.dataStatusOverall}</span>
                      </td>
                    </tr>
                  );
                })}
                {pageData.length === 0 && (
                  <tr><td colSpan="14" className="fdic-rt-empty">No banks match the selected signal filters in this scope.</td></tr>
                )}
              </tbody>
            </table>
          </div>

          {/* Mobile card list — the 14-column table becomes unreadable under
              a horizontal scroll on a phone (columns clip mid-word at the
              viewport edge instead of resizing). Same data and click target,
              restructured as one card per bank instead of a wide row. */}
          <div className="fdic-rt-cards fdic-rt-mobile-only">
            {pageData.map((b, i) => {
              const rank = page * LEADERBOARD_PAGE_SIZE + i + 1;
              const s = b._sig;
              const watched = watchlist.isWatched(b.CERT);
              return (
                <div key={b.CERT || i} className="fdic-rt-card" onClick={() => onSelect(b.CERT)}>
                  <div className="fdic-rt-card-top">
                    <span className="fdic-rt-card-rank">{rank}</span>
                    <div className="fdic-rt-card-id">
                      <div className="fdic-rt-name">{b.NAME}</div>
                      <div className="fdic-rt-sub">{[b.CITY, b.STALP || b.STNAME].filter(Boolean).join(", ")} · #{b.CERT} · {fmtDollars(b.ASSET)}</div>
                    </div>
                    <button className={"fdic-rt-star" + (watched ? " on" : "")} onClick={(e) => toggleWatch(e, b)} aria-label="Watch">
                      <svg width="16" height="16" viewBox="0 0 24 24" fill={watched ? "currentColor" : "none"} stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>
                    </button>
                  </div>

                  <div className="fdic-rt-card-signal">{s.primarySignal}</div>
                  {s.badges && s.badges.length > 0 && <SignalBadges badges={s.badges} />}

                  <div className="fdic-rt-card-pills">
                    <span className="fdic-seller-pill" style={{ color: sellerFill(s.sellerLabel).color, borderColor: sellerFill(s.sellerLabel).border, background: sellerFill(s.sellerLabel).bg }}>
                      {s.sellerScore} · {s.sellerLabel}
                    </span>
                    <span className="fdic-status-pill" style={{
                      color: s.dataStatusOverall === "Live" ? "var(--status-positive)" : "var(--vrb-ink-400)",
                      background: s.dataStatusOverall === "Live" ? "transparent" : "var(--vrb-ink-50)",
                    }}>{s.dataStatusOverall}</span>
                  </div>

                  {showAllColumns && (
                    <div className="fdic-rt-card-metrics">
                      <div><span>Target RE Loans</span><strong>{s.targetReLoans > 0 ? fmtDollars(s.targetReLoans) : "—"}</strong></div>
                      <div><span>NPL / Loans</span><strong>{s.nplRatio != null ? s.nplRatio.toFixed(1) + "%" : "—"}</strong></div>
                      <div><span>Severe HFS</span><strong>{fmtDollars(s.severeHFS)}</strong></div>
                      <div><span>Sold NAs</span><strong>{fmtDollars(s.soldNonaccrual)}</strong></div>
                      <div><span>RE NCO</span><strong>{s.reNcoRatio != null ? s.reNcoRatio.toFixed(2) + "%" : "—"}</strong></div>
                      <div><span>OREO</span><strong>{s.oreo > 0 ? fmtDollars(s.oreo) : "$0"}</strong></div>
                      <div><span>Texas</span><strong>{s.texas != null ? s.texas.toFixed(0) + "%" : "—"}</strong></div>
                    </div>
                  )}
                </div>
              );
            })}
            {pageData.length === 0 && <div className="fdic-rt-empty">No banks match the selected signal filters in this scope.</div>}
          </div>

          <div className="fdic-rt-foot">Severe HFS and Sold Nonaccruals are aggregate RC-N memorandum fields, sourced live from the FFIEC CDR for the top ~175 distress candidates (weekly cache) — shown as "—" for banks outside that set.</div>
          {sorted.length > pageData.length && (
            <FdicGateCTA total={sorted.length} shown={pageData.length} />
          )}
        </>
      )}
    </div>
  );
}


//  LANDING STATE 
function FdicCTABand() {
  return (
    <section className="cta-section" id="lead-form">
      <div className="cta-inner">
        <Reveal variant="right">
          <div className="cta-copy">
            <div className="eyebrow eyebrow-on-navy">Accredited Investors</div>
            <h2>The investor guide and a conversation.</h2>
            <p>Qualified accredited investors may request the VRB Capital Investor Guide and an introductory conversation with our investment team.</p>
            <ul>
              <li>Complete investor guide</li>
              <li>30‑minute call with a member of our investment team</li>
            </ul>
            <a className="cta-copy-sublink" href="https://www.investor.gov/introduction-investing/general-resources/news-alerts/alerts-bulletins/investor-bulletins/updated-3" target="_blank" rel="noopener noreferrer">Not sure if you qualify? See the SEC's accredited investor definition ↗</a>
          </div>
        </Reveal>
        <Reveal variant="left" delay={120}>
          <LeadForm />
        </Reveal>
      </div>
    </section>
  );
}

function FdicGateCTA({ total, shown }) {
  const locked = Math.max(0, total - shown);
  return (
    <div className="fdic-gate">
      <div className="fdic-gate-lead">
        <div className="fdic-gate-lock" aria-hidden="true">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
        </div>
        <div>
          <div className="fdic-gate-title">{locked.toLocaleString()} more ranked institutions in this view</div>
          <div className="fdic-gate-sub">The full Seller Signal Score screen, per-bank dashboards, and CSV export are available to qualified accredited investors.</div>
        </div>
      </div>
    </div>
  );
}

function FDICLanding({ onSelect, watchlist, stateFilter, assetFilter, targetType, signalType, sellerSignal, sortBy, onSignalType, onSortChange }) {
  return (
    <div className="fdic-landing">
      <WatchlistPanel watchlist={watchlist.list} onSelect={onSelect} onRemove={watchlist.remove} />
      <StressLeaderboard
        onSelect={onSelect}
        watchlist={watchlist}
        stateFilter={stateFilter}
        assetFilter={assetFilter}
        targetType={targetType}
        signalType={signalType}
        sellerSignal={sellerSignal}
        sortBy={sortBy}
        onSignalType={onSignalType}
        onSortChange={onSortChange}
      />
    </div>
  );
}

//  BRANCHES PANEL 

function BranchesPanel({ cert, inst, fin, onClose }) {
  const [branches, setBranches] = useState(null);
  const [loading, setLoading]   = useState(true);
  const [selected, setSelected] = useState(null);
  const [filter, setFilter]     = useState("");

  useEffect(() => {
    fetchBranches(cert)
      .then(b => { setBranches(b); if (b.length) setSelected(b[0]); })
      .catch(() => setBranches([]))
      .finally(() => setLoading(false));
  }, [cert]);

  const filtered = useMemo(() => {
    if (!branches) return [];
    if (!filter.trim()) return branches;
    const q = filter.trim().toLowerCase();
    return branches.filter(b =>
      (b.OFFNAME || "").toLowerCase().includes(q) ||
      (b.CITY || "").toLowerCase().includes(q) ||
      (b.STALP || "").toLowerCase().includes(q) ||
      (b.ADDRESS || "").toLowerCase().includes(q)
    );
  }, [branches, filter]);

  const fullServiceCount = (branches || []).filter(b => b.SERVTYPE === 11 || b.SERVTYPE === 12).length;
  const limitedCount = (branches || []).length - fullServiceCount;

  return (
    <div className="fdic-branches-panel">
      <div className="fdic-branches-header">
        <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
          <span style={{ fontFamily: "'MyriadPro-Semibold','Trebuchet MS',sans-serif", fontSize: "1rem", color: "var(--vrb-ink-900)" }}>Branch Locations</span>
          {branches && (
            <span style={{ fontSize: "0.75rem", background: "var(--vrb-light-blue)", color: "#2E75B6", borderRadius: 20, padding: "2px 10px", fontWeight: 700 }}>
              {branches.length} locations
            </span>
          )}
          {branches && fullServiceCount > 0 && (
            <span style={{ fontSize: "0.75rem", background: "var(--status-positive-bg)", color: "var(--status-positive)", borderRadius: 20, padding: "2px 10px", fontWeight: 700 }}>
              {fullServiceCount} full service
            </span>
          )}
          {branches && limitedCount > 0 && (
            <span style={{ fontSize: "0.75rem", background: "var(--status-caution-bg)", color: "var(--status-caution)", borderRadius: 20, padding: "2px 10px", fontWeight: 700 }}>
              {limitedCount} limited/other
            </span>
          )}
        </div>
        <button className="fdic-btn fdic-btn-outline" onClick={onClose} style={{ fontSize: "0.78rem" }}>Close</button>
      </div>

      {loading && <SkeletonCard height={120} />}
      {!loading && branches?.length === 0 && (
        <div className="fdic-history-empty">No location data on record for this institution.</div>
      )}
      {!loading && branches?.length > 0 && (
        <div className="fdic-branches-body">
          {/* Left: filterable list */}
          <div className="fdic-branches-list-col">
            <input
              className="fdic-branches-filter"
              type="text"
              placeholder="Filter by city, name, address…"
              value={filter}
              onChange={e => setFilter(e.target.value)}
            />
            <div className="fdic-branches-list">
              {filtered.length === 0 && (
                <div style={{ padding: "12px 14px", fontSize: "0.82rem", color: "var(--vrb-ink-400)" }}>No locations match "{filter}"</div>
              )}
              {filtered.map(b => {
                const isMain = b.MAINOFF === 1;
                const isSelected = selected
                  ? (b.OFFNUM === selected.OFFNUM && b.CITY === selected.CITY)
                  : false;
                const isFullService = b.SERVTYPE === 11 || b.SERVTYPE === 12;
                return (
                  <div
                    key={String(b.OFFNUM) + b.CITY}
                    onClick={() => setSelected(b)}
                    className={"fdic-branch-item" + (isSelected ? " active" : "")}
                  >
                    <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 6 }}>
                      <div style={{ fontWeight: 600, fontSize: "0.85rem", flex: 1 }}>
                        {isMain ? "Main Office" : (b.OFFNAME || "Office #" + b.OFFNUM)}
                      </div>
                      {isMain && (
                        <span style={{ fontSize: "0.65rem", background: isSelected ? "rgba(255,255,255,0.25)" : "var(--vrb-navy,#1F3864)", color: "#fff", borderRadius: 3, padding: "1px 6px", flexShrink: 0 }}>HQ</span>
                      )}
                      {!isMain && (
                        <span style={{ fontSize: "0.65rem", background: isSelected ? "rgba(255,255,255,0.2)" : (isFullService ? "var(--status-positive-bg)" : "var(--vrb-ink-100)"), color: isSelected ? "#fff" : (isFullService ? "var(--status-positive)" : "var(--vrb-ink-500)"), borderRadius: 3, padding: "1px 6px", flexShrink: 0 }}>
                          {isFullService ? "Full" : "Ltd"}
                        </span>
                      )}
                    </div>
                    <div style={{ fontSize: "0.75rem", opacity: 0.75, marginTop: 3 }}>
                      {[b.CITY, b.STALP].filter(Boolean).join(", ")}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Right: detail card */}
          {selected && (() => {
            const latest = fin?.[0];
            const prev   = fin?.[1];
            const isMain = selected.MAINOFF === 1;
            const mapQ   = encodeURIComponent([selected.ADDRESS, selected.CITY, selected.STALP, selected.ZIP].filter(Boolean).join(", "));
            const texas  = latest ? calcTexasRatio(latest) : null;
            const tb     = texas != null ? texasBand(texas) : null;
            const yearsOpen = selected.ESTYMD ? (() => {
              const parts = selected.ESTYMD.match(/(\d{2})\/(\d{2})\/(\d{4})/);
              return parts ? new Date().getFullYear() - parseInt(parts[3], 10) : null;
            })() : null;
            return (
              <div className="fdic-branch-detail">
                {/* Branch identity */}
                <div className="fdic-branch-detail-title">
                  {isMain ? "Main Office" : (selected.OFFNAME || "Office #" + selected.OFFNUM)}
                  {isMain && <span style={{ marginLeft: 8, fontSize: "0.7rem", background: "var(--vrb-navy,#1F3864)", color: "#fff", borderRadius: 3, padding: "2px 7px" }}>HQ</span>}
                </div>

                {/* Location info */}
                <div className="fdic-branch-detail-grid" style={{ marginBottom: 20 }}>
                  {[
                    { label: "Address", value: [selected.ADDRESS, selected.CITY, selected.STALP, selected.ZIP].filter(Boolean).join(", ") },
                    { label: "Service Type", value: selected.SERVTYPE_DESC || "—" },
                    { label: "Established", value: fmtDate(selected.ESTYMD) + (yearsOpen ? ` (${yearsOpen} yrs)` : "") },
                    { label: "Office #", value: selected.OFFNUM != null ? String(selected.OFFNUM) : "—" },
                  ].map(r => (
                    <div key={r.label} className="fdic-branch-detail-row">
                      <div className="fdic-branch-detail-label">{r.label}</div>
                      <div className="fdic-branch-detail-value">{r.value || "—"}</div>
                    </div>
                  ))}
                </div>

                <a className="fdic-map-link" href={"https://www.google.com/maps/search/?api=1&query=" + mapQ} target="_blank" rel="noopener noreferrer">
                  View on Google Maps
                </a>

                {/* Institution financial snapshot */}
                {latest && (
                  <div className="fdic-branch-fin">
                    <div className="fdic-branch-fin-title">
                      Institution Financial Snapshot
                      {inst?.NAME && <span style={{ fontWeight: 400, color: "var(--vrb-ink-500)", marginLeft: 6 }}>— {inst.NAME}</span>}
                    </div>
                    <div className="fdic-branch-fin-grid">
                      {[
                        { label: "Total Assets",    val: fmtDollars(latest.ASSET),   trend: prev ? (latest.ASSET > prev.ASSET ? "▲" : "▼") : null, up: latest.ASSET >= (prev?.ASSET||0) },
                        { label: "Total Deposits",  val: fmtDollars(latest.DEP),     trend: prev ? (latest.DEP > prev.DEP ? "▲" : "▼") : null,   up: latest.DEP >= (prev?.DEP||0) },
                        { label: "Net Income",      val: fmtDollars(latest.NETINC),  trend: prev ? (latest.NETINC > prev.NETINC ? "▲" : "▼") : null, up: latest.NETINC >= (prev?.NETINC||0) },
                        { label: "ROA",             val: fmtPct(latest.ROA) },
                        { label: "ROE",             val: fmtPct(latest.ROE) },
                        { label: "NIM",             val: fmtPct(latest.NIMY) },
                        { label: "Tier 1 Leverage", val: fmtPct(latest.RBCT1CER) },
                        { label: "Risk-Based Cap",  val: fmtPct(latest.RBCRWAJ) },
                      ].map(r => (
                        <div key={r.label} className="fdic-branch-fin-item">
                          <div className="fdic-branch-fin-val">
                            {r.val}
                            {r.trend && <span style={{ marginLeft: 4, fontSize: "0.7rem", color: r.up ? "var(--status-positive)" : "var(--status-negative)" }}>{r.trend}</span>}
                          </div>
                          <div className="fdic-branch-fin-lbl">{r.label}</div>
                        </div>
                      ))}
                    </div>

                    {/* Texas Ratio */}
                    {texas != null && (
                      <div className="fdic-branch-ratios">
                        <div className="fdic-branch-ratio-item">
                          <div className="fdic-branch-ratio-label">Texas Ratio</div>
                          <div className="fdic-branch-ratio-bar-track">
                            <div className="fdic-branch-ratio-bar-fill" style={{ width: Math.min(100,texas).toFixed(1)+"%", background: tb.color }} />
                          </div>
                          <span style={{ fontSize: "0.9rem", fontWeight: 700, color: tb.color }}>{texas.toFixed(1)}%</span>
                          <span className="fdic-bc-band-pill" style={{ background: tb.bg, color: tb.color, fontSize: "0.7rem" }}>{tb.label}</span>
                        </div>
                      </div>
                    )}
                  </div>
                )}
              </div>
            );
          })()}
        </div>
      )}
    </div>
  );
}

//  BANK HEADER 
function BankHeader({ inst, fin, isWatched, onWatch, onCompare, onExportPDF }) {
  if (!inst) return null;
  const latest = fin?.[0];
  const quarter = latest ? reptdateToQuarter(latest.REPDTE) : "";
  const texas   = latest ? calcTexasRatio(latest) : null;
  const tb      = texas != null ? texasBand(texas) : null;
  const isStale = (() => {
    if (!latest?.REPDTE) return false;
    const s = String(latest.REPDTE);
    const d = new Date(s.slice(0,4), parseInt(s.slice(4,6),10)-1, parseInt(s.slice(6,8),10));
    return (new Date() - d) / (1000 * 60 * 60 * 24 * 30) > 6;
  })();

  return (
    <div className="fdic-bank-header">
      {/* Top strip — identity + actions */}
      <div className="fdic-bank-header-top">
        <div className="fdic-bank-title">
          <h2>{inst.NAME}</h2>
          <div className="fdic-bank-meta">
            <span className="fdic-badge">FDIC #{inst.CERT}</span>
            {inst.RSSDID && <span className="fdic-badge">RSSD {inst.RSSDID}</span>}
            <span>{inst.CITY}, {inst.STNAME}</span>
            {inst.OFFICES && <span>{inst.OFFICES} locations</span>}
            {inst.WEBADDR && (
              <a href={inst.WEBADDR.startsWith("http") ? inst.WEBADDR : "https://" + inst.WEBADDR}
                 target="_blank" rel="noopener noreferrer" className="fdic-bank-web">
                {inst.WEBADDR.replace(/^https?:\/\//,"").replace(/\/$/,"")}
              </a>
            )}
            {quarter && (
              <span className={isStale ? "fdic-data-stale" : "fdic-data-date"}>
                {isStale ? "Stale · " : ""}Data: {quarter}
              </span>
            )}
          </div>
        </div>
        <div className="fdic-bank-actions">
          <button className={`fdic-btn fdic-btn-outline fdic-btn-watch ${isWatched ? "watching" : ""}`} onClick={onWatch}>
            {isWatched ? "Watching" : "Watch"}
          </button>
          <button className="fdic-btn fdic-btn-outline" onClick={onCompare}>Compare</button>
          <button className="fdic-btn fdic-btn-primary" onClick={onExportPDF}>Export PDF</button>
        </div>
      </div>

      {/* Bottom strip — investor signal snapshot */}
      {latest && (() => {
        const sig = window.BankSignals ? window.BankSignals.compute(latest, fin?.[1], inst.CERT) : null;
        if (!sig) return null;
        const items = [
          { label: "Total Loans", val: fmtDollars(sig.totalLoans), primary: true },
          { label: "NPL / Loans", val: sig.nplRatio != null ? sig.nplRatio.toFixed(1) + "%" : "—", primary: true,
            color: sig.isNplOutlier ? "var(--status-negative-on-navy)" : null },
          { label: "Severe HFS", val: fmtDollars(sig.severeHFS), primary: true,
            color: sig.isHfsSignal ? "var(--vrb-sky)" : null,
            badge: sig.isHfsSignal ? "Sale signal" : null },
          { label: "Nonaccruals Sold", val: fmtDollars(sig.soldNonaccrual), primary: true,
            color: sig.isSoldSignal ? "var(--vrb-green)" : null,
            badge: sig.isSoldSignal ? "Proven seller" : null },
          { label: "RE Net Charge-Off", val: sig.reNcoRatio != null ? sig.reNcoRatio.toFixed(2) + "%" : "—",
            color: sig.isCoSpike ? "var(--status-caution-on-navy)" : null },
          { label: "OREO", val: sig.oreo > 0 ? fmtDollars(sig.oreo) : "$0",
            color: sig.isOreoHeavy ? "var(--status-caution-on-navy)" : null },
          { label: "Texas Ratio", val: sig.texas != null ? sig.texas.toFixed(0) + "%" : "—",
            color: sig.isTexasDanger ? "var(--status-negative-on-navy)" : (tb ? tb.pop : null),
            badge: tb ? tb.label : null, badgeColor: tb ? tb.pop : null },
          { label: "Total Assets", val: fmtDollars(latest.ASSET) },
        ];
        return (
          <div className="fdic-bank-snapshot">
            {items.map(s => (
              <div key={s.label} className={"fdic-snap-item" + (s.primary ? " fdic-snap-primary" : "")}>
                <div className="fdic-snap-val" style={s.color ? { color: s.color } : null}>{s.val}</div>
                <div className="fdic-snap-lbl">{s.label}{s.badge && <span className="fdic-snap-badge" style={s.badgeColor ? { "--pop": s.badgeColor, color: "#1F3864" } : null}>{s.badge}</span>}</div>
              </div>
            ))}
            <div className="fdic-snap-item fdic-snap-seller">
              <div className="fdic-snap-val" style={{ color: sellerFill(sig.sellerLabel).border }}>{sig.sellerScore}</div>
              <div className="fdic-snap-lbl">Seller Signal <span className="fdic-snap-badge" style={{ background: sellerFill(sig.sellerLabel).bg !== "transparent" ? sellerFill(sig.sellerLabel).bg : sellerFill(sig.sellerLabel).border + "22", color: sellerFill(sig.sellerLabel).bg !== "transparent" ? "#fff" : sellerFill(sig.sellerLabel).border }}>{sig.sellerLabel}</span></div>
            </div>
          </div>
        );
      })()}
    </div>
  );
}

//  SUMMARY STATS 
function SummaryStats({ fin }) {
  if (!fin?.length) return <SkeletonRow cols={4} />;
  const latest = fin[0];
  const prev   = fin[1];
  const npl = (Number(latest.P9ASSET) || 0) + (Number(latest.LNLSNTV) || 0);
  const prevNpl = prev ? (Number(prev.P9ASSET) || 0) + (Number(prev.LNLSNTV) || 0) : null;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Summary</div>
      <div className="fdic-stat-row fdic-stat-row-4">
        {[
          { label: "Total Assets (TA)", val: fmtDollars(latest.ASSET), trend: <TrendBadge current={latest.ASSET} previous={prev?.ASSET} /> },
          { label: "Non-Performing Loans (NPL)", val: fmtDollars(npl), trend: <TrendBadge current={npl} previous={prevNpl} inverseGood /> },
          { label: "Real Estate Owned (REO)", val: fmtDollars(latest.FREPO) },
          { label: "Total Deposits (DEP)", val: fmtDollars(latest.DEP), trend: <TrendBadge current={latest.DEP} previous={prev?.DEP} /> },
        ].map(s => (
          <div key={s.label} className="fdic-stat-card">
            <div className="fdic-stat-label">{s.label}</div>
            <div className="fdic-stat-value">{s.val}</div>
            {s.trend}
          </div>
        ))}
      </div>
    </div>
  );
}

//  CAPITAL HEALTH 
function CapitalHealth({ fin }) {
  if (!fin?.length) return <SkeletonRow cols={5} />;
  const latest = fin[0];

  const cards = [
    { label: "Tier 1 Leverage Ratio (T1LR)", field: "RBCT1CER", threshold: "Reg. min: 4%", maxBar: 20,
      sub: "Core capital as % of average assets — the primary solvency test" },
    { label: "Tier 1 Risk-Based Capital (T1RBC)", field: "RBC1RWAJ", threshold: "Reg. min: 6%", maxBar: 25,
      sub: "Core capital vs. risk-weighted assets — measures credit risk coverage" },
    { label: "Total Risk-Based Capital (TRBC)", field: "RBCRWAJ", threshold: "Reg. min: 8%", maxBar: 25,
      sub: "All qualifying capital vs. risk-weighted assets — broadest capital test" },
    { label: "Loan Loss Provisions (LLP)", field: "LNLSNET", dollar: true,
      sub: "Dollar amount set aside for expected future loan losses — higher = more trouble anticipated" },
    { label: "Allowance for Loan & Lease Losses (ALLL)", field: "LNLSRES", dollar: true,
      sub: "Cumulative reserve buffer against bad loans — the bank's built-up loss cushion" },
  ].filter(c => latest[c.field] != null && latest[c.field] !== "");

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Capital Health</div>
      <div className="fdic-stat-row" style={{ gridTemplateColumns: `repeat(${cards.length}, 1fr)` }}>
        {cards.map(c => {
          const val = latest[c.field];
          const color = c.dollar ? "blue" : capitalColor(c.field, val);
          const pct = c.maxBar ? Math.min(100, (Number(val) / c.maxBar) * 100) : 0;
          return (
            <div key={c.label} className="fdic-capital-card">
              <div className="fdic-stat-label">{c.label}</div>
              <div className={`fdic-capital-value ${color}`}>
                {c.dollar ? fmtDollars(val) : fmtPct(val)}
              </div>
              {!c.dollar && (
                <>
                  <div className="fdic-capital-bar-track">
                    <div className={`fdic-capital-bar-fill ${color}`} style={{ width: pct + "%" }} />
                  </div>
                  <div className="fdic-threshold-label">{c.threshold}</div>
                </>
              )}
              {c.sub && <div className="fdic-stat-sub" style={{ marginTop: 6, fontSize: "0.7rem", color: "var(--vrb-ink-400)", lineHeight: 1.4 }}>{c.sub}</div>}
            </div>
          );
        })}
      </div>
    </div>
  );
}

//  TEXAS RATIO GAUGE 
function TexasRatioGauge({ fin }) {
  const canvasRef = useRef(null);
  const chartRef = useRef(null);

  const latest = fin?.[0];
  const ratio = latest ? calcTexasRatio(latest) : null;
  const band = ratio != null ? texasBand(ratio) : null;

  useEffect(() => {
    if (!canvasRef.current || ratio == null || typeof Chart === "undefined") return;
    if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; }

    const clamped = Math.min(ratio, 150);
    const remaining = Math.max(0, 150 - clamped);

    chartRef.current = new Chart(canvasRef.current, {
      type: "doughnut",
      data: {
        datasets: [{
          data: [clamped, remaining],
          backgroundColor: [band.color, "var(--vrb-ink-100)"],
          borderWidth: 0,
          circumference: 180,
          rotation: 270,
        }]
      },
      options: {
        responsive: false,
        cutout: "72%",
        plugins: { legend: { display: false }, tooltip: { enabled: false } },
        animation: { duration: 800 }
      }
    });
    return () => { if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; } };
  }, [ratio]);

  if (!fin?.length) return <SkeletonCard height={160} />;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Texas Ratio</div>
      <div className="fdic-texas-wrap">
        <div className="fdic-texas-gauge">
          <canvas ref={canvasRef} width={180} height={100} />
        </div>
        <div className="fdic-texas-info">
          <div className="fdic-texas-value" style={{ color: band?.color }}>
            {ratio != null ? ratio.toFixed(1) + "%" : "N/A"}
          </div>
          {band && <div className={`fdic-texas-band ${band.cls}`}>{band.label}</div>}
          <div className="fdic-threshold-label" style={{ marginTop: 10, fontSize: "0.78rem", color: "var(--vrb-ink-500)" }}>
            Healthy &lt;50 · Watch 50–75 · Stressed 75–100 · Danger &gt;100
          </div>
          <div className="fdic-texas-formula">
            (Non-Performing Loans + Foreclosed Properties) ÷ (Equity + Loan Loss Reserves) × 100
          </div>
          <div style={{ marginTop: 10, fontSize: "0.72rem", color: "var(--vrb-ink-500)", lineHeight: 1.5, maxWidth: 340 }}>
            <strong style={{ color: "var(--vrb-ink-700)" }}>What this means:</strong> Compares a bank's troubled assets against its ability to absorb losses. When the ratio crosses 100%, the bank's bad loans and foreclosed properties exceed all capital and reserves — historically, the majority of banks that reach this level either fail or are absorbed by a healthier institution. VRB monitors this as the primary signal that a bank may need to sell distressed mortgage notes to clean its balance sheet.
          </div>
        </div>
      </div>
    </div>
  );
}

//  DELINQUENCY INDICATORS 
function DelinquencyIndicators({ fin }) {
  if (!fin?.length) return <SkeletonRow cols={3} />;
  const latest = fin[0];
  const prev   = fin[1];

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Delinquency Indicators</div>
      <div className="fdic-stat-row fdic-stat-row-3">
        {[
          { label: "30–89 Days Past Due (Early DPD)", field: "P3ASSET",
            sub: "Loans 1–3 months behind — early warning stage, borrower may still recover" },
          { label: "90+ Days Past Due (DPD 90+)",    field: "P9ASSET",
            sub: "Loans 3+ months overdue — serious delinquency, likely to become non-performing" },
          { label: "Nonaccrual Loans (NAL)",          field: "LNLSNTV",
            sub: "Bank stopped recording interest income — these loans are effectively impaired" },
        ].map(c => (
          <div key={c.label} className="fdic-stat-card">
            <div className="fdic-stat-label">{c.label}</div>
            <div className="fdic-stat-value">{fmtDollars(latest[c.field])}</div>
            <TrendBadge current={latest[c.field]} previous={prev?.[c.field]} inverseGood />
            {c.sub && <div className="fdic-stat-sub" style={{ marginTop: 4, fontSize: "0.7rem", color: "var(--vrb-ink-400)", lineHeight: 1.4 }}>{c.sub}</div>}
          </div>
        ))}
      </div>
    </div>
  );
}

//  KPI RATIOS 
function KPIRatios({ fin }) {
  if (!fin?.length) return <SkeletonRow cols={4} />;
  const latest = fin[0];
  const prev   = fin[1];

  const ratios = [
    { label: "Return on Assets (ROA)",   field: "ROA",   pct: true,
      sub: "Net income ÷ total assets — measures how profitably the bank uses what it owns. Healthy: >1%" },
    { label: "Return on Equity (ROE)",   field: "ROE",   pct: true,
      sub: "Net income ÷ shareholder equity — shareholder return. Healthy: >10%" },
    { label: "Net Interest Margin (NIM)",field: "NIMY",  pct: true,
      sub: "Interest earned minus interest paid, as % of earning assets — the bank's core spread. Healthy: >3%" },
    { label: "Efficiency Ratio (ER)",    field: "EEFFR", pct: true, inverseGood: true,
      sub: "Overhead costs ÷ revenue — lower is better. Below 60% = efficient; above 80% = struggling" },
  ].filter(c => latest[c.field] != null && latest[c.field] !== "");

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Key Performance Ratios</div>
      <div className="fdic-stat-row" style={{ gridTemplateColumns: `repeat(${ratios.length}, 1fr)` }}>
        {ratios.map(c => (
          <div key={c.label} className="fdic-stat-card">
            <div className="fdic-stat-label">{c.label}</div>
            <div className="fdic-stat-value">{fmtPct(latest[c.field])}</div>
            <TrendBadge current={latest[c.field]} previous={prev?.[c.field]} inverseGood={c.inverseGood} />
            {c.sub && <div className="fdic-stat-sub" style={{ marginTop: 4, fontSize: "0.7rem", color: "var(--vrb-ink-400)", lineHeight: 1.4 }}>{c.sub}</div>}
          </div>
        ))}
      </div>
    </div>
  );
}

//  FUNDING & INCOME PROFILE 
function FundingProfile({ fin }) {
  if (!fin?.length) return null;
  const latest = fin[0];

  const dep = Number(latest.DEP) || 0;
  const brokPct = (latest.BRO != null && latest.BRO !== "" && dep > 0)
    ? (Number(latest.BRO) / dep * 100) : null;
  const brokColor = brokPct == null ? null : brokPct > 20 ? "var(--status-negative)" : brokPct > 10 ? "var(--status-caution)" : "var(--status-positive)";

  const items = [
    {
      label: "Brokered Deposits (BD)",
      val: latest.BRO,
      fmt: "dollar",
      sub: brokPct != null ? `${brokPct.toFixed(1)}% of deposits — expensive, volatile funding source` : "Deposits sourced via brokers — above 10% signals fragile funding",
      subColor: brokColor,
    },
    { label: "Securities Portfolio (SP)", val: latest.SC, fmt: "dollar",
      sub: latest.SCMTGBK != null && latest.SCMTGBK !== "" ? `${fmtDollars(latest.SCMTGBK)} in Mortgage-Backed Securities (MBS)` : "Investment securities held on balance sheet" },
    { label: "Interest Income (II)",      val: latest.INTINC,  fmt: "dollar",
      sub: "Revenue earned on loans and investments" },
    { label: "Interest Expense (IE)",     val: latest.EINTEXP, fmt: "dollar",
      sub: "Cost paid on deposits and borrowings" },
    { label: "Non-Interest Income (NII)", val: latest.NONII,   fmt: "dollar",
      sub: "Fee-based revenue — service charges, trading, other income" },
    { label: "Non-Interest Expense (NIX)",val: latest.NONIX,   fmt: "dollar",
      sub: "Overhead — salaries, occupancy, technology" },
  ].filter(c => c.val != null && c.val !== "");

  if (items.length === 0) return null;

  const cols = items.length <= 3 ? items.length : items.length <= 6 ? 3 : 4;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Funding &amp; Income Profile</div>
      <div className="fdic-stat-row" style={{ gridTemplateColumns: `repeat(${cols}, 1fr)` }}>
        {items.map(c => (
          <div key={c.label} className="fdic-stat-card">
            <div className="fdic-stat-label">{c.label}</div>
            <div className="fdic-stat-value">{fmtDollars(c.val)}</div>
            {c.sub && (
              <div className="fdic-stat-sub" style={c.subColor ? { color: c.subColor, fontWeight: 600 } : {}}>
                {c.sub}
              </div>
            )}
          </div>
        ))}
      </div>
      {brokPct != null && brokPct > 10 && (
        <div className="fdic-funding-alert" style={{ "--alert-color": brokColor }}>
          Brokered deposits represent <strong>{brokPct.toFixed(1)}%</strong> of total deposits
          {brokPct > 20 ? " — elevated funding risk, potential distress signal" : " — above average, monitor for liquidity pressure"}.
        </div>
      )}
    </div>
  );
}

//  CRE OWNER / NON-OWNER BREAKDOWN 
function CREBreakdown({ fin }) {
  if (!fin?.length) return null;
  const latest = fin[0];

  const total    = Number(latest.LNRENRES) || 0;
  const ownerOcc = Number(latest.LNRENROW) || 0;
  const nonOwner = Number(latest.LNRENRN)  || 0;
  const lnls     = Number(latest.LNLS)     || 0;

  if (total === 0) return null;

  const creConc    = lnls > 0 ? (total / lnls * 100).toFixed(1) : null;
  const ownerPct   = total > 0 && ownerOcc > 0 ? (ownerOcc / total * 100).toFixed(1) : null;
  const nonOwnerPct= total > 0 && nonOwner > 0 ? (nonOwner / total * 100).toFixed(1) : null;
  const hasSplit   = ownerOcc > 0 || nonOwner > 0;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Commercial CRE Breakdown (Nonfarm Nonresidential)</div>
      <div style={{ fontSize: "0.76rem", color: "var(--vrb-ink-500)", marginBottom: 14, lineHeight: 1.5 }}>
        Commercial Real Estate (CRE) loans are split into two types. <strong>Owner-Occupied</strong> means the borrowing business uses the property itself (e.g. a medical office, retail store) — lower credit risk. <strong>Non-Owner-Occupied</strong> means the property is purely investment-driven (office buildings, strip malls rented to tenants) — higher credit risk.
      </div>
      <div className="fdic-stat-row" style={{ gridTemplateColumns: hasSplit ? "repeat(3,1fr)" : "repeat(2,1fr)" }}>
        <div className="fdic-stat-card">
          <div className="fdic-stat-label">Total Comm. CRE (LNRENRES)</div>
          <div className="fdic-stat-value">{fmtDollars(total)}</div>
          {creConc && <div className="fdic-stat-sub">{creConc}% of total loan book</div>}
          <div className="fdic-stat-sub" style={{ marginTop: 4, fontSize: "0.68rem", color: "var(--vrb-ink-400)" }}>Nonfarm nonresidential RE — excludes residential, multifamily &amp; construction</div>
        </div>
        {hasSplit ? (
          <>
            <div className="fdic-stat-card">
              <div className="fdic-stat-label">Owner-Occupied CRE (OO-CRE)</div>
              <div className="fdic-stat-value">{fmtDollars(ownerOcc)}</div>
              {ownerPct && <div className="fdic-stat-sub" style={{ color: "var(--status-positive)" }}>{ownerPct}% of CRE</div>}
              <div className="fdic-stat-sub" style={{ marginTop: 4, fontSize: "0.68rem", color: "var(--vrb-ink-400)" }}>Business owns &amp; occupies the property — lower default risk</div>
            </div>
            <div className="fdic-stat-card">
              <div className="fdic-stat-label">Non-Owner-Occupied CRE (NOO-CRE)</div>
              <div className="fdic-stat-value">{fmtDollars(nonOwner)}</div>
              {nonOwnerPct && <div className="fdic-stat-sub" style={{ color: "var(--status-caution)" }}>{nonOwnerPct}% of CRE</div>}
              <div className="fdic-stat-sub" style={{ marginTop: 4, fontSize: "0.68rem", color: "var(--vrb-ink-400)" }}>Investment property rented to tenants — higher risk, primary note inventory</div>
            </div>
          </>
        ) : (
          <div className="fdic-stat-card">
            <div className="fdic-stat-label">CRE Concentration</div>
            <div className="fdic-stat-value">{creConc ? creConc + "%" : "—"}</div>
            <div className="fdic-stat-sub">of total loan book</div>
            <div className="fdic-stat-sub" style={{ marginTop: 4, fontSize: "0.68rem", color: "var(--vrb-ink-400)" }}>Owner-occupied vs. non-owner-occupied sub-split not separately reported by this institution</div>
          </div>
        )}
      </div>
    </div>
  );
}

//  PORTFOLIO DISTRIBUTION CHART 
function PortfolioDistribution({ fin }) {
  const canvasRef = useRef(null);
  const chartRef  = useRef(null);
  const latest = fin?.[0];

  useEffect(() => {
    if (!canvasRef.current || !latest || typeof Chart === "undefined") return;
    if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; }

    // Residential & Other = Total RE minus known sub-categories (best available proxy for 1-4 family + other RE)
    const residualRE = Math.max(0,
      (Number(latest.LNRE) || 0) - (Number(latest.LNRENRES) || 0) -
      (Number(latest.LNRECONS) || 0) - (Number(latest.LNREMULT) || 0)
    );
    const rawCategories = [
      { label: "Residential & Other RE", value: residualRE,                          color: "var(--vrb-blue)" },
      { label: "Comm. CRE",              value: Number(latest.LNRENRES) || 0,        color: "#8b5cf6" },
      { label: "- Owner-Occupied",       value: Number(latest.LNRENROW) || 0,        color: "#a78bfa" },
      { label: "Construction",           value: Number(latest.LNRECONS) || 0,        color: "#6366f1" },
      { label: "Multifamily",            value: Number(latest.LNREMULT) || 0,        color: "#10b981" },
      { label: "C&I Loans",              value: Number(latest.LNCI) || 0,            color: "var(--status-caution)" },
      { label: "Consumer",               value: Number(latest.LNCON) || 0,           color: "#ec4899" },
      { label: "Auto Loans",             value: Number(latest.LNAUTO) || 0,          color: "#06b6d4" },
    ].filter(c => c.value > 0);
    const categories = rawCategories.map(c => ({ ...c, field: null }));

    chartRef.current = new Chart(canvasRef.current, {
      type: "bar",
      data: {
        labels: categories.map(c => c.label),
        datasets: [{
          data: categories.map(c => c.value * 1000),
          backgroundColor: categories.map(c => c.color),
          borderRadius: 4,
          borderWidth: 0,
        }]
      },
      options: {
        indexAxis: "y",
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: { display: false },
          tooltip: {
            callbacks: {
              label: ctx => fmtDollars(ctx.raw / 1000)
            }
          }
        },
        scales: {
          x: {
            grid: { color: "var(--vrb-ink-100)" },
            ticks: {
              callback: v => {
                if (v >= 1e9) return "$" + (v / 1e9).toFixed(0) + "B";
                if (v >= 1e6) return "$" + (v / 1e6).toFixed(0) + "M";
                return "$" + (v / 1e3).toFixed(0) + "K";
              }
            }
          },
          y: { grid: { display: false } }
        }
      }
    });
    return () => { if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; } };
  }, [latest]);

  if (!fin?.length) return <SkeletonCard height={280} />;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Portfolio Distribution</div>
      <div className="fdic-chart-container" style={{ height: 340 }}>
        <canvas ref={canvasRef} />
      </div>
      <div className="fdic-chart-note">Source: FDIC Call Reports · Values in USD</div>
    </div>
  );
}

//  LOAN PORTFOLIO RISK TABLE 
function LoanPortfolioRisk({ fin }) {
  if (!fin?.length) return <SkeletonCard height={200} />;
  const latest = fin[0];

  const rows = [
    { label: "Residential RE",  portfolio: "LNRE",     p3: "P3RE",     p9: "P9RE",     na: null },
    { label: "Comm. CRE",       portfolio: "LNRENRES", p3: "P3RENRES", p9: "P9RENRES", na: "NTRENRES" },
    { label: "Construction",    portfolio: "LNRECONS",p3: "P3RECONS", p9: "P9RECONS", na: "NTRECONS" },
    { label: "Multifamily",     portfolio: "LNREMULT",p3: "P3REMULT", p9: "P9REMULT", na: "NTREMULT" },
    { label: "C&I Loans",       portfolio: "LNCI",    p3: "P3CI",     p9: "P9CI",     na: "NTLNCI" },
  ].map(r => {
    const port = Number(latest[r.portfolio]) || 0;
    const p9   = r.p9 ? Math.max(0, Number(latest[r.p9]) || 0) : null;
    const na   = r.na ? Math.max(0, Number(latest[r.na]) || 0) : null;
    const p3   = r.p3 ? Math.max(0, Number(latest[r.p3]) || 0) : null;
    const nplPct = (p9 !== null && na !== null && port > 0) ? ((p9 + na) / port) * 100 : null;
    return { ...r, portVal: port, p3Val: p3, p9Val: p9, naVal: na, nplPct };
  }).filter(r => r.portVal > 0);

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Loan Portfolio Risk Analysis</div>
      <div className="fdic-table-wrap">
        <table className="fdic-table">
          <thead>
            <tr>
              <th>Loan Category</th>
              <th>Portfolio</th>
              <th>30–89 Days</th>
              <th>90+ Days</th>
              <th>Nonaccrual</th>
              <th>NPL %</th>
            </tr>
          </thead>
          <tbody>
            {rows.map(r => (
              <tr key={r.label}>
                <td className="label-cell">{r.label}</td>
                <td>{fmtDollars(r.portVal)}</td>
                <td>{r.p3Val !== null ? fmtDollars(r.p3Val) : "—"}</td>
                <td>{r.p9Val !== null ? fmtDollars(r.p9Val) : "—"}</td>
                <td>{r.naVal !== null ? fmtDollars(r.naVal) : "—"}</td>
                <td>
                  {r.nplPct !== null
                    ? <span className={`fdic-npl-pct ${nplPctColor(r.nplPct)}`}>{r.nplPct.toFixed(2)}%</span>
                    : <span className="fdic-npl-pct">—</span>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

//  ASSETS & DEPOSITS TREND 
function AssetsTrend({ fin }) {
  const canvasRef = useRef(null);
  const chartRef  = useRef(null);

  useEffect(() => {
    if (!canvasRef.current || !fin?.length || typeof Chart === "undefined") return;
    if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; }

    const reversed = [...fin].reverse();
    const labels = reversed.map(r => reptdateToQuarter(r.REPDTE));

    chartRef.current = new Chart(canvasRef.current, {
      type: "line",
      data: {
        labels,
        datasets: [
          {
            label: "Total Assets",
            data: reversed.map(r => (Number(r.ASSET) || 0) * 1000),
            borderColor: "#1F3864",
            backgroundColor: "rgba(31,56,100,0.08)",
            fill: true,
            tension: 0.3,
            pointRadius: 4,
            pointBackgroundColor: "#1F3864",
            yAxisID: "y",
          },
          {
            label: "Total Deposits",
            data: reversed.map(r => (Number(r.DEP) || 0) * 1000),
            borderColor: "#2E75B6",
            backgroundColor: "rgba(46,117,182,0.06)",
            fill: true,
            tension: 0.3,
            pointRadius: 4,
            pointBackgroundColor: "#2E75B6",
            yAxisID: "y",
          }
        ]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        interaction: { mode: "index", intersect: false },
        plugins: {
          legend: { position: "top" },
          tooltip: {
            callbacks: { label: ctx => ctx.dataset.label + ": " + fmtDollars(ctx.raw / 1000) }
          }
        },
        scales: {
          y: {
            grid: { color: "var(--vrb-ink-100)" },
            ticks: {
              callback: v => {
                if (v >= 1e9) return "$" + (v / 1e9).toFixed(1) + "B";
                if (v >= 1e6) return "$" + (v / 1e6).toFixed(1) + "M";
                return "$" + v.toFixed(0);
              }
            }
          },
          x: { grid: { display: false } }
        }
      }
    });
    return () => { if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; } };
  }, [fin]);

  if (!fin?.length) return <SkeletonCard height={240} />;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Assets &amp; Deposits Trend</div>
      <div className="fdic-chart-container" style={{ height: 240 }}>
        <canvas ref={canvasRef} />
      </div>
    </div>
  );
}

//  NPA RATIO TREND 
function NPATrend({ fin }) {
  const canvasRef = useRef(null);
  const chartRef  = useRef(null);

  useEffect(() => {
    if (!canvasRef.current || !fin?.length || typeof Chart === "undefined") return;
    if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; }

    const reversed = [...fin].reverse();
    const labels = reversed.map(r => reptdateToQuarter(r.REPDTE));
    const npaRatios = reversed.map(r => {
      const npa = (Number(r.P9ASSET) || 0) + (Number(r.LNLSNTV) || 0) + (Number(r.FREPO) || 0);
      const asset = Number(r.ASSET) || 1;
      return ((npa / asset) * 100);
    });

    chartRef.current = new Chart(canvasRef.current, {
      type: "line",
      data: {
        labels,
        datasets: [{
          label: "NPA / Total Assets (%)",
          data: npaRatios,
          borderColor: "var(--status-negative)",
          backgroundColor: "rgba(220,38,38,0.07)",
          fill: true,
          tension: 0.3,
          pointRadius: 4,
          pointBackgroundColor: "var(--status-negative)",
        }]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
          legend: { position: "top" },
          tooltip: { callbacks: { label: ctx => "NPA Ratio: " + ctx.raw.toFixed(2) + "%" } }
        },
        scales: {
          y: {
            grid: { color: "var(--vrb-ink-100)" },
            ticks: { callback: v => v.toFixed(1) + "%" }
          },
          x: { grid: { display: false } }
        }
      }
    });
    return () => { if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; } };
  }, [fin]);

  if (!fin?.length) return <SkeletonCard height={240} />;

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">NPA Ratio Trend</div>
      <div className="fdic-chart-container" style={{ height: 240 }}>
        <canvas ref={canvasRef} />
      </div>
      <div className="fdic-chart-note">NPA = 90+ Days + Nonaccrual + REO</div>
    </div>
  );
}

//  QUARTERLY TRENDS BY CATEGORY 
const TREND_CATEGORIES = [
  {
    label: "Residential RE",
    fields: { p3: "P3RE", p9: "P9RE", na: null }
  },
  {
    label: "Comm. CRE",
    fields: { p3: "P3RENRES", p9: "P9RENRES", na: "NTRENRES" }
  },
  {
    label: "Construction",
    fields: { p3: "P3RECONS", p9: "P9RECONS", na: "NTRECONS" }
  },
  {
    label: "Multifamily",
    fields: { p3: "P3REMULT", p9: "P9REMULT", na: "NTREMULT" }
  },
  {
    label: "C&I",
    fields: { p3: "P3CI", p9: "P9CI", na: null }
  },
];

function QuarterlyTrends({ fin }) {
  const [activeCat, setActiveCat] = useState(0);
  const canvasRef = useRef(null);
  const chartRef  = useRef(null);
  const cat = TREND_CATEGORIES[activeCat];

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || !fin?.length || typeof Chart === "undefined") return;

    // Destroy any existing chart and clear the canvas before redrawing
    if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; }
    const ctx2d = canvas.getContext("2d");
    if (ctx2d) ctx2d.clearRect(0, 0, canvas.width, canvas.height);

    const currentCat = TREND_CATEGORIES[activeCat];
    const data4 = fin.slice(0, 4);
    const reversed = [...data4].reverse();
    const labels = reversed.map(r => reptdateToQuarter(r.REPDTE));

    const datasets = [
      {
        label: "30–89 Days",
        data: reversed.map(r => (Number(r[currentCat.fields.p3]) || 0) * 1000),
        backgroundColor: "var(--status-caution)",
        stack: "s",
        borderRadius: currentCat.fields.na ? { topLeft: 0, topRight: 0 } : { topLeft: 4, topRight: 4 },
      },
      {
        label: "90+ Days",
        data: reversed.map(r => (Number(r[currentCat.fields.p9]) || 0) * 1000),
        backgroundColor: "#8b5cf6",
        stack: "s",
        borderRadius: currentCat.fields.na ? {} : { topLeft: 4, topRight: 4 },
      },
    ];
    if (currentCat.fields.na) {
      datasets.push({
        label: "Nonaccrual",
        data: reversed.map(r => (Number(r[currentCat.fields.na]) || 0) * 1000),
        backgroundColor: "#ec4899",
        stack: "s",
        borderRadius: { topLeft: 4, topRight: 4 },
      });
    }

    chartRef.current = new Chart(canvas, {
      type: "bar",
      data: { labels, datasets },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        interaction: { mode: "index" },
        plugins: {
          legend: { position: "top" },
          tooltip: { callbacks: { label: ctx => ctx.dataset.label + ": " + fmtDollars(ctx.raw / 1000) } }
        },
        scales: {
          x: { stacked: true, grid: { display: false } },
          y: {
            stacked: true,
            grid: { color: "var(--vrb-ink-100)" },
            ticks: {
              callback: v => {
                if (v >= 1e9) return "$" + (v / 1e9).toFixed(1) + "B";
                if (v >= 1e6) return "$" + (v / 1e6).toFixed(1) + "M";
                if (v >= 1e3) return "$" + (v / 1e3).toFixed(0) + "K";
                return "$" + v;
              }
            }
          }
        }
      }
    });
    return () => { if (chartRef.current) { chartRef.current.destroy(); chartRef.current = null; } };
  }, [fin, activeCat]);

  if (!fin?.length) return <SkeletonCard height={320} />;

  const tableData = fin.slice(0, 4).map(r => ({
    quarter: reptdateToQuarter(r.REPDTE),
    p3: fmtDollars(r[cat.fields.p3], 1, true),
    p9: fmtDollars(r[cat.fields.p9], 1, true),
    na: cat.fields.na ? fmtDollars(r[cat.fields.na], 1, true) : null,
  }));

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">Quarterly Trends by Category</div>
      <div style={{ marginBottom: 8, fontSize: "0.8rem", color: "var(--vrb-ink-500)" }}>Select Category:</div>
      <div className="fdic-tabs">
        {TREND_CATEGORIES.map((c, i) => (
          <button key={c.label} className={`fdic-tab ${activeCat === i ? "active" : ""}`}
            onClick={() => setActiveCat(i)}>{c.label}</button>
        ))}
      </div>
      <div className="fdic-chart-container" style={{ height: 260 }}>
        <canvas ref={canvasRef} />
      </div>
      <div style={{ marginTop: 24 }}>
        <div style={{ fontSize: "0.85rem", fontWeight: 600, color: "var(--vrb-ink-700)", marginBottom: 10 }}>
          Historical Data — {cat.label}
        </div>
        <div className="fdic-table-wrap">
          <table className="fdic-table">
            <thead>
              <tr>
                <th>Quarter</th>
                <th>30–89 Days</th>
                <th>90+ Days</th>
                {cat.fields.na && <th>Nonaccrual</th>}
              </tr>
            </thead>
            <tbody>
              {tableData.map(r => (
                <tr key={r.quarter}>
                  <td className="label-cell">{r.quarter}</td>
                  <td>{r.p3}</td>
                  <td>{r.p9}</td>
                  {cat.fields.na && <td>{r.na}</td>}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

//  PEER BENCHMARKING 
function PeerBenchmarking({ fin, cert }) {
  const [peerData, setPeerData] = useState(null);
  const [loading, setLoading]   = useState(false);

  const latest = fin?.[0];

  useEffect(() => {
    if (!latest?.ASSET) return;
    setLoading(true);
    fetchPeerBanks(cert, Number(latest.ASSET))
      .then(setPeerData)
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [cert, latest?.ASSET]);

  if (!fin?.length) return <SkeletonCard height={160} />;
  if (loading) return <SkeletonCard height={160} />;
  if (!peerData) return null;

  const { rows, tierLabel } = peerData;

  const metrics = [
    { label: "ROA", field: "ROA", fmt: v => fmtPct(v), higherGood: true },
    { label: "ROE", field: "ROE", fmt: v => fmtPct(v), higherGood: true },
    { label: "NIM", field: "NIMY", fmt: v => fmtPct(v), higherGood: true },
    { label: "Tier 1 Capital", field: "RBCT1CER", fmt: v => fmtPct(v), higherGood: true },
    { label: "Total Risk-Based Cap", field: "RBCRWAJ", fmt: v => fmtPct(v), higherGood: true },
    { label: "Charge-off Rate", field: "NTLNLSR", fmt: v => fmtPct(v), higherGood: false },
  ];

  return (
    <div className="fdic-section">
      <div className="fdic-section-title">
        Peer Benchmarking
        <span style={{ fontSize: "0.75rem", fontWeight: 400, color: "var(--vrb-ink-400)", marginLeft: 8 }}>
          vs. {rows.length} peers · Asset tier: {tierLabel}
        </span>
      </div>
      <div className="fdic-peer-row">
        {metrics.map(m => {
          const thisVal = Number(latest[m.field]);
          const median  = peerMedian(rows, m.field);
          if (isNaN(thisVal) || median == null) return null;
          const diff = thisVal - median;
          const pct  = median !== 0 ? Math.abs(diff / median * 100).toFixed(0) : 0;
          const above = diff > 0;
          const good  = m.higherGood ? above : !above;
          const deltaLabel = above
            ? `▲ ${pct}% above peers`
            : `▼ ${pct}% below peers`;
          return (
            <div key={m.label} className="fdic-peer-card">
              <div className="fdic-peer-card-label">{m.label}</div>
              <div className="fdic-peer-compare">
                <div className="fdic-peer-this">{m.fmt(thisVal)}</div>
                <div className="fdic-peer-median">Peer median: {m.fmt(median)}</div>
              </div>
              <div className={`fdic-peer-delta ${good ? "below" : "above"}`}>{deltaLabel}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

//  BANK COMPARISON TOOL 
function BankComparison({ primaryCert, onClose }) {
  const [compareCert, setCompareCert] = useState(null);
  const [compareInst, setCompareInst] = useState(null);
  const [compareFin, setCompareFin]   = useState(null);
  const [primaryInst, setPrimaryInst] = useState(null);
  const [primaryFin, setPrimaryFin]   = useState(null);
  const [loading, setLoading]         = useState(false);

  useEffect(() => {
    if (!primaryCert) return;
    Promise.all([fetchInstitution(primaryCert), fetchFinancials(primaryCert, 1)])
      .then(([inst, fin]) => { setPrimaryInst(inst); setPrimaryFin(fin); });
  }, [primaryCert]);

  const handleSelectCompare = async (cert) => {
    setLoading(true);
    setCompareCert(cert);
    try {
      const [inst, fin] = await Promise.all([fetchInstitution(cert), fetchFinancials(cert, 1)]);
      setCompareInst(inst);
      setCompareFin(fin);
    } finally { setLoading(false); }
  };

  const rows = [
    { label: "Total Assets",   fieldA: "ASSET",   fmt: fmtDollars },
    { label: "Total Deposits", fieldA: "DEP",     fmt: fmtDollars },
    { label: "Net Income",     fieldA: "NETINC",  fmt: fmtDollars },
    { label: "ROA",            fieldA: "ROA",     fmt: fmtPct },
    { label: "ROE",            fieldA: "ROE",     fmt: fmtPct },
    { label: "NIM",            fieldA: "NIM",     fmt: fmtPct },
    { label: "Tier 1 Leverage",fieldA: "RBCT1CER",  fmt: fmtPct },
    { label: "Total Risk-Based",fieldA:"RBCRWAJ", fmt: fmtPct },
    { label: "90+ Days PD",    fieldA: "P9ASSET", fmt: fmtDollars },
    { label: "Nonaccrual",     fieldA: "LNLSNTV", fmt: fmtDollars },
    { label: "Charge-off Rate",fieldA: "NTLNLSR",fmt: fmtPct },
  ];

  return (
    <div className="fdic-section">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
        <div className="fdic-section-title" style={{ margin: 0 }}>Bank Comparison</div>
        <button className="fdic-btn fdic-btn-outline" onClick={onClose}>Close</button>
      </div>
      <div className="fdic-compare-grid">
        <div>
          <div className="fdic-compare-col-head">{primaryInst?.NAME || "Loading…"}</div>
          {rows.map(r => (
            <div key={r.label} className="fdic-compare-row">
              <span className="fdic-compare-row-label">{r.label}</span>
              <span className="fdic-compare-row-val">
                {primaryFin?.[0] ? r.fmt(primaryFin[0][r.fieldA]) : "—"}
              </span>
            </div>
          ))}
        </div>
        <div>
          {!compareCert
            ? (
              <div>
                <div className="fdic-compare-col-head">Select a bank to compare</div>
                <FDICSearch onSelect={handleSelectCompare} compact />
              </div>
            )
            : (
              <>
                <div className="fdic-compare-col-head">
                  {loading ? "Loading…" : compareInst?.NAME || "Unknown"}
                </div>
                {rows.map(r => (
                  <div key={r.label} className="fdic-compare-row">
                    <span className="fdic-compare-row-label">{r.label}</span>
                    <span className="fdic-compare-row-val">
                      {compareFin?.[0] ? r.fmt(compareFin[0][r.fieldA]) : "—"}
                    </span>
                  </div>
                ))}
              </>
            )
          }
        </div>
      </div>
    </div>
  );
}

//  EXPORT PDF 
function exportPDF(inst, fin) {
  if (!fin?.length || !inst || !window.jspdf) return;
  const { jsPDF } = window.jspdf;
  const doc = new jsPDF({ unit: "mm", format: "a4" });
  const W = 210, M = 14;
  const latest = fin[0];

  // Color helpers
  const navy  = [31,  56,  100];
  const blue  = [46,  117, 182];
  const dark  = [15,  27,  51];
  const gray  = [107, 114, 128];
  const lgray = [240, 243, 248];
  const white = [255, 255, 255];

  const hexToRgb = h => {
    // Guard against CSS var() strings accidentally landing here (jsPDF throws
    // an opaque "Invalid argument" on NaN color components, silently killing
    // the whole export) — fall back to the dark text color instead of crashing.
    const m = typeof h === "string" && /^#([0-9a-f]{6})$/i.exec(h.trim());
    if (!m) return dark;
    const hex = m[1];
    return [parseInt(hex.slice(0,2),16), parseInt(hex.slice(2,4),16), parseInt(hex.slice(4,6),16)];
  };
  // texasBand()/status colors return CSS var() strings for the live web UI —
  // resolve those to real hex here since jsPDF can't read CSS variables.
  const STATUS_HEX = { "var(--status-negative)": "#9B2C2C", "var(--status-caution)": "#B8860B", "var(--status-positive)": "#2E7D38" };
  const resolveColor = (c) => STATUS_HEX[c] || c;

  const texas  = calcTexasRatio(latest);
  const tb     = texas != null ? texasBand(texas) : null;
  const npl    = (Number(latest.P9ASSET)||0) + (Number(latest.LNLSNTV)||0);
  const quarter = reptdateToQuarter(latest.REPDTE);

  //  Header band 
  doc.setFillColor(...navy);
  doc.rect(0, 0, W, 40, "F");

  // blue accent bar left edge
  doc.setFillColor(...blue);
  doc.rect(0, 0, 4, 40, "F");

  // VRB Capital label
  doc.setTextColor(...blue);
  doc.setFontSize(7);
  doc.setFont("helvetica", "bold");
  doc.text("VRB CAPITAL  ·  FDIC BANK INTELLIGENCE REPORT", M, 9);

  // Bank name
  doc.setTextColor(...white);
  doc.setFontSize(17);
  doc.setFont("helvetica", "bold");
  const nameStr = inst.NAME.length > 50 ? inst.NAME.slice(0,47) + "…" : inst.NAME;
  doc.text(nameStr, M, 22);

  // Sub-line: cert, location, branches
  doc.setFontSize(8);
  doc.setFont("helvetica", "normal");
  doc.setTextColor(180, 200, 230);
  const subLine = [
    `FDIC #${inst.CERT}`,
    `${inst.CITY}, ${inst.STNAME}`,
    inst.OFFICES ? `${inst.OFFICES} locations` : null,
    `Data: ${quarter}`
  ].filter(Boolean).join("   ·   ");
  doc.text(subLine, M, 31);

  // Texas Ratio badge (top-right)
  if (texas != null && tb) {
    const tbRgb = hexToRgb(resolveColor(tb.color));
    doc.setFillColor(...tbRgb);
    doc.rect(W - M - 62, 6, 62, 10, "F");
    doc.setTextColor(...white);
    doc.setFontSize(7.5);
    doc.setFont("helvetica", "bold");
    doc.text(`Texas Ratio: ${texas.toFixed(1)}%  ·  ${tb.label.toUpperCase()}`, W - M - 59, 12.5);
  }

  let y = 48;

  // Section header helper
  const secHead = (title) => {
    doc.setFillColor(...lgray);
    doc.rect(M, y, W - M*2, 7.5, "F");
    doc.setFillColor(...blue);
    doc.rect(M, y, 3, 7.5, "F");
    doc.setTextColor(...dark);
    doc.setFontSize(8.5);
    doc.setFont("helvetica", "bold");
    doc.text(title, M + 6, y + 5.2);
    y += 11;
  };

  // 4-column metric helper
  const metricGrid = (items) => {
    const cols = [M, M+48, M+96, M+144];
    items.forEach((row, ri) => {
      row.forEach((item, ci) => {
        if (!item) return;
        const cx = cols[ci] || cols[ci % 4];
        doc.setFontSize(6.5); doc.setFont("helvetica", "normal"); doc.setTextColor(...gray);
        doc.text(item.label, cx, y);
        doc.setFontSize(9.5); doc.setFont("helvetica", "bold");
        if (item.color) doc.setTextColor(...hexToRgb(resolveColor(item.color)));
        else doc.setTextColor(...dark);
        doc.text(String(item.val), cx, y + 5);
      });
      y += (ri < items.length - 1) ? 11 : 13;
    });
  };

  //  KEY FINANCIALS 
  secHead("KEY FINANCIAL METRICS");
  metricGrid([
    [
      { label: "Total Assets",   val: fmtDollars(latest.ASSET) },
      { label: "Total Deposits", val: fmtDollars(latest.DEP) },
      { label: "Total Equity",   val: fmtDollars(latest.EQ) },
      { label: "Net Income",     val: fmtDollars(latest.NETINC) },
    ],
    [
      { label: "Return on Assets (ROA)",  val: fmtPct(latest.ROA) },
      { label: "Return on Equity (ROE)",  val: fmtPct(latest.ROE) },
      { label: "Net Interest Margin",     val: fmtPct(latest.NIMY) },
      { label: "Efficiency Ratio",        val: fmtPct(latest.EEFFR) },
    ],
  ]);

  //  CAPITAL ADEQUACY 
  secHead("CAPITAL ADEQUACY");
  metricGrid([[
    { label: "Tier 1 Leverage Ratio",  val: fmtPct(latest.RBCT1CER) },
    { label: "Tier 1 Risk-Based Cap",  val: fmtPct(latest.RBC1RWAJ) },
    { label: "Total Risk-Based Cap",   val: fmtPct(latest.RBCRWAJ) },
    { label: "ALLL (Loan Loss Res.)",  val: fmtDollars(latest.LNLSRES) },
  ]]);

  //  STRESS & DELINQUENCY 
  secHead("STRESS & DELINQUENCY INDICATORS");
  metricGrid([
    [
      { label: "30–89 Days Past Due",     val: fmtDollars(latest.P3ASSET) },
      { label: "90+ Days Past Due",       val: fmtDollars(latest.P9ASSET) },
      { label: "Nonaccrual Loans",        val: fmtDollars(latest.LNLSNTV) },
      { label: "REO (Foreclosed Assets)", val: fmtDollars(latest.FREPO) },
    ],
    [
      { label: "Total NPL",               val: fmtDollars(npl), color: npl > 0 ? "#9B2C2C" : null },
      { label: "Net Charge-off Rate",     val: fmtPct(latest.NTLNLSR) },
      { label: "Loan Loss Provisions",    val: fmtDollars(latest.LNLSNET) },
      texas != null ? { label: "Texas Ratio", val: texas.toFixed(1) + "%", color: tb.color } : null,
    ],
  ]);

  //  LOAN PORTFOLIO 
  secHead("LOAN PORTFOLIO COMPOSITION");
  metricGrid([
    [
      { label: "Residential Real Estate",      val: fmtDollars(latest.LNRE) },
      { label: "Comm. CRE (Nonfarm Nonres.)",  val: fmtDollars(latest.LNRENRES) },
      { label: "Multifamily RE",               val: fmtDollars(latest.LNREMULT) },
      { label: "C&I Loans",                    val: fmtDollars(latest.LNCI) },
    ],
    [
      { label: "Construction Loans",           val: fmtDollars(latest.LNRECONS) },
      { label: "Consumer Loans",               val: fmtDollars(latest.LNCON) },
      { label: "Total Loans & Leases",         val: fmtDollars(latest.LNLS) },
      { label: "Net Loans",                    val: fmtDollars(latest.LNLSNET) },
    ],
  ]);

  //  FUNDING & INCOME 
  const dep = Number(latest.DEP) || 0;
  const brokPct = (latest.BRO != null && latest.BRO !== "" && dep > 0)
    ? (Number(latest.BRO) / dep * 100) : null;
  const fundingItems = [
    latest.BRO != null && latest.BRO !== "" ?
      { label: "Brokered Deposits", val: fmtDollars(latest.BRO) + (brokPct != null ? `  (${brokPct.toFixed(1)}%)` : ""),
        color: brokPct != null && brokPct > 10 ? (brokPct > 20 ? "#9B2C2C" : "#B8860B") : null } : null,
    latest.SC != null && latest.SC !== "" ?
      { label: "Securities Portfolio", val: fmtDollars(latest.SC) } : null,
    latest.INTINC != null && latest.INTINC !== "" ?
      { label: "Interest Income", val: fmtDollars(latest.INTINC) } : null,
    latest.EINTEXP != null && latest.EINTEXP !== "" ?
      { label: "Interest Expense", val: fmtDollars(latest.EINTEXP) } : null,
    latest.NONII != null && latest.NONII !== "" ?
      { label: "Non-Interest Income", val: fmtDollars(latest.NONII) } : null,
    latest.NONIX != null && latest.NONIX !== "" ?
      { label: "Non-Interest Expense", val: fmtDollars(latest.NONIX) } : null,
  ].filter(Boolean);
  if (fundingItems.length > 0) {
    secHead("FUNDING & INCOME PROFILE");
    const rows = [];
    for (let i = 0; i < fundingItems.length; i += 4) rows.push(fundingItems.slice(i, i + 4));
    metricGrid(rows);
  }


  //  HISTORICAL (last 4 quarters) 
  if (fin.length > 1) {
    secHead("QUARTERLY TREND  (Last " + Math.min(fin.length, 4) + " Quarters)");
    const quarters = fin.slice(0, 4).reverse();

    // Table header
    const tCols = [M + 5, M + 46, M + 78, M + 110, M + 142, M + 168];
    const tHdrs = ["Quarter", "Assets", "Deposits", "ROA", "Tier 1", "Texas Ratio"];
    doc.setFontSize(7); doc.setFont("helvetica", "bold");
    doc.setFillColor(...lgray);
    doc.rect(M, y, W - M*2, 6, "F");
    tHdrs.forEach((h, i) => {
      doc.setTextColor(...gray);
      doc.text(h, tCols[i], y + 4.2);
    });
    y += 7;

    quarters.forEach((q, idx) => {
      const rowTx = calcTexasRatio(q);
      if (idx % 2 === 0) { doc.setFillColor(248, 250, 252); doc.rect(M, y, W - M*2, 6.5, "F"); }
      doc.setFontSize(7.5); doc.setFont("helvetica", "normal"); doc.setTextColor(...dark);
      doc.text(reptdateToQuarter(q.REPDTE), tCols[0], y + 4.5);
      doc.text(fmtDollars(q.ASSET),         tCols[1], y + 4.5);
      doc.text(fmtDollars(q.DEP),           tCols[2], y + 4.5);
      doc.text(fmtPct(q.ROA),               tCols[3], y + 4.5);
      doc.text(fmtPct(q.RBCT1CER),            tCols[4], y + 4.5);
      if (rowTx != null) {
        const rtb = texasBand(rowTx);
        doc.setTextColor(...hexToRgb(resolveColor(rtb.color)));
        doc.text(rowTx.toFixed(1) + "%",    tCols[5], y + 4.5);
      } else {
        doc.text("—", tCols[5], y + 4.5);
      }
      y += 7;
    });
    y += 4;
  }

  //  Footer 
  doc.setFillColor(...navy);
  doc.rect(0, 285, W, 12, "F");
  doc.setFillColor(...blue);
  doc.rect(0, 285, 4, 12, "F");
  doc.setFontSize(6.5);
  doc.setFont("helvetica", "normal");
  doc.setTextColor(180, 200, 230);
  doc.text("VRB Capital FDIC Bank Intelligence  ·  info@vrbcap.com  ·  Data: FDIC BankFind Suite", M, 292);
  doc.text(new Date().toLocaleDateString("en-US", { year:"numeric", month:"long", day:"numeric" }), W - M, 292, { align: "right" });

  doc.save(`VRB_FDIC_${inst.NAME.replace(/\s+/g,"_")}_${latest.REPDTE}.pdf`);
}

//  STICKY SECTION NAV 
const FDIC_SECTIONS = [
  { id: "fdic-sec-overview",  label: "Overview" },
  { id: "fdic-sec-risk",      label: "Capital & Risk" },
  { id: "fdic-sec-portfolio", label: "Loan Portfolio" },
  { id: "fdic-sec-trends",    label: "Trends" },
];

function FDICSectionNav({ inst, fin, onBranchClick }) {
  const [active, setActive] = useState("fdic-sec-overview");
  const [stuck, setStuck] = useState(false);

  useEffect(() => {
    const onScroll = () => {
      setStuck(window.scrollY > 160);
      for (let i = FDIC_SECTIONS.length - 1; i >= 0; i--) {
        const el = document.getElementById(FDIC_SECTIONS[i].id);
        if (el && el.getBoundingClientRect().top <= 120) {
          setActive(FDIC_SECTIONS[i].id);
          return;
        }
      }
      setActive("fdic-sec-overview");
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const scrollTo = (id) => {
    const el = document.getElementById(id);
    if (!el) return;
    const top = el.getBoundingClientRect().top + window.scrollY - 100;
    window.scrollTo({ top, behavior: "smooth" });
    setActive(id);
  };

  const latest = fin?.[0];
  const assets = latest ? fmtDollars(latest.ASSET) : "";

  return (
    <div className={"fdic-section-nav" + (stuck ? " stuck" : "")}>
      <div className="fdic-section-nav-inner">
        <div className="fdic-section-nav-left">
          {stuck && inst && (
            <div className="fdic-section-nav-bank">
              <span className="fdic-section-nav-name">{inst.NAME}</span>
              {assets && <span className="fdic-section-nav-assets">{assets}</span>}
            </div>
          )}
          <div className="fdic-section-tabs">
            {FDIC_SECTIONS.map(s => (
              <button
                key={s.id}
                className={"fdic-section-tab" + (active === s.id ? " active" : "")}
                onClick={() => scrollTo(s.id)}
              >
                {s.label}
              </button>
            ))}
          </div>
        </div>
        <button className="fdic-section-tab fdic-branch-tab" onClick={onBranchClick}>
          Branches
        </button>
      </div>
    </div>
  );
}

//  BANK PROFILE (full dashboard) 
function BankProfile({ cert, watchlist }) {
  const [inst, setInst]     = useState(null);
  const [fin, setFin]       = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError]   = useState(null);
  const [showCompare, setShowCompare] = useState(false);
  const [showBranches, setShowBranches] = useState(false);

  useEffect(() => {
    if (!cert) return;
    setLoading(true);
    setError(null);
    setInst(null);
    setFin(null);

    Promise.all([fetchInstitution(cert), fetchFinancials(cert, 8)])
      .then(([i, f]) => { setInst(i); setFin(f); })
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }, [cert]);

  const handleWatch = () => {
    if (!inst) return;
    if (watchlist.isWatched(inst.CERT)) watchlist.remove(inst.CERT);
    else watchlist.add({ CERT: inst.CERT, NAME: inst.NAME, CITY: inst.CITY, STALP: inst.STALP });
  };

  const NPLDash = window.NPLInvestorDashboard;

  if (error) return (
    <div className="fdic-dashboard">
      <div className="fdic-error-banner">Failed to load bank data: {error}</div>
    </div>
  );

  return (
    <>
      {loading
        ? (
          <div className="fdic-bank-header">
            <div className="fdic-bank-header-inner">
              <div className="fdic-skeleton" style={{ width: 56, height: 56, borderRadius: 10 }} />
              <div style={{ flex: 1 }}>
                <div className="fdic-skeleton fdic-skeleton-text" style={{ width: "40%", height: 28 }} />
                <div className="fdic-skeleton fdic-skeleton-text" style={{ width: "30%", marginTop: 8 }} />
              </div>
            </div>
          </div>
        )
        : (
          <BankHeader
              inst={inst}
              fin={fin}
              isWatched={watchlist.isWatched(inst?.CERT)}
              onWatch={handleWatch}
              onCompare={() => setShowCompare(v => !v)}
              onExportPDF={() => exportPDF(inst, fin)}
            />
        )
      }

      {showBranches && inst && !loading && (
        <BranchesPanel cert={cert} inst={inst} fin={fin} onClose={() => setShowBranches(false)} />
      )}

      <div className="fdic-dashboard">
        {showCompare && <BankComparison primaryCert={cert} onClose={() => setShowCompare(false)} />}
        {!loading && fin && NPLDash && <NPLDash fin={fin} cert={cert} />}
      </div>

    </>
  );
}

//  ROOT PAGE 
window.FDICPage = function FDICPage({ openForm }) {
  const [selectedCert, setSelectedCert] = useState(null);
  const [stateFilter, setStateFilter]   = useState("");
  const [assetFilter, setAssetFilter]   = useState("");
  const [targetType, setTargetType]     = useState("");
  const [signalType, setSignalType]     = useState("");
  const [sellerSignal, setSellerSignal] = useState("");
  const [sortBy, setSortBy]             = useState("seller");
  const watchlist = useWatchlist();

  useEffect(() => {
    const handlePop = () => {
      setSelectedCert(null);
      window.scrollTo({ top: 0, behavior: "smooth" });
    };
    window.addEventListener("popstate", handlePop);
    return () => window.removeEventListener("popstate", handlePop);
  }, []);

  const handleSelect = (cert) => {
    setSelectedCert(String(cert));
    window.history.pushState({ fdicCert: String(cert) }, "");
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  const FilterBtn = ({ value, current, onChange, label }) => (
    <button
      className={"fdic-filter-btn" + (current === value ? " active" : "")}
      onClick={() => onChange(current === value ? "" : value)}
    >{label}</button>
  );

  const SelectFilter = ({ value, onChange, options, placeholder }) => (
    <select className="fdic-filter-select" value={value} onChange={e => onChange(e.target.value)}>
      <option value="">{placeholder}</option>
      {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
    </select>
  );

  const clearFilters = () => { setStateFilter(""); setAssetFilter(""); setTargetType(""); setSignalType(""); setSellerSignal(""); };
  const hasFilters = !!(stateFilter || assetFilter || targetType || signalType || sellerSignal);

  return (
    <FDICErrorBoundary>
      <div className="fdic-page">

        {/* Hero — brand header only */}
        <div className="fdic-hero-band">
          <div className="fdic-hero-inner">
            <div>
              <div className="fdic-hero-eyebrow">Proprietary Bank Intelligence Platform</div>
              <h1 className="fdic-hero-title">Identify the banks most likely to become sellers.</h1>
              <p className="fdic-hero-sub">VRB Capital's acquisition team scores more than 4,500 FDIC-insured institutions each quarter, weighting capital adequacy, non-accrual ratios, and charge-off trends against public FDIC and FFIEC call report filings. The same model that sources our own deal flow flags which institutions are under balance-sheet pressure before they list a portfolio.</p>
              <p className="fdic-hero-builtfor"><span className="fdic-hero-builtfor-label">Built for</span> Private credit funds • Distressed debt investors • Mortgage note buyers</p>
            </div>
            <div className="hero-capsule">
              <div className="label">PLATFORM AT A GLANCE</div>
              <ul className="capsule-list">
                <li><strong>Institutions monitored</strong>4,500+ FDIC-insured banks</li>
                <li><strong>Data source</strong>FDIC &amp; FFIEC call report filings</li>
                <li><strong>Update cadence</strong>Quarterly, aligned to call-report cycles</li>
              </ul>
              <p>Seller Signal Scores weight capital adequacy, non-accrual ratios, and charge-off trends to flag institutions under balance-sheet pressure.</p>
              <div className="hero-cta">
                <button onClick={() => openForm && openForm()} className="btn btn-hero-cta">Speak to Our Team</button>
              </div>
            </div>
          </div>
        </div>

        {/* Control bar — two rows */}
        <div className="fdic-control-bar">
          {/* Row 1: Search */}
          <div className="fdic-control-search-row">
            <div className="fdic-control-inner">
              <FDICSearch onSelect={handleSelect} />
              {selectedCert && (
                <button className="fdic-back-btn" onClick={() => window.history.back()}>
                  All Banks
                </button>
              )}
            </div>
          </div>

          {/* Row 2: Filters (leaderboard only) */}
          {!selectedCert && (
            <div className="fdic-control-filter-row">
              <div className="fdic-control-inner">

                <div className="fdic-filter-group">
                  <span className="fdic-filter-group-label">State</span>
                  <StateSelect value={stateFilter} onChange={setStateFilter} />
                </div>

                <div className="fdic-filter-sep" />

                <div className="fdic-filter-group">
                  <span className="fdic-filter-group-label">Asset Size</span>
                  <SelectFilter value={assetFilter} onChange={setAssetFilter} placeholder="All sizes"
                    options={[
                      { value: "small", label: "<$100M" },
                      { value: "mid", label: "$100M–$1B" },
                      { value: "large", label: "$1B+" },
                    ]} />
                </div>

                <div className="fdic-filter-sep" />

                <div className="fdic-filter-group">
                  <span className="fdic-filter-group-label">Target Asset Type</span>
                  <SelectFilter value={targetType} onChange={setTargetType} placeholder="All RE"
                    options={[
                      { value: "residential", label: "Residential RE" },
                      { value: "cre", label: "Commercial RE" },
                      { value: "multifamily", label: "Multifamily" },
                      { value: "construction", label: "Construction / Land" },
                      { value: "mixed", label: "Mixed RE" },
                    ]} />
                </div>

                <div className="fdic-filter-sep" />

                <div className="fdic-filter-group">
                  <span className="fdic-filter-group-label">Seller Signal</span>
                  <SelectFilter value={sellerSignal} onChange={setSellerSignal} placeholder="Any"
                    options={[
                      { value: "Direct", label: "Direct (HFS / Sold)" },
                      { value: "Indirect", label: "Indirect" },
                      { value: "None", label: "None" },
                    ]} />
                </div>

                <div className="fdic-filter-sep" />

                <div className="fdic-filter-group">
                  <span className="fdic-filter-group-label">Sort By</span>
                  <SelectFilter value={sortBy === "seller" ? "" : sortBy} onChange={v => setSortBy(v || "seller")} placeholder="Seller Signal Score"
                    options={[
                      { value: "npl", label: "NPL / Loans" },
                      { value: "hfs", label: "Severe HFS" },
                      { value: "sold", label: "Sold Nonaccruals" },
                      { value: "co", label: "RE Charge-Off Ratio" },
                      { value: "oreo", label: "OREO" },
                      { value: "texas", label: "Texas Ratio" },
                      { value: "assets", label: "Assets" },
                    ]} />
                </div>

                {hasFilters && (
                  <button className="fdic-filter-clear" onClick={clearFilters}>Clear</button>
                )}
              </div>
            </div>
          )}
        </div>

        <div className="fdic-page-body">
          {!selectedCert
            ? <FDICLanding onSelect={handleSelect} watchlist={watchlist}
                stateFilter={stateFilter} assetFilter={assetFilter}
                targetType={targetType} signalType={signalType}
                sellerSignal={sellerSignal} sortBy={sortBy}
                onSignalType={setSignalType} onSortChange={setSortBy} />
            : <BankProfile cert={selectedCert} watchlist={watchlist} />
          }
        </div>
        <FdicCTABand />
      </div>
    </FDICErrorBoundary>
  );
};
