/* Spocitaito.de — flow dashboard (German market variant)
   Parallel to /app.jsx. Kept as a separate file (not a shared i18n layer) so the
   CZ production app is never touched by this build — see de/README.md for the
   consolidation plan. */

const { useState, useMemo, useRef, useEffect, useCallback, useLayoutEffect } = React;

/* ---------- formatters ---------- */
const fmtEUR = (n) => {
  const sign = n < 0 ? '−' : '';
  const abs = Math.abs(Math.round(n));
  const s = abs.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
  return `${sign}${s} €`;
};
const fmtPct = (n) => `${n.toString().replace('.', ',')} %`;
const fmtInt = (n) => {
  const sign = n < 0 ? '−' : '';
  const abs = Math.abs(Math.round(n));
  return sign + abs.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
};

/* ---------- German AfA (building depreciation, §7 EStG) ---------- */
// Linear AfA on the building value only (land is never depreciated).
function afaRate(buildYear) {
  const y = parseInt(buildYear, 10);
  if (!isFinite(y)) return 0.02;
  if (y > 2022) return 0.03;   // completed after 31.12.2022
  if (y < 1925) return 0.025;  // completed before 1925
  return 0.02;                 // completed 1925–2022 (the common case)
}

/* ---------- default data ---------- */
const DEFAULT_PROPERTIES = [
  { id: 1, name: 'Wohnung Berlin-Mitte', rent: 950, buildYear: 1998, buildingValue: 140000,
    costs: { mortgage: 520, fund: 140, insurance: 18, propertyTax: 12, management: 65, reserve: 55, other: 0 } },
  { id: 2, name: 'Wohnung München-Schwabing', rent: 1450, buildYear: 2015, buildingValue: 260000,
    costs: { mortgage: 890, fund: 190, insurance: 24, propertyTax: 16, management: 85, reserve: 70, other: 0 } },
  { id: 3, name: 'Wohnung Hamburg-Altona', rent: 1150, buildYear: 1962, buildingValue: 175000,
    costs: { mortgage: 680, fund: 160, insurance: 20, propertyTax: 14, management: 75, reserve: 60, other: 0 } },
];

const COST_LABELS = {
  mortgage: 'Finanzierung (Kredit)',
  fund: 'Hausgeld (Rücklage)',
  insurance: 'Versicherung',
  propertyTax: 'Grundsteuer',
  management: 'Hausverwaltung',
  reserve: 'Instandhaltungsreserve',
  other: 'Sonstiges',
};
const COST_ORDER = ['mortgage', 'fund', 'insurance', 'propertyTax', 'management', 'reserve', 'other'];

const sumCosts = (costs) => COST_ORDER.reduce((a, k) => a + (costs[k] || 0), 0);

/* ---------- Logo ---------- */
function Logo() {
  return (
    <div className="logo">
      <span className="logo-a">Spocit</span>
      <span className="logo-ai">AI</span>
      <span className="logo-a">to</span>
      <span className="logo-cz">.de</span>
    </div>
  );
}

/* ---------- EditableValue ---------- */
function EditableValue({ value, onChange, suffix = '€', className = '', ariaLabel, raw = false }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(String(value));
  const inputRef = useRef(null);

  useEffect(() => {
    if (editing && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
    }
  }, [editing]);

  const commit = () => {
    const cleaned = draft.replace(/[^\d-]/g, '');
    const n = parseInt(cleaned, 10);
    if (!isNaN(n) && n !== value) onChange(n);
    setEditing(false);
  };

  if (editing) {
    return (
      <span className={`editable editing ${className}`}>
        <input
          ref={inputRef}
          className="edit-input"
          value={draft}
          onChange={(e) => setDraft(e.target.value)}
          onBlur={commit}
          onKeyDown={(e) => {
            if (e.key === 'Enter') commit();
            if (e.key === 'Escape') { setDraft(String(value)); setEditing(false); }
          }}
          aria-label={ariaLabel}
        />
        <span className="edit-suffix">{suffix}</span>
      </span>
    );
  }

  return (
    <button
      className={`editable ${className}`}
      onClick={() => { setDraft(String(value)); setEditing(true); }}
      aria-label={ariaLabel}
      type="button"
    >
      <span className="num">{raw ? value : fmtInt(value)}</span>
      <span className="num-suffix">{suffix}</span>
    </button>
  );
}

