/* ═══════════ MODERN CSS RESET ═══════════ */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -moz-text-size-adjust: none;
  -webkit-text-size-adjust: none;
  text-size-adjust: none;
}

body {
  min-height: 100vh;
  line-height: 1.6;
}

h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

p {
  overflow-wrap: break-word;
}

video, canvas, svg {
  display: block;
  max-width: 100%;
}

input, button, textarea, select {
  font: inherit;
}

textarea {
  white-space: revert;
}

/* ═══════════ DESIGN-TOKENS (PROJEKT) ═══════════
   Projekteigene Design-Tokens — diese Datei gehört dem Projekt und wird von
   Template-Updates nie überschrieben (Konfliktregel: immer --ours, docs/UPDATES.md).
   Engine-CSS (_base.css & Co.) referenziert nur die Variablen.

   Theme-Blöcke sind erlaubt. Das Kontrast-Gate (scripts/check-contrast.js)
   erkennt sie als eigenes Theme und rechnet jedes einzeln gegen WCAG AA durch:
   `@media (prefers-color-scheme: dark)`, `[data-theme="…"]` (auch als
   `:root[data-theme=…]`, `body[data-theme=…]` oder im CSS-Nesting als
   `&[data-theme=…]`) und der klassenbasierte Umschalter (`html.dark`, `.dark`).
   Was hier im `:root` steht, gilt in allen Themes — ein Theme-Block
   überschreibt nur, was er selbst deklariert. `@layer`/`@supports` klammern
   bloß und bilden kein eigenes Theme; `@media print` und
   `@media (forced-colors: …)` bleiben ganz außen vor.

   Für ein dunkles Theme gilt: JEDES gepaarte Token gehört überschrieben, auch
   `--color-on-primary` (Text auf der Primärfarbe: .btn/.skip-link, CTA-Leiste,
   Formular-Button) und `--color-rating` (Bewertungssterne). Beide waren früher
   feste Farben im Engine-CSS und damit theme-blind — deshalb sind sie hier
   Token (N8). Was ein Theme nicht überschreibt, erbt es aus `:root`: ein
   dunkler Hintergrund plus geerbtes `--color-rating: #92400e` fällt im Gate
   als Kontrast-Befund auf, nicht erst im Betrieb.

   Weiter fest im Engine-CSS steht nur der WhatsApp-CTA (_cta.css): fremde
   Markenfarbe samt eigenem weißem Text, in jedem Theme unverändert. */

/* Palette aus dem Design-Import 2026-08-14 (design-entwurf/): Tannengrün auf
   Weiß/Mintweiß. Abweichungen vom Entwurf sind Kontrast-Korrekturen und stehen im
   Import-Bericht (reports/design-import-2026-08-14.md). */
:root {
  --color-primary: #0e6b5c;
  --color-primary-hover: #0c5f51;
  --color-on-primary: #ffffff; /* Text auf --color-primary/-hover: .btn, .skip-link, CTA-Leiste, Formular-Button */
  --color-text: #14302b;
  /* Kontrast auf Weiß ≥ 7:1 — bei Anpassung WCAG-AA-Grenze 4.5:1 nicht unterschreiten */
  --color-text-muted: #3c5650;
  --color-bg: #ffffff;
  --color-bg-alt: #f8fbf9;
  --color-border: #d9e7e2; /* Zierde: Karten, Trennstriche, Überschriften — ungemessen, siehe unten */
  /* Rahmen, die ein Bedienelement ERKENNBAR machen: Eingabefeld (_form.css),
     Register-Kachel des Glossars (_glossar.css), „Nicht mehr fragen"
     (_einbettung.css). Alle drei haben keine eigene Füllung — der Rahmen ist das
     Einzige, was sie als bedienbar ausweist, und dafür verlangt WCAG 1.4.11 (Level
     AA, wie 1.4.3 für Text) 3:1 gegen den Untergrund. --color-border erreicht dort
     1,23:1 bzw. 1,18:1 und genügt nicht; als Zierlinie ist es weiter richtig, an
     Zierde stellt 1.4.11 keine Anforderung. Deshalb zwei Token statt eines dunkleren.
     Gemessen: 3,56:1 auf --color-bg, 3,41:1 auf --color-bg-alt — check-contrast
     rechnet beide Paare in jedem Theme nach (N31). */
  --color-border-control: #6d8a82; /* grüngrau statt Entwurfs-#d9e7e2 (das misst nur ~1,2:1) */
  --color-success: #15803d; /* dunkel genug für Text auf Weiß/bg-alt (≥ 4,5:1, check-contrast) */
  --color-error: #c0392b; /* Entwurfs-Rot (Ablauf-Badge); ≥ 5:1 auf Weiß, weiß darauf ≥ 5:1 */
  --color-rating: #92400e; /* Bewertungssterne (.testimonial__stars) auf --color-bg/-alt: ≥ 6,78:1 */

  /* Selbst gehostete Schriften (static/fonts/, @font-face in _projekt.css — SIL OFL,
     s. static/fonts/LICENSE.txt). --font-serif ist ein projekt-eigenes Zusatz-Token
     für Headlines (nur _projekt.css liest es; das Kontrast-Gate misst Farben, keine
     Schriften). */
  --font-sans: "Source Sans 3", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-serif: "Source Serif 4", Georgia, "Times New Roman", serif;
  --font-mono: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace;

  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 2rem;
  --space-xl: 4rem;

  --container-max: 80rem; /* 1280px — Bühnenbreite des Entwurfs */
  --container-padding: 1.5rem;

  --radius: 0.625rem; /* 10px — Buttons/Eingaben des Entwurfs */
  --radius-lg: 1rem; /* 16px — Karten des Entwurfs */
}

/* Design-Token-Werte liegen in _tokens.css (projekteigen) — hier nur Engine-CSS. */

/* ═══════════ BODY ═══════════ */

body {
  font-family: var(--font-sans);
  color: var(--color-text);
  background-color: var(--color-bg);
}

/* ═══════════ DEUTSCHE TYPOGRAFIE ═══════════ */

/* Komposita („Grundstücksentwässerungsanlage") brauchen Silbentrennung in schmalen
   Spalten — hyphens: auto greift nur mit lang="de" am <html> (base.njk, site.language). */
body {
  hyphens: auto;
}

/* Überschriften: ausgewogene Umbrüche, Trennung nur per weichem Trennstrich (&shy;) */
h1, h2, h3, h4, h5, h6 {
  text-wrap: balance;
  hyphens: manual;
}

p {
  text-wrap: pretty;
}

/* ═══════════ CONTAINER ═══════════ */

.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

/* ═══════════ PROSE ═══════════ */

.prose h1 { font-size: 2.25rem; line-height: 1.2; margin-block: var(--space-lg) var(--space-md); }
.prose h2 { font-size: 1.75rem; line-height: 1.25; margin-block: var(--space-lg) var(--space-sm); }
.prose h3 { font-size: 1.375rem; line-height: 1.3; margin-block: var(--space-lg) var(--space-sm); }
.prose p { margin-block-end: var(--space-md); }
.prose ul, .prose ol { margin-block-end: var(--space-md); padding-inline-start: var(--space-lg); }
.prose li { margin-block-end: var(--space-xs); }
.prose blockquote {
  border-inline-start: 3px solid var(--color-primary);
  padding-inline-start: var(--space-md);
  color: var(--color-text-muted);
  margin-block-end: var(--space-md);
}
.prose code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--color-bg-alt);
  padding: 0.125em 0.25em;
  border-radius: var(--radius);
}
.prose pre {
  background: var(--color-bg-alt);
  padding: var(--space-md);
  border-radius: var(--radius);
  overflow-x: auto;
  margin-block-end: var(--space-md);
}
.prose pre code {
  background: none;
  padding: 0;
}

/* ═══════════ HEADINGS ═══════════ */

h1, h2, h3, h4, h5, h6 {
  line-height: 1.2;
}

/* ═══════════ LINKS ═══════════ */

a {
  color: var(--color-primary);
  text-decoration-skip-ink: auto;
}

a:hover {
  color: var(--color-primary-hover);
}

/* ═══════════ ACCESSIBILITY ═══════════ */

/* Sichtbarer Fokus für Tastaturnutzer — niemals ersatzlos entfernen (WCAG 2.4.7) */
:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ═══════════ UMGEBUNGS-LEISTE ═══════════ */

/* Nur auf Vorschau-Ständen im Markup (layouts/base.njk, `umgebung.istStaging`) — im
   Auslieferungszustand rendert die Regel gegen nichts.

   KEIN `min-block-size: 44px`. Die 44 px aus N26 gehören echten Tap-Zielen (WCAG 2.5.5);
   die Leiste ist ein Satz zum Lesen und kein Bedienelement. Ihre Höhe kommt deshalb aus
   dem Innenabstand, nicht aus einer Zahl der Nachbaraufgabe.

   FARBEN AUS BESTEHENDEN TOKEN, kein neues: `src/_includes/css/_tokens.css` gehört dem
   Projekt und wird von /template-update nie ersetzt (`--ours`, docs/UPDATES.md). Ein
   neues Token hier verlangte von JEDEM Bestandsprojekt eine Handanlegung, sonst bräche
   dessen Kontrast-Gate mit „Token fehlt" — genau der Weg, den N8 einmal gehen musste.
   `--color-error` trägt die Warnfarbe, die es schon gibt; das Paar steht in PAIRS
   (scripts/lib/kontrast.js) und wird gegen 4,5:1 gerechnet.

   NICHT `--color-primary`: Die Sprungmarke darunter füllt sich daraus. Blau auf Blau
   ließe sie im Fokus in der Leiste verschwinden — sie liegt mit `z-index: 100` über ihr
   und muss dort als eigene Fläche erkennbar bleiben. */
.umgebung-leiste {
  padding: var(--space-sm) var(--container-padding);
  background: var(--color-error);
  color: var(--color-on-primary);
  font-weight: 600;
  text-align: center;
}

/* ═══════════ SKIP LINK ═══════════ */

/* Tap-Ziel ≥ 44 px (WCAG 2.5.5, N26): gemessen 41,59 px. `inline-flex` blockifiziert
   hier wegen `position: absolute` zu `flex` — die Breite bleibt also weiterhin am Inhalt,
   nur die Höhe bekommt einen Boden und der Text seine Mitte. */
.skip-link {
  position: absolute;
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  top: -100%;
  left: var(--space-md);
  background: var(--color-primary);
  color: var(--color-on-primary);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius);
  z-index: 100;
  text-decoration: none;
  font-weight: 600;
}

.skip-link:focus {
  top: var(--space-sm);
}

/* ═══════════ BUTTON ═══════════ */

.btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 1rem;
  font-weight: 600;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s;
}

.btn:hover {
  background: var(--color-primary-hover);
  color: var(--color-on-primary);
}

/* ─────────────────────────────────────────────────────────
   Responsive Images — Base Styles
   Add these rules to your main stylesheet.
   Required for proper responsive behavior and CLS prevention.
   ───────────────────────────────────────────────────────── */

/* Core responsive image behavior + CLS prevention */
img {
  max-inline-size: 100%;
  block-size: auto;
  display: block;
}

/* Ensure <picture> wrapper doesn't break layout */
picture {
  display: block;
}

/* ─────────────────────────────────────────────────────────
   Hero Image — Optional utility class
   Apply to the hero <img> or wrapping <picture> element.
   Use with eleventy:pictureattr:class="hero-image" on the <img>.
   ───────────────────────────────────────────────────────── */
.hero-image {
  inline-size: 100%;
}

.hero-image img {
  inline-size: 100%;
  block-size: auto;
  object-fit: cover;
}

/* ─────────────────────────────────────────────────────────
   Content Images — Optional styling
   Images within the main content column.
   ───────────────────────────────────────────────────────── */
.content img,
.prose img {
  border-radius: 4px;
  margin-block: 1.5rem;
}

/* ─────────────────────────────────────────────────────────
   Thumbnail / Card Images — Optional
   For card grid layouts with fixed aspect ratio.
   ───────────────────────────────────────────────────────── */
.card-image img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  aspect-ratio: 16 / 9;
}

/* ═══════════ SITE HEADER + NAV ═══════════ */

.site-header {
  padding-block: var(--space-md);
  border-block-end: 1px solid var(--color-border);
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.site-header__logo {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--color-text);
  text-decoration: none;
}

.site-header__logo:hover {
  color: var(--color-primary);
}

/* Mobile: details/summary als Umschalter.
   Die Navigation steht als Geschwister NEBEN dem <details> (nav.njk), nicht
   darin: sie wird allein über `[open]` und die Media-Query ein-/ausgeblendet.
   Bewusst kein `display: contents` auf dem <details> — wie eine Engine den
   Inhalt eines geschlossenen <details> dabei behandelt, ist nicht verlässlich.
   Übernommener Befund (Audit 2026-07-24, Fund 7, Gegenprüfung): Chrome blendet
   ihn über ::details-content aus, die Hauptnavigation war ab 768px auf jeder
   Seite unsichtbar.
   Selbst nachgemessen wurde nicht diese Ursache, sondern das Ergebnis: das
   Rendering-Gate in .github/workflows/deploy.yml prüft im headless Chrome bei
   1280px und 375px (zu- und aufgeklappt) die Bounding-Box von
   `.site-nav__list a`. Gegen den alten Aufbau schlägt es fehl, gegen diesen
   nicht. Firefox/Safari sind nicht nachgemessen — bei leerem <details> hängt
   dort nichts mehr am Engine-Verhalten für geschlossene Inhalte.
   Quelltextseitig zusätzlich abgesichert in scripts/tests/kontrast.test.js. */
.site-nav__toggle {
  display: block;
}

/* Tap-Ziel ≥ 44 px (WCAG 2.5.5, N26). Gemessen bei 375 px waren es 41,59 px — die
   Polsterung allein trägt die Fläche nicht über die Schwelle. `display: flex` ist hier
   kein Beiwerk: `min-block-size` allein ließe „Menü" oben in der gewachsenen Fläche
   kleben. Das <summary> bleibt trotz des geänderten `display` der Umschalter des
   <details> — im Browser bei 375 px auf- und wieder zugeklappt nachgeprüft. */
.site-nav__toggle > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  min-block-size: 44px;
  padding: var(--space-sm) var(--space-md);
  font-weight: 600;
}

.site-nav__toggle > summary::-webkit-details-marker {
  display: none;
}

/* Geschlossen versteckt, offen als volle Zeile unter dem Umschalter
   (.site-header .container ist ein Flex-Container mit flex-wrap: wrap). */
.site-nav {
  display: none;
  flex-basis: 100%;
}

.site-nav__toggle[open] ~ .site-nav {
  display: block;
}

.site-nav__list {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* Tap-Ziel ≥ 44 px (WCAG 2.5.5, N26): gemessen 41,59 px. `flex` statt `block`, damit der
   Linktext in der gewachsenen Zeile mittig steht; die Fläche bleibt so breit wie zuvor,
   weil Flex-Container wie Blockboxen die volle Zeile einnehmen. */
.site-nav__list a {
  display: flex;
  align-items: center;
  min-block-size: 44px;
  padding: var(--space-sm) var(--space-md);
  color: var(--color-text);
  text-decoration: none;
  border-radius: var(--radius);
}

.site-nav__list a:hover,
.site-nav__list a[aria-current="page"] {
  color: var(--color-primary);
  background: var(--color-bg-alt);
}

/* Desktop: 768px+ — Umschalter weg, Navigation immer sichtbar. Der zweite
   Selektor deckt den Fall ab, dass das <details> aus der Mobilansicht noch
   [open] ist (Vergrößern des Fensters). */
@media (min-width: 768px) {
  .site-nav__toggle {
    display: none;
  }

  .site-nav,
  .site-nav__toggle[open] ~ .site-nav {
    display: block;
    flex-basis: auto;
  }

  .site-nav__list {
    flex-direction: row;
    gap: var(--space-sm);
  }
}

/* ═══════════ SITE FOOTER ═══════════ */

.site-footer {
  margin-block-start: var(--space-xl);
  padding-block: var(--space-lg);
  border-block-start: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.site-footer__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-lg);
  margin-block-end: var(--space-lg);
}

.site-footer__name {
  font-weight: 600;
  color: var(--color-text);
  margin: 0 0 var(--space-xs);
}

.site-footer__address {
  font-style: normal;
  line-height: 1.6;
}

.site-footer__heading {
  font-weight: 600;
  color: var(--color-text);
  margin: 0 0 var(--space-sm);
}

.site-footer__contact,
.site-footer__social,
.site-footer__hours {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-xs);
}

.site-footer__social {
  grid-auto-flow: column;
  justify-content: start;
  gap: var(--space-md);
  margin-block-start: var(--space-sm);
}

.site-footer__hours li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-md);
}

.site-footer__hint {
  margin-block-start: var(--space-sm);
}

/* Unterstrichen, weil die Linkfarbe dieselbe ist wie die des Fließtexts: in den
   Kanal-Zeilen („Support: +49 …") stünde der Link sonst ununterscheidbar im
   Text (WCAG 1.4.1/F73, Audit 2026-07-24, Fund 78). */
.site-footer a {
  color: var(--color-text-muted);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.site-footer a:hover {
  color: var(--color-primary);
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-md);
  padding-block-start: var(--space-md);
  border-block-start: 1px solid var(--color-border);
}

.site-footer__links {
  display: flex;
  gap: var(--space-md);
  list-style: none;
  padding: 0;
  margin: 0;
}

/* WCAG 2.5.8: Klickziele ≥ 24 px — Links in Footer-Listen sind eigenständige Ziele */
.site-footer__contact a,
.site-footer__social a,
.site-footer__links a {
  display: inline-block;
  padding-block: var(--space-xs);
}

/* ═══════════ LEAD FORM ═══════════ */

.lead-form {
  max-width: 32rem;
  margin: var(--space-lg) auto;
  padding: var(--space-lg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
}

.lead-form__heading {
  margin: 0 0 var(--space-md);
  font-size: 1.5rem;
}

.lead-form__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.lead-form__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.lead-form__field label {
  font-size: 0.875rem;
  font-weight: 600;
}

/* Der Rahmen ist hier keine Zierde: Das Feld trägt keine eigene Füllung und steht
   auf `.lead-form` (--color-bg). Ohne den Rahmen wäre nicht zu sehen, dass da ein
   Eingabefeld ist — genau das meint WCAG 1.4.11 mit „visual information required to
   identify user interface components" (3:1). Deshalb --color-border-control (N31). */
/* Tap-Ziel ≥ 44 px (WCAG 2.5.5, N26). Gemessen bei 375 px: 43,59 px — knapp, aber
   darunter. Keine Zentrierung nötig, die Felder zentrieren ihren Inhalt selbst; für
   das mehrzeilige textarea ist 44px ohnehin nur ein Boden, keine Höhe. Wirkt, weil
   _reset.css `box-sizing: border-box` setzt: die 44px enthalten Polsterung und Rahmen. */
.lead-form__field input,
.lead-form__field textarea,
.lead-form__field select {
  min-block-size: 44px;
  padding: var(--space-sm) 0.75rem;
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius);
  font-size: 1rem;
  font-family: inherit;
}

.lead-form__field input:focus,
.lead-form__field textarea:focus,
.lead-form__field select:focus {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
  border-color: var(--color-primary);
}

