const { useState, useMemo, useEffect } = React;

// ------- formatting helpers -------
const fmtEUR = (n, opts = {}) => {
  if (n == null || isNaN(n)) return '—';
  const { decimals = 0, sign = false } = opts;
  const s = Math.abs(n).toLocaleString('de-DE', { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
  return (n < 0 ? '−' : (sign && n > 0 ? '+' : '')) + s;
};
const fmtBig = (n) => fmtEUR(n, { decimals: 0 });
const fmtCents = (n) => fmtEUR(n, { decimals: 2 });
const monthNames = ['Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'];
const monthFull = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'];

const slips = window.SLIPS;

// ------- aggregations -------
function totalTax(s) {
  return (s.lohnsteuer || 0) + (s.soli || 0) + (s.kirchensteuer || 0) +
         (s.lstEZActual || 0) + (s.soliEZActual || 0);
}
// Effective gesetzliche SV implied by brutto - netto - tax (always reconciles to brutto)
function totalSv(s) {
  const t = (s.gesamtbrutto || 0) - (s.netto || 0) - totalTax(s);
  return t > 0 ? t : 0;
}
// Explicit freiwillig KV/PV (paid out of netto, partially refunded by AG-Zuschuss)
function freiwilligNet(s) {
  const out = (s.kvFreiw || 0) + (s.pvFreiw || 0);
  const z = (s.kvZuschuss || 0) + (s.kvZusatzZuschuss || 0) + (s.pvZuschuss || 0);
  return Math.max(0, out - z);
}

const byYear = {};
for (const s of slips) {
  if (!byYear[s.year]) byYear[s.year] = [];
  byYear[s.year].push(s);
}
const years = Object.keys(byYear).map(Number).sort();

// Compute actual per-month bonus and EZ tax from cumulative YTD fields.
for (const y of years) {
  const list = byYear[y].slice().sort((a, b) => a.month - b.month);
  let prevBonus = 0, prevLst = 0, prevSoli = 0;
  for (const s of list) {
    const ytd = s.bonusEZ || 0;
    const delta = ytd - prevBonus;
    s.bonusActual = delta > 0.5 ? delta : 0;
    if (ytd !== 0) prevBonus = ytd;

    // EZ tax actuals: only for new-employer slips (IBM lohnsteuer already bundles EZ)
    if (s.kind === 'new') {
      const lstYTD = s.lohnsteuerEZ || 0;
      const soliYTD = s.soliEZ || 0;
      s.lstEZActual = (lstYTD - prevLst) > 0.5 ? (lstYTD - prevLst) : 0;
      s.soliEZActual = (soliYTD - prevSoli) > 0.5 ? (soliYTD - prevSoli) : 0;
      if (lstYTD !== 0) prevLst = lstYTD;
      if (soliYTD !== 0) prevSoli = soliYTD;
    } else {
      s.lstEZActual = 0;
      s.soliEZActual = 0;
    }
  }
}

function yearStats(year) {
  const list = byYear[year] || [];
  let brutto = 0, netto = 0, tax = 0, sv = 0, auszahlung = 0, bonus = 0, freiw = 0;
  for (const s of list) {
    brutto += s.gesamtbrutto || 0;
    netto += s.netto || 0;
    tax += totalTax(s);
    sv += totalSv(s);
    auszahlung += s.auszahlung || 0;
    bonus += s.bonusActual || 0;
    freiw += freiwilligNet(s);
  }
  return { year, count: list.length, brutto, netto, tax, sv, auszahlung, bonus, freiw, list };
}

const lifetime = (() => {
  let brutto = 0, netto = 0, tax = 0, sv = 0, auszahlung = 0, bonus = 0;
  for (const s of slips) {
    brutto += s.gesamtbrutto || 0;
    netto += s.netto || 0;
    tax += totalTax(s);
    sv += totalSv(s);
    auszahlung += s.auszahlung || 0;
    bonus += s.bonusActual || 0;
  }
  return { brutto, netto, tax, sv, auszahlung, bonus, count: slips.length };
})();

// ------- components -------
function Stat({ label, value, unit = 'EUR', note }) {
  return (
    <div className="stat">
      <div className="stat-label">{label}</div>
      <div className="stat-value"><span className="num">{value}</span></div>
      <div className="stat-note">{note || unit}</div>
    </div>
  );
}

function YearTab({ y, active, onClick }) {
  const stats = yearStats(y);
  return (
    <button className={'year-tab' + (active ? ' active' : '')} onClick={onClick}>
      <span className="yt-num">{y}</span>
      <span className="yt-amt">{fmtBig(stats.auszahlung)} €</span>
      <span style={{ fontSize: 10, color: 'var(--ink-3)' }}>{stats.count} Mon.</span>
    </button>
  );
}

function MonthBar({ slip, max, onClick }) {
  const brutto = slip.gesamtbrutto || 0;
  const tax = totalTax(slip);
  const sv = totalSv(slip);
  const netto = slip.netto || 0;
  const auszahlung = slip.auszahlung || 0;
  const freiwGap = Math.max(0, netto - auszahlung);
  const h = (v) => (v / max) * 100;
  const isBonus = (slip.bonusActual || 0) > 1000;
  const retro = slip.retroBrutto || [];
  const retroSum = retro.reduce((a, r) => a + r.value, 0);
  return (
    <div className="bar-col" onClick={() => onClick(slip)}>
      <div className="bar-tooltip">
        {monthFull[slip.month - 1]} · {slip.year}{slip._mergedLabel && <> · <em>{slip._mergedLabel}</em></>}<br />
        Brutto <span className="num">{fmtBig(brutto)} €</span><br />
        Netto <span className="num">{fmtBig(netto)} €</span><br />
        Auszahlung <span className="num">{fmtBig(auszahlung)} €</span>
        {isBonus && <><br />+ Einmalzahlung <span className="num">{fmtBig(slip.bonusActual)} €</span></>}
        {retro.length > 0 && <><br />+ Nachzahlung ({retro.length} Mo.) <span className="num">{fmtBig(retroSum)} €</span></>}
      </div>
      <div className="bar-stack">
        {retro.length > 0 && <div className="bar-retro-dot" title={`${retro.length} Monat(e) rückwirkend`}></div>}
        <div className="bar-seg tax" style={{ height: h(tax) + '%' }}></div>
        <div className="bar-seg sv" style={{ height: h(sv) + '%' }}></div>
        {freiwGap > 0 && <div className="bar-seg freiw-gap" style={{ height: h(freiwGap) + '%' }}></div>}
        <div className="bar-seg netto" style={{ height: h(auszahlung) + '%' }}></div>
      </div>
      <div className="bar-lbl">{monthNames[slip.month - 1]}</div>
    </div>
  );
}

function MonthTable({ list, onRowClick }) {
  // Sort by month
  const sorted = [...list].sort((a, b) => a.month - b.month);
  return (
    <table className="mtable">
      <thead>
        <tr>
          <th>Monat</th>
          <th className="r">Brutto</th>
          <th className="r">Lohnsteuer</th>
          <th className="r">Soli</th>
          <th className="r">SV gesamt</th>
          <th className="r">Netto</th>
          <th className="r">Auszahlung</th>
        </tr>
      </thead>
      <tbody>
        {sorted.map(s => {
          const isBonus = (s.bonusActual || 0) > 1000;
          return (
            <tr key={s.path} onClick={() => onRowClick(s)}>
              <td className="month-cell">
                {monthFull[s.month - 1]}
                {isBonus && <span className="badge">Einmalz.</span>}
              </td>
              <td className="r">{fmtCents(s.gesamtbrutto)}</td>
              <td className="r">{fmtCents(s.lohnsteuer)}</td>
              <td className="r">{fmtCents(s.soli)}</td>
              <td className="r">{fmtCents(totalSv(s))}</td>
              <td className="r netto-val">{fmtCents(s.netto)}</td>
              <td className="r">{fmtCents(s.auszahlung)}</td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

function YearSummary({ year }) {
  const s = yearStats(year);
  const isPartial = s.count < 12;
  return (
    <div className="yd-summary">
      <div style={{ fontSize: 12, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 16 }}>
        Jahresbilanz {year}
      </div>
      <div className="yd-row">
        <span className="label">Bruttoentgelt</span>
        <span className="val">{fmtCents(s.brutto)} €</span>
      </div>
      {s.bonus > 0 && (
        <div className="yd-row" style={{ paddingLeft: 12, color: 'var(--ink-3)' }}>
          <span className="label">davon Einmalzahlungen</span>
          <span className="val">{fmtCents(s.bonus)} €</span>
        </div>
      )}
      <div className="yd-row tax">
        <span className="label">Lohnsteuer + Soli</span>
        <span className="val">−{fmtCents(s.tax)} €</span>
      </div>
      <div className="yd-row tax">
        <span className="label">Sozialvers. (gesetzlich)</span>
        <span className="val">−{fmtCents(s.sv)} €</span>
      </div>
      <div className="yd-row netto total">
        <span className="label">Netto</span>
        <span className="val">{fmtCents(s.netto)} €</span>
      </div>
      {s.freiw > 0 && (
        <div className="yd-row tax" style={{ paddingLeft: 12, fontSize: 13 }}>
          <span className="label">freiw. KV/PV + BVV (Eigenanteil)</span>
          <span className="val">−{fmtCents(s.freiw + (s.list || []).reduce((a, r) => a + (r.bvvANAnteil || 0), 0))} €</span>
        </div>
      )}
      <div className="yd-row netto total" style={{ marginTop: 0 }}>
        <span className="label">Auszahlung</span>
        <span className="val">{fmtCents(s.auszahlung)} €</span>
      </div>
      <div style={{ marginTop: 20, fontSize: 12, color: 'var(--ink-3)', lineHeight: 1.6 }}>
        <div>Abrechnungen: <span className="num">{s.count}</span> {isPartial && <em className="serif-i">· unvollständig</em>}</div>
        <div>Steuerquote: <span className="num">{((s.tax / s.brutto) * 100).toFixed(1)} %</span></div>
        <div>Auszahlung / Brutto: <span className="num">{((s.auszahlung / s.brutto) * 100).toFixed(1)} %</span></div>
        <div>Ø monatliche Auszahlung: <span className="num">{fmtBig(s.auszahlung / s.count)} €</span></div>
      </div>
    </div>
  );
}

const SUM_FIELDS = ['gesamtbrutto','netto','auszahlung','lohnsteuer','soli','kirchensteuer',
  'kv','pv','rv','av','kvFreiw','pvFreiw','kvZuschuss','kvZusatzZuschuss','pvZuschuss',
  'bvvAGZuschuss','bvvANAnteil','vlZuschuss','lstEZActual','soliEZActual','bonusActual'];
function mergeGroup(group) {
  if (group.length === 1) return group[0];
  // Use the new-employer slip as base (last in sorted list); sum numeric fields
  const base = { ...group[group.length - 1] };
  for (const f of SUM_FIELDS) base[f] = group.reduce((s, r) => s + (r[f] || 0), 0);
  base._mergedLabel = group.map(s => s.employer).join(' + ');
  return base;
}

function MonthlyBars({ year, onClick }) {
  const list = (byYear[year] || []).slice().sort((a, b) => a.month - b.month);
  // Group by month, merge if two employers share a month (e.g. Apr 2023 transition)
  const byMonth = {};
  for (const s of list) { (byMonth[s.month] = byMonth[s.month] || []).push(s); }
  const merged = Object.values(byMonth).map(mergeGroup);
  const max = Math.max(...merged.map(s => s.gesamtbrutto || 0)) * 1.05;
  const padded = [];
  for (let m = 1; m <= 12; m++) {
    padded.push(merged.find(s => s.month === m) || null);
  }
  return (
    <div>
      <div className="bars">
        {padded.map((s, i) => s
          ? <MonthBar key={i} slip={s} max={max} onClick={onClick} />
          : <div key={i} className="bar-col" style={{ opacity: 0.3 }}>
              <div className="bar-stack"><div style={{ height: 4, background: 'var(--line)', alignSelf: 'flex-end', width: '100%' }} /></div>
              <div className="bar-lbl">{monthNames[i]}</div>
            </div>
        )}
      </div>
      <div className="bar-legend">
        <span className="lg-netto">Auszahlung</span>
        <span className="lg-freiw">Freiw. Abzüge</span>
        <span className="lg-sv">Sozialvers.</span>
        <span className="lg-tax">Steuer</span>
      </div>
    </div>
  );
}

function TrendChart() {
  // Merge same-month slips (e.g. Apr 2023 IBM+new employer) before plotting
  const byKey = {};
  for (const s of slips) {
    const k = s.year * 100 + s.month;
    (byKey[k] = byKey[k] || []).push(s);
  }
  const sorted = Object.keys(byKey).map(Number).sort((a, b) => a - b)
    .map(k => mergeGroup(byKey[k]));
  const W = 1100, H = 280, padL = 64, padR = 16, padT = 16, padB = 28;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  const maxY = Math.max(...sorted.map(s => s.gesamtbrutto || 0)) * 1.08;
  const x = (i) => padL + (i / (sorted.length - 1)) * innerW;
  const y = (v) => padT + innerH - (v / maxY) * innerH;

  const bruttoPath = sorted.map((s, i) => `${i === 0 ? 'M' : 'L'} ${x(i).toFixed(1)} ${y(s.gesamtbrutto || 0).toFixed(1)}`).join(' ');
  const auszahlungPath = sorted.map((s, i) => `${i === 0 ? 'M' : 'L'} ${x(i).toFixed(1)} ${y(s.auszahlung || 0).toFixed(1)}`).join(' ');
  const bruttoArea = bruttoPath + ` L ${x(sorted.length - 1).toFixed(1)} ${y(0).toFixed(1)} L ${x(0).toFixed(1)} ${y(0).toFixed(1)} Z`;

  // Year boundaries
  const yearBounds = [];
  for (let i = 1; i < sorted.length; i++) {
    if (sorted[i].year !== sorted[i - 1].year) {
      yearBounds.push({ x: x(i - 0.5), year: sorted[i].year });
    }
  }
  
  // Y axis labels
  const yTicks = [];
  const step = maxY > 10000 ? 5000 : 2000;
  for (let v = 0; v <= maxY; v += step) {
    yTicks.push(v);
  }
  
  return (
    <div className="trend-chart">
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
        {/* Y gridlines */}
        {yTicks.map(v => (
          <g key={v}>
            <line x1={padL} y1={y(v)} x2={W - padR} y2={y(v)} stroke="var(--line-soft)" strokeWidth="1" />
            <text x={padL - 10} y={y(v) + 4} fontSize="11" fill="var(--ink-3)" textAnchor="end" fontFamily="Geist Mono, monospace">
              {(v / 1000).toFixed(0)}k
            </text>
          </g>
        ))}
        {/* Year boundary lines */}
        {yearBounds.map(b => (
          <g key={b.year}>
            <line x1={b.x} y1={padT} x2={b.x} y2={H - padB} stroke="var(--line)" strokeWidth="1" strokeDasharray="2,3" />
            <text x={b.x + 4} y={padT + 14} fontSize="11" fill="var(--ink-3)" fontFamily="Geist Mono, monospace">{b.year}</text>
          </g>
        ))}
        {/* First year label */}
        <text x={padL + 4} y={padT + 14} fontSize="11" fill="var(--ink-3)" fontFamily="Geist Mono, monospace">{sorted[0].year}</text>
        
        {/* Brutto area */}
        <path d={bruttoArea} fill="var(--moss)" opacity="0.08" />
        {/* Brutto line */}
        <path d={bruttoPath} fill="none" stroke="var(--ink-bar)" strokeWidth="1.5" />
        {/* Auszahlung line */}
        <path d={auszahlungPath} fill="none" stroke="var(--moss)" strokeWidth="2" />
        
        {/* Bonus markers (large actual EZ in this month) */}
        {sorted.map((s, i) => {
          if ((s.bonusActual || 0) > 1000) {
            return <circle key={i} cx={x(i)} cy={y(s.gesamtbrutto)} r="3.5" fill="var(--rust)" stroke="var(--bg)" strokeWidth="1.5" />;
          }
          return null;
        })}
      </svg>
      <div style={{ display: 'flex', gap: 18, marginTop: 12, fontSize: 12, color: 'var(--ink-3)' }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <span style={{ display: 'inline-block', width: 14, height: 2, background: 'var(--ink-bar)' }}></span>
          Brutto
        </span>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <span style={{ display: 'inline-block', width: 14, height: 2, background: 'var(--moss)' }}></span>
          Auszahlung
        </span>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
          <span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: '50%', background: 'var(--rust)' }}></span>
          Bonus / Einmalzahlung
        </span>
      </div>
    </div>
  );
}

function DetailModal({ slip, onClose }) {
  if (!slip) return null;
  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);
  const isNew = slip.kind === 'new';
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <div className="modal-title">{monthFull[slip.month - 1]} {slip.year}</div>
            <div className="modal-sub">
              {slip.employer} · Steuerklasse {slip.steuerklasse || '—'}
              {slip.karriereleiter && ` · ${slip.karriereleiter} ${slip.karrierestufe}`}
            </div>
          </div>
          <button className="modal-close" onClick={onClose}>×</button>
        </div>
        <div className="modal-body">

          {/* ── 1. Basisbezüge ── */}
          <div className="modal-section">
            <h4>Basisbezüge</h4>
            <div className="yd-row"><span className="label">{isNew ? 'Grundvergütung' : 'Grundgehalt'}</span><span className="val num">{fmtCents(slip.grundgehalt)} €</span></div>
            {slip.privVorsorge > 0 && <div className="yd-row"><span className="label">priv. Altersvorsorge (VZ)</span><span className="val num">{fmtCents(slip.privVorsorge)} €</span></div>}
            {slip.vlZuschuss > 0 && <div className="yd-row"><span className="label">Arbeitgeberleistung VL</span><span className="val num">{fmtCents(slip.vlZuschuss)} €</span></div>}
            {(slip.bonusActual || 0) > 0.5 && <div className="yd-row"><span className="label">Einmalzahlung</span><span className="val num">{fmtCents(slip.bonusActual)} €</span></div>}
            {slip.retroBrutto && slip.retroBrutto.length > 0 && (
              <div style={{ marginTop: 8, padding: '10px 12px', background: 'var(--bg)', border: '1px dashed var(--line)', borderRadius: 4 }}>
                <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Rückwirkende Nachzahlungen</div>
                {slip.retroBrutto.map((r, i) => (
                  <div key={i} className="yd-row" style={{ fontSize: 12, color: 'var(--ink-2)', borderBottom: 'none', padding: '2px 0' }}>
                    <span className="label">{monthFull[r.mm - 1]} 20{String(r.yy).padStart(2,'0')}</span>
                    <span className="val num">+{fmtCents(r.value)} €</span>
                  </div>
                ))}
                <div className="yd-row" style={{ fontSize: 11, color: 'var(--ink-3)', borderBottom: 'none', padding: '4px 0 0' }}>
                  <span className="label serif-i">Summe rückwirkend</span>
                  <span className="val num">+{fmtCents(slip.retroBrutto.reduce((a, r) => a + r.value, 0))} €</span>
                </div>
              </div>
            )}
          </div>

          {/* ── 2. BVV (nur neuer AG) ── */}
          {isNew && slip.bvvAGZuschuss > 0 && (
            <div className="modal-section">
              <h4>BVV</h4>
              <div className="yd-row"><span className="label">BVV-AG Anteil UK stfr</span><span className="val num" style={{ color: 'var(--moss)' }}>{fmtCents(slip.bvvAGZuschuss)} €</span></div>
              <div className="yd-row"><span className="label">BVV-AN Anteil UK stfr</span><span className="val num">{fmtCents(slip.bvvANAnteil)} €</span></div>
              <div className="yd-row total"><span className="label">BVV Summe Grundversorgung</span><span className="val num">{fmtCents((slip.bvvAGZuschuss || 0) + (slip.bvvANAnteil || 0))} €</span></div>
            </div>
          )}

          {/* ── 3. Bruttoentgelt ── */}
          <div className="modal-section">
            <div className="yd-row total"><span className="label">Gesamtbrutto</span><span className="val num">{fmtCents(slip.gesamtbrutto)} €</span></div>
          </div>

          {/* ── 4. Gesetzliche Abzüge ── */}
          <div className="modal-section">
            <h4>Gesetzliche Abzüge</h4>
            {(slip.lstEZActual || 0) > 0.5 && <div className="yd-row tax"><span className="label">Lohnsteuer, EZ</span><span className="val num">−{fmtCents(slip.lstEZActual)} €</span></div>}
            <div className="yd-row tax"><span className="label">Lohnsteuer, lfd.</span><span className="val num">−{fmtCents(slip.lohnsteuer)} €</span></div>
            {(slip.soliEZActual || 0) > 0.5 && <div className="yd-row tax"><span className="label">Solidaritätszuschlag, EZ</span><span className="val num">−{fmtCents(slip.soliEZActual)} €</span></div>}
            <div className="yd-row tax"><span className="label">Solidaritätszuschlag, lfd.</span><span className="val num">−{fmtCents(slip.soli)} €</span></div>
            {slip.kirchensteuer > 0 && <div className="yd-row tax"><span className="label">Kirchensteuer</span><span className="val num">−{fmtCents(slip.kirchensteuer)} €</span></div>}
            {slip.kv > 0 && <div className="yd-row tax"><span className="label">Krankenversicherung, lfd.</span><span className="val num">−{fmtCents(slip.kv)} €</span></div>}
            {slip.pv > 0 && <div className="yd-row tax"><span className="label">Pflegeversicherung, lfd.</span><span className="val num">−{fmtCents(slip.pv)} €</span></div>}
            <div className="yd-row tax"><span className="label">Rentenversicherung, lfd.</span><span className="val num">−{fmtCents(slip.rv)} €</span></div>
            <div className="yd-row tax"><span className="label">Arbeitslosenversicherung, lfd.</span><span className="val num">−{fmtCents(slip.av)} €</span></div>
          </div>

          {/* ── 5. Netto ── */}
          <div className="modal-section">
            <div className="yd-row netto total"><span className="label">{isNew ? 'Gesetzl. Netto (EBeschV)' : 'Nettoentgelt'}</span><span className="val num">{fmtCents(slip.netto)} €</span></div>
          </div>

          {/* ── 6. Be- und Abzüge ── */}
          {(slip.pvZuschuss || slip.vlZuschuss || slip.bvvANAnteil || slip.kvFreiw || slip.kvZuschuss || slip.kvZusatzZuschuss || slip.pvFreiw) && (
            <div className="modal-section">
              <h4>Be- und Abzüge</h4>
              {slip.pvZuschuss > 0 && <div className="yd-row"><span className="label">AG-Zuschuss PV</span><span className="val num" style={{ color: 'var(--moss)' }}>+{fmtCents(slip.pvZuschuss)} €</span></div>}
              {slip.vlZuschuss > 0 && <div className="yd-row tax"><span className="label">VB Kapitalsparen (Entgeltumwandlung)</span><span className="val num">−{fmtCents(slip.vlZuschuss)} €</span></div>}
              {slip.bvvANAnteil > 0 && <div className="yd-row tax"><span className="label">BVV-AN Anteil (Entgeltumwandlung)</span><span className="val num">−{fmtCents(slip.bvvANAnteil)} €</span></div>}
              {slip.kvFreiw > 0 && <div className="yd-row tax"><span className="label">Abgef. Beitrag freiw. KV</span><span className="val num">−{fmtCents(slip.kvFreiw)} €</span></div>}
              {slip.kvZuschuss > 0 && <div className="yd-row"><span className="label">AG-Zuschuss KV</span><span className="val num" style={{ color: 'var(--moss)' }}>+{fmtCents(slip.kvZuschuss)} €</span></div>}
              {slip.kvZusatzZuschuss > 0 && <div className="yd-row"><span className="label">KV-Zusatzbeitrag (AG)</span><span className="val num" style={{ color: 'var(--moss)' }}>+{fmtCents(slip.kvZusatzZuschuss)} €</span></div>}
              {slip.pvFreiw > 0 && <div className="yd-row tax"><span className="label">Abgef. Beitrag freiw. PV</span><span className="val num">−{fmtCents(slip.pvFreiw)} €</span></div>}
            </div>
          )}

          {/* ── 7. Zahlungen ── */}
          <div className="modal-section">
            <h4>Zahlungen</h4>
            <div className="yd-row netto"><span className="label">Überweisung</span><span className="val num">{fmtCents(slip.auszahlung - (slip.vlZuschuss || 0))} €</span></div>
            {slip.vlZuschuss > 0 && <div className="yd-row netto"><span className="label">VB Überweisung</span><span className="val num">{fmtCents(slip.vlZuschuss)} €</span></div>}
            {slip.vlZuschuss > 0 && <div className="yd-row netto total" style={{ marginTop: 0 }}><span className="label">Auszahlung gesamt</span><span className="val num">{fmtCents(slip.auszahlung)} €</span></div>}
          </div>

          <div style={{ marginTop: 24, paddingTop: 16, borderTop: '1px solid var(--line-soft)', fontSize: 11, color: 'var(--ink-3)' }}>
            Quelle: <span className="num">{slip.path.split('/').slice(-2).join('/')}</span>
          </div>
        </div>
      </div>
    </div>
  );
}

// ------- main app -------
function App() {
  const [selectedYear, setSelectedYear] = useState(years[years.length - 1]);
  const [modalSlip, setModalSlip] = useState(null);

  const firstSlip = slips[0];
  const lastSlip = slips[slips.length - 1];

  return (
    <div className="page" data-screen-label="Dashboard">
      <header className="topbar">
        <div className="brand">
          <span className="brand-mark"></span>
          <div>
            <div className="brand-title">Abrechnungen</div>
            <div className="brand-sub" style={{ marginTop: 4 }}>Verdienstübersicht · Salvatore Cancelliere</div>
          </div>
        </div>
        <div className="topbar-meta">
          {monthNames[firstSlip.month - 1]} {firstSlip.year} — {monthNames[lastSlip.month - 1]} {lastSlip.year}
        </div>
      </header>

      <section className="hero">
        <div className="hero-eyebrow">{lifetime.count} Abrechnungen · 2 Arbeitgeber · 9 Jahre</div>
        <h1 className="hero-title">
          <em>{fmtBig(lifetime.brutto)} €</em> verdient,<br />
          {fmtBig(lifetime.auszahlung)} € ausgezahlt.
        </h1>
        <p className="hero-desc">
          Eine vollständige Übersicht aller hochgeladenen Gehaltsabrechnungen — von der ersten Anstellung bei <span className="emp-chip">IBM D GmbH</span> im September 2018 bis zur aktuellen Position als <span className="emp-chip cur">PM 03 · GS-DT Digital Architecture</span>. Klicke einen Monat an, um die vollständige Aufschlüsselung zu sehen.
        </p>

        <div className="stats">
          <Stat label="Brutto gesamt" value={fmtBig(lifetime.brutto) + ' €'} note={`über ${lifetime.count} Abrechnungen`} />
          <Stat label="Auszahlung gesamt" value={fmtBig(lifetime.auszahlung) + ' €'} note={((lifetime.auszahlung / lifetime.brutto) * 100).toFixed(1) + ' % vom Brutto'} />
          <Stat label="Steuern" value={fmtBig(lifetime.tax) + ' €'} note={((lifetime.tax / lifetime.brutto) * 100).toFixed(1) + ' % Steuerquote'} />
          <Stat label="Sozialvers." value={fmtBig(lifetime.sv) + ' €'} note={((lifetime.sv / lifetime.brutto) * 100).toFixed(1) + ' % vom Brutto'} />
        </div>
      </section>

      <section className="sec">
        <div className="sec-head">
          <h2 className="sec-title">Verlauf <span className="serif-i" style={{ color: 'var(--ink-3)' }}>Brutto vs. Auszahlung</span></h2>
          <div className="sec-sub">Jede Linie = monatlicher Wert · gepunktete Marker = Einmalzahlung</div>
        </div>
        <TrendChart />
      </section>

      <section className="sec">
        <div className="sec-head">
          <h2 className="sec-title">Jahre</h2>
          <div className="sec-sub">Tab anklicken für Detailansicht</div>
        </div>
        <div className="years">
          {years.map(y => (
            <YearTab key={y} y={y} active={y === selectedYear} onClick={() => setSelectedYear(y)} />
          ))}
        </div>

        <div className="yd-grid">
          <YearSummary year={selectedYear} />
          <div>
            <MonthlyBars year={selectedYear} onClick={setModalSlip} />
            <MonthTable list={byYear[selectedYear] || []} onRowClick={setModalSlip} />
          </div>
        </div>
      </section>

      <section className="sec">
        <div className="sec-head">
          <h2 className="sec-title">Vergleich <span className="serif-i" style={{ color: 'var(--ink-3)' }}>Jahr für Jahr</span></h2>
          <div className="sec-sub">Bruttogehalt nach Jahr</div>
        </div>
        <YearComparison />
      </section>

      <footer className="footer">
        <span>Daten aus {lifetime.count} PDF-Abrechnungen extrahiert · {new Date().toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' })}</span>
        <span className="num">v1.0</span>
      </footer>

      <DetailModal slip={modalSlip} onClose={() => setModalSlip(null)} />
    </div>
  );
}

function YearComparison() {
  const data = years.map(y => yearStats(y));
  const max = Math.max(...data.map(d => d.brutto));
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginTop: 8 }}>
      {data.map(d => {
        const pct = (d.brutto / max) * 100;
        const isPartial = d.count < 12;
        return (
          <div key={d.year} style={{ display: 'grid', gridTemplateColumns: '60px 1fr 200px', alignItems: 'center', gap: 16 }}>
            <div style={{ fontFamily: 'Geist Mono, monospace', fontSize: 14, color: 'var(--ink-2)' }}>
              {d.year}
              {isPartial && <div style={{ fontSize: 10, color: 'var(--ink-3)' }}>({d.count} Mon.)</div>}
            </div>
            <div style={{ background: 'var(--bg-card)', borderRadius: 2, height: 32, position: 'relative', border: '1px solid var(--line-soft)' }}>
              <div style={{ position: 'absolute', inset: 0, width: pct + '%', background: 'var(--ink-bar)', borderRadius: 2, display: 'flex', alignItems: 'center', justifyContent: 'flex-end', paddingRight: 12 }}>
                <span style={{ fontFamily: 'Geist Mono, monospace', fontSize: 12, color: 'var(--bg)', fontWeight: 500 }}>
                  {pct > 25 ? fmtBig(d.brutto) + ' €' : ''}
                </span>
              </div>
              {pct <= 25 && (
                <span style={{ position: 'absolute', left: `calc(${pct}% + 10px)`, top: '50%', transform: 'translateY(-50%)', fontFamily: 'Geist Mono, monospace', fontSize: 12, color: 'var(--ink-2)' }}>
                  {fmtBig(d.brutto)} €
                </span>
              )}
            </div>
            <div style={{ fontFamily: 'Geist Mono, monospace', fontSize: 13, color: 'var(--moss)', textAlign: 'right' }}>
              Netto {fmtBig(d.netto)} €
            </div>
          </div>
        );
      })}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
