// Loonrun preview / confirm flow — opens as a full-screen takeover with stepper

const LoonrunFlow = ({ onClose, onConfirm, toast }) => {
  const [step, setStep] = React.useState(1);
  const [progress, setProgress] = React.useState(0);
  const [runData, setRunData] = React.useState(null); // { run, rows, totals }
  const [err, setErr] = React.useState(null);
  const period = LS_currentPeriod;

  React.useEffect(() => {
    if (step !== 1) return;
    let cancelled = false;
    let p = 5;
    const iv = setInterval(() => {
      p = Math.min(95, p + 6 + Math.random() * 8);
      setProgress(p);
    }, 220);
    (async () => {
      try {
        const res = await fetch("/api/runs", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ year: period.year, period: period.period }),
        });
        const data = await res.json();
        if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
        if (cancelled) return;
        const rows = (data.payslips || []).map(s => ({
          e: {
            id: s.employee_id, number: s.number, first_name: s.first_name, last_name: s.last_name,
            function: s.function_title, iban: s.iban, parttime: s.parttime, hours: Number(s.hours),
            lh_table: s.lh_table, heffingskorting: s.heffingskorting, bt_pct: Number(s.bt_pct),
            base_salary: Number(s.base_salary), avatar_color: s.avatar_color,
          },
          p: {
            bruto: Number(s.bruto), loonheffing: Number(s.loonheffing), zvw: Number(s.zvw),
            zvw_pct: Number(s.zvw_pct), net: Number(s.net), arbeidskorting: Number(s.arbeidskorting),
            payslip_id: s.id,
          },
        }));
        const totals = rows.reduce((a, { p }) => {
          a.bruto += p.bruto; a.heffing += p.loonheffing; a.zvw += p.zvw; a.net += p.net; return a;
        }, { bruto: 0, heffing: 0, zvw: 0, net: 0 });
        setRunData({ run: data.run, rows, totals });
        setProgress(100);
        clearInterval(iv);
        // Refresh the store so the new (unconfirmed) run shows up on dashboard/documents
        // even if the user cancels before confirming.
        window.LS_store?.refreshRuns?.();
        setTimeout(() => { if (!cancelled) setStep(2); }, 350);
      } catch (e) {
        if (!cancelled) { setErr(e.message); clearInterval(iv); }
      }
    })();
    return () => { cancelled = true; clearInterval(iv); };
  }, [step]);

  const rows = runData?.rows || [];
  const totals = runData?.totals || { bruto: 0, heffing: 0, zvw: 0, net: 0 };
  const run = runData?.run;

  const doConfirm = async () => {
    try {
      await fetch(`/api/runs/${run.id}/confirm`, { method: "POST" });
      await window.LS_store?.refreshRuns?.();
      setStep(4);
      setTimeout(() => onConfirm(), 1400);
    } catch (e) {
      toast("Bevestigen mislukt: " + e.message);
    }
  };

  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 50, background: "var(--bg)", display: "flex", flexDirection: "column" }}>

      {/* Top bar */}
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "14px 24px",
        borderBottom: "1px solid var(--line)",
        background: "var(--surface)",
      }}>
        <Row style={{ gap: 14 }}>
          <Btn variant="ghost" size="sm" icon="x" onClick={onClose}>Sluiten</Btn>
          <div style={{ width: 1, height: 18, background: "var(--line-2)" }} />
          <Stepper step={step} />
        </Row>
        <Row style={{ gap: 10 }}>
          <Pill tone={step === 4 ? "success" : "warn"} dot>
            {step === 1 ? "Berekenen…" : step === 2 ? "Preview" : step === 3 ? "Bevestigen" : "Verzonden"}
          </Pill>
          <span style={{ fontSize: 12.5, color: "var(--ink-3)" }}>Regels <span className="num">v2026.1</span></span>
        </Row>
      </div>

      {/* Content */}
      <div style={{ flex: 1, overflowY: "auto" }}>
        {step === 1 && <Computing progress={progress} n={LS_employees.length} err={err} />}
        {step === 2 && <PreviewStep rows={rows} totals={totals} run={run} onNext={() => setStep(3)} onBack={onClose} toast={toast} />}
        {step === 3 && <ConfirmStep rows={rows} totals={totals} run={run} onBack={() => setStep(2)} onConfirm={doConfirm} toast={toast} />}
        {step === 4 && <DoneStep rows={rows} totals={totals} />}
      </div>
    </div>
  );
};

