// Finanzen — refined private-banking feel
const { useState, useEffect } = React;

// Empty bar templates (kept so charts still render an axis when there's no data yet)
const EMPTY_WEEK_BARS = [
  { label: 'Mo', inc: 0, exp: 0 }, { label: 'Di', inc: 0, exp: 0 },
  { label: 'Mi', inc: 0, exp: 0 }, { label: 'Do', inc: 0, exp: 0 },
  { label: 'Fr', inc: 0, exp: 0 }, { label: 'Sa', inc: 0, exp: 0 },
  { label: 'So', inc: 0, exp: 0 },
];
const EMPTY_MONTH_BARS = [
  { label: 'W1', inc: 0, exp: 0 }, { label: 'W2', inc: 0, exp: 0 },
  { label: 'W3', inc: 0, exp: 0 }, { label: 'W4', inc: 0, exp: 0 },
];
const EMPTY_YEAR_BARS = [
  { label: 'Jan', inc: 0, exp: 0 }, { label: 'Feb', inc: 0, exp: 0 },
  { label: 'Mär', inc: 0, exp: 0 }, { label: 'Apr', inc: 0, exp: 0 },
  { label: 'Mai', inc: 0, exp: 0 }, { label: 'Jun', inc: 0, exp: 0 },
  { label: 'Jul', inc: 0, exp: 0 }, { label: 'Aug', inc: 0, exp: 0 },
  { label: 'Sep', inc: 0, exp: 0 }, { label: 'Okt', inc: 0, exp: 0 },
  { label: 'Nov', inc: 0, exp: 0 }, { label: 'Dez', inc: 0, exp: 0 },
];

// All historical month detail is now derived from the live `transactions` array
// via fin_buildMonthsRange / fin_txInMonth / fin_sumAgg (see finance-data.jsx).

function pctF(a, b) {if (!b) return null;const p = Math.round((a - b) / b * 100);return { val: Math.abs(p), up: p >= 0 };}

// System colors (matches calendar status bars, equipment utilization, etc.)
const palette = (t) => ({
  pos: t.green,
  posSft: t.greenSoft,
  posBar: t.green + (t.dark ? '85' : '6E'), // slightly more saturated but still soft
  neg: t.red,
  negSft: t.redSoft,
  negBar: t.red + (t.dark ? '85' : '6E'),
  ink: t.text,
  grid: t.dark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'
});

const NUMS = { fontVariantNumeric: 'tabular-nums', fontFeatureSettings: '"tnum"' };

// ─── Chart components ───────────────────────────────────────
function ChartBars({ bars, t, onPick, monthKeys }) {
  const p = palette(t);
  const rawMax = Math.max(...bars.map((b) => Math.max(b.inc, b.exp)), 1);
  // Round max up to a "nice" number so the axis ticks read cleanly
  const niceMax = (v) => {
    const pow = Math.pow(10, Math.floor(Math.log10(v)));
    const n = v / pow;
    const step = n <= 1 ? 1 : n <= 2 ? 2 : n <= 5 ? 5 : 10;
    return step * pow;
  };
  const max = niceMax(rawMax);
  const fmtAxis = (v) => v >= 1000 ? (v / 1000).toFixed(v % 1000 === 0 ? 0 : 1).replace('.', ',') + 'k' : String(v);
  const AXIS_W = 28;
  const H = 110;
  const [active, setActive] = React.useState(null); // hovered bar index
  const [pinned, setPinned] = React.useState(null); // tap-pinned bar (touch)

  // Pointer interaction: on touch we capture and scrub; on mouse we use per-bar enter/leave.
  const rowRef = React.useRef(null);
  const updateActiveFromEvent = (e) => {
    const el = rowRef.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const x = (e.clientX || (e.touches && e.touches[0] && e.touches[0].clientX) || 0) - rect.left;
    const idx = Math.floor(x / (rect.width / bars.length));
    if (idx >= 0 && idx < bars.length) setActive(idx);
  };

  return (
    <div style={{ position: 'relative', height: H + 22, paddingLeft: AXIS_W }}>
      {/* Y-axis labels */}
      <div style={{ position: 'absolute', left: 0, top: 0, width: AXIS_W - 6, height: H, pointerEvents: 'none' }}>
        {[0, 0.25, 0.5, 0.75, 1].map((g) =>
        <div key={g} style={{
          position: 'absolute', right: 0, top: H * (1 - g),
          transform: 'translateY(-50%)',
          fontSize: 9, color: t.textSec, fontWeight: 600,
          textAlign: 'right', lineHeight: 1, ...NUMS
        }}>{fmtAxis(Math.round(max * g))}{g === 1 ? ' €' : ''}</div>
        )}
      </div>
      {/* Gridlines */}
      {[0, 0.25, 0.5, 0.75, 1].map((g) =>
      <div key={g} style={{ position: 'absolute', left: AXIS_W, right: 0, top: H * (1 - g), borderTop: `0.5px ${g === 0 ? 'solid' : 'dashed'} ${p.grid}` }} />
      )}
      <div ref={rowRef}
        onPointerDown={(e) => { if (e.pointerType === 'touch') { updateActiveFromEvent(e); try { e.currentTarget.setPointerCapture(e.pointerId); } catch (_) {} } }}
        onPointerMove={(e) => { if (e.pointerType === 'touch' && (e.buttons || e.pressure)) updateActiveFromEvent(e); }}
        onPointerUp={(e) => { if (e.pointerType === 'touch') { updateActiveFromEvent(e); setPinned(active); setTimeout(() => { setActive(null); setPinned(null); }, 1600); } }}
        style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height: H, position: 'relative', touchAction: 'pan-y' }}>
        {bars.map((bar, i) => {
          const isOn = active === i || pinned === i;
          const incBg = isOn ? p.pos : p.posBar;
          const expBg = isOn ? p.neg : p.negBar;
          const monthKey = monthKeys && monthKeys[i];
          const net = bar.inc - bar.exp;
          return (
            <div key={i}
              onMouseEnter={() => setActive(i)}
              onMouseLeave={() => setActive((v) => v === i ? null : v)}
              onClick={() => { if (monthKey && onPick) { onPick(monthKey); } else { setPinned(i); setTimeout(() => setPinned(null), 1600); } }}
              style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, height: '100%', justifyContent: 'flex-end', cursor: monthKey ? 'pointer' : 'default', position: 'relative' }}>
              <div style={{ width: '100%', display: 'flex', gap: 2, alignItems: 'flex-end', height: H, justifyContent: 'center' }}>
                <div style={{ width: '38%', height: `${bar.inc / max * 100}%`, background: incBg, borderRadius: '3px 3px 0 0', transition: 'background 0.15s' }}/>
                <div style={{ width: '38%', height: `${bar.exp / max * 100}%`, background: expBg, borderRadius: '3px 3px 0 0', transition: 'background 0.15s' }}/>
              </div>
              {isOn &&
              <div style={{
                position: 'absolute', bottom: H + 8, left: '50%', transform: 'translateX(-50%)',
                background: t.card, color: t.text,
                border: `0.5px solid ${t.sep}`, borderRadius: 12, padding: '10px 12px',
                whiteSpace: 'nowrap', boxShadow: '0 8px 24px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.06)',
                zIndex: 8, pointerEvents: 'none', minWidth: 124
              }}>
                  <div style={{ fontSize: 10, color: t.textSec, fontWeight: 600, letterSpacing: 0.4, textTransform: 'uppercase', marginBottom: 6 }}>{bar.label}</div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, ...NUMS }}>
                    <span style={{ width: 7, height: 7, borderRadius: 4, background: p.pos, display: 'inline-block' }} />
                    <span style={{ color: t.textSec, fontWeight: 500 }}>Ein.</span>
                    <span style={{ marginLeft: 'auto', color: t.text, fontWeight: 700 }}>+{bar.inc} €</span>
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, marginTop: 3, ...NUMS }}>
                    <span style={{ width: 7, height: 7, borderRadius: 4, background: p.neg, display: 'inline-block' }} />
                    <span style={{ color: t.textSec, fontWeight: 500 }}>Aus.</span>
                    <span style={{ marginLeft: 'auto', color: t.text, fontWeight: 700 }}>−{bar.exp} €</span>
                  </div>
                  <div style={{ height: 0.5, background: t.sep, margin: '8px -12px 6px' }} />
                  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 12, ...NUMS }}>
                    <span style={{ color: t.textSec, fontWeight: 500 }}>Netto</span>
                    <span style={{ color: net >= 0 ? p.pos : p.neg, fontWeight: 700 }}>{net >= 0 ? '+' : '−'}{Math.abs(net)} €</span>
                  </div>
                  {monthKey &&
                <div style={{ fontSize: 10, color: t.textTer, fontWeight: 600, marginTop: 6, textAlign: 'center' }}>Klick → Details</div>
                }
                  {/* arrow */}
                  <div style={{ position: 'absolute', left: '50%', bottom: -5, transform: 'translateX(-50%) rotate(45deg)', width: 9, height: 9, background: t.card, borderRight: `0.5px solid ${t.sep}`, borderBottom: `0.5px solid ${t.sep}` }} />
                </div>
              }
            </div>);

        })}
      </div>
      <div style={{ display: 'flex', gap: 6, marginTop: 6 }}>
        {bars.map((bar, i) =>
        <div key={i} style={{ flex: 1, fontSize: 9, color: t.textSec, fontWeight: 500, textAlign: 'center' }}>{bar.label}</div>
        )}
      </div>
    </div>);

}