/* ---------- EditableText (name) ---------- */
function EditableText({ value, onChange, className = '' }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value);
  const inputRef = useRef(null);

  useEffect(() => {
    if (editing && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
    }
  }, [editing]);

  const commit = () => {
    const v = draft.trim();
    if (v && v !== value) onChange(v);
    setEditing(false);
  };

  if (editing) {
    return (
      <input
        ref={inputRef}
        className={`name-input ${className}`}
        value={draft}
        onChange={(e) => setDraft(e.target.value)}
        onBlur={commit}
        onKeyDown={(e) => {
          if (e.key === 'Enter') commit();
          if (e.key === 'Escape') { setDraft(value); setEditing(false); }
        }}
      />
    );
  }
  return (
    <button
      className={`name-btn ${className}`}
      onClick={() => { setDraft(value); setEditing(true); }}
      type="button"
    >
      {value}
    </button>
  );
}

/* ---------- PropertyCard ---------- */
function PropertyCard({ property, onUpdate, onRemove, viewMode, cardRef }) {
  const [expanded, setExpanded] = useState(false);

  const monthMul = viewMode === 'year' ? 12 : 1;
  const totalCosts = sumCosts(property.costs);
  const net = property.rent - totalCosts;
  const isPositive = net >= 0;
  const rate = afaRate(property.buildYear);
  const afaYear = (property.buildingValue || 0) * rate;

  const setRent = (v) => onUpdate({ ...property, rent: Math.max(0, v) });
  const setCost = (key, v) => onUpdate({ ...property, costs: { ...property.costs, [key]: Math.max(0, v) } });
  const setName = (v) => onUpdate({ ...property, name: v });
  const setBuildYear = (v) => onUpdate({ ...property, buildYear: Math.max(1800, Math.min(2100, v)) });
  const setBuildingValue = (v) => onUpdate({ ...property, buildingValue: Math.max(0, v) });

  return (
    <div className="card property-card" ref={cardRef}>
      <div className="card-head">
        <EditableText value={property.name} onChange={setName} />
        <button className="remove-btn" onClick={() => onRemove(property.id)} aria-label="Immobilie löschen" type="button">
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
            <path d="M3 3l8 8M11 3l-8 8" />
          </svg>
        </button>
      </div>

      <div className="row rent-row">
        <span className="row-label">Kaltmiete (monatlich)</span>
        <EditableValue value={property.rent * monthMul} onChange={(v) => setRent(Math.round(v / monthMul))} ariaLabel="Kaltmiete" />
      </div>

      <div className="divider" />

      <button className="costs-toggle" onClick={() => setExpanded(!expanded)} type="button" aria-expanded={expanded}>
        <span className="row-label">Kosten</span>
        <span className="costs-toggle-right">
          {!expanded && <span className="num costs-collapsed">{fmtEUR(totalCosts * monthMul)}</span>}
          <svg className={`chevron ${expanded ? 'open' : ''}`} width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
            <path d="M3 5l3 3 3-3" />
          </svg>
        </span>
      </button>

      {expanded && (
        <div className="costs-list">
          {COST_ORDER.map((k) => (
            <div className="row cost-row" key={k}>
              <span className="cost-label">{COST_LABELS[k]}</span>
              <EditableValue
                value={property.costs[k] * monthMul}
                onChange={(v) => setCost(k, Math.round(v / monthMul))}
                ariaLabel={COST_LABELS[k]}
                className="muted"
              />
            </div>
          ))}
          <div className="row cost-total">
            <span className="row-label">Kosten gesamt</span>
            <span className="num">{fmtEUR(totalCosts * monthMul)}</span>
          </div>
          <div className="divider" />
          <div className="row cost-row">
            <span className="cost-label" title="Baujahr des Gebäudes — bestimmt den AfA-Satz nach §7 EStG">Baujahr</span>
            <EditableValue value={property.buildYear} onChange={setBuildYear} ariaLabel="Baujahr" suffix="" raw className="muted" />
          </div>
          <div className="row cost-row">
            <span className="cost-label" title="Gebäudewert ohne Grundstücksanteil — Basis für die AfA">Gebäudewert (ohne Grundstück)</span>
            <EditableValue value={property.buildingValue} onChange={setBuildingValue} ariaLabel="Gebäudewert" className="muted" />
          </div>
          <div className="row cost-row">
            <span className="cost-label">AfA ({(rate * 100).toFixed(1).replace('.', ',')} % / Jahr)</span>
            <span className="num muted">{fmtEUR(afaYear)}&nbsp;/&nbsp;Jahr</span>
          </div>
        </div>
      )}

      <div className="card-foot">
        <span className="foot-label">Netto-Ertrag</span>
        <span className={`net-value ${isPositive ? 'pos' : 'neg'}`}>
          {isPositive ? '+' : ''}{fmtEUR(net * monthMul)}
        </span>
      </div>
    </div>
  );
}