const Stepper = ({ step }) => {
  const steps = ["Berekenen", "Controleren", "Bevestigen", "Verzonden"];
  return (
    <Row style={{ gap: 0 }}>
      <div style={{ fontSize: 12.5, color: "var(--ink-3)", fontWeight: 500, marginRight: 14 }}>Loonrun april 2026</div>
      {steps.map((s, i) => {
        const active = step === i + 1;
        const done = step > i + 1;
        return (
          <Row key={s} style={{ gap: 6, marginRight: 14 }}>
            <div style={{
              width: 20, height: 20, borderRadius: 999,
              background: done ? "var(--accent)" : active ? "var(--ink)" : "var(--bg-3)",
              color: done || active ? "#fff" : "var(--ink-3)",
              fontSize: 11, fontWeight: 600,
              display: "flex", alignItems: "center", justifyContent: "center",
            }}>{done ? <Icon name="check" size={12} /> : i + 1}</div>
            <div style={{ fontSize: 12.5, color: active ? "var(--ink)" : "var(--ink-3)", fontWeight: active ? 600 : 500 }}>{s}</div>
          </Row>
        );
      })}
    </Row>
  );
};

const Computing = ({ progress, n, err }) => (
  <div style={{ maxWidth: 520, margin: "120px auto", textAlign: "center", padding: "0 24px" }}>
    {err && (
      <div style={{ marginBottom: 20, padding: "12px 14px", background: "var(--danger-2)", color: "var(--danger)", borderRadius: 8, fontSize: 13 }}>
        Loonrun mislukt: {err}
      </div>
    )}
    <div style={{ position: "relative", width: 80, height: 80, margin: "0 auto 24px" }}>
      <svg width="80" height="80" viewBox="0 0 80 80" style={{ transform: "rotate(-90deg)" }}>
        <circle cx="40" cy="40" r="34" fill="none" stroke="var(--bg-3)" strokeWidth="4" />
        <circle cx="40" cy="40" r="34" fill="none" stroke="var(--accent)" strokeWidth="4"
          strokeDasharray={`${2 * Math.PI * 34}`}
          strokeDashoffset={`${2 * Math.PI * 34 * (1 - progress / 100)}`}
          style={{ transition: "stroke-dashoffset 200ms" }} strokeLinecap="round" />
      </svg>
      <div className="num" style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 18, fontWeight: 500 }}>{Math.floor(progress)}%</div>
    </div>
    <h2 style={{ fontSize: 24 }}>Stroken worden berekend</h2>
    <div style={{ color: "var(--ink-2)", marginTop: 8, fontSize: 14 }}>Rekenregels v2026.1 toegepast op {n} actieve medewerkers. Dit duurt meestal minder dan een minuut.</div>
    <div style={{ marginTop: 24, display: "flex", flexDirection: "column", gap: 6, fontSize: 12.5, color: "var(--ink-3)", textAlign: "left", maxWidth: 360, margin: "24px auto 0" }}>
      {["Loonheffing berekend", "ZVW-bijdrage berekend", "Werknemersverzekeringen", "Loonstrook-PDF's genereren", "Aangifte & journaalpost samenstellen"].map((l, i) => {
        const threshold = (i + 1) * 18;
        const active = progress >= threshold;
        return (
          <Row key={l} style={{ gap: 8 }}>
            <Icon name={active ? "check" : "dot"} size={12} style={{ color: active ? "var(--accent)" : "var(--line-2)" }} />
            <span style={{ color: active ? "var(--ink-2)" : "var(--ink-3)" }}>{l}</span>
          </Row>
        );
      })}
    </div>
  </div>
);