function ChartLine({ bars, t }) {
  const p = palette(t);
  const max = Math.max(...bars.map((b) => Math.max(b.inc, b.exp)), 1);
  const W = 280,H = 100,pad = 6;
  const xs = (i) => i / (bars.length - 1 || 1) * (W - pad * 2) + pad;
  const ys = (v) => H - v / max * (H - pad * 2) - pad;
  const linePath = (key) => bars.map((b, i) => `${i === 0 ? 'M' : 'L'}${xs(i)} ${ys(b[key])}`).join(' ');
  const areaPath = `M${pad} ${H} ${bars.map((b, i) => `L${xs(i)} ${ys(b.inc)}`).join(' ')} L${W - pad} ${H} Z`;
  return (
    <svg width="100%" viewBox={`0 0 ${W} ${H + 16}`} style={{ display: 'block' }}>
      <defs>
        <linearGradient id="incFill2" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={p.pos} stopOpacity="0.18" />
          <stop offset="100%" stopColor={p.pos} stopOpacity="0" />
        </linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map((g) => <line key={g} x1={pad} y1={H * g} x2={W - pad} y2={H * g} stroke={p.grid} strokeWidth="0.5" strokeDasharray="2 3" />)}
      <line x1={pad} y1={H} x2={W - pad} y2={H} stroke={p.grid} strokeWidth="0.5" />
      <path d={areaPath} fill="url(#incFill2)" />
      <path d={linePath('inc')} fill="none" stroke={p.pos} strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round" />
      <path d={linePath('exp')} fill="none" stroke={p.neg} strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round" strokeDasharray="3 3" />
      {bars.map((b, i) => <circle key={i} cx={xs(i)} cy={ys(b.inc)} r={b.inc > 0 ? 2 : 0} fill={p.pos} />)}
      {bars.map((b, i) => <text key={i} x={xs(i)} y={H + 13} textAnchor="middle" fontSize="8" fill={t.textSec} fontWeight="500">{b.label}</text>)}
    </svg>);

}

function ChartArea({ bars, t }) {
  const p = palette(t);
  let cum = 0;
  const nets = bars.map((b) => (cum += b.inc - b.exp, cum));
  const max = Math.max(...nets, 0),min = Math.min(...nets, 0);
  const range = max - min || 1;
  const W = 280,H = 100,pad = 6;
  const xs = (i) => i / (nets.length - 1 || 1) * (W - pad * 2) + pad;
  const ys = (v) => H - (v - min) / range * (H - pad * 2) - pad;
  const linePath = nets.map((v, i) => `${i === 0 ? 'M' : 'L'}${xs(i)} ${ys(v)}`).join(' ');
  const baseY = ys(0);
  const areaPath = `M${pad} ${baseY} ${nets.map((v, i) => `L${xs(i)} ${ys(v)}`).join(' ')} L${W - pad} ${baseY} Z`;
  return (
    <svg width="100%" viewBox={`0 0 ${W} ${H + 16}`} style={{ display: 'block' }}>
      <defs>
        <linearGradient id="netFill2" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={p.pos} stopOpacity="0.22" />
          <stop offset="100%" stopColor={p.pos} stopOpacity="0" />
        </linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map((g) => <line key={g} x1={pad} y1={H * g} x2={W - pad} y2={H * g} stroke={p.grid} strokeWidth="0.5" strokeDasharray="2 3" />)}
      <line x1={pad} y1={baseY} x2={W - pad} y2={baseY} stroke={p.grid} strokeWidth="0.5" />
      <path d={areaPath} fill="url(#netFill2)" />
      <path d={linePath} fill="none" stroke={p.pos} strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round" />
      {nets.map((v, i) => v !== 0 && <circle key={i} cx={xs(i)} cy={ys(v)} r="2" fill={p.pos} style={{ fill: "rgb(52, 199, 89)" }} />)}
      {bars.map((b, i) => <text key={i} x={xs(i)} y={H + 13} textAnchor="middle" fontSize="8" fill={t.textSec} fontWeight="500">{b.label}</text>)}
    </svg>);

}