/* ---------- AddCard ---------- */
function AddCard({ onAdd }) {
  return (
    <button className="card add-card" onClick={onAdd} type="button">
      <span className="add-icon" aria-hidden="true">
        <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
          <path d="M10 4v12M4 10h12" />
        </svg>
      </span>
      <span className="add-label">Immobilie hinzufügen</span>
      <span className="add-hint">Neue Wohnung oder Haus</span>
    </button>
  );
}

/* ---------- FlowLines ---------- */
function FlowLines({ anchors, summaryAnchor, properties, viewMode, height }) {
  if (!anchors.length || !summaryAnchor) return null;

  const monthMul = viewMode === 'year' ? 12 : 1;
  const maxAbs = Math.max(...anchors.map(a => Math.abs(a.net)), 1);

  return (
    <svg className="flow-svg" width="100%" height={height} aria-hidden="true">
      <defs>
        <filter id="dot-glow-pos" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur stdDeviation="2" result="blur"/>
          <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
      </defs>
      {anchors.map((a, i) => {
        const isPos = a.net >= 0;
        const stroke = isPos ? 'var(--green-500)' : 'var(--red-500)';
        const strokeBg = isPos ? 'var(--green-100)' : 'var(--red-100)';
        const thickness = 2 + (Math.abs(a.net) / maxAbs) * 3;
        const sx = a.x, sy = a.y;
        const ex = summaryAnchor.x, ey = summaryAnchor.y;
        const midY = sy + (ey - sy) * 0.55;
        const d = `M ${sx} ${sy} C ${sx} ${midY}, ${ex} ${midY}, ${ex} ${ey}`;
        const lx = sx + (ex - sx) * 0.5;
        const ly = sy + (ey - sy) * 0.5 - 8;
        const dur = 2.6 + (i % 3) * 0.4;
        const delay = i * 0.35;

        return (
          <g key={a.id}>
            <path d={d} stroke={strokeBg} strokeWidth={thickness} fill="none" strokeLinecap="round" />
            <path
              d={d}
              stroke={stroke}
              strokeWidth={thickness}
              fill="none"
              strokeLinecap="round"
              strokeDasharray="6 10"
              className="flow-dashes"
              style={{ animationDuration: `${dur}s`, animationDelay: `${delay}s` }}
            />
            <circle r={thickness + 1.5} fill={stroke} className="flow-dot" filter="url(#dot-glow-pos)">
              <animateMotion dur={`${dur}s`} repeatCount="indefinite" begin={`${delay}s`} path={d} rotate="auto" />
            </circle>
            <g transform={`translate(${lx}, ${ly})`}>
              <rect x="-44" y="-12" width="88" height="22" rx="11" className="flow-label-bg" fill="white" stroke={isPos ? 'var(--green-200)' : 'var(--red-200)'} />
              <text className="flow-label-text" x="0" y="3" textAnchor="middle" fill={isPos ? 'var(--green-700)' : 'var(--red-500)'}>
                {a.net >= 0 ? '+' : ''}{fmtEUR(a.net * monthMul)}
              </text>
            </g>
          </g>
        );
      })}
    </svg>
  );
}