const AICheckPanel = ({ rows, totals }) => {
  const [state, setState] = React.useState("loading"); // loading | ok | error
  const [data, setData] = React.useState(null);
  const [err, setErr] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await window.LS_ai.check({
          period: LS_currentPeriod.label,
          rulesVersion: "v2026.1",
          rows,
          totals,
        });
        if (cancelled) return;
        setData(res);
        setState("ok");
      } catch (e) {
        if (cancelled) return;
        setErr(e.message || "onbekende fout");
        setState("error");
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const sevTone = (s) => s === "error" ? "danger" : s === "warn" ? "warn" : "info";
  const sevLabel = (s) => s === "error" ? "Fout" : s === "warn" ? "Let op" : "Info";

  return (
    <Card style={{ marginBottom: 18, padding: 0 }}>
      <Row style={{ justifyContent: "space-between", padding: "12px 16px", borderBottom: "1px solid var(--line)" }}>
        <Row style={{ gap: 10 }}>
          <Icon name="sparkle" size={15} style={{ color: "var(--accent)" }} />
          <div style={{ fontSize: 12.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: 0.7, color: "var(--ink-2)" }}>AI-controle van berekeningen</div>
          {state === "loading" && <Pill tone="neutral" dot>Controle loopt…</Pill>}
          {state === "ok" && (data?.anomalies?.length ? <Pill tone="warn" dot>{data.anomalies.length} bevindingen</Pill> : <Pill tone="success" dot>Geen bevindingen</Pill>)}
          {state === "error" && <Pill tone="danger" dot>Controle mislukt</Pill>}
        </Row>
        <Row style={{ gap: 8 }}>
          <Pill tone="neutral">🔒 via OpenRouter · EU-routing</Pill>
          <span style={{ fontSize: 11.5, color: "var(--ink-3)" }} className="num">{data?.model || ""}</span>
        </Row>
      </Row>

      <div style={{ padding: "14px 16px" }}>
        {state === "loading" && (
          <div style={{ fontSize: 13, color: "var(--ink-2)" }}>
            Een AI-controleur vergelijkt de berekende stroken met de gepinde regels v2026.1 — deze AI rekent niet zelf, ze flagt alleen mogelijke afwijkingen.
          </div>
        )}
        {state === "error" && (
          <div style={{ fontSize: 13, color: "var(--danger)" }}>
            Kon AI-controle niet uitvoeren: <span className="num">{err}</span>. Check of OPENROUTER_API_KEY in .env is ingesteld. De loonrun kan gewoon doorgaan.
          </div>
        )}
        {state === "ok" && (
          <>
            {data.summary && (
              <div style={{ fontSize: 13, color: "var(--ink-2)", marginBottom: data.anomalies?.length ? 12 : 0 }}>
                {data.summary}
              </div>
            )}
            {data.anomalies?.length > 0 && (
              <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
                {data.anomalies.map((a, i) => {
                  const emp = rows.find(r => r.e.id === a.empId)?.e;
                  return (
                    <Row key={i} style={{ gap: 10, padding: "10px 12px", background: "var(--bg-2)", borderRadius: 8, alignItems: "flex-start" }}>
                      <div style={{ marginTop: 2 }}><Pill tone={sevTone(a.severity)} dot>{sevLabel(a.severity)}</Pill></div>
                      <div style={{ flex: 1 }}>
                        {emp && <div style={{ fontSize: 12.5, fontWeight: 500 }}>{emp.last_name}, {emp.first_name} <span style={{ color: "var(--ink-3)", fontWeight: 400 }}>· {emp.function}</span></div>}
                        <div style={{ fontSize: 12.5, color: "var(--ink-2)", marginTop: 2 }}>{a.message}</div>
                      </div>
                    </Row>
                  );
                })}
              </div>
            )}
          </>
        )}
      </div>
    </Card>
  );
};