function ChartDonut({ income, expenses, profit, t }) {
  const p = palette(t);
  const total = income + expenses || 1;
  const incPct = income / total;
  const C = 80,R = 58,SW = 10,gap = 2;
  const circ = 2 * Math.PI * R;
  return (
    <div style={{ height: 130, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <svg width={160} height={130} viewBox={`0 0 160 130`}>
        <g transform={`rotate(-90 ${C} 65)`}>
          <circle cx={C} cy={65} r={R} fill="none" stroke={p.grid} strokeWidth={SW} />
          <circle cx={C} cy={65} r={R} fill="none" stroke={p.pos} strokeWidth={SW}
          strokeDasharray={`${Math.max(0, incPct * circ - gap)} ${circ}`} strokeLinecap="round" style={{ stroke: "rgba(52, 199, 89, 0.498)" }} />
          <circle cx={C} cy={65} r={R} fill="none" stroke={p.neg} strokeWidth={SW}
          strokeDasharray={`${Math.max(0, (1 - incPct) * circ - gap)} ${circ}`}
          strokeDashoffset={-(incPct * circ)} strokeLinecap="round" style={{ stroke: "rgba(255, 59, 48, 0.494)" }} />
        </g>
      </svg>
      <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', textAlign: 'center' }}>
        <div style={{ fontSize: 9, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.8 }}>Netto</div>
        <div style={{ fontSize: 20, fontWeight: 600, color: t.text, letterSpacing: -0.5, marginTop: 2, ...NUMS }}>
          {profit >= 0 ? '+' : ''}{profit.toLocaleString('de-DE')} €
        </div>
        <div style={{ fontSize: 9, color: t.textSec, marginTop: 2, ...NUMS }}>{Math.round(incPct * 100)}% Ein. · {Math.round((1 - incPct) * 100)}% Aus.</div>
      </div>
    </div>);

}

const CHART_TYPES = [
{ id: 'bars', label: 'Balken', icon: 'M4 20V10M10 20V4M16 20V14M22 20H2' },
{ id: 'line', label: 'Linie', icon: 'M3 17l5-5 4 3 8-9' },
{ id: 'area', label: 'Gewinn', icon: 'M3 17l5-5 4 3 8-9M3 20h18' },
{ id: 'donut', label: 'Anteil', icon: 'M21 12a9 9 0 11-9-9v9h9z' }];


// ─── Add Transaction Sheet ──────────────────────────────────
function AddTxSheet({ open, onClose, onSave }) {
  const t = useTheme();
  const p = palette(t);
  const [kind, setKind] = useState('in');
  const [label, setLabel] = useState('');
  const [sub, setSub] = useState('');
  const [amount, setAmount] = useState('');
  const [date, setDate] = useState(() => fin_todayISO());
  // Whenever the sheet (re-)opens, default the date back to today
  useEffect(() => { if (open) setDate(fin_todayISO()); }, [open]);

  const reset = () => {setKind('in');setLabel('');setSub('');setAmount('');setDate(fin_todayISO());};
  const close = () => {reset();onClose();};
  const save = () => {
    const n = parseFloat(String(amount).replace(',', '.'));
    if (!label.trim() || !n || n <= 0) return;
    onSave({ kind, label: label.trim(), sub: sub.trim() || (kind === 'in' ? 'Vermietung' : 'Ausgabe'), amount: Math.round(n), date: date || fin_todayISO() });
    reset();onClose();
  };

  const fInp = {
    width: '100%', padding: '12px 14px', borderRadius: 12,
    border: `0.5px solid ${t.inputBorder}`, background: t.card,
    fontSize: 15, color: t.text, outline: 'none', fontFamily: 'inherit', boxSizing: 'border-box'
  };

  return (
    <Sheet open={open} onClose={close}>
      <div style={{ padding: '4px 24px 24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <div>
            <div style={{ fontSize: 22, fontWeight: 700, color: t.text, letterSpacing: -0.5 }}>Neue Buchung</div>
            <div style={{ fontSize: 13, color: t.textSec, marginTop: 4 }}>Einnahme oder Ausgabe erfassen.</div>
          </div>
          <Pressable onClick={close}><div style={{ fontSize: 14, color: t.textSec, fontWeight: 500 }}>Abbrechen</div></Pressable>
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 18 }}>
          {[['in', 'Einnahme', p.pos], ['out', 'Ausgabe', p.neg]].map(([k, l, c]) =>
          <Pressable key={k} onClick={() => setKind(k)} scale={0.96} style={{ flex: 1 }}>
              <div style={{
              padding: '13px 0', textAlign: 'center', borderRadius: 12,
              background: kind === k ? t.solidBg : t.chip,
              color: kind === k ? t.solidFg : t.text, fontSize: 13, fontWeight: 600,
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7
            }}>
                <div style={{ width: 7, height: 7, borderRadius: 4, background: c }} />
                {l}
              </div>
            </Pressable>
          )}
        </div>

        <div style={{ marginTop: 16 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>Betrag</div>
          <div style={{ position: 'relative' }}>
            <input value={amount} onChange={(e) => setAmount(e.target.value)} placeholder="0" type="number" inputMode="decimal"
            style={{ ...fInp, padding: '14px 36px 14px 14px', fontSize: 26, fontWeight: 600, color: t.text, letterSpacing: -0.6, ...NUMS }} />
            <span style={{ position: 'absolute', right: 16, top: '50%', transform: 'translateY(-50%)', fontSize: 20, color: t.textSec, fontWeight: 700 }}>€</span>
          </div>
        </div>

        <div style={{ marginTop: 14 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>Bezeichnung</div>
          <input value={label} onChange={(e) => setLabel(e.target.value)} placeholder={kind === 'in' ? 'z.B. Hochzeit Schmidt' : 'z.B. Neuer Lautsprecher'} style={fInp} />
        </div>

        <div style={{ marginTop: 12 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>Notiz · optional</div>
          <input value={sub} onChange={(e) => setSub(e.target.value)} placeholder={kind === 'in' ? 'Was wurde vermietet?' : 'Wofür?'} style={fInp} />
        </div>

        <div style={{ marginTop: 12 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
            <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5 }}>Datum</div>
            {date !== fin_todayISO() &&
              <Pressable onClick={() => setDate(fin_todayISO())} scale={0.96}>
                <div style={{ fontSize: 11, color: t.accent, fontWeight: 600 }}>Heute</div>
              </Pressable>
            }
          </div>
          <input value={date} onChange={(e) => setDate(e.target.value)} type="date" max={fin_todayISO()}
            style={{ ...fInp, color: t.text, fontVariantNumeric: 'tabular-nums' }} />
          <div style={{ fontSize: 11, color: t.textTer, fontWeight: 500, marginTop: 5 }}>
            {date === fin_todayISO() ? 'Standard: heute. Antippen, um nachträglich einzutragen.' : `Wird am ${fin_fmtDateLabel(date)} eingetragen.`}
          </div>
        </div>

        <Pressable onClick={save} scale={0.97} style={{ marginTop: 20 }}>
          <div style={{
            padding: '15px 0', textAlign: 'center', borderRadius: 14,
            background: t.solidBg, color: t.solidFg, fontSize: 16, fontWeight: 600,
            boxShadow: '0 6px 16px rgba(0,0,0,0.28)'
          }}>Speichern</div>
        </Pressable>
      </div>
    </Sheet>);

}

// ─── Edit Transaction Sheet — pre-filled, with delete ───────
function EditTxSheet({ tx, onClose, onSave, onDelete }) {
  const t = useTheme();
  const p = palette(t);
  const [kind, setKind] = useState('in');
  const [label, setLabel] = useState('');
  const [sub, setSub] = useState('');
  const [amount, setAmount] = useState('');
  const [date, setDate] = useState('');
  const [confirmDel, setConfirmDel] = useState(false);

  useEffect(() => {
    if (tx) {
      setKind(tx.kind);
      setLabel(tx.label);
      setSub(tx.sub || '');
      setAmount(String(tx.amount));
      setDate(tx.date && /^\d{4}-\d{2}-\d{2}/.test(tx.date) ? tx.date.slice(0, 10) : fin_todayISO());
    }
  }, [tx && tx.id]);

  if (!tx) return null;

  const save = () => {
    const n = parseFloat(String(amount).replace(',', '.'));
    if (!label.trim() || !n || n <= 0) return;
    onSave({ kind, label: label.trim(), sub: sub.trim(), amount: Math.round(n), date: date || fin_todayISO() });
  };

  const fInp = {
    width: '100%', padding: '12px 14px', borderRadius: 12,
    border: `0.5px solid ${t.inputBorder}`, background: t.card,
    fontSize: 15, color: t.text, outline: 'none', fontFamily: 'inherit', boxSizing: 'border-box'
  };

  return (
    <Sheet open={!!tx} onClose={onClose}>
      <div style={{ padding: '4px 24px 24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <div>
            <div style={{ fontSize: 22, fontWeight: 700, color: t.text, letterSpacing: -0.5 }}>Buchung bearbeiten</div>
            <div style={{ fontSize: 13, color: t.textSec, marginTop: 4 }}>{fin_fmtDateLabel(tx.date)}</div>
          </div>
          <Pressable onClick={onClose}><div style={{ fontSize: 14, color: t.textSec, fontWeight: 500 }}>Abbrechen</div></Pressable>
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 18 }}>
          {[['in', 'Einnahme', p.pos], ['out', 'Ausgabe', p.neg]].map(([k, l, c]) =>
          <Pressable key={k} onClick={() => setKind(k)} scale={0.96} style={{ flex: 1 }}>
              <div style={{
              padding: '13px 0', textAlign: 'center', borderRadius: 12,
              background: kind === k ? t.solidBg : t.chip,
              color: kind === k ? t.solidFg : t.text, fontSize: 13, fontWeight: 600,
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7
            }}>
                <div style={{ width: 7, height: 7, borderRadius: 4, background: c }} />
                {l}
              </div>
            </Pressable>
          )}
        </div>

        <div style={{ marginTop: 16 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>Betrag</div>
          <div style={{ position: 'relative' }}>
            <input value={amount} onChange={(e) => setAmount(e.target.value)} placeholder="0" type="number" inputMode="decimal"
            style={{ ...fInp, padding: '14px 36px 14px 14px', fontSize: 26, fontWeight: 600, color: t.text, letterSpacing: -0.6, ...NUMS }} />
            <span style={{ position: 'absolute', right: 16, top: '50%', transform: 'translateY(-50%)', fontSize: 20, color: t.textSec, fontWeight: 700 }}>€</span>
          </div>
        </div>

        <div style={{ marginTop: 14 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>Bezeichnung</div>
          <input value={label} onChange={(e) => setLabel(e.target.value)} style={fInp} />
        </div>

        <div style={{ marginTop: 12 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: 6 }}>Notiz</div>
          <input value={sub} onChange={(e) => setSub(e.target.value)} style={fInp} />
        </div>

        <div style={{ marginTop: 12 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
            <div style={{ fontSize: 11, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5 }}>Datum</div>
            {date !== fin_todayISO() &&
              <Pressable onClick={() => setDate(fin_todayISO())} scale={0.96}>
                <div style={{ fontSize: 11, color: t.accent, fontWeight: 600 }}>Auf heute</div>
              </Pressable>
            }
          </div>
          <input value={date} onChange={(e) => setDate(e.target.value)} type="date"
            style={{ ...fInp, color: t.text, fontVariantNumeric: 'tabular-nums' }} />
        </div>

        <div style={{ display: 'flex', gap: 10, marginTop: 20 }}>
          <Pressable onClick={() => setConfirmDel(true)} scale={0.97}>
            <div style={{
              padding: '15px 18px', textAlign: 'center', borderRadius: 14,
              background: p.negSft, color: p.neg, fontSize: 15, fontWeight: 600,
              display: 'flex', alignItems: 'center', gap: 8
            }}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={p.neg} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6M10 11v6M14 11v6" /></svg>
              Löschen
            </div>
          </Pressable>
          <Pressable onClick={save} scale={0.97} style={{ flex: 1 }}>
            <div style={{
              padding: '15px 0', textAlign: 'center', borderRadius: 14,
              background: t.solidBg, color: t.solidFg, fontSize: 16, fontWeight: 600,
              boxShadow: '0 6px 16px rgba(0,0,0,0.28)'
            }}>Speichern</div>
          </Pressable>
        </div>
      </div>
      <Confirm open={confirmDel} title="Buchung löschen?"
        message={`„${tx.label}" (${tx.kind === 'in' ? '+' : '−'}${tx.amount} €) wird entfernt.`}
        confirmLabel="Löschen" danger
        onCancel={() => setConfirmDel(false)}
        onConfirm={() => { setConfirmDel(false); onDelete(); }} />
    </Sheet>);

}

// ─── Month Detail Sheet — drill into a specific month for analysis ─────────
function MonthDetailSheet({ open, monthKey, onClose, t, p, transactions, monthsRange }) {
  const [chartType, setChartType] = useState('bars');
  if (!monthKey) return null;

  // Compute month figures on the fly from the shared transactions array.
  const [y, m] = monthKey.split('-').map(Number);
  const monthTxs = fin_txInMonth(transactions, monthKey).slice().sort((a, b) => (b.date || '').localeCompare(a.date || ''));
  const { income, expenses } = fin_sumAgg(monthTxs);
  const profit = income - expenses;
  const margin = income > 0 ? Math.round(profit / income * 100) : 0;
  const bars = fin_weeklyBars(transactions, y, m - 1);
  const label = fin_fmtMonthLabel(monthKey);

  // Compare with previous month from range
  const keys = (monthsRange || []).map(mo => mo.key);
  const idx = keys.indexOf(monthKey);
  let prevAgg = null;
  if (idx > 0) prevAgg = fin_sumAgg(fin_txInMonth(transactions, keys[idx - 1]));
  const incTrend  = prevAgg ? pctF(income, prevAgg.income) : null;
  const expTrend  = prevAgg ? pctF(expenses, prevAgg.expenses) : null;
  const profTrend = prevAgg ? pctF(profit, prevAgg.income - prevAgg.expenses) : null;

  // Top categories from transactions
  const topIn  = [...monthTxs].filter((x) => x.kind === 'in').sort((a, b) => b.amount - a.amount).slice(0, 1)[0];
  const topOut = [...monthTxs].filter((x) => x.kind === 'out').sort((a, b) => b.amount - a.amount).slice(0, 1)[0];

  return (
    <Sheet open={open} onClose={onClose}>
      <div style={{ padding: '4px 24px 24px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <div>
            <div style={{ fontSize: 13, color: t.textSec, fontWeight: 500 }}>Monatsanalyse</div>
            <div style={{ fontSize: 26, fontWeight: 700, color: t.text, letterSpacing: -0.6, marginTop: 2 }}>{label}</div>
          </div>
          <Pressable onClick={onClose}><div style={{ fontSize: 14, color: t.textSec, fontWeight: 500 }}>Schließen</div></Pressable>
        </div>

        {/* Big stats */}
        <div style={{ marginTop: 18, background: t.card, borderRadius: 18, padding: '16px 18px', boxShadow: t.shadowCard }}>
          <div style={{ fontSize: 10, color: t.textSec, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 1.0 }}>Netto-Ergebnis</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginTop: 4 }}>
            <div style={{ fontSize: 36, fontWeight: 600, color: profit >= 0 ? p.pos : p.neg, letterSpacing: -1.2, ...NUMS }}>
              {profit >= 0 ? '+' : ''}{profit.toLocaleString('de-DE')}<span style={{ fontSize: 20, marginLeft: 2 }}>€</span>
            </div>
            {profTrend &&
            <div style={{ fontSize: 11, color: profTrend.up ? p.pos : p.neg, fontWeight: 600, ...NUMS }}>
                {profTrend.up ? '▲' : '▼'} {profTrend.val}%
              </div>
            }
          </div>
          <div style={{ fontSize: 12, color: t.textSec, marginTop: 4, ...NUMS }}>
            Marge {margin}% · {monthTxs.length} Buchungen
          </div>

          <div style={{ display: 'flex', marginTop: 16, paddingTop: 14, borderTop: `0.5px solid ${t.sep}` }}>
            <div style={{ flex: 1, paddingRight: 14, borderRight: `0.5px solid ${t.sep}` }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <div style={{ width: 5, height: 5, borderRadius: 3, background: p.pos }} />
                <div style={{ fontSize: 10, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.8 }}>Einnahmen</div>
              </div>
              <div style={{ fontSize: 18, fontWeight: 600, color: t.text, marginTop: 5, ...NUMS }}>{income.toLocaleString('de-DE')} <span style={{ fontSize: 12, color: t.textSec }}>€</span></div>
              {incTrend && <div style={{ fontSize: 10, color: incTrend.up ? p.pos : p.neg, fontWeight: 600, marginTop: 2, ...NUMS }}>{incTrend.up ? '▲' : '▼'} {incTrend.val}% vs. Vormonat</div>}
            </div>
            <div style={{ flex: 1, paddingLeft: 14 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <div style={{ width: 5, height: 5, borderRadius: 3, background: p.neg }} />
                <div style={{ fontSize: 10, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.8 }}>Ausgaben</div>
              </div>
              <div style={{ fontSize: 18, fontWeight: 600, color: t.text, marginTop: 5, ...NUMS }}>{expenses.toLocaleString('de-DE')} <span style={{ fontSize: 12, color: t.textSec }}>€</span></div>
              {expTrend && <div style={{ fontSize: 10, color: !expTrend.up ? p.pos : p.neg, fontWeight: 600, marginTop: 2, ...NUMS }}>{expTrend.up ? '▲' : '▼'} {expTrend.val}% vs. Vormonat</div>}
            </div>
          </div>
        </div>

        {/* Chart switch */}
        <div style={{ marginTop: 16, display: 'flex', gap: 3, padding: 3, background: t.chipStrong, borderRadius: 10 }}>
          {CHART_TYPES.map((c) =>
          <Pressable key={c.id} onClick={() => setChartType(c.id)} scale={0.94} style={{ flex: 1 }}>
              <div style={{
              padding: '6px 0', textAlign: 'center', borderRadius: 8,
              background: chartType === c.id ? t.card : 'transparent',
              fontSize: 10, fontWeight: 600,
              color: chartType === c.id ? t.text : t.textSec,
              boxShadow: chartType === c.id ? '0 1px 3px rgba(0,0,0,0.08)' : 'none',
              display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4
            }}>
                <Icon d={c.icon} color={chartType === c.id ? t.text : t.textSec} size={11} sw={2} />
                {c.label}
              </div>
            </Pressable>
          )}
        </div>

        {/* Chart */}
        <div style={{ marginTop: 12, background: t.card, borderRadius: 18, padding: '14px 16px 10px' }}>
          {chartType === 'bars' && <ChartBars bars={bars} t={t} />}
          {chartType === 'line' && <ChartLine bars={bars} t={t} />}
          {chartType === 'area' && <ChartArea bars={bars} t={t} />}
          {chartType === 'donut' && <ChartDonut income={income} expenses={expenses} profit={profit} t={t} />}
        </div>

        {/* Highlights */}
        {(topIn || topOut) &&
        <div style={{ marginTop: 16 }}>
            <div style={{ fontSize: 11, color: t.textSec, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.6, marginBottom: 8 }}>Top-Positionen</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {topIn &&
            <div style={{ background: t.card, borderRadius: 12, padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 10 }}>
                  <div style={{ width: 30, height: 30, borderRadius: 9, background: p.posSft, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                    <Icon d="M7 17L17 7M17 7H9M17 7v8" color={p.pos} size={14} sw={2.2} />
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 10, color: t.textSec, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5 }}>Größte Einnahme</div>
                    <div style={{ fontSize: 13, fontWeight: 600, color: t.text, marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{topIn.label}</div>
                  </div>
                  <div style={{ fontSize: 14, fontWeight: 700, color: p.pos, ...NUMS }}>+{topIn.amount} €</div>
                </div>
            }
              {topOut &&
            <div style={{ background: t.card, borderRadius: 12, padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 10 }}>
                  <div style={{ width: 30, height: 30, borderRadius: 9, background: p.negSft, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                    <Icon d="M17 7L7 17M7 17h8M7 17V9" color={p.neg} size={14} sw={2.2} />
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 10, color: t.textSec, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.5 }}>Größte Ausgabe</div>
                    <div style={{ fontSize: 13, fontWeight: 600, color: t.text, marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{topOut.label}</div>
                  </div>
                  <div style={{ fontSize: 14, fontWeight: 700, color: p.neg, ...NUMS }}>−{topOut.amount} €</div>
                </div>
            }
            </div>
          </div>
        }

        {/* Transactions */}
        <div style={{ marginTop: 18 }}>
          <div style={{ fontSize: 11, color: t.textSec, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.6, marginBottom: 8 }}>Alle Buchungen</div>
          <div style={{ background: t.card, borderRadius: 14, overflow: 'hidden' }}>
            {monthTxs.map((tx, i, arr) => {
              const isIn = tx.kind === 'in';
              return (
                <div key={tx.id} style={{
                  padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 10,
                  borderBottom: i < arr.length - 1 ? `0.5px solid ${t.sep}` : 'none'
                }}>
                  <div style={{ width: 28, height: 28, borderRadius: 9, background: isIn ? p.posSft : p.negSft, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                    <Icon d={isIn ? 'M7 17L17 7M17 7H9M17 7v8' : 'M17 7L7 17M7 17h8M7 17V9'} color={isIn ? p.pos : p.neg} size={13} sw={2} />
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: t.text, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{tx.label}</div>
                    <div style={{ fontSize: 10, color: t.textSec, marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{tx.sub} · {fin_fmtDateLabel(tx.date)}</div>
                  </div>
                  <div style={{ fontSize: 13, fontWeight: 700, color: isIn ? p.pos : p.neg, ...NUMS }}>{isIn ? '+' : '−'}{tx.amount} €</div>
                </div>);

            })}
          </div>
        </div>
      </div>
    </Sheet>);

}

// ─── Main Finanzen ───────────────────────────────────────────
function ScreenFinanzen({ toast, transactions, setTransactions, installedAt }) {
  const t = useTheme();
  const p = palette(t);
  const [period, setPeriod] = useState('month');
  const [tab, setTab] = useState('all');
  const [addOpen, setAddOpen] = useState(false);
  const [editingTx, setEditingTx] = useState(null);
  const [monthDetailKey, setMonthDetailKey] = useState(null);

  const [defaultChart, setDefaultChart] = useState(() => {
    try {
      const raw = localStorage.getItem('rf-default-chart');
      if (!raw) return 'bars';
      // Tolerate legacy raw-string format AND the proper JSON-encoded form.
      try { const v = JSON.parse(raw); return typeof v === 'string' ? v : 'bars'; }
      catch { return raw; }
    } catch {return 'bars';}
  });
  const [chartType, setChartType] = useState(defaultChart);
  const lpRef = React.useRef({ timer: null, fired: false });
  const startPinPress = (id) => {
    lpRef.current.fired = false;
    clearTimeout(lpRef.current.timer);
    lpRef.current.timer = setTimeout(() => {
      lpRef.current.fired = true;
      pinAsDefault(id);
      if (navigator.vibrate) try { navigator.vibrate(10); } catch (_) {}
    }, 500);
  };
  const cancelPinPress = () => { clearTimeout(lpRef.current.timer); };

  const pinAsDefault = (id) => {
    try {localStorage.setItem('rf-default-chart', JSON.stringify(id));} catch {}
    setDefaultChart(id);
    toast(`„${CHART_TYPES.find((c) => c.id === id).label}“ als Standard gesetzt`);
  };

  const baseD = { label: period === 'month' ? fin_fmtMonthLabel(fin_monthKeyOf(new Date())) : `Jahr ${new Date().getFullYear()}` };
  // ── Live, dynamic data ──
  const today = new Date();
  const curYear  = today.getFullYear();
  const curMonth = today.getMonth();
  const CURRENT_MONTH_KEY = fin_monthKeyOf(today);
  const monthsRange = fin_buildMonthsRange(installedAt, transactions);
  const currentMonthLabel = fin_fmtMonthLabel(CURRENT_MONTH_KEY);

  const periodTxs = period === 'month'
    ? fin_txInMonth(transactions, CURRENT_MONTH_KEY)
    : fin_txInYear(transactions, curYear);
  const periodAgg = fin_sumAgg(periodTxs);
  const income   = periodAgg.income;
  const expenses = periodAgg.expenses;
  const profit   = periodAgg.profit;

  // Bars (weekly for month, monthly-of-active-months for year)
  const bars = period === 'month'
    ? fin_weeklyBars(transactions, curYear, curMonth)
    : fin_yearBars(transactions, curYear, installedAt);

  // Kontostand = net of ALL transactions (Home & Finanzen share this exact number)
  const liveBalance = fin_sumAgg(transactions).profit;

  // Hero-card month figures (always current month, independent of period toggle)
  const monthTxs = fin_txInMonth(transactions, CURRENT_MONTH_KEY);
  const monthAgg = fin_sumAgg(monthTxs);
  const monthIncome   = monthAgg.income;
  const monthExpenses = monthAgg.expenses;
  const monthProfit   = monthAgg.profit;

  // Mini-Bars: income per month across the active range (installation → today,
  // or oldest tx → today). Shows one bar per month — e.g. 2 bars for Mai + Juni.
  const monthBars = fin_monthlyIncomeBars(transactions, installedAt, 12);
  const sparkMax = Math.max(...monthBars.map(b => b.income)) || 1;

  // Transaction list (sorted newest-first)
  const filtered = periodTxs
    .filter((tx) => tab === 'all' || tx.kind === tab)
    .slice().sort((a, b) => (b.date || '').localeCompare(a.date || ''));

  const saveTxEdit = (id, patch) => {
    setTransactions((prev) => prev.map((x) => x.id === id ? { ...x, ...patch } : x));
    toast('Buchung aktualisiert');
  };
  const deleteTx = (id) => {
    setTransactions((prev) => prev.filter((x) => x.id !== id));
    toast('Buchung gelöscht');
  };
  const onSaveTx = (tx) => {
    setTransactions((prev) => [{ id: Date.now(), ...tx }, ...prev]);
    toast(`${tx.kind === 'in' ? 'Einnahme' : 'Ausgabe'} ${tx.amount} € gespeichert`);
  };

  const fmt = (n) => Math.abs(n) >= 1000 ? (n / 1000).toFixed(1).replace('.', ',') + 'T' : String(n);

  return (
    <div style={{ paddingBottom: 100 }}>
      {/* Header — title row on top, period segmented control below for breathing room */}
      <div style={{ padding: '8px 20px 0' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
          <div>
            <div style={{ fontSize: 13, color: t.textSec, fontWeight: 500 }}>{baseD.label}</div>
            <div style={{ fontSize: 32, fontWeight: 700, color: t.text, letterSpacing: -0.8, marginTop: 2 }}>Finanzen</div>
          </div>
          <div style={{ display: 'flex', gap: 10, alignItems: 'center', paddingTop: 6 }}>
            <Pressable onClick={() => setAddOpen(true)} scale={0.88}>
              <div style={{
                width: 38, height: 38, borderRadius: 19, background: t.solidBg,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: '0 4px 12px rgba(0,0,0,0.28)'
              }}>
                <Icon d={icons.plus} color={t.solidFg} size={18} sw={2.6} />
              </div>
            </Pressable>
            <CompanyGear size={38} />
          </div>
        </div>
        <div style={{ marginTop: 16, display: 'flex', padding: 3, borderRadius: 11, background: t.chipStrong, width: 'fit-content' }}>
          {[['month', 'Monat'], ['year', 'Jahr']].map(([id, label]) =>
          <Pressable key={id} onClick={() => setPeriod(id)} scale={0.96}>
              <div style={{
              padding: '7px 18px', borderRadius: 9, fontSize: 13, fontWeight: 600,
              background: period === id ? t.card : 'transparent',
              color: period === id ? t.text : t.textSec,
              boxShadow: period === id ? '0 1px 3px rgba(0,0,0,0.08)' : 'none'
            }}>{label}</div>
            </Pressable>
          )}
        </div>
      </div>

      {/* Hero: balance — matches Home Kontostand card style, with Einnahmen + Ausgaben */}
      <div style={{ padding: '18px 16px 0' }}>
        <div style={{
              borderRadius: 22, padding: '20px 22px',
              background: t.card, boxShadow: t.shadowCard
            }}>
              {/* Row 1 — Kontostand + sparkline */}
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                <div>
                  <div style={{ fontSize: 11, color: t.textSec, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 1.0 }}>Kontostand</div>
                  <div style={{ fontSize: 38, fontWeight: 600, color: t.text, letterSpacing: -1.3, marginTop: 4, ...NUMS }}>
                    {liveBalance.toLocaleString('de-DE')} <span style={{ fontSize: 22, color: t.textSec, fontWeight: 500 }}>€</span>
                  </div>
                  <div style={{ fontSize: 11, color: t.textSec, marginTop: 4 }}>Verfügbares Guthaben</div>
                </div>
                <div style={{ display: 'flex', alignItems: 'flex-end', gap: 3, height: 52 }}>
                  {monthBars.map((b, i) =>
                  <div key={b.key} title={`${b.short}: ${b.income} €`} style={{
                    width: monthBars.length === 1 ? 14 : 7,
                    height: Math.max(4, b.income / sparkMax * 52), borderRadius: 3,
                    background: i === monthBars.length - 1 ? p.pos : p.pos + '55'
                  }} />
                  )}
                </div>
              </div>

              {/* Hairline */}
              <div style={{ marginTop: 16, paddingTop: 14, borderTop: `0.5px solid ${t.sep}` }}>
                <div style={{ fontSize: 10, color: t.textTer, fontWeight: 700, textTransform: 'uppercase', letterSpacing: 0.8, marginBottom: 10 }}>
                  {currentMonthLabel}
                </div>
                <div style={{ display: 'flex' }}>
                  {/* Einnahmen */}
                  <div style={{ flex: 1, paddingRight: 12, borderRight: `0.5px solid ${t.sep}` }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ ...{ width: 5, height: 5, borderRadius: 3, background: p.pos }, background: "rgba(52, 199, 89, 0.6)" }} />
                      <div style={{ fontSize: 10, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.8 }}>Einnahmen</div>
                    </div>
                    <div style={{ fontSize: 18, fontWeight: 600, color: t.text, marginTop: 5, ...NUMS }}>
                      +{monthIncome.toLocaleString('de-DE')} <span style={{ fontSize: 12, color: t.textSec, fontWeight: 500 }}>€</span>
                    </div>
                  </div>
                  {/* Ausgaben */}
                  <div style={{ flex: 1, padding: '0 12px', borderRight: `0.5px solid ${t.sep}` }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ ...{ width: 5, height: 5, borderRadius: 3, background: p.neg }, background: "rgba(255, 59, 48, 0.604)" }} />
                      <div style={{ fontSize: 10, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.8 }}>Ausgaben</div>
                    </div>
                    <div style={{ fontSize: 18, fontWeight: 600, color: t.text, marginTop: 5, ...NUMS }}>
                      −{monthExpenses.toLocaleString('de-DE')} <span style={{ fontSize: 12, color: t.textSec, fontWeight: 500 }}>€</span>
                    </div>
                  </div>
                  {/* Netto */}
                  <div style={{ flex: 1, paddingLeft: 12 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ width: 5, height: 5, borderRadius: 3, background: monthProfit >= 0 ? p.pos : p.neg }} />
                      <div style={{ fontSize: 10, color: t.textSec, fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.8 }}>Netto</div>
                    </div>
                    <div style={{ fontSize: 18, fontWeight: 700, color: monthProfit >= 0 ? p.pos : p.neg, marginTop: 5, ...NUMS }}>
                      {monthProfit >= 0 ? '+' : ''}{monthProfit.toLocaleString('de-DE')} <span style={{ fontSize: 12, fontWeight: 500 }}>€</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>
      </div>

      {/* Chart selector — always visible. Long-press a tile to make it the default. */}
      <div style={{ padding: '20px 16px 0' }}>
        <div style={{ display: 'flex', gap: 3, padding: 3, background: t.chipStrong, borderRadius: 12 }}>
          {CHART_TYPES.map((c) =>
          <div key={c.id} style={{ flex: 1 }}
            onPointerDown={() => startPinPress(c.id)}
            onPointerUp={cancelPinPress}
            onPointerLeave={cancelPinPress}
            onPointerCancel={cancelPinPress}
            onContextMenu={(e) => { e.preventDefault(); pinAsDefault(c.id); }}>
              <Pressable onClick={() => { if (!lpRef.current.fired) setChartType(c.id); }} scale={0.94} style={{ width: '100%' }}>
                <div style={{
                padding: '7px 0', textAlign: 'center', borderRadius: 9,
                background: chartType === c.id ? t.card : 'transparent',
                boxShadow: chartType === c.id ? '0 1px 3px rgba(0,0,0,0.08)' : 'none',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
                position: 'relative'
              }}>
                  <Icon d={c.icon} color={chartType === c.id ? t.text : t.textSec} size={14} sw={2} />
                  <span style={{ fontSize: 9, color: chartType === c.id ? t.text : t.textSec, fontWeight: 600 }}>{c.label}</span>
                  {defaultChart === c.id &&
                <div title="Standard" style={{ position: 'absolute', top: 3, right: 3, width: 5, height: 5, borderRadius: 3, background: t.text }} />
                }
                </div>
              </Pressable>
            </div>
          )}
        </div>
        <div style={{ fontSize: 9.5, color: t.textTer, fontWeight: 500, textAlign: 'center', marginTop: 5, letterSpacing: 0.2 }}>
          Lang gedrückt halten, um als Standard festzulegen
        </div>
      </div>

      {/* Chart card */}
      <div style={{ padding: '10px 16px 0' }}>
        <div style={{ background: t.card, borderRadius: 20, padding: '16px 18px 12px', boxShadow: t.shadowCard }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
            <div style={{ fontSize: 12, fontWeight: 700, color: t.text, letterSpacing: 0.1 }}>
              {chartType === 'donut' ? 'Aufteilung' :
              chartType === 'area' ? 'Gewinn kumuliert' :
              chartType === 'line' ? 'Verlauf' : 'Einnahmen vs. Ausgaben'}
            </div>
            <div style={{ display: 'flex', gap: 12 }}>
              {chartType !== 'area' &&
              <>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                    <div style={{ ...{ width: 7, height: 7, borderRadius: 4, background: p.pos }, background: "rgba(52, 199, 89, 0.494)" }} />
                    <span style={{ fontSize: 10, color: t.textSec, fontWeight: 500 }}>{chartType === 'donut' ? 'Ein.' : 'Einnahmen'}</span>
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                    <div style={{ ...{ width: 7, height: 7, borderRadius: 4, background: p.neg }, background: "rgba(255, 59, 48, 0.498)" }} />
                    <span style={{ fontSize: 10, color: t.textSec, fontWeight: 500 }}>{chartType === 'donut' ? 'Aus.' : 'Ausgaben'}</span>
                  </div>
                </>
              }
              {chartType === 'area' &&
              <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                  <div style={{ width: 7, height: 7, borderRadius: 4, background: p.pos }} />
                  <span style={{ fontSize: 10, color: t.textSec, fontWeight: 500 }}>Netto kumuliert</span>
                </div>
              }
            </div>
          </div>

          {chartType === 'bars' && <ChartBars bars={bars} t={t}
            onPick={(key) => setMonthDetailKey(key)}
            monthKeys={period === 'year' ? bars.map(b => b.monthKey) : null}/>}
          {chartType === 'line' && <ChartLine bars={bars} t={t} />}
          {chartType === 'area' && <ChartArea bars={bars} t={t} />}
          {chartType === 'donut' && <ChartDonut income={income} expenses={expenses} profit={profit} t={t} />}
        </div>
      </div>

      {/* Transaction list */}
      <div style={{ padding: '22px 20px 8px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ fontSize: 16, fontWeight: 600, color: t.text, letterSpacing: -0.3 }}>Buchungen</div>
        <div style={{ display: 'flex', gap: 4 }}>
          {[['all', 'Alle'], ['in', 'Ein'], ['out', 'Aus']].map(([id, label]) =>
          <Pressable key={id} onClick={() => setTab(id)} scale={0.92}>
              <div style={{
              padding: '5px 10px', borderRadius: 100, fontSize: 11, fontWeight: 600,
              background: tab === id ? t.solidBg : t.chip,
              color: tab === id ? t.solidFg : t.text
            }}>{label}</div>
            </Pressable>
          )}
        </div>
      </div>

      <div style={{ padding: '0 16px', display: 'flex', flexDirection: 'column', gap: 1 }}>
        {filtered.length === 0 &&
        <div style={{ padding: '24px 0', textAlign: 'center', color: t.textSec, fontSize: 13 }}>Keine Buchungen.</div>
        }
        {filtered.map((tx, i, arr) => {
          const isIncome = tx.kind === 'in';
          const col = isIncome ? p.pos : p.neg;
          return (
            <LongPressRow key={tx.id}
              onTap={() => setEditingTx(tx)}
              onEdit={() => setEditingTx(tx)}
              onDelete={() => deleteTx(tx.id)}>
              <div style={{
                background: t.card, padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 12,
                borderTopLeftRadius: i === 0 ? 16 : 0, borderTopRightRadius: i === 0 ? 16 : 0,
                borderBottomLeftRadius: i === arr.length - 1 ? 16 : 0, borderBottomRightRadius: i === arr.length - 1 ? 16 : 0,
                borderBottom: i < arr.length - 1 ? `0.5px solid ${t.sep}` : 'none'
              }}>
                <div style={{ width: 34, height: 34, borderRadius: 10, background: isIncome ? p.posSft : p.negSft, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                  <Icon d={isIncome ? 'M7 17L17 7M17 7H9M17 7v8' : 'M17 7L7 17M7 17h8M7 17V9'} color={col} size={16} sw={2} />
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: t.text, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{tx.label}</div>
                  <div style={{ fontSize: 11, color: t.textSec, marginTop: 1, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{tx.sub}</div>
                </div>
                <div style={{ textAlign: 'right', flexShrink: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: t.text, ...NUMS }}>
                    <span style={{ color: col }}>{isIncome ? '+' : '−'}</span>{tx.amount} €
                  </div>
                  <div style={{ fontSize: 10, color: t.textSec, marginTop: 1 }}>{tx.date}</div>
                </div>
              </div>
            </LongPressRow>);

        })}
      </div>

      {/* Monatsverlauf — drill into past months */}
      <div style={{ padding: '24px 20px 8px', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
        <div style={{ fontSize: 16, fontWeight: 600, color: t.text, letterSpacing: -0.3 }}>Monatsverlauf</div>
        <div style={{ fontSize: 11, color: t.textTer, fontWeight: 600 }}>Tippen für Analyse</div>
      </div>
      <div style={{ padding: '0 16px', display: 'flex', flexDirection: 'column', gap: 1 }}>
        {monthsRange.length === 0 &&
          <div style={{ padding: '20px 0', textAlign: 'center', color: t.textSec, fontSize: 13 }}>Noch keine Monate.</div>
        }
        {monthsRange.slice().reverse().map((mo, i, arr) => {
          const key = mo.key;
          const mAgg = fin_sumAgg(fin_txInMonth(transactions, key));
          const prof = mAgg.profit;
          const isCurrent = key === CURRENT_MONTH_KEY;
          return (
            <Pressable key={key} onClick={() => setMonthDetailKey(key)} scale={0.99}>
              <div style={{
                background: t.card, padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 12,
                borderTopLeftRadius: i === 0 ? 16 : 0, borderTopRightRadius: i === 0 ? 16 : 0,
                borderBottomLeftRadius: i === arr.length - 1 ? 16 : 0, borderBottomRightRadius: i === arr.length - 1 ? 16 : 0,
                borderBottom: i < arr.length - 1 ? `0.5px solid ${t.sep}` : 'none'
              }}>
                <div style={{ width: 40, height: 40, borderRadius: 11, background: isCurrent ? t.accentSoft : t.chip, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, flexDirection: 'column' }}>
                  <div style={{ fontSize: 10, color: isCurrent ? t.accent : t.textSec, fontWeight: 700, letterSpacing: 0.4, textTransform: 'uppercase' }}>{mo.short}</div>
                  <div style={{ fontSize: 11, color: isCurrent ? t.accent : t.text, fontWeight: 700, ...NUMS }}>{key.slice(2, 4)}</div>
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: t.text, display: 'flex', alignItems: 'center', gap: 6 }}>
                    {mo.label}
                    {isCurrent && <span style={{ fontSize: 9, fontWeight: 700, color: t.accent, background: t.accentSoft, padding: '1px 6px', borderRadius: 100, letterSpacing: 0.3 }}>JETZT</span>}
                  </div>
                  <div style={{ fontSize: 11, color: t.textSec, marginTop: 2, display: 'flex', gap: 10, ...NUMS }}>
                    <span><span style={{ color: p.pos, fontWeight: 700 }}>+{mAgg.income}</span> €</span>
                    <span><span style={{ color: p.neg, fontWeight: 700 }}>−{mAgg.expenses}</span> €</span>
                  </div>
                </div>
                <div style={{ textAlign: 'right', flexShrink: 0 }}>
                  <div style={{ fontSize: 15, fontWeight: 700, color: prof >= 0 ? p.pos : p.neg, ...NUMS }}>
                    {prof >= 0 ? '+' : ''}{prof.toLocaleString('de-DE')} €
                  </div>
                  <div style={{ fontSize: 10, color: t.textSec, marginTop: 1 }}>Netto</div>
                </div>
                <Icon d={icons.chev} color={t.textTer} size={14} sw={2} />
              </div>
            </Pressable>);

        })}
      </div>

      <AddTxSheet open={addOpen} onClose={() => setAddOpen(false)} onSave={onSaveTx} />
      <EditTxSheet tx={editingTx} onClose={() => setEditingTx(null)}
        onSave={(patch) => { saveTxEdit(editingTx.id, patch); setEditingTx(null); }}
        onDelete={() => { deleteTx(editingTx.id); setEditingTx(null); }} />
      <MonthDetailSheet open={!!monthDetailKey} monthKey={monthDetailKey}
        onClose={() => setMonthDetailKey(null)} t={t} p={p}
        transactions={transactions} monthsRange={monthsRange} />
    </div>);

}

Object.assign(window, { ScreenFinanzen });