/* global React, Icon, StatusChip, PageHeader, Banner, etb */
const { useState: useStateCR2 } = React;

/* ============================================================
   NBE Credit Risk — RWA return, spreadsheet UI + Official·Stress lens
   Stress = rating migration / RW uplift → RWA grows → CAR falls vs 11% floor
   ETB millions · internal/synthetic
   ============================================================ */
const CR_CAPITAL = 12439;  // total eligible capital (from CAR return row 11)

// On-Balance Sheet — full NBE hierarchy. lvl: 0 category · 1 sub · 2 ECR band.
// leaf rows carry {ead, rw}; ECR bands mostly 0 except the bank's actual band.
const CR_ON = [
  { no: "1", lvl: 0, label: "Cash Items" },
  { no: "1.1", lvl: 1, label: "Cash on hand (local & foreign currency)", ead: 1620, rw: 0 },
  { no: "1.2", lvl: 1, label: "Gold Bullion — in vault", ead: 0, rw: 0 },
  { no: "1.3", lvl: 1, label: "Cash items in the process of collection", ead: 1180, rw: 20 },
  { no: "2", lvl: 0, label: "Exposures to Sovereigns" },
  { no: "2.1", lvl: 1, label: "Deposit at NBE, T-Bills, FDRE bonds", ead: 16800, rw: 0 },
  { no: "2.2", lvl: 1, label: "Claims on Regional Governments", ead: 900, rw: 20 },
  { no: "2.3", lvl: 1, label: "Claims on BIS, ECB, EC and IMF", ead: 0, rw: 0 },
  { no: "2.4", lvl: 1, label: "Other Sovereign exposures (by credit assessment)" },
  { no: "2.4.1", lvl: 2, label: "AAA to AA-", ead: 0, rw: 0 },
  { no: "2.4.2", lvl: 2, label: "A+ to A-", ead: 0, rw: 20 },
  { no: "2.4.3", lvl: 2, label: "BBB+ to BBB-", ead: 0, rw: 50 },
  { no: "2.4.4", lvl: 2, label: "BB+ to B-", ead: 0, rw: 100 },
  { no: "2.4.5", lvl: 2, label: "Below B-", ead: 0, rw: 150 },
  { no: "2.4.6", lvl: 2, label: "Unrated", ead: 600, rw: 100 },
  { no: "3", lvl: 0, label: "Exposures to State Owned Enterprises (SOEs)" },
  { no: "3.1", lvl: 1, label: "PSEs — denominated & funded in local currency", ead: 2400, rw: 20 },
  { no: "3.2", lvl: 1, label: "PSEs — based on RW of sovereign (by rating)" },
  { no: "3.2.1", lvl: 2, label: "AAA to AA-", ead: 0, rw: 20 },
  { no: "3.2.2", lvl: 2, label: "A+ to A-", ead: 0, rw: 50 },
  { no: "3.2.6", lvl: 2, label: "Unrated", ead: 800, rw: 100 },
  { no: "4", lvl: 0, label: "Exposures to Multilateral Development Banks (MDBs)" },
  { no: "4.1", lvl: 1, label: "MDBs eligible for 0% risk weight", ead: 1200, rw: 0 },
  { no: "4.2", lvl: 1, label: "Other MDBs (by rating)" },
  { no: "4.2.1", lvl: 2, label: "AAA to AA-", ead: 600, rw: 20 },
  { no: "4.2.6", lvl: 2, label: "Unrated", ead: 0, rw: 50 },
  { no: "5", lvl: 0, label: "Exposures to Banks & Securities firms" },
  { no: "5.1", lvl: 1, label: "Original maturity > 3 months (by rating)" },
  { no: "5.1.1", lvl: 2, label: "AAA to AA-", ead: 3200, rw: 20 },
  { no: "5.1.3", lvl: 2, label: "BBB+ to BBB-", ead: 2400, rw: 50 },
  { no: "5.1.6", lvl: 2, label: "Unrated", ead: 4100, rw: 50 },
  { no: "5.2", lvl: 1, label: "Original maturity ≤ 3 months (by rating)" },
  { no: "5.2.1", lvl: 2, label: "AAA to AA-", ead: 2900, rw: 20 },
  { no: "5.2.6", lvl: 2, label: "Unrated", ead: 1600, rw: 20 },
  { no: "5.3", lvl: 1, label: "Exposures in local currency funded", ead: 0, rw: 20 },
  { no: "6", lvl: 0, label: "Exposures to Covered Bonds" },
  { no: "6.1", lvl: 1, label: "Rated covered bonds (issue-specific)" },
  { no: "6.1.1", lvl: 2, label: "AAA to AA-", ead: 900, rw: 10 },
  { no: "6.2", lvl: 1, label: "Unrated covered bonds (RW of issuing bank)", ead: 0, rw: 25 },
  { no: "7", lvl: 0, label: "Exposures to Corporates" },
  { no: "7.1", lvl: 1, label: "General Corporate (by external rating)" },
  { no: "7.1.1", lvl: 2, label: "AAA to AA-", ead: 5200, rw: 20 },
  { no: "7.1.3", lvl: 2, label: "BBB+ to BB-", ead: 8400, rw: 75 },
  { no: "7.1.6", lvl: 2, label: "Unrated", ead: 28000, rw: 100 },
  { no: "7.1.7", lvl: 2, label: "Corporate SMEs", ead: 9200, rw: 85 },
  { no: "7.2", lvl: 1, label: "Specialized lending" },
  { no: "7.2.1", lvl: 2, label: "Project finance — pre-operational", ead: 1800, rw: 130 },
  { no: "7.2.2", lvl: 2, label: "Project finance — operational", ead: 3400, rw: 100 },
  { no: "8", lvl: 0, label: "Retail Exposures (individuals / small business)" },
  { no: "8.1", lvl: 1, label: "Qualifying regulatory retail" },
  { no: "8.1.1", lvl: 2, label: "Revolving credits & lines of credit", ead: 4200, rw: 75 },
  { no: "8.1.2", lvl: 2, label: "Personal term loans and leases", ead: 9800, rw: 75 },
  { no: "8.1.3", lvl: 2, label: "Small business facilities & commitments", ead: 3600, rw: 75 },
  { no: "8.2", lvl: 1, label: "Other retail (does not meet criteria)", ead: 1800, rw: 100 },
  { no: "9", lvl: 0, label: "Real Estate Exposures (performing)" },
  { no: "9.1", lvl: 1, label: "Residential real estate" },
  { no: "9.1.1", lvl: 2, label: "Owner-occupied / rented, not past due", ead: 11000, rw: 35 },
  { no: "9.1.2", lvl: 2, label: "Other residential real estate", ead: 1400, rw: 100 },
  { no: "9.2", lvl: 1, label: "Commercial real estate", ead: 5200, rw: 100 },
  { no: "10", lvl: 0, label: "Defaulted Exposure (> 90 days)" },
  { no: "10.1", lvl: 1, label: "Specific provisions ≥ 20% of outstanding", ead: 900, rw: 100 },
  { no: "10.2", lvl: 1, label: "Specific provisions < 20% of outstanding", ead: 1100, rw: 150 },
  { no: "10.3", lvl: 1, label: "Defaulted residential real estate", ead: 0, rw: 100 },
  { no: "11", lvl: 0, label: "Other Exposures" },
  { no: "11.1", lvl: 1, label: "Fixed Assets", ead: 3800, rw: 100 },
  { no: "11.2", lvl: 1, label: "Investments not deducted from Capital", ead: 1200, rw: 100 },
  { no: "11.3", lvl: 1, label: "Others", ead: 900, rw: 100 },
];
function ecrOf(r) {
  const m = r.label && r.label.match(/(AAA to AA-|A\+ to A-|BBB\+ to BBB-|BB\+ to B-|Below B-|Unrated)/);
  return m ? m[1] : "";
}
CR_ON.forEach(r => {
  if (r.ead != null) {
    r.total = r.ead;
    r.net = r.ead;
    r.crm = 0;
    r.ecr = ecrOf(r);
    r.rwa = Math.round((r.net + r.crm) * r.rw / 100);
  }
});
// leaf rows (those with EAD) drive the totals
const CR_ROWS = CR_ON.filter(r => r.ead != null && r.ead > 0);
// off-balance sheet items — exact NBE Credit Off-Balance categories · RWA = (C+E)×A/100
const CR_OFF = [
  { no: "1", label: "Commitments unconditionally cancellable at any time", face: 8000, ccf: 10, rw: 100 },
  { no: "2", label: "Short-term self-liquidating trade LCs (issuing & confirming)", face: 4200, ccf: 20, rw: 20 },
  { no: "3", label: "Commitments (regardless of maturity of underlying facility)", face: 3000, ccf: 40, rw: 100 },
  { no: "4", label: "Transaction-related contingents (performance bonds, standby LCs)", face: 2500, ccf: 50, rw: 100 },
  { no: "5", label: "Note issuance & revolving underwriting facilities (NIFs / RUFs)", face: 1200, ccf: 50, rw: 100 },
  { no: "6", label: "Direct credit substitutes (general guarantees of indebtedness)", face: 1900, ccf: 100, rw: 100 },
  { no: "7", label: "Sale & repurchase agreements / asset sales with recourse", face: 600, ccf: 100, rw: 100 },
  { no: "8", label: "Lending of banks' securities / posting securities as collateral", face: 450, ccf: 100, rw: 20 },
  { no: "9", label: "Forward asset purchases, forward deposits, partly-paid shares", face: 700, ccf: 100, rw: 100 },
  { no: "10", label: "Other off-balance credit substitutes", face: 500, ccf: 100, rw: 100 },
];
CR_OFF.forEach(r => {
  r.before = r.face;
  r.crm = 0;
  r.ce = Math.round(r.before * r.ccf / 100);
  r.ceCrm = Math.round(r.crm * r.ccf / 100);
  r.rwa = Math.round((r.ce + r.ceCrm) * r.rw / 100);
});
const ON_RWA = CR_ROWS.reduce((a, r) => a + r.rwa, 0);
const OFF_RWA = CR_OFF.reduce((a, r) => a + r.rwa, 0);
const CREDIT_RWA = ON_RWA + OFF_RWA;
const OTHER_RWA = 5000;                   // market + operational RWA
const TOTAL_RWA = CREDIT_RWA + OTHER_RWA;
const BASE_CAR = CR_CAPITAL / TOTAL_RWA * 100;

