aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2026-08-23 09:26:19 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2026-08-23 09:26:19 +0200
commit18f85ced396b6eadfe0823e97ac6ed944d593f58 (patch)
treeb0e72020e51ea40506d0419ff5add504f87080a7 /src/main
parent1db8201439680474bf7d0b98721af8011e67d494 (diff)
Die Synopse ergeht fortan als Formblatt ÄG-2
Seit die Aufgabeseite das Gewand eines amtlichen Formblatts trägt, sah man beim Öffnen der Synopse zwei Dokumente zweier Häuser: dort Groteske, Briefkopf und Amtsrot, hier Antiqua auf Weiß ohne Kopf und ohne Fuß. Sie treten nunmehr als Vorgang und Erzeugnis desselben Hauses auf — der Antrag als ÄG-1, die darauf ergehende Synopse als ÄG-2. Der Kopf trägt denselben Aufbau: links die ausstellende Stelle, rechts die Kennung mit Formblatt, Stammgesetz, Erstellungstag und Geltung, bei Entwürfen zusätzlich der Stand. Die Felder des Spaltenkopfes und die Überschriften der beiden Sonderabschnitte treten als schwarze Balken auf wie die Legende des Feldblocks. Jede Norm trägt im Steg links eine Randziffer, wie der Vordruck die Feldziffer; sie macht die Abschnitte zugleich zitierbar. Die alte Fassung liegt auf dem Kastenton wie ein Durchschlag, die neue auf Bogenweiß. Die Schrift bleibt geteilt: Der Vordruck steht in der Groteske, der Wortlaut der Normen in der Antiqua. Amtskopf und Vorschrift sind zweierlei, im Gesetzblatt wie hier. Dass das Farbgerüst zweimal geführt wird, ist unvermeidlich und nun an beiden Stellen vermerkt — die Synopse wird aus einem blob:-Verweis geöffnet und kann kein fremdes Stilblatt einbinden. Drei Mängel traten dabei zutage. Der Spaltenkopf klebte innerhalb des Kopfblocks und verschwand deshalb beim Blättern alsbald; er steht jetzt mit der Gegenüberstellung in einem eigenen Block. Auf schmalen Geräten standen zwei Spalten Gesetzestext nebeneinander; unterhalb von sechzig Halbgevierten wird gestapelt, und jede Spalte beschriftet sich dort selbst. Und die Druckblöcke beider Stilblätter setzten nur einen Teil des Farbgerüstes zurück — aus einem dunkel eingestellten Browser heraus wäre die alte Spalte als schwarzer Block aus dem Drucker gekommen. Geprüft an zwei wirklichen Läufen der Befehlszeilenfassung: UWG mit dem Dritten Änderungsgesetz (19 Befehle, 0 manuell, 6 Normen) und AGG mit dem Regierungsentwurf (23 Befehle, 1 manuell, 14 Normen, Entwurfsfassung), beide hell und dunkel, breit und schmal, dazu die Druckvorschau; reuse lint meldet 154/154, mvnw test dreihundertsiebenundzwanzig Testfälle ohne Fehler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Change-Id: I76d1f5f14638700d695a7ffe7a6a5933bee10611
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java346
-rw-r--r--src/main/resources/eu/mulk/aendggner/web/style.css6
2 files changed, 302 insertions, 50 deletions
diff --git a/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java b/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java
index 91f5574..09a60de 100644
--- a/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java
+++ b/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java
@@ -37,34 +37,60 @@ public final class HtmlRenderer {
rendereKopf(sb, synopse, quelleBeschreibung, entwurfsfassung);
+ // Der Spaltenkopf steht mit der Gegenüberstellung in einem Block: Sein Klebebereich reicht
+ // damit über alle Normen, endet aber vor dem Abschnitt „Manuell prüfen“, der keine Spalten
+ // hat und über dem er nur im Wege stünde.
+ sb.append("<div class=\"gegenueberstellung\">\n");
+ sb.append("<div class=\"spaltenkopf\"><div>Alte Fassung</div><div>Neue Fassung</div></div>\n");
+
rendereGliederungsAenderungen(sb, synopse);
for (var eintrag : synopse.eintraege()) {
rendereEintrag(sb, eintrag);
}
+ sb.append("</div>\n");
+
rendereManuellZuPruefen(sb, synopse);
+ rendereFuss(sb);
+
sb.append("</body>\n</html>\n");
return sb.toString();
}
+ /**
+ * Der Briefkopf des Vordrucks ÄG-2, im Aufbau derselbe wie auf der Aufgabeseite: links die
+ * ausstellende Stelle, rechts die Kennung; darunter der Vorspann mit Herkunft und Statistik.
+ */
private static void rendereKopf(
StringBuilder sb, Synopse synopse, String quelle, boolean entwurfsfassung) {
- sb.append("<header>\n<h1>Synopse: ").append(esc(synopse.alt().jurabk())).append("</h1>\n");
+ sb.append("<header class=\"briefkopf\">\n<div class=\"dienststelle\">\n");
+ sb.append("<p class=\"langname\">").append(LANGNAME).append("</p>\n");
+ sb.append("<h1>Synopse: ").append(esc(synopse.alt().jurabk())).append("</h1>\n");
+ if (synopse.alt().langue() != null) {
+ sb.append("<p class=\"langue\">").append(esc(synopse.alt().langue())).append("</p>\n");
+ }
+ sb.append("</div>\n<dl class=\"kennung\">\n");
+ sb.append("<dt>Formblatt</dt><dd>ÄG&#8209;2</dd>\n");
+ sb.append("<dt>Stammgesetz</dt><dd>")
+ .append(esc(synopse.alt().jurabk()))
+ .append("</dd>\n<dt>Erstellt</dt><dd>")
+ .append(LocalDate.now())
+ .append("</dd>\n");
+ if (entwurfsfassung) {
+ sb.append("<dt>Stand</dt><dd>Entwurfsfassung</dd>\n");
+ }
+ sb.append("<dt>Geltung</dt><dd>nichtamtlich</dd>\n");
+ sb.append("</dl>\n</header>\n");
+
+ sb.append("<div class=\"vorgang\">\n");
if (entwurfsfassung) {
sb.append(
"<p class=\"entwurfshinweis\">Entwurfsfassung — nicht geltendes Recht. Die neue Fassung"
+ " gibt den Stand des Gesetzgebungsverfahrens wieder.</p>\n");
}
- if (synopse.alt().langue() != null) {
- sb.append("<p class=\"langue\">").append(esc(synopse.alt().langue())).append("</p>\n");
- }
- sb.append("<p class=\"quelle\">")
- .append(esc(quelle))
- .append(" — erstellt am ")
- .append(LocalDate.now())
- .append(" mit ÄndGgner</p>\n");
+ sb.append("<p class=\"quelle\">Grundlage: ").append(esc(quelle)).append("</p>\n");
long geaendert =
synopse.eintraege().stream()
.filter(e -> e.art() != Synopse.Aenderungsart.UNVERAENDERT)
@@ -74,10 +100,27 @@ public final class HtmlRenderer {
.append(" geänderte Normen, ")
.append(synopse.manuellZuPruefen().size())
.append(" manuell zu prüfende Befehle</p>\n");
- sb.append("<div class=\"spaltenkopf\"><div>Alte Fassung</div><div>Neue Fassung</div></div>\n");
- sb.append("</header>\n");
+ sb.append("</div>\n");
}
+ /**
+ * Der Fußsteg. Der Vorbehalt gehört gerade hierher und nicht bloß auf die Aufgabeseite: Die
+ * Synopse wird ausgedruckt und weitergereicht, das Formular nicht.
+ */
+ private static void rendereFuss(StringBuilder sb) {
+ sb.append("<footer>\n<span>Erstellt am ")
+ .append(LocalDate.now())
+ .append(" mit ÄndGgner</span>\n")
+ .append(
+ "<span class=\"nebenquelle\">Ohne Gewähr; maßgeblich ist allein die amtliche"
+ + " Verkündung im jeweiligen Gesetz- oder Verordnungsblatt.</span>\n")
+ .append("</footer>\n");
+ }
+
+ private static final String LANGNAME =
+ "Nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen anhand"
+ + " von Änderungsvorschriften des Bundes und der Länder";
+
private static void rendereGliederungsAenderungen(StringBuilder sb, Synopse synopse) {
if (synopse.gliederungsAenderungen().isEmpty()) {
return;
@@ -208,76 +251,200 @@ public final class HtmlRenderer {
private static final String CSS =
"""
- /* Grundgerüst schwarzweiß wie ein Gesetzblatt; Farbe trägt allein die Änderung:
- rot heißt weg, grün heißt hinzu. Damit die Aussage auch im Schwarzweiß-Ausdruck
- und bei Farbfehlsichtigkeit erhalten bleibt, tritt zur Farbe stets die Form —
- durchgestrichen gegen unterstrichen — sowie die Spalte, in der sie steht. */
+ /* Der Vordruck ÄG-2. Das Farbgerüst ist dasselbe wie in
+ src/main/resources/eu/mulk/aendggner/web/style.css und wird hier ein zweites Mal
+ geführt: Diese Datei wird aus einem blob:-Verweis geöffnet und im Befehlszeilen-
+ betrieb als einzelne Datei abgelegt; sie kann kein fremdes Stilblatt einbinden.
+ Wer dort etwas ändert, ändere es hier mit.
+
+ Die Schrift ist geteilt: Der Vordruck — Briefkopf, Kennung, Überschriften,
+ Spaltenköpfe, Kästchen, Fußsteg — steht in der Groteske, der Wortlaut der Normen
+ in der Antiqua. Amtskopf und Vorschrift sind zweierlei, im Gesetzblatt wie hier.
+
+ Farbe trägt allein die Änderung: rot heißt weg, grün heißt hinzu. Damit die
+ Aussage auch im Schwarzweiß-Ausdruck und bei Farbfehlsichtigkeit erhalten bleibt,
+ tritt zur Farbe stets die Form — durchgestrichen gegen unterstrichen — sowie die
+ Spalte, in der sie steht. */
:root {
color-scheme: light dark;
--fg: #111;
--bg: #fff;
- --rand: #bbb;
- --dezent: #595959;
+ --papier: #f3f1ea;
+ --muted: #595959;
+ --raster: #d6d2c6;
+ --kasten: #f0ede4;
+ --amt: #8b0f21;
--del-bg: #ffd7d7;
--del-fg: #8b0000;
--ins-bg: #d7f5d7;
--ins-fg: #005f00;
+ --grotesk: system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
+ --antiqua: Georgia, "Times New Roman", serif;
}
@media (prefers-color-scheme: dark) {
:root {
--fg: #e6e6e6;
- --bg: #141414;
- --rand: #4a4a4a;
- --dezent: #a0a0a0;
+ --bg: #1c1c1c;
+ --papier: #0f0f0f;
+ --muted: #a0a0a0;
+ --raster: #3c3c3c;
+ --kasten: #242424;
+ --amt: #e79aa4;
--del-bg: #5a1f1f;
--del-fg: #ffb3b3;
--ins-bg: #1f4a1f;
--ins-fg: #b3ffb3;
}
}
+ * { box-sizing: border-box; }
+ /* Die Unterlage endet nie, auch wenn der Bogen kürzer ist als das Fenster. */
+ html { background: var(--papier); }
body {
- font-family: Georgia, "Times New Roman", serif;
- line-height: 1.45;
+ counter-reset: norm;
+ font-family: var(--grotesk);
+ line-height: 1.5;
max-width: 90rem;
- margin: 0 auto;
- padding: 1rem 2rem;
+ margin: 2rem auto 3rem;
+ padding: 2rem 2.25rem 2.5rem;
+ border: 1px solid var(--fg);
color: var(--fg);
background: var(--bg);
}
- header h1 { margin-bottom: 0.2rem; }
- .langue { font-style: italic; margin-top: 0; }
- .quelle, .statistik, .gliederung, .ursachen { color: var(--dezent); font-size: 0.9rem; }
+ /* Auf schmalen Geräten wäre der Bogenrand nur ein Verlust an Satzbreite. */
+ @media (max-width: 48rem) {
+ body { margin: 0; padding: 1.25rem 1rem 2rem; border: none; }
+ }
+
+ /* Briefkopf und Doppellinie wie auf der Aufgabeseite: kräftig in Amtsrot, dünn in
+ Rasterfarbe, wobei die zweite Linie der Oberrand des Vorspanns ist. */
+ .briefkopf {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ gap: 1rem 2rem;
+ align-items: end;
+ padding-bottom: 0.7rem;
+ border-bottom: 3px solid var(--amt);
+ }
+ .langname {
+ margin: 0 0 0.3rem;
+ max-width: 30rem;
+ font-size: 0.75rem;
+ letter-spacing: 0.05em;
+ text-transform: uppercase;
+ line-height: 1.35;
+ color: var(--muted);
+ }
+ .dienststelle h1 {
+ margin: 0;
+ font-size: 1.9rem;
+ letter-spacing: 0.06em;
+ line-height: 1.1;
+ }
+ .langue { margin: 0.35rem 0 0; font-style: italic; color: var(--muted); }
+ .kennung {
+ display: grid;
+ grid-template-columns: auto auto;
+ gap: 0 0.6rem;
+ margin: 0;
+ padding: 0.4rem 0.6rem;
+ border: 1px solid var(--raster);
+ font-size: 0.75rem;
+ line-height: 1.5;
+ }
+ .kennung dt { letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
+ .kennung dd { margin: 0; font-weight: bold; color: var(--amt); white-space: nowrap; }
+ /* Gestapelt zöge die Kennung sonst über die ganze Breite und sähe aus wie ein Kasten
+ des Satzspiegels statt wie ein Stempel am Kopfrand. */
+ @media (max-width: 34rem) {
+ .briefkopf { grid-template-columns: 1fr; align-items: start; }
+ .kennung { justify-self: start; }
+ }
+
+ .vorgang { margin-top: 3px; padding-top: 1rem; border-top: 1px solid var(--raster); }
+ .quelle, .statistik, .gliederung, .ursachen {
+ color: var(--muted);
+ font-size: 0.85rem;
+ margin: 0.2rem 0;
+ }
.entwurfshinweis {
- border: 1px solid var(--rand);
+ margin: 0 0 0.9rem;
+ padding: 0.9rem 1.1rem;
+ border: 1px solid var(--raster);
border-left: 4px solid var(--del-fg);
- padding: 0.5rem 0.75rem;
- margin: 0.6rem 0;
- font-size: 0.95rem;
+ background: var(--kasten);
+ font-size: 0.9rem;
}
+
+ /* Der Spaltenkopf steht mit der Gegenüberstellung in einem Block und nicht mehr im
+ Kopfblock: Nur so reicht sein Klebebereich über alle Normen und nicht bloß über den
+ Vorspann. Seine beiden Felder tragen die Form der Legende des Antragsvordrucks. */
.spaltenkopf {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
- font-weight: bold;
- border-bottom: 2px solid var(--rand);
- padding: 0.5rem 0;
position: sticky;
top: 0;
- background: inherit;
+ z-index: 1;
+ margin-top: 1.25rem;
+ padding: 0.6rem 0 0.6rem 3rem;
+ background: var(--bg);
}
- section.norm { border-bottom: 1px solid var(--rand); padding: 0.7rem 0; }
- section.norm h2 { font-size: 1.15rem; margin: 0.3rem 0; }
+ .spaltenkopf div {
+ padding: 0.3rem 0.8rem;
+ background: var(--fg);
+ color: var(--bg);
+ font-size: 0.8rem;
+ font-weight: bold;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ }
+
+ /* Der Steg links trägt die Randziffer, wie im Vordruck die Feldziffer; sie macht die
+ Abschnitte überdies zitierbar. */
+ section { position: relative; padding-left: 3rem; }
+ section.norm {
+ counter-increment: norm;
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+ border-bottom: 1px solid var(--raster);
+ }
+ section.norm::before {
+ content: counter(norm);
+ position: absolute;
+ top: 1.15rem;
+ left: 0;
+ width: 1.5rem;
+ height: 1.5rem;
+ border: 1px solid var(--amt);
+ color: var(--amt);
+ font-size: 0.8rem;
+ font-weight: bold;
+ line-height: 1.4rem;
+ text-align: center;
+ }
+ section.norm h2 { font-size: 1.05rem; margin: 0 0 0.5rem; letter-spacing: 0.02em; }
+
.vergleich {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
align-items: start;
}
+ /* Die alte Fassung liegt auf dem Kastenton wie ein Durchschlag, die neue auf
+ Bogenweiß; beim Springen zwischen den Spalten ist damit ohne Hinsehen klar, wo man
+ steht. Die Hinterlegungen der Änderungen heben sich von beiden Gründen ab. */
.vergleich > div {
+ padding: 0.75rem 0.9rem;
+ border: 1px solid var(--raster);
white-space: pre-wrap;
overflow-wrap: anywhere;
+ font-family: var(--antiqua);
font-size: 0.95rem;
+ line-height: 1.45;
}
+ .vergleich > .alt { background: var(--kasten); }
+ .vergleich > .neu { background: var(--bg); }
+
del, .alt del {
background: var(--del-bg);
color: var(--del-fg);
@@ -288,31 +455,112 @@ public final class HtmlRenderer {
color: var(--ins-fg);
text-decoration: underline;
}
- .leer { color: var(--dezent); font-style: italic; }
+ .leer { color: var(--muted); font-style: italic; }
+
/* Kästchen in Versalien; die Farbe folgt derselben Regel wie im Diff. Beschriftet
- sind sie ohnehin, sodass die Farbe hier nur bestätigt, was dasteht. */
+ sind sie ohnehin, sodass die Farbe hier nur bestätigt, was dasteht. Der Rahmen
+ steht auch dort, wo die Hinterlegung schwach wirkt. */
.badge {
- font-family: system-ui, sans-serif;
+ font-family: var(--grotesk);
font-size: 0.7rem;
font-weight: normal;
text-transform: uppercase;
letter-spacing: 0.06em;
- border: 1px solid transparent;
+ border: 1px solid var(--raster);
padding: 0.1rem 0.55rem;
vertical-align: middle;
+ white-space: nowrap;
+ }
+ .neu-badge { background: var(--ins-bg); color: var(--ins-fg); border-color: var(--ins-fg); }
+ .aufgehoben-badge {
+ background: var(--del-bg);
+ color: var(--del-fg);
+ border-color: var(--del-fg);
+ }
+ .geaendert-badge { border-color: var(--raster); color: var(--muted); }
+
+ /* Die Abschnittsüberschriften treten als Balken auf wie die Legende des Feldblocks. */
+ section.gliederung-aenderungen > h2, section.manuell > h2 {
+ display: inline-block;
+ margin: 0 0 0.9rem;
+ padding: 0.3rem 0.8rem;
+ background: var(--fg);
+ color: var(--bg);
+ font-size: 0.8rem;
+ font-weight: bold;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ }
+ section.gliederung-aenderungen { padding-top: 1.25rem; }
+ section.manuell { margin-top: 2rem; padding-top: 1.5rem; border-top: 3px solid var(--amt); }
+ section.manuell h3 {
+ margin: 1.25rem 0 0.5rem;
+ font-size: 0.8rem;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
}
- .neu-badge { background: var(--ins-bg); color: var(--ins-fg); }
- .aufgehoben-badge { background: var(--del-bg); color: var(--del-fg); }
- .geaendert-badge { border-color: var(--rand); color: var(--dezent); }
- section.manuell { margin-top: 2rem; }
section.manuell li { margin-bottom: 0.7rem; }
- .originaltext { color: var(--dezent); font-size: 0.85rem; }
+ .originaltext { font-family: var(--antiqua); color: var(--muted); font-size: 0.85rem; }
+
+ footer {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ gap: 0.5rem 1.5rem;
+ margin-top: 2.5rem;
+ padding-top: 0.9rem;
+ border-top: 1px solid var(--fg);
+ font-size: 0.8125rem;
+ color: var(--muted);
+ }
+
+ /* Zwei Spalten Gesetzestext nebeneinander sind auf dem Telefon nicht zu lesen. Gestapelt
+ trägt der Spaltenkopf nichts mehr; deshalb beschriftet sich dort jede Spalte selbst. */
+ @media (max-width: 60rem) {
+ .spaltenkopf { display: none; }
+ .vergleich { grid-template-columns: 1fr; }
+ section { padding-left: 2.25rem; }
+ .vergleich > div::before {
+ display: block;
+ margin-bottom: 0.4rem;
+ font-family: var(--grotesk);
+ font-size: 0.7rem;
+ font-weight: bold;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--muted);
+ }
+ .vergleich > .alt::before { content: "Alte Fassung"; }
+ .vergleich > .neu::before { content: "Neue Fassung"; }
+ }
+
+ /* Gedruckt wird stets auf weißes Papier, auch aus einem dunkel eingestellten Browser
+ heraus: prefers-color-scheme gilt im Druck fort. Deshalb ist hier das ganze
+ Farbgerüst zurückzusetzen und nicht nur ein Teil davon — sonst käme die alte Spalte
+ als schwarzer Block aus dem Drucker. */
@media print {
- .vergleich { break-inside: avoid; }
+ :root {
+ --fg: #000;
+ --bg: #fff;
+ --papier: #fff;
+ --muted: #333;
+ --raster: #999;
+ --kasten: #f2f0ea;
+ --amt: #000;
+ --del-bg: #ffd7d7;
+ --del-fg: #8b0000;
+ --ins-bg: #d7f5d7;
+ --ins-fg: #005f00;
+ }
+ body { margin: 0; padding: 0; max-width: none; border: none; font-size: 10pt; }
+ .spaltenkopf { position: static; }
+ .vergleich, section.norm { break-inside: avoid; }
/* Ohne diese Festlegung wirft der Druck die Hinterlegung weg. Durchstreichung
und Unterstreichung überstehen ihn ohnehin und tragen die Aussage auch dort,
- wo schwarzweiß gedruckt wird. */
- del, ins, .badge, .entwurfshinweis {
+ wo schwarzweiß gedruckt wird; der Spaltenbalken und der Durchschlagston der
+ alten Fassung aber haben keine solche zweite Gestalt. */
+ del, ins, .badge, .entwurfshinweis, .spaltenkopf div, .vergleich > .alt,
+ section.gliederung-aenderungen > h2, section.manuell > h2 {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
diff --git a/src/main/resources/eu/mulk/aendggner/web/style.css b/src/main/resources/eu/mulk/aendggner/web/style.css
index 46d583f..81c16d7 100644
--- a/src/main/resources/eu/mulk/aendggner/web/style.css
+++ b/src/main/resources/eu/mulk/aendggner/web/style.css
@@ -487,7 +487,9 @@ footer nav {
/* Ein Formblatt gehört ausgedruckt: ohne Unterlage, ohne Bogenrand, mit Linien in
Schwarz. Der Knopf und das Merkblatt entfallen, weil auf Papier weder gedrückt noch
- aufgeklappt wird. */
+ aufgeklappt wird. Gedruckt wird stets auf weißes Papier, auch aus einem dunkel
+ eingestellten Browser heraus — prefers-color-scheme gilt im Druck fort. Deshalb ist
+ das ganze Farbgerüst zurückzusetzen und nicht nur ein Teil davon. */
@media print {
:root {
--fg: #000;
@@ -498,6 +500,8 @@ footer nav {
--raster: #999;
--kasten: #fff;
--amt: #000;
+ --warnung: #8b0000;
+ --bestaetigung: #005f00;
}
body {