/* ==========================================================================
   nils.plagemann — Seitenstile
   Aufbau:  1 Basis · 2 Layout/Shell · 3 Komponenten · 4 Seitenbausteine
            5 Responsiv

   Abschnitt 1 folgt tokens/base.css des Design-Systems, Abschnitt 3 ist
   wörtlich aus _ds_bundle.js übernommen (Button, Badge, Tag, PostCard,
   CodeBlock, Card, Input, Select), damit Seite und System nicht
   auseinanderlaufen.
   ========================================================================== */

/* ==========================================================================
   1 · Basis
   ========================================================================== */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* Mono ist der Standard. Plex Sans nur für laufende Absätze. */
body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-body);
  font-family: var(--font-core);
  font-size: var(--t-md);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out);
}

/* Überschriften: Mono, fett, −0,04 em. Satz-Stil, nie Title Case. */
h1, h2, h3, h4 {
  font-family: var(--font-core);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-heading);
  color: var(--text-heading);
  margin: 0;
  text-wrap: balance;
  /* Deutsche Komposita sind länger als ein 320-px-Telefon breit ist:
     „Datenschutzerklärung" brauchte 304 px in einem 280-px-Kasten und schob
     die Seite seitlich heraus. Getrennt wird nach den Regeln aus lang="de",
     und wo selbst das nicht reicht, bricht das Wort hart um. */
  hyphens: auto;
  -webkit-hyphens: auto;
  overflow-wrap: break-word;
}
h1 { font-size: var(--t-3xl); line-height: 1.08; }
h2 { font-size: var(--t-2xl); line-height: 1.18; max-width: var(--measure-h2); }
h3 { font-size: var(--t-xl); line-height: 1.28; max-width: var(--measure-h3); }
h4 { font-size: var(--t-lg); line-height: var(--lh-h3); max-width: var(--measure-h3); }

/* Laufende Absätze: Plex Sans, 65–75 Zeichen, Flattersatz, Silbentrennung. */
p {
  margin: 0;
  font-family: var(--font-prose);
  font-size: var(--t-md);
  line-height: var(--lh-body);
  max-width: var(--measure-prose);
  text-align: left;
  text-wrap: pretty;
  hyphens: auto;
  -webkit-hyphens: auto;
}
p + p { margin-top: var(--space-4); }

/* Links: im Fließtext immer unterstrichen, in Navigation und Schaltflächen nie. */
a {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-1) var(--ease-out);
}
a:hover { color: var(--link-hover); }
a:focus-visible { outline: none; box-shadow: var(--ring-focus); border-radius: 1px; }
nav a, .u-nav a, a.np-logo, a.np-mark, a.np-btn, a.u-plain { text-decoration: none; }
nav a:hover, .u-nav a:hover, a.u-plain:hover { text-decoration: none; }
/* Ein Unterstreichen des Vorfahren lässt sich im Kind nicht zurücknehmen —
   deshalb hier verhindern, wo ein Link nur einen Button umschließt. */
a:has(> .np-btn) { text-decoration: none; }

:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

::selection { background: var(--accent-primary-dim); color: var(--text-heading); }

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

/* Muss nach allen display-Regeln greifen: .np-post und .filters setzen
   display selbst und würden das UA-[hidden] sonst überstimmen. */
[hidden] { display: none !important; }

/* Auszeichnungen: Fett nur bei der ersten Nennung, Kursiv nur in Plex Sans. */
strong, b { font-family: var(--font-prose); font-weight: var(--weight-semibold); }
em, i, cite { font-family: var(--font-prose); font-style: italic; }
h1 em, h2 em, h3 em, h4 em, code em { font-style: normal; }

/* Deutsche Anführungszeichen außen „ ", innen ‚ '. */
q { quotes: '\201E' '\201C' '\201A' '\2018'; }
blockquote { margin: 0; font-family: var(--font-prose); quotes: '\201E' '\201C' '\201A' '\2018'; }

/* Aufzählungen: blauer Punkt, Einzug 0,63 cm, hängend. */
ul {
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-prose);
  font-size: var(--t-md);
  line-height: var(--lh-body);
  max-width: var(--measure-prose);
}
ul > li { position: relative; padding-left: 0.63cm; }
ul > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .62em;
  width: 5px;
  height: 5px;
  border-radius: var(--radius-full);
  background: var(--text-accent);
}
ul > li + li { margin-top: var(--space-2); }
ol {
  margin: 0;
  padding-left: 0.63cm;
  font-family: var(--font-prose);
  font-size: var(--t-md);
  line-height: var(--lh-body);
  max-width: var(--measure-prose);
}
ol > li::marker { font-family: var(--font-core); color: var(--text-accent); }

/* Code: Inline auf getönter Fläche, 2 px Radius. */
code, pre, kbd, samp { font-family: var(--font-core); }
code {
  font-size: .9em;
  background: var(--surface-tint);
  border-radius: var(--radius-xs);
  padding: 1px 5px;
  color: var(--text-accent);
}
pre {
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  overflow-x: auto;
  font-size: var(--text-code);
  line-height: var(--lh-code);
  max-width: var(--measure-code);
}
pre code { background: none; border: none; padding: 0; color: var(--syn-plain); font-size: inherit; }

/* Tabellen: Kopf in Akzentblau, Zebra, Ziffern gleich breit. */
table { border-collapse: collapse; font-family: var(--font-core); font-size: var(--t-sm); font-variant-numeric: tabular-nums; }
th {
  text-align: left;
  font-weight: var(--weight-bold);
  color: var(--text-accent);
  border-bottom: 1px solid var(--border-default);
  padding: var(--space-2) var(--space-3);
}
td { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border-subtle); color: var(--text-body); }
tbody tr:nth-child(even) td { background: var(--surface-tint); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 5px; border: 2px solid var(--surface-page); }
::-webkit-scrollbar-track { background: transparent; }

/* ---- Hilfsklassen ---- */
/* Versalien-Label: nur bis vier Wörter, 0,14 em Laufweite. Nie im Fließtext. */
.u-label {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  line-height: 1.4;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.u-eyebrow {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  line-height: 1.4;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-accent);
}
.u-caption {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  line-height: var(--lh-caption);
  max-width: var(--measure-caption);
  color: var(--text-muted);
}
.u-mono {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.u-prose {
  font-family: var(--font-prose);
  font-size: var(--t-md);
  line-height: var(--lh-body);
  max-width: var(--measure-prose);
  hyphens: auto;
  -webkit-hyphens: auto;
}
.u-nums { font-variant-numeric: tabular-nums; }
.u-nowrap { white-space: nowrap; }
.u-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Honigtopf im Kontaktformular. display:none statt .u-sr — sonst steht das
   Feld weiter im Layout und check_render.py misst es als echtes Bedienelement.
   Bots füllen es trotzdem, die lesen das HTML, nicht das CSS. */
.hp { display: none; }

/* Syntax-Utilities */
.tok-kw { color: var(--syn-keyword); }
.tok-ty { color: var(--syn-type); }
.tok-fn { color: var(--syn-method); }
.tok-str { color: var(--syn-string); }
.tok-num { color: var(--syn-number); }
.tok-com { color: var(--syn-comment); font-style: italic; }
.tok-pn { color: var(--syn-punct); }
.tok-at { color: var(--syn-attr); }
.tok-pr { color: var(--syn-prompt); user-select: none; }
.tok-ok { color: var(--syn-out-ok); }
.tok-err { color: var(--syn-out-err); }

/* ==========================================================================
   2 · Layout / Shell
   ========================================================================== */

/* Sprunglink */
.skip {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -140%);
  z-index: 100;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-accent);
  background: var(--surface-card);
  border: 1px solid var(--text-accent);
  border-radius: var(--radius-sm);
  padding: 9px 14px;
  text-decoration: none;
  transition: transform var(--dur-1) var(--ease-out);
}
.skip:focus { transform: translate(-50%, 10px); outline: 2px solid var(--text-accent); outline-offset: 2px; }

.page { min-height: 100vh; display: flex; flex-direction: column; }

/* ---- Seitenwechsel ----
   Mobil-Mock 19 „Seitenwechsel – Übergang": Ausblenden 120 ms, Seitenanfang,
   Einblenden 200 ms mit 10 px Versatz — mobil 8 px, „auf 402 px reichen 8 px".
   Der Mock führt das an drei Umschaltflächen vor; hier trägt es der Browser
   über dokumentübergreifende View Transitions. Die Seite bleibt damit eine
   gewöhnliche Mehrseiten-Site: kein Skript im Navigationsweg, kein Router.
   Browser ohne Unterstützung wechseln hart — sichtbar fehlt nur die Blende.
   Die Regeln des Mocks: kein Wischen, kein Schieben (Richtungsanimationen
   versprechen eine Hierarchie, die die Seite nicht hat), die Kopfleiste bleibt
   stehen, und Anker im Artikel scrollen weich ohne Blende — das tun sie von
   selbst, ein Anker wechselt das Dokument nicht. */
@view-transition { navigation: auto; }

/* „Kopfleiste und Safe-Area bleiben stehen." Sie bekommt einen eigenen Namen
   und fällt damit aus der Blende des Inhalts heraus. Ihr altes Abbild blendet
   trotzdem in 120 ms aus, sonst stünde die Markierung der aktiven Seite
   (aria-current) den ganzen Wechsel lang auf der alten Seite. */
.site-header { view-transition-name: kopf; }
::view-transition-group(kopf) { animation-duration: 0s; }

::view-transition-image-pair(root),
::view-transition-image-pair(kopf) { isolation: auto; }
::view-transition-old(root), ::view-transition-new(root),
::view-transition-old(kopf), ::view-transition-new(kopf) { mix-blend-mode: normal; }

@keyframes seitenwechsel-aus { to { opacity: 0; } }
@keyframes seitenwechsel-ein { from { opacity: 0; transform: translateY(10px); } }
/* Zurück und Neuladen blenden ohne Versatz ein: der Browser stellt die
   Scrollposition wieder her, ein Versatz würde eine Bewegung behaupten,
   die es nicht gibt. */
@keyframes seitenwechsel-ein-flach { from { opacity: 0; } }

::view-transition-old(root) { animation: seitenwechsel-aus var(--dur-1) var(--ease-out) both; }
::view-transition-new(root) { animation: seitenwechsel-ein var(--dur-2) var(--ease-out) var(--dur-1) both; }
:root[data-seitenwechsel="flach"]::view-transition-new(root) { animation-name: seitenwechsel-ein-flach; }
::view-transition-old(kopf) { animation: seitenwechsel-aus var(--dur-1) var(--ease-out) both; }
::view-transition-new(kopf) { animation: none; }

