const { useState, useMemo, useCallback } = React;

/* ============================ pay matrix ============================ */
const STARTS = { "1":18000,"2":19900,"3":21700,"4":25500,"5":29200,"6":35400,"7":44900,
  "8":47600,"9":53100,"10":56100,"11":67700,"12":78800,"13":123100,"13A":131100,
  "14":144200,"15":182200,"16":205400,"17":225000,"18":250000 };
const STAGES = { "1":40,"2":40,"3":40,"4":40,"5":40,"6":40,"7":40,"8":40,"9":40,"10":40,
  "11":40,"12":40,"13":20,"13A":20,"14":18,"15":15,"16":8,"17":1,"18":1 };
const LEVELS = Object.keys(STARTS);

const matrixFor = (lvl) => {
  const out = []; let v = STARTS[lvl] || 0;
  for (let i = 0; i < (STAGES[lvl] || 1); i++) { out.push(v); v = Math.ceil((v * 1.03) / 100) * 100; }
  return out;
};
const MATRIX = LEVELS.reduce((a, l) => ({ ...a, [l]: matrixFor(l) }), {});
const lvlNum = (l) => (l === "13A" ? 13 : parseInt(l, 10));

/* ============================ helpers ============================ */
const inr = (n) => (n === 0 ? "0" : new Intl.NumberFormat("en-IN", { maximumFractionDigits: 0 }).format(Math.round(n || 0)));
const inr2 = (n) => new Intl.NumberFormat("en-IN", { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(n || 0);
const clamp = (n, lo, hi) => Math.min(hi, Math.max(lo, n));
const band = (x, lo, hi) => clamp(x, lo, hi) - lo;

const slabNew = (ti) =>
  Math.max(0, ti - 2400000) * 0.30 + band(ti, 2000000, 2400000) * 0.25 +
  band(ti, 1600000, 2000000) * 0.20 + band(ti, 1200000, 1600000) * 0.15 +
  band(ti, 800000, 1200000) * 0.10 + band(ti, 400000, 800000) * 0.05;

const slabOld = (ti) =>
  Math.max(0, ti - 1000000) * 0.30 + band(ti, 500000, 1000000) * 0.20 + band(ti, 250000, 500000) * 0.05;

const surchargeRate = (ti, regime) => {
  if (regime === "new") return ti > 20000000 ? 0.25 : ti > 10000000 ? 0.15 : ti > 5000000 ? 0.10 : 0;
  return ti > 50000000 ? 0.37 : ti > 20000000 ? 0.25 : ti > 10000000 ? 0.15 : ti > 5000000 ? 0.10 : 0;
};

/* ============================ engine ============================ */
function compute(s) {
  const mat = MATRIX[s.level] || [0];
  const idx = clamp(s.index, 1, mat.length);
  const bpMatrix = mat[idx - 1];
  const bp = s.bpOverride > 0 ? s.bpOverride : Math.round(bpMatrix * s.fitment);

  const npa = s.npaOn ? Math.max(0, Math.min(Math.round(bp * s.npaRate), s.npaCap - bp)) : 0;
  const da = Math.round((bp + npa) * s.daRate);
  const hraRate = s.hraClass === "X" ? 0.30 : s.hraClass === "Y" ? 0.20 : 0.10;
  const hraFloor = s.hraClass === "X" ? 5400 : s.hraClass === "Y" ? 3600 : 1800;
  const hra = Math.max(Math.round(bp * hraRate), hraFloor);

  const n = lvlNum(s.level);
  const taBase = n >= 9 ? (s.tpta ? 7200 : 3600) : n >= 3 ? (s.tpta ? 3600 : 1800) : (s.tpta ? 1350 : 900);
  const ta = Math.round(taBase * (1 + s.daRate));

  const allowances = s.allowances.map((a) => {
    const base = a.basis === "flat" ? a.value : a.basis === "pctBP" ? bp * a.value : (bp + npa) * a.value;
    return { ...a, amount: Math.round(base * (a.daOn ? 1 + s.daRate : 1)) };
  });
  const allowTotal = allowances.reduce((t, a) => t + a.amount, 0);
  const allowExempt = allowances.filter((a) => !a.taxable).reduce((t, a) => t + a.amount, 0);

  const gross = bp + npa + da + hra + ta + allowTotal;

  const npsBase = bp + (s.npaInNps ? npa : 0) + da;
  const eeRate = s.eeRate;
  const erRate = s.scheme === "UPS" ? 0.185 : 0.14;
  const ee = npsBase * eeRate;
  const er = npsBase * erRate;

  const cashDeduct = ee + s.cghs + s.cgegis + s.pt + s.otherRec;

  /* ---- tax ---- */
  const grossA = gross * 12, erA = er * 12, eeA = ee * 12, ptA = s.pt * 12;
  const gti = grossA - allowExempt * 12 + erA + s.otherIncome;

  const sal80 = (bp + da + (s.npaIn80 ? npa : 0)) * 12;
  const d80ccd2 = Math.min(erA, 0.14 * sal80);

  // new regime
  const tiNew = Math.round(Math.max(0, gti - 75000 - d80ccd2));
  const rawNew = slabNew(tiNew);
  const rebNew = tiNew <= 1200000 ? rawNew : Math.max(0, Math.min(rawNew, 60000) - (tiNew - 1200000));
  const afterNew = Math.max(0, rawNew - rebNew);
  const surNew = afterNew * surchargeRate(tiNew, "new");
  const cessNew = (afterNew + surNew) * 0.04;
  const taxNew = Math.round(afterNew + surNew + cessNew);

  // old regime
  const hraSal = (bp + npa + da) * 12;
  const hraEx = Math.min(hra * 12, Math.max(0, s.rent * 12 - 0.1 * hraSal), (s.metro ? 0.5 : 0.4) * hraSal);
  const d80c = Math.min(150000, s.inv80c + eeA);
  const d80ccd1b = Math.min(50000, s.inv80ccd1b);
  const tiOld = Math.round(Math.max(0, gti - hraEx - 50000 - ptA - d80ccd2 - d80c - d80ccd1b - s.inv80d - s.invOther));
  const rawOld = slabOld(tiOld);
  const rebOld = tiOld <= 500000 ? Math.min(rawOld, 12500) : 0;
  const afterOld = Math.max(0, rawOld - rebOld);
  const surOld = afterOld * surchargeRate(tiOld, "old");
  const cessOld = (afterOld + surOld) * 0.04;
  const taxOld = Math.round(afterOld + surOld + cessOld);

  const taxSel = s.regime === "old" ? taxOld : taxNew;
  const taxM = Math.round(taxSel / 12);
  const net = gross - cashDeduct - taxM;

  return {
    bpMatrix, idx, bp, npa, da, hra, ta, taBase, hraRate, allowances, allowTotal, allowExempt,
    gross, npsBase, ee, er, eeRate, erRate, cashDeduct, net, ctc: gross + er, npsTotal: ee + er,
    gti, d80ccd2, hraEx, d80c, d80ccd1b, ptA, eeA, erA,
    tiNew, rawNew, rebNew, surNew, cessNew, taxNew,
    tiOld, rawOld, rebOld, surOld, cessOld, taxOld,
    taxSel, taxM, better: taxNew < taxOld ? "new" : taxNew > taxOld ? "old" : "tie",
    gap: Math.abs(taxNew - taxOld),
    effRate: gti > 0 ? taxSel / gti : 0,
  };
}

/* ============================ defaults ============================ */
const baseScenario = {
  level: "10", index: 1, fitment: 1, bpOverride: 0,
  npaOn: true, npaRate: 0.20, npaCap: 237500, daRate: 0.60,
  hraClass: "Y", tpta: true,
  allowances: [{ id: 1, name: "Academic allowance", basis: "flat", value: 0, daOn: false, taxable: true }],
  scheme: "NPS", eeRate: 0.10, npaInNps: true, npaIn80: false,
  cghs: 650, cgegis: 120, pt: 200, otherRec: 0,
  regime: "new", otherIncome: 0, rent: 0, metro: false,
  inv80c: 0, inv80ccd1b: 0, inv80d: 0, invOther: 0,
};
const A0 = { ...baseScenario, allowances: baseScenario.allowances.map((a) => ({ ...a })) };
const B0 = { ...baseScenario, level: "12", index: 1, hraClass: "X",
  allowances: [{ id: 1, name: "Academic allowance", basis: "flat", value: 0, daOn: false, taxable: true }] };

/* ============================ styles ============================ */
const CSS = `
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap');
.pb { --paper:#FBFCFD; --card:#FFFFFF; --rule:#DCE3EB; --rule2:#EDF1F5;
  --ink:#16202B; --mut:#5B6B7C; --faint:#8A98A6;
  --a:#16607A; --aSoft:#E4F0F4; --b:#6D3F8F; --bSoft:#F0E9F7;
  --pos:#146B45; --neg:#A33A2E; --posSoft:#E6F2EB;
  font-family:'IBM Plex Sans',ui-sans-serif,system-ui,sans-serif; color:var(--ink);
  background:var(--paper); -webkit-font-smoothing:antialiased; }
.pb *,.pb *::before,.pb *::after { box-sizing:border-box; }
.pb .num { font-family:'IBM Plex Mono',ui-monospace,monospace; font-variant-numeric:tabular-nums; letter-spacing:-0.01em; }
.pb .eyebrow { font-size:10px; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--faint); }
.pb h1 { font-size:26px; font-weight:600; letter-spacing:-.025em; margin:2px 0 0; line-height:1.15; }
.pb h2 { font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--mut); margin:0; }
.pb .wrap { max-width:1240px; margin:0 auto; padding:22px 20px 56px; }
.pb .card { background:var(--card); border:1px solid var(--rule); border-radius:10px; }
.pb .pad { padding:16px 18px; }
.pb .rule { border-top:1px solid var(--rule2); }

/* matrix strip — the signature */
.pb .strip { display:flex; gap:5px; overflow-x:auto; padding:12px 4px 14px; scrollbar-width:thin; }
.pb .stage { flex:0 0 auto; min-width:76px; padding:7px 8px 6px; border:1px solid var(--rule);
  border-radius:7px; background:#fff; cursor:pointer; text-align:right; transition:all .13s ease; }
.pb .stage:hover { border-color:var(--mut); transform:translateY(-1px); }
.pb .stage:focus-visible { outline:2px solid var(--a); outline-offset:2px; }
.pb .stage .si { display:block; font-size:9px; color:var(--faint); text-align:left; margin-bottom:1px; }
.pb .stage .sv { display:block; font-size:12px; font-weight:500; }
.pb .stage.onA { border-color:var(--a); background:var(--aSoft); box-shadow:inset 0 0 0 1px var(--a); }
.pb .stage.onA .si, .pb .stage.onA .sv { color:var(--a); font-weight:600; }
.pb .stage.onB { border-color:var(--b); background:var(--bSoft); box-shadow:inset 0 0 0 1px var(--b); }
.pb .stage.onB .si, .pb .stage.onB .sv { color:var(--b); font-weight:600; }
.pb .stage.onAB { border-color:var(--ink); background:#F4F6F8; box-shadow:inset 0 0 0 1px var(--ink); }

/* controls */
.pb label.f { display:block; font-size:11px; color:var(--mut); margin-bottom:4px; font-weight:500; }
.pb input[type=text],.pb input[type=number],.pb select {
  width:100%; font-family:'IBM Plex Mono',monospace; font-size:13px; font-variant-numeric:tabular-nums;
  padding:6px 8px; border:1px solid var(--rule); border-radius:6px; background:#fff; color:var(--ink); }
.pb select { font-family:'IBM Plex Sans',sans-serif; }
.pb input:focus,.pb select:focus { outline:none; border-color:var(--a); box-shadow:0 0 0 3px var(--aSoft); }
.pb .grid2 { display:grid; grid-template-columns:1fr 1fr; gap:10px 12px; }
.pb .grid3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px 12px; }

.pb .seg { display:inline-flex; border:1px solid var(--rule); border-radius:7px; overflow:hidden; background:#fff; }
.pb .seg button { border:0; background:#fff; padding:6px 13px; font:inherit; font-size:12px; font-weight:500;
  color:var(--mut); cursor:pointer; border-right:1px solid var(--rule2); }
.pb .seg button:last-child { border-right:0; }
.pb .seg button.on { background:var(--ink); color:#fff; }
.pb .seg button.onA { background:var(--a); color:#fff; }
.pb .seg button.onB { background:var(--b); color:#fff; }

.pb .sw { display:flex; align-items:center; gap:7px; font-size:12px; color:var(--ink); cursor:pointer; user-select:none; }
.pb .sw input { accent-color:var(--a); width:15px; height:15px; cursor:pointer; }

.pb details { border-top:1px solid var(--rule2); }
.pb details:first-of-type { border-top:0; }
.pb summary { list-style:none; cursor:pointer; padding:11px 18px; display:flex; align-items:center;
  justify-content:space-between; font-size:12px; font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--mut); }
.pb summary::-webkit-details-marker { display:none; }
.pb summary:hover { color:var(--ink); }
.pb summary .chev { font-size:10px; color:var(--faint); transition:transform .15s; }
.pb details[open] summary .chev { transform:rotate(90deg); }
.pb .body { padding:2px 18px 18px; }

/* ledger */
.pb table { width:100%; border-collapse:collapse; }
.pb td { padding:5px 0; font-size:13px; vertical-align:baseline; }
.pb td.n { text-align:right; font-family:'IBM Plex Mono',monospace; font-variant-numeric:tabular-nums; white-space:nowrap; }
.pb tr.sub td { border-top:1px solid var(--rule); font-weight:600; padding-top:7px; }
.pb tr.tot td { border-top:2px solid var(--ink); font-weight:600; padding-top:8px; font-size:14px; }
.pb .lbl { color:var(--mut); }
.pb .hint { font-size:10.5px; color:var(--faint); line-height:1.45; }

.pb .hero { display:flex; flex-wrap:wrap; gap:2px 26px; align-items:flex-end; }
.pb .heroN { font-family:'IBM Plex Mono',monospace; font-variant-numeric:tabular-nums;
  font-size:34px; font-weight:600; letter-spacing:-.03em; line-height:1; }
.pb .chip { display:inline-block; font-size:10px; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  padding:3px 7px; border-radius:4px; }
.pb .chipA { background:var(--aSoft); color:var(--a); }
.pb .chipB { background:var(--bSoft); color:var(--b); }
.pb .chipP { background:var(--posSoft); color:var(--pos); }

.pb .arow { display:grid; grid-template-columns:1.5fr .9fr .8fr auto auto auto; gap:8px; align-items:center; margin-bottom:7px; }
.pb .xbtn { border:1px solid var(--rule); background:#fff; color:var(--faint); border-radius:6px;
  width:26px; height:28px; cursor:pointer; font-size:14px; line-height:1; }
.pb .xbtn:hover { color:var(--neg); border-color:var(--neg); }
.pb .addbtn { border:1px dashed var(--rule); background:#fff; color:var(--mut); border-radius:6px;
  padding:7px 12px; font:inherit; font-size:12px; cursor:pointer; width:100%; }
.pb .addbtn:hover { border-color:var(--a); color:var(--a); }

.pb .cols { display:grid; grid-template-columns:minmax(0,380px) minmax(0,1fr); gap:18px; align-items:start; }
@media (max-width:900px){ .pb .cols { grid-template-columns:1fr; } .pb .grid3 { grid-template-columns:1fr 1fr; } }
@media (max-width:520px){ .pb .grid2,.pb .grid3 { grid-template-columns:1fr; }
  .pb .arow { grid-template-columns:1fr 1fr; } .pb h1{font-size:21px;} .pb .heroN{font-size:27px;} }
@media (prefers-reduced-motion:reduce){ .pb *{transition:none!important;} }
`;

/* ============================ small components ============================ */
const Field = ({ label, hint, children }) => (
  <div><label className="f">{label}</label>{children}
    {hint && <div className="hint" style={{ marginTop: 3 }}>{hint}</div>}</div>
);
const Num = ({ value, onChange, step = 1, min = 0 }) => (
  <input type="number" value={value} step={step} min={min}
    onChange={(e) => onChange(e.target.value === "" ? 0 : parseFloat(e.target.value))} />
);
const Pct = ({ value, onChange }) => (
  <input type="number" value={+(value * 100).toFixed(2)} step={0.5} min={0}
    onChange={(e) => onChange((parseFloat(e.target.value) || 0) / 100)} />
);
const Sec = ({ title, note, open, children }) => (
  <details open={open}><summary><span>{title}</span><span className="chev">›</span></summary>
    <div className="body">{note && <div className="hint" style={{ marginBottom: 12 }}>{note}</div>}{children}</div>
  </details>
);
const Row = ({ label, val, cls = "", sub, hint }) => (
  <tr className={cls}><td>{label}{hint && <div className="hint">{hint}</div>}</td>
    <td className="n">{sub ? `(${inr(Math.abs(val))})` : inr(val)}</td></tr>
);

/* ============================ main ============================ */
export default function PayBench() {
  const [cmp, setCmp] = useState(false);
  const [edit, setEdit] = useState("A");
  const [A, setA] = useState(A0);
  const [B, setB] = useState(B0);
  const [detail, setDetail] = useState(false);

  const cur = edit === "B" && cmp ? B : A;
  const setCur = edit === "B" && cmp ? setB : setA;
  const up = useCallback((patch) => setCur((s) => ({ ...s, ...patch })), [setCur]);

  const rA = useMemo(() => compute(A), [A]);
  const rB = useMemo(() => compute(B), [B]);
  const r = edit === "B" && cmp ? rB : rA;

  const mat = MATRIX[cur.level] || [];
  const accent = edit === "B" && cmp ? "var(--b)" : "var(--a)";

  const setAllow = (i, patch) =>
    up({ allowances: cur.allowances.map((a, k) => (k === i ? { ...a, ...patch } : a)) });
  const addAllow = () =>
    up({ allowances: [...cur.allowances, { id: Date.now(), name: "", basis: "flat", value: 0, daOn: false, taxable: true }] });
  const delAllow = (i) => up({ allowances: cur.allowances.filter((_, k) => k !== i) });

  /* --------- results panel --------- */
  const Ledger = ({ res, sc, tint }) => (
    <div>
      <div className="hero" style={{ marginBottom: 14 }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 5 }}>Net in hand · monthly</div>
          <div className="heroN" style={{ color: tint }}>₹{inr(res.net)}</div>
        </div>
        <div>
          <div className="eyebrow" style={{ marginBottom: 5 }}>Tax · monthly</div>
          <div className="heroN" style={{ fontSize: 20, color: "var(--mut)" }}>₹{inr(res.taxM)}</div>
        </div>
        <div>
          <div className="eyebrow" style={{ marginBottom: 5 }}>Cost to govt</div>
          <div className="heroN" style={{ fontSize: 20, color: "var(--mut)" }}>₹{inr(res.ctc)}</div>
        </div>
      </div>

      <table>
        <tbody>
          <tr><td colSpan={2}><h2 style={{ paddingTop: 4 }}>Earnings</h2></td></tr>
          <Row label="Basic pay" val={res.bp} />
          <Row label={`NPA · ${(sc.npaRate * 100).toFixed(0)}% of basic`} val={res.npa} />
          <Row label={`DA · ${(sc.daRate * 100).toFixed(0)}% of basic + NPA`} val={res.da} />
          <Row label={`HRA · ${(res.hraRate * 100).toFixed(0)}% of basic`} val={res.hra} />
          <Row label={`Transport · ₹${inr(res.taBase)} + DA`} val={res.ta} />
          {res.allowances.map((a, i) => (
            <Row key={a.id ?? i} label={(a.name || "Unnamed allowance") + (a.taxable ? "" : " · exempt")} val={a.amount} />
          ))}
          <Row label="Gross salary" val={res.gross} cls="sub" />

          <tr><td colSpan={2}><h2 style={{ paddingTop: 14 }}>Deductions</h2></td></tr>
          <Row label={`${sc.scheme} · employee ${(res.eeRate * 100).toFixed(1)}%`} val={res.ee} sub
               hint={`on ₹${inr(res.npsBase)} (basic${sc.npaInNps ? " + NPA" : ""} + DA)`} />
          <Row label="CGHS" val={sc.cghs} sub />
          <Row label="CGEGIS" val={sc.cgegis} sub />
          <Row label="Professional tax" val={sc.pt} sub />
          {sc.otherRec > 0 && <Row label="Other recoveries" val={sc.otherRec} sub />}
          <Row label={`Income tax · ${sc.regime === "old" ? "old" : "new"} regime`} val={res.taxM} sub />
          <Row label="Total deductions" val={res.cashDeduct + res.taxM} cls="sub" sub />
          <Row label="Net in hand" val={res.net} cls="tot" />

          <tr><td colSpan={2}><h2 style={{ paddingTop: 14 }}>Pension corpus · not cash</h2></td></tr>
          <Row label={`Government share · ${(res.erRate * 100).toFixed(1)}%`} val={res.er} />
          <Row label="Total monthly inflow" val={res.npsTotal} cls="sub" />
        </tbody>
      </table>

      <div style={{ marginTop: 18, padding: 13, borderRadius: 8,
        background: res.better === "new" ? "var(--posSoft)" : "#FDF3E8",
        border: "1px solid " + (res.better === "new" ? "#CBE4D5" : "#F0DCC2") }}>
        <div style={{ display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 8 }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 3 }}>Cheaper regime</div>
            <div style={{ fontWeight: 600, fontSize: 15 }}>
              {res.better === "tie" ? "Identical" : res.better === "new" ? "New regime" : "Old regime"}
            </div>
          </div>
          <div style={{ textAlign: "right" }}>
            <div className="eyebrow" style={{ marginBottom: 3 }}>Saves per year</div>
            <div className="num" style={{ fontWeight: 600, fontSize: 15 }}>₹{inr(res.gap)}</div>
          </div>
        </div>
        <div className="hint" style={{ marginTop: 8 }}>
          Annual tax — new ₹{inr(res.taxNew)} · old ₹{inr(res.taxOld)}. New regime is the statutory default;
          you must opt in to the old one. Effective rate {(res.effRate * 100).toFixed(2)}% of gross total income.
        </div>
      </div>

      {detail && (
        <table style={{ marginTop: 16 }}>
          <tbody>
            <tr><td colSpan={2}><h2>Tax working · annual · {sc.regime === "old" ? "old" : "new"} regime</h2></td></tr>
            <Row label="Gross total income" val={res.gti} hint="cash salary + govt NPS share + other income, less exempt allowances" />
            {sc.regime === "old" && <Row label="HRA exemption · 10(13A)" val={res.hraEx} sub />}
            <Row label="Standard deduction" val={sc.regime === "old" ? 50000 : 75000} sub />
            {sc.regime === "old" && <Row label="Professional tax · 16(iii)" val={res.ptA} sub />}
            <Row label="Employer NPS · 80CCD(2)" val={res.d80ccd2} sub
                 hint={`capped at 14% of basic + DA${sc.npaIn80 ? " + NPA" : ""}`} />
            {sc.regime === "old" && <><Row label="80C" val={res.d80c} sub />
              <Row label="80CCD(1B)" val={res.d80ccd1b} sub />
              <Row label="80D" val={sc.inv80d} sub />
              <Row label="Other Chapter VI-A" val={sc.invOther} sub /></>}
            <Row label="Taxable income" val={sc.regime === "old" ? res.tiOld : res.tiNew} cls="sub" />
            <Row label="Tax at slab rates" val={sc.regime === "old" ? res.rawOld : res.rawNew} />
            <Row label="87A rebate" val={sc.regime === "old" ? res.rebOld : res.rebNew} sub />
            <Row label="Surcharge" val={sc.regime === "old" ? res.surOld : res.surNew} />
            <Row label="Cess @ 4%" val={sc.regime === "old" ? res.cessOld : res.cessNew} />
            <Row label="Tax payable" val={sc.regime === "old" ? res.taxOld : res.taxNew} cls="tot" />
          </tbody>
        </table>
      )}
    </div>
  );

  const Delta = () => {
    const rows = [
      ["Basic pay", rA.bp, rB.bp], ["NPA", rA.npa, rB.npa], ["DA", rA.da, rB.da],
      ["HRA", rA.hra, rB.hra], ["Transport", rA.ta, rB.ta], ["Other allowances", rA.allowTotal, rB.allowTotal],
      ["Gross salary", rA.gross, rB.gross, "sub"],
      ["Employee NPS", -rA.ee, -rB.ee], ["Other deductions", -(rA.cashDeduct - rA.ee), -(rB.cashDeduct - rB.ee)],
      ["Income tax", -rA.taxM, -rB.taxM],
      ["Net in hand", rA.net, rB.net, "tot"],
      ["Govt NPS share", rA.er, rB.er], ["Cost to govt", rA.ctc, rB.ctc, "sub"],
      ["Annual tax · new", rA.taxNew, rB.taxNew], ["Annual tax · old", rA.taxOld, rB.taxOld],
    ];
    const head = (t, c, sc) => (
      <div><span className={"chip " + c}>{t}</span>
        <div className="hint" style={{ marginTop: 4 }}>Level {sc.level} · stage {sc.index} · {sc.hraClass} class · {sc.scheme} · {sc.regime} regime</div></div>
    );
    return (
      <div className="card pad">
        <div className="grid2" style={{ marginBottom: 14 }}>
          {head("Scenario A", "chipA", A)}{head("Scenario B", "chipB", B)}
        </div>
        <div className="grid2" style={{ marginBottom: 16 }}>
          <div><div className="eyebrow">Net in hand</div>
            <div className="heroN" style={{ fontSize: 27, color: "var(--a)" }}>₹{inr(rA.net)}</div></div>
          <div><div className="eyebrow">Net in hand</div>
            <div className="heroN" style={{ fontSize: 27, color: "var(--b)" }}>₹{inr(rB.net)}</div>
            <div style={{ marginTop: 5 }}>
              <span className="chip chipP" style={{
                background: rB.net >= rA.net ? "var(--posSoft)" : "#FBE9E7",
                color: rB.net >= rA.net ? "var(--pos)" : "var(--neg)" }}>
                {rB.net >= rA.net ? "+" : "−"}₹{inr(Math.abs(rB.net - rA.net))} vs A
              </span></div></div>
        </div>
        <table>
          <thead><tr>
            <td style={{ fontSize: 10, letterSpacing: ".1em", textTransform: "uppercase", color: "var(--faint)", fontWeight: 600 }}>Head</td>
            <td className="n" style={{ fontSize: 10, letterSpacing: ".1em", textTransform: "uppercase", color: "var(--a)", fontWeight: 600 }}>A</td>
            <td className="n" style={{ fontSize: 10, letterSpacing: ".1em", textTransform: "uppercase", color: "var(--b)", fontWeight: 600 }}>B</td>
            <td className="n" style={{ fontSize: 10, letterSpacing: ".1em", textTransform: "uppercase", color: "var(--faint)", fontWeight: 600 }}>B − A</td>
          </tr></thead>
          <tbody>
            {rows.map(([lab, a, b, cls], i) => {
              const d = b - a;
              return (
                <tr key={i} className={cls || ""}>
                  <td className="lbl" style={cls ? { color: "var(--ink)" } : undefined}>{lab}</td>
                  <td className="n">{a < 0 ? `(${inr(-a)})` : inr(a)}</td>
                  <td className="n">{b < 0 ? `(${inr(-b)})` : inr(b)}</td>
                  <td className="n" style={{ color: d === 0 ? "var(--faint)" : d > 0 ? "var(--pos)" : "var(--neg)" }}>
                    {d === 0 ? "—" : (d > 0 ? "+" : "−") + inr(Math.abs(d))}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        <div className="hint" style={{ marginTop: 12 }}>
          Deductions shown in parentheses. B − A is computed on the monthly figure except for the two annual tax rows.
        </div>
      </div>
    );
  };

  return (
    <div className="pb">
      <style>{CSS}</style>
      <div className="wrap">

        {/* header */}
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 12, marginBottom: 16 }}>
          <div>
            <div className="eyebrow">7th CPC pay matrix · FY 2026-27 · AY 2027-28</div>
            <h1>Pay bench</h1>
            <div className="hint" style={{ marginTop: 5, maxWidth: 520 }}>
              Central Government salary, NPS and income tax. Change anything on the left; the ledger recomputes as you type.
            </div>
          </div>
          <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
            <label className="sw"><input type="checkbox" checked={detail} onChange={(e) => setDetail(e.target.checked)} />Tax working</label>
            <div className="seg">
              <button className={!cmp ? "on" : ""} onClick={() => setCmp(false)}>Single</button>
              <button className={cmp ? "on" : ""} onClick={() => { setCmp(true); }}>Compare A / B</button>
            </div>
          </div>
        </div>

        {/* signature: pay matrix strip */}
        <div className="card" style={{ marginBottom: 18, overflow: "hidden" }}>
          <div className="pad" style={{ paddingBottom: 0, display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 8 }}>
            <h2>Pay matrix · level {cur.level} · {mat.length} stages</h2>
            <div className="hint">Each stage is a 3% increment rounded up to the next ₹100. Click a stage to sit on it.</div>
          </div>
          <div className="strip" style={{ paddingLeft: 18, paddingRight: 18 }}>
            {mat.map((v, i) => {
              const isA = A.level === cur.level && A.index === i + 1;
              const isB = cmp && B.level === cur.level && B.index === i + 1;
              const cls = isA && isB ? "onAB" : isA ? "onA" : isB ? "onB" : "";
              return (
                <button key={i} className={"stage " + cls} onClick={() => up({ index: i + 1 })}
                  aria-label={`Stage ${i + 1}, ${v} rupees`}>
                  <span className="si num">{i + 1}{isA ? " ·A" : ""}{isB ? " ·B" : ""}</span>
                  <span className="sv num">{inr(v)}</span>
                </button>
              );
            })}
          </div>
        </div>

        {/* scenario switch */}
        {cmp && (
          <div style={{ marginBottom: 14, display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
            <span className="eyebrow">Editing</span>
            <div className="seg">
              <button className={edit === "A" ? "onA" : ""} onClick={() => setEdit("A")}>Scenario A</button>
              <button className={edit === "B" ? "onB" : ""} onClick={() => setEdit("B")}>Scenario B</button>
            </div>
            <button className="xbtn" style={{ width: "auto", padding: "0 11px", height: 30, fontSize: 12 }}
              onClick={() => { const a = JSON.parse(JSON.stringify(A)); const b = JSON.parse(JSON.stringify(B));
                setA(b); setB(a); }}>Swap A ⇄ B</button>
            <button className="xbtn" style={{ width: "auto", padding: "0 11px", height: 30, fontSize: 12 }}
              onClick={() => { const src = edit === "A" ? A : B; const copy = JSON.parse(JSON.stringify(src));
                edit === "A" ? setB(copy) : setA(copy); }}>Copy {edit} → {edit === "A" ? "B" : "A"}</button>
          </div>
        )}

        <div className="cols">
          {/* ---------------- inputs ---------------- */}
          <div className="card" style={{ borderTop: `3px solid ${accent}` }}>
            <Sec title="Pay fixation" open>
              <div className="grid2">
                <Field label="Pay level">
                  <select value={cur.level} onChange={(e) => up({ level: e.target.value, index: 1 })}>
                    {LEVELS.map((l) => <option key={l} value={l}>Level {l}</option>)}
                  </select>
                </Field>
                <Field label={`Stage (1–${mat.length})`}>
                  <Num value={cur.index} min={1} onChange={(v) => up({ index: clamp(Math.round(v), 1, mat.length) })} />
                </Field>
                <Field label="Fitment factor" hint="1.00 = current 7th CPC. Try 1.92 / 2.28 / 2.57 for an 8th CPC scenario.">
                  <Num value={cur.fitment} step={0.01} onChange={(v) => up({ fitment: v })} />
                </Field>
                <Field label="Basic pay override" hint="Leave 0 to use the matrix.">
                  <Num value={cur.bpOverride} step={100} onChange={(v) => up({ bpOverride: v })} />
                </Field>
              </div>
              <div style={{ marginTop: 11, padding: "9px 11px", background: "#F6F8FA", borderRadius: 7 }}>
                <span className="eyebrow">Basic pay applied</span>
                <div className="num" style={{ fontSize: 18, fontWeight: 600, color: accent }}>₹{inr(r.bp)}</div>
              </div>
            </Sec>

            <Sec title="Allowance parameters" open>
              <div className="grid2">
                <Field label="DA rate %" hint="60% from 1 Jan 2026. July instalment expected ~63%, not yet notified.">
                  <Pct value={cur.daRate} onChange={(v) => up({ daRate: v })} />
                </Field>
                <Field label="HRA city class" hint="X 30% · Y 20% · Z 10%. Bhubaneswar is Y.">
                  <select value={cur.hraClass} onChange={(e) => up({ hraClass: e.target.value })}>
                    <option value="X">X — 30%</option><option value="Y">Y — 20%</option><option value="Z">Z — 10%</option>
                  </select>
                </Field>
                <Field label="NPA rate %" hint={`Capped so basic + NPA ≤ ₹${inr(cur.npaCap)}.`}>
                  <Pct value={cur.npaRate} onChange={(v) => up({ npaRate: v })} />
                </Field>
                <Field label="Cap on basic + NPA">
                  <Num value={cur.npaCap} step={2500} onChange={(v) => up({ npaCap: v })} />
                </Field>
              </div>
              <div style={{ display: "flex", gap: 16, marginTop: 12, flexWrap: "wrap" }}>
                <label className="sw"><input type="checkbox" checked={cur.npaOn} onChange={(e) => up({ npaOn: e.target.checked })} />NPA applicable</label>
                <label className="sw"><input type="checkbox" checked={cur.tpta} onChange={(e) => up({ tpta: e.target.checked })} />Higher-TPTA city</label>
              </div>
              <div className="hint" style={{ marginTop: 7 }}>
                Transport allowance ₹{inr(r.taBase)} for level {cur.level}, plus DA at the same rate.
              </div>
            </Sec>

            <Sec title={`Other allowances · ${cur.allowances.length}`}
                 note="Add any head that appears on your pay bill. Academic allowance, PG allowance, deputation, uniform — whatever applies.">
              {cur.allowances.map((a, i) => (
                <div key={a.id ?? i}>
                  <div className="arow">
                    <input type="text" placeholder="Allowance name" value={a.name}
                      onChange={(e) => setAllow(i, { name: e.target.value })} style={{ fontFamily: "'IBM Plex Sans',sans-serif" }} />
                    <select value={a.basis} onChange={(e) => setAllow(i, { basis: e.target.value })}>
                      <option value="flat">Flat ₹</option><option value="pctBP">% of basic</option><option value="pctBPNPA">% of basic + NPA</option>
                    </select>
                    {a.basis === "flat"
                      ? <Num value={a.value} step={100} onChange={(v) => setAllow(i, { value: v })} />
                      : <Pct value={a.value} onChange={(v) => setAllow(i, { value: v })} />}
                    <label className="sw" title="DA payable on this allowance">
                      <input type="checkbox" checked={a.daOn} onChange={(e) => setAllow(i, { daOn: e.target.checked })} />DA</label>
                    <label className="sw" title="Taxable in the hands of the employee">
                      <input type="checkbox" checked={a.taxable} onChange={(e) => setAllow(i, { taxable: e.target.checked })} />Tax</label>
                    <button className="xbtn" onClick={() => delAllow(i)} aria-label="Remove allowance">×</button>
                  </div>
                  <div className="hint" style={{ margin: "-2px 0 9px" }}>
                    Pays ₹{inr(r.allowances[i]?.amount || 0)} a month{a.taxable ? "" : " · exempt from tax"}
                  </div>
                </div>
              ))}
              <button className="addbtn" onClick={addAllow}>+ Add an allowance</button>
            </Sec>

            <Sec title="Pension & deductions">
              <div className="grid2">
                <Field label="Scheme" hint="UPS carries an 18.5% government share.">
                  <select value={cur.scheme} onChange={(e) => up({ scheme: e.target.value })}>
                    <option value="NPS">NPS — govt 14%</option><option value="UPS">UPS — govt 18.5%</option>
                  </select>
                </Field>
                <Field label="Employee share %"><Pct value={cur.eeRate} onChange={(v) => up({ eeRate: v })} /></Field>
                <Field label="CGHS ₹/month" hint="Level 7–11 ₹650 · level 12+ ₹1,000."><Num value={cur.cghs} step={50} onChange={(v) => up({ cghs: v })} /></Field>
                <Field label="CGEGIS ₹/month"><Num value={cur.cgegis} step={10} onChange={(v) => up({ cgegis: v })} /></Field>
                <Field label="Professional tax ₹/month" hint="Odisha caps the year at ₹2,500."><Num value={cur.pt} step={50} onChange={(v) => up({ pt: v })} /></Field>
                <Field label="Other recoveries ₹/month"><Num value={cur.otherRec} step={100} onChange={(v) => up({ otherRec: v })} /></Field>
              </div>
              <div style={{ display: "flex", gap: 16, marginTop: 12, flexWrap: "wrap" }}>
                <label className="sw"><input type="checkbox" checked={cur.npaInNps} onChange={(e) => up({ npaInNps: e.target.checked })} />NPA counts in the NPS base</label>
                <label className="sw"><input type="checkbox" checked={cur.npaIn80} onChange={(e) => up({ npaIn80: e.target.checked })} />NPA counts in 80CCD(2) salary</label>
              </div>
              <div className="hint" style={{ marginTop: 7 }}>
                Section 80CCD defines salary as basic plus DA, which reads out NPA. Leaving the second box unticked is the
                conservative call — any contribution above the cap is taxed. Tick it if your DDO allows the full amount.
              </div>
            </Sec>

            <Sec title="Tax inputs">
              <div className="grid2">
                <Field label="Regime to apply">
                  <select value={cur.regime} onChange={(e) => up({ regime: e.target.value })}>
                    <option value="new">New regime</option><option value="old">Old regime</option>
                  </select>
                </Field>
                <Field label="Other income ₹/year"><Num value={cur.otherIncome} step={1000} onChange={(v) => up({ otherIncome: v })} /></Field>
                <Field label="Rent paid ₹/month" hint="Old regime only, for the 10(13A) exemption."><Num value={cur.rent} step={500} onChange={(v) => up({ rent: v })} /></Field>
                <Field label="80C ₹/year" hint="Your own NPS already counts inside the ₹1.5 lakh ceiling."><Num value={cur.inv80c} step={5000} onChange={(v) => up({ inv80c: v })} /></Field>
                <Field label="80CCD(1B) ₹/year"><Num value={cur.inv80ccd1b} step={5000} onChange={(v) => up({ inv80ccd1b: v })} /></Field>
                <Field label="80D ₹/year"><Num value={cur.inv80d} step={5000} onChange={(v) => up({ inv80d: v })} /></Field>
                <Field label="Other Chapter VI-A ₹/year"><Num value={cur.invOther} step={5000} onChange={(v) => up({ invOther: v })} /></Field>
              </div>
              <div style={{ marginTop: 12 }}>
                <label className="sw"><input type="checkbox" checked={cur.metro} onChange={(e) => up({ metro: e.target.checked })} />
                  Metro for HRA exemption — Delhi, Mumbai, Kolkata, Chennai only</label>
              </div>
            </Sec>

            <div className="body" style={{ paddingTop: 4 }}>
              <button className="addbtn" onClick={() => { setCur(edit === "B" && cmp ? { ...B0 } : { ...A0, allowances: A0.allowances.map(x => ({ ...x })) }); }}>
                Reset scenario {cmp ? edit : ""}
              </button>
            </div>
          </div>

          {/* ---------------- results ---------------- */}
          <div>
            {cmp ? (
              <>
                <Delta />
                <div style={{ marginTop: 16 }} className="card pad">
                  <div style={{ marginBottom: 12 }}>
                    <span className={"chip " + (edit === "A" ? "chipA" : "chipB")}>Scenario {edit} · full ledger</span>
                  </div>
                  <Ledger res={r} sc={cur} tint={accent} />
                </div>
              </>
            ) : (
              <div className="card pad"><Ledger res={rA} sc={A} tint="var(--a)" /></div>
            )}

            <div className="hint" style={{ marginTop: 14, lineHeight: 1.6 }}>
              <strong style={{ color: "var(--mut)" }}>Before you rely on this.</strong> CGHS, CGEGIS and professional
              tax are entered by hand — check them against your own pay slip. Marginal relief on surcharge is not
              modelled and only bites above ₹50 lakh. Employer contributions to NPS, EPF and superannuation above
              ₹7.5 lakh a year become a taxable perquisite under 17(2)(vii), which is also not modelled. Slabs,
              standard deduction, the 87A rebate, surcharge and cess are as they stand for FY 2026-27 after Budget 2026
              left them unchanged. This is a planning tool, not tax advice.
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