const PreviewStep = ({ rows, totals, onNext, onBack, toast }) => {
  const [selected, setSelected] = React.useState(rows[0]?.e?.id || null);
  const selRow = rows.find(r => r.e.id === selected) || rows[0];
  if (!selRow) {
    return (
      <div style={{ padding: "60px 32px", maxWidth: 640, margin: "0 auto", textAlign: "center" }}>
        <h2 style={{ fontSize: 22 }}>Geen stroken gegenereerd</h2>
        <div style={{ color: "var(--ink-2)", marginTop: 8, fontSize: 14 }}>
          De loonrun leverde geen stroken op. Controleer of er actieve medewerkers zijn en of de tax-tabel geseed is.
        </div>
        <Btn variant="secondary" onClick={onBack} style={{ marginTop: 20 }}>Sluiten</Btn>
      </div>
    );
  }

  return (
    <div style={{ display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 0, height: "100%" }}>
      <div style={{ padding: "28px 32px", borderRight: "1px solid var(--line)" }}>
        <div style={{ marginBottom: 18 }}>
          <h2 style={{ fontSize: 24 }}>Controleer de loonrun</h2>
          <div style={{ color: "var(--ink-2)", marginTop: 6, fontSize: 14, maxWidth: 600 }}>
            Loop onderstaand overzicht door. Klik op een medewerker voor de volledige strook. Als er iets niet klopt, corrigeer je de mutatie en draai je opnieuw.
          </div>
        </div>

        <AICheckPanel rows={rows} totals={totals} />

        {/* Table */}
        <Card pad={0}>
          <div style={{
            display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr",
            padding: "10px 18px",
            borderBottom: "1px solid var(--line)",
            fontSize: 11.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: 0.5, color: "var(--ink-3)",
          }}>
            <div>Medewerker</div>
            <div style={{ textAlign: "right" }}>Bruto</div>
            <div style={{ textAlign: "right" }}>Loonheffing</div>
            <div style={{ textAlign: "right" }}>ZVW</div>
            <div style={{ textAlign: "right" }}>Netto</div>
          </div>
          {rows.map(({ e, p }, i) => (
            <button key={e.id} onClick={() => setSelected(e.id)} style={{
              display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr",
              padding: "14px 18px", width: "100%",
              background: selected === e.id ? "var(--bg-2)" : "transparent",
              border: "none",
              borderTop: i === 0 ? "none" : "1px solid var(--line)",
              cursor: "pointer", textAlign: "left",
              alignItems: "center",
              borderLeft: selected === e.id ? "2px solid var(--ink)" : "2px solid transparent",
              paddingLeft: selected === e.id ? 16 : 18,
            }}>
              <Row style={{ gap: 10 }}>
                <Avatar emp={e} size={28} />
                <div>
                  <div style={{ fontSize: 13.5, fontWeight: 500 }}>{e.last_name}, {e.first_name}</div>
                  <div style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{e.function}</div>
                </div>
              </Row>
              <div className="num" style={{ textAlign: "right", fontSize: 13.5 }}>{LS_fmt.eurSigned(p.bruto)}</div>
              <div className="num" style={{ textAlign: "right", fontSize: 13.5, color: "var(--ink-2)" }}>{LS_fmt.eurSigned(p.loonheffing)}</div>
              <div className="num" style={{ textAlign: "right", fontSize: 13.5, color: "var(--ink-2)" }}>{LS_fmt.eurSigned(p.zvw)}</div>
              <div className="num" style={{ textAlign: "right", fontSize: 14, fontWeight: 600 }}>{LS_fmt.eurSigned(p.net)}</div>
            </button>
          ))}
          {/* Totals row */}
          <div style={{
            display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr",
            padding: "14px 18px",
            borderTop: "2px solid var(--ink)",
            background: "var(--bg-2)",
            alignItems: "center",
          }}>
            <div style={{ fontWeight: 600, fontSize: 13.5 }}>Totaal — {rows.length} medewerkers</div>
            <div className="num" style={{ textAlign: "right", fontWeight: 600 }}>{LS_fmt.eurSigned(totals.bruto)}</div>
            <div className="num" style={{ textAlign: "right", fontWeight: 600 }}>{LS_fmt.eurSigned(totals.heffing)}</div>
            <div className="num" style={{ textAlign: "right", fontWeight: 600 }}>{LS_fmt.eurSigned(totals.zvw)}</div>
            <div className="num" style={{ textAlign: "right", fontWeight: 700, fontSize: 15 }}>{LS_fmt.eurSigned(totals.net)}</div>
          </div>
        </Card>

        {/* Afdrachten */}
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginTop: 18 }}>
          <Card>
            <div style={{ fontSize: 11.5, textTransform: "uppercase", letterSpacing: 0.7, color: "var(--ink-3)", fontWeight: 600 }}>Afdrachten Belastingdienst</div>
            <div style={{ marginTop: 14, display: "flex", flexDirection: "column", gap: 10 }}>
              <Row style={{ justifyContent: "space-between" }}>
                <span style={{ fontSize: 13, color: "var(--ink-2)" }}>Loonheffing</span>
                <span className="num" style={{ fontSize: 13.5 }}>{LS_fmt.eurSigned(Math.abs(totals.heffing))}</span>
              </Row>
              <Row style={{ justifyContent: "space-between" }}>
                <span style={{ fontSize: 13, color: "var(--ink-2)" }}>Bijdrage ZVW</span>
                <span className="num" style={{ fontSize: 13.5 }}>{LS_fmt.eurSigned(Math.abs(totals.zvw))}</span>
              </Row>
              <Divider />
              <Row style={{ justifyContent: "space-between" }}>
                <span style={{ fontSize: 13, fontWeight: 600 }}>Totaal af te dragen</span>
                <span className="num" style={{ fontSize: 14, fontWeight: 700 }}>{LS_fmt.eurSigned(Math.abs(totals.heffing) + Math.abs(totals.zvw))}</span>
              </Row>
              <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 4 }}>Uiterste betaaldatum: <span className="num">31 mei 2026</span></div>
            </div>
          </Card>
          <Card>
            <div style={{ fontSize: 11.5, textTransform: "uppercase", letterSpacing: 0.7, color: "var(--ink-3)", fontWeight: 600 }}>Gegenereerde documenten</div>
            <div style={{ marginTop: 14, display: "flex", flexDirection: "column", gap: 10 }}>
              {[
                { n: `${rows.length} loonstroken`, sub: "→ per e-mail naar medewerker" },
                { n: "Loonaangifte april 2026", sub: "blijft in portal voor indiening" },
                { n: "Loonjournaalpost", sub: `→ ${LS_employer?.admin_email || "administratie"}` },
              ].map(d => (
                <Row key={d.n} style={{ gap: 10 }}>
                  <Icon name="pdf" size={18} style={{ color: "var(--accent)" }} />
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 13, fontWeight: 500 }}>{d.n}</div>
                    <div style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{d.sub}</div>
                  </div>
                </Row>
              ))}
            </div>
          </Card>
        </div>

        <Row style={{ marginTop: 24, justifyContent: "space-between" }}>
          <Btn variant="secondary" icon="chevronl" onClick={onBack}>Annuleren</Btn>
          <Row style={{ gap: 10 }}>
            <Btn variant="secondary" icon="edit" onClick={() => toast("Mutaties openen (demo)")}>Mutatie</Btn>
            <Btn variant="primary" iconRight="chevronr" onClick={onNext}>Doorgaan naar bevestigen</Btn>
          </Row>
        </Row>
      </div>

      {/* Strook preview side */}
      <div style={{ padding: "28px 28px", background: "var(--bg-2)" }}>
        <div style={{ fontSize: 11.5, textTransform: "uppercase", letterSpacing: 0.7, color: "var(--ink-3)", fontWeight: 600, marginBottom: 10 }}>Strook-preview</div>
        <PayslipMini emp={selRow.e} p={selRow.p} />
      </div>
    </div>
  );
};