/* Ladebalken, 2 px unter der Leiste. Er zeichnet sich in 260 ms von links auf
   und ist weg, wenn der Wechsel nach 320 ms fertig ist — ein Balken, der
   stehen bliebe, wäre eine Linie im Layout und keine Rückmeldung. Er läuft
   nur beim Wechsel nach vorn: zurück wird wiederhergestellt, nicht geladen.
   Das Attribut dazu setzt das Kopfskript in basis.njk. Die Leiste ist
   `position: sticky` und damit sein Bezug; `bottom: -2px` legt ihn über die
   Haarlinie der Kopfzeile, solange er läuft. */
.ladebalken {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--text-accent);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  pointer-events: none;
}
:root[data-seitenwechsel="an"] .ladebalken { animation: ladebalken 320ms var(--ease-out) both; }
@keyframes ladebalken {
  from { transform: scaleX(0); opacity: 1; }
  81% { transform: scaleX(1); opacity: 1; }
  to { transform: scaleX(1); opacity: 0; }
}

/* Wortmarke — „Nils" Light, „Plagemann" Bold, kein Punkt dazwischen.
   Laufweite und Wortabstand sind Teil der Marke. */
.np-logo {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--logo-font);
  letter-spacing: var(--logo-tracking);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
}
.np-logo-given { font-weight: var(--logo-weight-given); }
.np-logo-family { font-weight: var(--logo-weight-family); margin-left: var(--logo-word-gap); }
a.np-logo { transition: color var(--dur-1) var(--ease-out); }
a.np-logo:hover .np-logo-family { color: var(--link-hover); }
/* Kopfzeile: 24 px, die kleinste zweifarbige Stufe. */
.np-logo--header { font-size: var(--logo-size-header); color: var(--logo-given); }
.np-logo--header .np-logo-family { color: var(--logo-family); }
/* Fußzeile: 15 px, darunter einfarbig — Blau trägt dort nicht. */
.np-logo--footer { font-size: var(--logo-size-footer); color: var(--logo-solid); }

/* Monogramm — wörtlich aus der DS-Komponente Logo (variant="avatar").
   Mock 21: „Ersatz für das Porträt, solange kein Foto vorliegt."
   Die Fläche bringt der Avatar selbst mit, deshalb gilt er hell wie dunkel. */
.np-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  font-family: var(--logo-font);
  letter-spacing: -0.04em;
  line-height: 1;
}
.np-mark--avatar { background: var(--logo-avatar-bg); border-radius: var(--radius-full); }
.np-mark-given { font-weight: var(--logo-weight-given); }
.np-mark-family { font-weight: var(--logo-weight-family); }
.np-mark--avatar .np-mark-given { color: var(--logo-avatar-given); }
.np-mark--avatar .np-mark-family { color: var(--logo-avatar-family); }

/* Kopfzeile */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  height: 64px;
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 0 var(--gut);
  border-bottom: 1px solid var(--line-2);
  background: var(--bg-1);
}

/* Monogramm statt Wortmarke — mobil steht neben Lupe und Menüknopf keine
   24-px-Wortmarke mehr. Die Fläche kommt aus denselben Marken-Tokens wie das
   Logo, die Glyphen folgen der Kopfzeilen-Regel: „N" in --logo-given,
   „P" unter 24 px im dunkleren --logo-family-sm. */
.np-mark--head {
  display: none;
  width: 28px;
  height: 28px;
  font-size: 15px;
  border-radius: var(--radius-md);
  background: var(--logo-mark-bg);
  border: 1px solid var(--logo-mark-border);
}
.np-mark--head .np-mark-given { color: var(--logo-given); }
.np-mark--head .np-mark-family { color: var(--logo-family-sm); }

.site-nav { display: flex; gap: 6px; margin-left: auto; align-items: center; }
.site-nav a {
  font-size: var(--t-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight);
  line-height: 1;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
}
.site-nav a:hover { background: var(--surface-hover); color: var(--text-body); }
.site-nav a[aria-current="page"] { color: var(--text-body); background: var(--line-1); }
.site-nav .cta { margin-left: 2px; padding: 0; background: none; }
.site-nav .cta:hover { background: none; }

/* Trennstrich zwischen Zielen und Werkzeugen (Suche, Farbmodus, Kontakt). */
.nav-sep { width: 1px; height: 22px; background: var(--line-2); margin: 0 4px; }

/* ---- Aufklapper in der Kopfzeile ----
   Geöffnet wird ohne Skript: Zeigen oder Tastaturfokus genügen, deshalb
   funktionieren die Untereinträge auch, wenn das Skript nicht lädt. site.js
   zieht nur aria-expanded nach, damit Hilfsmittel denselben Zustand lesen. */
.nv { position: relative; }
.nv-t { display: flex; align-items: center; gap: 7px; }
.nv-c { font-size: 10px; line-height: 1; color: var(--text-faint); }
.nv-p {
  position: absolute;
  top: calc(100% - 2px);
  left: 0;
  display: none;
  min-width: 262px;
  padding: 6px;
  background: var(--bg-2);
  border: 1px solid var(--line-3);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-3);
  z-index: 30;
}
.nv-p--right { left: auto; right: 0; }
.nv:hover > .nv-p, .nv:focus-within > .nv-p { display: block; }
.nv:hover > .nv-t, .nv:focus-within > .nv-t { background: var(--line-1); color: var(--text-body); }
.nv-p__label {
  padding: 6px 10px 9px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}
.site-nav .nv-p a, .nv-p__soon {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 3px 14px;
  line-height: 1;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  color: var(--text-body);
}
.site-nav .nv-p a:hover { background: var(--line-1); }
.nv-p__name {
  font-size: var(--t-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight);
}
/* Die Zahl steht rechts, der Pfad darunter — die Zeile nennt damit Ziel,
   Umfang und Adresse, ohne dass man sie öffnen muss. */
.nv-p__n {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.nv-p__path {
  grid-column: 1;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
  color: var(--text-muted);
}
/* „bald": die Seite gibt es noch nicht, also ist der Eintrag kein Link. */
.nv-p__soon .nv-p__name { color: var(--text-muted); }

/* ---- Suchfeld in der Kopfzeile ----
   Ohne Skript ein gewöhnliches GET-Formular auf suche.html; mit Skript holt
   „/" den Fokus hierher. Sobald etwas darin steht, weichen die Ziele links
   und das Feld nimmt sich den Platz. */
.nav-search {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  min-width: 196px;
  padding: 0 8px 0 11px;
  background: var(--bg-2);
  border: 1px solid var(--line-3);
  border-radius: var(--radius-sm);
  transition: min-width 200ms var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.nav-search:hover { border-color: var(--text-accent); }
.nav-search:focus-within { border-color: var(--text-accent); box-shadow: var(--ring-focus); }
.nav-search__sign {
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  font-weight: var(--weight-bold);
  color: var(--text-accent);
}
/* Der Kasten ist 34 px hoch wie im Mock, das Tippziel bleibt trotzdem die
   44 px, die --hit-min für Formularfelder verspricht: die negativen Ränder
   ziehen das höhere Feld auf die Kastenhöhe zurück, ohne es zu verkleinern. */
.nav-search__q {
  flex: 1;
  min-width: 0;
  height: var(--hit-min);
  margin: -6px 0;
  padding: 0;
  background: transparent;
  border: 0;
  outline: none;
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  letter-spacing: .02em;
  color: var(--text-body);
}
.nav-search__q::placeholder { color: var(--text-muted); }
.nav-search__q::-webkit-search-cancel-button,
.nav-search__q::-webkit-search-decoration { -webkit-appearance: none; display: none; }
.nav-search__key { font-size: var(--t-2xs); line-height: 1.5; color: var(--text-faint); flex: none; }
.site-nav:has(> .nav-search > .nav-search__q:not(:placeholder-shown)) .nv-hide { display: none; }
.site-nav:has(> .nav-search > .nav-search__q:not(:placeholder-shown)) > .nav-search { min-width: 430px; }
.nav-search:has(> .nav-search__q:not(:placeholder-shown)) > .nav-search__key { display: none; }

/* ---- Farbschema ----
   Nicht mehr die Ausnahme aus den alten Mocks: der aktuelle Desktop-Mock
   führt den Schalter als Aufklapper „Darstellung", der Mobil-Mock als
   Segmentleiste im Menü. Beide schalten dieselben drei Werte.
   Die Auswahl liegt unter localStorage["nils-theme"]. */
.theme-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 9px;
  background: transparent;
  border: 1px solid var(--line-3);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  letter-spacing: .02em;
  line-height: 1;
  cursor: pointer;
}
.nv:hover > .theme-btn, .nv:focus-within > .theme-btn,
.theme-btn:hover { color: var(--text-body); border-color: var(--text-accent); }
/* Halbkreis: die linke Hälfte gefüllt, die rechte offen — dasselbe Zeichen
   für „hell und dunkel", das der Mock zeichnet. */
.theme-btn__dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px currentColor;
  background: linear-gradient(90deg, currentColor 0 50%, transparent 50%);
}

