Designframework
Token, Grundstile und Komponenten für alle Projekte auf jsengenberger.de — CSS ohne Abhängigkeit und eine Kartenkomponente, in Hell und Dunkel geprüft.
Einbinden
<link rel="stylesheet" href="https://static.jsengenberger.de/v1/framework.css">
Grundlagen
Farben
Jede Farbe hat eine Aufgabe. Die Felder folgen dem Thema — schalte oben um und sieh, was sich ändert.
Marke
Status
Flächen
Text
Linien
Karte
Kartenkategorien
Schrift
Systemschrift, kein Webfont. 9 Größen, keine dazwischen.
- --font-familySystemschriftPrüfbericht, 148 KB
- --font-family-monoFestbreiteword/people.xml
- --font-size-4xl36 pxVerbindlich für alle Projekte
- --font-size-3xl30 pxVerbindlich für alle Projekte
- --font-size-2xl24 pxVerbindlich für alle Projekte
- --font-size-xl20 pxVerbindlich für alle Projekte
- --font-size-lg18 pxVerbindlich für alle Projekte
- --font-size-base16 pxVerbindlich für alle Projekte
- --font-size-sm14 pxVerbindlich für alle Projekte
- --font-size-xs12 pxVerbindlich für alle Projekte
- --font-size-2xs10 pxVerbindlich für alle Projekte
Abstände
Jeder Abstand im Framework ist eine dieser Stufen.
- --spacing-2xs2 px
- --spacing-xs4 px
- --spacing-sm8 px
- --spacing-md16 px
- --spacing-lg24 px
- --spacing-xl32 px
- --spacing-2xl48 px
- --spacing-3xl64 px
Radien
Von der Haarkante bis zur Pille.
Alle Token
Die vollständige Liste, 122 Einträge. Maßgeblich ist immer 01-tokens.css.
Liste anzeigen
| Token | Wert (helles Thema) |
|---|---|
| --color-primary | #e75421 |
| --color-primary-light | #f16a3e |
| --color-primary-dark | #c64419 |
| --color-primary-rgb | 231, 84, 33 |
| --color-primary-alpha | rgba(231, 84, 33, 0.1) |
| --color-primary-ink | #ffffff |
| --color-primary-fill | var(--color-primary-dark) |
| --color-primary-fill-hover | #a8380f |
| --color-primary-text | #b83d16 |
| --color-success | #66bb6a |
| --color-success-light | #81c784 |
| --color-success-dark | #4caf50 |
| --color-success-alpha | rgba(102, 187, 106, 0.1) |
| --color-warning | #ff9800 |
| --color-warning-light | #ffb74d |
| --color-warning-dark | #f57c00 |
| --color-warning-alpha | rgba(255, 152, 0, 0.1) |
| --color-success-ink | #1a1a1a |
| --color-warning-ink | #1a1a1a |
| --color-error | #ef5350 |
| --color-error-light | #e57373 |
| --color-error-dark | #e53935 |
| --color-error-alpha | rgba(239, 83, 80, 0.1) |
| --color-error-ink | #ffffff |
| --color-error-fill | #c62828 |
| --color-error-fill-hover | #b71c1c |
| --color-info | #2196f3 |
| --color-info-light | #64b5f6 |
| --color-info-dark | #1976d2 |
| --color-info-alpha | rgba(33, 150, 243, 0.1) |
| --bg-primary | #ffffff |
| --bg-secondary | #f8f9fa |
| --bg-tertiary | #e9ecef |
| --text-primary | #2c3e50 |
| --text-secondary | #616970 |
| --text-tertiary | #808080 |
| --text-muted | #adb5bd |
| --text-inverse | #ffffff |
| --border-color | #e0e0e0 |
| --border-color-light | #f0f0f0 |
| --border-color-dark | #d0d0d0 |
| --hover-bg | #f8f9fa |
| --active-bg | #e9ecef |
| --color-backdrop | rgba(0, 0, 0, 0.5) |
| --map-land | #f3f4f6 |
| --map-water | #cbd8e1 |
| --map-green | #e0eadd |
| --map-building | #e4e6e9 |
| --map-road | #ffffff |
| --map-cat-1 | #7b3fb5 |
| --map-cat-2 | #00787c |
| --map-cat-3 | #b02d7c |
| --map-cat-4 | #657315 |
| --map-cat-5 | #3f4fbf |
| --map-cat-6 | #6f6259 |
| --status-success-text | #2e7d32 |
| --status-warning-text | #8a5300 |
| --status-error-text | #c62828 |
| --status-info-text | #0d5bb9 |
| --select-arrow | url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23616970' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e") |
| --shadow-xs | 0 1px 2px rgba(0, 0, 0, 0.04) |
| --shadow-sm | 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04) |
| --shadow-md | 0 4px 6px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.05) |
| --shadow-lg | 0 10px 15px rgba(0, 0, 0, 0.08), 0 4px 6px rgba(0, 0, 0, 0.05) |
| --shadow-xl | 0 20px 25px rgba(0, 0, 0, 0.1), 0 10px 10px rgba(0, 0, 0, 0.04) |
| --radius-xs | 2px |
| --radius-sm | 4px |
| --radius-md | 8px |
| --radius-lg | 12px |
| --radius-xl | 16px |
| --radius-full | 9999px |
| --spacing-2xs | 2px |
| --spacing-xs | 4px |
| --spacing-sm | 8px |
| --spacing-md | 16px |
| --spacing-lg | 24px |
| --spacing-xl | 32px |
| --spacing-2xl | 48px |
| --spacing-3xl | 64px |
| --font-family | -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif |
| --font-family-mono | 'SF Mono', 'Fira Code', 'Consolas', ui-monospace, monospace |
| --font-size-2xs | 0.625rem |
| --font-size-xs | 0.75rem |
| --font-size-sm | 0.875rem |
| --font-size-base | 1rem |
| --font-size-lg | 1.125rem |
| --font-size-xl | 1.25rem |
| --font-size-2xl | 1.5rem |
| --font-size-3xl | 1.875rem |
| --font-size-4xl | 2.25rem |
| --font-weight-normal | 400 |
| --font-weight-medium | 500 |
| --font-weight-semibold | 600 |
| --font-weight-bold | 700 |
| --line-height-tight | 1.25 |
| --line-height-snug | 1.375 |
| --line-height-normal | 1.5 |
| --line-height-relaxed | 1.625 |
| --letter-spacing-tight | -0.025em |
| --letter-spacing-normal | 0 |
| --letter-spacing-wide | 0.025em |
| --input-height-sm | 32px |
| --input-height | 40px |
| --input-height-lg | 48px |
| --table-field-width | 14ch |
| --button-height-sm | 32px |
| --button-height | 40px |
| --button-height-lg | 48px |
| --navbar-height | 64px |
| --container-max-width | 1400px |
| --container-narrow | 720px |
| --focus-ring-color | var(--color-primary) |
| --focus-ring-width | 3px |
| --focus-ring-offset | 2px |
| --transition-fast | 150ms ease |
| --transition-normal | 250ms ease |
| --transition-slow | 400ms ease |
| --z-dropdown | 100 |
| --z-sticky | 150 |
| --z-modal-backdrop | 200 |
| --z-modal | 250 |
| --z-toast | 400 |
Komponenten
Gerüst
Navigationsleiste, Inhaltsbreite und Seitenkopf — der Rahmen, in den jede Ansicht gesetzt wird.
Prüfbericht
Schriftsatz.docx · 148 KB
Vier Befunde mit hoher Schwere in zwei Dateien.
Quelltext
<nav class="navbar">
<div class="navbar__container">
<a class="navbar__brand" href="/">
<span class="navbar__mark">A</span>
<span>Anwendung</span>
</a>
<div class="navbar__menu">
<a class="navbar__link navbar__link--active" href="#">Prüfen</a>
<a class="navbar__link" href="#">Bereinigen</a>
</div>
<div class="navbar__user"><span class="navbar__avatar">J</span> Jens S.</div>
</div>
</nav>
<main class="container page">
<header class="page-header">
<div>
<h1 class="page-header__title">Prüfbericht</h1>
<p class="page-header__subtitle">Schriftsatz.docx · 148 KB</p>
</div>
<span class="badge badge--danger"><span class="badge__dot"></span>4 hoch</span>
</header>
<div class="stack"><p>Vier Befunde mit hoher Schwere in zwei Dateien.</p></div>
</main>
Reiter
Mehrere Ansichten auf einer Seite. Die Leiste haftet unter der Navigation, damit keine Ansicht außer Reichweite rutscht.
Drei Befunde in zwei Dateien.
Fünf Kommentare von zwei Verfassern.
Quelltext
<div class="stack">
<div class="tabs" role="tablist" aria-label="Ansichten" id="reiter-beispiel">
<button class="tabs__tab tabs__tab--active" role="tab" id="tab-uebersicht" aria-selected="true" aria-controls="panel-uebersicht" tabindex="0">Übersicht</button>
<button class="tabs__tab" role="tab" id="tab-kommentare" aria-selected="false" aria-controls="panel-kommentare" tabindex="-1">Kommentare <span class="badge badge--sm">5</span></button>
</div>
<section class="tab-panel" role="tabpanel" id="panel-uebersicht" aria-labelledby="tab-uebersicht"><p>Drei Befunde in zwei Dateien.</p></section>
<section class="tab-panel" role="tabpanel" id="panel-kommentare" aria-labelledby="tab-kommentare" hidden><p>Fünf Kommentare von zwei Verfassern.</p></section>
</div>
<script type="module">
import { connectTabs } from "https://static.jsengenberger.de/v1/tabs/tabs.js";
connectTabs(document.getElementById("reiter-beispiel"));
</script>
Knöpfe
Eine Hauptaktion je Ansicht, alles andere tritt zurück. Feste Höhen halten eine Reihe Knöpfe auf einer Linie.
Quelltext
<div class="row">
<button class="btn btn-primary">Dokument öffnen</button>
<button class="btn btn-secondary">Ansehen</button>
<button class="btn btn-danger">Alles entfernen</button>
<button class="btn btn-ghost">Zurücksetzen</button>
<button class="btn btn-secondary btn-sm">klein</button>
<button class="btn btn-primary btn-lg">groß</button>
<button class="btn btn-primary" disabled>gesperrt</button>
</div>
Badges
Kurze Zustände und Zahlen. Die Farbe trägt die Bedeutung, der Text sagt sie aus.
Quelltext
<div class="row">
<span class="badge badge--danger"><span class="badge__dot"></span>Hoch</span>
<span class="badge badge--warning"><span class="badge__dot"></span>Mittel</span>
<span class="badge badge--info"><span class="badge__dot"></span>Gering</span>
<span class="badge badge--success"><span class="badge__dot"></span>Sauber</span>
<span class="badge">70 Befunde</span>
</div>
Karten
Inhalt in einem Rahmen, mit Kopf und Fuß für Titel und Aktionen. Kacheln fassen eine Kennzahl zusammen.
Was gefunden wurde
4 hochAutor, Firma und zwei Kommentare mit Namen.
Quelltext
<section class="card">
<header class="card__header">
<h2 class="card__header-title">Was gefunden wurde</h2>
<span class="badge badge--danger">4 hoch</span>
</header>
<div class="card__body"><p>Autor, Firma und zwei Kommentare mit Namen.</p></div>
<footer class="card__footer">
<button class="btn btn-secondary">Verwerfen</button>
<button class="btn btn-primary">Auswahl entfernen</button>
</footer>
</section>
Quelltext
<div class="grid grid--4">
<div class="stat-card">
<div class="stat-card__tile stat-card__tile--danger">H</div>
<div>
<div class="stat-card__value">4</div>
<div class="stat-card__label">Hohes Risiko</div>
</div>
</div>
<div class="stat-card"><div class="stat-card__tile stat-card__tile--warning">M</div><div><div class="stat-card__value">7</div><div class="stat-card__label">Mittleres Risiko</div></div></div>
<div class="stat-card"><div class="stat-card__tile stat-card__tile--info">G</div><div><div class="stat-card__value">12</div><div class="stat-card__label">Geringes Risiko</div></div></div>
<div class="stat-card"><div class="stat-card__tile stat-card__tile--success">S</div><div><div class="stat-card__value">3</div><div class="stat-card__label">Dateien sauber</div></div></div>
</div>
Quelltext
<div class="grid grid--4">
<div class="card is-dragging"><div class="card__body">Seite 1</div></div>
<div class="card is-drop-target" data-side="before"><div class="card__body">Seite 2</div></div>
<div class="card"><div class="card__body">Seite 3</div></div>
<div class="card is-drop-target" data-side="after"><div class="card__body">Seite 4</div></div>
</div>
Formular
Beschriftung über dem Feld, Hinweis oder Fehler darunter — jedes Feld in seiner eigenen Gruppe.
Quelltext
<div class="form-group">
<label class="form-label" for="autor">Neuer Autorname</label>
<input class="form-control" id="autor" placeholder="leer lassen">
<span class="form-hint">Leer entfernt den Namen vollständig.</span>
</div>
<div class="form-group">
<label class="form-label" for="pfad">Vorlagenpfad</label>
<input class="form-control form-control--mono is-invalid" id="pfad" value="C:\Vorlagen\">
<span class="form-error">Ein Pfad ist als Autorname nicht zulässig.</span>
</div>
<div class="form-group">
<label class="form-label" for="tiefe">Prüftiefe</label>
<select class="form-control form-select" id="tiefe"><option>Gründlich</option><option>Schnell</option></select>
</div>
<div class="form-group">
<label class="form-label" for="notiz">Anmerkung</label>
<textarea class="form-control form-textarea" id="notiz"></textarea>
</div>
Quelltext
<div class="stack stack--sm">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="a" checked>
<label class="form-check-label" for="a">Autor und Firma entfernen</label>
</div>
<div class="form-switch">
<input class="form-switch-input" type="checkbox" id="roh" checked>
<label for="roh">Rohansicht</label>
</div>
</div>
Quelltext
<div class="form-group">
<label class="form-label" for="wert">Wert in der Datei</label>
<div class="input-group">
<input class="form-control form-control--mono" id="wert" value="Dr. Katharina Vogelsang">
<button class="btn btn-secondary">Leeren</button>
</div>
</div>
<div class="form-group">
<label class="form-label" for="anschrift">Anschrift</label>
<textarea class="form-control form-control--sm form-textarea--grow" id="anschrift" rows="1"></textarea>
</div>
Word-Dokument hierher ziehenWord-Dokument auswählen
oder
Quelltext
<div class="dropzone">
<p class="empty-state__title"><span class="pointer-only">Word-Dokument hierher ziehen</span><span class="touch-only">Word-Dokument auswählen</span></p>
<p class="empty-state__text"><span class="pointer-only">oder </span><button class="btn btn-secondary btn-sm">Datei auswählen</button></p>
</div>
Tabelle
Zahlen und Werte in Zeilen. Breite Tabellen scrollen in ihrem eigenen Kasten, nie die Seite.
| Fundort | Wert | Anzahl |
|---|---|---|
| word/people.xml | Katharina Vogelsang | 218 |
Quelltext
<div class="table-scroll">
<table class="table">
<thead><tr><th>Fundort</th><th>Wert</th><th class="table__num">Anzahl</th></tr></thead>
<tbody>
<tr><td class="table__mono">word/people.xml</td><td class="table__mono">Katharina Vogelsang</td><td class="table__num">218</td></tr>
</tbody>
</table>
</div>
| Autor | Dr. Katharina Vogelsang |
|---|
Quelltext
<table class="table">
<tbody>
<tr><th class="table__key" scope="row">Autor</th><td class="table__mono">Dr. Katharina Vogelsang</td></tr>
</tbody>
</table>
| Nr. | Name | Zeile entfernen |
|---|---|---|
| 1 | ||
| 2 |
Quelltext
<div class="table-scroll">
<table class="table table--nowrap table--edit">
<thead><tr><th class="table__num">Nr.</th><th>Name</th><th class="table__actions"><span class="visually-hidden">Zeile entfernen</span></th></tr></thead>
<tbody>
<tr><td class="table__num">1</td><td><input class="form-control form-control--sm" aria-label="Name, Zeile 1" value="Vogelsang"></td><td class="table__actions"><button class="btn btn-ghost btn-sm">Entfernen</button></td></tr>
<tr><td class="table__num">2</td><td><input class="form-control form-control--sm" aria-label="Name, Zeile 2" value="Schulz"></td><td class="table__actions"><button class="btn btn-ghost btn-sm">Entfernen</button></td></tr>
</tbody>
</table>
</div>
Vorher/Nachher
Ein geänderter Wert an seinem Platz: der alte durchgestrichen, der neue hervorgehoben, beide mit Wort.
| Feld | Änderung |
|---|---|
| Fristende | vorher |
| Zuständig | vorher |
Quelltext
<div class="table-scroll">
<table class="table">
<thead><tr><th>Feld</th><th>Änderung</th></tr></thead>
<tbody>
<tr><th class="table__key" scope="row">Fristende</th><td><span class="diff"><span class="diff__part"><span class="diff__label">vorher</span> <del>12.03.2026</del></span> <span class="diff__part"><span class="diff__label">nachher</span> <ins>15.03.2026</ins></span></span></td></tr>
<tr><th class="table__key" scope="row">Zuständig</th><td><span class="diff"><span class="diff__part"><span class="diff__label">vorher</span> <del>Amtsgericht Bonn</del></span> <span class="diff__part"><span class="diff__label">nachher</span> <ins>Landgericht Köln, 3. Zivilkammer</ins></span></span></td></tr>
</tbody>
</table>
</div>
Hinweisboxen
Eine Meldung, die stehen bleibt, bis man sie gelesen hat — in den vier Statusfarben.
Änderungen annehmen verändert den Inhalt
Bereinigt — keine Metadaten mehr gefunden.
Die Datei ist beschädigt und lässt sich nicht öffnen.
Die Prüfung läuft vollständig im Browser.
Quelltext
<div class="stack stack--sm">
<div class="alert alert--warning">
<span class="alert__mark" aria-hidden="true">!</span>
<div class="alert__content">
<p class="alert__title">Änderungen annehmen verändert den Inhalt</p>
<p class="alert__message">Das Original bleibt unangetastet.</p>
</div>
</div>
<div class="alert alert--success">
<span class="alert__mark" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5l3 3 7-7"/></svg></span>
<div class="alert__content"><p class="alert__title">Bereinigt — keine Metadaten mehr gefunden.</p></div>
</div>
<div class="alert alert--danger">
<span class="alert__mark" aria-hidden="true">!</span>
<div class="alert__content"><p class="alert__title">Die Datei ist beschädigt und lässt sich nicht öffnen.</p></div>
</div>
<div class="alert alert--info">
<span class="alert__mark" aria-hidden="true">i</span>
<div class="alert__content"><p class="alert__title">Die Prüfung läuft vollständig im Browser.</p></div>
</div>
</div>
Aufklappbereich
Einzelheiten, die nicht jeder lesen muss — zu, bis man sie aufklappt.
Einzelheiten zu den Links ansehen (3)
Quelltext
<details class="disclosure">
<summary>Einzelheiten zu den Links ansehen (3)</summary>
<div class="stack stack--sm">
<div class="list-item">https://example.org/rechnung</div>
<div class="list-item">https://example.org/konto</div>
<div class="list-item">https://example.org/hilfe</div>
</div>
</details>
Erläuterung
Ein „i" neben einem Feld oder Ergebnis öffnet einen kurzen Text — ein Begriff und die Norm, aus der er stammt.
Quelltext
<div class="form-group">
<label class="form-label" for="zugang">Bekanntgabe des Bescheids</label>
<button class="info-btn" type="button" popovertarget="info-zugang" aria-controls="info-zugang" aria-label="Erläuterung: Bekanntgabe">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><circle cx="8" cy="8" r="6.25"/><path d="M8 7.25v3.75"/><circle cx="8" cy="5" r="0.5" fill="currentColor"/></svg>
</button>
<span class="info-pop" id="info-zugang" popover>Ein schriftlicher Verwaltungsakt gilt am vierten Tag nach der Aufgabe zur Post als bekannt gegeben (§ 41 Abs. 2 Satz 1 VwVfG).</span>
<input class="form-control" id="zugang" type="date">
</div>
Fortschritt
Wie weit ein Vorgang ist. Die Breite ist der einzige Inline-Stil, den das Framework erlaubt.
Quelltext
<div class="stack stack--sm">
<div class="progress progress--sm"><div class="progress__fill" style="width: 30%"></div></div>
<div class="progress"><div class="progress__fill" style="width: 60%"></div></div>
<div class="progress progress--lg"><div class="progress__fill progress__fill--success" style="width: 100%"></div></div>
</div>
Leerzustand
Was eine Ansicht zeigt, solange es noch nichts zu zeigen gibt — mit dem einen Schritt, der das ändert.
Noch kein Dokument geöffnet
Ziehen Sie eine Word-Datei hierher.
Quelltext
<div class="empty-state">
<div class="empty-state__mark" aria-hidden="true">∅</div>
<h2 class="empty-state__title">Noch kein Dokument geöffnet</h2>
<p class="empty-state__text">Ziehen Sie eine Word-Datei hierher.</p>
<button class="btn btn-primary">Datei auswählen</button>
</div>
Dialog
Eine Rückfrage, die die Seite anhält. Abbrechen steht zuerst und bekommt den Fokus.
Quelltext
<div class="modal-overlay">
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="t">
<header class="modal__header">
<div>
<h2 class="modal__title" id="t">Änderungen annehmen?</h2>
<p class="modal__subtitle">16 Revisionen von drei Personen</p>
</div>
<button class="btn btn-ghost btn-sm" aria-label="Schließen">×</button>
</header>
<div class="modal__body"><p>Die Revisionen werden übernommen und aus dem Dokument entfernt. Das lässt sich nicht rückgängig machen.</p></div>
<footer class="modal__footer">
<button class="btn btn-secondary">Abbrechen</button>
<button class="btn btn-primary">Annehmen</button>
</footer>
</div>
</div>
Code und Werte
Werte aus fremden Dateien in Festbreitenschrift, Fundstellen in den Statusfarben.
Der Wert steht in word/people.xml.
m.schulz@kanzlei.exampleQuelltext
<p>Der Wert steht in <code>word/people.xml</code>.</p>
<pre><span class="code-mark--high">m.schulz@kanzlei.example</span></pre>
Landkarte
Eine schlichte Karte in unseren Farben: Straßen einfärben, Marker und Werte setzen, mit Legende und Werkzeugen — ein Modul, kein Markup.
Quelltext
<div id="karte-beispiel"></div>
<script type="module">
import { createMap } from "https://static.jsengenberger.de/v1/map/map.js";
const map = await createMap(document.getElementById("karte-beispiel"), {
label: "Bonn, Innenstadt",
center: [7.0995, 50.734],
zoom: 15,
});
const innenstadt = [7.09, 50.728, 7.11, 50.74];
await map.highlightStreet("Poststraße", { area: innenstadt, category: 1, fit: false,
info: "Vom Hauptbahnhof zum Münsterplatz" });
await map.highlightStreet("Sternstraße", { area: innenstadt, category: 2, fit: false,
info: "Fußgängerzone zwischen Friedensplatz und Markt" });
map.addMarker([7.1029, 50.7351], { label: "Altes Rathaus", info: "Markt 2" });
map.addMarker([7.0968, 50.732], { label: "Bonn Hauptbahnhof", text: "Hbf", category: 5 });
map.setLegend({
title: "Legende",
toggle: true,
items: [
{ label: "Poststraße", category: 1 },
{ label: "Sternstraße", category: 2 },
{ label: "Sehenswürdigkeit", kind: "marker" },
{ label: "Bahnhof", kind: "marker", category: 5 },
],
});
</script>
Druck
Ergebnisseiten drucken sauber auf A4: ohne Bedienelemente, in Hell, mit einem Kopf, den es nur auf Papier gibt.
Fristenberechnung — Ergebnis
Quelltext
<header class="print-header">
<p class="print-header__title">Fristenberechnung — Ergebnis</p>
<dl class="print-header__meta">
<div><dt>Version</dt><dd>2.1.0</dd></div>
<div><dt>Stand</dt><dd>01.11.2026</dd></div>
<div><dt>Erstellt</dt><dd><time datetime="2026-11-01T14:32">01.11.2026, 14:32 Uhr</time></dd></div>
</dl>
</header>