const CRSEV = [
  { name: "Mild", up: 10 }, { name: "Moderate", up: 25 }, { name: "Severe", up: 45 }, { name: "Extreme", up: 75 },
];
function carAt(up) {
  const credit = Math.round(CREDIT_RWA * (1 + up / 100));
  const total = OTHER_RWA + credit;
  return { credit, total, car: CR_CAPITAL / total * 100 };
}

const CR_HELP = {
  title: "Credit Risk · RWA",
  purpose: "The credit risk-weighted-assets return. Each exposure class carries a regulatory risk weight; EAD × RW builds RWA, which drives the capital ratio. Stress migrates ratings (RW uplift), inflating RWA and pulling CAR toward the 11% floor.",
  first: "Read total RWA and its share of the capital ratio. In Stress, scan the CAR row across severities for the band that breaches 11%.",
  terms: [["EAD", "Exposure at default — the exposure amount after CRM."], ["RW", "NBE regulatory risk weight for the class."], ["Rating migration", "Downgrades raise risk weights under stress."]],
  next: ["Open Stress to see RWA and CAR under each severity.", "Tune the RW-uplift lever; the Custom column recomputes live.", "A breach hands off to Recovery."],
  connections: ["EAD reconciles to the loans & off-balance sources.", "Capital comes from the CAR return.", "CCF/CRM evidence gates official use."],
  guardrail: "Internal RWA workpaper. CRM & CCF evidence are incomplete, so this RWA is not official; stress is analysis-only.",
};