/* Drei Vorschauen statt drei Wörter: die Kachel zeigt, was sie schaltet. */
.theme-cards { display: flex; gap: 8px; padding: 0 10px 2px; }
.theme-cards button {
  display: grid;
  gap: 8px;
  justify-items: start;
  width: 72px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.th-frame {
  display: block;
  width: 72px;
  height: 46px;
  border: 1px solid var(--line-3);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.theme-cards button[aria-pressed="true"] .th-frame { border-color: var(--text-accent); }
.th-frame--split { display: grid; grid-template-columns: 1fr 1fr; }
.th-mini {
  display: grid;
  align-content: start;
  gap: 3px;
  padding: 5px;
  height: 100%;
  box-sizing: border-box;
}
.th-mini i { display: block; height: 3px; border-radius: 1px; }
.th-mini i:first-child { height: 4px; }
.th-mini i:nth-child(2) { width: 78%; opacity: .8; }
.th-mini i:nth-child(3) { width: 52%; opacity: .45; }
/* Feste Farben: die Kachel zeigt das Schema, das sie schaltet, nicht das
   gerade eingestellte. Deshalb stehen hier Werte und keine Tokens. */
.th-mini--light { background: #FFFFFF; }
.th-mini--light i { background: #1F2733; }
.th-mini--light i:first-child { background: #DEE2E8; }
.th-mini--dark { background: #12171F; }
.th-mini--dark i { background: #C7CCD4; }
.th-mini--dark i:first-child { background: #26303D; }
.th-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
  color: var(--text-muted);
}
.theme-cards button[aria-pressed="true"] .th-name { color: var(--text-accent); }
.th-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--line-3);
}
.theme-cards button[aria-pressed="true"] .th-dot { background: var(--text-accent); box-shadow: none; }
.nv-p__foot {
  margin-top: 10px;
  padding: 9px 10px 5px;
  border-top: 1px solid var(--line-2);
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
  color: var(--text-faint);
}

/* Segmentleiste — nur noch im mobilen Menü, der Desktop nimmt die Kacheln. */
.theme-switch {
  display: flex;
  /* Als Ganzes nicht stauchbar — sonst schneidet das eigene overflow:hidden
     die Beschriftungen ab, sobald die Leiste eng wird. */
  flex: none;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.theme-switch button {
  flex: 1;
  white-space: nowrap;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  min-height: var(--hit-min);
  padding: 0 11px;
  border: none;
  cursor: pointer;
  background: transparent;
  color: var(--text-muted);
  transition: background-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out);
}
.theme-switch button:hover { color: var(--text-body); }
/* Nicht --text-on-accent: das ist Weiß und passt zum satten Blau der
   Primärknöpfe, nicht zum hellen Kleintext-Blau hier — Weiß darauf trug 2,23:1.
   Die Seitenfläche ist im dunklen Schema dunkel und im hellen hell, also
   ergibt sie in beiden den nötigen Gegenpol. */
.theme-switch button[aria-pressed="true"] { background: var(--text-accent); color: var(--surface-page); }

/* Lupe und Hamburger — nur mobil, Gegenstück zur Leiste rechts. */
.site-tools { display: none; margin-left: auto; align-items: center; gap: 9px; }
.nav-search-link {
  width: var(--hit-min);
  height: var(--hit-min);
  display: flex;
  align-items: center;
  justify-content: center;
}
.icon-search { position: relative; display: block; width: 17px; height: 17px; }
.icon-search::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  box-sizing: border-box;
  border: 1.5px solid var(--text-secondary);
  border-radius: 50%;
}
.icon-search::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 1px;
  width: 7px;
  height: 1.5px;
  background: var(--text-secondary);
  transform: rotate(45deg);
  transform-origin: right center;
}
.nav-toggle {
  display: none;
  width: var(--hit-min);
  height: var(--hit-min);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}
.nav-toggle span { width: 18px; height: 1.5px; background: var(--text-secondary); }

/* Vollflächiges Menü */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  flex-direction: column;
  background: var(--surface-page);
}
.mobile-menu[data-open="true"] { display: flex; }
body.menu-open { overflow: hidden; }

.mobile-menu__bar {
  display: flex;
  align-items: center;
  flex: none;
  height: 52px;
  padding: 0 10px 0 20px;
  border-bottom: 1px solid var(--line-2);
}
.mobile-menu__close {
  width: var(--hit-min); height: var(--hit-min);
  margin-left: auto;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; cursor: pointer;
  color: var(--text-secondary); font-size: 17px;
}

/* Suche steht vor den Zielen: wer weiß, was er sucht, tippt es. */
.mobile-menu__search {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  margin: 12px 20px 4px;
  padding: 0 13px;
  background: var(--surface-sunken);
  border: 1px solid var(--line-3);
  border-radius: var(--radius-sm);
}
.mobile-menu__search:focus-within { border-color: var(--text-accent); box-shadow: var(--ring-focus); }
.mobile-menu__search span:first-child {
  font-family: var(--font-core);
  font-size: var(--t-xs);
  font-weight: var(--weight-bold);
  color: var(--text-accent);
}
.mobile-menu__search input {
  flex: 1;
  min-width: 0;
  min-height: var(--hit-min);
  background: none;
  border: none;
  outline: none;
  font-family: var(--font-core);
  font-size: var(--t-xs);
  letter-spacing: .02em;
  color: var(--text-body);
}
.mobile-menu__search input::placeholder { color: var(--text-muted); }
.mobile-menu__search .kbd { margin-left: auto; font-size: var(--t-2xs); color: var(--text-faint); }

/* Die Liste ist das einzige, was scrollt — Kopf, Suche und Fuß bleiben. */
.mobile-menu nav {
  display: grid;
  align-content: start;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 0 8px;
}
.mobile-menu nav a, .mobile-menu__soon {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 56px;
  padding: 0 22px;
  color: var(--text-body);
  font-size: var(--t-lg);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-heading);
}
.mobile-menu nav a:hover { background: var(--surface-hover); }
/* Der aktive Punkt trägt links eine Kante; die 2 px nimmt der Innenabstand
   zurück, sonst rückte die Zeile gegenüber den anderen ein. */
.mobile-menu nav a[aria-current="page"] {
  color: var(--text-accent);
  background: var(--accent-primary-dim);
  border-left: 2px solid var(--text-accent);
  padding-left: 20px;
}
.mobile-menu nav .num {
  width: 22px;
  flex: none;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .08em;
  color: var(--text-muted);
}
.mobile-menu nav .count {
  margin-left: auto;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
/* Zwischenüberschriften gliedern die acht Ziele in Beiträge, Person, Kontakt. */
.mobile-menu__group {
  padding: 16px 22px 6px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.mobile-menu__soon { color: var(--text-muted); }

.mobile-menu__foot { flex: none; padding: 0 20px 28px; display: grid; gap: 14px; }
.mobile-menu__theme { display: grid; gap: 9px; }
.mobile-menu__theme .u-label { color: var(--text-faint); }
.mobile-menu__resolved {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
  color: var(--text-muted);
}
.mobile-menu__build {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
  color: var(--text-muted);
}
.mobile-menu__build::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-muted);
}
.mobile-menu__links { display: flex; gap: 18px; }
.mobile-menu__links a {
  display: flex;
  align-items: center;
  min-height: var(--hit-min);
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* Hauptbereich */
.main { flex: 1; }
.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--container-pad);
  width: 100%;
}
/* Schmalere Spalten für Seiten ohne Sidebar. Die Zahlen stehen so im
   Desktop-Mock; sie richten sich danach, was die Seite trägt — eine Liste mit
   zwei Spalten braucht mehr als ein Fließtext. */
.container--narrow { max-width: 900px; }
.container--reading { max-width: 820px; }
.container--lesen { max-width: 1000px; }
.container--ehrenamt { max-width: 880px; }

/* Fußzeile */
.site-footer {
  border-top: 1px solid var(--border-default);
  background: var(--surface-card);
  padding: 24px var(--gut);
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
  color: var(--text-muted);
}
.site-footer__brand { display: flex; align-items: center; gap: 14px; }
.site-footer nav { margin-left: auto; display: flex; gap: 18px; flex-wrap: wrap; }
.site-footer nav a { color: var(--text-muted); }
.site-footer nav a:hover { color: var(--link-hover); }
.site-footer nav a[aria-current="page"] { color: var(--text-body); }

/* ==========================================================================
   3 · Komponenten (wörtlich aus _ds_bundle.js)
   ========================================================================== */

/* --- Button --- */
.np-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-core);
  font-weight: var(--weight-medium);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  height: var(--control-md);
  padding: 0 16px;
  font-size: var(--text-sm);
  transition: background var(--dur-1) var(--ease-out),
              border-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out),
              filter var(--dur-1) var(--ease-out);
}
.np-btn:focus-visible { outline: none; box-shadow: var(--ring-focus); }
.np-btn[disabled] { opacity: .45; cursor: not-allowed; pointer-events: none; }
.np-btn--sm { height: var(--control-sm); padding: 0 12px; font-size: var(--text-xs); }
.np-btn--md { height: var(--control-md); padding: 0 16px; font-size: var(--text-sm); }
.np-btn--lg { height: var(--control-lg); padding: 0 22px; font-size: var(--text-md); }
.np-btn--block { display: flex; width: 100%; }
.np-btn--primary { background: var(--accent-primary); color: var(--text-on-accent); }
.np-btn--primary:hover { background: var(--accent-primary-hover); color: var(--text-on-accent); }
.np-btn--primary:active { filter: brightness(.82); }
.np-btn--secondary { background: var(--surface-raised); border-color: var(--border-default); color: var(--text-body); }
.np-btn--secondary:hover { background: var(--surface-active); border-color: var(--border-strong); color: var(--text-body); }
.np-btn--secondary:active { filter: brightness(.9); }
.np-btn--ghost { background: transparent; color: var(--text-secondary); }
.np-btn--ghost:hover { background: var(--surface-hover); color: var(--text-body); }
.np-btn--ghost:active { filter: brightness(.9); }

/* --- Badge. Zustand immer mit Wort, nie Punkt oder Farbe allein. --- */
.np-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 9px;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
}
.np-badge-dot { width: 6px; height: 6px; border-radius: var(--radius-full); background: currentColor; flex: none; }
.np-badge--neutral { background: var(--surface-raised); color: var(--fg-2); border: 1px solid var(--border-default); }
.np-badge--success { background: var(--status-success-dim); color: var(--status-success); }
.np-badge--warning { background: var(--status-warning-dim); color: var(--status-warning); }
.np-badge--danger { background: var(--status-danger-dim); color: var(--status-danger); }
.np-badge--info { background: var(--status-info-dim); color: var(--status-info); }
.np-badge--accent { background: var(--accent-primary-dim); color: var(--accent-small); }

/* --- Tag --- */
.np-tag {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-default);
  background: transparent;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: default;
  transition: border-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out),
              background var(--dur-1) var(--ease-out);
}
.np-tag-hash { color: var(--text-faint); }
.np-tag--clickable { cursor: pointer; }
.np-tag--clickable:hover { border-color: var(--text-accent); color: var(--text-accent); }
.np-tag--clickable:hover .np-tag-hash { color: var(--text-accent); }
.np-tag--active { background: var(--accent-primary-dim); border-color: var(--text-accent); color: var(--text-accent); }
.np-tag--active .np-tag-hash { color: var(--text-accent); }
.np-tag:focus-visible { outline: none; box-shadow: var(--ring-focus); }

/* --- PostCard --- */
.np-post {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border-subtle);
  padding: var(--space-6) 0;
  font-family: var(--font-core);
}
.np-post-top { display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.np-post-date {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.np-post-feat {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--accent-small);
}
.np-post-read {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.np-post-title {
  font-family: var(--font-core);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-heading);
  color: var(--text-heading);
  margin: 0 0 8px;
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  max-width: none;
  transition: color var(--dur-1) var(--ease-out);
}
.np-post--featured .np-post-title { font-size: var(--text-xl); }
.np-post-title a { color: inherit; }
.np-post-title a:hover { color: var(--text-accent); }
.np-post:hover .np-post-title { color: var(--text-accent); }
.np-post-excerpt {
  font-family: var(--font-prose);
  font-size: var(--text-base);
  line-height: var(--lh-body);
  color: var(--text-body);
  margin: 0 0 14px;
  max-width: var(--measure-prose);
  hyphens: auto;
}
.np-post-tags { display: flex; gap: 8px; flex-wrap: wrap; }

/* --- Card --- */
.np-card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  font-family: var(--font-core);
}
.np-card--pad-sm { padding: var(--space-4); }
.np-card--pad-md { padding: var(--space-6); }
.np-card--pad-lg { padding: var(--space-7); }