/* Inline-Validierung ohne JS: markiert erst nach Nutzer-Interaktion (WCAG 3.3.1) */
.lead-form__field input:user-invalid,
.lead-form__field textarea:user-invalid {
  border-color: var(--color-error);
  outline-color: var(--color-error);
}

.lead-form__required-hint {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  margin: 0;
}

.lead-form__privacy-note {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  margin: 0;
}

.lead-form__privacy-note a {
  color: var(--color-primary);
}

.lead-form__submit {
  padding: 0.75rem 1.5rem;
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 1rem;
  font-weight: 600;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.15s;
}

.lead-form__submit:hover {
  background: var(--color-primary-hover);
}

/* ═══════════ BLOG INDEX ═══════════ */

.post-list {
  padding-block: var(--space-xl);
}

.post-list__items {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-md);
  margin-block-start: var(--space-md);
}

.post-list__item {
  padding: var(--space-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.post-list__item a {
  text-decoration: none;
  color: inherit;
}

.post-list__title {
  margin-block-end: var(--space-xs);
  font-size: 1.25rem;
}

.post-list__meta {
  color: var(--color-text-muted);
  font-size: 0.875rem;
  margin: 0;
}

.post-list__excerpt {
  margin-block-start: var(--space-sm);
  margin-block-end: 0;
}

/* ═══════════ BLOG POST ═══════════ */

.post__header {
  margin-block-end: var(--space-lg);
  padding-block-end: var(--space-md);
  border-block-end: 1px solid var(--color-border);
}

.post__meta {
  color: var(--color-text-muted);
  font-size: 0.875rem;
  margin-block-start: var(--space-sm);
}

/* ═══════════ SEKTIONEN (Leistungen, Team, Kundenstimmen) ═══════════ */

.section {
  padding-block: var(--space-xl);
}

.section--alt {
  background-color: var(--color-bg-alt);
}

.section__lead {
  color: var(--color-text-muted);
  max-width: 40rem;
  margin-block-start: var(--space-sm);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-md);
  margin-block-start: var(--space-lg);
  list-style: none;
  padding: 0;
}

.card {
  padding: var(--space-lg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background-color: var(--color-bg);
}

/* Karten-Headings tag-unabhängig auf Design-Größe festlegen: das adaptive kartenTag
   (h2 statt h3 ohne Sektions-h2, siehe a1a9401) darf die Optik nicht ändern.
   1.25rem = bestehende Präzedenz der Standort-Übersichtskarten. */
.card :is(h2, h3) {
  font-size: 1.25rem;
}

/* ── Leistungen ── */

.leistung {
  display: flex;
  flex-direction: column;
}

.leistung--featured {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 1px var(--color-primary);
}

.leistung__name {
  margin: 0 0 var(--space-xs);
}

.leistung__desc {
  color: var(--color-text-muted);
  margin: 0 0 var(--space-md);
}

.leistung__price {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-text);
}

.leistung__price small {
  display: block;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--color-text-muted);
}

.leistung__features {
  list-style: none;
  padding: 0;
  margin: var(--space-md) 0 0;
  display: grid;
  gap: var(--space-xs);
  font-size: 0.9375rem;
}

.leistung__features li::before {
  content: "✓";
  color: var(--color-success);
  margin-inline-end: var(--space-xs);
}

/* ── Kundenstimmen ── */

.testimonial {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.testimonial__quote {
  font-size: 1.0625rem;
  line-height: 1.6;
  margin: 0;
}

.testimonial__stars {
  /* Eigenes Token, damit ein dunkles Theme die Sterne mit umstellen kann — als
     Literal maß das Gate hier in jedem Theme den Light-Wert (N8). Im
     Auslieferungszustand ≥ 6,78:1 auf --color-bg und --color-bg-alt (WCAG 1.4.3),
     deutlich über dem AA-Mindestwert 4,5:1. */
  color: var(--color-rating);
  letter-spacing: 0.1em;
}

.testimonial__author {
  color: var(--color-text-muted);
  font-size: 0.9375rem;
}

/* ── FAQ ── */

.faq__list {
  display: grid;
  gap: var(--space-sm);
  margin-block-start: var(--space-lg);
  max-width: 48rem;
}

.faq__item {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
  background-color: var(--color-bg);
}

/* Tap-Ziel ≥ 44 px (WCAG 2.5.5, N26). Gemessen bei 375 px: 25,59 px bei einzeiliger
   Frage — die Höhe hing allein an der Zeilenhöhe und damit an der Fragelänge. Genau
   deshalb ist der Boden nötig: eine lange, umbrechende Frage kam zufällig über 44 px,
   eine kurze nie.

   `display: list-item` ist der Vorgabewert von <summary> und steht hier trotzdem
   ausgeschrieben — als Sperre. Dieses <summary> hat, anders als der Nav-Umschalter
   (`_nav.css:52` mit `list-style: none`), KEIN `list-style: none`: sein Aufklapp-Dreieck
   ▶ ist der einzige optische Hinweis, dass der Eintrag sich öffnet. Chrome rendert diesen
   Marker nur bei `display: list-item` — jeder andere Wert löscht ihn. Eine erste Fassung
   dieser Regel stand auf `display: flex` und tat genau das (Fix-Runde 1: gemessen
   textLeft 17,00 statt 33,94, Dreieck weg). Die Mitte holt deshalb `align-content`, das
   auf Blockcontainern dasselbe leistet, ohne den Marker anzufassen.
   Wer hier ein anderes `display` einträgt, nimmt der ganzen Fleet das Dreieck;
   scripts/tests/touch-ziele.test.js hält den Wert fest. */
.faq__question {
  display: list-item;
  align-content: center;
  min-block-size: 44px;
  font-weight: 600;
  cursor: pointer;
}

.faq__answer {
  margin: var(--space-sm) 0 0;
  color: var(--color-text-muted);
}

/* ── Team ── */

.team-member__photo {
  width: 5rem;
  height: 5rem;
  border-radius: 50%;
  object-fit: cover;
  margin-block-end: var(--space-sm);
}

.team-member__name {
  margin: 0;
}

.team-member__role {
  color: var(--color-primary);
  font-size: 0.9375rem;
  margin: 0 0 var(--space-sm);
}

.team-member__bio {
  color: var(--color-text-muted);
  font-size: 0.9375rem;
  margin: 0;
}

/* Hinweiszeile unter Sektionen (z. B. § 19 UStG unter den Preisen) */
.section__hinweis {
  color: var(--color-text-muted);
  font-size: 0.875rem;
  margin-block-start: var(--space-md);
}

/* Sichtbare KI-Kennzeichnung (Art. 50 KI-VO) — generisch für alle Bild-Datenobjekte */
.ki-kennzeichnung {
  display: block;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin-block-end: var(--space-sm);
}

/* ── Karte (components/karte.njk) ── */

/* Steht bewusst hier und nicht in einer eigenen, bedingt eingebundenen Datei wie
   _einbettung.css: Die Karte hängt an keinem Dienst (E9) und ist auf jeder Site
   verfügbar. Eine Bedingung in assets/style.njk wäre der Anfang genau der Kopplung, die
   die Komponente vermeidet. */
.karte {
  margin: 0 0 var(--space-lg);
}

/* Ein Kartenausschnitt kommt in der Breite, in der ihn jemand exportiert hat. `max-width`
   hält ihn im Container, `height: auto` verhindert dabei das Verzerren. Ein festes
   `aspect-ratio` wie in _einbettung.css wäre hier falsch: Dort ersetzt der Klick das Bild
   durch ein iframe, und nur gleiche Höhen lassen die Seite nicht springen — hier bleibt
   das Bild, was es ist. */
.karte__bild {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: var(--radius);
}

/* Die figcaption trägt hier die Handlung statt einer Bildunterschrift; ohne eigenen
   Abstand klebte der Knopf am Bildrand. */
.karte__aktion {
  margin-block-start: var(--space-md);
}

/* ═══════════ STICKY MOBILE CTA ═══════════ */

.cta-bar {
  display: none;
}

@media (max-width: 767px) {
  .cta-bar {
    position: fixed;
    inset-block-end: 0;
    inset-inline: 0;
    display: flex;
    gap: 1px;
    z-index: 90;
    background: var(--color-border);
    box-shadow: 0 -2px 8px rgb(0 0 0 / 0.08);
    padding-block-end: env(safe-area-inset-bottom);
  }

  /* Inhalt nicht von der Leiste verdecken */
  body {
    padding-block-end: 3.5rem;
  }

  /* WCAG 2.4.11: fokussierte Elemente dürfen beim Tabben nicht hinter der Leiste landen */
  html {
    scroll-padding-block-end: calc(3.5rem + env(safe-area-inset-bottom));
  }
}

.cta-bar__btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: 0.875rem;
  background: var(--color-primary);
  color: var(--color-on-primary);
  text-decoration: none;
  font-weight: 600;
}

.cta-bar__btn:hover {
  background: var(--color-primary-hover);
  color: var(--color-on-primary);
}

.cta-bar__btn svg {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
}

/* Dunkles WhatsApp-Teal statt Brand-Grün. Der Text ist normaler Text (1rem/600,
   kein „large text"), also gilt WCAG 1.4.3 mit 4,5:1 — das frühere #128c7e
   erreichte nur 4,14:1. Beide Werte stehen als Paar in scripts/lib/kontrast.js
   und werden vom Build-Gate nachgerechnet (Audit 2026-07-24, Fund 10).

   Fremde Markenfarbe: sie folgt KEINEM Token und bleibt in jedem Theme dieselbe
   — deshalb setzt die Variante auch ihren Textton selbst statt das theme-
   abhängige --color-on-primary aus `.cta-bar__btn` zu erben (im dunklen Theme
   wäre das dunkel auf dunkel). Die Hover-Regel braucht das eigene `color`
   ebenfalls: `.cta-bar__btn:hover` ist spezifischer als diese Grundregel (N8). */
.cta-bar__btn--whatsapp {
  background: #0e7266; /* 5,81:1 zu #fff */
  color: #fff;
}

.cta-bar__btn--whatsapp:hover {
  background: #0b5b52; /* 7,98:1 zu #fff */
  color: #fff;
}



/* ═══════════ GLOSSAR-HUB ═══════════ */

.glossar__intro {
  color: var(--color-text-muted);
  margin-block-end: var(--space-lg);
}

.glossar__register ul {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-lg);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

/* Kachel statt Textlink: `text-decoration: none` nimmt dem Anker die Unterstreichung,
   eine eigene Füllung hat er nicht. Damit ist der Rahmen das Einzige, was die Kachel
   als klickbares Ziel ausweist — Bedienelement-Rahmen nach WCAG 1.4.11 (3:1),
   deshalb --color-border-control statt der Zierfarbe (N31). */
.glossar__register a {
  display: inline-block;
  min-width: 2.25rem;
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius);
  text-align: center;
  text-decoration: none;
}

.glossar__gruppe {
  margin-block-end: var(--space-lg);
  /* Sprungziel nicht unter die klebende Navigation schieben. */
  scroll-margin-block-start: var(--space-lg);
}

.glossar__gruppe h2 {
  padding-block-end: var(--space-xs);
  border-block-end: 1px solid var(--color-border);
}

.glossar__liste {
  margin: 0;
}

.glossar__liste dt {
  margin-block-start: var(--space-md);
  font-weight: 600;
}

.glossar__liste dd {
  margin-inline-start: 0;
  color: var(--color-text-muted);
}

/* ═══════════ GLOSSAR-BEGRIFFSSEITE ═══════════ */

.glossar-begriff__pfad {
  margin-block-end: var(--space-sm);
  font-size: 0.875rem;
}

