diff --git a/README.md b/README.md
index 8d68d01..74a502e 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,7 @@ Unlike `vatExempt`, this package does **not** expect `unitPrice` to be de-grosse
- Visual PDF (`invoicePdf.tsx`/`correctionInvoicePdf.tsx`): the "enthält X% MwSt." annotation under Gesamt becomes "Gemäß § 19 UStG wird keine Umsatzsteuer berechnet." instead — takes precedence over the `vatExempt` note if (implausibly) both were ever set.
- E-invoice XML (`buildEInvoiceData.ts`): VAT category `E` + a free-text exemption reason, no VATEX code — see "E-invoicing" above.
+- **No Netto row** (added 2026-07-24, at the user's own request) — every other invoice type still shows Netto directly under the tax note/annotation, including `vatExempt` ones, where Netto = Gesamt is a *coincidence* worth keeping for layout consistency (0% happens to apply to that one sale). For `kleinunternehmer` it isn't a coincidence — §19 UStG means no tax component ever existed on any of this tenant's invoices, so the row would just repeat Gesamt directly under the §19 notice above it instead of adding information.
`InvoiceSeller.vatId` is now optional (`string | null`, was a plain required `string`) for the same reason — a Kleinunternehmer commonly never registers for an USt-IdNr. at all (no intra-EU trade). Every renderer treats a missing value as "omit the USt-IdNr. line/field" rather than printing an empty one: the visual PDF footer drops the whole `· USt-IdNr. …` segment, and `buildEInvoiceData.ts`'s `sellerParty()` omits `cac:PartyTaxScheme` entirely rather than emitting one with a blank `CompanyID`.
diff --git a/package.json b/package.json
index e1db368..5730421 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@einfach-produktiv/invoicing",
- "version": "0.2.1",
+ "version": "0.2.2",
"private": true,
"description": "Shared invoice / correction-invoice (Stornorechnung, Gutschrift) PDF generation and VAT-breakdown math, consumed as a git dependency by both the einfach-produktiv frontend and the payload backend — not published to npm.",
"type": "module",
diff --git a/src/correctionInvoicePdf.tsx b/src/correctionInvoicePdf.tsx
index 4c6b833..acb65cb 100644
--- a/src/correctionInvoicePdf.tsx
+++ b/src/correctionInvoicePdf.tsx
@@ -364,15 +364,23 @@ function CorrectionInvoiceDocument({ kind, order, seller }: { kind: CorrectionIn
single well-defined figure (Gesamt minus every rate's own
tax, summed) regardless of how many rates are present.
Shown on every correction invoice (Storno and Gutschrift
- alike), not just non-exempt ones. Same small/muted
- vatNoteLabel/vatNoteValue styling as the MwSt annotation
- above it, not the larger summaryLabel/summaryValue the
- build-up rows use — both are supplementary detail below
- the hero Gesamt figure, same visual tier. */}
-
- Netto
- -{formatPrice(rateGroups.reduce((sum, g) => sum + g.net, 0))}
-
+ alike), not just non-exempt ones — except `kleinunternehmer`
+ (built 2026-07-24, at the user's own request), same
+ exception as invoicePdf.tsx's own row for the same reason:
+ Netto = Gesamt there isn't a coincidence to preserve for
+ layout consistency, it's structural (§19 UStG means no tax
+ component ever existed to subtract), so the row would just
+ duplicate Gesamt right under the §19 notice. Same
+ small/muted vatNoteLabel/vatNoteValue styling as the MwSt
+ annotation above it, not the larger summaryLabel/
+ summaryValue the build-up rows use — both are supplementary
+ detail below the hero Gesamt figure, same visual tier. */}
+ {!order.kleinunternehmer && (
+
+ Netto
+ -{formatPrice(rateGroups.reduce((sum, g) => sum + g.net, 0))}
+
+ )}
diff --git a/src/invoicePdf.tsx b/src/invoicePdf.tsx
index 60ab31c..11a34fd 100644
--- a/src/invoicePdf.tsx
+++ b/src/invoicePdf.tsx
@@ -425,19 +425,28 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
by hand. Shown on every invoice, not just B2B/non-exempt
ones — on a vatExempt order Netto and Gesamt happen to be
the same figure (0% tax), but the row stays for layout
- consistency across every invoice this shop issues. Placed
- last (after the MwSt annotation, not before it) — see
- that annotation's own comment above for why the order
- matters here. Styled with the same small/muted
- vatNoteLabel/vatNoteValue as that annotation, not the
- larger summaryLabel/summaryValue the build-up rows above
- Gesamt use — Netto is supplementary detail *below* the
- hero Gesamt figure, same visual tier as the tax
- breakdown, not another primary line competing with it. */}
-
- Netto
- {formatPrice(rateGroups.reduce((sum, g) => sum + g.net, 0))}
-
+ consistency across every invoice this shop issues. The one
+ exception is `kleinunternehmer` (built 2026-07-24, at the
+ user's own request): there Netto = Gesamt for a
+ structural reason, not a coincidental one (§19 UStG means
+ there was never a tax component to subtract in the first
+ place), and the row would just look like a second,
+ redundant total sitting directly under the §19 notice
+ above rather than genuinely new information. Placed last
+ (after the MwSt annotation, not before it) — see that
+ annotation's own comment above for why the order matters
+ here. Styled with the same small/muted vatNoteLabel/
+ vatNoteValue as that annotation, not the larger
+ summaryLabel/summaryValue the build-up rows above Gesamt
+ use — Netto is supplementary detail *below* the hero
+ Gesamt figure, same visual tier as the tax breakdown, not
+ another primary line competing with it. */}
+ {!order.kleinunternehmer && (
+
+ Netto
+ {formatPrice(rateGroups.reduce((sum, g) => sum + g.net, 0))}
+
+ )}
{paid && (