/* --- CodeBlock. Die Codefläche sitzt heller als der Grund, nicht dunkler. --- */
.np-code {
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
  font-family: var(--font-mono);
}
/* Lange Dateinamen (~/.config/…/config.toml) brechen auf schmalen Telefonen
   um, statt vom overflow: hidden der Codefläche abgeschnitten zu werden. */
.np-code-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--surface-card);
}
.np-code-file {
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.np-code-lang {
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}
.np-code-body {
  margin: 0;
  padding: 14px 16px;
  overflow-x: auto;
  font-size: var(--t-xs);
  line-height: 1.8;
  background: none;
  border: none;
  border-radius: 0;
  max-width: none;
  tab-size: 4;
}
.np-code-line { display: block; white-space: pre; }
.np-code-line--hl { background: var(--accent-primary-dim); margin: 0 -16px; padding: 0 16px; }

/* --- Formularfelder --- */
.np-field { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-core); }
.np-field-label { font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--text-secondary); }
.np-input-wrap {
  display: flex;
  align-items: center;
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-1) var(--ease-out),
              box-shadow var(--dur-1) var(--ease-out);
}
.np-input-wrap:focus-within { border-color: var(--border-accent); box-shadow: 0 0 0 3px var(--accent-primary-dim); }
.np-input-wrap--error { border-color: var(--status-danger); }
.np-input-wrap--error:focus-within { border-color: var(--status-danger); box-shadow: 0 0 0 3px var(--status-danger-dim); }
.np-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-body);
  font-family: inherit;
  padding: 0 12px;
  /* --hit-min statt --control-md: 44 px, wie tokens.css es zusagt. Volle
     Höhe, nicht minus Rahmen — der Rahmen gehört dem Wrapper, das Tippziel
     ist das Feld selbst. Der Kasten außenrum wird dadurch 46 px hoch. */
  height: var(--hit-min);
  font-size: var(--text-sm);
}
.np-input::placeholder { color: var(--text-faint); }
.np-input--mono { font-family: var(--font-mono); }
.np-textarea {
  width: 100%;
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-body);
  font-family: var(--font-prose);
  font-size: var(--text-sm);
  line-height: 1.6;
  padding: 12px 14px;
  resize: vertical;
  min-height: 120px;
  transition: border-color var(--dur-1) var(--ease-out),
              box-shadow var(--dur-1) var(--ease-out);
}
.np-textarea::placeholder { color: var(--text-faint); }
.np-textarea:focus { outline: none; border-color: var(--border-accent); box-shadow: 0 0 0 3px var(--accent-primary-dim); }
.np-textarea--error { border-color: var(--status-danger); box-shadow: 0 0 0 3px var(--status-danger-dim); }
.np-field-hint { font-size: var(--text-2xs); color: var(--text-muted); }
.np-field-error { font-size: var(--t-xs); line-height: 1.5; color: var(--status-danger); font-family: var(--font-core); }
/* Im Fehlerfall wird auch das Label rot — so trägt der Zustand ein Wort
   und eine Position, nicht nur eine Farbe. */
.np-field[data-invalid="true"] .np-field-label { color: var(--status-danger); }

.np-select-wrap {
  position: relative;
  display: flex;
  align-items: center;
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-1) var(--ease-out),
              box-shadow var(--dur-1) var(--ease-out);
}
.np-select-wrap:focus-within { border-color: var(--border-accent); box-shadow: 0 0 0 3px var(--accent-primary-dim); }
.np-select-wrap--error { border-color: var(--status-danger); }
.np-select {
  appearance: none;
  -webkit-appearance: none;
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-body);
  font-family: var(--font-core);
  padding: 0 32px 0 12px;
  cursor: pointer;
  height: var(--hit-min);
  font-size: var(--text-sm);
}
.np-select option { background: var(--bg-3); color: var(--text-body); }
.np-select-caret {
  position: absolute;
  right: 13px;
  top: 50%;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--text-muted);
  border-bottom: 1.5px solid var(--text-muted);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

/* ==========================================================================
   4 · Seitenbausteine
   ========================================================================== */

/* ---- Wiederkehrende Textrollen ---- */
.lede {
  font-family: var(--font-prose);
  font-size: var(--t-lg);
  line-height: 1.55;
  letter-spacing: var(--tracking-tight);
  color: var(--text-secondary);
  max-width: 58ch;
}
.more-link {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  margin-left: auto;
  white-space: nowrap;
}

.actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: var(--r-4); }

/* ---- Now-Liste: Punkt trägt den Zustand, das Wort steht im Satz ---- */
/* Überschrift links, Liste rechts. Stand als Inline-Style in index.html —
   dort konnte keine Media Query die feste 230-px-Spalte zurücknehmen, und auf
   dem Telefon blieben der Liste 61 px, in denen der Text buchstabenweise
   umbrach. Als Klasse greift der Umbruch unten wieder. */
.now-split {
  display: grid;
  grid-template-columns: 230px minmax(0, 1fr);
  gap: var(--r-5);
  align-items: start;
}
.now-list { display: grid; gap: 14px; max-width: 62ch; }
.now-list > div { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 14px; align-items: start; }
.now-list .dot { width: 8px; height: 8px; border-radius: var(--radius-full); margin-top: 9px; background: var(--text-accent); }
.now-list .dot--ok { background: var(--status-success); }
.now-list .dot--open { background: var(--status-warning); }
.now-list p { font-size: var(--t-md); line-height: 1.7; }

/* ---- Karten ---- */
.cards-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 24px;
}
.card--sm { padding: 20px 22px; }
.card h3 { font-size: var(--t-lg); line-height: 1.3; letter-spacing: var(--tracking-tight); margin: 0 0 var(--r-2); text-wrap: balance; }
.card p { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); max-width: 40ch; }
/* Trägt die Karte einen Satz statt eines Schlagworts, steht der Titel in
   Fließtextgröße und ohne Ausgleich — sonst bricht „Führung ohne
   Weisungsbefugnis" hinter dem ersten Wort um. */
.card--kompakt h3 { font-size: var(--t-sm); line-height: 1.4; margin-bottom: 12px; text-wrap: normal; }
.card__links { display: grid; gap: 11px; }
.card__links a { font-size: var(--t-sm); line-height: 1.45; }

/* ---- Stack: Inhaltsspalte, Gruppen, Werkzeugzeilen (Mock 05) ---- */
.stack-layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: var(--r-6);
  align-items: start;
}
.stack-layout__main { display: grid; gap: var(--r-5); max-width: 1000px; min-width: 0; }