function Credit({ go, info }) {
  const [stress, setStress] = useStateCR2(false);
  const [mode, setMode] = useStateCR2("Custom");
  const [up, setUp] = useStateCR2(45);
  const [sheet, setSheet] = useStateCR2("On-balance");
  const live = carAt(up);
  const breach = live.car < 11;
  const uBreach = Math.round((( CR_CAPITAL / 0.11 - OTHER_RWA) / CREDIT_RWA - 1) * 100);
  const onEAD = CR_ROWS.reduce((a, r) => a + r.ead, 0);
  const onTotal = CR_ROWS.reduce((a, r) => a + r.total, 0);
  const onCrm = CR_ROWS.reduce((a, r) => a + r.crm, 0);
  const offFace = CR_OFF.reduce((a, r) => a + r.face, 0);

  return (
    <div className="main-inner">
      <PageHeader eyebrow="Prudential Risk" title="Credit Risk · RWA" onInfo={() => info(CR_HELP)}
        right={<button className={"btn btn-sm " + (stress ? "btn-dark" : "btn-ghost")} onClick={() => setStress(!stress)}><Icon name="flask" size={15} /> {stress ? "Stress on" : "Stress test"}</button>} />

      {/* official RWA build-up (Official lens only) — On / Off sub-sheets like the NBE workbook */}
      {!stress && <React.Fragment>
        <div className="between mb12">
          <div className="seg-ctl">{["On-balance", "Off-balance"].map(s => <button key={s} className={sheet === s ? "on" : ""} onClick={() => setSheet(s)}>{s} sheet</button>)}</div>
          <span className="muted" style={{ fontSize: 12 }}>Combined credit RWA <b style={{ color: "var(--ink)" }}>{etb(CREDIT_RWA)}</b> = on {etb(ON_RWA)} + off {etb(OFF_RWA)}</span>
        </div>
        {sheet === "On-balance"
          ? <div className="xl-wrap mb16">
              <table className="xl xl-scroll">
                <colgroup><col style={{ width: 44 }} /><col style={{ width: 310 }} /><col style={{ width: 118 }} /><col style={{ width: 118 }} /><col style={{ width: 132 }} /><col style={{ width: 112 }} /><col style={{ width: 64 }} /><col style={{ width: 112 }} /><col style={{ width: 136 }} /></colgroup>
                <thead><tr>
                  <th className="xl-no"></th><th style={{ textAlign: "left" }}>Credit On-Balance Sheet · RWA · ETB millions · as at Jun 30, 2026</th>
                  <th className="xl-amt">Total exposure</th><th className="xl-amt">ECR</th><th className="xl-amt">Net after CRM</th><th className="xl-amt">CRM exposure</th><th className="xl-amt">RW</th><th className="xl-amt">RWA</th><th className="xl-amt">Evidence</th>
                </tr></thead>
                <tbody>
                  {CR_ON.map(r => {
                    if (r.lvl === 0) return <tr key={r.no} className="xl-green"><td className="xl-no">{r.no}</td><td colSpan="8">{r.label}</td></tr>;
                    const leaf = r.ead != null;
                    return (
                      <tr key={r.no} className="xl-item">
                        <td className="xl-no">{r.no}</td>
                        <td className="xl-label" style={{ paddingLeft: r.lvl === 2 ? 38 : 22, color: leaf ? undefined : "var(--ink-3)", fontStyle: leaf ? undefined : "italic" }}>{r.label}</td>
                        <td className="xl-amt tnum">{leaf ? (r.total ? etb(r.total) : <span style={{ opacity: .35 }}>–</span>) : ""}</td>
                        <td className="xl-amt tnum" style={{ color: r.ecr ? "var(--ink-2)" : "var(--ink-3)" }}>{leaf ? (r.ecr || "—") : ""}</td>
                        <td className="xl-amt tnum">{leaf ? (r.net ? etb(r.net) : <span style={{ opacity: .35 }}>–</span>) : ""}</td>
                        <td className="xl-amt tnum">{leaf ? (r.crm ? etb(r.crm) : <span style={{ opacity: .35 }}>–</span>) : ""}</td>
                        <td className="xl-amt tnum">{leaf ? r.rw + "%" : ""}</td>
                        <td className="xl-amt tnum" style={{ fontWeight: 600 }}>{leaf && r.ead ? etb(r.rwa) : ""}</td>
                        <td className="xl-amt" style={{ textAlign: "right" }}>{leaf && r.ead ? <StatusChip s={r.rw >= 100 ? "MAPPED" : "RECONCILED"} /> : ""}</td>
                      </tr>
                    );
                  })}
                  <tr className="xl-orange"><td className="xl-no"></td><td className="xl-label">Total on-balance credit RWA</td><td className="xl-amt tnum">{etb(onTotal)}</td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(onEAD)}</td><td className="xl-amt tnum">{onCrm ? etb(onCrm) : <span style={{ opacity: .35 }}>–</span>}</td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(ON_RWA)}</td><td className="xl-amt"></td></tr>
                </tbody>
              </table>
            </div>
          : <div className="xl-wrap mb16">
              <table className="xl xl-scroll">
                <colgroup><col style={{ width: 44 }} /><col style={{ width: 300 }} /><col style={{ width: 112 }} /><col style={{ width: 64 }} /><col style={{ width: 118 }} /><col style={{ width: 118 }} /><col style={{ width: 108 }} /><col style={{ width: 122 }} /><col style={{ width: 108 }} /><col style={{ width: 120 }} /></colgroup>
                <thead><tr>
                  <th className="xl-no"></th><th style={{ textAlign: "left" }}>Credit Off-Balance Sheet · RWA · ETB millions · as at Jun 30, 2026</th>
                  <th className="xl-amt">Total exposure</th><th className="xl-amt">RW</th><th className="xl-amt">Exposure before CCF</th><th className="xl-amt">Credit equiv.</th><th className="xl-amt">CRM coverage</th><th className="xl-amt">CE with CRM</th><th className="xl-amt">RWA</th><th className="xl-amt">Evidence</th>
                </tr></thead>
                <tbody>
                  {CR_OFF.map(r => (
                    <tr key={r.no} className="xl-item">
                      <td className="xl-no">{r.no}</td><td className="xl-label">{r.label}</td>
                      <td className="xl-amt tnum">{etb(r.face)}</td><td className="xl-amt tnum">{r.rw}%</td>
                      <td className="xl-amt tnum">{etb(r.before)} <span className="muted" style={{ fontSize: 10 }}>· CCF {r.ccf}%</span></td>
                      <td className="xl-amt tnum">{etb(r.ce)}</td>
                      <td className="xl-amt tnum">{r.crm ? etb(r.crm) : <span style={{ opacity: .35 }}>–</span>}</td>
                      <td className="xl-amt tnum">{r.ceCrm ? etb(r.ceCrm) : <span style={{ opacity: .35 }}>–</span>}</td>
                      <td className="xl-amt tnum" style={{ fontWeight: 600 }}>{etb(r.rwa)}</td>
                      <td className="xl-amt" style={{ textAlign: "right" }}><StatusChip s="EVIDENCE_NEEDED" /></td>
                    </tr>
                  ))}
                  <tr className="xl-orange"><td className="xl-no"></td><td className="xl-label">Total off-balance credit RWA</td><td className="xl-amt tnum">{etb(offFace)}</td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(CR_OFF.reduce((a, r) => a + r.before, 0))}</td><td className="xl-amt tnum">{etb(CR_OFF.reduce((a, r) => a + r.ce, 0))}</td><td className="xl-amt tnum">{CR_OFF.some(r => r.crm) ? etb(CR_OFF.reduce((a, r) => a + r.crm, 0)) : <span style={{ opacity: .35 }}>–</span>}</td><td className="xl-amt tnum">{CR_OFF.some(r => r.ceCrm) ? etb(CR_OFF.reduce((a, r) => a + r.ceCrm, 0)) : <span style={{ opacity: .35 }}>–</span>}</td><td className="xl-amt tnum">{etb(OFF_RWA)}</td><td className="xl-amt"></td></tr>
                </tbody>
              </table>
            </div>}
      </React.Fragment>}

      {!stress && <Banner kind="amber" icon="alert">Off-balance CCF and CRM evidence are incomplete, so this RWA is provisional. Switch to <b>Stress</b> to model rating migration.</Banner>}

      {stress && <div style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
        <div className="grow" style={{ minWidth: 0 }}>
          <div className="between mb12">
            <div className="seg-ctl">{["On-balance", "Off-balance"].map(s => <button key={s} className={sheet === s ? "on" : ""} onClick={() => setSheet(s)}>{s} sheet</button>)}</div>
            <span className="chip chip-indigo">CAR floor 11%</span>
          </div>
          <div className="banner banner-indigo mb12" style={{ alignItems: "center", padding: "11px 15px" }}>
            <Icon name="flask" size={18} className="ic" />
            <div className="grow"><b>Rating-migration overlay</b> · {sheet} sheet · analysis-only · never merged into the official RWA</div>
          </div>
          <div className="xl-wrap">
            <table className="xl xl-scroll">
              <colgroup><col style={{ width: 40 }} /><col style={{ width: 300 }} /><col style={{ width: 96 }} /><col style={{ width: 64 }} /><col style={{ width: 100 }} />{CRSEV.map(s => <col key={s.name} style={{ width: 82 }} />)}<col style={{ width: 96 }} /></colgroup>
              <thead><tr>
                <th className="xl-no"></th>
                <th style={{ textAlign: "left" }}>{sheet} credit RWA under rating migration · ETB millions · analysis-only</th>
                <th className="xl-amt">{sheet === "On-balance" ? "EAD" : "Face"}</th><th className="xl-amt">RW</th><th className="xl-amt">RWA</th>
                {CRSEV.map((s, i) => <th key={s.name} className={"xl-amt xl-stress" + (up === s.up ? " on" : "")} style={{ cursor: "pointer" }} onClick={() => setUp(s.up)}>{s.name}</th>)}
                <th className="xl-amt" style={{ background: "var(--indigo)", color: "#fff", borderLeft: "2px solid var(--indigo)" }}>Custom</th>
              </tr></thead>
              <tbody>
                {sheet === "On-balance" ? <React.Fragment>
                  {CR_ON.map(r => {
                    if (r.lvl === 0) return <tr key={r.no} className="xl-sub"><td className="xl-no">{r.no}</td><td className="xl-label" colSpan={4 + CRSEV.length + 1} style={{ fontWeight: 700 }}>{r.label}</td></tr>;
                    if (r.ead == null) return <tr key={r.no} className="xl-item"><td className="xl-no">{r.no}</td><td className="xl-label" style={{ paddingLeft: r.lvl === 2 ? 38 : 22, color: "var(--ink-3)", fontStyle: "italic" }}>{r.label}</td><td colSpan={4 + CRSEV.length} /></tr>;
                    return <CRStressRow key={r.no} no={r.no} label={r.label} base={r.ead} rw={r.rw + "%"} rwa={r.rwa} up={up} indent={r.lvl === 2 ? 38 : 22} muted={!r.ead} />;
                  })}
                  <tr className="xl-orange"><td className="xl-no"></td><td className="xl-label">Total on-balance credit RWA</td><td className="xl-amt"></td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(ON_RWA)}</td>{CRSEV.map((s, i) => <td key={i} className={"xl-amt xl-stress tnum" + (up === s.up ? " on" : "")} style={{ color: "var(--indigo)", fontWeight: 700 }}>{etb(Math.round(ON_RWA * (1 + s.up / 100)))}</td>)}<td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", color: "var(--indigo)", fontWeight: 700, background: "rgba(79,77,208,.05)" }}>{etb(Math.round(ON_RWA * (1 + up / 100)))}</td></tr>
                </React.Fragment> : <React.Fragment>
                  <tr className="xl-green"><td className="xl-no"></td><td colSpan={4 + CRSEV.length + 1}>Off-Balance Sheet Items (credit equivalent after CCF)</td></tr>
                  {CR_OFF.map(r => <CRStressRow key={"off" + r.no} no={r.no} label={r.label} base={r.face} rw={"CCF " + r.ccf + "% · RW " + r.rw + "%"} rwa={r.rwa} up={up} />)}
                  <tr className="xl-orange"><td className="xl-no"></td><td className="xl-label">Total off-balance credit RWA</td><td className="xl-amt"></td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(OFF_RWA)}</td>{CRSEV.map((s, i) => <td key={i} className={"xl-amt xl-stress tnum" + (up === s.up ? " on" : "")} style={{ color: "var(--indigo)", fontWeight: 700 }}>{etb(Math.round(OFF_RWA * (1 + s.up / 100)))}</td>)}<td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", color: "var(--indigo)", fontWeight: 700, background: "rgba(79,77,208,.05)" }}>{etb(Math.round(OFF_RWA * (1 + up / 100)))}</td></tr>
                </React.Fragment>}
                <tr className="xl-sub"><td className="xl-no"></td><td className="xl-label">Total credit RWA (on + off)</td><td className="xl-amt"></td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(CREDIT_RWA)}</td>{CRSEV.map((s, i) => <td key={i} className={"xl-amt xl-stress tnum" + (up === s.up ? " on" : "")} style={{ color: "var(--indigo)", fontWeight: 700 }}>{etb(carAt(s.up).credit)}</td>)}<td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", color: "var(--indigo)", fontWeight: 700, background: "rgba(79,77,208,.05)" }}>{etb(live.credit)}</td></tr>
                <tr className="xl-item"><td className="xl-no"></td><td className="xl-label">Total RWA (incl. market &amp; op)</td><td className="xl-amt"></td><td className="xl-amt"></td><td className="xl-amt tnum">{etb(TOTAL_RWA)}</td>{CRSEV.map((s, i) => <td key={i} className={"xl-amt xl-stress tnum" + (up === s.up ? " on" : "")} style={{ color: "var(--indigo)" }}>{etb(carAt(s.up).total)}</td>)}<td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", color: "var(--indigo)", background: "rgba(79,77,208,.05)" }}>{etb(live.total)}</td></tr>
                <tr className="xl-orange">
                  <td className="xl-no"></td><td className="xl-label">CAR · NBE floor 11%</td><td className="xl-amt"></td><td className="xl-amt"></td>
                  <td className="xl-amt tnum">{BASE_CAR.toFixed(1)}%</td>
                  {CRSEV.map((s, i) => { const c = carAt(s.up).car, br = c < 11; return <td key={i} className={"xl-amt tnum xl-cell hit" + (up === s.up ? " on" : "")} onClick={() => setUp(s.up)} style={{ background: br ? "var(--red-soft)" : undefined, color: br ? "var(--red)" : "var(--indigo)", fontWeight: 800 }}>{c.toFixed(1)}%</td>; })}
                  <td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", background: breach ? "var(--red-soft)" : "rgba(79,77,208,.05)", color: breach ? "var(--red)" : "var(--indigo)", fontWeight: 800 }}>{live.car.toFixed(1)}%</td>
                </tr>
              </tbody>
            </table>
          </div>
          <div className="mt12"><Banner kind={breach ? "red" : "indigo"} icon={breach ? "alert" : "flask"}>
            {breach
              ? <span><b>Breach — CAR {live.car.toFixed(1)}% falls below the 11% floor.</b> Scenario result; hand to Recovery. Official RWA unchanged.</span>
              : <span>Columns show RWA &amp; CAR under NBE migration bands. The <b style={{ color: "var(--indigo)" }}>Custom</b> column is your own RW uplift — tune it in the panel.</span>}
          </Banner></div>
        </div>

        <aside className="stress-dock">
          <div className="between mb12"><span className="center gap8"><Icon name="sliders" size={15} style={{ color: "var(--indigo)" }} /><b style={{ fontSize: 14, whiteSpace: "nowrap" }}>Migration controls</b></span><span className="chip chip-indigo">Analysis-only</span></div>
          <div className="seg-ctl" style={{ width: "100%", marginBottom: 14 }}>{[["Presets", "Presets"], ["Custom", "Custom"], ["Reverse", "Reverse"]].map(([l, k]) => <button key={k} className={mode === k ? "on" : ""} style={{ flex: 1 }} onClick={() => setMode(k)}>{l}</button>)}</div>

          {mode === "Presets" && <div>
            <div className="dock-label">Scenario severity</div>
            <div className="seg-ctl" style={{ width: "100%" }}>{CRSEV.map((s, i) => <button key={s.name} className={up === s.up ? "on" : ""} style={{ flex: 1, padding: "6px 2px" }} onClick={() => setUp(s.up)}>{s.name === "Moderate" ? "Mod" : s.name}</button>)}</div>
            <div className="muted" style={{ fontSize: 11.5, marginTop: 8 }}>Sets the RW uplift to NBE's named bands.</div>
          </div>}

          {mode === "Custom" && <div>
            <div className="between" style={{ marginBottom: 5 }}><span style={{ fontSize: 12, fontWeight: 600 }}>RW uplift (rating migration)</span><span className="chip chip-indigo" style={{ fontSize: 10.5 }}>{up}%</span></div>
            <input type="range" className="lev-slider" min={0} max={120} step={5} value={up} onChange={e => setUp(+e.target.value)} />
            <div className="muted" style={{ fontSize: 10.5, marginTop: 3 }}>raises every non-zero risk weight</div>
          </div>}

          {mode === "Reverse" && <div>
            <div className="dock-label">Find the breaking point</div>
            <div className="muted" style={{ fontSize: 11.5, marginBottom: 10 }}>Reverse stress — solves the RW uplift that pulls CAR to the 11% floor.</div>
            <div className="banner banner-indigo" style={{ padding: "11px 13px" }}><Icon name="flask" size={16} className="ic" /><div>A RW uplift of <b>≈{uBreach}%</b> takes CAR to the 11% floor.</div></div>
            <button className="btn btn-dark btn-sm" style={{ width: "100%", marginTop: 12 }} onClick={() => setUp(Math.max(0, uBreach))}>Set to breaking point</button>
          </div>}

          <hr className="hr" style={{ margin: "16px 0" }} />
          <div className="dock-label">Live CAR (stressed)</div>
          <div className="big-num tnum" style={{ fontSize: 30, color: breach ? "var(--red)" : "var(--green-ink)", marginTop: 2 }}>{live.car.toFixed(1)}%</div>
          <div className="gauge"><span className="gauge-fill" style={{ width: Math.max(2, Math.min(98, (live.car - 4) / 12 * 100)) + "%", background: breach ? "var(--red)" : "var(--green)" }} /><span className="gauge-floor" style={{ left: ((11 - 4) / 12 * 100) + "%" }} /></div>
          <div className="between" style={{ fontSize: 10.5, color: "var(--ink-3)", marginTop: 3 }}><span>4%</span><span>11% floor</span><span>16%</span></div>
          {breach
            ? <button className="btn btn-dark btn-sm" style={{ width: "100%", marginTop: 12 }} onClick={() => go("recovery")}>Breach — Send to Recovery <Icon name="arrowR" size={13} /></button>
            : <div className="chip chip-green chip-lg" style={{ marginTop: 12 }}><span className="dot" />Within 11% floor</div>}
          <button className="btn btn-ghost btn-sm" style={{ width: "100%", marginTop: 8 }} onClick={() => setUp(0)}><Icon name="refresh" size={13} /> Clear stress · restore baseline</button>
        </aside>
      </div>}
    </div>
  );
}