/* ---------- SummaryBlock ---------- */
function SummaryBlock({ properties, viewMode, taxEnabled, marginalRatePct, summaryRef }) {
  const monthMul = viewMode === 'year' ? 12 : 1;
  const grossMonth = properties.reduce((a, p) => a + p.rent, 0);
  const costsMonth = properties.reduce((a, p) => a + sumCosts(p.costs), 0);
  const netMonth = grossMonth - costsMonth;
  const netYear = netMonth * 12;
  const netView = netMonth * monthMul;

  const afaYearTotal = properties.reduce((a, p) => a + (p.buildingValue || 0) * afaRate(p.buildYear), 0);
  const afaMonth = afaYearTotal / 12;
  const taxableBase = netMonth - afaMonth; // Werbungskosten already in costsMonth; AfA is a non-cash deduction on top
  const rate = Math.max(0, Math.min(100, marginalRatePct)) / 100;
  const tax = taxEnabled ? Math.max(0, taxableBase) * rate : 0;
  const afterTax = netMonth - tax; // AfA reduces tax owed, not real cashflow

  return (
    <div className="summary" ref={summaryRef}>
      <div className="summary-accent" />
      <div className="summary-inner">
        <div className="summary-head">
          <span className="caption">Ihre Tasche</span>
          <h2 className="summary-title">Übersicht {properties.length} {properties.length === 1 ? 'Immobilie' : 'Immobilien'}</h2>
        </div>

        <div className="summary-grid">
          <div className="kv">
            <span className="kv-label">Bruttoeinnahmen</span>
            <span className="kv-value num">{fmtEUR(grossMonth * monthMul)}</span>
          </div>
          <div className="kv">
            <span className="kv-label">Kosten gesamt</span>
            <span className="kv-value num">{fmtEUR(costsMonth * monthMul)}</span>
          </div>
          <div className="kv">
            <span className="kv-label">Marge</span>
            <span className="kv-value num">{grossMonth > 0 ? fmtPct(((netMonth / grossMonth) * 100).toFixed(1)) : '—'}</span>
          </div>
        </div>

        <div className={`summary-hero ${netMonth >= 0 ? 'pos' : 'neg'}`}>
          <div className="hero-top">
            <span className="caption">Netto-Ertrag</span>
            <span className="hero-view-mode">{viewMode === 'year' ? 'Jahresansicht' : 'Monatsansicht'}</span>
          </div>
          <div className="hero-num">
            <span className={`hero-value num ${netMonth >= 0 ? 'pos' : 'neg'}`}>
              {netMonth >= 0 ? '+' : ''}{fmtEUR(netView)}
            </span>
          </div>
          <div className="hero-sub">
            <span className="num">{fmtEUR(netYear)}</span> pro Jahr
            <span className="dot-sep">·</span>
            <span className="num">{fmtEUR(netMonth)}</span> / Monat
          </div>
        </div>

        {taxEnabled && (
          <div className="tax-block">
            <div className="kv tax-row">
              <span className="kv-label">AfA-Abschreibung (§7 EStG)</span>
              <span className="kv-value num muted">−{fmtEUR(afaMonth * monthMul).replace('−','')}</span>
            </div>
            <div className="kv tax-row">
              <span className="kv-label">Einkommensteuer ({marginalRatePct} %)</span>
              <span className="kv-value num neg">−{fmtEUR(tax * monthMul).replace('−','')}</span>
            </div>
            {taxableBase <= 0 && (
              <p className="hint" style={{ margin: '2px 0 8px', fontSize: '12px', color: 'var(--text-muted)' }}>
                Kein zu versteuerndes Einkommen — die AfA übersteigt den Netto-Ertrag (steuerlicher Verlust, {fmtEUR(taxableBase * monthMul)}).
              </p>
            )}
            <div className="kv tax-row">
              <span className="kv-label kv-label-strong">Nach Steuern</span>
              <span className="kv-value num strong">{fmtEUR(afterTax * monthMul)}</span>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

/* ---------- Toast ---------- */
function Toast({ message, onUndo, onClose }) {
  useEffect(() => {
    const t = setTimeout(onClose, 5000);
    return () => clearTimeout(t);
  }, [onClose]);
  return (
    <div className="toast" role="status">
      <span>{message}</span>
      <button className="toast-undo" onClick={onUndo} type="button">Rückgängig</button>
    </div>
  );
}

/* ---------- Dashboard page ---------- */
function DashboardPage({ properties, setProperties, viewMode, taxEnabled, marginalRatePct, addProperty, removeProperty, updateProperty, totals }) {
  const cardRefs = useRef({});
  const summaryRef = useRef(null);
  const stageRef = useRef(null);
  const [anchors, setAnchors] = useState([]);
  const [summaryAnchor, setSummaryAnchor] = useState(null);
  const [stageHeight, setStageHeight] = useState(420);

  const measure = useCallback(() => {
    if (!stageRef.current) return;
    const stageRect = stageRef.current.getBoundingClientRect();
    const next = [];
    for (const p of properties) {
      const el = cardRefs.current[p.id];
      if (!el) continue;
      const r = el.getBoundingClientRect();
      next.push({
        id: p.id,
        x: r.left - stageRect.left + r.width / 2,
        y: r.bottom - stageRect.top,
        net: p.rent - sumCosts(p.costs),
      });
    }
    setAnchors(prev => {
      if (prev.length !== next.length) return next;
      for (let i = 0; i < prev.length; i++) {
        const a = prev[i], b = next[i];
        if (a.id !== b.id || Math.abs(a.x - b.x) > 0.5 || Math.abs(a.y - b.y) > 0.5 || a.net !== b.net) return next;
      }
      return prev;
    });
    if (summaryRef.current) {
      const r = summaryRef.current.getBoundingClientRect();
      const sx = r.left - stageRect.left + r.width / 2;
      const sy = r.top - stageRect.top;
      const h = r.bottom - stageRect.top + 4;
      setSummaryAnchor(prev => (prev && Math.abs(prev.x - sx) < 0.5 && Math.abs(prev.y - sy) < 0.5) ? prev : { x: sx, y: sy });
      setStageHeight(prev => Math.abs(prev - h) < 0.5 ? prev : h);
    }
  }, [properties]);

  useLayoutEffect(() => { measure(); }, [measure]);
  useEffect(() => {
    let raf = 0;
    const schedule = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => measure());
    };
    window.addEventListener('resize', schedule);
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(schedule);
    const interval = setInterval(schedule, 500);
    return () => { cancelAnimationFrame(raf); clearInterval(interval); window.removeEventListener('resize', schedule); };
  }, [measure]);

  return (
    <>
      <div className="page-toolbar">
        <div className="toolbar-left">
          <h1 className="page-title">Ihr Portfolio</h1>
          <span className="page-sub">{properties.length} {properties.length === 1 ? 'Immobilie' : 'Immobilien'} · netto {viewMode === 'year' ? 'jährlich' : 'monatlich'} <span className={`num ${totals.net >= 0 ? 'pos' : 'neg'}`}>{totals.net >= 0 ? '+' : ''}{fmtEUR(totals.net * (viewMode === 'year' ? 12 : 1))}</span></span>
        </div>
        <div className="toolbar-right">
          <button className="btn btn-primary" onClick={addProperty} type="button">
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M7 2v10M2 7h10"/></svg>
            Immobilie hinzufügen
          </button>
        </div>
      </div>

      <div className="stage" ref={stageRef} style={{ minHeight: stageHeight }}>
        <FlowLines anchors={anchors} summaryAnchor={summaryAnchor} properties={properties} viewMode={viewMode} height={stageHeight} />
        <div className="cards-row">
          {properties.map((p) => (
            <PropertyCard
              key={p.id}
              property={p}
              onUpdate={updateProperty}
              onRemove={removeProperty}
              viewMode={viewMode}
              cardRef={(el) => { if (el) cardRefs.current[p.id] = el; else delete cardRefs.current[p.id]; }}
            />
          ))}
          <AddCard onAdd={addProperty} />
        </div>
        <SummaryBlock properties={properties} viewMode={viewMode} taxEnabled={taxEnabled} marginalRatePct={marginalRatePct} summaryRef={summaryRef} />
      </div>
    </>
  );
}

/* ---------- App ---------- */
function App(props) {
  const ext = props && props.externalProperties !== undefined;
  const [internalProperties, setInternalProperties] = useState(DEFAULT_PROPERTIES);
  const properties = ext ? props.externalProperties : internalProperties;
  const setProperties = ext ? props.externalSetProperties : setInternalProperties;
  const [viewMode, setViewMode] = useState('month');
  const [taxEnabled, setTaxEnabled] = useState(true);
  const [marginalRatePct, setMarginalRatePct] = useState(30);
  const [removed, setRemoved] = useState(null);
  const [nextId, setNextId] = useState(4);

  const updateProperty = ext
    ? props.externalUpdateProperty
    : (p) => setProperties(prev => prev.map(x => x.id === p.id ? p : x));
  const removeProperty = ext
    ? props.externalRemoveProperty
    : (id) => {
        const idx = properties.findIndex(p => p.id === id);
        if (idx < 0) return;
        setRemoved({ property: properties[idx], index: idx });
        setProperties(prev => prev.filter(p => p.id !== id));
      };
  const undoRemove = () => {
    if (!removed) return;
    setProperties(prev => {
      const next = [...prev];
      next.splice(removed.index, 0, removed.property);
      return next;
    });
    setRemoved(null);
  };
  const addProperty = ext
    ? props.externalAddProperty
    : () => {
        const id = nextId;
        setNextId(id + 1);
        setProperties(prev => [...prev, {
          id,
          name: `Neue Immobilie ${prev.length + 1}`,
          rent: 1000,
          buildYear: 2000,
          buildingValue: 150000,
          costs: { mortgage: 600, fund: 150, insurance: 20, propertyTax: 14, management: 70, reserve: 55, other: 0 },
        }]);
      };

  const totals = useMemo(() => {
    const gross = properties.reduce((a, p) => a + p.rent, 0);
    const costs = properties.reduce((a, p) => a + sumCosts(p.costs), 0);
    return { gross, costs, net: gross - costs };
  }, [properties]);

  return (
    <div className="app">
      <header className="header">
        <div className="container header-inner">
          <a href="/de/" className="logo-link"><Logo /></a>
          <nav className="header-nav">
            <span className="nav-link active">Übersicht</span>
            <a className="nav-link" href="najemnici.html">Mieter &amp; Zahlungen</a>
            <a className="nav-link" href="/">🇨🇿 Čeština</a>
          </nav>
          <div className="header-right">
            <div className="view-toggle" role="tablist" aria-label="Ansicht">
              <button className={viewMode === 'month' ? 'active' : ''} onClick={() => setViewMode('month')} type="button">Monatlich</button>
              <button className={viewMode === 'year' ? 'active' : ''} onClick={() => setViewMode('year')} type="button">Jährlich</button>
            </div>
            <div className="plan-badge">
              <span className="plan-dot" />
              Demo
            </div>
            <div className="avatar" aria-label="Konto">DE</div>
          </div>
        </div>
      </header>

      <div className="subheader">
        <div className="container subheader-inner">
          <div className="subhead-route-tag">Flow-Übersicht</div>
          <div className="subhead-right">
            <label className="select-wrap" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
              <input type="checkbox" checked={taxEnabled} onChange={(e) => setTaxEnabled(e.target.checked)} id="taxToggle" />
              <span className="caption">Steuer berücksichtigen</span>
            </label>
            {taxEnabled && (
              <label className="select-wrap" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
                <span className="caption">Grenzsteuersatz</span>
                <input
                  type="number"
                  min="0"
                  max="45"
                  step="1"
                  value={marginalRatePct}
                  onChange={(e) => setMarginalRatePct(Math.max(0, Math.min(45, parseInt(e.target.value, 10) || 0)))}
                  style={{ width: '56px', padding: '4px 6px', border: '1px solid var(--border)', borderRadius: '6px' }}
                  aria-label="Persönlicher Grenzsteuersatz in Prozent"
                />
                <span className="caption">%</span>
              </label>
            )}
          </div>
        </div>
      </div>

      <main className="main">
        <div className="container">
          <DashboardPage
            properties={properties}
            setProperties={setProperties}
            viewMode={viewMode}
            taxEnabled={taxEnabled}
            marginalRatePct={marginalRatePct}
            addProperty={addProperty}
            removeProperty={removeProperty}
            updateProperty={updateProperty}
            totals={totals}
          />
        </div>
      </main>

      <footer className="footer">
        <div className="container footer-inner">
          <Logo />
          <span className="footer-meta">Was bringt Ihre Vermietung wirklich? · v0.1 DE-Demo</span>
        </div>
      </footer>

      {removed && <Toast message={`Gelöscht: ${removed.property.name}`} onUndo={undoRemove} onClose={() => setRemoved(null)} />}
    </div>
  );
}

Object.assign(window, {
  fmtEUR, fmtPct, fmtInt, sumCosts, afaRate, COST_LABELS, COST_ORDER,
  App,
});