/* Übersicht, keine Navigation — im Mock stehen dort keine Links. */
.stack-toc { position: sticky; top: 84px; display: grid; min-width: 0; }
.stack-toc__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--t-2xs);
  letter-spacing: .02em;
  color: var(--text-secondary);
}
.stack-toc__n { font-size: var(--t-3xs); letter-spacing: .06em; color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* Gruppenkopf: Label, Haarlinie bis zum Rand, Anzahl. */
.rule-head { display: flex; align-items: center; gap: 14px; margin-bottom: var(--r-2); }
.rule-head__line { flex: 1; border-top: 1px solid var(--line-2); }
.rule-head__n {
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  letter-spacing: .06em;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.stack-group { display: grid; border-top: 1px solid var(--border-subtle); }
.stack-row {
  display: grid;
  grid-template-columns: 230px minmax(0, 1fr) 160px;
  gap: 28px;
  padding: 17px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.stack-row__name { grid-column: 1; font-weight: var(--weight-bold); color: var(--text-body); }
.stack-row__text { grid-column: 2; grid-row: 1; font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); max-width: none; }
.stack-row__art {
  grid-column: 3;
  grid-row: 1;
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  letter-spacing: .06em;
  color: var(--text-muted);
}

.stack-out {
  display: grid;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
.stack-out > div { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 28px; padding: 20px 24px; }
.stack-out > div + div { border-top: 1px solid var(--border-subtle); }
.stack-out__name { font-size: var(--t-sm); font-weight: var(--weight-bold); color: var(--text-body); }
.stack-out p { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); max-width: none; }
/* Dasselbe Kästchen, engere Namensspalte — „Was nicht drin ist" im Kolophon
   trägt ein Wort je Zeile, nicht einen halben Satz wie der Stack. */
.stack-out--eng > div { grid-template-columns: 200px minmax(0, 1fr); gap: 24px; padding: 18px 22px; }

/* ---- Kolophon: Stichwort links, Angabe rechts (Mock 07) ----
   Die linke Spalte ist getönt, nicht fett: sie benennt, was rechts steht,
   und soll dabei nicht mit den Angaben um Aufmerksamkeit ringen. */
.spec {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
  font-family: var(--font-core);
  font-size: 13px;
  line-height: 1.6;
}
.spec__k, .spec__v { padding: 12px 16px; border-bottom: 1px solid var(--border-subtle); }
.spec__k { background: var(--surface-sunken); color: var(--text-muted); }
.spec__v { color: var(--text-body); }
.spec > :nth-last-child(-n + 2) { border-bottom: 0; }

/* ---- Lesen: Titel und Urheber links, die Notiz rechts (Mock 08) ---- */
.read-groups { display: grid; gap: var(--r-5); }
.read-list { display: grid; border-top: 1px solid var(--border-subtle); }
.read-row {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 28px;
  align-items: baseline;
  padding: 18px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.read-row__head { display: grid; gap: 5px; }
.read-row__title { font-size: var(--t-md); font-weight: var(--weight-bold); letter-spacing: -.03em; color: var(--text-body); text-wrap: pretty; }
.read-row__by { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .04em; color: var(--text-muted); }
.read-row__text { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); max-width: none; }

/* ---- Ehrenamt: Stationen, Kennzahlen, Verbindung zum Beruf (Mock 09) ----
   Die Station ist gebaut wie die Laufbahn unter „Über mich", nur ohne Linie:
   sie trägt zusätzlich Aufgaben und — bei der laufenden — Kennzahlen. */
.duties { display: grid; border-top: 1px solid var(--border-subtle); }
.duty {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  gap: 28px;
  padding: 26px 0;
  border-bottom: 1px solid var(--border-subtle);
}
.duty__when {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding-top: 6px;
}
.duty__body { display: grid; gap: 7px; min-width: 0; }
.duty__role { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.duty__role span:first-child { font-size: var(--t-lg); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-heading); }
.duty__org { font-family: var(--font-core); font-size: 13px; letter-spacing: -.01em; color: var(--text-muted); }
.duty__body > p { font-size: 16px; line-height: 1.65; color: var(--text-secondary); margin: 4px 0 6px; }

/* Aufzählung mit Halbgeviertstrich statt Punkt — der Punkt gehört im
   Fließtext zu <ul>, hier steht eine Liste von Aufgaben, kein Text. */
.dashes { display: grid; gap: 7px; }
.dashes > div { display: grid; grid-template-columns: 12px minmax(0, 1fr); gap: 11px; align-items: baseline; }
.dashes > div > span:first-child { color: var(--text-faint); }
.dashes > div > span + span { font-size: var(--t-sm); line-height: 1.6; color: var(--text-secondary); }

/* Kennzahlen: vier Felder an einer Haarlinie, die aus dem Rand kommt. */
.figures {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  margin-top: 6px;
  background: var(--border-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.figures > div { background: var(--surface-card); padding: 16px 14px; display: grid; gap: 6px; }
.figures__n { font-family: var(--font-core); font-size: var(--t-lg); font-weight: var(--weight-bold); color: var(--text-accent); font-variant-numeric: tabular-nums; }
.figures__t { font-family: var(--font-core); font-size: var(--t-3xs); line-height: 1.5; color: var(--text-muted); }

.bridge {
  display: grid;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
.bridge > div { display: grid; grid-template-columns: 110px 240px minmax(0, 1fr); gap: 24px; align-items: baseline; padding: 18px 22px; }
.bridge > div + div { border-top: 1px solid var(--border-subtle); }
.bridge__when { font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.bridge__name { font-size: var(--t-sm); font-weight: var(--weight-bold); color: var(--text-body); }
.bridge__text { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); max-width: none; }

.ask {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 28px;
  align-items: start;
  border-top: 1px solid var(--border-subtle);
  padding-top: var(--r-4);
}
.ask > div:first-child { padding-top: 3px; }
.ask .dashes { gap: 12px; }

/* ---- Über mich: Laufbahn ---- */
.with-aside {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 96px;
  align-items: start;
}
.with-aside__main { max-width: 840px; min-width: 0; }
.with-aside__side { display: grid; gap: 24px; min-width: 0; }

.timeline { display: grid; }
.timeline > div { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 24px; padding: 0 0 28px; }
.timeline > div:last-child { padding-bottom: 0; }
.timeline__when {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  padding-top: 4px;
}
.timeline__body { border-left: 1px solid var(--border-default); padding-left: 24px; position: relative; }
.timeline__body::before {
  content: '';
  position: absolute;
  left: -4.5px;
  top: 6px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--line-3);
}
.timeline > div:first-child .timeline__body::before { background: var(--text-accent); }
.timeline__role { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.timeline__role span:first-child { font-size: var(--t-lg); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-heading); }
.timeline__org { font-family: var(--font-core); font-size: 13px; letter-spacing: -.01em; color: var(--text-muted); margin-bottom: 8px; }
.timeline__body p { font-size: 16px; line-height: 1.65; color: var(--text-secondary); }

/* ---- Über mich: Ausbildung, Zertifikate, Ehrenamt ---- */
/* Die Mocks setzen die Absätze in Laufbahn, Karten und Grundsätzen auf 15 px.
   Mit den neuen, längeren Texten sind das Fließtexte, und die brauchen hier
   16 px (check_render.py, Regel schriftgroesse). */
.edu { display: grid; }
.edu > div {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  gap: 24px;
  padding: 14px 0;
  border-top: 1px solid var(--border-subtle);
}
.edu__when { font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.edu__title { font-size: var(--t-sm); font-weight: var(--weight-semibold); letter-spacing: -.02em; margin-bottom: 3px; }
.edu__org { font-family: var(--font-core); font-size: 13px; color: var(--text-muted); }

.creds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.cred {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 20px;
}
.cred__top { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px; margin-bottom: 8px; }
.cred__when { font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-muted); }
.cred__title { font-size: var(--t-lg); font-weight: var(--weight-semibold); line-height: 1.3; max-width: none; margin-bottom: 4px; }
.cred__org { font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: .04em; color: var(--text-muted); margin-bottom: 10px; }
.cred p { font-size: 16px; line-height: 1.65; color: var(--text-secondary); }

/* Porträt: auf breiten Schirmen in der Seitenspalte (4:5), einspaltig oben
   über dem Text im Querformat (3:2) — so zeigen es Desktop- und Mobil-Mock. */
.portrait.portrait--wide { display: none; aspect-ratio: 3/2; margin-bottom: 22px; }

/* ---- Nummerierte Grundsätze ---- */
.principles { display: grid; }
.principles > div {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 20px;
  padding: 20px 0;
  border-top: 1px solid var(--border-subtle);
}
.principles .n { font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: .06em; color: var(--text-accent); padding-top: 5px; }
.principles__title { font-size: var(--t-lg); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-heading); line-height: 1.35; margin-bottom: 8px; }
.principles p { font-size: 16px; line-height: 1.65; color: var(--text-secondary); max-width: 62ch; }

/* ---- Porträt und Bildplatzhalter ---- */
.portrait { aspect-ratio: 4/5; border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; position: relative; }
.frame { position: relative; border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; background: var(--surface-card); }
.frame img { width: 100%; height: 100%; object-fit: cover; }
/* Bildplatzhalter: keine Schraffur, keine Textur — nur Fläche und Linie. */
.ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 16px;
  background: var(--surface-sunken);
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  line-height: 1.5;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}

/* ---- Schlagwortwolke in der Sidebar ---- */
.tag-row { display: flex; flex-wrap: wrap; gap: 7px; }

/* ---- Blog: Beiträge links, Themen und Jahre rechts (Mock 02) ---- */
.blog-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 80px;
  align-items: start;
}
.blog-layout__main { min-width: 0; max-width: 880px; }
.blog-layout__side { min-width: 0; display: grid; gap: 28px; position: sticky; top: 84px; align-self: start; }

/* ---- Artikel: Randspalte · Satzspiegel · Seitenspalte ----
   Grundform sind zwei Spalten: links Thema, Datum, Dauer und Schlagwörter,
   daneben der Satzspiegel. 720 px (--measure-article) ist dabei die
   Obergrenze, nicht das Maß.
   Zwei Seiten bauen darauf auf und schließen sich gegenseitig aus:
   --seite stellt die Seitenspalte des Artikels daneben (Mock 03),
   --recht rückt Impressum und Datenschutz ohne dritte Spalte in die Mitte,
   statt sie an den linken Rand zu hängen (Mock 09/10). */
.article-layout {
  display: grid;
  grid-template-columns: 210px minmax(0, var(--measure-article));
  gap: 64px;
}
.article-layout--recht { justify-content: center; }

/* Artikel: Inhaltsverzeichnis, Quelle und „Weiter im Thema" in einer dritten
   Spalte. Satzspiegel und Spalte teilen sich, was der Container übrig lässt —
   bei 1440 px steht der Artikel damit auf rund 680 px, die Spalte auf 340. */
.article-layout--seite {
  grid-template-columns: 210px minmax(0, var(--measure-article)) minmax(0, 340px);
}
.article-gutter {
  display: grid;
  gap: 10px;
  text-align: right;
  padding-top: 12px;
  position: sticky;
  top: 84px;
  align-self: start;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  line-height: 1.5;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
.article-gutter__rule { color: var(--text-faint); border-top: 1px solid var(--border-default); padding-top: 10px; }
.article-gutter a { color: var(--text-muted); }
.article-gutter a[aria-current] { color: var(--text-body); }

.prose > p { max-width: 66ch; line-height: 1.7; }
.prose > p + p { margin-top: var(--r-3); }
.prose h2 { font-size: var(--t-2xl); line-height: 1.18; margin: var(--r-6) 0 var(--r-2); max-width: 28ch; }
.prose h3 { font-size: var(--t-xl); line-height: 1.28; letter-spacing: var(--tracking-tight); margin: var(--r-5) 0 12px; max-width: 34ch; }
.prose .np-code { margin: 0 0 var(--r-3); }
.prose ul, .prose ol { margin: 0 0 var(--r-3); max-width: 66ch; }
.rule { height: 1px; background: var(--line-2); border: 0; margin: var(--r-5) 0; }

/* ---- Definitionsraster (Impressum, Eingangsbestätigung) ---- */
.defs {
  display: grid;
  gap: 1px;
  background: var(--border-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.defs > div {
  background: var(--surface-card);
  padding: 14px 18px;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .04em;
}
.defs .k { color: var(--text-muted); }
.defs .v { color: var(--text-body); }

/* Impressum: Angabenblock mit breiter Beschriftungsspalte */
.fields { display: grid; gap: 16px; font-size: var(--t-sm); line-height: 1.6; }
.fields > div { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 20px; }
.fields > div.is-separated { border-top: 1px solid var(--border-subtle); padding-top: 16px; }
.fields dt, .fields .k {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  padding-top: 2px;
}
.fields dd { margin: 0; }
.todo { color: var(--text-faint); }

/* ---- Setup-Tabelle (Now) ---- */
.setup { background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); overflow: hidden; }
.setup__grid { display: grid; grid-template-columns: 150px minmax(0, 1fr); font-family: var(--font-core); font-size: var(--t-xs); }
.setup__grid > div { padding: 12px 16px; border-bottom: 1px solid var(--border-subtle); }
.setup__grid > div:nth-child(odd) { background: var(--surface-sunken); color: var(--text-muted); }
.setup__grid > div:nth-child(even) { color: var(--text-body); }
.setup__grid > div:nth-last-child(-n+2) { border-bottom: 0; }

/* ---- Hinweisbanner ---- */
.notice {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: 16px 20px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
/* Grundgröße statt --t-sm: hier steht Fließtext, der gelesen werden muss. */
.notice p { line-height: 1.6; color: var(--text-body); max-width: none; }
.notice__tag {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding-top: 3px;
}
.notice--warning { border-color: var(--status-warning); background: var(--status-warning-dim); }
.notice--warning .notice__tag { color: var(--status-warning); }
.notice--danger { border-color: var(--status-danger); background: var(--status-danger-dim); }

/* Fehlerzusammenfassung im Formular */
.error-summary {
  border: 1px solid var(--status-danger);
  background: var(--status-danger-dim);
  border-radius: var(--radius-md);
  padding: 18px 22px;
}
.error-summary__head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.error-summary__count {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--status-danger);
}
.error-summary ul { display: grid; gap: 6px; margin: 0; max-width: none; }
.error-summary li { padding-left: 0; }
.error-summary li::before { display: none; }
.error-summary a { font-family: var(--font-prose); font-size: var(--t-sm); line-height: 1.5; color: var(--text-body); }

/* ---- Filterleiste und Leerzustand (Schreiben) ---- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding-bottom: var(--r-3);
  border-bottom: 1px solid var(--border-default);
  margin-bottom: var(--r-5);
}
.filters__label {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-right: 6px;
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .05em;
  padding: 6px 10px;
  border: 1px solid var(--text-accent);
  background: var(--accent-primary-dim);
  border-radius: var(--radius-xs);
  color: var(--text-accent);
}
.filter-chip button {
  background: none; border: none; cursor: pointer; color: inherit;
  font-size: 12px; line-height: 1; padding: 2px; opacity: .7;
}
.filter-chip button:hover { opacity: 1; }
.filters__count {
  margin-left: auto;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .05em;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.empty-state {
  border: 1px dashed var(--line-3);
  border-radius: var(--radius-md);
  padding: 52px 40px;
  text-align: center;
  margin-bottom: var(--r-6);
}
.empty-state h2 { font-size: var(--t-xl); line-height: 1.25; letter-spacing: var(--tracking-tight); margin: 0 auto var(--r-2); max-width: 30ch; }
.empty-state p { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); margin: 0 auto var(--r-4); max-width: 52ch; }
.empty-state__actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* „Ohne Jahresfilter" (Mock 12): drei Karten unter dem Leerzustand, die
   zeigen, was dieselben Themen ohne das Jahr hergeben. */
.fallback { margin-bottom: var(--r-6); }
/* Drei Karten wie im Mock, solange sie nebeneinander passen — die
   Beitragsspalte ist schmaler als die Mock-Leinwand. */
.fallback__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 20px; }
.fallback__card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 22px;
  display: grid;
  gap: 10px;
  text-decoration: none;
}
.fallback__card:hover { border-color: var(--border-strong); }
.fallback__meta {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-accent);
}
.fallback__title {
  font-size: var(--t-lg);
  font-weight: var(--weight-semibold);
  line-height: 1.3;
  letter-spacing: var(--tracking-tight);
  color: var(--text-body);
  text-wrap: balance;
}
.fallback__excerpt { font-size: var(--t-sm); line-height: 1.6; color: var(--text-secondary); }