const ConfirmStep = ({ rows, totals, onBack, onConfirm, toast }) => {
  const [checked, setChecked] = React.useState(false);
  return (
    <div style={{ maxWidth: 640, margin: "60px auto", padding: "0 24px" }}>
      <h2 style={{ fontSize: 26 }}>Bevestigen en verzenden</h2>
      <div style={{ color: "var(--ink-2)", marginTop: 6, fontSize: 14 }}>
        Na bevestigen worden alle stroken automatisch gemaild naar medewerkers en wordt de journaalpost naar administratie verstuurd. Dit kan niet ongedaan worden.
      </div>

      <Card style={{ marginTop: 22, padding: 0 }}>
        {[
          { label: "Periode", value: "April 2026 · maandloon" },
          { label: "Aantal stroken", value: `${rows.length}` },
          { label: "Naar medewerkers", value: `${rows.length} × e-mail (strook-PDF)` },
          { label: "Naar administratie", value: LS_employer?.admin_email || "—" },
          { label: "Totaal netto", value: <span className="num">{LS_fmt.eurSigned(totals.net)}</span> },
          { label: "Af te dragen BD", value: <span className="num">{LS_fmt.eurSigned(Math.abs(totals.heffing) + Math.abs(totals.zvw))}</span> },
          { label: "Rekenregels", value: <>v2026.1 · <span style={{ color: "var(--ink-3)" }}>geldig vanaf 15 jan 2026</span></> },
        ].map((r, i) => (
          <Row key={r.label} style={{ justifyContent: "space-between", padding: "14px 18px", borderTop: i === 0 ? "none" : "1px solid var(--line)" }}>
            <span style={{ fontSize: 13, color: "var(--ink-2)" }}>{r.label}</span>
            <span style={{ fontSize: 13.5, fontWeight: 500 }}>{r.value}</span>
          </Row>
        ))}
      </Card>

      <label style={{
        marginTop: 18, display: "flex", gap: 12,
        padding: 16, background: "var(--warn-2)",
        border: "1px solid oklch(85% 0.08 80)", borderRadius: 10,
        cursor: "pointer",
      }}>
        <input type="checkbox" checked={checked} onChange={e => setChecked(e.target.checked)} style={{ marginTop: 2, accentColor: "var(--ink)" }} />
        <div style={{ fontSize: 13, color: "oklch(32% 0.05 75)" }}>
          Ik bevestig dat ik de bedragen heb gecontroleerd en dat alle mutaties juist zijn verwerkt. Loonstroken worden direct naar medewerkers verstuurd.
        </div>
      </label>

      <Row style={{ marginTop: 24, justifyContent: "space-between" }}>
        <Btn variant="secondary" icon="chevronl" onClick={onBack}>Terug</Btn>
        <Btn variant="accent" size="lg" icon="send" disabled={!checked} onClick={onConfirm}>Bevestigen en verzenden</Btn>
      </Row>
    </div>
  );
};