function CRStressRow({ no, label, base, rw, rwa, up, indent }) {
  const cust = Math.round(rwa * (1 + up / 100));
  return (
    <tr className="xl-item">
      <td className="xl-no">{no}</td>
      <td className="xl-label" style={{ paddingLeft: indent }}>{label}</td>
      <td className="xl-amt tnum">{base ? etb(base) : <span style={{ opacity: .35 }}>–</span>}</td>
      <td className="xl-amt tnum" style={{ fontSize: 11.5 }}>{rw}</td>
      <td className="xl-amt tnum" style={{ fontWeight: 600 }}>{base ? etb(rwa) : ""}</td>
      {CRSEV.map((s, i) => <td key={i} className={"xl-amt xl-stress tnum" + (up === s.up ? " on" : "")} style={{ color: "var(--indigo)" }}>{base ? etb(Math.round(rwa * (1 + s.up / 100))) : ""}</td>)}
      <td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", background: "rgba(79,77,208,.05)", color: "var(--indigo)", fontWeight: 600 }}>{base ? etb(cust) : ""}</td>
    </tr>
  );
}
function CRLadder({ label, official, bands, custom }) {
  return (
    <tr className="xl-item">
      <td className="xl-label">{label}</td>
      <td className="xl-amt tnum">{etb(official)}</td>
      {bands.map((b, i) => <td key={i} className="xl-amt xl-stress tnum" style={{ color: b !== official ? "var(--indigo)" : undefined, fontWeight: b !== official ? 700 : undefined }}>{etb(b)}</td>)}
      <td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", background: "rgba(79,77,208,.05)", color: custom !== official ? "var(--indigo)" : undefined, fontWeight: 700 }}>{etb(custom)}</td>
    </tr>
  );
}
function Stat({ label, v, foot, tone, big }) {
  const c = tone === "green" ? "var(--green-ink)" : "var(--ink)";
  return <div className="card card-pad" style={{ padding: "15px 18px" }}><div className="section-label">{label}</div><div className="big-num tnum" style={{ marginTop: 6, color: c, fontSize: big ? 32 : 26 }}>{v}</div><div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>{foot}</div></div>;
}

// override the stub Credit with the spreadsheet version
window.Credit = Credit;