/* Jahrgangsliste in der Sidebar */
.years { display: grid; gap: 2px; font-family: var(--font-core); font-size: var(--t-xs); }
.years a, .years button {
  display: flex;
  justify-content: space-between;
  align-items: center;
  min-height: var(--hit-min);
  padding: 0 8px;
  margin: 0 -8px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  font-size: inherit;
  color: var(--text-body);
  cursor: pointer;
  text-align: left;
  text-decoration: none;
}
.years a:hover, .years button:hover { background: var(--surface-hover); }
.years .count { color: var(--text-muted); }
.years [aria-pressed="true"], .years [aria-current="true"] {
  background: var(--surface-raised);
  color: var(--text-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.years [aria-pressed="true"] .count { color: var(--text-secondary); }

/* ---- 404 ---- */
.term {
  background: var(--bg-0);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: var(--r-5);
}
.term__bar {
  height: 36px;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--border-default);
  background: var(--bg-2);
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.term__bar .dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--text-accent); }
.term__body {
  padding: 18px var(--space-6);
  font-family: var(--font-core);
  font-size: var(--t-xs);
  line-height: 1.9;
  white-space: pre-wrap;
  overflow-x: auto;
}
.term__body .m { color: var(--text-muted); }
.term__body .f { color: var(--text-faint); }
.term__body .a { color: var(--text-accent); }