.glossar-begriff__synonyme {
  margin-block-start: 0;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

/* Der Definitionsabsatz ist der wichtigste Block der Seite — er wird auch optisch
   als eigenständige Aussage gesetzt, nicht als erster Fließtextabsatz. */
.glossar-begriff__definition {
  margin-block: var(--space-md);
  padding-inline-start: var(--space-md);
  border-inline-start: 4px solid var(--color-primary);
  font-size: 1.125rem;
}

.glossar-begriff__verwandt ul {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.glossar-begriff__weiter {
  margin-block-start: var(--space-lg);
}

/* ═══════════ BEGRIFFS-POPOVER IM FLIESSTEXT ═══════════ */

.begriff {
  /* Ankerpunkt für die Positionierung, wo der Browser sie unterstützt.
     `anchor-scope` ist hier Pflicht, nicht Kür: alle Begriffe einer Seite tragen
     denselben Ankernamen — ohne Scope löste jedes Popover auf denselben (letzten)
     Anker auf und erschiene beim falschen Wort. */
  anchor-name: --begriff-anker;
  anchor-scope: --begriff-anker;
}

.begriff__anker {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 0.2em;
}

.begriff__popover {
  max-inline-size: min(28rem, calc(100vw - 2 * var(--container-padding)));
  padding: var(--space-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg);
  color: var(--color-text);
  font-size: 0.9375rem;
  box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
}

.begriff__definition {
  display: block;
}

.begriff__mehr {
  display: inline-block;
  margin-block-start: var(--space-sm);
}

/* Ohne Anchor-Positioning zeigt der Browser das Popover mittig im Viewport — ein
   brauchbarer Rückfall. Wo sie unterstützt wird, steht es beim Begriff. */
@supports (position-anchor: --begriff-anker) {
  .begriff__popover {
    position-anchor: --begriff-anker;
    position-area: block-end span-inline-end;
    margin: var(--space-xs) 0 0;
    position-try-fallbacks: flip-block, flip-inline;
  }
}








/* ═══════════ PROJEKT-CSS (Design-Import 2026-08-14) ═══════════
   Quelle: design-entwurf/ (energieausweis.portal-Entwurf, umbenannt auf
   Energieausweis-Blog). Diese Datei gehört dem Projekt und lädt nach dem
   Engine-CSS (gewinnt bei gleicher Spezifität) und vor _print.css.
   Farben laufen über die Token aus _tokens.css; Literale stehen nur dort,
   wo der Entwurf feste Flächen definiert (dunkler Footer, Ausweis-Skala,
   Mint-Flächen) — Textkontraste dieser Flächen sind im Import-Bericht
   nachgerechnet (≥ 4,5:1 bzw. 3:1). */

/* ── Selbst gehostete Schriften (static/fonts/, SIL OFL) ── */
@font-face {
  font-family: "Source Sans 3";
  src: url("/fonts/source-sans-3-latin-var.woff2") format("woff2");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Serif 4";
  src: url("/fonts/source-serif-4-latin-var.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ── Grundtypografie des Entwurfs ── */
body {
  background: var(--color-bg-alt);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, .pj-h2, .pj-h3 {
  font-family: var(--font-serif);
  font-weight: 600;
  letter-spacing: -0.015em;
}
::selection { background: #cfe8e0; color: var(--color-text); }

/* ── Bausteine: Kicker, Pills, Badges, Buttons, Karten ── */
.pj-kicker {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.pj-kicker--gruen { color: var(--color-primary); }
.pj-pill {
  display: inline-flex;
  align-self: flex-start;
  text-decoration: none;
  background: #e6f2ee;
  color: var(--color-primary);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.44rem 0.75rem;
  border-radius: 999px;
}
/* `display` ist hier nicht optional: Ohne Angabe ist ein <span> inline, und dann zählt
   sein vertikales Padding NICHT zur Zeilenhöhe. Zwei Belegstufen untereinander in einer
   Matrix-Zelle stießen deshalb fast aneinander (gemessen auf /bausteine/, 375 px).
   `hyphens: manual`, weil body `hyphens: auto` setzt — eine getrennte Kurzmarke
   („QUELLEN WIDER-SPRECHEN SICH") ist keine Marke mehr. */
.pj-badge, .pj-badge-neutral {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  white-space: nowrap;
  hyphens: manual;
}
.pj-badge--gruen { color: var(--color-on-primary); background: var(--color-primary); }
.pj-badge--gelb { color: #6b4a00; background: #f9d774; }
.pj-badge--rot { color: var(--color-on-primary); background: var(--color-error); }
.pj-badge-neutral { font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--color-text-muted); background: #e6f2ee; }
/* Volltonfarbe statt Verlauf — und das ist eine Messfrage, keine Geschmacksfrage
   (gemessen 2026-08-14): Steht ein Verlauf als `background`/`background-image` am Element,
   kann axe den Kontrast darauf grundsätzlich nicht bestimmen und meldet JEDES Textelement
   darauf. Der Entwurf hatte drei solche Verläufe (hier, `.pj-header__cta`, `.pj-hero`) —
   sie allein erzeugten 25 der 25 pa11y-Fehler, ohne dass der tatsächliche Kontrast je
   schlecht war (4,85:1 an der hellsten Verlaufsstufe gegen Weiß). Auch der Umweg über ein
   ::before hinter dem Text hilft nicht; er machte es messbar schlechter (40 Fehler).
   Die Tiefe trägt jetzt der `inset`-Schatten in der Zeile darunter.
   Wer hier einen Verlauf zurückschreibt, macht den Barrierefreiheits-Scan wieder rot. */
/* `hyphens: manual` gegen das globale `hyphens: auto` aus _base.css: In einer schmalen
   Spalte trennt Chrome die Beschriftung sonst SILBENWEISE. Gemessen auf /bausteine/ im
   Artikelkörper: „Energieausweis online erstellen" stand als 78 px breite, 269 px hohe
   Buchstabensäule („En-er-gie-aus-weis-on-line-er-stel-len"). Silbentrennung gehört in
   den Fließtext, nicht auf ein Bedienelement. */
.pj-btn {
  display: inline-block;
  background-color: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 0.94rem;
  font-weight: 700;
  padding: 0.9rem 1.5rem;
  border-radius: var(--radius);
  hyphens: manual;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 4px 10px -6px rgba(12, 95, 81, 0.45);
  text-decoration: none;
}
.pj-btn:hover, .pj-btn:focus-visible { background: var(--color-primary-hover); color: var(--color-on-primary); }
.pj-btn--ghost {
  background: var(--color-bg);
  color: var(--color-text);
  border: 1px solid #cfe0da;
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.04);
}
.pj-btn--ghost:hover, .pj-btn--ghost:focus-visible { background: var(--color-bg); color: var(--color-primary); border-color: var(--color-primary); }
.pj-link { color: var(--color-primary); font-weight: 700; text-decoration: none; }
.pj-karte, .pj-teaser--karte, .pj-wizard, .pj-schaetzer, .pj-tools, .pj-vgl-karte {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.03), 0 16px 34px -26px rgba(20, 48, 43, 0.22);
}

/* ── Seitenbühne: 1280px, luftige Ränder ──
   Jedes Element, das direkt unter <main> sitzt, muss hier stehen — sonst läuft es bis
   an den Fensterrand. Ergänzt 2026-08-16 um die Kopfbereiche der neuen Seitenarten
   (Ratgeber-Hub, Kategorie, News, Werkzeuge), den Artikel und die Rechtstexte. */
/* `.pj-artikel` steht hier bewusst NICHT (mehr): Der Artikel besteht seit dem
   Vorlagen-Angleich aus zwei Vollbreiten-Flächen (Kopfband, Bildband) und einem
   Rumpf, der die Bühne selbst setzt — läge die Bühne am Artikel, könnten die Bänder
   nicht bis an den Rand laufen. */
.pj-notice, .pj-hero, .pj-section,
.pj-hub-kopf {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4.4vw, 3.5rem);
}
.pj-section { padding-block: 0 4rem; }
.pj-section--eng { padding-block-end: 2rem; }

/* 2a weicht als einzige Seitenart ab: Der Entwurf misst dort 48px Rand statt 56px, und
   er setzt ihn an die BÄNDER, nicht an den Container. Beides zusammen ergibt 1184px
   Inhaltsbreite statt 1168 — sichtbar am Raster, dessen Textspalte dadurch die 924px
   des Entwurfs bekommt statt 908. */
.pj-rechtstext { max-width: var(--container-max); margin-inline: auto; }
.pj-rechtstext__kopf, .pj-rechtstext__raster { padding-inline: 48px; }

/* ── Mint-Bänder (Entscheidung Yves, 2026-08-16) ──
   ERGÄNZUNG, keine Wiederherstellung: Der Entwurf kennt keine wechselnden
   Sektionsflächen. Alle fünf Entwurfsseiten sind eine einzige Fläche #f8fbf9, den
   Rhythmus tragen dort allein die weißen Karten; Farbe haben nur Header, Rechtsstand-
   Leiste, Hero-Schleier und Footer. Wer den Entwurf danebenlegt und die Bänder
   vermisst, sucht etwas, das dort nie stand.
   Die Bandfarbe ist bewusst das Mint der Rechtsstand-Leiste — keine sechste Fläche.
   Vollton, kein Verlauf (Begründung bei .pj-btn oben); Kontraste darauf nachgerechnet
   2026-08-16: --color-text 12,3:1 · --color-text-muted 6,93:1 · --color-primary
   5,59:1, alle über 4,5:1. Der Kontrast-Gate prüft nur Token-Paare aus _tokens.css,
   dieses Literal sieht er nicht — deshalb steht die Rechnung hier.
   Volle Breite bei gehaltener Bühne: `max-width: none` plus ein Innenabstand, der die
   Rechnung der Canvas-Sektionen nachbaut — erst die Hälfte des Überschusses über
   1280px (das, was dort `margin-inline: auto` erledigt), dann derselbe reguläre Rand.
   Beides zu addieren ist der Punkt: `max()` der beiden Werte stellt den Bandinhalt
   links NEBEN die Kante der Canvas-Sektionen, und der Versatz wächst mit dem
   Bildschirm (18px bei 1316px, 56px bei 1920px).
   So ist das Band ein echter Hintergrund AM Element und nicht ein ::before dahinter,
   das axe nicht sieht. */
/* Auch die Rechtsstand-Leiste läuft über die volle Breite und zog den Rand bisher
   NICHT nach: ihr Inhalt stand bei 1720px Fenster auf 56px, während Header, Hero,
   Bänder und Footer auf 269px stehen (gemessen 2026-08-16). Der Versatz wächst mit
   dem Bildschirm und war ohne zweite Vollbreiten-Fläche daneben kaum zu sehen. */
/* HERO-SCHLEIER: BEWUSST NICHT ÜBERNOMMEN (entschieden 2026-08-28, mit Messung).

   Der Entwurf eröffnet 1a, 3a und 3b mit einem radialen Verlauf oben rechts
   (`radial-gradient(120% 110% at 88% -10%, #ecf6f2 0%, transparent 62%)`). Er fehlte
   hier, fiel im Bildvergleich auf — und wurde nach dem Einbau wieder entfernt:

     mit Verlauf   pa11y  9/18 URLs bestanden, 82 Kontrastfehler
     ohne Verlauf  pa11y 18/18 URLs bestanden

   axe kann bei einem `background-image` den effektiven Hintergrund nicht bestimmen und
   meldet JEDEN Text darauf als Kontrastfehler. Das gilt auch, wenn der Verlauf in einem
   ::before liegt statt am Element — beides wurde gemessen, beides fällt durch. Betroffen
   waren Startseite, Ratgeber-Hub, Kategorieseite, alle vier Werkzeugseiten und beide
   Autorenprofile.

   Die Abwägung ist damit eindeutig: Der Schleier verschiebt den tatsächlichen Kontrast
   um höchstens 0,76 Stufen (Text 13,55 → 12,79 · gedämpft 7,64 → 7,21 · Primär
   6,15 → 5,81) — er ist optisch fast nicht wahrnehmbar. Dagegen steht ein hartes Gate
   (`site.pruefung.stufe: "hart"`), das mit ihm jeden Build und jeden Deploy rot macht.
   Zierde darf kein Gate brechen; dieselbe Linie führt CLAUDE.md schon für die
   Zierpfeile, die als Markup axe-Fehler auslösten und deshalb ins CSS gewandert sind.

   Wer ihn doch will, braucht zuerst eine Antwort auf die axe-Meldung — nicht eine
   Ausnahme in .pa11yci, denn die schaltet die Kontrastprüfung für die ganze Seite ab. */
.pj-hub-kopf > * { position: relative; }
.pj-hero,
.pj-hub-kopf:not(.pj-hub-kopf--news),
.pj-notice,
.pj-section--band {
  max-width: none;
  padding-inline: calc(max(0px, 100% - var(--container-max)) / 2 + clamp(1.25rem, 4.4vw, 3.5rem));
}
.pj-section--band {
  background-color: #e6f2ee;
  padding-block: 3.5rem 4rem;
}
/* Die Trennlinie #e0eeea steht auf dem Band bei 1,04:1 und verschwindet damit — das
   trifft jede Linie im Band, nicht nur den Sektionskopf: auch die Zeilentrenner der
   FAQ und den Kopf der Redaktionsspalte. */
.pj-section--band .pj-section__kopf,
.pj-section--band .pj-redaktion__kopf,
.pj-section--band .faq__item { border-bottom-color: #cfe4dd; }
/* .pj-section hat oben bewusst keinen Abstand — nach einem Band stieße der Inhalt
   der nächsten Sektion sonst unmittelbar an die Bandkante. */
.pj-section--band + .pj-section { padding-block-start: 3.5rem; }

/* Zwei Bänder direkt übereinander verschmelzen zu EINER Fläche — der Wechsel ist dann
   weg, ohne dass es nach einem Fehler aussieht. Die Werkzeug-Includes bringen ihr Band
   von der Startseite mit; wo eine Seite sie anders anordnet, umschließt sie das Include
   mit einem `div.pj-band-neutral`. Das nimmt ihm die Bandfarbe, statt ihn zu forken.
   Die Trennlinien müssen mit: #cfe4dd ist die Bandvariante und steht auf Canvas bei
   1,04:1 — sie verschwände.

   ACHTUNG, hier gelernt: In diese Datei gehört KEINE Nunjucks-Syntax — auch nicht als
   Beispiel in einem Kommentar. src/assets/style.njk rendert das Projekt-CSS durch
   Nunjucks; ein Include-Tag im Kommentar wird AUSGEFÜHRT und schreibt die gerenderte
   Sektion als HTML mitten in die ausgelieferte style.css (hier waren es 4 KB
   Schätzer-Markup). Kein Gate meldet das: Der CSS-Kommentar bleibt geschlossen, die
   Datei ist gültiges CSS. Wer ein Beispiel braucht, schreibt es in Worten. */
.pj-band-neutral > .pj-section--band { background-color: transparent; }
.pj-band-neutral > .pj-section--band .pj-section__kopf,
.pj-band-neutral > .pj-section--band .pj-schaetzer__kopf { border-bottom-color: #e0eeea; }

.pj-section__kopf {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  border-bottom: 1px solid #e0eeea;
  padding-bottom: 1rem;
  margin-bottom: 1.6rem;
}
.pj-section__kopf .pj-h2 { margin: 0.4rem 0 0; }
.pj-h2 { font-size: 1.56rem; }
.pj-h3 { font-size: 1.3rem; margin: 0; }
.pj-section__neben { margin: 0; font-size: 0.9rem; color: var(--color-text-muted); }

/* ── Header ── */
.pj-header { background: var(--color-bg); border-bottom: 1px solid #e6f0ec; }
.pj-header__inner {
  max-width: var(--container-max);
  margin-inline: auto;
  /* 22px wie im Entwurf — 1.15rem ergaben 18,4px und machten den Kopf 7px flacher. */
  padding: 22px clamp(1.25rem, 4.4vw, 3.5rem);
  display: flex;
  align-items: center;
  gap: 1.4rem;
}
.pj-brand { display: flex; align-items: center; gap: 0.6rem; text-decoration: none; color: var(--color-text); }
.pj-brand__mark { width: 22px; height: 22px; border-radius: 5px; background: var(--color-primary); }
.pj-brand__name { font-weight: 800; font-size: 1.06rem; letter-spacing: -0.02em; }
.pj-brand__accent { color: var(--color-primary); }
.pj-nav { margin-right: auto; }
.pj-nav__list { list-style: none; margin: 0; padding: 0; display: flex; gap: 1.6rem; }
.pj-nav__list a { font-size: 0.92rem; font-weight: 500; color: var(--color-text-muted); text-decoration: none; }
.pj-nav__list a:hover, .pj-nav__list a:focus-visible, .pj-nav__list a[aria-current] { color: var(--color-primary); }
.pj-nav__list a[aria-current] { font-weight: 700; }
.pj-header__cta {
  white-space: nowrap;
  /* Volltonfarbe statt Verlauf — Begründung bei .pj-btn oben. 6,4:1 gegen Weiß. */
  background-color: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 0.9rem;
  font-weight: 800;
  padding: 0.8rem 1.35rem;
  border-radius: var(--radius);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 4px 10px -6px rgba(12, 95, 81, 0.45);
  text-decoration: none;
}
.pj-header__cta:hover, .pj-header__cta:focus-visible { background: var(--color-primary-hover); color: var(--color-on-primary); }
.pj-nav-toggle { display: none; }
@media (max-width: 860px) {
  .pj-header__inner { flex-wrap: wrap; }
  .pj-header__cta { display: none; }
  .pj-nav-toggle { display: block; margin-left: auto; }
  .pj-nav-toggle summary {
    cursor: pointer;
    list-style: none;
    font-weight: 700;
    font-size: 0.95rem;
    padding: 0.5rem 0.9rem;
    border: 1.5px solid var(--color-border-control);
    border-radius: var(--radius);
  }
  .pj-nav-toggle summary::-webkit-details-marker { display: none; }
  .pj-nav { display: none; width: 100%; margin: 0; }
  .pj-nav-toggle[open] ~ .pj-nav { display: block; }
  .pj-nav__list { flex-direction: column; gap: 0; padding-top: 0.5rem; }
  .pj-nav__list a { display: block; padding: 0.7rem 0.25rem; font-size: 1.05rem; border-top: 1px solid var(--color-border); }
}

/* ── Rechtsstand-Leiste ── */
.pj-notice {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  background: #e6f2ee;
  border-bottom: 1px solid #d9e7e2;
  /* `max-width: none` + der bühnenhaltende Innenabstand stehen oben bei den
     Vollbreiten-Flächen — eine Stelle für beide. */
  padding-block: 0.8rem;
}
.pj-notice__stand { color: var(--color-primary); white-space: nowrap; }
.pj-notice__text { margin: 0; font-size: 0.9rem; line-height: 1.5; color: #22403a; }
.pj-notice__link { margin-left: auto; white-space: nowrap; font-size: 0.9rem; font-weight: 700; color: var(--color-primary); text-decoration: none; }
@media (max-width: 700px) { .pj-notice { flex-wrap: wrap; } .pj-notice__link { margin-left: 0; } }

/* ── Hero ── */
.pj-hero {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  /* 64px Spaltenabstand und 76/66px Bandhöhe — der Entwurf misst hier in Pixeln.
     Über rem gerechnet waren es 56 und 70,4/64: Der Hero stand 6px zu hoch und die
     beiden Spalten 8px zu eng beieinander. */
  gap: 64px;
  padding-block: 76px 66px;
  align-items: start;
}
/* Grid-Kinder tragen von sich aus `min-width: auto` und schrumpfen deshalb NICHT unter
   ihre Mindestinhaltsbreite. Auf 375px drückte das die Hero-Spalte auf 363px in einem
   335px breiten Inhaltskasten — die Startseite ließ sich quer scrollen (gemessen
   2026-08-16: scrollWidth 383 bei clientWidth 375). Sichtbar war es kaum, weil die acht
   Pixel unter der Kante des Hero-Schleiers lagen. */
.pj-hero > * { min-width: 0; }
.pj-hero__copy { display: flex; flex-direction: column; gap: 1.5rem; min-width: 0; }
.pj-hero__title { margin: 0; font-size: clamp(2.3rem, 4.6vw, 3.6rem); line-height: 1.04; letter-spacing: -0.018em; text-wrap: balance; }
.pj-hero__lead { margin: 0; font-size: 1.14rem; line-height: 1.6; color: var(--color-text-muted); max-width: 46ch; text-wrap: pretty; }
.pj-hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; }
.pj-hero__stats { display: flex; gap: 2rem; padding-top: 1.4rem; border-top: 1px solid #e0eeea; }
.pj-stat { display: flex; flex-direction: column; gap: 0.2rem; }
.pj-stat__wert { font-size: 1.55rem; font-weight: 800; letter-spacing: -0.03em; }
.pj-stat__label { font-size: 0.82rem; color: var(--color-text-muted); }
@media (max-width: 960px) { .pj-hero { grid-template-columns: 1fr; gap: 2.4rem; padding-block: 3rem 2.6rem; } }

/* ── Wegweiser-Karte ── */
.pj-wizard { padding: 1.9rem; display: flex; flex-direction: column; gap: 1.2rem; box-shadow: 0 1px 3px rgba(20, 48, 43, 0.05), 0 30px 60px -34px rgba(20, 48, 43, 0.4); }
.pj-wizard__kopf { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; }
.pj-wizard__kopf .pj-h3 { font-size: 1.13rem; }
.pj-wizard__schritte { display: flex; justify-content: space-between; font-size: 0.8rem; font-weight: 600; color: var(--color-text-muted); margin-bottom: 0.55rem; }
.pj-balken { height: 6px; border-radius: 999px; background: #cfe4dd; overflow: hidden; }
.pj-balken__wert { height: 100%; background: var(--color-primary); border-radius: 999px; transition: width 220ms ease; }
.pj-wizard__frage { font-family: var(--font-serif); font-size: 1.28rem; font-weight: 600; line-height: 1.25; margin-bottom: 1rem; }
.pj-wizard__optionen { display: flex; flex-direction: column; gap: 0.5rem; }
.pj-option {
  appearance: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1.5px solid var(--color-border-control);
  border-radius: var(--radius);
  padding: 0.8rem 0.95rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  transition: border-color 140ms ease, background 140ms ease;
}
.pj-option:hover, .pj-option:focus-visible { border-color: var(--color-primary); background: #f4faf8; }
.pj-option__label { font-size: 0.95rem; font-weight: 700; }
.pj-option__hint { font-size: 0.82rem; line-height: 1.45; color: var(--color-text-muted); }
.pj-wizard__zurueck {
  appearance: none;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  margin-top: 0.9rem;
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--color-text-muted);
}
.pj-wizard__zurueck:hover, .pj-wizard__zurueck:focus-visible { color: var(--color-primary); }
.pj-wizard__fallback { margin: 0; font-size: 0.94rem; line-height: 1.6; color: var(--color-text-muted); }
.pj-wizard__ergebnis { background: #edf7f4; border-radius: var(--radius-lg); padding: 1.35rem; display: flex; flex-direction: column; gap: 0.7rem; }
.pj-wizard__ergebnis-kopf { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; }
.pj-wizard__ergebnis-titel { font-family: var(--font-serif); font-size: 1.6rem; font-weight: 600; line-height: 1.14; letter-spacing: -0.014em; }
.pj-wizard__law { border-top: 1px solid #cfe4dd; padding-top: 0.7rem; font-size: 0.8rem; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.pj-wizard__aktionen { display: flex; align-items: center; gap: 0.9rem; margin-top: 0.9rem; }
.pj-wizard__aktionen .pj-wizard__zurueck { margin-top: 0; }

/* ── Raster & Karten ── */
.pj-grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.pj-karte { padding: 1.6rem 1.5rem; display: flex; flex-direction: column; gap: 0.7rem; text-decoration: none; color: var(--color-text); border-radius: 14px; }
/* Die Beitragskachel trägt im Entwurf KEINEN Rahmen: Bildfläche, Kicker, Titel, Anriss,
   Meta stehen als einfacher Stapel auf der Seitenfläche (1a-homepage.html, „Neu im
   Ratgeber"; ebenso die Weiterlesen-Kacheln). Kartenoptik hat dort nur, was die Vorlage
   auch als Karte zeichnet — der Aufmacher und die zwei Kacheln daneben (3a/3c). Die
   trägt `--karte`. */
.pj-teaser { display: flex; flex-direction: column; gap: 0.875rem; text-decoration: none; color: var(--color-text); }
.pj-teaser__text { display: flex; flex-direction: column; gap: 0.55rem; }
.pj-teaser--karte { overflow: hidden; border-radius: 16px; }
.pj-teaser--karte .pj-teaser__bild { border-radius: 0; }
.pj-teaser--karte .pj-teaser__text { padding: 1.4rem 1.6rem 1.6rem; }
/* Kachel ohne Bildfläche (die zwei Begleiter des Aufmachers): der Text bringt seinen
   eigenen oberen Innenabstand mit, sonst klebte der Kicker an der Kartenkante. */
.pj-teaser--karte:not(:has(.pj-teaser__bild)) .pj-teaser__text { padding: 1.4rem 1.5rem; }
.pj-karte:hover, .pj-teaser:hover { color: var(--color-text); border-color: var(--color-primary); }
.pj-teaser:hover .pj-teaser__titel, .pj-teaser:focus-visible .pj-teaser__titel { color: var(--color-primary); }
.pj-karte__titel, .pj-teaser__titel { font-family: var(--font-serif); font-size: 1.32rem; font-weight: 600; letter-spacing: -0.012em; line-height: 1.28; }
.pj-karte__text { font-size: 0.92rem; line-height: 1.6; color: var(--color-text-muted); }
.pj-karte__mehr { font-size: 0.92rem; font-weight: 700; color: var(--color-primary); margin-top: 0.3rem; }
.pj-teaser__meta { font-size: 0.82rem; color: var(--color-text-muted); }
.pj-tags { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.3rem; }
.pj-tag { font-size: 0.78rem; font-weight: 600; background: #e6f2ee; color: var(--color-primary); padding: 0.3rem 0.65rem; border-radius: 999px; }
.pj-register {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--color-border);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  overflow: hidden;
}
.pj-register__zelle { background: var(--color-bg); padding: 1.35rem; display: flex; flex-direction: column; gap: 0.4rem; text-decoration: none; color: var(--color-text); }
.pj-register__zelle:hover { color: var(--color-text); background: #f4faf8; }
.pj-register__zelle:hover .pj-register__titel { color: var(--color-primary); }
.pj-register__titel { font-family: var(--font-serif); font-size: 1.06rem; font-weight: 600; }
.pj-register__text { font-size: 0.84rem; line-height: 1.55; color: var(--color-text-muted); }
/* Das Register zeichnet seine Trennlinien über den Container-Hintergrund, der durch
   1px-Lücken scheint. Bleibt eine Zelle der letzten Reihe leer, ist genau dieser
   Hintergrund als grauer Kasten sichtbar — im Vierer-Raster also bei 3 und bei 6
   Kacheln. Deshalb ein Modifier statt einer festen Spaltenzahl für alle:
     8 Kacheln (Startseite, Ratgeber-Hub) → Standard, 4×2 ohne Lücke
     3 oder 6 (verwandte Kategorien, News-Vertiefung, Werkzeug-Hub) → --drei */
.pj-register--drei { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 960px) {
  .pj-grid3 { grid-template-columns: 1fr; }
  .pj-register, .pj-register--drei { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) { .pj-register, .pj-register--drei { grid-template-columns: 1fr; } }

/* Freistehender FAQ-Block (Kategorieseiten). Teilt sich die Optik mit der FAQ-Spalte
   der Startseite (Selektoren weiter unten), aber NICHT deren Zweispalten-Raster:
   .pj-redaktion heißt „FAQ links, Redaktion rechts" — allein verwendet bliebe die
   rechte Hälfte der Seite leer. */
.pj-faq-block { max-width: 52rem; }

/* ── Klassen-Schätzer ── */
.pj-schaetzer { padding: 2.1rem 2.2rem; display: flex; flex-direction: column; gap: 1.5rem; }
.pj-schaetzer__kopf { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem; }
.pj-schaetzer__kopf .pj-h2 { margin: 0 0 0.35rem; font-size: 1.44rem; }
.pj-schaetzer__form { display: grid; grid-template-columns: 150px 1fr; gap: 0.9rem 1.25rem; align-items: center; }
.pj-schaetzer__label { font-size: 0.88rem; font-weight: 700; color: var(--color-text-muted); }
.pj-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pj-pills button {
  appearance: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  border: 1.5px solid var(--color-border-control);
  background: var(--color-bg);
  color: var(--color-text-muted);
  transition: border-color 140ms ease, color 140ms ease;
  hyphens: manual; /* wie .pj-btn — eine Auswahlmarke wird nicht getrennt */
}
.pj-pills button:hover, .pj-pills button:focus-visible { border-color: var(--color-primary); color: var(--color-primary); }
.pj-pills button[aria-pressed="true"] {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
}
.pj-pills--liste { flex-direction: column; align-items: stretch; }
.pj-pills--liste button { text-align: left; border-radius: var(--radius); padding: 0.75rem 1rem; font-size: 0.95rem; }
.pj-pills--liste button[aria-pressed="true"] { background: #edf7f4; color: var(--color-primary); }
.pj-skala { position: relative; padding-top: 42px; }
.pj-skala__marker { position: absolute; top: 0; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 3px; transition: left 260ms cubic-bezier(0.2, 0.8, 0.3, 1); }
.pj-skala__fahne { white-space: nowrap; font-size: 0.8rem; font-weight: 700; background: var(--color-text); color: var(--color-bg); padding: 0.3rem 0.7rem; border-radius: 999px; }
.pj-skala__pfeil { width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 6px solid var(--color-text); }
.pj-skala__balken { display: flex; gap: 4px; align-items: flex-end; }
.pj-skala__stufe { flex: 1; display: flex; flex-direction: column; gap: 7px; align-items: center; }
.pj-skala__stufe > div { width: 100%; border-radius: 4px; }
.pj-skala__stufe span { font-size: 0.82rem; font-weight: 700; }
.pj-schaetzer__fuss { display: flex; align-items: center; justify-content: space-between; gap: 1.75rem; border-top: 1px solid #e0eeea; padding-top: 1.1rem; }
.pj-schaetzer__fuss p { margin: 0; font-size: 0.9rem; line-height: 1.6; color: var(--color-text-muted); max-width: 68ch; }
@media (max-width: 800px) {
  .pj-schaetzer { padding: 1.4rem; }
  .pj-schaetzer__form { grid-template-columns: 1fr; gap: 0.5rem; }
  .pj-schaetzer__form .pj-pills { margin-bottom: 0.6rem; }
  .pj-schaetzer__fuss { flex-direction: column; align-items: flex-start; }
}

/* ── Werkzeugkasten ── */
.pj-tools { overflow: hidden; }
.pj-tools__leiste { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0.75rem 0.9rem; background: #f2f9f6; border-bottom: 1px solid #e0eeea; }
.pj-tools__leiste button {
  appearance: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.6rem 1.1rem;
  border-radius: 9px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--color-text-muted);
}
.pj-tools__leiste button:hover, .pj-tools__leiste button:focus-visible { background: #e2efea; color: var(--color-primary); }
.pj-tools__leiste button[aria-selected="true"] {
  font-weight: 700;
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
  box-shadow: 0 4px 10px -7px rgba(12, 95, 81, 0.6);
}
/* Kopfleiste des Werkzeugs — im Entwurf trägt jede Werkzeugkarte im Fließtext ihren
   Namen mit, sonst steht dort ein Eingabefeld ohne Auskunft darüber, was es rechnet.
   Nur bei `kompakt` (Fließtext): In den Reitern und auf den Werkzeugseiten steht der
   Name schon als Überschrift darüber, und zweimal derselbe Titel wäre eine Dopplung. */
.pj-tool__kopf {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 13px 22px;
  background: #f5f9f7;
  border-bottom: 1px solid #e7eeeb;
}
.pj-tool__punkt { flex: none; width: 7px; height: 7px; border-radius: 999px; background: var(--color-primary); }
.pj-tool__name { font-family: var(--font-serif); font-size: 0.97rem; font-weight: 600; letter-spacing: -0.006em; }
.pj-tool__frei { margin-left: auto; font-size: 0.69rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-text-muted); }
.pj-tool__spalten { display: grid; grid-template-columns: 1fr 1fr; gap: 2.2rem; padding: 2rem 2.1rem; }
.pj-tool__eingaben { display: flex; flex-direction: column; gap: 1rem; }
.pj-tool__text { margin: 0; font-size: 0.92rem; line-height: 1.6; color: var(--color-text-muted); }
.pj-tool__hinweis { margin: 0; font-size: 0.82rem; line-height: 1.55; color: var(--color-text-muted); }
.pj-felder { display: flex; flex-wrap: wrap; gap: 1rem; }
.pj-feld { display: flex; flex-direction: column; gap: 0.45rem; font-size: 0.86rem; font-weight: 600; color: var(--color-text-muted); }
.pj-feld input {
  font-family: inherit;
  font-size: 1rem;
  color: var(--color-text);
  padding: 0.75rem 0.85rem;
  border: 1.5px solid var(--color-border-control);
  border-radius: var(--radius);
  background: var(--color-bg);
  max-width: 220px;
  font-variant-numeric: tabular-nums;
}
.pj-ergebnis { background: #f2f9f6; border-radius: 14px; padding: 1.6rem; display: flex; flex-direction: column; gap: 0.8rem; align-self: start; }
.pj-ergebnis__kopf { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; }
.pj-ergebnis__wert { font-size: 2.1rem; font-weight: 500; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.pj-ergebnis__wert--gruen { color: var(--color-primary); }
/* `hyphens: manual` und `flex-wrap`: Schlüssel und Wert stehen in einer Zeile, die in
   einer Vergleichskarte nur rund 200 px breit ist. Mit Auto-Trennung wurde daraus
   „Datengrund-/lage" neben „Gemessener/Verbrauch" — beide Hälften zerhackt, obwohl
   untereinander beide in eine Zeile gepasst hätten. Jetzt bricht die Zeile als Ganzes
   um, statt die Wörter zu brechen. */
.pj-fakten { margin: 0; display: flex; flex-direction: column; gap: 0.55rem; border-top: 1px solid #cfe4dd; padding-top: 0.85rem; hyphens: manual; }
.pj-fakten > div { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.15rem 1rem; font-size: 0.9rem; }
.pj-fakten dt { color: var(--color-text-muted); }
/* `margin-inline-start: auto` hält den Wert auch dann rechts, wenn die Zeile umbricht —
   `justify-content: space-between` kann das nicht, es sieht auf der zweiten Zeile nur
   noch ein einziges Element und stellt es nach links. Ohne diese Zeile sprang der Wert
   je nach Länge zwischen linkem und rechtem Rand. */
.pj-fakten dd { margin: 0 0 0 auto; font-weight: 700; text-align: right; }
.pj-vorher-nachher { display: flex; align-items: center; gap: 1.1rem; }

/* ── Abschluss eines Werkzeugs: Empfehlung + Handlungs-Button ──
   Jedes Werkzeug endet mit einem Satz, der das Ergebnis in eine Handlung übersetzt,
   und dem Button dorthin (Ziel: src/_data/partner.json). Die Trennlinie setzt den
   Block sichtbar vom Rechenergebnis ab — er ist eine Empfehlung, kein Messwert. */
/* UMBAU 2026-08-28: Der Abschluss stand bis dahin INNERHALB der Ergebnisspalte. Beide
   Entwurfsfassungen — 1a wie 5b — setzen ihn dagegen als Fußleiste über die volle
   Kartenbreite, mit Empfehlung links und Knopf rechts. In der Spalte war der Knopf so
   breit wie die halbe Karte und die Empfehlung brach über vier Zeilen um. */
.pj-abschluss {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.85rem 1.4rem;
  border-top: 1px solid #e0eeea;
  padding: 18px 2.1rem;
}
/* Ohne Flex-Basis nimmt der Text die ganze Zeile und drückt den Knopf immer um. */
.pj-abschluss__text { flex: 1 1 20rem; }
.pj-abschluss__text { margin: 0; font-size: 0.9rem; line-height: 1.6; color: var(--color-text-muted); }
.pj-abschluss__text strong { color: var(--color-text); }
.pj-abschluss__aktionen { display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem; }
/* `hidden` am Aktionsblock muss gegen das `display: flex` oben gewinnen — sonst
   bliebe der Button bei gültigem Ausweis sichtbar, obwohl das Skript ihn abschaltet. */
.pj-abschluss__aktionen[hidden] { display: none; }
.pj-vorher-nachher > div { display: flex; flex-direction: column; gap: 0.25rem; }
.pj-vorher-nachher__pfeil { font-size: 1.4rem; color: var(--color-primary); }
/* Der Pfeil kommt aus dem CSS. Als Textknoten im Markup meldet axe „Element content
   contains only non-text characters" (incomplete → pa11y-Fehler), sobald er sichtbar ist.
   Auf /werkzeuge/ fiel das nie auf, weil er dort in einem inaktiven, `hidden`en Reiter
   liegt und axe ihn überspringt. `:empty` trifft nur die neue, leere Fassung — die alte
   mit Textknoten bliebe unverändert, falls irgendwo eine übersehen wurde. */
.pj-vorher-nachher__pfeil:empty::after { content: "→"; }
@media (max-width: 800px) { .pj-tool__spalten { grid-template-columns: 1fr; padding: 1.3rem; gap: 1.4rem; } }

/* ── Ratgeber-Kachel: Bildfläche oben ──
   Der Entwurf gibt der Fläche 168 px Höhe bei rund 372 px Kachelbreite — als festes
   Seitenverhältnis nachgebaut, damit sie in jeder Spaltenbreite dieselbe Form behält
   und beim Nachladen des Bildes nichts springt (CLS). `object-fit: cover` schneidet
   zu, statt zu verzerren; `width/height` setzt der Transform-Plugin selbst. */
.pj-teaser__bild {
  display: block;
  width: 100%;
  aspect-ratio: 372 / 168;
  object-fit: cover;
  border-radius: 10px;
  background: #edf3f1;
}
/* Ohne Bild: ruhige Tonfläche mit feinem Rahmen. Bewusst NICHT die gestreifte
   Platzhalterfläche des Entwurfs samt „Foto: …"-Beschriftung — die ist eine Notiz an
   den Designer. Diese Fläche darf ausgeliefert werden und verschwindet in dem
   Moment, in dem der Beitrag ein `bild` im Front Matter bekommt.
   Vollton, kein Verlauf — dieselbe Regel wie bei den Knöpfen (Begründung bei .pj-btn). */
.pj-teaser__bild--leer { border: 1px solid #e0eeea; background: #eef5f2; }

/* ── Abschluss der Startseite: FAQ + Redaktion nebeneinander ──
   Nachbau des letzten Entwurfsblocks (design-entwurf/1a-homepage.html): zwei gleich
   breite Spalten, je ein Kopf mit Kicker über Serifen-Überschrift und Trennlinie. */
.pj-redaktion { display: grid; grid-template-columns: 1fr 1fr; gap: 3.5rem; align-items: start; }
.pj-redaktion__spalte { display: flex; flex-direction: column; gap: 1.4rem; }
.pj-redaktion__kopf {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  border-bottom: 1px solid #e0eeea;
  padding-bottom: 1rem;
}
.pj-redaktion__kopf .pj-h2 { margin: 0; }

/* Die FAQ bleibt `components/faq.njk` (dort hängt das FAQPage-JSON-LD an derselben
   Schleife). Sie sitzt hier IN einer Rasterspalte — ihre eigene Sektions- und
   Container-Geometrie muss deshalb weg. */
.pj-redaktion .faq, .pj-faq-block .faq { padding: 0; }
.pj-redaktion .faq .container, .pj-faq-block .faq .container { max-width: none; margin-inline: 0; padding-inline: 0; }
.pj-redaktion .faq__list, .pj-faq-block .faq__list { display: flex; flex-direction: column; gap: 0; margin-block-start: 0; max-width: none; }
.pj-redaktion .faq__item, .pj-faq-block .faq__item {
  border: 0;
  border-bottom: 1px solid #e0eeea;
  border-radius: 0;
  padding: 0;
  background: none;
}
/* ACHTUNG, hier wird ein Wächter umgangen — bewusst und mit Ersatz.
   `_sections.css` hält `.faq__question` auf `display: list-item` OHNE `list-style:
   none`, weil das ▶ dort der einzige Hinweis ist, dass der Eintrag aufklappt;
   scripts/tests/touch-ziele.test.js pinnt beides. Der Test liest aber NUR
   `_sections.css` nach EINEM Selektor — er sieht diesen Override grundsätzlich
   nicht, und sein eigener Kommentar sagt das ausdrücklich.
   Zulässig ist der Tausch nur, weil der Hinweis nicht entfällt, sondern wechselt:
   Der Entwurf setzt an das Zeilenende ein grünes + bzw. − (unten). Wer diese Regeln
   entfernt, muss das Dreieck zurückholen — sonst klappt die FAQ ohne jedes sichtbare
   Zeichen auf. Die 44 px Tap-Ziel (WCAG 2.5.5) stehen unverändert. */
.pj-redaktion .faq__question, .pj-faq-block .faq__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  min-block-size: 44px;
  padding-block: 0.9rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-text);
}
.pj-redaktion .faq__question::-webkit-details-marker, .pj-faq-block .faq__question::-webkit-details-marker { display: none; }
.pj-redaktion .faq__question::after, .pj-faq-block .faq__question::after {
  content: "+";
  color: var(--color-primary);
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1;
}
.pj-redaktion .faq__item[open] .faq__question::after, .pj-faq-block .faq__item[open] .faq__question::after { content: "−"; }
.pj-redaktion .faq__question:hover, .pj-faq-block .faq__question:hover,
.pj-redaktion .faq__question:focus-visible, .pj-faq-block .faq__question:focus-visible { color: var(--color-primary); }
.pj-redaktion .faq__answer, .pj-faq-block .faq__answer { margin: 0; padding-bottom: 1rem; font-size: 0.94rem; line-height: 1.65; }

/* Redaktion: Personenzeilen mit runder Fläche links */
.pj-redaktion__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1.15rem; }
.pj-person { display: flex; gap: 0.9rem; align-items: flex-start; }
.pj-person__bild, .pj-person__initiale {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 999px;
  object-fit: cover;
}
.pj-person__initiale {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #e6f2ee;
  color: var(--color-primary);
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 600;
}
.pj-person__text { display: flex; flex-direction: column; gap: 0.2rem; }
.pj-person__name { margin: 0; font-family: var(--font-sans); font-size: 0.97rem; font-weight: 800; letter-spacing: 0; }
.pj-person__rolle, .pj-person__bio { font-size: 0.88rem; line-height: 1.55; color: var(--color-text-muted); }
.pj-person__link { font-size: 0.88rem; }

/* Profilseite (/autor/<slug>/): dieselbe runde Fläche, nur groß genug für einen
   Seitenkopf. Ein eigener Modifier statt einer Kontextregel `.pj-hub-kopf__neben
   .pj-person__initiale` — die Fläche soll sich auch anderswo vergrößern lassen,
   ohne dass jemand die Verschachtelung nachbauen muss. */
.pj-person__bild--gross, .pj-person__initiale--gross { width: 96px; height: 96px; }
.pj-person__initiale--gross { font-size: 2.4rem; }

@media (max-width: 800px) { .pj-redaktion { grid-template-columns: 1fr; gap: 2.5rem; } }

/* ── Ausweisarten-Vergleich + Hinweisbox ── */
.pj-vergleich { display: grid; grid-template-columns: 1fr 1fr; gap: 1.3rem; }
.pj-vgl-karte { padding: 1.9rem 2rem; display: flex; flex-direction: column; gap: 1.1rem; }
.pj-vgl-karte--betont { border: 1.5px solid var(--color-primary); box-shadow: 0 1px 2px rgba(14, 107, 92, 0.06), 0 22px 44px -28px rgba(14, 107, 92, 0.3); }
.pj-vgl-karte .pj-fakten { border-top-color: #e0eeea; }
.pj-hinweisbox {
  margin-top: 1rem;
  background: #e6f2ee;
  border-radius: 14px;
  padding: 1.1rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}
.pj-hinweisbox p { margin: 0; font-size: 0.94rem; line-height: 1.6; }
.pj-hinweisbox .pj-btn { white-space: nowrap; }
@media (max-width: 800px) { .pj-vergleich { grid-template-columns: 1fr; } .pj-hinweisbox { flex-direction: column; align-items: flex-start; } }

/* ── Footer (ersetzt Engine-Footer + CTA-Leiste, projekt/footer.njk) ──
   Dunkelfläche #0a3f37; Textfarbe #9dc0b7 misst 5,99:1 darauf, Weiß 21:1. */
/* KEIN margin-top am Footer (entfernt 2026-08-16). Ein Außenabstand hier ist kein
   Abstand, sondern eine 32px hohe Fläche in der Body-Farbe zwischen dem letzten
   Abschnitt und dem dunklen Footer — sie liest sich als leere Mini-Sektion. Solange
   alle Sektionen auf Canvas standen, war der Streifen unsichtbar (gleiche Farbe);
   seit die Bänder da sind, sitzt er als dritte Farbe zwischen Mint und Dunkelgrün.
   Den Abstand trägt der letzte Abschnitt selbst über sein `padding-block-end` (4rem),
   und der Entwurf setzt den Footer ohnehin unmittelbar unter den Inhalt. */
.pj-footer { background: #0a3f37; color: #9dc0b7; }
.pj-footer__inner {
  max-width: var(--container-max);
  margin-inline: auto;
  /* 58/54px und 40px Spaltenabstand — die Entwurfsmaße. Über rem waren es 54,4/41,6
     und 38,4: Der Fuß stand unten 12px zu knapp. */
  padding: 58px clamp(1.25rem, 4.4vw, 3.5rem) 54px;
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr 1fr;
  gap: 40px;
}
.pj-footer__name { font-weight: 800; font-size: 1rem; color: #ffffff; }
.pj-footer__claim { margin: 0.7rem 0 0; font-size: 0.88rem; line-height: 1.6; max-width: 32ch; }
.pj-footer__col { display: flex; flex-direction: column; gap: 0.55rem; font-size: 0.88rem; }
.pj-footer__heading { color: #ffffff; font-weight: 700; margin-bottom: 0.25rem; }
.pj-footer__col a { color: #9dc0b7; text-decoration: none; }
.pj-footer__col a:hover, .pj-footer__col a:focus-visible { color: #ffffff; }
.pj-footer__meta {
  max-width: var(--container-max);
  margin-inline: auto;
  padding: 0 clamp(1.25rem, 4.4vw, 3.5rem) 2rem;
  font-size: 0.82rem;
}
@media (max-width: 860px) { .pj-footer__inner { grid-template-columns: 1fr 1fr; gap: 1.8rem; } }
@media (max-width: 520px) { .pj-footer__inner { grid-template-columns: 1fr; } }

/* ── Blog: Listing + Artikel im Entwurfs-Stil ── */
.post-list h1 { font-size: clamp(2rem, 4vw, 2.9rem); letter-spacing: -0.018em; }
.post-list__items { border-top: 1px solid #e0eeea; }
.post-list__item { border-bottom: 1px solid #e0eeea; }
.post-list__item a { display: flex; flex-direction: column; gap: 0.45rem; padding: 1.4rem 0; text-decoration: none; color: var(--color-text); }
.post-list__title { font-family: var(--font-serif); font-size: 1.32rem; margin: 0; line-height: 1.28; }
.post-list__item a:hover .post-list__title { color: var(--color-primary); }
.post-list__meta { margin: 0; font-size: 0.8rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-primary); font-variant-numeric: tabular-nums; }
.post-list__excerpt { margin: 0; font-size: 0.95rem; line-height: 1.6; color: var(--color-text-muted); }
.post { padding-top: 0; }
.post__header {
  background: #e6f2ee;
  border-radius: var(--radius-lg);
  padding: 2.6rem 2rem 2.2rem;
  margin: 1.5rem 0 2rem;
  text-align: center;
}
.post__header h1 { margin: 0 auto; font-size: clamp(1.9rem, 3.8vw, 2.6rem); line-height: 1.1; max-width: 24ch; text-wrap: balance; }
.post__meta { margin-top: 0.9rem; font-size: 0.86rem; color: var(--color-text-muted); }
.prose { font-size: 1.05rem; line-height: 1.75; color: #22403a; }
.prose h2 { font-size: 1.6rem; margin-top: 2.2rem; }
.prose a { color: var(--color-primary); }
/* Ein Knopf im Fließtext behält seine eigene Schriftfarbe. `.prose a` (0,1,1) schlägt
   sonst `.pj-btn` (0,1,0): Der Handlungs-Button im eingebetteten Ablauf-Checker stand
   grün auf grün und war schlicht nicht lesbar. Auf der Startseite trat das nicht auf —
   dort gibt es keine Prosa; gefunden hat es pa11y auf der Artikelseite (2026-08-16). */
.prose a.pj-btn { color: var(--color-on-primary); }
.prose a.pj-btn:hover, .prose a.pj-btn:focus-visible { color: var(--color-on-primary); }
.prose a.pj-btn--ghost { color: var(--color-text); }
.prose a.pj-btn--ghost:hover, .prose a.pj-btn--ghost:focus-visible { color: var(--color-primary); }
/* „Kurz gesagt"-Kasten und Diagramm-Karten aus dem Entwurfs-Artikel */
.pj-kurzgesagt {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.03), 0 14px 30px -26px rgba(20, 48, 43, 0.25);
  /* px und nicht rem: Der Entwurf misst die Prosa-Boxen in festen 24/26 Pixeln. Über
     rem gerechnet kamen 22,4/25,6 heraus — nah dran, aber eben nicht der Wert. */
  padding: 24px 26px;
  margin: 1.6rem 0;
}
.pj-kurzgesagt__label { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-primary); margin-bottom: 0.4rem; }
/* Kein `margin: 0` hier: Diese Regel ist (0,1,1) und schlug damit das Abstandspaar
   `.pj-kurzgesagt > * + *` (0,1,0) weiter unten — zwei Absätze in einem „Kurz gesagt"
   klebten aneinander. Den Rand setzt jetzt dort `> *` zurück. */
.pj-kurzgesagt p { font-size: 1.02rem; line-height: 1.6; font-weight: 600; }
.pj-diagramm { margin: 1.6rem 0; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 14px; overflow: hidden; }
.pj-diagramm__titel { padding: 1.2rem 1.5rem 0.3rem; font-size: 0.95rem; font-weight: 700; }
.pj-diagramm__zeilen { padding: 0.5rem 1.5rem 1.2rem; display: flex; flex-direction: column; gap: 0.65rem; }
.pj-diagramm__zeile { display: flex; align-items: center; gap: 0.85rem; font-size: 0.88rem; }
.pj-diagramm__name { width: 130px; color: var(--color-text-muted); flex-shrink: 0; }
.pj-diagramm__spur { flex: 1; height: 16px; background: #eef4f2; border-radius: 3px; }
.pj-diagramm__wert { height: 100%; background: var(--color-primary); border-radius: 3px; }
.pj-diagramm__zahl { width: 40px; text-align: right; font-variant-numeric: tabular-nums; font-size: 0.84rem; }
.pj-diagramm figcaption { border-top: 1px solid var(--color-border); padding: 0.75rem 1.5rem; font-size: 0.82rem; color: var(--color-text-muted); }
/* ── Werkzeug im Fließtext (5b) ──
   KORREKTUR 2026-08-28 nach dem Vorlagenabgleich. Hier stand vorher „im Artikel ist ein
   Werkzeug IMMER einspaltig", begründet mit: „Bei 572 px verfügbarer Breite gibt es
   keine sinnvolle zweispaltige Aufteilung." Der erste Teil der Beobachtung war richtig —
   `1fr 1fr` teilt die Artikelspalte in zwei 244-px-Hälften, und daraus wurden
   Buchstabensäulen und 450 px hohe Leerflächen. Der Schluss daraus war es nicht.

   Der Entwurf löst dasselbe Problem mit einem ASYMMETRISCHEN Raster: 196px für die
   Eingabe, der Rest fürs Ergebnis (196 + 28 + 348 = 572). Einspaltig gestapelt wurde die
   Karte dagegen 682 px hoch statt der 292 px des Entwurfs — mehr als das Doppelte, und
   das war im Bildvergleich der auffälligste Unterschied des ganzen Artikels.

   Auch die Hülle ist eine andere als auf der Startseite: Dort ist das Werkzeug ein
   großes Panel (radius 16, Schatten, Zeile 117), hier eine ruhige Karte im Lesefluss —
   radius 14, kein Schatten. Ein schwebendes Element mitten im Text liest sich wie ein
   Dialogfenster. */
.pj-artikel-tool {
  margin: 1.8rem 0;
  border-radius: 14px;
  box-shadow: none;
}
.pj-artikel-tool .pj-tool__spalten {
  grid-template-columns: 196px 1fr;
  gap: 28px;
  padding: 22px;
  align-items: stretch;
}
/* Ergebnisspalte: im Entwurf keine getönte Box, sondern eine Spalte hinter einer feinen
   Trennlinie. Die Tonfläche gehört der Startseiten-Fassung — im Artikel säße sie als
   zweiter Kasten in einem Kasten. */
.pj-artikel-tool .pj-ergebnis {
  background: transparent;
  border-radius: 0;
  padding: 0 0 0 28px;
  border-left: 1px solid #ecf1ef;
  align-self: stretch;
  gap: 0.7rem;
}
.pj-artikel-tool .pj-ergebnis__wert { font-size: 1.63rem; }
.pj-artikel-tool .pj-feld input { max-width: 100%; }
/* Der Abschlussblock steht im Entwurf als eigene Fußleiste über die volle Kartenbreite.
   Hier bleibt er in der Ergebnisspalte: Er liegt im Markup INNERHALB von .pj-ergebnis,
   und ihn herauszuziehen hieße, sieben Werkzeug-Includes samt ihrer JS-Verdrahtung
   umzubauen. Bekannte Abweichung, bewusst offen gelassen. */
.pj-artikel-tool .pj-abschluss { border-top-color: #ecf1ef; padding: 14px 22px; }
.pj-artikel-tool .pj-abschluss__text { font-size: 0.81rem; flex: 1 1 14rem; }
/* Statusbadges: Der Entwurf fährt im Artikel die HELLE Fassung (Fläche getönt, Schrift
   dunkel), auf der Startseite die kräftige. Ein Vollton-Rot mitten im Lesetext zieht
   mehr Aufmerksamkeit als die Aussage verdient. */
.pj-artikel-tool .pj-badge { background: #e6f2ee; color: var(--color-primary); }
.pj-artikel-tool .pj-badge--rot { background: #fbe5e2; color: #a5271a; }
.pj-artikel-tool .pj-badge--gelb { background: #fbf0cf; color: #7a5500; }

/* Erst unterhalb der Artikelspalte wird gestapelt — 196px Eingabe plus Trennlinie
   brauchen rund 480px Fensterbreite. */
@media (max-width: 640px) {
  .pj-artikel-tool .pj-tool__spalten { grid-template-columns: 1fr; gap: 1.4rem; padding: 1.3rem; }
  .pj-artikel-tool .pj-ergebnis { border-left: 0; padding-left: 0; }
}
.pj-artikel-tool .pj-schaetzer { padding: 1.4rem 1.5rem; }
.pj-artikel-tool .pj-schaetzer__fuss { flex-direction: column; align-items: flex-start; gap: 1rem; }

/* ══════════════════════════════════════════════════════════════════════════════
   AUSBAU 2026-08-16 — die übrigen fünf Entwurfsseiten
   3a-ratgeber · 3b-kategorie · 3c-news · 5b-artikel · 2a-impressum
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── Brotkrume (3b, 2a) ── */
.pj-brotkrume {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 1rem;
}
.pj-brotkrume a { color: var(--color-text-muted); text-decoration: none; }
.pj-brotkrume a:hover, .pj-brotkrume a:focus-visible { color: var(--color-primary); text-decoration: underline; }
.pj-brotkrume [aria-current="page"] { color: var(--color-text); font-weight: 600; }

/* ── Kopfbereich der Hub-Seiten (3a, 3b, 3c, Werkzeuge) ── */
/* Die drei Hub-Arten tragen im Entwurf UNTERSCHIEDLICHE Maße — Ratgeber 52/40px bei
   46px Titel, Kategorie 44/40 bei 44px, News 44/34 bei 42px. Vorher stand hier ein
   Wert für alle (40/32, Titel 46,4px): Der Ratgeber-Kopf war 20px zu flach, der
   News-Titel 4px zu groß. Auch die Zeilenhöhe war mit 1.15 durchweg zu locker; der
   Entwurf setzt 1.06 und lässt die Titel dadurch als Block wirken. */
.pj-hub-kopf { padding-block: 52px 40px; }
.pj-hub-kopf--karte { padding-block-start: 44px; }
.pj-hub-kopf--news { padding-block: 44px 34px; }
.pj-hub-kopf__titel {
  font-family: var(--font-serif);
  font-size: clamp(1.9rem, 4vw, 2.875rem);
  line-height: 1.06;
  letter-spacing: -0.018em;
  font-weight: 600;
  margin: 0.6rem 0 0;
  max-width: 22ch;
}
.pj-hub-kopf--karte .pj-hub-kopf__titel { font-size: clamp(1.9rem, 4vw, 2.75rem); }
.pj-hub-kopf--news .pj-hub-kopf__titel { font-size: clamp(1.9rem, 4vw, 2.625rem); }
.pj-hub-kopf__lead {
  margin: 0.9rem 0 0;
  font-size: 1.06rem;
  line-height: 1.65;
  color: var(--color-text-muted);
  max-width: 62ch;
}

/* ── Aufmacher: eine große Kachel plus zwei schmale (3a, 3c) ── */
.pj-aufmacher { display: grid; gap: 1.4rem; }
.pj-aufmacher__neben { display: grid; gap: 1.15rem; align-content: start; }
@media (min-width: 860px) {
  /* Verhältnis und Abstand des Entwurfs: 1.55fr/1fr bei 28px (3a), 1.6fr/1fr (3c). */
  .pj-aufmacher { grid-template-columns: 1.55fr 1fr; gap: 1.75rem; }
}
/* Bildfläche des Aufmachers: 300px bei rund 693px Kachelbreite (3a) — als Verhältnis
   nachgebaut, damit sie in jeder Spaltenbreite dieselbe Form behält. */
.pj-teaser--gross .pj-teaser__bild { aspect-ratio: 7 / 3; }
.pj-teaser--gross .pj-teaser__titel { font-size: clamp(1.45rem, 2.2vw, 1.81rem); line-height: 1.2; }
.pj-teaser--gross .pj-teaser__text { padding: 1.6rem 1.75rem 1.75rem; }
.pj-teaser--gross .pj-karte__text { font-size: 0.97rem; }

/* Beitragszahl in der Registerkachel — gezählt, nicht behauptet. Im Entwurf steht sie
   gedämpft und ohne Auszeichnung unter dem Kurztext, nicht als grüner Fettdruck: sie
   ist eine Angabe, keine Handlungsaufforderung. */
.pj-register__zahl {
  margin-top: 0.35rem;
  font-size: 0.78rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}

/* ── „Das Wichtigste in drei Sätzen" (3b) und die Merklisten der Werkzeugseiten ── */
.pj-kurzfassung { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
@media (min-width: 800px) { .pj-kurzfassung { grid-template-columns: repeat(3, 1fr); } }
.pj-kurzfassung__punkt {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 1.1rem 1.25rem;
  font-size: 0.96rem;
  line-height: 1.55;
}
.pj-kurzfassung__zahl {
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  color: var(--color-primary);
  flex-shrink: 0;
  padding-top: 0.15rem;
}

/* ── Meldungsliste (3c) ── */
.pj-meldungen { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.85rem; }
.pj-meldung {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: baseline;
  gap: 0.5rem 0.85rem;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 1.1rem 1.35rem;
}
.pj-meldung__datum {
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
  white-space: nowrap;
}
.pj-meldung__titel {
  grid-column: 1 / -1;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--color-text);
  text-decoration: none;
}
.pj-meldung__titel:hover, .pj-meldung__titel:focus-visible { color: var(--color-primary); text-decoration: underline; }
.pj-meldung__text { grid-column: 1 / -1; margin: 0; font-size: 0.94rem; line-height: 1.6; color: var(--color-text-muted); }

/* ── Zeitleiste „Was wann gilt" (3c) ── */
.pj-zeitleiste { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.pj-zeitleiste li {
  display: grid;
  grid-template-columns: 7.5rem 1fr;
  gap: 1rem;
  align-items: baseline;
  padding: 1rem 0 1rem 1.25rem;
  border-left: 2px solid var(--color-border);
  position: relative;
}
.pj-zeitleiste li::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 1.35rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-primary);
}
.pj-zeitleiste__marke { font-weight: 800; font-size: 0.92rem; font-variant-numeric: tabular-nums; }
.pj-zeitleiste__text { color: var(--color-text-muted); line-height: 1.55; font-size: 0.96rem; }
.pj-zeitleiste__fussnote { margin-top: 1.2rem; font-size: 0.84rem; color: var(--color-text-muted); }
@media (max-width: 560px) {
  .pj-zeitleiste li { grid-template-columns: 1fr; gap: 0.2rem; }
}

/* ── Filter-Chips (3a, 3c) ──
   `hidden` MUSS gewinnen: Die Leiste ist im Markup ausgeblendet und wird erst von
   static/assets/projekt.js eingeblendet. Ohne diese Zeile schlägt `display: flex`
   das Attribut, und die Chips stünden auch ohne JS da — als Bedienelemente, die
   nichts tun. Derselbe Fall wie bei .pj-abschluss__aktionen weiter oben. */
.pj-chips[hidden] { display: none; }
.pj-chips { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 1.75rem; }
.pj-chips__label { font-size: 0.82rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted); }
.pj-chips__leiste { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pj-chip {
  /* 44px Mindesthöhe: Tap-Ziel nach WCAG 2.5.5, geprüft von axe (target-size). */
  min-block-size: 44px;
  padding: 0.55rem 1.05rem;
  border: 1px solid var(--color-border-control);
  border-radius: 999px;
  background: var(--color-bg);
  color: var(--color-text);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.pj-chip:hover { border-color: var(--color-primary); color: var(--color-primary); }
.pj-chip[aria-pressed="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
.pj-chips__stand { margin: 0; font-size: 0.85rem; color: var(--color-text-muted); min-block-size: 1.2em; }
/* Der Filter blendet über das `hidden`-Attribut aus. Beide Kartenarten setzen selbst
   ein `display`, das das Attribut sonst schlägt — dieselbe Falle wie bei .pj-chips. */
.pj-teaser[hidden], .pj-meldung[hidden] { display: none; }

/* ── Werkzeug-Leiste „Werkzeuge zum Thema" (3a, 3b, 5b) ── */
.pj-werkzeugleiste {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 1.4rem 1.6rem;
  display: grid;
  gap: 0.9rem;
}
.pj-werkzeugleiste__titel { font-size: 0.82rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-primary); }
.pj-werkzeugleiste__links { display: grid; gap: 0.75rem; }
@media (min-width: 760px) { .pj-werkzeugleiste__links { grid-template-columns: repeat(3, 1fr); } }
.pj-werkzeugleiste__links a {
  display: flex;
  align-items: center;
  min-block-size: 44px;
  padding: 0.6rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--color-text);
  text-decoration: none;
}
.pj-werkzeugleiste__links a::after { content: " →"; margin-left: auto; padding-left: 0.5rem; color: var(--color-primary); }
.pj-werkzeugleiste__links a:hover,
.pj-werkzeugleiste__links a:focus-visible { border-color: var(--color-primary); color: var(--color-primary); }

/* ── Artikel (5b) ──
   Der Entwurf setzt den Kopf als getöntes Band über die volle Breite und stellt
   Kicker, Titel, Lead und Meta ZENTRIERT hinein; darunter läuft ein Bildband über
   dieselbe Breite, erst dann beginnt die zentrierte Textspalte. Bis zum 18.08. stand
   hier stattdessen alles linksbündig auf Weiß in einer 46-rem-Spalte am linken
   Bühnenrand — das war der auffälligste Unterschied zur Vorlage. */
.pj-artikel__kopf {
  background: #e6f2ee;
  padding-block: 3rem 2.6rem;
  /* Vollbreite bei gehaltener Bühne — dieselbe Rechnung wie bei .pj-notice oben. */
  padding-inline: calc(max(0px, 100% - var(--container-max)) / 2 + clamp(1.25rem, 4.4vw, 3.5rem));
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1rem;
}
.pj-artikel__titel {
  font-family: var(--font-serif);
  font-size: clamp(1.85rem, 4vw, 2.63rem);
  line-height: 1.07;
  letter-spacing: -0.018em;
  font-weight: 600;
  margin: 0;
  max-width: 22ch;
  text-wrap: balance;
}
.pj-artikel__lead { margin: 0; font-size: 1.12rem; line-height: 1.6; color: var(--color-text-muted); max-width: 58ch; text-wrap: pretty; }
.pj-artikel__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.55rem 10px;
  margin: 0;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}
/* Runde Fläche vor dem Namen (Entwurf: 30px). Sie steht für ein Porträt, das es noch
   nicht gibt — deshalb Tonfläche statt Initiale: eine Initiale behauptete eine
   Person, die Fläche hält nur den Platz. */
.pj-artikel__avatar { flex: none; width: 30px; height: 30px; border-radius: 999px; background: #cfe4dd; }
.pj-artikel__autor { font-weight: 700; color: var(--color-text); }
/* Entwurfshinweis: sichtbar, aber nicht als Fehlermeldung gestaltet — der Text ist
   brauchbar, nur eben ungeprüft. */
.pj-artikel__entwurf {
  margin: 1.2rem 0 0;
  padding: 0.7rem 1rem;
  border-left: 3px solid var(--color-rating);
  background: #fdf8ef;
  font-size: 0.88rem;
  color: #6b4a12;
  border-radius: 0 8px 8px 0;
}
/* Bildband: läuft wie im Entwurf über die volle Breite direkt unter dem Kopfband,
   ohne Radius und ohne Innenabstand. Ohne Bild bleibt die Fläche stehen (Entscheidung
   Yves, 18.08.) — sie füllt sich in dem Moment, in dem ein Beitrag `bild` im Front
   Matter bekommt. */
.pj-artikel__bild { margin: 0; }
.pj-artikel__bild img, .pj-artikel__bild--leer {
  display: block;
  width: 100%;
  /* 24vw, nicht 23vw: Bei der Bühnenbreite von 1280px ergaben 23vw nur 294,4px — die
     300px des Entwurfs wurden nie erreicht, weil die obere Grenze des clamp gar nicht
     zum Zug kam. Gemessen am 2026-08-28. */
  height: clamp(180px, 24vw, 300px);
  object-fit: cover;
  border-radius: 0;
  background: #eef5f2;
}
.pj-artikel__bild--leer { border-bottom: 1px solid #e0eeea; }
.pj-artikel__bild figcaption { padding: 0.6rem clamp(1.25rem, 4.4vw, 3.5rem); font-size: 0.82rem; color: var(--color-text-muted); }
.pj-artikel__rumpf {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4.4vw, 3.5rem);
  padding-block: 2.75rem 3rem;
}
/* 700px und zentriert (Ansage Yves, 2026-08-29). Der Entwurf misst 17px/1.75 in einer
   68ch-Spalte — das sind hier 574px, und das ist der Wert, gegen den der Design-Abgleich
   sonst prüft. Die Abweichung ist deshalb in scripts/lib/design-paare.js hinterlegt,
   sonst meldete jeder Lauf sie als Befund — und eine Liste mit Dauermeldungen wird nicht
   mehr gelesen.

   Feste Pixel statt `ch`: Die Zahl ist eine Desktop-Entscheidung und soll nicht an der
   Schriftmetrik hängen. Auf schmalen Fenstern greift sie ohnehin nicht, dort ist die
   Spalte durch den Innenabstand des Rumpfs begrenzt (1168px verfügbar bei 1280px Bühne).
   Alles im Textkörper skaliert mit: Content-Bausteine, CTA-Flächen und die eingebetteten
   Werkzeuge, deren Raster 196px | 1fr die Mehrbreite der Ergebnisspalte zuschlägt. */
/* EIGENE RAHMENPALETTE IM ARTIKELKÖRPER (gemessen 2026-08-28). Der Entwurf führt auf
   5b durchgängig hellere Linien als auf den Übersichtsseiten: #dfe6e3 statt #d9e7e2 für
   Kartenrahmen, #ecf1ef statt #e0eeea für Trennlinien. Statt zwei Dutzend
   Baustein-Regeln einzeln umzuschreiben, wird das Token hier im Geltungsbereich neu
   belegt — jede Karte im Artikel erbt es, jede Karte außerhalb behält die kräftigere.
   Geprüft, bevor das hier stand: KEIN Bedienelement liest --color-border (die Rahmen
   von Eingaben hängen an --color-border-control, das 3:1 halten muss, WCAG 1.4.11).
   Ein Scope-Override wäre sonst ein stiller Kontrastverlust an genau den Stellen, an
   denen er verboten ist. */
.pj-artikel__text {
  --color-border: #dfe6e3;
  max-width: 700px;
  margin-inline: auto;
  font-size: 1.0625rem;
  line-height: 1.75;
}
.pj-artikel__text > * + * { margin-top: 1.5rem; }
.pj-artikel__text h2 { font-size: 1.69rem; margin-top: 2.4rem; }
.pj-artikel__text h3 { font-size: 1.25rem; margin-top: 1.9rem; }
.pj-artikel__fuss { margin-top: 1rem; }

/* ── Rechtstexte zweispaltig (2a) ── */
.pj-rechtstext__kopf { padding-block: 44px 30px; border-bottom: 1px solid var(--color-border); }
.pj-rechtstext__titel {
  font-family: var(--font-serif);
  font-size: clamp(1.9rem, 3.6vw, 2.5rem);
  line-height: 1.08;
  font-weight: 600;
  letter-spacing: -0.018em;
  margin: 0.6rem 0 0;
}
.pj-rechtstext__intro { margin: 0.85rem 0 0; color: var(--color-text-muted); max-width: 62ch; line-height: 1.6; }
.pj-rechtstext__raster { display: grid; gap: 2.5rem; padding-block: 36px 48px; }
@media (min-width: 900px) {
  .pj-rechtstext__raster { grid-template-columns: minmax(0, 1fr) 13.75rem; gap: 2.5rem; }
}
.pj-rechtstext__text { max-width: 44rem; }
/* Abschnittsmarke des Entwurfs: „01 · ANBIETER" in EINER Zeile über der Karte, klein,
   grün, versal — nicht die Ziffer über einer großen Serifen-Überschrift, wie es hier
   bis zum 18.08. stand. Die Nummer macht weiter der CSS-Zähler und nicht das Markup:
   sonst wanderte sie beim Umsortieren eines Abschnitts nicht mit. */
.pj-rechtstext__text { counter-reset: abschnitt; }
.pj-rechtstext__text h2 {
  counter-increment: abschnitt;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
  margin: 2.35rem 0 0.9rem;
}
.pj-rechtstext__text h2::before { content: counter(abschnitt, decimal-leading-zero) " · "; }
.pj-rechtstext__text h2:first-child { margin-top: 0; }
/* Der Abschnittsinhalt steht im Entwurf in einer weißen Karte — sie kommt aus dem
   Filter `alsBloecke` (_config/filters.js), weil Markdown Überschrift und Absätze als
   flache Geschwister liefert. */
.pj-rechtstext__karte {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.03), 0 14px 30px -24px rgba(20, 48, 43, 0.2);
  padding: 1.5rem 1.75rem;
}
.pj-rechtstext__karte > :first-child { margin-top: 0; }
.pj-rechtstext__karte > :last-child { margin-bottom: 0; }
.pj-rechtstext__spalte { display: grid; gap: 1.5rem; align-content: start; }
@media (min-width: 900px) { .pj-rechtstext__spalte { position: sticky; top: 2rem; } }
/* Umgekehrt zur bisherigen Umsetzung: Im Entwurf trägt der TEXT die Karten, die
   Sprungliste steht offen daneben — nur mit einer Linie zum Inhalt hin. */
/* 2px und 20px: Der Entwurf führt die Sprungliste an einer deutlich sichtbaren Kante,
   nicht an einer Haarlinie. Feste Farbe statt Token — im Artikelkörper ist
   --color-border auf die hellere 5b-Palette umgestellt, und dort verschwände die Kante. */
.pj-sprungliste {
  background: none;
  border: 0;
  border-left: 2px solid #e0eeea;
  border-radius: 0;
  padding: 0.1rem 0 0.1rem 20px;
}
.pj-sprungliste__titel { font-size: 0.78rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); margin-bottom: 0.7rem; }
.pj-sprungliste ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.15rem; }
.pj-sprungliste a {
  display: block;
  padding: 0.5rem 0;
  font-size: 0.92rem;
  line-height: 1.4;
  color: var(--color-text);
  text-decoration: none;
}
.pj-sprungliste a:hover, .pj-sprungliste a:focus-visible { color: var(--color-primary); text-decoration: underline; }

/* ── Wegweiser auf einer eigenen Seite: sonst liefe die Hero-Karte über die volle
   Bühnenbreite und die Fragen stünden als sehr lange Zeilen nebeneinander. ── */
.pj-wegweiser-breit { max-width: 34rem; }

/* ── Lexikon: Engine-Templates (src/glossar/) bleiben unangetastet, nur die Optik
   kommt aus dem Projekt. Deshalb hier ausschließlich Engine-Klassennamen. ── */
.glossar .container, .glossar-begriff .container { padding-block: 2.5rem 4rem; }
.glossar h1, .glossar-begriff h1 {
  font-family: var(--font-serif);
  font-size: clamp(1.9rem, 3.6vw, 2.6rem);
  letter-spacing: -0.018em;
}
.glossar__intro { color: var(--color-text-muted); font-size: 1.05rem; max-width: 62ch; }
.glossar__register ul { list-style: none; display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0; margin: 1.5rem 0 2.5rem; }
.glossar__register a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 44px;
  min-block-size: 44px;
  border: 1px solid var(--color-border-control);
  border-radius: 10px;
  font-weight: 700;
  text-decoration: none;
  color: var(--color-text);
}
.glossar__register a:hover, .glossar__register a:focus-visible { border-color: var(--color-primary); color: var(--color-primary); }
.glossar__gruppe { margin-bottom: 2.5rem; }
.glossar__gruppe h2 { font-size: 1.4rem; border-bottom: 1px solid var(--color-border); padding-bottom: 0.4rem; }
.glossar__liste { display: grid; gap: 0.25rem; margin: 1.2rem 0 0; }
.glossar__liste dt { font-weight: 700; margin-top: 0.9rem; }
.glossar__liste dt a { color: var(--color-text); text-decoration: none; }
.glossar__liste dt a:hover, .glossar__liste dt a:focus-visible { color: var(--color-primary); text-decoration: underline; }
.glossar__liste dd { margin: 0.2rem 0 0; color: var(--color-text-muted); font-size: 0.95rem; line-height: 1.55; }
.glossar-begriff__pfad { font-size: 0.85rem; margin-bottom: 1rem; }
.glossar-begriff__pfad a { color: var(--color-text-muted); text-decoration: none; }
.glossar-begriff__synonyme { color: var(--color-text-muted); font-size: 0.92rem; margin-top: 0.3rem; }
.glossar-begriff__definition {
  font-size: 1.1rem;
  line-height: 1.65;
  font-weight: 600;
  background: #e6f2ee;
  border-radius: 14px;
  padding: 1.3rem 1.5rem;
  margin: 1.4rem 0 2rem;
  max-width: 46rem;
}
.glossar-begriff .prose, .glossar-begriff__verwandt { max-width: 46rem; }
.glossar-begriff__verwandt ul { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.glossar-begriff__verwandt a {
  display: flex;
  align-items: center;
  min-block-size: 44px;
  padding: 0.5rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--color-text);
}
.glossar-begriff__verwandt a:hover, .glossar-begriff__verwandt a:focus-visible { border-color: var(--color-primary); color: var(--color-primary); }

/* ══════════════════════════════════════════════════════════════════════════════
   VORLAGEN-ANGLEICH 2026-08-18 — die Darstellungsformen der Entwürfe
   ══════════════════════════════════════════════════════════════════════════════
   Beim Import am 16.08. bekam jede Seitenart dasselbe Kachelraster (.pj-teaser in
   .pj-grid3). Die Vorlage kennt aber vier verschiedene Formen, und genau ihr Fehlen
   ist der Grund, warum Ratgeber, Kategorie, News und Artikel „komplett anders"
   aussahen als die Entwürfe:
     · eine 320px breite Seitenleiste neben dem Inhalt (3a, 3b, 3c)
     · Beitragszeilen statt Kacheln, in drei Zuschnitten (3a, 3b, 3c)
     · eine horizontale Einstiegskarte (3b)
     · der zentrierte Artikelkopf im getönten Band (5b, oben bei .pj-artikel__kopf)
   Maße stehen so, wie der Entwurf sie setzt; wo er px nennt, steht hier rem. */

/* ── Inhalt + Seitenleiste (3a, 3b, 3c) ── */
.pj-spalten { display: grid; gap: 2.5rem; align-items: start; }
/* Grid-Kinder tragen min-width:auto und schrumpfen nicht unter ihre
   Mindestinhaltsbreite — ohne diese Zeile schiebt eine lange Zeile die Leiste raus. */
.pj-spalten > * { min-width: 0; }
@media (min-width: 980px) {
  .pj-spalten { grid-template-columns: minmax(0, 1fr) 20rem; gap: 3rem; }
}
.pj-leiste { display: grid; gap: 1.4rem; align-content: start; }
.pj-leiste__karte {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.03), 0 16px 34px -26px rgba(20, 48, 43, 0.22);
  padding: 1.5rem;
  display: grid;
  gap: 0.85rem;
  align-content: start;
}
/* Mint-Karte: im Entwurf ohne Rahmen und ohne Schatten — sie soll als Fläche wirken,
   nicht als zweite Karte. Kontraste auf #e6f2ee sind oben bei den Mint-Bändern
   nachgerechnet (Text 12,3:1 · gedämpft 6,93:1 · Primär 5,59:1). */
.pj-leiste__karte--mint { background: #e6f2ee; border-color: transparent; box-shadow: none; }
.pj-leiste__titel { font-family: var(--font-serif); font-size: 1.06rem; font-weight: 600; letter-spacing: -0.008em; }
.pj-leiste__text { margin: 0; font-size: 0.92rem; line-height: 1.6; color: #22403a; }
.pj-leiste__liste { list-style: none; margin: 0; padding: 0; display: grid; }
.pj-leiste__liste a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  min-block-size: 44px;
  padding: 0.55rem 0;
  border-bottom: 1px solid #e0eeea;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--color-text);
  text-decoration: none;
}
.pj-leiste__liste li:last-child a { border-bottom: 0; padding-bottom: 0; }
.pj-leiste__liste a:hover, .pj-leiste__liste a:focus-visible { color: var(--color-primary); }
/* Zierpfeil aus dem CSS, nicht als aria-hidden-Span im Markup — Begründung steht
   ausführlich bei .pj-werkzeugleiste__links (axe/pa11y-Fehlalarm). */
.pj-leiste__liste--pfeil a::after { content: "→"; color: var(--color-primary); font-weight: 700; }
.pj-leiste__zahl { font-size: 0.8rem; font-variant-numeric: tabular-nums; color: var(--color-text-muted); font-weight: 500; }
/* „Meistgelesen"-Form des Entwurfs: Rang links, kein Trennstrich, oben ausgerichtet. */
.pj-leiste__liste--rang a { align-items: flex-start; justify-content: flex-start; gap: 0.75rem; border-bottom: 0; padding: 0.4rem 0; line-height: 1.4; }
.pj-leiste__rang { flex: none; font-size: 0.82rem; font-variant-numeric: tabular-nums; color: var(--color-text-muted); font-weight: 500; padding-top: 0.1rem; }
.pj-leiste .pj-person__bild, .pj-leiste .pj-person__initiale { width: 38px; height: 38px; font-size: 1rem; }
.pj-leiste .pj-person__name { font-size: 0.92rem; }
.pj-leiste .pj-person__rolle { font-size: 0.84rem; }
.pj-leiste__fussnote { margin: 0; border-top: 1px solid #e0eeea; padding-top: 0.75rem; font-size: 0.85rem; line-height: 1.55; color: var(--color-text-muted); }
/* Zeitleiste in der Leiste: schmaler als die Sektionsvariante, ohne Punkt. */
.pj-leiste .pj-zeitleiste li { grid-template-columns: 4.6rem 1fr; gap: 0.75rem; padding: 0.55rem 0 0.75rem 0.85rem; }
.pj-leiste .pj-zeitleiste li::before { content: none; }
.pj-leiste .pj-zeitleiste li:first-child { border-left-color: var(--color-primary); }
.pj-leiste .pj-zeitleiste__marke { font-size: 0.82rem; font-weight: 500; color: var(--color-text-muted); }
.pj-leiste .pj-zeitleiste li:first-child .pj-zeitleiste__marke { color: var(--color-primary); }
.pj-leiste .pj-zeitleiste__text { font-size: 0.88rem; line-height: 1.5; color: var(--color-text); }

/* ── Beitragszeilen (3a: mit Bild · 3b: kompakt · 3c: Meldung) ── */
.pj-liste { display: grid; }
.pj-zeile {
  display: grid;
  gap: 0.9rem;
  padding: 1.35rem 0;
  border-bottom: 1px solid #e0eeea;
  text-decoration: none;
  color: var(--color-text);
}
.pj-zeile__bild {
  display: block;
  width: 100%;
  aspect-ratio: 168 / 112;
  object-fit: cover;
  border-radius: 10px;
  background: #eef5f2;
}
.pj-zeile__bild--leer { border: 1px solid #e0eeea; }
.pj-zeile__inhalt { display: grid; gap: 0.45rem; align-content: start; }
.pj-zeile__kicker { font-size: 0.7rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--color-primary); font-variant-numeric: tabular-nums; }
.pj-zeile__titel { font-family: var(--font-serif); font-size: 1.3rem; font-weight: 600; line-height: 1.24; letter-spacing: -0.012em; }
.pj-zeile__text { font-size: 0.91rem; line-height: 1.6; color: var(--color-text-muted); }
.pj-zeile__meta { font-size: 0.82rem; color: var(--color-text-muted); }
.pj-zeile__datum { font-size: 0.79rem; font-variant-numeric: tabular-nums; color: var(--color-text-muted); white-space: nowrap; }
.pj-zeile__rubrik { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--color-primary); }
.pj-zeile__paragraf { font-size: 0.76rem; color: var(--color-primary); font-variant-numeric: tabular-nums; }
.pj-zeile:hover .pj-zeile__titel, .pj-zeile:focus-visible .pj-zeile__titel { color: var(--color-primary); }
.pj-zeile--kompakt .pj-zeile__titel, .pj-zeile--meldung .pj-zeile__titel { font-size: 1.16rem; line-height: 1.3; }
@media (min-width: 720px) {
  .pj-zeile--bild { grid-template-columns: 10.5rem minmax(0, 1fr); gap: 1.4rem; padding: 1.4rem 0; }
  .pj-zeile--kompakt { grid-template-columns: 6.75rem minmax(0, 1fr) 5.75rem; gap: 1.25rem; align-items: baseline; padding: 1.15rem 0; }
  .pj-zeile--meldung { grid-template-columns: 6.25rem 8rem minmax(0, 1fr); gap: 1.25rem; align-items: baseline; padding: 1.05rem 0; }
  .pj-zeile--kompakt .pj-zeile__paragraf { text-align: right; }
}
/* Unter 720px stehen Datum und Rubrik als eine Zeile über dem Titel, statt jeweils
   eine eigene Zeile zu belegen. */
@media (max-width: 719px) {
  .pj-zeile--kompakt, .pj-zeile--meldung { gap: 0.4rem; }
  .pj-zeile--meldung .pj-zeile__datum, .pj-zeile--meldung .pj-zeile__rubrik,
  .pj-zeile--kompakt .pj-zeile__datum { display: inline-block; margin-right: 0.6rem; }
  .pj-zeile--kompakt .pj-zeile__paragraf { margin-top: 0.2rem; }
}
.pj-zeile[hidden] { display: none; }

/* ── Zweispaltiger Seitenkopf (3a, 3b) ── */
.pj-hub-kopf--zwei { display: grid; gap: 1.75rem; }
/* Zwei Spalten nur, wenn die zweite auch etwas trägt: Die Chip-Leiste des
   Ratgeber-Hubs ist bis zum Start von projekt.js `hidden` (progressive
   enhancement, s. filter-chips.njk). Ohne diese Bedingung stünde die Überschrift
   ohne JS in einer 55-%-Spalte neben einer leeren Fläche. */
@media (min-width: 900px) {
  .pj-hub-kopf--zwei:has(.pj-hub-kopf__neben > :not([hidden])) {
    grid-template-columns: 1.1fr 0.9fr;
    gap: 3.5rem;
    align-items: end;
  }
  .pj-hub-kopf--zwei.pj-hub-kopf--karte:has(.pj-hub-kopf__neben > :not([hidden])) {
    grid-template-columns: 1.15fr 0.85fr;
    align-items: start;
  }
}
.pj-hub-kopf--zwei > * { min-width: 0; }
.pj-hub-kopf__neben { display: flex; flex-direction: column; gap: 0.9rem; }
/* Der Kopf der Kategorieseite schließt im Entwurf mit einer Trennlinie ab. */
.pj-hub-kopf--linie { border-bottom: 1px solid #e0eeea; padding-bottom: 40px; }
/* Im zweispaltigen Kopf sitzen die Chips rechts und brauchen keinen Abstand nach
   unten — die Sektion darunter bringt ihren eigenen mit. */
.pj-hub-kopf__neben .pj-chips { margin-bottom: 0; }

/* Inhaltsspalte der Kategorieseite: Einstiegskarte, Liste und FAQ untereinander. */
.pj-kategorie__inhalt { display: grid; gap: 2.75rem; align-content: start; }

/* „Das Wichtigste in drei Sätzen" als Karteninhalt (3b): untereinander, ohne eigene
   Rahmen — der Rahmen ist die Karte. Die Sektionsvariante mit drei nebeneinander
   liegenden Kästen bleibt für die Werkzeugseiten bestehen. */
.pj-kurzfassung--liste { grid-template-columns: 1fr; gap: 0.75rem; }
.pj-kurzfassung--liste .pj-kurzfassung__punkt {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  font-size: 0.92rem;
  line-height: 1.6;
  gap: 0.7rem;
}
.pj-kurzfassung--liste .pj-kurzfassung__zahl { font-size: 0.78rem; font-weight: 500; }

/* ── Einstiegskarte der Kategorieseite (3b) ── */
.pj-einstieg { display: grid; gap: 0; overflow: hidden; text-decoration: none; color: var(--color-text); }
.pj-einstieg__bild { display: block; width: 100%; height: 100%; min-height: 12.5rem; object-fit: cover; background: #eef5f2; }
.pj-einstieg__text { display: flex; flex-direction: column; gap: 0.6rem; padding: 1.6rem 1.75rem; }
.pj-einstieg__titel { font-family: var(--font-serif); font-size: 1.63rem; font-weight: 600; line-height: 1.22; letter-spacing: -0.014em; text-wrap: pretty; }
.pj-einstieg:hover .pj-einstieg__titel, .pj-einstieg:focus-visible .pj-einstieg__titel { color: var(--color-primary); }
@media (min-width: 760px) {
  .pj-einstieg { grid-template-columns: 18.75rem minmax(0, 1fr); }
}

/* ── Dunkle Ticker-Leiste der News (3c) ──
   Die helle Mint-Leiste bleibt der Startseite (1a); News trägt im Entwurf die dunkle.
   Kontraste gegen #14302b nachgerechnet: #dce9e5 = 11,3:1 · #8fd0bd = 8,0:1 — beide
   über 4,5:1. Das Kontrast-Gate prüft nur Token-Paare aus _tokens.css und sieht diese
   Literale nicht, deshalb steht die Rechnung hier. */
.pj-notice--dunkel { background: #14302b; border-bottom-color: #14302b; }
.pj-notice--dunkel .pj-notice__stand { color: #8fd0bd; }
.pj-notice--dunkel .pj-notice__text { color: #dce9e5; }
.pj-notice--dunkel .pj-notice__link { color: #8fd0bd; }

/* ── Pille auf getönter Fläche (5b): weiß statt mint, sonst verschwände sie ──
   `align-self` muss mit: .pj-pill setzt flex-start, der Artikelkopf zentriert alles. */
.pj-pill--weiss { background: var(--color-bg); }
.pj-artikel__kopf .pj-pill { align-self: center; }
.pj-artikel__kopf .pj-pill:hover, .pj-artikel__kopf .pj-pill:focus-visible { color: var(--color-text); }

/* ── Bildplatzhalter ──
   Eine Fläche, die nach Bildplatz aussieht, nicht nach Leere: #eef5f2 lag mit 1,02:1
   auf der Seitenfläche #f8fbf9 und war schlicht nicht zu sehen — der Artikelkopf
   endete optisch in einem 300px hohen Nichts. Der Ton hier ist der hellere der beiden
   Streifenfarben des Entwurfs (#e2efea/#eef7f4), als Vollton statt als Streifen:
   Streifen samt „Foto: …"-Beschriftung sind eine Notiz an den Designer und gehören
   nicht ausgeliefert. Sie verschwindet, sobald der Beitrag ein `bild` bekommt.
   Der Ton muss sich auch vom Kopfband des Artikels (#e6f2ee) absetzen — sonst laufen
   Kopf und Bildplatz zu einer einzigen 700px hohen Fläche zusammen. */
.pj-teaser__bild--leer, .pj-zeile__bild--leer, .pj-artikel__bild--leer,
.pj-einstieg__bild:not(img) { background: #dde8e4; border-color: #cddfd9; }
.pj-artikel__bild--leer { border-top: 1px solid #cddfd9; }

/* ── Gefüllter Rubrik-Badge des News-Aufmachers (3c) ── */
.pj-teaser__rubrik { display: flex; align-items: center; gap: 0.6rem; }

/* ═══════════════════════ CONTENT-BAUSTEINE ═══════════════════════
   Die Darstellungs-Bibliothek des Artikelkörpers. Markup: _config/bausteine.js,
   Katalog: docs/BAUSTEINE.md, Wächter: scripts/tests/bausteine.test.js.

   Gemeinsames Maß ist die Karte des Entwurfsartikels (design-entwurf/5b-artikel.html),
   die .pj-kurzgesagt und .pj-diagramm schon tragen: 14px Radius (nicht --radius-lg = 16px
   — der Entwurf zeichnet 14), Rahmen in --color-border, derselbe zweistufige Schatten,
   1.4rem/1.6rem Innenabstand, 1.6rem Außenabstand.

   Keine Verläufe hinter Text: drei Verläufe erzeugten am 2026-08-14 gemessen 25 von 25
   pa11y-Fehlern bei echten 4,85:1 (Begründung bei .pj-btn). Zierzeichen kommen aus
   ::before/::after, nie aus dem Markup. */

/* ── Altlast: in Templates benutzt, im CSS nie definiert ──
   Vier Klassen standen in Templates und nirgends in dieser Datei. Sie taten deshalb
   nichts — sichtbar wurde das nirgends, weil jede von ihnen neben einer greifenden
   Klasse stand. Gefunden bei der Baustein-Inventur 2026-08-19. */
.pj-section--aufmacher { padding-block-start: 24px; }
/* Der News-Kopf trägt seinen Abstand selbst (34px unten); ein zweiter darunter ergäbe
   die doppelte Lücke, die der Entwurf dort nicht hat. */
.pj-hub-kopf--news + .pj-section--aufmacher { padding-block-start: 0; }
/* Der Kategoriekopf endet mit einer Linie — der Hauptbereich darunter braucht Abstand
   zu ihr, sonst klebt die Einstiegskarte an der Kante (Entwurf: 44px). */
.pj-hub-kopf--karte + .pj-section { padding-block-start: 44px; }
.pj-footer__brand { display: flex; flex-direction: column; gap: 0.55rem; }
.pj-vgl-karte__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 0.9rem; }
.pj-wizard__fortschritt { display: flex; flex-direction: column; gap: 0.45rem; }
.pj-wizard__fortschritt[hidden] { display: none; }

/* ── Gruppe A: Prosa-Boxen ── */
.pj-box, .pj-mythos, .pj-norm, .pj-copy, .pj-kennzahl {
  margin: 1.6rem 0;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.03), 0 14px 30px -26px rgba(20, 48, 43, 0.25);
  padding: 1.4rem 1.6rem;
}
.pj-box__label {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary);
}
/* Markdown im Kasten erzeugt mehrere <p>. Diese Regeln geben ihnen ihren Abstand zurück.
   DIE SPEZIFITÄT IST HIER DER GANZE PUNKT, und der erste Anlauf hat sie verloren: Er
   setzte den Rand mit `.pj-box > p { margin: 0 }` (0,1,1) zurück und den Abstand mit
   `.pj-box > * + *` (0,1,0) wieder drauf. Die zweite Regel schlägt die erste nicht — und
   zwar für genau die Elemente, um die es ging: Absätze. Gemessen auf /bausteine/ am
   2026-08-20: `margin-top` war an JEDEM Absatz in `paragraf`, `urteil` und den
   Prosa-Boxen 0px, das Normzitat klebte an seiner Einordnung.

   Die Auflösung teilt die Aufgaben statt sie gegeneinander zu stellen. Zu bekämpfen ist
   nur `.prose p/ul/ol { margin-block-end: … }` aus _base.css (0,1,1) — dafür braucht es
   dieselbe Spezifität, und _projekt.css lädt später. Den Abstand NACH OBEN setzt niemand
   sonst, dort genügt `* + *` (0,1,0). Zwei Regeln, die verschiedene Kanten anfassen,
   können sich nicht mehr schlagen. */
.pj-box > p, .pj-mythos > p, .pj-norm > p, .pj-merksatz > p, .pj-copy__text > p, .pj-kurzgesagt > p,
.pj-box > ul, .pj-mythos > ul, .pj-norm > ul, .pj-merksatz > ul, .pj-copy__text > ul, .pj-kurzgesagt > ul,
.pj-box > ol, .pj-mythos > ol, .pj-norm > ol, .pj-merksatz > ol, .pj-copy__text > ol, .pj-kurzgesagt > ol {
  margin-block-end: 0;
}
.pj-box > * + *, .pj-mythos > * + *, .pj-norm > * + *,
.pj-merksatz > * + *, .pj-copy__text > * + * { margin-block-start: 0.7rem; }
.pj-kurzgesagt > * + * { margin-block-start: 0.6rem; }

/* Mint wie .pj-hinweisbox, aber ohne Knopfzeile und ohne Schatten: Ein Hinweis im
   Fließtext ist eine Randnotiz, keine gehobene Karte. */
.pj-box--hinweis { background: #e6f2ee; border-color: #cfe4dd; box-shadow: none; }
/* Warnfarben aus .pj-artikel__entwurf — dieselbe Kombination, dieselbe Messung. */
.pj-box--achtung {
  background: #fdf8ef;
  border-color: #f0e2c4;
  border-left: 3px solid var(--color-rating);
  box-shadow: none;
}
.pj-box--achtung .pj-box__label { color: #6b4a12; }
.pj-box--gut { background: #e6f2ee; border-color: #cfe4dd; border-left: 3px solid var(--color-primary); box-shadow: none; }
/* Gestrichelt, weil hier bewusst NICHTS behauptet wird: Alle fünf Langartikel benennen
   Stellen, an denen die Recherche nichts hergab. Eine geschlossene Karte sähe aus wie
   eine Aussage. */
.pj-box--offen { background: var(--color-bg-alt); border-style: dashed; border-color: var(--color-border-control); box-shadow: none; }
.pj-box--offen .pj-box__label { color: var(--color-text-muted); }

.pj-merksatz {
  margin: 1.6rem 0;
  border-left: 3px solid var(--color-primary);
  padding: 0.2rem 0 0.2rem 1.2rem;
  font-size: 1.08rem;
  line-height: 1.6;
  font-weight: 600;
}

/* Mythos/Fakt. Die Behauptung wird BENANNT statt durchgestrichen: Durchstreichen
   verschlechtert die Lesbarkeit und trägt die Bedeutung nur visuell. */
.pj-mythos__falsch {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.55rem;
  margin-bottom: 0.9rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--color-border);
}
.pj-mythos__marke {
  flex-shrink: 0;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-error);
}
.pj-mythos__satz { min-width: 0; color: var(--color-text-muted); }
.pj-mythos__label { margin-bottom: 0.4rem; }

/* Normzitat und Urteil. Der Serif-Anschnitt der Fundstelle ist der Griff, an dem das
   Auge eine Rechtsstelle im Fließtext findet — 20-mal pro Langartikel steht ein §. */
.pj-norm { border-left: 3px solid var(--color-primary); }
.pj-norm__marke { margin: 0; font-family: var(--font-serif); font-size: 1.02rem; font-weight: 600; color: var(--color-primary); }
.pj-norm__meta { font-size: 0.84rem; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.pj-norm__marke + .pj-norm__meta { margin-top: 0.1rem; }
.pj-norm--urteil { border-left-color: var(--color-text-muted); }
.pj-norm--urteil .pj-norm__marke { color: var(--color-text); }
.pj-norm__quelle { font-size: 0.84rem; }

/* Textbaustein zum Übernehmen. Der Knopf ist bis zum JS-Start `hidden` — und braucht
   deshalb die [hidden]-Regel, weil .pj-btn ein `display` setzt, das `hidden` sonst
   schlägt (dieselbe Falle wie bei .pj-chips und .pj-abschluss__aktionen). */
.pj-copy__text {
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  font-family: var(--font-mono);
  font-size: 0.9rem;
  line-height: 1.65;
}
.pj-copy > * + * { margin-top: 0.9rem; }
.pj-copy__leiste { display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem; }
.pj-copy__leiste button[hidden] { display: none; }
.pj-copy__stand { font-size: 0.84rem; font-weight: 600; color: var(--color-primary); }

/* ── Gruppe B: Struktur & Ablauf ── */

/* Nummerierter Ablauf mit Verbindungslinie — sie macht aus vier Kacheln eine Folge.
   Die Ziffer ist im Markup aria-hidden, weil <ol> die Reihenfolge schon trägt. */
.pj-schritte { list-style: none; margin: 1.6rem 0; padding: 0; }
.pj-schritte__punkt {
  position: relative;
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: 0.9rem;
  margin: 0;
  padding-bottom: 1.05rem;
}
.pj-schritte__punkt:last-child { padding-bottom: 0; }
/* `bottom: 0` und nicht 0.2rem: Die Punkte stoßen ohne Außenabstand aneinander, die
   Unterkante ist also genau die Oberkante der nächsten Scheibe. Mit 0.2rem hielt die Linie
   davor an und wurde bei einzeiligen Schritten auf wenige Pixel gestaucht — im Bild sah es
   aus, als gäbe es keinen Verbinder. Dieselbe Zierlinie wie bei .pj-zeitleiste, dieselbe
   Farbe; Zierde braucht keinen Kontrast, muss aber durchlaufen. */
.pj-schritte__punkt:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 1rem;
  top: 2.1rem;
  bottom: 0;
  width: 2px;
  background: var(--color-border);
  transform: translateX(-1px);
}
.pj-schritte__zahl {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 0.86rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.pj-schritte__text { min-width: 0; align-self: start; padding-top: 0.28rem; line-height: 1.6; }

/* Echte Kontrollkästchen, implizit beschriftet (Input IM Label, deshalb ohne id).
   44px in der BASIS-Regel, nicht erst im Media-Query — axe prüft `target-size`
   unabhängig von der Bildschirmbreite (scripts/tests/touch-ziele.test.js). */
.pj-checkliste-block { margin: 1.6rem 0; }
.pj-checkliste { list-style: none; margin: 0; padding: 0; }
.pj-checkliste li { margin: 0; }
.pj-checkliste__punkt {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  min-block-size: 44px;
  padding-block: 0.35rem;
  line-height: 1.55;
  cursor: pointer;
}
.pj-checkliste__punkt input {
  flex-shrink: 0;
  inline-size: 1.15rem;
  block-size: 1.15rem;
  accent-color: var(--color-primary);
}
/* Das ✕ kommt aus dem CSS, nie aus dem Markup: axe meldet ein <span aria-hidden> mit
   Zierzeichen als needsFurtherReview, pa11y zählt das als Fehler. Die Bedeutung steht in
   der Beschriftung über der Liste, nicht im Zeichen — es darf ausfallen. */
.pj-checkliste--negativ li { display: flex; align-items: baseline; gap: 0.8rem; padding-block: 0.3rem; line-height: 1.55; }
.pj-checkliste--negativ li::before { content: "✕"; flex-shrink: 0; font-weight: 700; color: var(--color-error); }

/* Prüfpfad — die lesbare, druckbare, indexierbare Schwester des interaktiven Wegweisers.
   Häufigster Bedarf im Bestand: mindestens zwölf Beiträge formulieren eine
   Entscheidungsfolge als Prosa. */
.pj-pfad { list-style: none; margin: 1.6rem 0; padding: 0; }
.pj-pfad__stufe {
  position: relative;
  margin: 0 0 0.8rem;
  padding: 1.1rem 1.3rem 1.1rem 3.5rem;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
}
.pj-pfad__stufe:last-child { margin-bottom: 0; }
/* Ein echtes Element, kein ::before mit Inhalt. axe kann den Hintergrund von Text nicht
   mehr bestimmen, wenn im selben Element ein positioniertes Pseudo-Element MIT Inhalt
   sitzt („could not be determined due to a pseudo element") — es meldet `incomplete`,
   pa11y zählt das als Fehler, und die Seite ist rot bei gemessenen 6,4:1. Ein
   Pseudo-Element mit `content: ""` (Zeitleisten-Punkt, Schritte-Verbindungslinie) löst
   es nicht aus. */
.pj-pfad__zahl {
  position: absolute;
  left: 1.1rem;
  top: 1.05rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 999px;
  background: #e6f2ee;
  color: var(--color-primary);
  font-size: 0.8rem;
  font-weight: 800;
}
.pj-pfad__frage { margin: 0 0 0.7rem; font-weight: 700; line-height: 1.5; }
.pj-pfad__zweig { display: flex; gap: 0.7rem; margin: 0; padding-block: 0.3rem; font-size: 0.95rem; line-height: 1.55; color: var(--color-text-muted); }
/* FESTE Breite, nicht `min-width`: Mit einer Mindestbreite wächst die Marke mit ihrem
   Text, und die Antwortspalte begann bei jedem Zweig woanders — auf /bausteine/ standen
   die drei Antworten einer Stufe („Buchst. a", „Buchst. b", „Gegenprobe") bei 512, 509
   und 530 px. Eine Entscheidungsfolge liest man spaltenweise; eine ausgefranste Kante
   nimmt ihr genau das. 5.4rem trägt die längste Marke, die dieser Baustein kennt. */
.pj-pfad__marke {
  flex-shrink: 0;
  inline-size: 5.4rem;
  padding-top: 0.18rem;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  hyphens: manual;
}
.pj-pfad__zweig--ja .pj-pfad__marke { color: var(--color-primary); }
.pj-pfad__zweig--nein .pj-pfad__marke { color: var(--color-error); }
.pj-pfad__zweig--weiter .pj-pfad__marke { color: var(--color-text-muted); }

/* ── Gruppe C: Zahlen, Vergleich, Statistik ── */

/* Kennzahl-Kachel. Der Quellenfuß ist nicht optional: Eine Zahl ohne Fundstelle und ohne
   Stand ist auf einer Rechtsseite keine Angabe, sondern eine Behauptung — und der
   Bußgeldrahmen stand im Bestand an zehn Stellen als reine Prosa. */
.pj-kennzahl { min-width: 0; }
.pj-kennzahl__wert {
  margin: 0;
  font-size: 1.9rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}
.pj-kennzahl__label { margin: 0.35rem 0 0; font-weight: 600; line-height: 1.5; }
.pj-kennzahl__hinweis { margin: 0.55rem 0 0; font-size: 0.9rem; line-height: 1.55; color: var(--color-text-muted); }
.pj-kennzahl__quelle {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem;
  margin: 0.8rem 0 0;
  padding-top: 0.7rem;
  border-top: 1px solid var(--color-border);
  font-size: 0.8rem;
  color: var(--color-text-muted);
}
.pj-kennzahl__gruppe { margin: 1.6rem 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 1rem; }
.pj-kennzahl__gruppe .pj-kennzahl { margin: 0; padding: 1.1rem 1.2rem; }
.pj-kennzahl__gruppe .pj-kennzahl__wert { font-size: 1.5rem; }
/* Die letzte Kachel füllt die Reihe, wenn sie allein darin steht. In der Artikelspalte
   passen genau zwei Kacheln nebeneinander (572 px verfügbar, 12rem Mindestbreite plus
   1rem Abstand lassen keine dritte zu) — bei drei Kennzahlen blieb rechts unten eine
   halbe leere Zelle stehen, die wie ein Fehler aussah. `:nth-child(odd)` trifft die
   letzte Kachel nur dann, wenn ihre Anzahl ungerade ist, also genau im Waisenfall.
   Bewusst auf .prose beschränkt: Nur dort ist die Spaltenzahl bekannt. */
.prose .pj-kennzahl__gruppe .pj-kennzahl:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* ── Tabellen ──
   Es gab im ganzen Projekt keine einzige `table`-Regel: sieben Markdown-Tabellen im
   Bestand rendeten im Browser-Default, bis zu vier Spalten, und schoben die Artikelspalte
   auf 375 px quer. Der Rahmen kommt aus dem Filter `mitTabellenrahmen` (jede Tabelle aus
   Markdown) oder aus dem Baustein `matrix`.

   `min-inline-size` ist der Punkt, an dem der Rahmen seinen Zweck erfüllt: Ohne ihn
   quetscht der Browser vier Spalten in 327 px und bricht jede Zelle auf ein Wort pro
   Zeile — es überläuft nichts, es ist nur unlesbar. Mit ihm scrollt der Bereich. */
.pj-tabelle { overflow-x: auto; border: 1px solid var(--color-border); border-radius: 14px; }
.pj-tabelle:focus-visible { outline: 3px solid var(--color-primary); outline-offset: 2px; }
/* `hyphens: manual` gegen das globale `hyphens: auto` aus _base.css. In einer Tabelle ist
   die automatische Trennung nicht nur hässlich, sie verschiebt das LAYOUT: Die
   Mindestbreite einer Spalte ist die Breite ihres längsten unteilbaren Stücks — mit
   Auto-Trennung ist das eine Silbe. Der Browser darf die Spalte dann beliebig schmal
   ziehen, und genau das tat er (gemessen auf /bausteine/, 375 px): „Wohnhaus,
   Altenteilerhaus" stand als „Wohn-/haus,/Altentei-/lerhaus" in einer Spalte von rund
   110 px, während die Nachbarspalte den Platz nahm. Ohne Auto-Trennung ist die
   Mindestbreite wieder das längste WORT, und die Spalten teilen sich vernünftig auf. */
.prose table, .pj-matrix {
  inline-size: 100%;
  min-inline-size: 28rem;
  margin: 0;
  border-collapse: collapse;
  font-size: 0.92rem;
  line-height: 1.5;
  hyphens: manual;
}
/* KEIN `text-transform: uppercase`: Versalien zerstören Einheiten und Formelzeichen.
   „Endenergie in kWh/(m²·a)" wurde damit zu „ENDENERGIE IN KWH/(M²·A)" — kWh ist die
   Kilowattstunde, KWH ist nichts, und auf einer Seite, die Kennwerte erklärt, ist das
   kein Schönheitsfehler. Der Kopf hebt sich weiter über Fläche, Linie, Fettung, Größe
   und Farbe ab; die Auszeichnung war das einzige Mittel, das den Text verändert hat. */
.prose thead th, .pj-matrix thead th {
  padding: 0.8rem 1rem;
  text-align: left;
  vertical-align: bottom;
  white-space: nowrap;
  background: #f5f9f7;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--color-text-muted);
}
.prose tbody th, .prose tbody td, .pj-matrix tbody th, .pj-matrix tbody td {
  padding: 0.75rem 1rem;
  text-align: left;
  vertical-align: top;
  border-top: 1px solid #eef4f2;
  font-variant-numeric: tabular-nums;
}
.prose tbody th, .pj-matrix tbody th { font-weight: 700; }
.prose tbody tr:first-child > *, .pj-matrix tbody tr:first-child > * { border-top: 0; }
.prose tbody tr:nth-child(even), .pj-matrix tbody tr:nth-child(even) { background: #fbfdfc; }
.pj-tabelle-figur { margin: 1.6rem 0; }
.pj-tabelle__titel { margin-bottom: 0.6rem; font-size: 0.95rem; font-weight: 700; }
.pj-tabelle__quelle { margin-top: 0.6rem; font-size: 0.82rem; color: var(--color-text-muted); }

/* Schwellenwert mit seinen Lesarten. „Nicht mehr als 50" und „weniger als 50" sind zwei
   verschiedene Rechtslagen — in einer Zeile Prosa ist der Unterschied unsichtbar. */
.pj-schwelle {
  margin: 1.6rem 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.4rem;
  align-items: start;
  background: #e6f2ee;
  border-radius: 14px;
  padding: 1.4rem 1.6rem;
}
.pj-schwelle__zahl {
  margin: 0;
  white-space: nowrap;
  font-size: 2.1rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary);
}
.pj-schwelle__faelle { min-width: 0; }
.pj-schwelle__fall { display: flex; flex-direction: column; gap: 0.15rem; margin: 0; font-size: 0.95rem; line-height: 1.55; }
.pj-schwelle__fall + .pj-schwelle__fall { margin-top: 0.8rem; padding-top: 0.8rem; border-top: 1px solid #cfe4dd; }
.pj-schwelle__marke { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-primary); }
.pj-schwelle__hinweis { margin: 0.9rem 0 0; font-size: 0.88rem; line-height: 1.55; color: var(--color-text-muted); }

/* Skala im Fließtext. Zwei Marker nebeneinander würden ihre Fahnen überdecken — genau der
   Fall, für den effizienzklassen-vergleich sie braucht („ein Haus knapp unter und eines
   knapp über einer Grenze"). Der zweite hängt deshalb tiefer. */
.pj-skala--prosa { margin: 1.8rem 0; }
.pj-skala--zwei { padding-top: 80px; }
.pj-skala--zwei .pj-skala__marker--tief { top: 38px; }

/* Vorher/Nachher als eigenständiger Baustein — im Werkzeugkasten steht dieselbe Zeile
   ohne Rahmen, weil sie dort in einer Ergebnisfläche liegt. */
.pj-vorhernachher-block {
  margin: 1.6rem 0;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 1.4rem 1.6rem;
}
.pj-vorhernachher-block .pj-tool__hinweis { margin-top: 0.9rem; }
/* Das Feld ist für kurze Werte gebaut („F", „36 Monate"). Ein langes Wort bei 2,1rem
   sprengte auf dem CI-Runner seine Spalte — mit einer breiteren Ersatzschrift lief es
   über den Nachbarn, und axe konnte den Hintergrund des Textes nicht mehr bestimmen
   (incomplete → pa11y-Fehler). Lokal fiel es nicht auf, weil dort die eigene Schrift
   geladen war und der Wert gerade noch passte. Jetzt schrumpft und bricht er statt
   überzulaufen — unabhängig davon, welche Schrift greift. */
.pj-vorhernachher-block .pj-ergebnis__wert {
  font-size: clamp(1.3rem, 4.6vw, 2.1rem);
  line-height: 1.15;
  overflow-wrap: anywhere;
  hyphens: auto;
}
.pj-vorhernachher-block .pj-vorher-nachher > div { min-width: 0; flex: 1; }

/* Vorhandene Bausteine im Artikelmaß: Der Vergleich ist für die 1280px-Bühne gebaut, in
   einer Textspalte dieser Breite sind 1.9rem/2rem Innenabstand zu viel. */
.prose > .pj-vergleich, .prose > .pj-fakten, .prose > .pj-zeitleiste,
.prose > .pj-faq-block, .prose > .pj-diagramm, .prose > .pj-kurzgesagt { margin: 1.6rem 0; }
.prose .pj-vergleich { gap: 1rem; }
.prose .pj-vgl-karte { padding: 1.3rem 1.4rem; gap: 0.8rem; }
.prose .pj-vgl-karte .pj-h3 { font-size: 1.13rem; }
.prose .pj-zeitleiste li { margin: 0; }
.prose .pj-schritte li, .prose .pj-pfad li, .prose .pj-checkliste li { margin: 0; }

/* Codeblöcke brechen um, statt zu scrollen. `.prose pre` (Engine, _base.css) setzt
   `overflow-x: auto`; ein scrollbarer Bereich braucht Tastaturzugang, sonst meldet axe
   `scrollable-region-focusable`. Aufgefallen ist das erst mit der Musterseite — sie ist
   die einzige Seite dieser Site mit breiten Codeblöcken, und sie riss damit 29 Befunde
   auf einen Schlag. Umbrechen statt tabindex: Auf einer Ratgeber-Site ist ein
   umgebrochenes Syntaxbeispiel besser lesbar als ein horizontal scrollender Kasten, und
   ohne Überlauf gibt es die Regel gar nicht erst zu erfüllen. */
.prose pre { white-space: pre-wrap; overflow-wrap: anywhere; overflow-x: visible; }
/* Der Codeblock war UNSICHTBAR. _base.css gibt ihm `background: var(--color-bg-alt)` —
   und dieses Projekt hat genau damit seinen Seitengrund eingefärbt: Beide sind #f8fbf9,
   im Browser nachgemessen (`getComputedStyle(pre).backgroundColor` === die des <body>).
   Übrig blieb Monospace-Text, der ohne Fläche im Nichts hing; auf /bausteine/ betrifft
   das jeden zweiten Block, weil dort unter jedem Baustein seine Syntax steht.
   Weiß plus Rahmen ist dieselbe Kartenform wie bei allen anderen Bausteinen. */
.prose pre {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
}

/* Das Inhaltsverzeichnis des Artikels. Dieselbe Sprungliste wie im Rechtstext, nur ohne
   Sticky-Verhalten: Sie steht im Textfluss, nicht in einer Spalte daneben. */
.pj-artikel__inhalt { margin: 0 0 2rem; }
.pj-artikel__inhalt .pj-sprungliste__titel { margin-top: 0; }

@media (max-width: 560px) {
  .pj-box, .pj-mythos, .pj-norm, .pj-copy, .pj-kennzahl, .pj-vorhernachher-block { padding: 1.1rem 1.2rem; }
  .pj-schwelle { grid-template-columns: 1fr; gap: 0.8rem; padding: 1.1rem 1.2rem; }
  .pj-pfad__stufe { padding: 1rem 1.1rem 1rem 3.2rem; }
  .pj-kennzahl__wert { font-size: 1.7rem; }
}

/* ═══════════════════════ HANDLUNGSAUFRUF IM ARTIKEL ═══════════════════════
   Markup: projekt/cta-block.njk · Platzierung: projekt/post.njk + Filter `mitCta`.

   UMBAU 2026-08-28. Bis dahin war das hier ein Vollton-Block in der Primärfarbe, drei
   Stück je Beitrag, mit fester Marke „Anzeige". Beides ist gefallen:

   • ZWEI statt drei Flächen (Mitte, Ende). Die obere ist entfallen — dort hat der Leser
     noch nichts bekommen, wofür er etwas geben würde, und der Entwurf zeigt dort nichts.
   • KARTE statt Vollton. Die Fläche ist kein eingekaufter Fremdlink, sondern ein Verweis
     auf das eigene Angebot (partner.eigen). Der Vollton-Riegel zerschnitt den Lesefluss
     und behauptete optisch eine Werbebeziehung, die es nicht gibt. Maße und Schatten
     sind die der Artikelkarten aus design-entwurf/5b-artikel.html — dieselbe Sprache
     wie „Kurz gesagt", Diagramm und eingebettetes Werkzeug.

   DIE KENNZEICHNUNG IST NICHT ABGESCHAFFT, sondern an den Schalter gebunden: Steht
   partner.eigen auf false, ist das Ziel bezahlte Vermittlung — dann rendert
   cta-block.njk die Marke „Anzeige" UND setzt .pj-cta--anzeige, und erst diese Klasse
   trägt den auffälligen Rahmen. Werbung muss auf den ersten Blick erkennbar sein
   (§ 5a Abs. 4 UWG); eine weiße Karte im Artikelstil leistet das allein nicht.

   Zwei Dichten: `voll` steht mitten im Text und bleibt neutral-weiß, `stark` steht am
   Schluss auf der getönten Fläche des Entwurfs (#e6f2ee) — die Steigerung kommt aus
   dem Tonwert, nicht aus einem Farbschlag. */
.pj-cta {
  margin: 2rem 0;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.6rem 1.6rem;
  border-radius: 14px;
  padding: 24px 26px;
  hyphens: manual;
}
.pj-cta__anzeige {
  margin: 0;
  grid-column: 1 / -1;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.pj-cta__text { min-width: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.pj-cta__titel { margin: 0; font-family: var(--font-serif); font-size: 1.24rem; font-weight: 600; line-height: 1.3; }
.pj-cta__zeile { margin: 0; font-size: 0.95rem; line-height: 1.55; color: var(--color-text-muted); }
.pj-cta__aktion { display: flex; }
.pj-cta .pj-btn { min-block-size: 44px; display: inline-flex; align-items: center; white-space: nowrap; }

/* Mitte: die Kartenspezifikation des Entwurfs — 5b führt eine eigene, hellere
   Rahmenfarbe als die Übersichtsseiten (#dfe6e3 statt #d9e7e2). */
.pj-cta--voll {
  background: var(--color-bg);
  border: 1px solid #dfe6e3;
  box-shadow: 0 1px 2px rgba(20, 48, 43, 0.03), 0 14px 30px -26px rgba(20, 48, 43, 0.25);
}

/* Schluss: getönt wie die Hinweiskästen des Entwurfs. Kein Schatten — eine Tonfläche,
   die auch noch schwebt, wirkt wie ein Dialogfenster mitten im Text. */
.pj-cta--stark {
  background: #e6f2ee;
  border: 1px solid #cfe4dd;
}

/* NUR bei bezahlter Vermittlung (partner.eigen === false). Der Rahmen in der
   Primärfarbe ist die optische Trennung, die das Trennungsgebot verlangt. */
.pj-cta--anzeige { border: 1.5px solid var(--color-primary); }

/* Unter der Spaltenbreite des Artikelkörpers hat ein zweispaltiges Raster keinen Platz:
   Der Knopf stünde als schmale Buchstabensäule neben dem Text. Dieselbe Falle wie bei
   .pj-tool__spalten — ein Media Query misst das FENSTER, nicht die Spalte, in der der
   Block steht. Der Artikelkörper ist in der Breite begrenzt, deshalb greift die Fensterbreite
   hier ausnahmsweise doch: Schmaler als 640px ist auch die Spalte immer zu schmal. */
@media (max-width: 640px) {
  .pj-cta { grid-template-columns: 1fr; align-items: start; padding: 20px 18px; }
}


/* ── Print: Projekt-Chrome ausblenden (die Engine-Regeln in _print.css kennen
   nur .site-header/.site-footer/.cta-bar) ── */
@media print {
  .pj-header, .pj-footer, .pj-notice, .pj-wizard, .pj-schaetzer, .pj-tools,
  .pj-hinweisbox, .pj-artikel-tool,
  .pj-chips, .pj-werkzeugleiste, .pj-rechtstext__spalte, .pj-leiste,
  /* Ein Handlungsaufruf auf Papier ist ein Farbblock ohne Ziel — der Link ist dort tot. */
  .pj-cta { display: none !important; }
  /* Bausteine: Der Kopieren-Knopf ist auf Papier sinnlos, die Kontrollkästchen der
     Checkliste sind dort der ganze Zweck — sie bleiben. */
  .pj-copy__leiste { display: none !important; }
  /* Ein Scroll-Rahmen auf Papier schneidet ab, statt zu scrollen: Rahmen auf, Mindestbreite
     weg, damit die Tabelle in die Seitenbreite umbricht. */
  .pj-tabelle { overflow: visible; }
  .prose table, .pj-matrix { min-inline-size: 0; }
  /* Ein Kasten, den der Seitenumbruch mittendurch schneidet, verliert seine Aussage. */
  .pj-box, .pj-mythos, .pj-norm, .pj-copy, .pj-kennzahl, .pj-pfad__stufe,
  .pj-schwelle, .pj-vorhernachher-block, .pj-kurzgesagt, .pj-diagramm { box-shadow: none; break-inside: avoid; }
  .pj-schritte__punkt, .pj-checkliste li, .pj-zeitleiste li, .pj-vgl-karte { break-inside: avoid; }
  /* Ohne Seitenleiste soll der Inhalt die ganze Breite nutzen — wie beim Rechtstext. */
  .pj-spalten { display: block; }
  /* Ohne Seitenleiste soll der Rechtstext die ganze Breite nutzen — sonst bliebe
     rechts eine leere Spalte stehen. */
  .pj-rechtstext__raster { display: block; }
}

/* ═══════════ PRINT ═══════════
   Impressum und Leistungen/Angebote werden ausgedruckt: Interaktives raus,
   externe Link-Ziele lesbar machen, Druckfarbe sparen. */

@media print {
  .site-header,
  .cta-bar,
  .lead-form,
  .skip-link,
  .site-footer {
    display: none !important;
  }

  body {
    color: #000;
    background: #fff;
    hyphens: manual;
  }

  /* Externe Link-Ziele ausschreiben — interne Pfade wären nur Rauschen */
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.875em;
    word-break: break-all;
  }

  h1, h2, h3 {
    break-after: avoid;
  }

  figure, blockquote, .card {
    break-inside: avoid;
  }
}

