PageSourceSearch

https://brainmotion.ai/assets/Lohn-CfKMrOJk.js

js brainmotion.ai collected 2026-10-05 15:29:50 UTC 44,983 bytes, 425 lines download raw bytes

1import{j as n,b as nt,c as st,e as rt,s as E,aW as it,X as at,Y as ot,bl as lt,aD as ct,br as Be,cF as dt,_ as ht,aj as ut,n as gt,M as pt,w as bt,d as i}from"./index-D64xVk13.js";import{r as x,L as He}from"./vendor-BFTzQMpF.js";import{P as mt}from"./PageLoadingSkeleton-D6HkdxlU.js";import{V as ft,u as xt,c as vt,f as Ct,g as kt}from"./VaultLockCard-CdjVe6Wy.js";import{u as _t}from"./useTaxProfile-spz7T2GL.js";import{g as wt}from"./pdfWorker-ah5aZAt9.js";import{t as Ee,b as yt}from"./incomeTax-D7M5ME9V.js";import{e as At,s as jt,a as zt,c as $t,t as St}from"./doppelterHaushalt-BNNSpmkC.js";import{M as Bt}from"./index-DYoZ3bT4.js";import{r as Et}from"./index-B3d5vJU4.js";import"./animations-Ch79rzwJ.js";import"./activityYear-BYsymiTO.js";const Mt=8;function Dt(e){const s=new Map;for(const a of e){if(!a.str.trim())continue;const c=Math.round(a.y/2)*2,d=s.get(c)??[];d.push(a),s.set(c,d)}return[...s.entries()].sort((a,c)=>c[0]-a[0]).map(([,a])=>{const c=a.sort((f,u)=>f.x-u.x);let d="",r=null;return c.forEach((f,u)=>{u>0&&(d+=r!==null&&f.x-r<Mt?" ":"  "),d+=f.str.trim(),r=f.w!==void 0?f.x+f.w:null}),d})}async function Tt(e){const s=await wt({data:new Uint8Array(e.slice(0))}).promise,a=[];for(let c=1;c<=s.numPages;c++){const r=await(await s.getPage(c)).getTextContent(),f=[];for(const u of r.items)"str"in u&&f.push({str:u.str,x:u.transform[4],y:u.transform[5],w:u.width});a.push(...Dt(f))}return await s.cleanup(),a}async function Ft(e){const s=await crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(s)].map(a=>a.toString(16).padStart(2,"0")).join("")}const Lt={januar:1,februar:2,märz:3,maerz:3,april:4,mai:5,juni:6,juli:7,august:8,september:9,oktober:10,november:11,dezember:12},Pt=/-?\d{1,3}(?:\.\d{3})*,\d{2}-?/g;function Rt(e){const s=e.startsWith("-")||e.endsWith("-"),a=e.replace(/-/g,"").replace(/\./g,"").replace(",","."),c=Math.round(parseFloat(a)*100);return s?-c:c}const me=e=>{const[s,a,c]=e.split(".");return`${c}-${a}-${s}`};function Kt(e){return(e.match(Pt)||[]).map(Rt)}const Nt=[{key:"brutto",re:/^Gesamtbrutto/i},{key:"steuerBruttoCents",re:/^Steuer-Brutto/i},{key:"lohnsteuerCents",re:/^Lohnsteuer/i},{key:"soliCents",re:/^(Solidarit|SolZ|Soli\b)/i},{key:"kircheCents",re:/^Kirchenst/i},{key:"rvAnCents",re:/^Rentenvers/i},{key:"avAnCents",re:/^Arbeitslosenvers/i},{key:"kvAnCents",re:/^Krankenvers/i},{key:"pvAnCents",re:/^Pflegevers/i},{key:"kvAgZuschussCents",re:/^AG-Zuschuss\s+KV/i},{key:"pvAgZuschussCents",re:/^AG-Zuschuss\s+PV/i},{key:"kvAbgefuehrtCents",re:/^Abgef\.?\s+Beitrag\s+frei\.?\s+KV/i,abs:!0},{key:"pvAbgefuehrtCents",re:/^Abgef\.?\s+Beitrag\s+frei\.?\s+PV/i,abs:!0},{key:"netto",re:/^Gesetzl\.?\s*Netto/i},{key:"auszahlung",re:/^Überweisung/i},{key:"reisekosten",re:/^Reisekosten/i}];class de extends Error{}function Wt(e){const s=e.join(`
2`),a=e.map(v=>v.replace(/\s+/g," ").trim()),c=s.match(/Entgeltabrechnung\s+für\s+([A-Za-zÄÖÜäöü]+)\s+(\d{4})/);if(!c)throw new de('Kein Abrechnungsmonat gefunden („Entgeltabrechnung für …").');const d=Lt[c[1].toLowerCase()];if(!d)throw new de(`Unbekannter Monat „${c[1]}".`);const r=`${c[2]}-${String(d).padStart(2,"0")}-01`,f=s.match(/Datum:\s*(\d{2}\.\d{2}\.\d{4})/),u=s.match(/Eintritt\s+Unternehmen:\s*(\d{2}\.\d{2}\.\d{4})/)||s.match(/Ein\/Austritt:\s*(\d{2}\.\d{2}\.\d{4})/),w=s.match(/LStKl\.:\s*(\d)/),z=e.find(v=>/Abs\.:/.test(v))?.match(/Abs\.:\s+(.+?)(?:\s{2,}|$)/)?.[1]?.trim()||"Arbeitgeber",L={},A={};for(const v of a){const $=Nt.find(N=>N.re.test(v));if(!$)continue;const R=Kt(v);if(R.length===0)continue;const K=N=>$.abs?Math.abs(N):N;L[$.key]=(L[$.key]??0)+K(R[0]),R.length>=2&&(A[$.key]=(A[$.key]??0)+K(R[R.length-1]))}const p=v=>L[v]??0,k=v=>
2A[v]??0,H=p("brutto")||p("steuerBruttoCents");if(!H)throw new de("Kein Bruttoentgelt gefunden.");const b=s.match(/Zeitnachweis\s+vom\s+(\d{2}\.\d{2}\.\d{4})/),P=b?me(b[1]).slice(0,7):null,M=[];if(P)for(const v of a){const $=v.match(/^(\d{2})\s+(Mo|Di|Mi|Do|Fr|Sa|So)\s+\d{2}:\d{2}\s+\d{2}:\d{2}/);$&&M.push(`${P}-${$[1]}`)}const T=s.match(/Stand\s+Ende\s+lfd\.\s+Monat\s+(-?\d+,\d+)/)||s.match(/Freizeitkto:\s*(-?\d+,\d+)/),_=s.match(/Resturl\.:\s*(-?\d+,\d+)/),m={employer:z,period:r,issuedOn:f?me(f[1]):null,entryDate:u?me(u[1]):null,steuerklasse:w?w[1]:null,bruttoCents:H,steuerBruttoCents:p("steuerBruttoCents")||H,lohnsteuerCents:p("lohnsteuerCents"),soliCents:p("soliCents"),kircheCents:p("kircheCents"),rvAnCents:p("rvAnCents"),avAnCents:p("avAnCents"),kvAnCents:p("kvAnCents"),pvAnCents:p("pvAnCents"),kvAbgefuehrtCents:p("kvAbgefuehrtCents"),pvAbgefuehrtCents:p("pvAbgefuehrtCents"),kvAgZuschussCents:p("kvAgZuschussCents"),pvAgZuschussCents:p("pvAgZuschussCents"),nettoCents:p("netto"),auszahlungCents:p("auszahlung"),reisekostenFreiCents:Math.max(0,p("reisekosten")),ytd:{steuerBruttoCents:k("steuerBruttoCents")||k("brutto"),lohnsteuerCents:k("lohnsteuerCents"),soliCents:k("soliCents"),kircheCents:k("kircheCents"),rvAnCents:k("rvAnCents"),avAnCents:k("avAnCents"),kvAnCents:k("kvAnCents"),pvAnCents:k("pvAnCents"),kvAbgefuehrtCents:k("kvAbgefuehrtCents"),pvAbgefuehrtCents:k("pvAbgefuehrtCents"),kvAgZuschussCents:k("kvAgZuschussCents"),pvAgZuschussCents:k("pvAgZuschussCents")},timeSheetMonth:P,officeDays:M,hoursBalance:T?parseFloat(T[1].replace(",",".")):null,vacationLeft:_?parseFloat(_[1].replace(",",".")):null,warnings:[]};if(m.nettoCents){const v=m.steuerBruttoCents-m.lohnsteuerCents-m.soliCents-m.kircheCents-m.rvAnCents-m.avAnCents-m.kvAnCents-m.pvAnCents;Math.abs(v-m.nettoCents)>100&&m.warnings.push("Die Rechenprobe (Brutto − Abzüge = Netto) geht nicht auf. Bitte die übernommenen Beträge mit der Abrechnung vergleichen.")}return m.ytd.steuerBruttoCents||m.warnings.push("Keine Jahreswerte gefunden — für die Jahressumme zählen dann nur die Monatsbeträge."),m}function Zt(e){return{employer:e.employer,period:e.period,issued_on:e.issuedOn,entry_date:e.entryDate,steuerklasse:e.steuerklasse,brutto_cents:e.bruttoCents,steuer_brutto_cents:e.steuerBruttoCents,lohnsteuer_cents:e.lohnsteuerCents,soli_cents:e.soliCents,kirche_cents:e.kircheCents,rv_an_cents:e.rvAnCents,av_an_cents:e.avAnCents,kv_an_cents:e.kvAnCents,pv_an_cents:e.pvAnCents,kv_abgefuehrt_cents:e.kvAbgefuehrtCents,pv_abgefuehrt_cents:e.pvAbgefuehrtCents,kv_ag_zuschuss_cents:e.kvAgZuschussCents,pv_ag_zuschuss_cents:e.pvAgZuschussCents,netto_cents:e.nettoCents,auszahlung_cents:e.auszahlungCents,reisekosten_frei_cents:e.reisekostenFreiCents,ytd_steuer_brutto_cents:e.ytd.steuerBruttoCents,ytd_lohnsteuer_cents:e.ytd.lohnsteuerCents,ytd_soli_cents:e.ytd.soliCents,ytd_kirche_cents:e.ytd.kircheCents,ytd_rv_an_cents:e.ytd.rvAnCents,ytd_av_an_cents:e.ytd.avAnCents,ytd_kv_an_cents:e.ytd.kvAnCents,ytd_pv_an_cents:e.ytd.pvAnCents,ytd_kv_abgefuehrt_cents:e.ytd.kvAbgefuehrtCents,ytd_pv_abgefuehrt_cents:e.ytd.pvAbgefuehrtCents,ytd_kv_ag_zuschuss_cents:e.ytd.kvAgZuschussCents,ytd_pv_ag_zuschuss_cents:e.ytd.pvAgZuschussCents,time_sheet_month:e.timeSheetMonth,office_days:e.officeDays,hours_balance:e.hoursBalance,vacation_left:e.vacationLeft}}const Oe=.96;function Gt(e){const s=(d,r)=>d||r,a=s(e.ytd_kv_an_cents,e.kv_an_cents)+Math.max(0,s(e.ytd_kv_abgefuehrt_cents,e.kv_abgefuehrt_cents)-s(e.ytd_kv_ag_zuschuss_cents,e.kv_ag_zuschuss_cents)),c=s(e.ytd_pv_an_cents,e.pv_an_cents)+Math.max(0,s(e.ytd_pv_abgefuehrt_cents,e.pv_abgefuehrt_cents)-s(e.ytd_pv_ag_zuschuss_cents,e.pv_ag_zuschuss_cents));return{bruttoarbeitslohnCents:s(e.ytd_steuer_brutto_cents,e.steuer_brutto_cents),lohnsteuerCents:s(e.ytd_lohnsteuer_cents,e.lohnsteuer_cents),soliCents:s(e.ytd_soli_cents,e.soli_cents),kircheCents:s(e.ytd_kirche_cents,e.kirche_cents),rvAnCents:s(e.ytd_rv_an_cents,e.rv_an_cents),avAnCents:s(e.ytd_av_an_cents,e.av_an_cents),kvPvBasisCents:Math.round(a*Oe)+c}}function Je(e){const s=e.kv_an_cents+Math.max(0,e.kv_abgefuehrt_cents-e.kv_ag_zuschuss_cents),a=e.pv_an_cents+Math.max(0,e.pv_abgefuehrt_cents-e.pv_ag_zuschuss_cents);return{bruttoarbeitslohnCents:e.steuer_brutto_cents,lohnsteuerCents:e.lohnsteuer_cents,soliCents:e.soli_cents,kircheCents:e.kirche_cents,rvAnCents:e.rv_an_cents,avAnCents:e.av_an_cents,kvPvBasisCents:Math.round(s*Oe)+a}}function he(e,s,a=1){return{bruttoarbeitslohnCents:e.bruttoarbeitslohnCents+s.bruttoarbeitslohnCents*a,lohnsteuerCents:e.lohnsteuerCents+s.lohnsteuerCents*a,soliCents:e.soliCents+s.soliCents*a,kircheCents:e.kircheCents+s.kircheCents
2*a,rvAnCents:e.rvAnCents+s.rvAnCents*a,avAnCents:e.avAnCents+s.avAnCents*a,kvPvBasisCents:e.kvPvBasisCents+s.kvPvBasisCents*a}}const Ce={bruttoarbeitslohnCents:0,lohnsteuerCents:0,soliCents:0,kircheCents:0,rvAnCents:0,avAnCents:0,kvPvBasisCents:0};function Ht(e){return he(Ce,Je(e),12)}function Ot(e,s){const a=e.filter(d=>d.period.startsWith(String(s))),c=new Map;for(const d of a){const r=c.get(d.employer)??[];r.push(d),c.set(d.employer,r)}return[...c.entries()].map(([d,r])=>{const f=[...r].sort((A,p)=>A.period.localeCompare(p.period)),u=f[f.length-1],w=Gt(u),z=12-Number(u.period.slice(5,7)),L=[...new Set(f.flatMap(A=>A.office_days||[]))].filter(A=>A.startsWith(String(s))).sort();return{employer:d,slips:f,latest:u,months:f.map(A=>A.period.slice(0,7)),bisher:w,prognose:he(w,Je(u),z),restMonate:z,officeDays:L}})}function Me(e,s){return e.reduce((a,c)=>he(a,c[s]),Ce)}const Y=38,De=45e4,Jt=6e4,Te={2026:1014e4},Fe=1600,j=e=>`${Math.round(e/100).toLocaleString("de-DE")} €`,X=e=>`${e.slice(8,10)}.${e.slice(5,7)}.${e.slice(0,4)}`,Le={warnung:0,hinweis:1,info:2},Pe=new Set(["lohn-haushalt-rolle"]);function Re(e,s,a,c){return yt({year:e,profile:s,gewinnCents:0,bruttoarbeitslohnCents:a.bruttoarbeitslohnCents,werbungskostenCents:c,lohnsteuerCents:a.lohnsteuerCents,lohnSoliCents:a.soliCents,lohnKircheCents:a.kircheCents,vorsorge:{altersvorsorgeCents:a.rvAnCents,kvPvBasisCents:a.kvPvBasisCents,sonstigeVorsorgeCents:a.avAnCents},sonderausgabenCents:0})}const G=(e,s)=>Math.round(e*s/100);function It(e){const{year:s,todayYmd:a,profile:c,employers:d,haushalt:r}=e,f=Me(d,"prognose"),u=Me(d,"bisher"),w=d.reduce((C,S)=>C+S.officeDays.length,0),F=Math.floor(Math.max(0,c.arbeitsweg_km||0)),z=Math.min(De,w*F*Y),L=r&&r.role==="angestellt"?r.totalCents:0,A=z+L,p=Re(s,c,f,A),k=p.grenzsteuersatzPct,H=d.reduce((C,S)=>he(C,Ht(S.latest)),Ce),b=s+1,P=Ee(b).year,M=d.length?Re(P,c,H,0):null,T=M?.grenzsteuersatzPct??k,_=[];if(d.length===0)return{prognose:f,bisher:u,werbungskostenCents:A,arbeitswegCents:z,officeDays:w,estimate:p,vollesJahr:M,tips:_};const m=d.map(C=>C.latest).sort((C,S)=>S.period.localeCompare(C.period))[0],v=m.entry_date&&m.entry_date.startsWith(String(s))?m.entry_date:null;if(p.ergebnisCents>1e4&&_.push({id:"lohn-erstattung",level:"hinweis",title:`Voraussichtlich rund ${j(p.ergebnisCents)} Lohnsteuer zurück für ${s}`,detail:(v?`Der Arbeitgeber rechnet die monatliche Lohnsteuer so, als würdest du das ganze Jahr ${j(m.steuer_brutto_cents)} im Monat verdienen. Seit dem Eintritt am ${X(v)} sind es aber nur ein paar Monate — über das Jahr liegt dein Steuersatz deutlich niedriger. `:"")+`Hochgerechnet werden ${j(f.lohnsteuerCents)} einbehalten, die Steuer auf den Lohn beträgt aber nur etwa ${j(p.gesamtCents)}. Das Geld kommt nur über die Steuererklärung zurück. Gerechnet ohne den Gewinn aus Brainmotion — die Gesamtrechnung steht im Jahresabschluss.`,href:`/crm/steuerjahr/${s}`,amountCents:p.ergebnisCents}),r&&r.role==="selbststaendig"&&_.push({id:"lohn-haushalt-rolle",level:"warnung",title:"Doppelte Haushaltsführung als Anstellung führen",detail:`Die Zweitwohnung ist als Betriebsausgabe der Selbstständigkeit hinterlegt. Bezogen hast du sie am ${X(r.movedInOn)} — `+(v?`nach dem Eintritt bei ${m.employer} am ${X(v)}. `:"während der Anstellung. ")+'Beruflich veranlasst ist sie dann durch die Anstellung: Die Kosten sind Werbungskosten in der Anlage N, nicht Betriebsausgaben. Das Finanzamt fragt genau das ab („Anlass der doppelten Haushaltsführung"). Umstellen unter „Stammdaten" in der doppelten Haushaltsführung.',href:"/crm/doppelter-haushalt",amountCents:r.totalCents}),r&&!r.mealExpired&&r.mealMissingDays>0&&_.push({id:"lohn-verpflegung",level:"warnung",title:`${r.mealMissingDays} Tage Verpflegungspauschale noch nicht erfasst — bis zu ${j(r.mealMissingCents)}`,detail:`In den ersten drei Monaten an der Zweitwohnung gibt es 28 € je vollem Tag und 14 € für An- und Abreisetage. Die Frist endet am ${X(r.mealDeadline)}. Erfasst ist noch kein einziger Tag. Nachtragen geht jederzeit — aber je näher am Geschehen, desto belastbarer (Zeitnac
2hweis, Kalender, Tankbelege). Steuerwirkung etwa ${j(G(r.mealMissingCents,k))}.`,href:"/crm/doppelter-haushalt",amountCents:G(r.mealMissingCents,k)}),r&&r.distanceKm>0&&r.weeksWithoutTrip>0){const C=r.weeksWithoutTrip*r.perHomeTripCents;_.push({id:"lohn-heimfahrten",level:"hinweis",title:`${r.weeksWithoutTrip} Wochen ohne erfasste Heimfahrt — je Fahrt ${j(r.perHomeTripCents)}`,detail:`Eine Familienheimfahrt pro Woche ist abziehbar: ${Math.floor(r.distanceKm)} km einfache Strecke × 0,38 €. Fährst du jedes Wochenende nach Hause, fehlen bisher ${j(C)} Werbungskosten (Steuerwirkung etwa ${j(G(C,k))}).`,href:"/crm/doppelter-haushalt",amountCents:G(C,k)})}if(r&&(r.kmRateCents!==Y||r.kmRateFarCents!==Y)){const C=Math.floor(r.distanceKm),W=Math.min(C,Math.max(1,r.kmRateFarFrom)-1)*(Y-r.kmRateCents);_.push({id:"lohn-kmsatz",level:"hinweis",title:"Kilometersatz auf 0,38 € ab dem ersten Kilometer stellen",detail:`Seit 2026 gilt die Entfernungspauschale einheitlich mit 0,38 € je Kilometer (§ 9 Abs. 1 EStG). Im Haushaltsprofil stehen noch ${r.kmRateCents} Cent für die ersten ${r.kmRateFarFrom-1} km — das kostet ${j(W)} je Heimfahrt.`,href:"/crm/doppelter-haushalt",amountCents:G(W*Math.max(1,r.countedTrips||r.weeksWithoutTrip),k)})}if(w>0&&(F?_.push({id:"lohn-arbeitsweg",level:"info",title:`Arbeitsweg: ${w} Tage × ${F} km = ${j(z)} Werbungskosten`,detail:"Gezählt sind nur Tage mit Kommen/Gehen-Buchung aus den beigelegten Zeitnachweisen. Monate ohne Zeitnachweis (vor dem ersten, nach dem letzten) fehlen noch — die kommen mit den nächsten Abrechnungen.",amountCents:G(z,k)}):_.push({id:"lohn-arbeitsweg-km",level:"hinweis",title:`${w} Bürotage aus den Zeitnachweisen — Entfernung zum Büro fehlt`,detail:`Jeder Tag im Büro bringt die Entfernungspauschale: 0,38 € je Kilometer einfache Strecke von der Wohnung, von der du losfährst (unter der Woche die Zweitwohnung). Bei 10 km wären das für die erfassten Tage ${j(w*10*Y)}. Trag die Entfernung oben ein.`})),r||F>0){const C=Ee(b).arbeitnehmerPauschbetrag*100,S=r&&r.activeMonths>0?Math.round(r.unterkunftCents/r.activeMonths):0,W=(r?46*r.perHomeTripCents+Math.min(12*S,12*1e5):0)+Math.min(De,220*F*Y),V=W-C;if(V>Jt){const O=Math.round(G(V,T)/12),ee=a<=`${s}-11-30`;_.push({id:"lohn-freibetrag",level:"hinweis",title:`Freibetrag beantragen: etwa ${j(O)} mehr netto pro Monat`,detail:`Deine Werbungskosten liegen aufs Jahr gerechnet bei rund ${j(W)} — ${j(V)} über dem Arbeitnehmer-Pauschbetrag. Mit dem „Antrag auf Lohnsteuer-Ermäßigung" (Mein ELSTER) zieht der Arbeitgeber gleich weniger Lohnsteuer ab, statt dass du das Geld erst mit dem Bescheid im Folgejahr bekommst. Der Freibetrag gilt bis zu zwei Jahre${ee?`; für ${s} geht der Antrag noch bis 30.11.${s}`:""}. Mit einem Freibetrag wird die Steuererklärung Pflicht — wegen der Erstattung gibst du sie ohnehin ab.`,amountCents:O*12})}}const $=Te[s]??Te[2026],K=m.steuer_brutto_cents*12<$&&m.steuer_brutto_cents>0?(m.rv_an_cents+m.av_an_cents)/m.steuer_brutto_cents*100:0,N=Math.round(100-T-K);return _.push({id:"lohn-bav",level:"info",title:`Betriebsrente prüfen: 100 € Beitrag kosten dich rund ${N} € netto`,detail:`Entgeltumwandlung ist steuerfrei bis ${j(Math.round($*.08))} im Jahr, sozialversicherungsfrei bis ${j(Math.round($*.04))}. Bei deinem Grenzsteuersatz von etwa ${Math.round(T)} %${K?` plus ${K.toFixed(1).replace(".",",")} % Renten- und Arbeitslosenversicherung`:""} trägt der Staat einen großen Teil. Spart der Arbeitgeber Sozialabgaben, muss er 15 % dazugeben. Die Kehrseite: Die spätere Rente wird voll versteuert und ist in der Kranken- und Pflegeversicherung beitragspflichtig, die gesetzliche Rente fällt etwas niedriger aus. Frag bei ${m.employer} nach dem Angebot und dem Zuschuss — das ist keine Anlageempfehlung, sondern die Rechnung, die du dafür brauchst.`}),_.push({id:"lohn-kleinkram",level:"info",title:"Pauschalen, die fast jeder vergisst",detail:`Kontoführungsgebühren: ${j(Fe)} ohne Nachweis. Arbeitsmittel für den Job (Fachbücher, Kurse, Headset, Tasche) bis 800 € netto sofort. Umzugskosten zur Zweitwohnung laufen über die doppelte Haushaltsführung. Achtung bei Geräten, die du schon über Brainmotion absetzt — nichts doppelt ansetzen.`,amountCents:G(Fe,k)}),d.some(C=>C.slips.some(S=>S.reisekosten_frei_cents>0))&&_.push({id:"lohn-reisekosten",level:"info",title:"Dienstreisen: Differenz zu den Verpflegungspauschalen absetzen",detail
2:"Der Arbeitgeber erstattet Reisekosten steuerfrei (Concur). Zahlt er weniger als die Pauschalen — 14 € ab 8 Stunden Abwesenheit, 28 € für volle Tage —, ist die Differenz Werbungskosten. Einmal die Concur-Abrechnungen des Jahres danebenlegen."}),v&&v>`${s}-01-31`&&_.push({id:"lohn-vorheriger",level:"info",title:`Einkünfte vor dem ${X(v)} nicht vergessen`,detail:"Warst du davor woanders angestellt oder hattest Lohnersatzleistungen (z. B. Arbeitslosengeld), gehört das in dieselbe Erklärung — jede Lohnsteuerbescheinigung einzeln in die Anlage N. Lohnersatzleistungen sind steuerfrei, erhöhen aber den Steuersatz (Progressionsvorbehalt)."}),e.jahresabschluss&&e.jahresabschluss.bruttoarbeitslohnCents!==u.bruttoarbeitslohnCents&&_.push({id:"lohn-sync",level:"hinweis",title:"Jahresabschluss kennt die Abrechnungen noch nicht",detail:`Dort stehen ${j(e.jahresabschluss.bruttoarbeitslohnCents)} Bruttoarbeitslohn, die Abrechnungen ergeben bisher ${j(u.bruttoarbeitslohnCents)}. Mit „In den Jahresabschluss übernehmen" gleichst du das ab.`}),_.push({id:"lohn-frist",level:"info",title:`Steuererklärung ${s}: früh abgeben lohnt`,detail:`Pflicht ist sie, wenn die Einkünfte aus Brainmotion über 410 € liegen oder ein Freibetrag eingetragen ist — dann bis 31.07.${s+1}. Sonst ist sie freiwillig, mit vier Jahren Zeit. Bei einer Erstattung zahlt sich früh abgeben aus: Das Geld kommt Wochen statt Monate später.`}),_.sort((C,S)=>Le[C.level]-Le[S.level]||Number(Pe.has(S.id))-Number(Pe.has(C.id))||(S.amountCents??0)-(C.amountCents??0)),{prognose:f,bisher:u,werbungskostenCents:A,arbeitswegCents:z,officeDays:w,estimate:p,vollesJahr:M,tips:_}}const g=e=>`${(e/100).toLocaleString("de-DE",{minimumFractionDigits:2,maximumFractionDigits:2})} €`,Q=e=>`${Math.round(e/100).toLocaleString("de-DE")} €`,re=e=>new Date(`${e.slice(0,7)}-15T12:00:00`).toLocaleDateString("de-DE",{month:"long",year:"numeric"}),Ke=(e=new Date)=>`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`,Vt=()=>{const{user:e,session:s}=st(),{confirm:a,alert:c}=rt(),d=xt(),{profile:r,update:f}=_t(),u=x.useMemo(()=>Ke(),[]),[w,F]=x.useState([]),[z,L]=x.useState(null),[A,p]=x.useState(null),[k,H]=x.useState(!0),[b,P]=x.useState(()=>Number(Ke().slice(0,4))),[M,T]=x.useState([]),[_,m]=x.useState(!1),[v,$]=x.useState(null),[R,K]=x.useState(!1),[N,C]=x.useState(!1),S=x.useRef(null),[W,V]=x.useState(""),[O,ee]=x.useState([]),[ue,ke]=x.useState(""),[U,_e]=x.useState(!1),[we,ye]=x.useState(null),J=x.useCallback(async()=>{if(!e?.id)return;const[t,l,o,h,y]=await Promise.all([E.from("salary_slips").select("*").eq("user_id",e.id).order("period",{ascending:!0}),E.from("household_profiles").select("*").eq("user_id",e.id).maybeSingle(),E.from("household_costs").select("*").eq("user_id",e.id),E.from("household_days").select("*").eq("user_id",e.id),E.from("tax_year_inputs").select("bruttoarbeitslohn_cents, lohnsteuer_cents").eq("user_id",e.id).eq("year",b).maybeSingle()]);F(t.data??[]),L(l.data?{profile:l.data,costs:o.data??[],days:h.data??[]}:null),p(y.data?y.data:null),H(!1)},[e?.id,b]);x.useEffect(()=>{J()},[J]),x.useEffect(()=>{V(r.arbeitsweg_km?String(r.arbeitsweg_km).replace(".",","):"")},[r.arbeitsweg_km]);const I=x.useMemo(()=>Ot(w,b),[w,b]),ge=x.useMemo(()=>{const t=new Set(w.map(l=>Number(l.period.slice(0,4))));return t.add(Number(u.slice(0,4))),[...t].sort()},[w,u]),Z=x.useMemo(()=>{if(!z)return null;const t=z.profile??At(u),l=jt(t,z.costs,b,u),o=zt(t,z.days,u),h=$t(t,z.days,b,u);return{role:t.role,movedInOn:t.moved_in_on,distanceKm:Number(t.distance_km)||0,kmRateCents:t.km_rate_cents,kmRateFarCents:t.km_rate_far_cents,kmRateFarFrom:t.km_rate_far_from,totalCents:St(l,o,h),perHomeTripCents:h.perTripCents,weeksWithoutTrip:h.weeksWithoutTrip,countedTrips:h.countedTrips,unterkunftCents:l.capYearlyCents,activeMonths:l.activeMonths,mealDeadline:o.deadline,mealExpired:o.expired,mealMissingDays:o.missingDays,mealMissingCents:o.missingCents}},[z,b,u]),te=x.useMemo(()=>It({year:b,todayYmd:u,profile:r,employers:I,haushalt:Z,jahresabschluss:A?{bruttoarbeitslohnCents:A.bruttoarbeitslohn_cents,lohnsteuerCents:A.lohnsteuer_cents}:null}),[b,u,r,I,Z,A]),Ie=x.useMemo(()=>w.filter(t=>t.period.startsWith(String(b))).sort((t,l)=>l.period.localeCompare(t.period)),[w,b]),Ae=async t=>{const l=[...t].filter(y=>y.type==="application/pdf"||y.name.toLowerCase().endsWith(".pdf"));if(l.length===0){$("Bitte die Abrechnung als PDF wählen.");return}m(!0),$(null);const o=[],h=[];for(const y of l)try{const B=await y.arrayBuffer(),ne=Wt(await Tt(B));o.push({key:`${y.name}-${y.size}`,fileName:y.name,parsed:ne,hash:await Ft(B),data:B})}catch(B){h.push(`${y.name}: ${B instanceof de?B.message:"Das PDF ließ sich nicht lesen."}`)}T(y=>[...y,...o]),h.length&&$(h.join(" · ")),o.length&&P(Number(o[o.length-1].parsed.period.slice(0,4))),m(!1)},je=async t=>
2{if(!e?.id||t.length===0)return;K(!0);let l=0;try{for(const o of t){const h=w.find(se=>se.employer===o.parsed.employer&&se.period===o.parsed.period),y=!!h&&h.file_hash===o.hash;if(y&&(h.pdf_path||!d.key)||h&&!y&&!await a({title:"Abrechnung ersetzen?",message:`Für ${re(o.parsed.period)} (${o.parsed.employer}) gibt es schon eine Abrechnung. Durch diese ersetzen — z. B. weil es eine Korrekturabrechnung ist?`,confirmLabel:"Ersetzen"}))continue;let B=null;if(d.key){const{iv:se,data:tt}=await Ct(d.key,o.data),be=`${e.id}/${o.parsed.period.slice(0,7)}-${o.hash.slice(0,12)}.bin`,{error:Se}=await E.storage.from("salary-slips").upload(be,new Blob([tt],{type:"application/octet-stream"}),{upsert:!0});if(Se)throw new Error(`Original konnte nicht abgelegt werden: ${Se.message}`);B={pdf_path:be,pdf_iv:se,pdf_name:o.fileName},h?.pdf_path&&h.pdf_path!==be&&await E.storage.from("salary-slips").remove([h.pdf_path])}else l++;const{error:ne}=await E.from("salary_slips").upsert({user_id:e.id,...Zt(o.parsed),file_hash:o.hash,...B??{},updated_at:new Date().toISOString()},{onConflict:"user_id,employer,period"});if(ne)throw new Error(ne.message)}r.hat_anstellung||await f({hat_anstellung:!0}),T(o=>o.filter(h=>!t.includes(h))),await J(),l>0&&await c(`Gespeichert. ${l===1?"Das Original wurde":`${l} Originale wurden`} nicht abgelegt, weil der Tresor gesperrt ist — die Zahlen sind vollständig übernommen.`)}catch(o){await c(o instanceof Error?o.message:"Speichern fehlgeschlagen.")}finally{K(!1)}},Ve=async t=>{if(!t.pdf_path||!t.pdf_iv)return;if(!d.key){await c("Zum Öffnen des Originals den Tresor entsperren — es ist Ende-zu-Ende verschlüsselt.");return}const l=window.open("","_blank");try{const{data:o,error:h}=await E.storage.from("salary-slips").download(t.pdf_path);if(h||!o)throw new Error(h?.message||"Download fehlgeschlagen");const y=await kt(d.key,t.pdf_iv,await o.arrayBuffer()),B=URL.createObjectURL(new Blob([y],{type:"application/pdf"}));l?l.location.href=B:window.open(B,"_blank"),window.setTimeout(()=>URL.revokeObjectURL(B),6e4)}catch(o){l?.close(),await c(`Original lässt sich nicht öffnen: ${o instanceof Error?o.message:"unbekannter Fehler"}`)}},Ue=async t=>{await a({title:"Abrechnung löschen",message:`${re(t.period)} (${t.employer}) mitsamt dem verschlüsselten Original löschen?`,confirmLabel:"Löschen",danger:!0})&&(t.pdf_path&&await E.storage.from("salary-slips").remove([t.pdf_path]),await E.from("salary_slips").delete().eq("id",t.id),await J())},Ye=async()=>{if(!e?.id||!await a({title:"Als Anstellung führen?",message:"Die doppelte Haushaltsführung zählt dann als Werbungskosten (Anlage N) statt als Betriebsausgabe von Brainmotion. Beträge und Belege bleiben, wie sie sind.",confirmLabel:"Umstellen"}))return;const{error:t}=await E.from("household_profiles").update({role:"angestellt"}).eq("user_id",e.id);t&&await c(`Umstellen fehlgeschlagen: ${t.message}`),await J()},qe=async()=>{if(!e?.id)return;const{error:t}=await E.from("household_profiles").update({km_rate_cents:38,km_rate_far_cents:38}).eq("user_id",e.id);t&&await c(`Speichern fehlgeschlagen: ${t.message}`),await J()},ze=async()=>{if(!e?.id)return;const t=te.bisher,l=b===Number(u.slice(0,4));if(!await a({title:`In den Jahresabschluss ${b} übernehmen?`,message:`Bruttoarbeitslohn ${g(t.bruttoarbeitslohnCents)}, Lohnsteuer ${g(t.lohnsteuerCents)}, Rentenversicherung ${g(t.rvAnCents)}, Kranken-/Pflegeversicherung ${g(t.kvPvBasisCents)}, Arbeitslosenversicherung ${g(t.avAnCents)}. `+(l?"Das ist der Stand der letzten Abrechnung — mit der Dezember-Abrechnung bzw. der Lohnsteuerbescheinigung erneut übernehmen.":"Vor der Abgabe gegen die Lohnsteuerbescheinigung prüfen."),confirmLabel:"Übernehmen"}))return;const{error:o}=await E.from("tax_year_inputs").upsert({user_id:e.id,year:b,bruttoarbeitslohn_cents:t.bruttoarbeitslohnCents,lohnsteuer_cents:t.lohnsteuerCents,lohn_soli_cents:t.soliCents,lohn_kirche_cents:t.kircheCents,altersvorsorge_cents:t.rvAnCents,kv_pv_basis_cents:t.kvPvBasisCents,sonstige_vorsorge_cents:t.avAnCents},{onConflict:"user_id,year"});o&&await c(`Übernehmen fehlgeschlagen: ${o.message}`),await J()},Xe=async()=>{const t=Number(W.replace(",",".")),l=Number.isFinite(t)&&t>0?Math.round(t*10)/10:0;
2l!==(r.arbeitsweg_km||0)&&await f({arbeitsweg_km:l})},$e=x.useMemo(()=>{const t=te,l=t.estimate;return[`Steuerjahr ${b}. Angestellt (Steuerklasse ${I[0]?.latest.steuerklasse??"?"}), daneben selbstständig als Kleinunternehmer (§ 19 UStG).`,`Kranken-/Pflegeversicherung: ${I.some(h=>h.latest.kv_abgefuehrt_cents>0)?"freiwillig gesetzlich, Arbeitgeber führt Beitrag ab, steuerfreier AG-Zuschuss":"pflichtversichert"}.`,...I.map(h=>`Arbeitgeber: Eintritt ${h.latest.entry_date??"unbekannt"}, Monatsbrutto ${g(h.latest.steuer_brutto_cents)}, Abrechnungen für ${h.months.join(", ")}.`),`Bisher laut Jahreswerten: Brutto ${g(t.bisher.bruttoarbeitslohnCents)}, Lohnsteuer ${g(t.bisher.lohnsteuerCents)}, RV-AN ${g(t.bisher.rvAnCents)}, AV-AN ${g(t.bisher.avAnCents)}, KV/PV-Basis eigen ${g(t.bisher.kvPvBasisCents)}.`,`Hochgerechnet bis Dezember: Brutto ${g(t.prognose.bruttoarbeitslohnCents)}, Lohnsteuer ${g(t.prognose.lohnsteuerCents)}.`,`Werbungskosten im CRM: ${g(t.werbungskostenCents)} (Arbeitsweg ${g(t.arbeitswegCents)} aus ${t.officeDays} Bürotagen).`,Z?`Doppelte Haushaltsführung seit ${Z.movedInOn}, ${Z.distanceKm} km zum Hauptwohnsitz, geführt als ${Z.role==="angestellt"?"Werbungskosten":"Betriebsausgabe"}, abziehbar bisher ${g(Z.totalCents)}.`:"Keine doppelte Haushaltsführung erfasst.",`Schätzung nur aus dem Lohn: zvE ${g(l.zveCents)}, Steuer ${g(l.gesamtCents)}, Grenzsteuersatz ${l.grenzsteuersatzPct} %, Ergebnis ${l.ergebnisCents>=0?"Erstattung":"Nachzahlung"} ${g(Math.abs(l.ergebnisCents))}.`,"","Bereits erkannte Tipps:",...t.tips.map(h=>`- ${h.title}: ${h.detail}`)].join(`
3`)},[te,I,Z,b]),pe=x.useCallback(async t=>{const l=t.trim();if(!l||U)return;const o=[...O,{role:"user",content:l}];ee(o),ke(""),_e(!0),ye(null);try{const h=s?.access_token;if(!h)throw new Error("Sitzung abgelaufen — bitte neu anmelden.");const y=await fetch("/api/tax-assistant",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${h}`},body:JSON.stringify({context:$e,messages:o})}),B=await y.json().catch(()=>({}));if(!y.ok)throw new Error(B.error||"Antwort fehlgeschlagen.");ee([...o,{role:"assistant",content:B.reply}])}catch(h){ye(h instanceof Error?h.message:"Antwort fehlgeschlagen.")}finally{_e(!1)}},[O,U,s?.access_token,$e]);if(k)return n.jsx(mt,{});const D=te,Qe=I.length>0,et=t=>t.id==="lohn-haushalt-rolle"?n.jsx(xe,{type:"button",onClick:()=>void Ye(),children:"Jetzt umstellen"}):t.id==="lohn-kmsatz"?n.jsx(xe,{type:"button",onClick:()=>void qe(),children:"Auf 0,38 € stellen"}):t.id==="lohn-sync"?n.jsx(xe,{type:"button",onClick:()=>void ze(),children:"Übernehmen"}):null;return n.jsxs(Ut,{children:[n.jsxs(Yt,{to:"/crm/steuer",children:[n.jsx(it,{size:14})," Steuer-Assistent"]}),n.jsxs(qt,{children:[n.jsxs("div",{children:[n.jsx(Xt,{children:"Gehalt & Lohnsteuer"}),n.jsx(Qt,{children:"Entgeltabrechnungen hochladen — daraus werden Jahressummen für die Anlage N, eine Hochrechnung und konkrete Tipps mit Euro-Beträgen."})]}),n.jsxs(en,{children:[n.jsx(Ne,{type:"button","aria-label":"Vorjahr",disabled:b<=ge[0],onClick:()=>P(t=>t-1),children:n.jsx(at,{size:16})}),n.jsx("span",{children:b}),n.jsx(Ne,{type:"button","aria-label":"Folgejahr",disabled:b>=ge[ge.length-1],onClick:()=>P(t=>t+1),children:n.jsx(ot,{size:16})})]})]}),n.jsxs(tn,{$over:N,onDragOver:t=>{t.preventDefault(),C(!0)},onDragLeave:()=>C(!1),onDrop:t=>{t.preventDefault(),C(!1),Ae(t.dataTransfer.files)},children:[n.jsx(lt,{size:22}),n.jsxs(nn,{children:[n.jsx("strong",{children:_?"Lese Abrechnung…":"Abrechnung hierher ziehen"}),n.jsxs("span",{children:["PDF, auch mehrere Monate auf einmal. Gelesen wird im Browser — Steuer-ID und IBAN verlassen dein Gerät nicht."," ",d.key?n.jsxs(sn,{children:[n.jsx(ct,{size:11})," Original wird Ende-zu-Ende verschlüsselt abgelegt."]}):n.jsx(rn,{children:"Tresor gesperrt: Es werden nur die Zahlen gespeichert."})]})]}),n.jsx(fe,{type:"button",disabled:_,onClick:()=>S.current?.click(),children:"PDF wählen"}),n.jsx("input",{ref:S,type:"file",accept:"application/pdf",multiple:!0,hidden:!0,onChange:t=>{t.target.files&&Ae(t.target.files),t.target.value=""}})]}),v&&n.jsx(Ze,{children:v}),!d.key&&d.supported&&!d.tableMissing&&n.jsx(an,{children:n.jsx(vt,{})}),M.length>0&&n.jsxs(on,{children:[n.jsxs(ie,{children:["Gelesen — bitte kurz prüfen",M.length>1&&n.jsxs(fe,{type:"button",disabled:R,onClick:()=>void je(M),children:["Alle ",M.length," speichern"]})]}),n.jsx(ln,{children:M.map(t=>n.jsxs(cn,{children:[n.jsxs(dn,{children:[n.jsxs("div",{children:[n.jsxs(hn,{children:[re(t.parsed.period)," · ",t.parsed.employer]}),n.jsx(q,{children:t.fileName})]}),n.jsxs(un,{children:[n.jsx(We,{type:"button",onClick:()=>T(l=>l.filter(o=>o!==t)),children:"Verwerfen"}),n.jsx(fe,{type:"button",disabled:R,onClick:()=>void je([t]),children:"Speichern"})]})]}),n.jsxs(gn,{children:[n.jsx("span",{children:"Steuer-Brutto"}),n.jsx("b",{children:g(t.parsed.steuerBruttoCents)}),n.jsx("span",{children:"Lohnsteuer"}),n.jsx("b",{children:g(t.parsed.lohnsteuerCents)}),n.jsx("span",{children:"Renten-/Arbeitslosenvers."}),n.jsxs("b",{children:[g(t.parsed.rvAnCents)," / ",g(t.parsed.avAnCents)]}),n.jsx("span",{children:"Netto / Auszahlung"}),n.jsxs("b",{children:[g(t.parsed.nettoCents)," / ",g(t.parsed.auszahlungCents)]}),n.jsx("span",{children:"Jahreswert Brutto / Lohnsteuer"}),n.jsxs("b",{children:[g(t.parsed.ytd.steuerBruttoCents)," / ",g(t.parsed.ytd.lohnsteuerCents)]}),t.parsed.officeDays.length>0&&n.jsxs(n.Fragment,{children:[n.jsxs("span",{children:["Zeitnachweis ",t.parsed.timeSheetMonth]}),n.jsxs("b",{children:[t.parsed.officeDays.length," Bürotage"]})]})]}
3),t.parsed.warnings.map(l=>n.jsxs(pn,{children:[n.jsx(Be,{size:12})," ",l]},l))]},t.key))})]}),Qe?n.jsxs(n.Fragment,{children:[n.jsxs(mn,{children:[n.jsxs(ae,{children:[n.jsxs(oe,{children:["Brutto ",b]}),n.jsx(le,{children:Q(D.bisher.bruttoarbeitslohnCents)}),n.jsxs(ce,{children:["Hochrechnung bis Dez.: ",Q(D.prognose.bruttoarbeitslohnCents)]})]}),n.jsxs(ae,{children:[n.jsx(oe,{children:"Lohnsteuer einbehalten"}),n.jsx(le,{children:Q(D.bisher.lohnsteuerCents)}),n.jsxs(ce,{children:["bis Dez.: ",Q(D.prognose.lohnsteuerCents)]})]}),n.jsxs(ae,{$accent:D.estimate.ergebnisCents>0,children:[n.jsx(oe,{children:D.estimate.ergebnisCents>=0?"Voraussichtlich zurück":"Voraussichtlich nachzahlen"}),n.jsx(le,{children:Q(Math.abs(D.estimate.ergebnisCents))}),n.jsx(ce,{children:"nur aus dem Lohn gerechnet"})]}),n.jsxs(ae,{children:[n.jsx(oe,{children:"Grenzsteuersatz"}),n.jsxs(le,{children:[D.estimate.grenzsteuersatzPct.toLocaleString("de-DE")," %"]}),n.jsxs(ce,{children:["volles Jahr:"," ",D.vollesJahr?`${D.vollesJahr.grenzsteuersatzPct.toLocaleString("de-DE")} %`:"—"]})]})]}),n.jsxs(fn,{children:[n.jsxs(Ge,{children:[n.jsxs(ie,{children:["Tipps für ",b,n.jsx(We,{type:"button",onClick:()=>void ze(),children:"In den Jahresabschluss übernehmen"})]}),n.jsxs(xn,{children:[n.jsx("label",{htmlFor:"arbeitsweg",children:"Arbeitsweg (einfache Strecke, km)"}),n.jsx(vn,{id:"arbeitsweg",inputMode:"decimal",placeholder:"z. B. 7",value:W,onChange:t=>V(t.target.value),onBlur:()=>void Xe(),onKeyDown:t=>t.key==="Enter"&&t.target.blur()}),n.jsx(q,{children:"von der Wohnung, von der du unter der Woche ins Büro fährst"})]}),n.jsx(Cn,{children:D.tips.map(t=>n.jsxs(kn,{$level:t.level,children:[n.jsx(_n,{$level:t.level,children:t.level==="warnung"?n.jsx(Be,{size:15}):t.level==="hinweis"?n.jsx(dt,{size:15}):n.jsx(ht,{size:15})}),n.jsxs("div",{style:{minWidth:0},children:[n.jsx(wn,{children:t.title}),n.jsx(yn,{children:t.detail}),n.jsxs(An,{children:[et(t),t.href&&n.jsxs(jn,{to:t.href,children:["Ansehen ",n.jsx(ut,{size:11})]}),n.jsx(zn,{type:"button",disabled:U,onClick:()=>void pe(`Erklär mir das genauer und sag mir, was ich konkret tun soll: ${t.title}`),children:"Nachfragen"})]})]})]},t.id))})]}),n.jsxs(Ge,{children:[n.jsxs(ie,{children:["Abrechnungen ",b]}),n.jsx($n,{children:Ie.map(t=>n.jsxs(Sn,{children:[n.jsxs(Bn,{children:[re(t.period),n.jsx(q,{children:t.employer})]}),n.jsxs(En,{children:[n.jsxs("span",{children:["Brutto ",g(t.steuer_brutto_cents)]}),n.jsxs("span",{children:["LSt ",g(t.lohnsteuer_cents)]}),n.jsxs("span",{children:["Auszahlung ",g(t.auszahlung_cents)]})]}),n.jsxs(Mn,{children:[t.pdf_path?n.jsx(ve,{type:"button",title:"Original öffnen",onClick:()=>void Ve(t),children:n.jsx(gt,{size:15})}):n.jsx(q,{title:"Beim Hochladen war der Tresor gesperrt",children:"ohne Original"}),n.jsx(ve,{type:"button",title:"Löschen",onClick:()=>void Ue(t),children:n.jsx(pt,{size:15})})]})]},t.id))}),n.jsx(ie,{style:{marginTop:22},children:"Frag nach"}),n.jsxs(Dn,{children:[O.length===0&&n.jsx(Tn,{children:["Welche Steuervorteile übersehe ich noch?","Lohnt sich der Freibetrag für mich jetzt schon?","Was muss ich bis Jahresende noch erledigen?"].map(t=>n.jsx(Fn,{type:"button",disabled:U,onClick:()=>void pe(t),children:t},t))}),O.map((t,l)=>n.jsx(Ln,{$user:t.role==="user",children:t.role==="assistant"?n.jsx(Pn,{children:n.jsx(Bt,{remarkPlugins:[Et],children:t.content})}):t.content},l)),U&&n.jsx(q,{children:"denkt nach…"}),we&&n.jsx(Ze,{children:we}),n.jsxs(Rn,{onSubmit:t=>{t.preventDefault(),pe(ue)},children:[n.jsx(Kn,{value:ue,onChange:t=>ke(t.target.value),placeholder:"Frage zu Gehalt, Werbungskosten, Freibetrag …"}),n.jsx(ve,{type:"submit",disabled:U||!ue.trim(),"aria-label":"Senden",children:n.jsx(bt,{size:15})})]}),n.jsx(q,{children:"An die KI gehen nur Summen und Tipps — keine Abrechnung, keine Steuer-ID, keine Bankdaten. Ersetzt keine Steuerberatung."})]})]})]})]}):n.jsxs(bn,{children:["Für ",b," ist noch keine Abrechnung da. Lade die erste hoch — ab dann rechnet die Seite Jahressummen, die voraussichtliche Erstattung und deine Tipps aus."]})]})},Xn=()=>n.jsx(nt,{roles:["admin"],children:n.jsx(ft,{children:n.jsx(Vt,{})})}),Ut=i.div`
4  min-height: 100vh;
5  padding: 110px 2rem 4rem;
6  max-width: 1320px;
7  margin: 0 auto;
8  @media (max-width: 640px) {
9    padding: 92px 1rem 3rem;
10  }
11`,Yt=i(He)`
12  display: inline-flex;
13  align-items: center;
14  gap: 6px;
15  color: #9fb0c8;
16  text-decoration: none;
17  font-size: 13px;
18  margin-bottom: 1rem;
19  &:hover {
20    color: #ff9bb5;
21  }
22`,qt=i.header`
23  display: flex;
24  align-items: flex-end;
25  justify-content: space-between;
26  gap: 16px;
27  flex-wrap: wrap;
28  margin-bottom: 1.4rem;
29`,Xt=i.h1`
30  margin: 0 0 0.3rem;
31  font-size: clamp(1.7rem, 5vw, 2.2rem);
32  font-weight: 700;
33  background: linear-gradient(120deg, #ff9bb5, #ff7a9e);
34  -webkit-background-clip: text;
35  -webkit-text-fill-color: transparent;
36`,Qt=i.p`
37  margin: 0;
38  color: #9fb0c8;
39  font-size: 0.95rem;
40  max-width: 70ch;
41`,en=i.div`
42  display: inline-flex;
43  align-items: center;
44  gap: 8px;
45  font-weight: 600;
46  color: #e8eef7;
47`,Ne=i.button`
48  width: 30px;
49  height: 30px;
50  border-radius: 8px;
51  border: 1px solid rgba(255, 255, 255, 0.12);
52  background: rgba(255, 255, 255, 0.04);
53  color: #cfd8e6;
54  display: grid;
55  place-items: center;
56  cursor: pointer;
57  &:disabled {
58    opacity: 0.35;
59    cursor: default;
60  }
61`,tn=i.div`
62  display: flex;
63  align-items: center;
64  gap: 14px;
65  flex-wrap: wrap;
66  padding: 16px 18px;
67  border-radius: 14px;
68  border: 1.5px dashed ${e=>e.$over?"#ff9bb5":"rgba(255, 155, 181, 0.35)"};
69  background: ${e=>e.$over?"rgba(255, 155, 181, 0.08)":"rgba(255, 155, 181, 0.035)"};
70  color: #ff9bb5;
71  transition: border-color 0.15s, background 0.15s;
72`,nn=i.div`
73  flex: 1;
74  min-width: 220px;
75  display: flex;
76  flex-direction: column;
77  gap: 3px;
78  strong {
79    color: #e8eef7;
80    font-size: 14px;
81  }
82  span {
83    color: #9fb0c8;
84    font-size: 12.5px;
85    line-height: 1.5;
86  }
87`,sn=i.span`
88  color: #5ecf8f !important;
89  display: inline-flex;
90  align-items: center;
91  gap: 4px;
92`,rn=i.span`
93  color: #fbbf24 !important;
94`,q=i.span`
95  display: block;
96  font-size: 11.5px;
97  color: #6b7a94;
98`,an=i.div`
99  margin-top: 12px;
100  max-width: 620px;
101`,fe=i.button`
102  padding: 8px 16px;
103  border-radius: 10px;
104  border: none;
105  background: linear-gradient(135deg, #ff9bb5, #ff7a9e);
106  color: #1a0a12;
107  font-weight: 600;
108  font-size: 13px;
109  cursor: pointer;
110  flex-shrink: 0;
111  &:disabled {
112    opacity: 0.6;
113    cursor: wait;
114  }
115`,We=i.button`
116  padding: 6px 12px;
117  border-radius: 9px;
118  border: 1px solid rgba(255, 255, 255, 0.14);
119  background: transparent;
120  color: #cfd8e6;
121  font-size: 12px;
122  text-transform: none;
123  letter-spacing: 0;
124  cursor: pointer;
125  &:hover {
126    border-color: rgba(255, 155, 181, 0.5);
127    color: #ff9bb5;
128  }
129`,xe=i.button`
130  padding: 3px 10px;
131  border-radius: 8px;
132  border: 1px solid rgba(255, 155, 181, 0.45);
133  background: rgba(255, 155, 181, 0.12);
134  color: #ff9bb5;
135  font-size: 11.5px;
136  font-weight: 600;
137  cursor: pointer;
138  &:hover {
139    background: rgba(255, 155, 181, 0.2);
140  }
141`,Ze=i.div`
142  margin-top: 8px;
143  font-size: 12.5px;
144  color: #ef5a6e;
145`,on=i.section`
146  margin-top: 18px;
147`,ie=i.div`
148  display: flex;
149  align-items: center;
150  justify-content: space-between;
151  gap: 10px;
152  flex-wrap: wrap;
153  font-size: 10.5px;
154  text-transform: uppercase;
155  letter-spacing: 0.05em;
156  color: #6b7a94;
157  margin-bottom: 10px;
158`,ln=i.div`
159  display: flex;
160  flex-direction: column;
161  gap: 10px;
162`,cn=i.div`
163  padding: 14px 16px;
164  border-radius: 12px;
165  border: 1px solid rgba(255, 255, 255, 0.1);
166  background: rgba(255, 255, 255, 0.03);
167`,dn=i.div`
168  display: flex;
169  justify-content: space-between;
170  align-items: flex-start;
171  gap: 12px;
172  flex-wrap: wrap;
173  margin-bottom: 10px;
174`,hn=i.div`
175  font-weight: 600;
176  color: #e8eef7;
177`,un=i.div`
178  display: flex;
179  gap: 8px;
180`,gn=i.div`
181  display: grid;
182  grid-template-columns: max-content 1fr;
183  gap: 4px 16px;
184  font-size: 12.5px;
185  span {
186    color: #9fb0c8;
187  }
188  b {
189    color: #e8eef7;
190    font-weight: 600;
191    font-variant-numeric: tabular-nums;
192  }
193`,pn=i.div`
194  display: flex;
195  align-items: center;
196  gap: 6px;
197  margin-top: 8px;
198  font-size: 12px;
199  color: #fbbf24;
200`,bn=i.div`
201  margin-top: 20px;
202  padding: 22px;
203  border-radius: 12px;
204  border: 1px solid rgba(255, 255, 255, 0.07);
205  color: #9fb0c8;
206  font-size: 13.5px;
207  text-align: center;
208`,mn=i.div`
209  display: grid;
210  grid-template-columns: repeat(4, minmax(0, 1fr));
211  gap: 10px;
212  margin: 20px 0;
213  @media (max-width: 900px) {
214    grid-template-columns: repeat(2, minmax(0, 1fr));
215  }
216`,ae=i.div`
217  padding: 12px 14px;
218  border-radius: 12px;
219  background: ${e=>e.$accent?"rgba(94, 207, 143, 0.07)":"rgba(255, 255, 255, 0.03)"};
220  border: 1px solid ${e=>e.$accent?"rgba(94, 207, 143, 0.35)":"rgba(255, 255, 255, 0.08)"};
221`,oe=i.div`
222  font-size: 11.5px;
223  color: #9fb0c8;
224`,le=i.div`
225  font-size: 1.35rem;
226  font-weight: 700;
227  color: #fff;
228  margin: 3px 0 1px;
229  font-variant-numeric: tabular-nums;
230`,ce=i.div`
231  font-size: 11px;
232  color: #6b7a94;
233`,fn=i.div`
234  display: grid;
235  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
236  gap: 20px;
237  align-items: start;
238  @media (max-width: 980px) {
239    grid-template-columns: 1fr;
240  }
241`,Ge=i.div`
242  min-width: 0;
243`,xn=i.div`
244  display: flex;
245  align-items: center;
246  gap: 10px;
247  flex-wrap: wrap;
248  margin-bottom: 12px;
249  font-size: 12.5px;
250  color: #cfd8e6;
251`,vn=i.input`
252  width: 80px;
253  padding: 6px 10px;
254  border-radius: 8px;
255  border: 1px solid rgba(255, 255, 255, 0.14);
256  background: rgba(255, 255, 255, 0.04);
257  color: #fff;
258  font: inherit;
259`,Cn=i.div`
260  display: flex;
261  flex-direction: column;
262  gap: 8px;
263`,kn=i.div`
264  display: grid;
265  grid-template-columns: 24px minmax(0, 1fr);
266  gap: 10px;
267  padding: 12px 14px;
268  border-radius: 12px;
269  background: ${e=>e.$level==="warnung"?"rgba(239, 90, 110, 0.06)":e.$level==="hinweis"?"rgba(251, 191, 36, 0.05)":"rgba(255, 255, 255, 0.025)"};
270  border: 1px solid
271    ${e=>e.$level==="warnung"?"rgba(239, 90, 110, 0.28)":e.$level==="hinweis"?"rgba(251, 191, 36, 0.22)":"rgba(255, 255, 255, 0.07)"};
272`,_n=i.div`
273  display: flex;
274  padding-top: 1px;
275  color: ${e=>e.$level==="warnung"?"#ef5a6e":e.$level==="hinweis"?"#fbbf24":"#7c8ba5"};
276`,wn=i.div`
277  font-size: 13.5px;
278  font-weight: 600;
279  color: #e8eef7;
280  margin-bottom: 3px;
281`,yn=i.div`
282  font-size: 12.5px;
283  line-height: 1.55;
284  color: #9fb0c8;
285`,An=i.div`
286  display: flex;
287  align-items: center;
288  flex-wrap: wrap;
289  gap: 12px;
290  margin-top: 8px;
291`,jn=i(He)`
292  display: inline-flex;
293  align-items: center;
294  gap: 4px;
295  font-size: 11.5px;
296  color: #ff9bb5;
297  text-decoration: none;
298  &:hover {
299    text-decoration: underline;
300  }
301`,zn=i.button`
302  border: none;
303  background: none;
304  padding: 0;
305  font-size: 11.5px;
306  color: #9fb0c8;
307  cursor: pointer;
308  &:hover {
309    color: #cfd8e6;
310  }
311  &:disabled {
312    opacity: 0.5;
313    cursor: default;
314  }
315`,$n=i.div`
316  display: flex;
317  flex-direction: column;
318  border: 1px solid rgba(255, 255, 255, 0.08);
319  border-radius: 12px;
320  overflow: hidden;
321`,Sn=i.div`
322  display: grid;
323  grid-template-columns: minmax(0, 1fr) auto;
324  grid-template-areas: 'month actions' 'nums nums';
325  gap: 4px 10px;
326  padding: 10px 14px;
327  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
328  &:last-child {
329    border-bottom: none;
330  }
331`,Bn=i.div`
332  grid-area: month;
333  font-weight: 600;
334  color: #e8eef7;
335  font-size: 13.5px;
336`,En=i.div`
337  grid-area: nums;
338  display: flex;
339  flex-wrap: wrap;
340  gap: 4px 14px;
341  font-size: 12px;
342  color: #9fb0c8;
343  font-variant-numeric: tabular-nums;
344`,Mn=i.div`
345  grid-area: actions;
346  display: flex;
347  align-items: center;
348  gap: 4px;
349`,ve=i.button`
350  width: 32px;
351  height: 32px;
352  border-radius: 8px;
353  border: none;
354  background: transparent;
355  color: #9fb0c8;
356  display: grid;
357  place-items: center;
358  cursor: pointer;
359  &:hover {
360    background: rgba(255, 255, 255, 0.06);
361    color: #fff;
362  }
363  &:disabled {
364    opacity: 0.4;
365    cursor: default;
366  }
367`,Dn=i.div`
368  display: flex;
369  flex-direction: column;
370  gap: 10px;
371  padding: 14px;
372  border-radius: 12px;
373  border: 1px solid rgba(255, 155, 181, 0.2);
374  background: rgba(255, 155, 181, 0.03);
375`,Tn=i.div`
376  display: flex;
377  flex-wrap: wrap;
378  gap: 6px;
379`,Fn=i.button`
380  padding: 6px 11px;
381  border-radius: 999px;
382  border: 1px solid rgba(255, 255, 255, 0.14);
383  background: transparent;
384  color: #cfd8e6;
385  font-size: 12px;
386  cursor: pointer;
387  &:hover {
388    border-color: rgba(255, 155, 181, 0.5);
389    color: #ff9bb5;
390  }
391`,Ln=i.div`
392  align-self: ${e=>e.$user?"flex-end":"flex-start"};
393  max-width: 92%;
394  padding: 9px 12px;
395  border-radius: 12px;
396  font-size: 13px;
397  line-height: 1.55;
398  color: #e8eef7;
399  background: ${e=>e.$user?"rgba(255, 155, 181, 0.14)":"rgba(255, 255, 255, 0.04)"};
400`,Pn=i.div`
401  p {
402    margin: 0 0 0.5em;
403  }
404  ul,
405  ol {
406    margin: 0.2em 0 0.5em;
407    padding-left: 1.2em;
408  }
409  p:last-child {
410    margin-bottom: 0;
411  }
412`,Rn=i.form`
413  display: flex;
414  gap: 6px;
415`,Kn=i.input`
416  flex: 1;
417  min-width: 0;
418  padding: 8px 12px;
419  border-radius: 10px;
420  border: 1px solid rgba(255, 255, 255, 0.14);
421  background: rgba(255, 255, 255, 0.04);
422  color: #fff;
423  font: inherit;
424  font-size: 13px;
425`;export{Xn as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.