.stack-rows {
  display: grid;
  gap: 1px;
  background: var(--border-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.stack-rows > a, .stack-rows > div { background: var(--surface-card); padding: 16px 20px; display: grid; gap: 5px; }
.stack-rows__title { font-size: var(--t-sm); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-tight); color: var(--text-body); }
.stack-rows__meta { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .06em; color: var(--text-muted); }

/* ---- Kontakt ---- */
.contact-grid { display: grid; grid-template-columns: minmax(0, 1fr) 240px; gap: 48px; align-items: start; }
.contact-form { display: grid; gap: 18px; }
.contact-aside { display: grid; gap: 14px; }
.contact-aside__links { display: grid; gap: 10px; font-family: var(--font-core); font-size: var(--t-xs); }
.contact-aside p { font-size: var(--t-xs); line-height: 1.65; color: var(--text-muted); }
.contact-note { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .05em; color: var(--text-faint); }
.expectations { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: var(--r-5); border-top: 1px solid var(--border-subtle); padding-top: var(--r-3); }
.expectations p { font-family: var(--font-prose); font-size: var(--t-xs); line-height: 1.6; color: var(--text-secondary); max-width: none; }
.hairline { height: 1px; background: var(--border-subtle); margin: 6px 0; border: 0; }

/* ---- Bestätigung ---- */
.confirm-mark { display: flex; align-items: center; gap: 12px; margin-bottom: var(--r-3); }
.confirm-mark__icon {
  width: 26px; height: 26px;
  border-radius: var(--radius-full);
  border: 1px solid var(--status-success);
  background: var(--status-success-dim);
  color: var(--status-success);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1;
}
.steps {
  display: grid;
  gap: 1px;
  background: var(--border-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.steps > div {
  background: var(--surface-card);
  padding: 18px 20px;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 14px;
  align-items: baseline;
}
.steps .n { font-family: var(--font-core); font-size: var(--t-2xs); color: var(--text-accent); font-variant-numeric: tabular-nums; }
.steps p { font-family: var(--font-prose); font-size: var(--t-sm); line-height: 1.6; max-width: none; }

/* Zweispalter „Inhalt + schmale Spalte" für 404 und Bestätigung */
.split-300 { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 40px; align-items: start; }
.split-300__side { display: grid; gap: var(--r-2); }
.split-300__side p { font-family: var(--font-core); font-size: var(--t-3xs); line-height: 1.7; letter-spacing: .04em; color: var(--text-muted); max-width: none; }

/* ---- Artikel: Abbildung, Tabelle, Zitat (Mock 15) ---- */
.figure { margin: 0 0 var(--r-4); }
.figure__shot {
  aspect-ratio: 16/9;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-md);
  overflow: hidden;
  position: relative;
  background: var(--bg-0);
}
.figure figcaption {
  display: flex;
  gap: 14px;
  margin-top: 10px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  line-height: 1.6;
  letter-spacing: .04em;
  color: var(--text-muted);
}
.figure__n {
  color: var(--text-accent);
  white-space: nowrap;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
.figure figcaption > span:last-child { max-width: 58ch; }

/* Die Tabelle steht im Rahmen und scrollt für sich — der Fließtext nicht. */
.table-wrap {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow-x: auto;
  margin: 0 0 var(--r-4);
}
.table-wrap table { width: 100%; font-size: var(--t-sm); line-height: 1.6; }
.table-wrap thead tr { background: var(--surface-sunken); }
.table-wrap th {
  padding: 12px 18px;
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.table-wrap td { padding: 14px 18px; color: var(--text-secondary); }
.table-wrap td:first-child { color: var(--text-body); }
/* Mock 15 trennt mit Linien, nicht mit Zebra. */
.table-wrap tbody tr:nth-child(even) td { background: none; }
.table-wrap tbody tr:last-child td { border-bottom: 0; }
.table-wrap .is-danger { color: var(--status-danger); }

/* Hervorgehobenes Zitat: 2 px Akzentlinie links, keine Anführungszeichen. */
.pull {
  margin: 0 0 var(--r-4);
  padding: 6px 0 6px 24px;
  border-left: 2px solid var(--text-accent);
  max-width: 62ch;
}
.pull p {
  font-size: var(--t-xl);
  line-height: 1.45;
  letter-spacing: var(--tracking-tight);
  color: var(--text-body);
  margin: 0 0 10px;
  max-width: none;
}
.pull footer {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Lange Pfade in Inline-Code und lange Adressen in Links passen auf einem
   320-px-Telefon nicht in die Zeile. Bisher schnitt der Glasrahmen der Seite
   sie ab (overflow: clip), seit er weg ist, schoben sie die Seite seitlich
   heraus. Jetzt brechen sie um, wo nichts anderes geht. */
.prose :is(p, li, td) :is(code, a), .sources :is(a, code, span) { overflow-wrap: anywhere; }

/* ---- Artikelende: Autor, Quellen, Lizenz, Nachbarn (Mock 15) ---- */
.author {
  margin-top: var(--r-6);
  border-top: 1px solid var(--line-2);
  padding-top: var(--r-4);
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.author__portrait {
  width: 72px;
  height: 72px;
  border-radius: var(--radius-full);
  border: 1px solid var(--line-3);
  overflow: hidden;
  position: relative;
}
.author__portrait .np-mark { width: 100%; height: 100%; font-size: calc(72px * var(--logo-mark-glyph)); }
.author__name {
  font-size: var(--t-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.3;
  margin-bottom: 8px;
}
.author p { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); margin: 0 0 12px; max-width: 58ch; }
.author__links {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.sources { margin-top: var(--r-4); border-top: 1px solid var(--line-2); padding-top: var(--r-3); }
.sources ol {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
  /* 16 px statt --t-sm: lange Quellenangaben sind Fließtext (check_render.py). */
  font-size: 16px;
  line-height: 1.6;
  max-width: 66ch;
}
.sources li { display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 10px; color: var(--text-secondary); }
.sources .n { font-family: var(--font-core); font-size: var(--t-2xs); color: var(--text-accent); padding-top: 3px; }
.sources em { font-style: normal; color: var(--text-body); }

.licence {
  margin-top: var(--r-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: 20px 22px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 20px;
  align-items: center;
}
.licence p { font-size: var(--t-sm); line-height: 1.65; color: var(--text-secondary); margin: 0; max-width: 56ch; }

.post-nav {
  margin-top: var(--r-4);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--border-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.post-nav a { background: var(--surface-card); padding: 20px 22px; display: grid; gap: 8px; }
.post-nav a + a { text-align: right; }
/* Nur ein Nachbar (neuester Beitrag): „Nächster" bleibt rechts. */
.post-nav__next { grid-column: 2; text-align: right; }
.post-nav__dir {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.post-nav__title {
  font-size: var(--t-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.35;
  color: var(--text-body);
  text-wrap: pretty;
  transition: color var(--dur-1) var(--ease-out);
}
.post-nav__meta { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .06em; color: var(--text-faint); }
.post-nav a:hover .post-nav__title { color: var(--text-accent); }

/* Inhaltsverzeichnis in der dritten Spalte. Ab zwei Zwischenüberschriften. */
/* Sprungziele nicht unter der fixierten Kopfleiste verstecken. */
.prose [id], .sources, .licence { scroll-margin-top: 96px; }

/* ---- Seitenspalte des Artikels (Mock 03) ---- */
.article-side { position: sticky; top: 84px; align-self: start; padding-top: 12px; min-width: 0; }
.toc__head {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 14px;
}
.toc { display: grid; gap: 2px; border-left: 1px solid var(--border-default); }
.toc a { padding: 7px 0 7px 14px; font-size: var(--t-xs); line-height: 1.45; color: var(--text-secondary); }
.toc a.is-sub { padding-left: 26px; color: var(--text-muted); }
.toc a[aria-current="true"] { margin-left: -1px; border-left: 2px solid var(--text-accent); color: var(--text-accent); }

/* Woher der Text kommt: Datei im Content-Repo und Stand. */
.article-side__file {
  margin-top: var(--r-3);
  border-top: 1px solid var(--border-default);
  padding-top: 14px;
  display: grid;
  gap: 8px;
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  line-height: 1.7;
  letter-spacing: .04em;
  color: var(--text-muted);
}
.article-side__related { margin-top: var(--r-3); border-top: 1px solid var(--border-default); padding-top: 14px; }
.article-side__related .u-label { margin-bottom: 12px; }
.article-side__list { display: grid; gap: 12px; }
.article-side__list a { display: grid; gap: 5px; }
.article-side__title {
  font-size: var(--t-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.35;
  color: var(--text-body);
}
.article-side__meta { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .06em; color: var(--text-muted); }

/* Dasselbe Verzeichnis ausklappbar über dem Text, sobald die Randspalte
   quer steht (unter 1000 px). */
.toc-mobile { display: none; margin: 0 0 var(--r-5); border: 1px solid var(--border-default); border-radius: 4px; }
.toc-mobile summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 14px;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}
.toc-mobile summary::-webkit-details-marker { display: none; }
.toc-mobile summary::after { content: "+"; font-size: var(--t-sm); color: var(--text-accent); }
.toc-mobile[open] summary::after { content: "−"; }
.toc-mobile nav { display: grid; gap: 2px; margin: 0 14px 14px; border-left: 1px solid var(--border-default); }
.toc-mobile a { padding: 7px 0 7px 14px; font-size: var(--t-xs); line-height: 1.45; color: var(--text-secondary); }
.toc-mobile a.is-sub { padding-left: 26px; color: var(--text-muted); }
.toc__note {
  margin-top: var(--r-3);
  border-top: 1px solid var(--border-default);
  padding-top: 14px;
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  line-height: 1.7;
  letter-spacing: .04em;
  color: var(--text-muted);
}

/* ---- Suche (Mock 16) ---- */
.search-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 56px; align-items: start; }
/* Für /suche gibt es keinen Desktop-Mock. Der Deckel ist derselbe wie im
   Blog — ohne ihn liefe die Trefferliste im 1440er Container zu breit. */
.search-layout__main { min-width: 0; max-width: 880px; }
.search-box {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 52px;
  padding: 0 16px;
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.search-box:focus-within { border-color: var(--border-accent); box-shadow: var(--ring-focus); }
.search-box__label {
  flex: none;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-accent);
}
.search-box input {
  flex: 1;
  min-width: 0;
  height: 50px;
  background: none;
  border: none;
  outline: none;
  color: var(--text-body);
  font-family: var(--font-core);
  font-size: var(--t-md);
}
.search-box input::placeholder { color: var(--text-faint); }
.search-box__hint {
  flex: none;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-core);
  font-size: var(--t-3xs);
  letter-spacing: .06em;
  color: var(--text-faint);
}
.kbd {
  border: 1px solid var(--line-3);
  border-radius: var(--radius-xs);
  padding: 2px 6px;
  font-family: var(--font-core);
  font-size: inherit;
  color: var(--text-body);
}

.search-meta {
  display: flex;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
  padding-bottom: var(--r-2);
  margin-bottom: var(--r-3);
  border-bottom: 1px solid var(--border-default);
}
.search-meta__count {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.scopes { display: flex; gap: 8px; margin-left: auto; flex-wrap: wrap; }
.scope {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .06em;
  padding: 5px 10px;
  border: 1px solid var(--line-3);
  border-radius: var(--radius-xs);
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
}
.scope:hover { border-color: var(--text-accent); color: var(--text-accent); }
.scope[aria-pressed="true"] { border-color: var(--text-accent); background: var(--accent-primary-dim); color: var(--text-accent); }

.result { display: grid; gap: 8px; padding: 20px 0; border-bottom: 1px solid var(--border-subtle); }
.result__path { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .06em; color: var(--text-muted); }
.result__title {
  font-size: var(--t-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.3;
  color: var(--text-body);
  transition: color var(--dur-1) var(--ease-out);
}
.result__snippet { font-family: var(--font-prose); font-size: var(--t-sm); line-height: 1.6; color: var(--text-secondary); max-width: 70ch; }
.result__meta { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .06em; color: var(--text-faint); }
.result:hover .result__title { color: var(--text-accent); }
.result.is-active { background: var(--surface-hover); box-shadow: inset 2px 0 0 var(--text-accent); padding-left: 14px; }
/* Treffer im Text: getönte Fläche, nie nur Farbe. */
mark { background: var(--accent-primary-dim); color: var(--text-accent); padding: 0 3px; border-radius: var(--radius-xs); }
.search-foot {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  line-height: 1.7;
  letter-spacing: .05em;
  color: var(--text-muted);
  margin: var(--r-3) 0 0;
  max-width: none;
}
.search-aside { display: grid; gap: var(--r-2); min-width: 0; }
.search-aside__list { display: grid; gap: 12px; font-size: var(--t-xs); line-height: 1.6; color: var(--text-secondary); }
.keys { display: grid; gap: 10px; font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: .04em; color: var(--text-secondary); }
.keys > span { display: flex; justify-content: space-between; gap: 12px; align-items: center; }

/* ---- Sortierung und „mehr laden" (Mock 17) ---- */
.filters__sort {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: .05em;
  color: var(--text-muted);
}
.filters__sort button {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font: inherit;
  color: var(--text-body);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.more { display: grid; justify-items: center; gap: 14px; padding: var(--r-4) 0 0; }
.meter { width: 220px; height: 2px; background: var(--border-default); border-radius: 1px; overflow: hidden; }
.meter span { display: block; height: 2px; background: var(--text-accent); transition: width var(--dur-2) var(--ease-out); }
.meter--block { width: 100%; }
.more__count {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.more__jump { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .05em; color: var(--text-faint); }

/* ---- Pflichtfelder, Senden, Serverfehler (Mock 18, 19) ---- */
/* Pflicht steht als Wort am Label, nicht als Sternchen. */
.field-req, .field-opt { letter-spacing: .06em; text-transform: none; font-weight: var(--weight-regular); }
.field-req { color: var(--status-danger); }
.field-opt { color: var(--text-faint); }
.form-note { font-family: var(--font-core); font-size: var(--t-2xs); letter-spacing: .06em; color: var(--text-muted); }

/* Während des Sendens sind Felder gesperrt, der Text bleibt sichtbar. */
form[data-sending="true"] .contact-form { opacity: .75; pointer-events: none; }
.sending { display: grid; gap: 14px; margin-top: var(--r-3); border-top: 1px solid var(--border-default); padding-top: var(--r-3); }
.sending__head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.sending__note { font-family: var(--font-core); font-size: var(--t-3xs); line-height: 1.7; letter-spacing: .04em; color: var(--text-muted); margin: 0; max-width: none; }

.error-server {
  border: 1px solid var(--status-danger);
  background: var(--status-danger-dim);
  border-radius: var(--radius-md);
  padding: 20px 22px;
  margin-bottom: var(--r-4);
}
.error-server__head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.error-server__title {
  font-family: var(--font-core);
  font-size: var(--t-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--status-danger);
}
.error-server__try { font-family: var(--font-core); font-size: var(--t-3xs); letter-spacing: .05em; color: var(--text-muted); }
.error-server p { font-size: var(--t-sm); line-height: 1.65; color: var(--text-body); margin: 0 0 14px; max-width: 62ch; }
.error-server__actions { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
/* Ab dem dritten Fehlversuch steht die Mailadresse an erster Stelle und der
   Button rückt nach unten — wenn das Formular dreimal scheitert, ist der
   direkte Weg der verlässlichere. */
.error-server.is-persistent .error-server__actions { flex-direction: column; align-items: flex-start; gap: 14px; }
.error-server.is-persistent .contact-note { order: -1; font-size: var(--t-sm); color: var(--text-body); }
/* „Falls es bleibt" (Mock 19) */
.error-server__ways { margin-top: var(--r-3); border-top: 1px solid var(--border-subtle); padding-top: 14px; }
.error-server__ways .u-label { margin-bottom: 10px; }
.error-server__links { display: grid; gap: 10px; font-family: var(--font-core); font-size: var(--t-xs); }
.term__bar .dot--danger { background: var(--status-danger); }

/* ==========================================================================
   5 · Responsiv
   ========================================================================== */

/* Unter der vollen Containerbreite bleiben für die Seitenspalte des Artikels
   keine 340 px mehr: Spalte und Satzspiegel teilen sich den Rest, und der
   Artikel fiel bei 1181 px auf 31 Zeichen je Zeile (check_render.py, Regel
   `zeilenlaenge`). Spalte und Rinne gehen deshalb zurück, bevor der Text es
   tut. */
@media (max-width: 1439px) {
  .article-layout--seite {
    grid-template-columns: 210px minmax(0, var(--measure-article)) minmax(0, 240px);
    gap: 40px;
  }
}

/* Sechs Ziele brauchen Platz. Die volle Kopfzeile — Wortmarke, Führung,
   Architektur, Code, Vorträge, Blog, Über mich, Suchfeld, Farbmodus und CTA —
   braucht mit den echten Schriften rund 1270 px. Darunter wird sie kompakt:
   das Monogramm tritt an die Stelle der Wortmarke, das Suchfeld schrumpft
   auf ein Tippziel und klappt beim Fokus auf (die Ziele weichen dann wie
   beim Tippen), der Farbmodus zeigt nur noch sein Zeichen. Gegenstück in
   _build/check_render.py: die Breiten 1320 und 1321. */
@media (max-width: 1320px) {
  .site-header > .np-logo--header { display: none; }
  .np-mark--head { display: inline-flex; }
  .nav-search { position: relative; min-width: 0; width: calc(var(--hit-min) + 2px); padding: 0; }
  .nav-search__sign { position: absolute; left: 12px; pointer-events: none; }
  .nav-search__q { padding-left: 24px; }
  .nav-search__q::placeholder { color: transparent; }
  .nav-search__key { display: none; }
  .site-nav:has(> .nav-search:focus-within) .nv-hide { display: none; }
  .site-nav:has(> .nav-search:focus-within) > .nav-search { width: auto; min-width: 360px; }
  .site-nav:has(> .nav-search:focus-within) .nav-search__q::placeholder { color: var(--text-muted); }
  .theme-btn [data-theme-name] { display: none; }
}

/* Die breiten Maße des 1440er Mocks brauchen den 1440er Container. Sobald
   das Fenster schmaler ist, gehen Seitenspalten und Rinnen auf die Maße
   zurück, mit denen die Seite vorher lief — sonst frisst die breitere
   Seitenspalte genau den Platz, den Laufbahn und Beitragszeilen für ihre
   40 Zeichen je Zeile brauchen (check_render.py, Regel `zeilenlaenge`).
   Dieser Block steht vor dem 1000-px-Block, damit dessen einspaltige Regel
   bei gleicher Spezifität gewinnt. */
@media (max-width: 1180px) {
  /* Über mich: neben der 380-px-Spalte bleiben der Laufbahn bei 1001 px noch
     445 px. Mit 160 px Datumsspalte fällt der Fließtext darunter auf unter
     30 Zeichen je Zeile. Seitenspalte und Rinne gehen deshalb zurück, statt
     den Text schmaler werden zu lassen. */
  .with-aside { grid-template-columns: minmax(0, 1fr) 300px; gap: 40px; }
  .timeline > div { grid-template-columns: 140px minmax(0, 1fr); gap: 20px; }

  /* Stack: dasselbe in klein — die Beschreibung ist die Spalte, die den
     Platz braucht, Name und Kurzwort geben ihn her. */
  .stack-layout { grid-template-columns: 180px minmax(0, 1fr); gap: var(--r-5); }
  .stack-row { grid-template-columns: 190px minmax(0, 1fr) 130px; gap: 20px; }
  .stack-out > div { grid-template-columns: 240px minmax(0, 1fr); gap: 20px; }
  .stack-out--eng > div { grid-template-columns: 170px minmax(0, 1fr); gap: 20px; }

  /* Kolophon, Lesen, Ehrenamt: dasselbe Prinzip — die Spalte mit dem Satz
     behält ihre Breite, Stichwort, Titel und Datum geben sie her. */
  .spec { grid-template-columns: 130px minmax(0, 1fr); }
  .read-row { grid-template-columns: 240px minmax(0, 1fr); gap: 22px; }
  .duty { grid-template-columns: 130px minmax(0, 1fr); gap: 22px; }
  .bridge > div { grid-template-columns: 100px 200px minmax(0, 1fr); gap: 20px; }

  /* Artikel: auch die schmalere 240-px-Spalte trägt nicht mehr weit — bei
     1001 px blieben dem Satzspiegel noch rund 390 px. Die Seitenspalte rückt
     deshalb unter den Artikel. Das Verzeichnis bleibt dort weg: hinter dem
     Text gesprungen wird nicht mehr, dafür klappt .toc-mobile über dem Text
     auf. */
  .article-layout--seite { grid-template-columns: 210px minmax(0, var(--measure-article)); gap: 64px; }
  .article-side {
    grid-column: 2;
    position: static;
    padding-top: 0;
    margin-top: var(--r-5);
    border-top: 1px solid var(--border-default);
  }
  .article-side .toc, .article-side .toc__head { display: none; }
  .article-side__file { margin-top: var(--r-3); border-top: 0; padding-top: 0; }
  .toc-mobile { display: block; }
}

@media (max-width: 1000px) {
  .with-aside { grid-template-columns: 1fr; gap: var(--r-5); }
  .with-aside__main { max-width: none; }
  .portrait.portrait--wide { display: block; }
  .about-portrait, .about-offline { display: none; }
  /* Stack: die Inhaltsspalte entfällt — sie zählt nur auf, was jetzt ohnehin
     direkt untereinander steht. Die Zeile bricht wie im Mobil-Mock: Name und
     Kurzwort in eine Zeile, die Beschreibung darunter. */
  .stack-layout { grid-template-columns: 1fr; }
  .stack-toc { display: none; }
  .stack-row { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; padding: 14px 0; }
  .stack-row__art { grid-column: 2; grid-row: 1; text-align: right; }
  .stack-row__text { grid-column: 1 / -1; grid-row: 2; }
  .stack-out > div, .stack-out--eng > div { grid-template-columns: 1fr; gap: 6px; padding: 16px 18px; }
  /* Kennzahlen stehen zu viert nur breit; darunter zwei mal zwei, wie im
     Mobil-Mock. */
  .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ask { grid-template-columns: 1fr; gap: 11px; }
  .ask > div:first-child { padding-top: 0; }
  .split-300 { grid-template-columns: 1fr; gap: var(--r-4); }
  .contact-grid { grid-template-columns: 1fr; gap: var(--r-4); }

  .blog-layout { grid-template-columns: minmax(0, 1fr); gap: var(--r-5); }
  .blog-layout__main { max-width: none; }
  .blog-layout__side { position: static; }
  .article-layout { grid-template-columns: minmax(0, 1fr); gap: var(--r-3); }
  .article-side { grid-column: 1; }
  .article-gutter {
    position: static;
    text-align: left;
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    gap: 16px;
    align-items: center;
    padding: 0 0 var(--r-2);
    border-bottom: 1px solid var(--border-subtle);
    overflow-x: auto;
  }
  .article-gutter__rule { border-top: 0; padding-top: 0; }

  .cards-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .search-layout { grid-template-columns: minmax(0, 1fr); gap: var(--r-5); }
  .search-layout__main { max-width: none; }
}

/* Auch kompakt (siehe 1320 oben) braucht die Leiste mit sechs Zielen gut
   850 px. Der Umbruch liegt bei 1000: darunter zeigt die Kopfzeile
   Monogramm, Lupe und Menüknopf. Wer ein Navigationsziel ergänzt, lässt
   check_render.py über die 1001er-Breite laufen und korrigiert notfalls.
   Gegenstücke: die matchMedia-Abfrage in site.js und NAV_KANTE in
   _build/check_render.py. */
@media (max-width: 1000px) {
  /* Ab hier steht die mobile Kopfleiste — und mit ihr der kleinere Versatz des
     Seitenwechsels: „Fade plus 8 px nach oben – auf 402 px reichen 8 px."
     Gleiche Regel, später notiert, gewinnt gegen die 10 px weiter oben. */
  @keyframes seitenwechsel-ein { from { opacity: 0; transform: translateY(8px); } }

  /* Navigation wird zum Menü, die Wortmarke zum Monogramm */
  .site-nav { display: none; }
  .site-tools { display: flex; }
  .nav-toggle { display: flex; }
  .site-header { height: 52px; padding: 0 10px 0 20px; gap: 9px; }
  .site-header > .np-logo--header { display: none; }
  .np-mark--head { display: inline-flex; }
}

/* Alles Übrige bricht weiter bei 900 um — die Kopfzeile ist der einzige
   Teil, der früher Platz braucht. */
@media (max-width: 900px) {
  .container { padding: 0 20px; }
  .site-footer { padding: var(--r-3) 20px; }

  .cards-3 { grid-template-columns: 1fr; }
  .expectations { grid-template-columns: 1fr; gap: var(--r-3); }
  .now-split { grid-template-columns: 1fr; gap: var(--r-3); }

  .author { grid-template-columns: 1fr; gap: var(--r-2); }
  .licence { grid-template-columns: 1fr; gap: var(--r-2); }
  .post-nav { grid-template-columns: 1fr; }
  .post-nav a + a, .post-nav__next { grid-column: auto; text-align: left; }
  .search-box { flex-wrap: wrap; padding: 10px 14px; }
  .search-box input { height: auto; min-height: var(--hit-min); }
  .search-box__hint { display: none; }
  .scopes { margin-left: 0; }

  /* Lange Linktexte müssen hier umbrechen dürfen — nowrap schob sie sonst
     über den rechten Rand hinaus. */
  .more-link { white-space: normal; }

  .fields > div { grid-template-columns: 1fr; gap: 4px; }
  /* Mobil: eine durchgehende Linie links, Datum über der Rolle. */
  .timeline { border-left: 1px solid var(--border-default); padding-left: 16px; }
  .timeline > div { position: relative; grid-template-columns: 1fr; gap: 6px; padding-bottom: 22px; }
  .timeline__body { position: static; border-left: 0; padding-left: 0; }
  .timeline__body::before { left: -21px; width: 9px; height: 9px; }
  .timeline__when { padding-top: 0; }
  .edu > div { grid-template-columns: 1fr; gap: 5px; }
  /* Kolophon: Stichwort über die Angabe. Die getönte Fläche entfällt dabei —
     sie trennt zwei Spalten, nicht zwei Zeilen. */
  .spec { grid-template-columns: 1fr; }
  .spec__k { background: none; border-bottom: 0; padding: 13px 16px 0; }
  .spec__v { padding: 4px 16px 13px; }
  /* Lesen, Ehrenamt: Titel, Datum und Rolle stehen über dem Satz. */
  .read-row { grid-template-columns: 1fr; gap: 7px; padding: 15px 0; }
  .duty { grid-template-columns: 1fr; gap: 8px; padding: 18px 0; }
  .duty__when { padding-top: 0; }
  .bridge > div { grid-template-columns: 1fr; gap: 6px; padding: 15px 17px; }
  .creds { grid-template-columns: 1fr; gap: 12px; }
  .cred { padding: 18px; }
  .principles > div { grid-template-columns: 1fr; gap: 4px; }
  .setup__grid { grid-template-columns: 1fr; }
  .setup__grid > div:nth-child(odd) { padding-bottom: 0; border-bottom: 0; }
  .np-post-read { margin-left: 0; }
  .defs > div { flex-direction: column; gap: 4px; }
  .empty-state { padding: 36px 20px; }
}

@media (max-width: 480px) {
  .actions .np-btn, .actions > a { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  /* Seitenwechsel „ohne Fade, sofort". Zuerst gar keiner — @view-transition
     darf in einer Bedingung stehen. Falls ein Browser die Verschachtelung
     überliest, bleibt der Wechsel an, endet aber im nächsten Bild: ohne
     Animation an Gruppe und Abbildern wartet er auf nichts. Den
     Universalselektor darunter sehen die Pseudoelemente nicht. */
  @view-transition { navigation: none; }
  ::view-transition-group(root), ::view-transition-group(kopf) { animation-duration: 0s; }
  ::view-transition-old(root), ::view-transition-old(kopf) { animation: none; opacity: 0; }
  ::view-transition-new(root), ::view-transition-new(kopf) { animation: none; }
  .ladebalken { display: none; }

  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
  html { scroll-behavior: auto; }
}

/* Gedruckt ist immer hell — dunkle Vollflächen kosten Toner. */
@media print {
  .site-header, .mobile-menu, .theme-switch, .skip, .nav-toggle { display: none !important; }
  body { background: #fff; color: #1F2733; }
  .card, .np-card, .defs > div, .steps > div { border-color: #DEE2E8; }
}
