aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FASSUNGEN.txt71
-rw-r--r--src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java430
-rw-r--r--src/main/resources/eu/mulk/aendggner/web/datenschutz.html30
-rw-r--r--src/main/resources/eu/mulk/aendggner/web/favicon.svg14
-rw-r--r--src/main/resources/eu/mulk/aendggner/web/impressum.html30
-rw-r--r--src/main/resources/eu/mulk/aendggner/web/index.html271
-rw-r--r--src/main/resources/eu/mulk/aendggner/web/style.css676
-rw-r--r--src/test/java/eu/mulk/aendggner/synopse/HtmlRendererTest.java14
8 files changed, 794 insertions, 742 deletions
diff --git a/FASSUNGEN.txt b/FASSUNGEN.txt
index ab1fb2b..88c3cc5 100644
--- a/FASSUNGEN.txt
+++ b/FASSUNGEN.txt
@@ -282,6 +282,77 @@ Drei Mängel, die dabei zutage traten
darunter zwei neue für Kennung, Fußsteg und Entwurfsausweis.
+Artikel 11
+Berichtigung der Gestaltung nach dem Vorbild eines wirklichen Vordrucks
+
+Die Artikel 7 und 9 hatten sich am Begriff des amtlichen Formulars orientiert,
+nicht an einem solchen. Der Abgleich mit einem wirklichen Bundesvordruck — dem
+„Antrag auf Erteilung einer Bescheinigung für den Lohnsteuerabzug bei erweiterter
+unbeschränkter Einkommensteuerpflicht“ — hat ergeben, dass die bisherige Fassung
+in fast jedem Merkmal danebenlag. Sie wird berichtigt.
+
+(1) Maßgeblich ist eine einzige Regel, die im Muster sogar ausgeschrieben steht:
+ „Weiße Felder bitte ausfüllen“. Grau ist, was die Stelle gedruckt hat —
+ Beschriftungen, Leitspalten, Abschnittsköpfe, die Verfügung am Ende; weiß
+ ist, was der Antragsteller beiträgt. Bisher war es umgekehrt: weißer Bogen
+ mit blass getönten Kästen. Diese Regel trägt fortan die gesamte Gestaltung
+ und ist im Vordruck selbst benannt.
+
+(2) Schmuckfarbe entfällt ersatzlos. Das Amtsrot der Artikel 7 und 9 war
+ erfunden; wirkliche Bundesvordrucke führen keine. Rot und Grün treten allein
+ dort auf, wo sie etwas bedeuten: Fehler und Bestätigung in der Verfügung,
+ gestrichener und eingefügter Wortlaut in der Synopse.
+
+(3) Die Zellen stoßen aneinander, ohne Abstand und ohne Rundung, verbunden durch
+ schwarze Haarlinien. Die Rahmen sind halbiert — außen oben und links, an den
+ Zellen unten und rechts —, damit zwischen zwei Zellen eine einzige Linie
+ steht und nicht zwei.
+
+(4) Die Beschriftung steht klein im Feld oben links, die Erläuterung in noch
+ kleinerer Schrift in Klammern dahinter; darunter bleibt der Platz für die
+ Eintragung. Die fette Zeile über einem Eingabefeld nebst gesondertem
+ Hinweisabsatz entfällt.
+
+(5) Links läuft die Leitspalte mit den Abschnittsbezeichnungen („Angaben zum
+ Stammgesetz“, „Angaben zu den Änderungen“, „Antragstellung“). Auf schmalen
+ Geräten tritt sie über ihre Felder, als voller Beschriftungsstreifen — eine
+ Form, die das Muster ebenfalls kennt.
+
+(6) Das Ankreuzfeld ist ein Kästchen vor dem Text und wird angekreuzt, nicht
+ angehakt.
+
+(7) Der Abschnitt „Zur Beachtung:“ nimmt auf, was bisher über Tagline,
+ Haftungsabsatz und noscript-Kasten verstreut war.
+
+(8) Die Verfügung der Zentralstelle tritt an die Stelle der bloßen Meldung: ein
+ grau umrandeter Abschnitt mit zentrierter Überschrift, wie im Muster die
+ „Verfügung des Finanzamts“. Er steht auch dann schon da, wenn er noch leer
+ ist, und trägt dann den Vermerk, dass er nach Absenden ausgefüllt wird; ein
+ Vordruck zeigt seine Abschnitte, bevor sie ausgefüllt sind.
+
+(9) Die Kennung wandert aus dem gerahmten Verzeichnis oben rechts in die
+ Fußecken: links die Vordrucknummer, rechts der Ausgabestand, beide winzig
+ und ohne Zierrat. Impressum und Datenschutz führen ÄG-1/A und ÄG-1/B.
+
+(10) Die Schrift ist Arial in dreizehn Achteln eines Gevierts, die Beschriftungen
+ in elf; Sperrung und Versalien entfallen bis auf die Kästchen der Synopse.
+
+(11) Die Synopse folgt demselben Gerüst: Der Vorspann ist ein
+ Beschriftungsstreifen aus grauen Bezeichnungen und weißen Eintragungen, die
+ Spaltenköpfe und die Abschnittsüberschriften sind graue Streifen statt
+ schwarzer Balken, die Randziffer sitzt in einem Kästchen, und der Fußsteg
+ trägt Vordrucknummer und Ausgabestand in den Ecken.
+
+(12) Dabei ist ein weiterer Mangel behoben worden: Der Grund der Leitspalte hing
+ am Block und nicht an der Zelle; im Druck fällt die Fläche des Blocks weg,
+ sodass die Leitspalte weiß herausgekommen wäre. Das Grau ist keine Zier — es
+ sagt, welche Felder auszufüllen sind — und wird deshalb ausdrücklich
+ mitgedruckt.
+
+(13) Dreihundertsiebenundzwanzig Testfälle bestehen; die beiden Prüffälle des
+ Artikels 9 sind auf den neuen Vorspann umgestellt.
+
+
════════════════════════════════════════════════════════════════════════════════
Fassung vom 22. August 2026,
zuletzt geändert durch die am 22. August 2026 vorgenommenen Änderungen
diff --git a/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java b/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java
index 09a60de..6357b29 100644
--- a/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java
+++ b/src/main/java/eu/mulk/aendggner/synopse/HtmlRenderer.java
@@ -33,7 +33,7 @@ public final class HtmlRenderer {
.append(esc(synopse.alt().jurabk()))
.append("</title>\n<style>\n")
.append(CSS)
- .append("</style>\n</head>\n<body>\n");
+ .append("</style>\n</head>\n<body>\n<div class=\"bogen\">\n");
rendereKopf(sb, synopse, quelleBeschreibung, entwurfsfassung);
@@ -55,71 +55,76 @@ public final class HtmlRenderer {
rendereFuss(sb);
- sb.append("</body>\n</html>\n");
+ sb.append("</div>\n</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.
+ * Der Kopf des Vordrucks ÄG-2: Titel, ausstellende Stelle, darunter der Vorspann als
+ * Beschriftungsstreifen — grau, was die Stelle gedruckt hat, weiß die Eintragung daneben.
*/
private static void rendereKopf(
StringBuilder sb, Synopse synopse, String quelle, boolean entwurfsfassung) {
- 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>")
+ sb.append("<header>\n<h1>Synopse zum Stammgesetz ")
.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");
+ .append("</h1>\n<p class=\"stelle\">")
+ .append(LANGNAME)
+ .append("</p>\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");
+ "<p class=\"entwurfshinweis\"><strong>Entwurfsfassung — nicht geltendes Recht.</strong>"
+ + " Die neue Fassung gibt den Stand des Gesetzgebungsverfahrens wieder.</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)
.count();
- sb.append("<p class=\"statistik\">")
- .append(geaendert)
- .append(" geänderte Normen, ")
- .append(synopse.manuellZuPruefen().size())
- .append(" manuell zu prüfende Befehle</p>\n");
- sb.append("</div>\n");
+ sb.append("<dl class=\"vorspann\">\n");
+ vorspannZeile(sb, "Stammgesetz", synopse.alt().jurabk());
+ if (synopse.alt().langue() != null) {
+ vorspannZeile(sb, "Langbezeichnung", synopse.alt().langue());
+ }
+ vorspannZeile(sb, "Grundlage", quelle);
+ vorspannZeile(sb, "Erstellt am", LocalDate.now().toString());
+ vorspannZeile(
+ sb,
+ "Umfang",
+ geaendert
+ + " geänderte Normen, "
+ + synopse.manuellZuPruefen().size()
+ + " manuell zu prüfende Befehle");
+ vorspannZeile(sb, "Geltung", entwurfsfassung ? "nichtamtlich, Entwurfsstand" : "nichtamtlich");
+ sb.append("</dl>\n");
+ }
+
+ private static void vorspannZeile(StringBuilder sb, String bezeichnung, String wert) {
+ sb.append("<dt>")
+ .append(esc(bezeichnung))
+ .append("</dt><dd>")
+ .append(esc(wert))
+ .append("</dd>\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.
+ * Der Fußsteg trägt wie im Muster die Vordrucknummer links und den Ausgabestand rechts. 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")
+ sb.append("<footer>\n<span class=\"vordrucknummer\">ÄG&#8209;2</span>\n")
.append(
- "<span class=\"nebenquelle\">Ohne Gewähr; maßgeblich ist allein die amtliche"
+ "<span>Erstellt mit ÄndGgner. Ohne Gewähr; maßgeblich ist allein die amtliche"
+ " Verkündung im jeweiligen Gesetz- oder Verordnungsblatt.</span>\n")
- .append("</footer>\n");
+ .append("<span class=\"ausgabe\">")
+ .append(LocalDate.now())
+ .append("</span>\n</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";
+ "ÄndGgner — 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()) {
@@ -251,45 +256,50 @@ public final class HtmlRenderer {
private static final String CSS =
"""
- /* 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. */
+ /* Der Vordruck ÄG-2, gesetzt nach demselben Muster wie die Aufgabeseite (siehe
+ src/main/resources/eu/mulk/aendggner/web/style.css): weißes Papier, schwarze
+ Haarlinien, grauer Raster für alles, was die Stelle gedruckt hat. Das Farbgerüst
+ wird hier ein zweites Mal geführt, weil diese Datei aus einem blob:-Verweis
+ geöffnet und im Befehlszeilenbetrieb als einzelne Datei abgelegt wird; sie kann
+ kein fremdes Stilblatt einbinden. Wer dort etwas ändert, ändere es hier mit.
+
+ Die Schrift ist geteilt: Der Vordruck steht in der Groteske, der Wortlaut der
+ Normen in der Antiqua. Amtskopf und Vorschrift sind zweierlei, im Gesetzblatt wie
+ hier.
+
+ Schmuckfarbe gibt es nicht. 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;
- --papier: #f3f1ea;
- --muted: #595959;
- --raster: #d6d2c6;
- --kasten: #f0ede4;
- --amt: #8b0f21;
+ --fg: #000;
+ --papier: #fff;
+ --feld: #fff;
+ --grund: #d5d5d5;
+ --tint: #e4e4e4;
+ --linie: #000;
+ --muted: #444;
+ --tisch: #9a9a9a;
--del-bg: #ffd7d7;
--del-fg: #8b0000;
--ins-bg: #d7f5d7;
--ins-fg: #005f00;
- --grotesk: system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
+ --grotesk: Arial, "Helvetica Neue", Helvetica, system-ui, sans-serif;
--antiqua: Georgia, "Times New Roman", serif;
}
+ /* Im Dunkeln kehrt sich nicht die Farbe um, sondern das Verhältnis: Der Grund der
+ Stelle bleibt heller als das Feld. */
@media (prefers-color-scheme: dark) {
:root {
- --fg: #e6e6e6;
- --bg: #1c1c1c;
- --papier: #0f0f0f;
- --muted: #a0a0a0;
- --raster: #3c3c3c;
- --kasten: #242424;
- --amt: #e79aa4;
+ --fg: #e8e8e8;
+ --papier: #1a1a1a;
+ --feld: #101010;
+ --grund: #333333;
+ --tint: #242424;
+ --linie: #7a7a7a;
+ --muted: #a8a8a8;
+ --tisch: #000;
--del-bg: #5a1f1f;
--del-fg: #ffb3b3;
--ins-bg: #1f4a1f;
@@ -297,153 +307,136 @@ public final class HtmlRenderer {
}
}
* { box-sizing: border-box; }
- /* Die Unterlage endet nie, auch wenn der Bogen kürzer ist als das Fenster. */
- html { background: var(--papier); }
+ html { background: var(--tisch); }
body {
counter-reset: norm;
+ margin: 0;
+ padding: 1.5rem 1rem;
font-family: var(--grotesk);
- line-height: 1.5;
- max-width: 90rem;
- margin: 2rem auto 3rem;
- padding: 2rem 2.25rem 2.5rem;
- border: 1px solid var(--fg);
+ font-size: 0.8125rem;
+ line-height: 1.4;
color: var(--fg);
- background: var(--bg);
}
- /* 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; }
+ /* Ein Blatt Papier hat keinen Rahmen; die Kante entsteht aus dem Farbunterschied zur
+ Unterlage. Die Breite ist größer als beim Antrag, weil zwei Spalten sie brauchen. */
+ .bogen {
+ max-width: 88rem;
+ margin: 0 auto;
+ padding: 1.75rem 1.75rem 0.75rem;
+ background: var(--papier);
}
-
- /* 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);
+ @media (max-width: 40rem) {
+ body { padding: 0; }
+ .bogen { padding: 1rem 0.75rem 0.5rem; }
}
- .langname {
- margin: 0 0 0.3rem;
- max-width: 30rem;
+
+ h1 { margin: 0 0 0.5rem; font-size: 1rem; line-height: 1.35; }
+ .stelle { margin: 0 0 0.9rem; font-size: 0.6875rem; color: var(--muted); }
+
+ .entwurfshinweis {
+ margin: 0 0 0.9rem;
+ padding: 0.45rem 0.6rem;
+ border: 1px solid var(--linie);
+ border-left: 4px solid var(--del-fg);
+ background: var(--feld);
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 {
+
+ /* Der Vorspann ist der Beschriftungsstreifen des Musters: links grau die Bezeichnung,
+ rechts weiß die Eintragung, Zelle an Zelle ohne Abstand. */
+ .vorspann {
display: grid;
- grid-template-columns: auto auto;
- gap: 0 0.6rem;
+ grid-template-columns: 10rem 1fr;
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; }
+ border-top: 1px solid var(--linie);
+ border-left: 1px solid var(--linie);
+ font-size: 0.6875rem;
}
-
- .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;
+ .vorspann dt {
+ padding: 0.2rem 0.5rem;
+ border-right: 1px solid var(--linie);
+ border-bottom: 1px solid var(--linie);
+ background: var(--grund);
+ font-weight: bold;
}
- .entwurfshinweis {
- margin: 0 0 0.9rem;
- padding: 0.9rem 1.1rem;
- border: 1px solid var(--raster);
- border-left: 4px solid var(--del-fg);
- background: var(--kasten);
- font-size: 0.9rem;
+ .vorspann dd {
+ margin: 0;
+ padding: 0.2rem 0.5rem;
+ border-right: 1px solid var(--linie);
+ border-bottom: 1px solid var(--linie);
+ background: var(--feld);
+ overflow-wrap: anywhere;
}
- /* 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. */
+ /* Der Spaltenkopf steht mit der Gegenüberstellung in einem Block: Sein Klebebereich
+ reicht damit über alle Normen und endet vor dem Abschnitt „Manuell prüfen“. Seine
+ beiden Felder sind Beschriftungsstreifen wie im Vordruck, also grau. */
.spaltenkopf {
display: grid;
grid-template-columns: 1fr 1fr;
- gap: 1rem;
+ gap: 0.75rem;
position: sticky;
top: 0;
z-index: 1;
margin-top: 1.25rem;
- padding: 0.6rem 0 0.6rem 3rem;
- background: var(--bg);
+ padding: 0.5rem 0 0.5rem 2.5rem;
+ background: var(--papier);
}
.spaltenkopf div {
- padding: 0.3rem 0.8rem;
- background: var(--fg);
- color: var(--bg);
- font-size: 0.8rem;
+ padding: 0.25rem 0.5rem;
+ border: 1px solid var(--linie);
+ background: var(--grund);
+ font-size: 0.6875rem;
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; }
+ /* Der Steg links trägt die Randziffer in einem Kästchen, wie der Antrag das
+ Ankreuzfeld; sie macht die Abschnitte überdies zitierbar. */
+ section { position: relative; padding-left: 2.5rem; }
section.norm {
counter-increment: norm;
- padding-top: 1rem;
- padding-bottom: 1rem;
- border-bottom: 1px solid var(--raster);
+ padding-top: 0.9rem;
+ padding-bottom: 0.9rem;
+ border-bottom: 1px solid var(--linie);
}
section.norm::before {
content: counter(norm);
position: absolute;
- top: 1.15rem;
+ top: 1rem;
left: 0;
width: 1.5rem;
- height: 1.5rem;
- border: 1px solid var(--amt);
- color: var(--amt);
- font-size: 0.8rem;
+ height: 1.2rem;
+ border: 1px solid var(--linie);
+ background: var(--grund);
+ font-size: 0.6875rem;
font-weight: bold;
- line-height: 1.4rem;
+ line-height: 1.1rem;
text-align: center;
}
- section.norm h2 { font-size: 1.05rem; margin: 0 0 0.5rem; letter-spacing: 0.02em; }
+ section.norm h2 { font-size: 0.8125rem; margin: 0 0 0.15rem; }
+ .gliederung, .ursachen { color: var(--muted); font-size: 0.6875rem; margin: 0.1rem 0; }
.vergleich {
display: grid;
grid-template-columns: 1fr 1fr;
- gap: 1rem;
+ gap: 0.75rem;
align-items: start;
+ margin-top: 0.5rem;
}
- /* 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
+ /* Die alte Fassung liegt auf dem hellen Raster wie ein Durchschlag, die neue auf dem
+ weißen Feld; 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);
+ padding: 0.5rem 0.6rem;
+ border: 1px solid var(--linie);
white-space: pre-wrap;
overflow-wrap: anywhere;
font-family: var(--antiqua);
- font-size: 0.95rem;
+ font-size: 0.875rem;
line-height: 1.45;
}
- .vergleich > .alt { background: var(--kasten); }
- .vergleich > .neu { background: var(--bg); }
+ .vergleich > .alt { background: var(--tint); }
+ .vergleich > .neu { background: var(--feld); }
del, .alt del {
background: var(--del-bg);
@@ -455,111 +448,104 @@ public final class HtmlRenderer {
color: var(--ins-fg);
text-decoration: underline;
}
- .leer { color: var(--muted); font-style: italic; }
+ .leer { font-family: var(--grotesk); font-size: 0.75rem; color: var(--muted); }
- /* 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. Der Rahmen
- steht auch dort, wo die Hinterlegung schwach wirkt. */
+ /* Kästchen wie die Ankreuzfelder des Antrags: eckig, haarfein umrandet. Beschriftet
+ sind sie ohnehin, sodass die Farbe nur bestätigt, was dasteht. */
.badge {
font-family: var(--grotesk);
- font-size: 0.7rem;
+ font-size: 0.625rem;
font-weight: normal;
text-transform: uppercase;
- letter-spacing: 0.06em;
- border: 1px solid var(--raster);
- padding: 0.1rem 0.55rem;
+ border: 1px solid var(--linie);
+ padding: 0 0.4rem;
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); }
+ .neu-badge { background: var(--ins-bg); color: var(--ins-fg); }
+ .aufgehoben-badge { background: var(--del-bg); color: var(--del-fg); }
+ .geaendert-badge { background: var(--grund); color: var(--fg); }
- /* Die Abschnittsüberschriften treten als Balken auf wie die Legende des Feldblocks. */
+ /* Die Abschnittsüberschriften sind Beschriftungsstreifen über die volle Breite, wie im
+ Muster die Zeile „Verfügung des Finanzamts“. */
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;
+ margin: 0 0 0.6rem;
+ padding: 0.25rem 0.5rem;
+ border: 1px solid var(--linie);
+ background: var(--grund);
+ font-size: 0.75rem;
+ text-align: center;
}
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;
- }
- section.manuell li { margin-bottom: 0.7rem; }
- .originaltext { font-family: var(--antiqua); color: var(--muted); font-size: 0.85rem; }
+ section.manuell { margin-top: 1.5rem; padding-top: 1.25rem; }
+ section.manuell h3 { margin: 1rem 0 0.4rem; font-size: 0.6875rem; }
+ section.manuell li { margin-bottom: 0.6rem; font-size: 0.75rem; }
+ .originaltext { font-family: var(--antiqua); color: var(--muted); font-size: 0.8125rem; }
+ /* Vordrucknummer links, Ausgabestand rechts, beide winzig und ohne Zierrat. */
footer {
display: flex;
flex-wrap: wrap;
+ align-items: baseline;
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;
+ gap: 0.4rem 1rem;
+ margin-top: 1.5rem;
+ padding: 0.4rem 0 0.6rem;
+ font-size: 0.625rem;
color: var(--muted);
}
+ .vordrucknummer, .ausgabe { white-space: nowrap; }
/* 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; }
+ .vorspann { grid-template-columns: 7rem 1fr; }
+ section { padding-left: 2rem; }
.vergleich > div::before {
display: block;
- margin-bottom: 0.4rem;
+ margin: -0.5rem -0.6rem 0.4rem;
+ padding: 0.15rem 0.6rem;
+ border-bottom: 1px solid var(--linie);
+ background: var(--grund);
font-family: var(--grotesk);
- font-size: 0.7rem;
+ font-size: 0.625rem;
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. */
+ heraus: prefers-color-scheme gilt im Druck fort. Deshalb ist 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 {
:root {
--fg: #000;
- --bg: #fff;
--papier: #fff;
+ --feld: #fff;
+ --grund: #d5d5d5;
+ --tint: #e4e4e4;
+ --linie: #000;
--muted: #333;
- --raster: #999;
- --kasten: #f2f0ea;
- --amt: #000;
+ --tisch: #fff;
--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; }
+ body { padding: 0; font-size: 9pt; }
+ .bogen { max-width: none; padding: 0; }
.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; der Spaltenbalken und der Durchschlagston der
- alten Fassung aber haben keine solche zweite Gestalt. */
+ /* 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; der Raster der Stelle aber hat keine solche zweite
+ Gestalt — er sagt, was gedruckt und was eingetragen ist. */
del, ins, .badge, .entwurfshinweis, .spaltenkopf div, .vergleich > .alt,
+ .vorspann dt, section.norm::before,
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/datenschutz.html b/src/main/resources/eu/mulk/aendggner/web/datenschutz.html
index b217b89..e88a699 100644
--- a/src/main/resources/eu/mulk/aendggner/web/datenschutz.html
+++ b/src/main/resources/eu/mulk/aendggner/web/datenschutz.html
@@ -10,20 +10,13 @@
<link rel="stylesheet" href="style.css">
</head>
<body>
- <header class="briefkopf">
- <div class="dienststelle">
- <p class="langname">
- Nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen
- anhand von Änderungsvorschriften des Bundes und der Länder
- </p>
- <p class="wortmarke"><a href="index.html">ÄndGgner</a></p>
- </div>
+<div class="bogen">
- <dl class="kennung">
- <dt>Formblatt</dt><dd>ÄG&#8209;1/B</dd>
- <dt>Anlage</dt><dd>Datenschutz</dd>
- <dt>Geltung</dt><dd>nichtamtlich</dd>
- </dl>
+ <header>
+ <p class="stelle">
+ ÄndGgner — nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen
+ anhand von Änderungsvorschriften des Bundes und der Länder
+ </p>
</header>
<main>
@@ -126,8 +119,13 @@
<p>Stand: 22. August 2026.</p>
</main>
<footer>
- <nav><a href="index.html">Zurück zum Formular</a></nav>
- <span class="nebenquelle">(<a href="https://gerrit.benkard.de/plugins/gitiles/aendggner">Git</a>)</span>
+ <span class="vordrucknummer">ÄG&#8209;1/B</span>
+ <nav>
+ <a href="index.html">Zurück zum Vordruck</a> ·
+ <a href="impressum.html">Impressum</a>
+ </nav>
+ <span class="ausgabe">08.26</span>
</footer>
+
+</div>
</body>
-</html>
diff --git a/src/main/resources/eu/mulk/aendggner/web/favicon.svg b/src/main/resources/eu/mulk/aendggner/web/favicon.svg
index 2f54d8f..b619c30 100644
--- a/src/main/resources/eu/mulk/aendggner/web/favicon.svg
+++ b/src/main/resources/eu/mulk/aendggner/web/favicon.svg
@@ -1,13 +1,13 @@
<!-- SPDX-FileCopyrightText: 2020 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
SPDX-License-Identifier: AGPL-3.0-or-later -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="ÄndGgner">
- <!-- Farben wie in style.css: Papier, Amtsrot als Rahmen des Vordrucks, schwarzes
- Zeichen. Ein Favicon erbt keine CSS-Variablen, deshalb stehen die Werte hier
+ <!-- Farben wie in style.css: Vordruckgrau als Grund, ein weißes Feld, schwarze Haarlinie,
+ schwarzes Zeichen. Ein Favicon erbt keine CSS-Variablen, deshalb stehen die Werte hier
ausgeschrieben. -->
- <rect width="32" height="32" fill="#fff"/>
- <rect x="1" y="1" width="30" height="30" fill="none" stroke="#8b0f21" stroke-width="2"/>
- <text x="16" y="17.5" fill="#111"
- font-family="system-ui, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif"
- font-size="21" font-weight="bold" text-anchor="middle"
+ <rect width="32" height="32" fill="#d5d5d5"/>
+ <rect x="0.5" y="0.5" width="31" height="31" fill="none" stroke="#000"/>
+ <rect x="4.5" y="8.5" width="23" height="19" fill="#fff" stroke="#000"/>
+ <text x="16" y="19" fill="#000" font-family="Arial, Helvetica, sans-serif"
+ font-size="17" font-weight="bold" text-anchor="middle"
dominant-baseline="central">§</text>
</svg>
diff --git a/src/main/resources/eu/mulk/aendggner/web/impressum.html b/src/main/resources/eu/mulk/aendggner/web/impressum.html
index cce8797..03f4063 100644
--- a/src/main/resources/eu/mulk/aendggner/web/impressum.html
+++ b/src/main/resources/eu/mulk/aendggner/web/impressum.html
@@ -10,20 +10,13 @@
<link rel="stylesheet" href="style.css">
</head>
<body>
- <header class="briefkopf">
- <div class="dienststelle">
- <p class="langname">
- Nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen
- anhand von Änderungsvorschriften des Bundes und der Länder
- </p>
- <p class="wortmarke"><a href="index.html">ÄndGgner</a></p>
- </div>
+<div class="bogen">
- <dl class="kennung">
- <dt>Formblatt</dt><dd>ÄG&#8209;1/A</dd>
- <dt>Anlage</dt><dd>Impressum</dd>
- <dt>Geltung</dt><dd>nichtamtlich</dd>
- </dl>
+ <header>
+ <p class="stelle">
+ ÄndGgner — nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen
+ anhand von Änderungsvorschriften des Bundes und der Länder
+ </p>
</header>
<main>
@@ -72,8 +65,13 @@
</p>
</main>
<footer>
- <nav><a href="index.html">Zurück zum Formular</a></nav>
- <span class="nebenquelle">(<a href="https://gerrit.benkard.de/plugins/gitiles/aendggner">Git</a>)</span>
+ <span class="vordrucknummer">ÄG&#8209;1/A</span>
+ <nav>
+ <a href="index.html">Zurück zum Vordruck</a> ·
+ <a href="datenschutz.html">Datenschutz</a>
+ </nav>
+ <span class="ausgabe">08.26</span>
</footer>
+
+</div>
</body>
-</html>
diff --git a/src/main/resources/eu/mulk/aendggner/web/index.html b/src/main/resources/eu/mulk/aendggner/web/index.html
index 26ff522..4a0bbdd 100644
--- a/src/main/resources/eu/mulk/aendggner/web/index.html
+++ b/src/main/resources/eu/mulk/aendggner/web/index.html
@@ -15,152 +15,165 @@
<script src="app.js" defer></script>
</head>
<body>
- <header class="briefkopf">
- <div class="dienststelle">
- <p class="langname">
- Nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen
- anhand von Änderungsvorschriften des Bundes und der Länder
- </p>
- <h1>ÄndGgner</h1>
- </div>
-
- <dl class="kennung">
- <dt>Formblatt</dt><dd>ÄG&#8209;1</dd>
- <dt>Vorgang</dt><dd>Synopse</dd>
- <dt>Geltung</dt><dd>nichtamtlich</dd>
- </dl>
+<div class="bogen">
+
+ <header>
+ <h1>Antrag auf Erstellung einer Synopse<br>
+ zu einem Stammgesetz nach Maßgabe eines oder mehrerer Änderungsdokumente</h1>
+ <p class="stelle">
+ ÄndGgner — nichtamtliche Zentralstelle für die maschinelle Fortschreibung von Stammgesetzen
+ anhand von Änderungsvorschriften des Bundes und der Länder
+ </p>
</header>
- <main>
- <p class="betreff">
- Änderungsgesetze automatisch auf ein Stammgesetz anwenden und als Synopse darstellen.
+ <section class="beachtung">
+ <h2>Zur Beachtung:</h2>
+ <p>
+ Dieser Vordruck wendet ein oder mehrere Änderungsdokumente — verkündete Änderungsgesetze,
+ Gesetzentwürfe, Änderungsanträge und Beschlussempfehlungen — selbsttätig auf ein Stammgesetz
+ an und stellt das Ergebnis als zweispaltige Synopse gegenüber. Die Dokumentart wird aus dem
+ Text erkannt; eine Angabe darüber ist nicht zu machen.
+ </p>
+ <p>
+ Die gewählten Dateien <strong>verlassen Ihren Rechner nicht</strong>. Die gesamte Auswertung
+ läuft als WebAssembly-Programm in Ihrem Browser; es wird nichts hochgeladen und nichts
+ gespeichert.
+ </p>
+ <p>
+ Die Synopse wird automatisch erstellt und ist <strong>ohne Gewähr</strong> für Vollständigkeit
+ und Richtigkeit; sie ersetzt keine Rechtsberatung. Maßgeblich ist allein die amtliche
+ Verkündung im jeweiligen Gesetz- oder Verordnungsblatt. Uneindeutige Änderungsbefehle werden
+ zur manuellen Prüfung markiert statt stillschweigend verworfen.
</p>
-
<noscript>
- <aside class="kasten warnung">
- <h2>Hinweis</h2>
- <p>
- Dieses Werkzeug rechnet im Browser statt auf dem Server: Es braucht JavaScript und
- WebAssembly. Ohne sie bleibt das nachstehende Formular wirkungslos. Wer beides nicht
- einschalten möchte, verwende die Befehlszeilenfassung — sie liegt dem
- <a href="aendggner-quelltext.tar.gz">Quelltext</a> bei und leistet dasselbe.
- </p>
- </aside>
- </noscript>
-
- <details class="einfuehrung">
- <summary>Noch keine Dateien? Zwei Beispiele zum Ausprobieren</summary>
-
- <p>
- Das Werkzeug braucht zweierlei: das <strong>Stammgesetz</strong> in seiner geltenden
- Fassung und das <strong>Änderungsdokument</strong>, das es ändert. Beides liegt bei den
- amtlichen Stellen bereit.
+ <p class="fehlt">
+ Dieser Vordruck rechnet im Browser statt auf dem Server und braucht dafür JavaScript und
+ WebAssembly. Ohne sie bleibt er wirkungslos. Wer beides nicht einschalten möchte, verwende
+ die Befehlszeilenfassung — sie liegt dem <a href="aendggner-quelltext.tar.gz">Quelltext</a>
+ bei und leistet dasselbe.
</p>
-
- <ol>
- <li>Die beiden Dateien eines Beispiels herunterladen.</li>
- <li>Sie in die Felder darunter eintragen — das xml.zip so, wie es kommt, ohne Entpacken.</li>
- <li>„Synopse erzeugen“ drücken.</li>
- </ol>
-
- <dl class="beispiele">
- <dt>Verkündetes Änderungsgesetz — Gesetz gegen den unlauteren Wettbewerb</dt>
- <dd>
- Stammgesetz:
- <a href="https://www.gesetze-im-internet.de/uwg_2004/xml.zip"
- target="_blank" rel="noopener noreferrer">UWG (xml.zip, 22 KB)</a><br>
- Änderung:
- <a href="https://www.recht.bund.de/bgbl/1/2026/43/regelungstext.pdf?__blob=publicationFile&amp;v=1"
- target="_blank" rel="noopener noreferrer">Drittes Gesetz zur Änderung des UWG,
- BGBl. 2026 I Nr. 43 (PDF, 0,3 MB)</a><br>
- <span class="hint">19 Befehle an 6 Normen, nichts manuell zu prüfen.</span>
- </dd>
-
- <dt>Gesetzentwurf — Allgemeines Gleichbehandlungsgesetz</dt>
- <dd>
- Stammgesetz:
- <a href="https://www.gesetze-im-internet.de/agg/xml.zip"
- target="_blank" rel="noopener noreferrer">AGG (xml.zip, 14 KB)</a><br>
- Änderung:
- <a href="https://dserver.bundestag.de/btd/21/061/2106178.pdf"
- target="_blank" rel="noopener noreferrer">Zweites Gesetz zur Änderung des AGG,
- BT-Drs. 21/6178 (PDF, 0,5 MB)</a><br>
- <span class="hint">
- 23 Befehle an 14 Normen, einer zur manuellen Prüfung markiert. Zeigt zugleich, was
- gälte, wenn der Entwurf so beschlossen würde — der Begründungsteil dahinter erzeugt
- keine Befehle.
- </span>
- </dd>
- </dl>
-
- <p class="hint">
- Die Verweise führen zu gesetze-im-internet.de, recht.bund.de und dserver.bundestag.de. Das
- Werkzeug ruft dort nichts von sich aus ab: Es sieht nur die Dateien, die Sie ihm im Formular
- übergeben.
- </p>
- </details>
-
- <form id="synopse-formular">
- <fieldset>
- <legend>Antrag auf Erstellung einer Synopse</legend>
-
- <div class="field">
- <label for="stamm">Stammgesetz</label>
- <input type="file" id="stamm" name="stamm" required aria-describedby="stamm-hinweis">
- <p class="hint" id="stamm-hinweis">
- gii-Norm-XML von gesetze-im-internet.de — auch als heruntergeladenes xml.zip, ohne
- Entpacken —, oder für Landesrecht die konsolidierte Fassung aus dem Landesportal (PDF
- oder Klartext).
- </p>
+ </noscript>
+ </section>
+
+ <p class="ausfuellhinweis">
+ Weiße Felder bitte ausfüllen oder <span class="kreuz">X</span> ankreuzen
+ </p>
+
+ <form id="synopse-formular">
+ <div class="vordruck">
+
+ <div class="block">
+ <div class="leitspalte">Angaben zum Stammgesetz</div>
+ <div class="felder">
+ <div class="feld">
+ <label for="stamm">Stammgesetz in der geltenden Fassung
+ <span class="erl">(gii-Norm-XML von gesetze-im-internet.de — auch als
+ heruntergeladenes xml.zip, ohne Entpacken —, oder für Landesrecht die
+ konsolidierte Fassung aus dem Landesportal als PDF oder Klartext)</span></label>
+ <input type="file" id="stamm" name="stamm" required>
+ </div>
</div>
+ </div>
- <div class="field">
- <label for="aenderung">Änderungsdokument(e)</label>
- <input type="file" id="aenderung" name="aenderung" multiple required
- aria-describedby="aenderung-hinweis">
- <p class="hint" id="aenderung-hinweis">
- Ein oder mehrere PDFs oder Klartextdateien: Änderungsgesetze aus BGBl und GVBl,
- Gesetzentwürfe (Referenten-, Regierungs- und Fraktionsentwürfe, Drucksachen) sowie
- Änderungsanträge — letztere zusammen mit dem Entwurf hochladen, den sie ändern. Die
- Dokumentart wird aus dem Text erkannt. Bei Mehrfachauswahl wird in der gewählten
- Reihenfolge nacheinander angewendet.
- </p>
+ <div class="block">
+ <div class="leitspalte">Angaben zu den Änderungen</div>
+ <div class="felder">
+ <div class="feld">
+ <label for="aenderung">Änderungsdokument(e)
+ <span class="erl">(ein oder mehrere PDFs oder Klartextdateien: Änderungsgesetze aus
+ BGBl und GVBl, Gesetzentwürfe, Drucksachen sowie Änderungsanträge — letztere
+ zusammen mit dem Entwurf, den sie ändern. Bei Mehrfachauswahl wird in der
+ gewählten Reihenfolge nacheinander angewendet)</span></label>
+ <input type="file" id="aenderung" name="aenderung" multiple required>
+ </div>
+ <div class="feld ankreuzfeld">
+ <label>
+ <input type="checkbox" id="vollstaendig" name="vollstaendig">
+ Unveränderte Vorschriften mit in die Synopse aufnehmen
+ </label>
+ </div>
</div>
+ </div>
- <div class="field checkbox">
- <label>
- <input type="checkbox" id="vollstaendig" name="vollstaendig">
- Unveränderte Vorschriften mit in die Synopse aufnehmen
- </label>
+ <div class="block">
+ <div class="leitspalte">Antragstellung</div>
+ <div class="felder">
+ <div class="feld absenden">
+ <button type="submit">Synopse erstellen</button>
+ <span class="erl">Die Auswertung läuft in diesem Browser; je nach Umfang der
+ Dokumente dauert sie einige Sekunden.</span>
+ </div>
</div>
- </fieldset>
-
- <div class="absenden">
- <button type="submit">Synopse erzeugen</button>
</div>
- </form>
-
- <p id="meldung" class="meldung" hidden aria-live="polite" aria-atomic="true"></p>
-
- <aside class="kasten disclaimer">
- <h2>Haftungsausschluss</h2>
- <p>
- Die Synopse wird automatisch erstellt und ist <strong>ohne Gewähr</strong> für Vollständigkeit
- und Richtigkeit; sie ersetzt keine Rechtsberatung. Uneindeutige Änderungsbefehle werden zur
- manuellen Prüfung markiert statt stillschweigend verworfen. Die gewählten Dateien
- <strong>verlassen Ihren Rechner nicht</strong>: Die Auswertung läuft vollständig im Browser,
- es wird nichts hochgeladen und nichts gespeichert.
- </p>
- </aside>
- </main>
+
+ </div>
+ </form>
+
+ <section class="verfuegung">
+ <h2>Verfügung der Zentralstelle</h2>
+ <div class="verfuegungsfeld">
+ <p id="meldung" class="meldung" hidden aria-live="polite" aria-atomic="true"></p>
+ <p class="platzhalter">Wird nach Absenden des Antrags ausgefüllt.</p>
+ </div>
+ </section>
+
+ <details class="ausfuellhilfe">
+ <summary>Ausfüllhilfe — zwei Beispiele zum Ausprobieren</summary>
+
+ <p>
+ Der Vordruck braucht zweierlei: das <strong>Stammgesetz</strong> in seiner geltenden Fassung
+ und das <strong>Änderungsdokument</strong>, das es ändert. Beides liegt bei den amtlichen
+ Stellen bereit. Die beiden Dateien eines Beispiels herunterladen, in die Felder oben
+ eintragen — das xml.zip so, wie es kommt, ohne Entpacken — und „Synopse erstellen“ drücken.
+ </p>
+
+ <dl class="beispiele">
+ <dt>Verkündetes Änderungsgesetz — Gesetz gegen den unlauteren Wettbewerb</dt>
+ <dd>
+ Stammgesetz:
+ <a href="https://www.gesetze-im-internet.de/uwg_2004/xml.zip"
+ target="_blank" rel="noopener noreferrer">UWG (xml.zip, 22 KB)</a><br>
+ Änderung:
+ <a href="https://www.recht.bund.de/bgbl/1/2026/43/regelungstext.pdf?__blob=publicationFile&amp;v=1"
+ target="_blank" rel="noopener noreferrer">Drittes Gesetz zur Änderung des UWG,
+ BGBl. 2026 I Nr. 43 (PDF, 0,3 MB)</a><br>
+ <span class="erl">19 Befehle an 6 Normen, nichts manuell zu prüfen.</span>
+ </dd>
+
+ <dt>Gesetzentwurf — Allgemeines Gleichbehandlungsgesetz</dt>
+ <dd>
+ Stammgesetz:
+ <a href="https://www.gesetze-im-internet.de/agg/xml.zip"
+ target="_blank" rel="noopener noreferrer">AGG (xml.zip, 14 KB)</a><br>
+ Änderung:
+ <a href="https://dserver.bundestag.de/btd/21/061/2106178.pdf"
+ target="_blank" rel="noopener noreferrer">Zweites Gesetz zur Änderung des AGG,
+ BT-Drs. 21/6178 (PDF, 0,5 MB)</a><br>
+ <span class="erl">
+ 23 Befehle an 14 Normen, einer zur manuellen Prüfung markiert. Zeigt zugleich, was gälte,
+ wenn der Entwurf so beschlossen würde — der Begründungsteil dahinter erzeugt keine
+ Befehle.
+ </span>
+ </dd>
+ </dl>
+
+ <p class="erl">
+ Die Verweise führen zu gesetze-im-internet.de, recht.bund.de und dserver.bundestag.de. Der
+ Vordruck ruft dort nichts von sich aus ab: Er sieht nur die Dateien, die Sie ihm übergeben.
+ </p>
+ </details>
<footer>
+ <span class="vordrucknummer">ÄG&#8209;1</span>
<nav>
<a href="impressum.html">Impressum</a> ·
<a href="datenschutz.html">Datenschutz</a> ·
- <a href="aendggner-quelltext.tar.gz">Quelltext dieser Fassung (AGPLv3 oder später)</a>
+ <a href="aendggner-quelltext.tar.gz">Quelltext dieser Fassung (AGPLv3 oder später)</a> ·
+ <a href="https://gerrit.benkard.de/plugins/gitiles/aendggner">Git</a>
</nav>
- <span class="nebenquelle">(<a href="https://gerrit.benkard.de/plugins/gitiles/aendggner">Git</a>)</span>
+ <span class="ausgabe">08.26</span>
</footer>
+
+</div>
</body>
</html>
diff --git a/src/main/resources/eu/mulk/aendggner/web/style.css b/src/main/resources/eu/mulk/aendggner/web/style.css
index 81c16d7..36c2198 100644
--- a/src/main/resources/eu/mulk/aendggner/web/style.css
+++ b/src/main/resources/eu/mulk/aendggner/web/style.css
@@ -1,35 +1,43 @@
/* SPDX-FileCopyrightText: 2020 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
SPDX-License-Identifier: AGPL-3.0-or-later */
-/* Ein Vordruck, kein Aufsatz: Der Bogen liegt auf einer Unterlage, trägt oben einen
- Briefkopf mit Formblattkennung und darunter einen Feldblock mit numerierten Feldern.
- Farbe tritt an drei Stellen auf und meint dort jeweils dasselbe: Behördenrot führt
- das Auge zu den Kennungen und Feldziffern, rot warnt, grün bestätigt. Kein Kasten
- verlässt sich auf seine Farbe allein; Wort und Zeichen tragen die Aussage mit. */
+/* Ein Vordruck nach dem Vorbild der amtlichen Steuerformulare. Dort gilt eine einzige,
+ durchgehaltene Regel, und sie steht sogar im Formular selbst: „Weiße Felder bitte
+ ausfüllen“. Grau ist, was die Stelle gedruckt hat — Beschriftungen, Leitspalten,
+ Abschnittsköpfe, die Verfügung am Ende. Weiß ist, was der Antragsteller beiträgt.
+ Diese Regel trägt hier die gesamte Gestaltung.
+
+ Alles andere folgt daraus: schwarze Haarlinien, aneinanderstoßende Zellen ohne Abstand
+ und ohne Rundung, kleine enge Groteske, Beschriftung innen oben links im Feld,
+ Erläuterungen in noch kleinerer Schrift dahinter, die Vordrucknummer winzig in den
+ Fußecken. Schmuckfarbe gibt es nicht: Rot und Grün treten allein dort auf, wo sie etwas
+ bedeuten — Fehler und Bestätigung —, und nie als einziger Träger der Aussage. */
:root {
color-scheme: light dark;
- --fg: #111;
- --bg: #fff;
- --papier: #f3f1ea;
- --muted: #595959;
- --border: #bbb;
- --raster: #d6d2c6;
- --kasten: #f0ede4;
- --amt: #8b0f21;
+ --fg: #000;
+ --papier: #fff;
+ --feld: #fff;
+ --grund: #d5d5d5;
+ --tint: #e4e4e4;
+ --linie: #000;
+ --muted: #444;
+ --tisch: #9a9a9a;
--warnung: #8b0000;
--bestaetigung: #005f00;
}
+/* Im Dunkeln kehrt sich nicht die Farbe um, sondern das Verhältnis: Der Grund der Stelle
+ bleibt heller als das Feld, das auszufüllen ist. */
@media (prefers-color-scheme: dark) {
:root {
- --fg: #e6e6e6;
- --bg: #1c1c1c;
- --papier: #0f0f0f;
- --muted: #a0a0a0;
- --border: #4a4a4a;
- --raster: #3c3c3c;
- --kasten: #242424;
- --amt: #e79aa4;
+ --fg: #e8e8e8;
+ --papier: #1a1a1a;
+ --feld: #101010;
+ --grund: #333333;
+ --tint: #242424;
+ --linie: #7a7a7a;
+ --muted: #a8a8a8;
+ --tisch: #000;
--warnung: #ffb3b3;
--bestaetigung: #b3ffb3;
}
@@ -39,286 +47,247 @@
box-sizing: border-box;
}
-/* Die Unterlage endet nie, auch wenn der Bogen kürzer ist als das Fenster. */
html {
- background: var(--papier);
+ background: var(--tisch);
}
body {
- margin: 2rem auto 3rem;
- padding: 2rem 2.25rem 2.5rem;
- max-width: 46rem;
- border: 1px solid var(--fg);
- font-family: system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
- font-size: 1rem;
+ margin: 0;
+ padding: 1.5rem 1rem;
+ font-family: Arial, "Helvetica Neue", Helvetica, system-ui, sans-serif;
+ font-size: 0.8125rem;
+ line-height: 1.4;
color: var(--fg);
- background: var(--bg);
- line-height: 1.55;
-}
-
-/* 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;
- }
-}
-
-/* Der Briefkopf: links die ausstellende Stelle, rechts die Kennung des Vordrucks.
- Darunter die Doppellinie — kräftig in Amtsrot, dünn in Rasterfarbe —, deren zweite
- Linie der Oberrand des Satzspiegels 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);
-}
-
-/* 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;
- }
}
-h1,
-.wortmarke {
- margin: 0;
- font-size: 1.9rem;
- font-weight: bold;
- letter-spacing: 0.06em;
- line-height: 1.1;
+/* Der Bogen. Kein Rahmen: Ein Blatt Papier hat keinen, die Kante entsteht aus dem
+ Farbunterschied zur Unterlage. */
+.bogen {
+ max-width: 52rem;
+ margin: 0 auto;
+ padding: 1.75rem 1.75rem 0.75rem;
+ background: var(--papier);
}
-.wortmarke a {
- text-decoration: none;
+@media (max-width: 40rem) {
+ body { padding: 0; }
+ .bogen { padding: 1rem 0.75rem 0.5rem; }
}
-.langname {
- margin: 0 0 0.3rem;
- max-width: 26rem;
- font-size: 0.75rem;
- letter-spacing: 0.05em;
- text-transform: uppercase;
+h1 {
+ margin: 0 0 0.5rem;
+ font-size: 1rem;
line-height: 1.35;
- color: var(--muted);
}
-/* Die Kennung steht als Verzeichnis im Text und nicht als Zierrat im Stilblatt: Sie
- lässt sich damit auswählen und vorlesen. „Nichtamtlich“ ist dabei keine Pointe,
- sondern die Klarstellung, die die amtliche Anmutung nötig macht. */
-.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;
+.stelle {
+ margin: 0 0 0.9rem;
+ font-size: 0.6875rem;
+ color: var(--muted);
}
-.kennung dt {
- letter-spacing: 0.06em;
- text-transform: uppercase;
- color: var(--muted);
+/* Ohne Schmuckfarbe trägt allein die Unterstreichung das Klick-Signal. */
+a {
+ color: inherit;
+ text-decoration: underline;
}
-.kennung dd {
- margin: 0;
- font-weight: bold;
- color: var(--amt);
- white-space: nowrap;
+/* Der Vorgabe-Umriss ist auf dem grauen Raster kaum auszumachen. */
+:focus-visible {
+ outline: 2px solid var(--fg);
+ outline-offset: 1px;
}
-main {
- margin-top: 3px;
- padding-top: 1.5rem;
- border-top: 1px solid var(--raster);
+/* „Zur Beachtung“ steht im Muster als weißer Kasten mit fetter Anrede und dichtem
+ Fließtext; die Überschrift bleibt in der Zeile des ersten Absatzes. */
+.beachtung {
+ padding: 0.6rem 0.7rem;
+ border: 1px solid var(--linie);
+ background: var(--feld);
+ font-size: 0.75rem;
}
-.betreff {
- margin: 0 0 1.75rem;
- font-size: 1.05rem;
+.beachtung h2 {
+ margin: 0 0 0.35rem;
+ font-size: 0.75rem;
}
-/* Impressum und Datenschutz. */
-main > h1 {
- margin-bottom: 1.25rem;
- font-size: 1.4rem;
+.beachtung p {
+ margin: 0 0 0.5rem;
}
-h2 {
- margin: 1.75rem 0 0.5rem;
- font-size: 0.9rem;
- letter-spacing: 0.06em;
- text-transform: uppercase;
+.beachtung p:last-child {
+ margin-bottom: 0;
}
-address {
- font-style: normal;
- margin: 0.5rem 0;
+.fehlt {
+ padding-left: 0.6rem;
+ border-left: 3px solid var(--warnung);
+ font-weight: bold;
}
-code {
- font-size: 0.9375em;
+/* Der Ausfüllhinweis ist im Muster ein eigener Streifen über dem Feldblock — er erklärt
+ genau die Regel, nach der dieses Blatt gesetzt ist. */
+.ausfuellhinweis {
+ margin: 0.9rem 0 0;
+ padding: 0.3rem 0.5rem;
+ border: 1px solid var(--linie);
+ border-bottom: none;
+ background: var(--grund);
+ font-size: 0.75rem;
+ font-weight: bold;
}
-/* Ohne Schmuckfarbe trägt allein die Unterstreichung das Klick-Signal. */
-a {
- color: var(--fg);
- text-decoration: underline;
+.kreuz {
+ display: inline-block;
+ width: 1.1em;
+ border: 1px solid var(--linie);
+ background: var(--feld);
+ font-weight: bold;
+ text-align: center;
}
-/* Der Vorgabe-Umriss verschwindet auf dem hellen Bogen fast; im Amtsrot ist der Halt
- der Tastatur überall zu sehen. */
-:focus-visible {
- outline: 2px solid var(--amt);
- outline-offset: 2px;
+/* Der Feldblock. Die Rahmen sind halbiert — außen oben und links, an den Zellen unten und
+ rechts —, damit zwischen zwei Zellen nur eine einzige Haarlinie steht und nicht zwei. */
+.vordruck {
+ border-top: 1px solid var(--linie);
+ border-left: 1px solid var(--linie);
+ background: var(--grund);
}
-/* Der Feldblock. Die Legende sitzt als schwarzer Balken im oberen Rahmen, wie die
- Abschnittsüberschrift eines Vordrucks. */
-fieldset {
- counter-reset: feld;
- margin: 0 0 1.5rem;
- padding: 1.25rem 1.25rem 0.5rem;
- border: 1px solid var(--fg);
- background: var(--kasten);
+.block {
+ display: grid;
+ grid-template-columns: 8.5rem 1fr;
}
-legend {
- margin-left: -0.25rem;
- padding: 0.3rem 0.8rem;
- background: var(--fg);
- color: var(--bg);
- font-size: 0.8rem;
+/* Der Grund steht ausdrücklich an der Zelle und nicht nur am Block: Im Druck fällt sonst
+ die Fläche des Blocks weg und die Leitspalte käme weiß heraus. */
+.leitspalte {
+ padding: 0.4rem 0.5rem;
+ border-right: 1px solid var(--linie);
+ border-bottom: 1px solid var(--linie);
+ background: var(--grund);
+ font-size: 0.6875rem;
font-weight: bold;
- letter-spacing: 0.08em;
- text-transform: uppercase;
}
-/* Die Feldziffer entsteht aus dem Zähler und steht im Steg links, damit sie die
- Beschriftung nicht verschiebt und in jedem Feld an derselben Stelle sitzt. */
-.field {
- position: relative;
- margin-bottom: 1.25rem;
- padding: 0.9rem 1rem 0.9rem 3rem;
- border: 1px solid var(--raster);
- background: var(--bg);
- counter-increment: feld;
+/* Auf dem Telefon nähme die Leitspalte die halbe Zeile. Sie tritt dann über ihre Felder,
+ als voller Beschriftungsstreifen — eine Form, die das Muster ebenfalls kennt. */
+@media (max-width: 34rem) {
+ .block {
+ grid-template-columns: 1fr;
+ }
+
+ .leitspalte {
+ border-right: none;
+ }
}
-.field::before {
- content: counter(feld);
- position: absolute;
- top: 0.85rem;
- left: 0.85rem;
- 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;
+.feld {
+ padding: 0.25rem 0.5rem 0.4rem;
+ border-right: 1px solid var(--linie);
+ border-bottom: 1px solid var(--linie);
+ background: var(--feld);
}
+/* Die Beschriftung steht klein im Feld oben links, die Erläuterung noch kleiner dahinter;
+ darunter bleibt der Platz für die Eintragung. */
label {
display: block;
+ font-size: 0.6875rem;
font-weight: bold;
- letter-spacing: 0.04em;
- margin-bottom: 0.4rem;
}
-.field.checkbox label {
+.erl {
font-weight: normal;
- letter-spacing: normal;
- margin-bottom: 0;
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
-
-.field.checkbox input {
- accent-color: var(--amt);
- width: 1rem;
- height: 1rem;
- flex: none;
-}
-
-.hint {
- margin: 0.4rem 0 0;
- font-size: 0.8125rem;
+ font-size: 0.6875rem;
color: var(--muted);
}
input[type="file"] {
width: 100%;
- padding: 0.35rem;
- border: 1px solid var(--border);
+ margin-top: 0.35rem;
+ padding: 0;
+ border: none;
background: transparent;
color: inherit;
font: inherit;
- font-size: 0.875rem;
+ font-size: 0.75rem;
}
-/* Der Dateiwähler ist der zweite Knopf des Vordrucks und trägt deshalb dessen Form,
- nur in der Umkehrung, damit er dem Absenden nicht den Rang abläuft. */
+/* Der Dateiwähler ist der einzige Knopf im Feld und trägt deshalb die Form der übrigen
+ Eintragungsfelder: eckig, haarfein umrandet, weiß. */
input[type="file"]::file-selector-button {
- margin-right: 0.75rem;
- padding: 0.3rem 0.9rem;
- border: 1px solid var(--fg);
- background: var(--bg);
+ margin-right: 0.6rem;
+ padding: 0.15rem 0.7rem;
+ border: 1px solid var(--linie);
+ background: var(--feld);
color: var(--fg);
font: inherit;
- font-size: 0.8125rem;
- font-weight: bold;
- letter-spacing: 0.04em;
+ font-size: 0.6875rem;
cursor: pointer;
}
input[type="file"]::file-selector-button:hover {
- background: var(--fg);
- color: var(--bg);
+ background: var(--grund);
+}
+
+/* Das Ankreuzfeld steht vor dem Text und wird angekreuzt, nicht angehakt. */
+.ankreuzfeld label {
+ display: flex;
+ align-items: baseline;
+ gap: 0.5rem;
+ font-weight: normal;
+ font-size: 0.75rem;
+}
+
+.ankreuzfeld input {
+ appearance: none;
+ -webkit-appearance: none;
+ flex: none;
+ position: relative;
+ width: 0.95rem;
+ height: 0.95rem;
+ margin: 0;
+ border: 1px solid var(--linie);
+ background: var(--feld);
+ cursor: pointer;
+}
+
+.ankreuzfeld input:checked::before {
+ content: "\00D7";
+ position: absolute;
+ inset: 0;
+ font-size: 0.9rem;
+ font-weight: bold;
+ line-height: 0.85rem;
+ text-align: center;
+ color: var(--fg);
}
.absenden {
- margin-bottom: 0.5rem;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 0.5rem 0.9rem;
+ padding-top: 0.5rem;
}
button {
font: inherit;
+ font-size: 0.8125rem;
font-weight: bold;
- letter-spacing: 0.08em;
- text-transform: uppercase;
- padding: 0.7rem 1.75rem;
- border: 1px solid var(--fg);
- background: var(--fg);
- color: var(--bg);
- box-shadow: 3px 3px 0 var(--raster);
+ padding: 0.4rem 1.1rem;
+ border: 2px solid var(--linie);
+ background: var(--feld);
+ color: var(--fg);
cursor: pointer;
}
-/* Umkehr statt brightness(): Ein schwarzer Knopf wird davon nicht heller. */
+/* Umkehr statt brightness(): An einem weißen Knopf richtet die nichts aus. */
button:hover {
- background: var(--bg);
- color: var(--fg);
-}
-
-/* Gedrückt fährt der Knopf in seinen eigenen Schatten. */
-button:active {
- transform: translate(3px, 3px);
- box-shadow: none;
+ background: var(--fg);
+ color: var(--papier);
}
/* grayscale() ist an einem grauen Knopf wirkungslos. */
@@ -327,100 +296,52 @@ button[disabled] {
cursor: progress;
}
-/* Hinweiskästen und Meldungen teilen einen Zuschnitt, damit erkennbar bleibt, dass sie
- dasselbe sind: Text am Rande des Vordrucks. Der Balken links zeigt den Zustand an. */
-.kasten,
-.einfuehrung,
-.meldung {
- padding: 0.9rem 1.1rem;
- border: 1px solid var(--raster);
- border-left: 4px solid var(--raster);
- background: var(--kasten);
- font-size: 0.875rem;
-}
-
-.kasten {
- margin: 0 0 1.75rem;
-}
-
-.kasten.warnung {
- border-left-color: var(--warnung);
+button[disabled]:hover {
+ background: var(--feld);
+ color: var(--fg);
}
-.kasten h2 {
- margin: 0 0 0.5rem;
- font-size: 0.75rem;
+/* Die Verfügung ist im Muster der Abschnitt, den die Stelle ausfüllt: grau umrandet,
+ mit zentrierter fetter Überschrift. Er steht auch dann schon da, wenn er noch leer ist —
+ ein Vordruck zeigt seine Abschnitte, bevor sie ausgefüllt sind. */
+.verfuegung {
+ margin-top: 1.25rem;
+ border: 1px solid var(--linie);
+ background: var(--grund);
}
-.kasten p {
+.verfuegung h2 {
margin: 0;
+ padding: 0.3rem 0.5rem;
+ border-bottom: 1px solid var(--linie);
+ font-size: 0.75rem;
+ text-align: center;
}
-/* Zugeklappt eine Zeile, damit das Formular oben bleibt; aufgeklappt im Zuschnitt der
- übrigen Kästen. Der eigene Marker steht vor dem Wort statt daneben, sonst hinge er
- außerhalb des Kastenrahmens. */
-.einfuehrung {
- margin: 0 0 1.75rem;
+.verfuegungsfeld {
+ padding: 0.5rem;
}
-.einfuehrung summary {
- font-weight: bold;
- letter-spacing: 0.04em;
- cursor: pointer;
- list-style: none;
+.platzhalter {
+ margin: 0;
+ font-size: 0.75rem;
+ color: var(--muted);
}
-.einfuehrung summary::-webkit-details-marker {
+/* Steht eine Meldung, so tritt der Platzhalter zurück. */
+#meldung:not([hidden]) + .platzhalter {
display: none;
}
-.einfuehrung summary::before {
- content: "\25B8";
- display: inline-block;
- width: 1em;
- color: var(--amt);
-}
-
-.einfuehrung[open] summary::before {
- content: "\25BE";
-}
-
-.einfuehrung > :not(summary) {
- margin: 0.75rem 0 0;
-}
-
-.einfuehrung ol {
- padding-left: 1.25rem;
-}
-
-.einfuehrung dt {
- font-weight: bold;
- margin-top: 0.9rem;
- padding-top: 0.5rem;
- border-top: 1px solid var(--raster);
-}
-
-.einfuehrung dd {
- margin: 0.25rem 0 0;
-}
-
-/* Der Erläuterungssatz unter einem Beispiel steht als span in der dd und braucht deshalb
- eigene Absatzbildung. */
-.einfuehrung .hint {
- display: block;
-}
-
-.disclaimer {
- margin-top: 2rem;
- color: var(--muted);
-}
-
-/* Die Meldung führt ihr Zeichen im Balken mit: Wer die Farbe nicht sieht, liest ✓ oder !
- Das Zeichen steht im Stilblatt und nicht im Text, weil app.js den Text ersetzt.
- Während der Arbeit steht weder Balken noch Zeichen, weil noch nichts feststeht. */
+/* Die Meldung ist die Eintragung der Stelle und deshalb weiß. Ihr Zeichen im Steg — ✓ oder
+ ! — trägt den Zustand auch dort, wo die Farbe nicht ankommt. Während der Arbeit steht
+ weder Zeichen noch Farbe, weil noch nichts feststeht. */
.meldung {
- margin: 1.5rem 0 0;
- font-size: 0.9375rem;
+ margin: 0;
+ padding: 0.45rem 0.6rem;
+ border: 1px solid var(--linie);
+ background: var(--feld);
+ font-size: 0.8125rem;
}
.meldung.arbeit {
@@ -430,13 +351,14 @@ button[disabled] {
.meldung.fertig,
.meldung.fehler {
position: relative;
- padding-left: 2.5rem;
+ padding-left: 2rem;
+ border-left-width: 4px;
}
.meldung.fertig::before,
.meldung.fehler::before {
position: absolute;
- left: 1.1rem;
+ left: 0.7rem;
font-weight: bold;
}
@@ -459,72 +381,134 @@ button[disabled] {
color: var(--warnung);
}
-/* Der Fußsteg trägt die Pflichtangaben und die Herkunft — links das Verzeichnis, rechts
- die Quelle, so wie ein Vordruck unten seine Herkunft nennt. */
+/* Die Ausfüllhilfe ist ein Merkblatt und liegt dem Vordruck bei, statt in ihm zu stehen. */
+.ausfuellhilfe {
+ margin-top: 1.25rem;
+ padding: 0.5rem 0.7rem;
+ border: 1px solid var(--linie);
+ background: var(--tint);
+ font-size: 0.75rem;
+}
+
+.ausfuellhilfe summary {
+ font-weight: bold;
+ cursor: pointer;
+ list-style: none;
+}
+
+.ausfuellhilfe summary::-webkit-details-marker {
+ display: none;
+}
+
+.ausfuellhilfe summary::before {
+ content: "\25B8\00A0";
+}
+
+.ausfuellhilfe[open] summary::before {
+ content: "\25BE\00A0";
+}
+
+.ausfuellhilfe > :not(summary) {
+ margin: 0.6rem 0 0;
+}
+
+.ausfuellhilfe dt {
+ margin-top: 0.7rem;
+ padding-top: 0.5rem;
+ border-top: 1px solid var(--linie);
+ font-weight: bold;
+}
+
+.ausfuellhilfe dd {
+ margin: 0.2rem 0 0;
+}
+
+.ausfuellhilfe .erl {
+ display: block;
+}
+
+/* Im Muster steht unten links die Vordrucknummer und unten rechts der Ausgabestand, beide
+ winzig und ohne Zierrat. Die Pflichtangaben stehen dazwischen. */
footer {
display: flex;
flex-wrap: wrap;
+ align-items: baseline;
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);
-}
-
-footer a {
+ gap: 0.4rem 1rem;
+ margin-top: 1.5rem;
+ padding: 0.4rem 0 0.6rem;
+ font-size: 0.625rem;
color: var(--muted);
}
footer nav {
- max-width: 32rem;
+ font-size: 0.6875rem;
}
-.nebenquelle {
+.vordrucknummer,
+.ausgabe {
white-space: nowrap;
}
-/* 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. 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. */
+/* Impressum und Datenschutz: dieselbe Anmutung, aber Fließtext statt Feldblock. */
+.bogen > main {
+ padding-bottom: 0.5rem;
+ font-size: 0.8125rem;
+}
+
+main h1 {
+ font-size: 1rem;
+}
+
+main h2 {
+ margin: 1.1rem 0 0.3rem;
+ padding: 0.2rem 0.4rem;
+ border: 1px solid var(--linie);
+ background: var(--grund);
+ font-size: 0.6875rem;
+}
+
+main p,
+main address {
+ margin: 0.4rem 0;
+ max-width: 42rem;
+}
+
+address {
+ font-style: normal;
+}
+
+code {
+ font-size: 0.9375em;
+}
+
+/* Ein Vordruck gehört ausgedruckt: ohne Unterlage, ohne Ränder. 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. Das Grau selbst muss mitgedruckt werden: Es sagt, welche Felder auszufüllen
+ sind, und ist damit keine Zier. */
@media print {
:root {
--fg: #000;
- --bg: #fff;
--papier: #fff;
+ --feld: #fff;
+ --grund: #d5d5d5;
+ --tint: #e4e4e4;
+ --linie: #000;
--muted: #333;
- --border: #666;
- --raster: #999;
- --kasten: #fff;
- --amt: #000;
+ --tisch: #fff;
--warnung: #8b0000;
--bestaetigung: #005f00;
}
- body {
- margin: 0;
- padding: 0;
- max-width: none;
- border: none;
- font-size: 10pt;
- }
-
- .einfuehrung,
- .absenden,
- .meldung[hidden] {
- display: none;
- }
-
- a {
- text-decoration: none;
- }
+ body { padding: 0; font-size: 9pt; }
+ .bogen { max-width: none; padding: 0; }
+ .ausfuellhilfe { display: none; }
+ a { text-decoration: none; }
+ .block, .beachtung, .verfuegung { break-inside: avoid; }
- fieldset,
- .field,
- .kasten {
- break-inside: avoid;
+ .leitspalte, .ausfuellhinweis, .verfuegung, .verfuegung h2, .kreuz, .ausfuellhilfe {
+ -webkit-print-color-adjust: exact;
+ print-color-adjust: exact;
}
}
diff --git a/src/test/java/eu/mulk/aendggner/synopse/HtmlRendererTest.java b/src/test/java/eu/mulk/aendggner/synopse/HtmlRendererTest.java
index 09a5b7c..b80fc88 100644
--- a/src/test/java/eu/mulk/aendggner/synopse/HtmlRendererTest.java
+++ b/src/test/java/eu/mulk/aendggner/synopse/HtmlRendererTest.java
@@ -108,20 +108,22 @@ class HtmlRendererTest {
}
@Test
- void traegtKennungUndFusssteg() {
+ void traegtVorspannUndFusssteg() {
var html = HtmlRenderer.rendere(synopse(), "test.xml + test.pdf");
- assertThat(html).contains("&#8209;2").contains("Stammgesetz").contains("nichtamtlich");
- assertThat(html).contains("Grundlage: test.xml + test.pdf");
+ assertThat(html).contains("<dt>Stammgesetz</dt><dd>TestG</dd>");
+ assertThat(html).contains("<dt>Grundlage</dt><dd>test.xml + test.pdf</dd>");
+ assertThat(html).contains("<dt>Geltung</dt><dd>nichtamtlich</dd>");
+ assertThat(html).contains("class=\"vordrucknummer\">ÄG&#8209;2<");
assertThat(html).contains("maßgeblich ist allein die amtliche Verkündung");
- assertThat(html).doesNotContain("Entwurfsfassung");
+ assertThat(html).doesNotContain("Entwurfsstand");
}
@Test
- void weistDieEntwurfsfassungInDerKennungAus() {
+ void weistDenEntwurfsstandImVorspannAus() {
var html = HtmlRenderer.rendere(synopse(), "quelle", true);
- assertThat(html).contains("<dt>Stand</dt><dd>Entwurfsfassung</dd>");
+ assertThat(html).contains("<dt>Geltung</dt><dd>nichtamtlich, Entwurfsstand</dd>");
assertThat(html).contains("nicht geltendes Recht");
}