const DoneStep = ({ rows, totals }) => (
  <div style={{ maxWidth: 520, margin: "100px auto", textAlign: "center", padding: "0 24px" }}>
    <div style={{ width: 72, height: 72, borderRadius: 999, background: "var(--accent-2)", color: "var(--accent)", margin: "0 auto 24px", display: "flex", alignItems: "center", justifyContent: "center" }}>
      <Icon name="check" size={36} stroke={2} />
    </div>
    <h2 style={{ fontSize: 28 }}>Loonrun april verzonden</h2>
    <div style={{ color: "var(--ink-2)", marginTop: 8, fontSize: 14 }}>
      {rows.length} loonstroken zijn gemaild. De journaalpost is naar administratie gestuurd. De aangifte vind je in Documenten.
    </div>
    <Card style={{ marginTop: 28, textAlign: "left" }}>
      <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
        {[
          { icon: "mail", n: `${rows.length} stroken → medewerkers`, sub: "zojuist verzonden" },
          { icon: "mail", n: `Journaalpost → ${LS_employer?.admin_email || "administratie"}`, sub: "zojuist verzonden" },
          { icon: "building", n: "Loonaangifte april 2026", sub: <>staat klaar in Documenten · indienen vóór <span className="num">31 mei</span></> },
        ].map(i => (
          <Row key={i.n} style={{ gap: 12 }}>
            <div style={{ width: 32, height: 32, borderRadius: 7, background: "var(--bg-3)", display: "flex", alignItems: "center", justifyContent: "center" }}><Icon name={i.icon} size={15} /></div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 13.5, fontWeight: 500 }}>{i.n}</div>
              <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{i.sub}</div>
            </div>
          </Row>
        ))}
      </div>
    </Card>
  </div>
);

