diff --git a/AGENTS.md b/AGENTS.md
index 2b1b324..4ef8496 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -8,6 +8,8 @@
- `templates/settings.html` — Einstellungsseite (Druckerabschreibung, Arbeitskosten, Marge, MwSt., Firmendaten, Logo)
- `static/style.css` — Light-/Dark-Mode-Theming
- `static/script.js` — Live-Berechnung + Auto-Save beim Tippen
+- `static/img/logo/` — JET-Design-Wortmarke: `jet-design.svg` (dunkle Schrift),
+ `jet-design-weiss.svg` (Dark Mode), `jet-design.jpg` (Rechnungs-PDF)
- `druckkalkulation_config.yaml` — auto-created/auto-saved state (in .gitignore)
- `proxmox-setup.sh` — Proxmox LXC-Ersteinrichtung
- `proxmox-update.sh` — Proxmox LXC-Update
@@ -100,4 +102,14 @@ Kein Test, Lint, Typecheck oder CI vorhanden. README.md und AGENTS.md enthalten
`_migriere()` in eine einzelne Position und entfernt die Altfelder.
- **Saeamtliche UI-Texte sind Deutsch** — Labels, Fehlermeldungen, Rechnungsinhalte.
- Nur `.venv/`, `druckkalkulation_config.yaml` und `static/logo.*` werden ignoriert.
+ `static/img/logo/` ist davon nicht betroffen und wird versioniert.
+- Das Rechnungslogo liefert `logo_datei()`: hochgeladenes Logo vor
+ `STANDARD_LOGO`, und erst wenn beide Dateien fehlen, setzt der PDF-Kopf
+ den Namen als Text. Nie direkt `config['logo']` fuer die Ausgabe lesen.
+- Die Wortmarke ist im SVG fest eingefaerbt. Deshalb stehen im Kopf beide
+ Varianten im Markup und `static/style.css` blendet ueber
+ `[data-bs-theme="dark"]` die passende ein -- `toggleDarkMode()` laedt die
+ Seite nicht neu, eine serverseitige Auswahl waere danach falsch. Am
+ `navbar-brand` darf `navbar-brand-autodark` nicht stehen: Tabler invertiert
+ damit Bilder im Dark Mode und wuerde die weisse Variante schwarz faerben.
- `3dDruckKalkulator.py` ist die alte Tkinter-Version und wird nicht mehr verwendet (nicht im Tracking).
diff --git a/README.md b/README.md
index f879915..5e0b9ae 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,8 @@ sich ueber `HOST` und `PORT` ueberschreiben.
- *Regelbesteuert* — MwSt. mit 19 % oder 7 %
- **Rechnungspflichtangaben** nach §14 UStG (Steuernummer/USt-IdNr.,
Leistungsdatum) — nur in den beiden Unternehmer-Modi
-- **Logo-Upload** (PNG/JPEG/WebP) für die Rechnung
+- **JET-Design-Wortmarke** im Seitenkopf (SVG, hell/dunkel) und auf der
+ Rechnung (JPEG). Ein eigenes **Logo-Upload** (PNG/JPEG/WebP) ersetzt sie.
## Installation auf Proxmox (LXC-Container)
@@ -151,3 +152,5 @@ druckkalkulation_projekte.yaml # Gespeicherte Projekte (ignoriert)
- Alle UI-Texte sind Deutsch
- Die YAML-Config wird automatisch erstellt und bei jedem Tastendruck gespeichert
- `druckkalkulation_config.yaml` und `static/logo.*` sind in `.gitignore` ausgeschlossen
+- `static/img/logo/` gehört dagegen ins Repo: die beiden SVG-Varianten für den
+ Seitenkopf und `jet-design.jpg` für den Rechnungsdruck (fpdf2 setzt nur Pixelbilder)
diff --git a/app.py b/app.py
index c79bb95..b3e1bc4 100644
--- a/app.py
+++ b/app.py
@@ -118,6 +118,20 @@ def as_stueckzahl(value):
return max(1, zahl)
+
+def logo_datei(config):
+ """Pfad des Rechnungslogos relativ zu static/.
+
+ Ein hochgeladenes Logo hat Vorrang, sonst greift die mitgelieferte
+ Wortmarke. Fehlen beide Dateien, kommt '' zurueck und der PDF-Kopf
+ setzt den Firmennamen als Text.
+ """
+ for name in (config.get('logo', ''), STANDARD_LOGO):
+ if name and os.path.exists(os.path.join('static', name)):
+ return name
+ return ''
+
+
def pdf_text(value):
"""Macht beliebigen Text fuer die latin-1-Kernfonts von fpdf sicher.
@@ -147,6 +161,11 @@ MAX_PROJEKTE = 500
LOGO_EXTS = ('png', 'jpg', 'webp')
+# Mitgelieferte JET-Design-Wortmarke fuer den Rechnungskopf. Aus der
+# SVG-Vorlage des Shops gerastert, weil fpdf2 nur Pixelbilder setzt.
+# Greift, solange kein eigenes Logo hochgeladen wurde.
+STANDARD_LOGO = 'img/logo/jet-design.jpg'
+
# Obergrenze, damit ein fehlerhafter Client die Config nicht aufblaeht.
MAX_POSITIONEN = 50
@@ -589,7 +608,8 @@ def index():
def settings():
"""Einstellungsseite fuer Druckerabschreibung, Arbeitskosten und Marge."""
config = load_config()
- return render_template('settings.html', config=config)
+ return render_template('settings.html', config=config,
+ logo_anzeige=logo_datei(config))
@app.route('/calculate', methods=['POST'])
@@ -843,9 +863,9 @@ def invoice_pdf():
col_w = 45
# Logo rechts oben
- logo_name = config.get('logo', '')
+ logo_name = logo_datei(config)
logo_path = os.path.join('static', logo_name) if logo_name else ''
- if logo_name and os.path.exists(logo_path):
+ if logo_name:
pdf.image(logo_path, x=175, y=12, w=20)
img_w, img_h = image_dimensions(logo_path)
if img_w and img_h:
diff --git a/static/img/logo/jet-design-weiss.svg b/static/img/logo/jet-design-weiss.svg
new file mode 100644
index 0000000..1a44c71
--- /dev/null
+++ b/static/img/logo/jet-design-weiss.svg
@@ -0,0 +1,7 @@
+
diff --git a/static/img/logo/jet-design.jpg b/static/img/logo/jet-design.jpg
new file mode 100644
index 0000000..0c2d602
Binary files /dev/null and b/static/img/logo/jet-design.jpg differ
diff --git a/static/img/logo/jet-design.svg b/static/img/logo/jet-design.svg
new file mode 100644
index 0000000..e7bb54a
--- /dev/null
+++ b/static/img/logo/jet-design.svg
@@ -0,0 +1,7 @@
+
diff --git a/static/style.css b/static/style.css
index b5de207..8614fef 100644
--- a/static/style.css
+++ b/static/style.css
@@ -11,3 +11,25 @@
white-space: pre;
overflow-x: auto;
}
+
+/* Wortmarke im Kopf. Die Schrift ist im SVG fest eingefaerbt, deshalb
+ liegen beide Varianten im Markup und die zum Theme passende wird
+ eingeblendet -- der Dark-Mode-Schalter tauscht nur das Attribut am
+ , ohne die Seite neu zu laden. */
+.marke {
+ height: 40px;
+ width: auto;
+ display: block;
+}
+
+.marke-dunkel {
+ display: none;
+}
+
+[data-bs-theme="dark"] .marke-hell {
+ display: none;
+}
+
+[data-bs-theme="dark"] .marke-dunkel {
+ display: block;
+}
diff --git a/templates/index.html b/templates/index.html
index c7c1b34..08a8149 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -16,8 +16,9 @@