// Mini payslip card used in preview
const PayslipMini = ({ emp, p }) => (
  <div style={{
    background: "#fff",
    border: "1px solid var(--line)",
    borderRadius: 10,
    overflow: "hidden",
    boxShadow: "0 8px 24px -18px oklch(20% 0.01 85 / 0.3)",
  }}>
    <div style={{ padding: "18px 20px", borderBottom: "1px solid var(--line)" }}>
      <Row style={{ justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <div style={{ fontSize: 11.5, textTransform: "uppercase", letterSpacing: 0.8, color: "var(--ink-3)" }}>Loonstrook</div>
          <div style={{ fontSize: 16, fontWeight: 600, marginTop: 2 }}>April 2026 · Periode 4</div>
        </div>
        <Pill tone="neutral">Ehold B.V.</Pill>
      </Row>
      <div style={{ marginTop: 14, fontSize: 13 }}>
        <div style={{ fontWeight: 500 }}>{emp.first_name} {emp.last_name}</div>
        <div style={{ color: "var(--ink-3)", fontSize: 12 }}>{emp.function} · #{emp.number} · {emp.lh_table} {emp.heffingskorting ? "· HK" : ""}</div>
      </div>
    </div>

    <div style={{ padding: "18px 20px", display: "flex", flexDirection: "column", gap: 8 }}>
      {[
        { l: "Basissalaris", v: emp.base_salary, sub: `${emp.hours.toLocaleString("nl-NL", { minimumFractionDigits: 2 })} uur · ${emp.parttime}%` },
        { l: "Bruto", v: p.bruto, bold: true, rule: true },
        { l: "Loonheffing", v: p.loonheffing, sub: `BT ${LS_fmt.pct(emp.bt_pct)}` },
        { l: "Bijdrage ZVW", v: p.zvw, sub: LS_fmt.pct(p.zvw_pct) },
      ].map((r, i) => (
        <Row key={i} style={{ justifyContent: "space-between", borderTop: r.rule ? "1px solid var(--line)" : "none", paddingTop: r.rule ? 10 : 0 }}>
          <div>
            <div style={{ fontSize: 13, fontWeight: r.bold ? 600 : 400 }}>{r.l}</div>
            {r.sub && <div style={{ fontSize: 11, color: "var(--ink-3)" }}>{r.sub}</div>}
          </div>
          <span className="num" style={{ fontSize: 13.5, fontWeight: r.bold ? 600 : 500 }}>{LS_fmt.eurSigned(r.v)}</span>
        </Row>
      ))}
    </div>

    <div style={{ padding: "16px 20px", borderTop: "2px solid var(--ink)", background: "var(--bg-2)" }}>
      <Row style={{ justifyContent: "space-between" }}>
        <div>
          <div style={{ fontSize: 12, color: "var(--ink-3)" }}>Uit te betalen naar</div>
          <div className="num" style={{ fontSize: 12, color: "var(--ink-2)" }}>{emp.iban}</div>
        </div>
        <div style={{ textAlign: "right" }}>
          <div style={{ fontSize: 11, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: 0.6 }}>Netto</div>
          <div className="num" style={{ fontSize: 22, fontWeight: 600, letterSpacing: "-0.01em" }}>{LS_fmt.eurSigned(p.net)}</div>
        </div>
      </Row>
    </div>

    <div style={{ padding: "10px 20px", borderTop: "1px solid var(--line)", background: "var(--bg-2)", fontSize: 11, color: "var(--ink-3)", display: "flex", justifyContent: "space-between" }}>
      <span>Arbeidskorting: <span className="num">{LS_fmt.eurSigned(p.arbeidskorting)}</span> (YTD)</span>
      <span>Regels v2026.1</span>
    </div>
  </div>
);

Object.assign(window, { LoonrunFlow, PayslipMini });
