/* ============================================================================
   GENERIERT - NICHT VON HAND EDITIEREN (#431, Gestalt-Schicht #557)
   Brand: roughly
   Quelle (SoT): web-engine/assets/blog.css (geteilte Schicht: Struktur+Rhythmus)
               + web-engine/brands/roughly/blog-tokens.css (Token-Bruecke)
               + web-engine/brands/roughly/blog-gestalt.css (die Handschrift)
               + web-engine/brands/roughly/blog-overrides.css (optional, laedt zuletzt)
   Neu erzeugen: python web-engine/tools/sync_blog_css.py
   Drift-Check:  python web-engine/tools/sync_blog_css.py --check
   Quell-Hash: 1e82a5817d75
   ============================================================================ */

/* ⚠ NICHT ableitbar aus dem Manifest: --blog-sticky-top */
/* roughly Token-Bruecke — GENERIERT (#552) aus
   brand-engine bzw. Kunden-Akte: assets/manifest.yaml `colors:`/`fonts:`.
   Neu erzeugen: python web-engine/tools/blog_tokens.py generiere roughly --schreiben
   Pruefen:      python web-engine/tools/blog_tokens.py pruefe roughly
   Gescoped auf .post-layout, damit nichts in die Site-Styles leckt.
   Der @import oben laedt die Marken-Schriften auch auf ALT-Posts, deren
   eingebackener <head> sie nicht anfordert (#611, ohne Republish). */
@import url('https://fonts.googleapis.com/css2?family=Onest:wght@400;700;800;900&family=Onest:wght@400;500;600&family=JetBrains+Mono:wght@400;500;700&display=swap');

.post-layout{
  --accent-tint:var(--accent-soft);
  --body:var(--ink-2);
  --gutter:var(--s5);
  --muted:var(--ink-3);
  --rule:var(--line);
  --rule-strong:var(--line-strong);
  --font-head:'Onest',sans-serif;
  --font-body:'Onest',sans-serif;
  --font-mono:'JetBrains Mono',monospace;
}

/* ============================================================================
   BLOG.CSS — GETEILTE BLOG-SCHICHT (SoT, web-engine · #431)
   ============================================================================
   Die EINE Wahrheit fuer das Blog-Post-Layout aller Brand-Sites (Blueprint #422,
   auf Seonar bewiesen). Die Engine (seo-engine/engine/publish.py) emittiert das
   Markup brand-agnostisch; diese Datei ist die Web-Schicht dazu.

   VERTEILUNG: Sites halten GENERIERTE Kopien (<Site>/assets/blog.css) =
   Header + Brand-Token-Bruecke (web-engine/brands/<slug>/blog-tokens.css) + diese Datei.
     Neu erzeugen: python web-engine/tools/sync_blog_css.py
     Drift-Check:  python web-engine/tools/sync_blog_css.py --check

   TOKEN-VERTRAG (was diese Schicht von der Site erwartet — nativ oder via Bruecke,
   Bruecke gescoped auf .post-layout, damit nichts in die Site-Styles leckt):
     Farben:  --accent --accent-dark --accent-soft(Tint-Hintergrund!) --accent-tint
              --ink --body --muted --paper --rule --rule-strong
     Fonts:   --font-head --font-body --font-mono
     Layout:  --gutter
   ============================================================================ */

/* ============================================================================
   ARTIKEL-BASIS-TYPO (#431 aus dem Post-Inline-<style> des Seonar-Blueprints gehoben)
   Die Grund-Typografie des Engine-Markups (build_article_html): Hero/Meta/Titel/Lead
   + Body-Fluss (p/h2/a/Listen/blockquote) + Doktrin-Elemente Pull-Quote ([!PULL]) und
   MERKEN-Box ([!MERKEN]). Vorher trug jeder Post sie im eigenen <style>-Block (Donor-
   Vererbung) — neue Brands hatten sie damit NICHT. Seonar-Alt-Posts tragen sie noch
   doppelt inline (identische Werte, harmlos; Entschlackung = spaeterer Republish).
   ============================================================================ */
.article__hero{padding:40px 0 48px;text-align:left}
/* #559 LESBARKEITS-REGEL DIESER SCHICHT (Wurzel-Fix, gemessen ueber alle 11):
   Die geteilte Schicht faerbt TEXT nie mit einer Signal- oder Dekor-Farbe der Marke.
   Sie nutzt ausschliesslich ink-abgeleitete Toene (ink, body, oder eine Mischung aus
   ink und paper) — die sind per Definition lesbar, weil ink die Textfarbe AUF paper ist.
   Wer einen anderen Ton will, deklariert ihn in web-engine/brands/<slug>/blog-gestalt.css.

   WARUM (der Befund, blog_tokens.py status vor diesem Fix): --accent ist ein SIGNAL,
   keine Textfarbe. Als Textfarbe auf paper gemessen: slf 1.16 · hypnosolve 1.53 ·
   mentivo 2.65 · seonar 3.77 — vier von elf Brands mit unlesbaren Fliesstext-Links.
   Dasselbe bei --muted (dekorativer Zweitton der Marke, als Meta-Text benutzt):
   hypnosolve 1.85 · trovely 3.15 · mut-im-kopf 3.63 · reset-box 3.65 · signex 4.44.
   Das ist kein Ton-Problem einzelner Marken, sondern eine falsche Zuweisung in DIESER
   Datei: sie hat Farben, die fuer Flaechen und Akzente gedacht sind, an Text gehaengt.

   NICHT gemacht (bewusst): die Toene der Marken nachdunkeln. blog_tokens.py haelt seit
   #552 fest, dass der Generator KEINEN Design-Entscheid ersetzt — reicht ein Ton nicht,
   entscheidet Esteban den Ton. Diese Regel hier faellt keinen Ton-Entscheid, sie nimmt
   nur die Dekor-Farben aus der Text-Rolle heraus. --muted bleibt verfuegbar.

   #560 — DIE REGEL WAR NUR ZUR HAELFTE DURCHGEZOGEN. #559 hat fuenf Stellen entfaerbt
   und SIEBEN weitere stehen lassen. Nicht aus Nachlaessigkeit, sondern weil die Suche am
   Fliesstext hing: die uebrigen sassen im Abschluss-CTA, in der rechten Sidebar und in
   den Bausteinen (Stat-Zahl, Checklisten-Haken) — Stellen, die im gerade betrachteten
   Post gar nicht vorkamen. Gemessen ueber alle 11 Brands (Token-Ebene, jedes Paar
   gerechnet statt nur die im Post sichtbaren): 23 Verstoesse ueber 6 Brands.
   Die schlimmste war der Such-Knopf: WEISSER Pfeil auf Signalflaeche, hartkodiert #fff.
   Er faellt bei SECHS Brands durch (slf 1.31 · runthesim 1.49 · hypnosolve 1.65 ·
   signalfabrik 2.73 · mentivo 3.06 · seonar 3.77) und verletzt bei slf zusaetzlich eine
   ausdrueckliche Marken-Regel (konzept.md: «Gelb + Weiss verboten»).
   LEHRE, die ueber diese Datei hinausgeht: eine Regel gilt erst, wenn sie an der VOLLEN
   Grundgesamtheit ihrer Stellen durchgezogen ist — nicht an denen, die man gerade sieht.
   Das ist Apex-Prinzip 4a (volle Grundgesamtheit) auf eine Design-Regel angewandt.

   Ab #560 gilt fuer die geteilte Schicht zusaetzlich: auch eine FLAECHE, die Text traegt,
   wird aus ink/paper gebaut, nicht aus dem Akzent. Der Akzent bleibt fuer Kanten, Raender,
   Flaechen OHNE Text und die Brand-Gestalt. */
.article__meta{display:flex;gap:16px;flex-wrap:wrap;font-family:var(--font-mono);font-size:11px;letter-spacing:0.16em;text-transform:uppercase;color:color-mix(in srgb, var(--ink) 74%, var(--paper));font-weight:600;margin-bottom:32px}
/* Der hervorgehobene Teil der Meta-Zeile (Kategorie): strukturell staerker, nicht farbig.
   Die Farbe ist Gestalt — z.B. traegt runthesim hier sein Magenta (#559). */
.article__meta .accent{color:var(--ink);font-weight:700}
.article__title{font-family:var(--font-head);font-weight:900;font-size:clamp(36px,5vw,56px);line-height:1.05;letter-spacing:-0.03em;color:var(--ink);-webkit-text-stroke:0.4px var(--ink);margin-bottom:32px;max-width:24ch}
.article__lead{font-family:var(--font-body);font-weight:400;font-size:19px;line-height:1.6;color:var(--body);max-width:58ch;border-left:3px solid var(--accent);padding-left:18px}
.article__body{padding:40px 0 96px;font-family:var(--font-body);font-size:18px;line-height:1.75;color:var(--body)}
/* #611 (Esteban-Befund M2, bei SIGNEX/Seonar/trovely/esteban wortgleich «zu viel Whitespace
   zwischen Kurzfassung und erstem Uebertitel»): der Abstand war eine ADDITION, die niemand so
   entschieden hat. Das Padding des Koerpers (32px) und der obere Rand der ersten Ueberschrift
   (64px) stossen aneinander, ohne zu kollabieren — dazwischen liegt Padding, und Padding
   unterbricht das Margin-Collapsing. Gemessen also 96px, wo 40px gemeint waren.
   Der Reset gilt fuer JEDES erste Kind, nicht nur h2: faengt denselben Fall, wenn der Post mit
   einer Merken-Box, einer Stat-Karte oder einem Absatz beginnt.

   WARUM ER AUF `.post-layout .article__body` STEHT UND NICHT AUF `.article__body` (Nachbesserung #611):
   Als `.article__body > *:first-child` kompiliert der Reset zu Spezifitaet (0,2,0) — und JEDE
   Handschrift-Regel schlaegt ihn: `.post-layout .article__body element` ergibt (0,2,1), `.post-layout .article__body .klasse`
   ergibt (0,3,0), und bei Gleichstand gewinnt die Handschrift ohnehin, weil sie spaeter
   laedt. Gemessen wirkte der Reset darum bei 3 von 11 Marken und bei 8 nicht; genau die
   acht, bei denen Esteban den Weissraum bemaengelt hat.
   Auf `.post-layout .article__body` sind es (0,3,0) — die zusaetzliche Pseudoklasse `:first-child` zaehlt wie
   eine Klasse — und er schlaegt `.post-layout .article__body element` (0,2,1).

   ZWISCHENSTAND, DER GENAU DAS BEWEIST, warum man am Blatt misst und nicht im Kopf rechnet:
   der erste Anlauf schrieb `.post-layout .post-layout .article__body > *:first-child`, in der Absicht, die Spezifitaet
   noch weiter zu heben. Das war falsch: `.post-layout .article__body` ENTHAELT `.post-layout` bereits (es loest zu
   `.post-layout .article__body` auf), die Regel verlangte also ZWEI verschachtelte
   `.post-layout` und matchte in keinem einzigen Post. Der Reset war damit fuer alle elf
   Marken tot, und M2 war zurueck — ohne dass irgendein Gate rot geworden waere. Gefunden hat
   es der signalfabrik-Strang, per Laufzeit-Injektion gegengeprueft (mit Reset 40px, ohne
   88px). Eine hoehere Spezifitaet nuetzt nichts, wenn der Selektor nichts trifft.

   Das ist bewusst die EINZIGE Stelle, an der die Basis die Handschrift ueberstimmt, und sie
   ist es zu Recht: dass das erste Element im Fliesstext-Bereich seinen oberen Rand auf das
   Container-Padding addiert, ist keine Gestaltungs-Entscheidung, die eine Marke treffen
   wollen koennte — es ist immer falsch, in jeder Marke, auf jedem Seitentyp. Alles andere am
   Rhythmus (wie WEIT die Ueberschriften atmen) bleibt Sache der Handschrift; sie kann es
   ueber `gestalt_abweichungen:` sogar deklariert abweichend halten. */
.post-layout .article__body > *:first-child{margin-top:0}
/* #611 (derselbe Befund, zweite Haelfte — Seonar nennt ihn MITTEN im Text, an zwei
   Zwischentiteln): 64px oberer Rand bei 32px Schriftgrad sind das Doppelte dessen, was der
   Rhythmus traegt. Zwischen Absatz und Ueberschrift kollabieren die Raender zu max(24, 64),
   der Leser sieht also 64px Leere und verliert den Zusammenhang zum Abschnitt darueber.
   48px = 1.5x Schriftgrad; die Ueberschrift bleibt klar abgesetzt (20px darunter), ohne dass
   der Text in Inseln zerfaellt. */
.article__body h2{font-family:var(--font-head);font-weight:900;font-size:32px;line-height:1.15;letter-spacing:-0.025em;color:var(--ink);-webkit-text-stroke:0.35px var(--ink);margin:48px 0 20px}
.article__body p{margin-bottom:24px}
.article__body strong{color:var(--ink);font-weight:700}
/* #557: `text-decoration:none` ist hier PFLICHT, nicht Geschmack. Diese Schicht zeichnet die
   Link-Linie selbst als `border-bottom` (damit sie in Akzentfarbe und Staerke steuerbar ist);
   die Site-Unterstreichung kam ungefragt dazu -> gemessen ZWEI Linien unter jedem Fliesstext-
   Link bei 8 von 11 Brands. Eine Linie, und zwar die deklarierte. */
/* #559: KEINE Farbe hier (Lesbarkeits-Regel oben). Der Link ist strukturell erkennbar —
   staerkeres Gewicht + eine deklarierte Linie in der eigenen Textfarbe. Die Handschrift
   (Akzent-Unterstreichung, Markierung, Ink-auf-Gelb) kommt aus der Brand-Gestalt. */
/* #611: die Kurzfassung gehoert MIT in die Link-Rolle. Der Lead sitzt im Artikel-Kopf, also
   ausserhalb des Fliesstext-Bereichs, und war damit von KEINER Schicht gedeckt: weder von der
   Basis (die auf `.article__body`, also den Koerper, zielt) noch von den Handschriften (die dieselbe
   Grenze erben). Gemessen am signalfabrik-Blatt ueber alle vier Posts: der Link in der
   Kurzfassung fiel auf die nackte Browser-/Site-Unterstreichung zurueck, waehrend derselbe
   Link zwei Absaetze weiter unten die Marken-Linie trug. Das ist Estebans M7-Befund im
   Wortlaut — «der Link ist eine andere Farbe wie normalerweise, diese Unterschreibung» —, und
   er betraf ALLE Marken, nicht nur die eine, an der er ihn gesehen hat.
   `.article__lead` ist typ-eigenes Schalen-Markup (eine Landing-Page hat keine Kurzfassung);
   ein eigener Platzhalter dafuer waere Vorrat, solange es genau einen Seitentyp mit Lead gibt
   (Apex Prinzip 1). Kommt der zweite, wird daraus ein `@lead`. */
.article__body a, .post-layout .article__lead a{color:inherit;font-weight:600;text-decoration:none;border-bottom:1px solid color-mix(in srgb, currentColor 42%, transparent);transition:border-color .2s}
.article__body a:hover, .post-layout .article__lead a:hover{border-bottom-color:currentColor}
.article__body ul, .article__body ol{margin:0 0 24px 24px;padding:0}
.article__body ul li, .article__body ol li{padding-left:8px;margin-bottom:8px}
.article__body ul{list-style:disc}
.article__body ol{list-style:decimal}
.article__body blockquote{margin:32px 0;padding:24px 28px;background:var(--accent-soft);border-left:3px solid var(--accent);font-style:italic;font-size:17px;line-height:1.6}
.article__body blockquote p:last-child{margin-bottom:0}
/* Pull-Quote ([!PULL], Doktrin) — #559: Farbe raus (Lesbarkeits-Regel oben).
   accent-dark stand hier als Textfarbe: slf 1.46 auf Creme, praktisch unlesbar.
   ink ist der strukturelle Default; die Handschrift kommt aus der Brand-Gestalt. */
.post-pull{font-family:var(--font-head);font-weight:900;font-size:26px;line-height:1.3;letter-spacing:-0.02em;color:var(--ink);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:28px 0;margin:40px 0;text-align:center}

/* ----------------------------------------------------------------------------
   MERKEN-Box ([!MERKEN], Doktrin) — STRUKTUR + RHYTHMUS, BEWUSST KEIN LOOK (#557)
   ----------------------------------------------------------------------------
   ESTEBAN-DIREKTIVE #557: jede Brand bekommt eine EIGENE, dedizierte Gestalt —
   kein geteilter Look, auch kein Katalog zum Auswaehlen. Begruendung: solange die
   geteilte Schicht einen Default-Look liefert, sieht jede Brand ohne eigene Gestalt
   gleich aus, und genau das war der #552-Befund («alle sehen gleich aus»).
   Darum steht hier nur noch, was die Box zum Element macht:
     - position:relative  -> Anker fuer ein evtl. absolut gesetztes Etikett
     - content:var(--label-merken) -> DASS ein Etikett moeglich ist; der TEXT ist
       brand-eigen (und damit auch sprach-faehig, D5). Ist die Variable nicht
       deklariert, wird gar kein Etikett erzeugt — ein lautes, sichtbares Fehlen
       statt eines stillen deutschen Defaults auf einer englischen Lane.
     - margin-bottom:0 am letzten Absatz -> Lesefluss
   Flaeche, Kante, Radius, Polsterung, Typografie und die Etikett-Gestalt leben in
   web-engine/brands/<slug>/blog-gestalt.css.
   Waechter: python web-engine/tools/blog_gestalt.py status
   ---------------------------------------------------------------------------- */
.post-highlight{position:relative;margin:36px 0}
.post-highlight::before{content:var(--label-merken)}
.post-highlight p{margin-bottom:0}
@media(max-width:900px){
  .article__hero{padding:48px 0 32px}
  .article__body{padding:16px 0 64px;font-size:17px}
  .article__body h2{font-size:26px;margin:48px 0 16px}
  .post-pull{font-size:21px}
}

/* ============================================================================
   BLOG-MERKEN-BOX (#419 als Float-Randnotiz; #422 zurück auf VOLLE BREITE, Esteban)
   Die [!MERKEN]-Box läuft im Lesefluss, volle Breite, links. Der #419-Float-Aside quetschte
   den Body rechts daneben und wirkte "nach rechts geschoben" (Esteban #422).
   Hier NUR Rhythmus + die NEUTRALISIERTE Alt-Klasse .post-highlight--aside (bestehende Posts
   tragen --aside noch im HTML -> so rendern auch sie voll-breit statt gefloatet).
   #557: die Polsterung ist von hier weg — sie ist Gestalt, nicht Rhythmus, und gehoert in
   web-engine/brands/<slug>/blog-gestalt.css (sonst haette eine Brand ihre eigene Polsterung
   gegen einen geteilten Wert durchsetzen muessen).
   ============================================================================ */
.article__body .post-highlight{clear:both;margin:36px 0}
.article__body .post-highlight--aside{float:none;width:auto;max-width:none;margin:36px 0}

/* Blog-Hero-Cover (#419, t-0609): brand-Cover als Banner oben im Artikel (zugleich og:image) */
/* #552: KEIN aspect-ratio hier. Die Zahl 1200/630 war eine KOPIE des OG-Formats und wurde
   falsch, als das Muster-System (#526) Titelbilder in 1536x1024 zu liefern begann — object-fit
   ist per Default `fill`, also wurde jedes Cover ~27% in die Breite gestreckt (alle 11 Brands,
   jeder Post). Ein Format gehoert NICHT in die CSS: `width:100%` + `height:auto` uebernimmt das
   echte Verhaeltnis der Datei, welches Format auch immer kommt (Apex Prinzip 3, eine Wahrheit).
   Gegen Layout-Sprung liefert publish.py die ECHTEN Masse als width/height-Attribute mit.
   object-fit:cover bleibt als Netz, falls eine Site-Regel doch einmal eine Hoehe erzwingt. */
.article__cover{width:100%;height:auto;object-fit:cover;border-radius:12px;border:1px solid var(--rule);margin-bottom:36px;display:block}

/* ============================================================================
   BLOG-GRAFIKEN (#419, t-0609) — brand-stilige In-Content-Visuals (grafik.py)
   split-bar = SVG (Proportion); stat + checkliste = HTML (Text bleibt KI-extrahierbar).
   ============================================================================ */
.article__body .post-figure{clear:both;margin:40px 0}
.article__body .post-figure svg{border:1px solid var(--rule,#e2e8f0);border-radius:10px;background:var(--paper,#fff);padding:24px 26px}
.article__body .post-figure figcaption{margin-top:12px;font-size:13px;line-height:1.55;color:color-mix(in srgb, var(--ink) 74%, var(--paper));font-style:italic}
/* stat-card: grosse Zahl + Kontext + Quelle */
.article__body .post-stat{display:grid;grid-template-columns:auto 1fr;gap:24px;align-items:center;border:1px solid var(--rule);border-left:4px solid var(--accent);border-radius:0 10px 10px 0;background:var(--accent-soft);padding:24px 28px}
/* #560 Lesbarkeits-Regel: accent-dark raus. Die Zahl ist der groesste Text des ganzen
   Bausteins; als Signalfarbe gemessen slf 1.46 und hypnosolve 1.72 auf ihrem Papier.
   Wirkung kommt hier aus GROESSE und Gewicht, nicht aus Farbe — und wer die Zahl farbig
   will, faerbt sie in seiner blog-gestalt.css mit einem Ton, den er gemessen hat. */
.article__body .post-stat__num{font-family:var(--font-head);font-weight:900;font-size:clamp(40px,6vw,60px);line-height:1;letter-spacing:-0.03em;color:var(--ink)}
.article__body .post-stat__label{font-weight:700;color:var(--ink);margin:0 0 6px}
.article__body .post-stat__ctx{font-size:15px;line-height:1.55;color:var(--body);margin:0}
.article__body .post-stat__src{display:block;margin-top:10px;font-family:var(--font-mono);font-size:11px;letter-spacing:0.04em;color:color-mix(in srgb, var(--ink) 74%, var(--paper))}
.article__body .post-stat figcaption{grid-column:1 / -1}
/* branded Checkliste: Akzent-Haken statt Bullet */
.article__body .post-checkliste{border:1px solid var(--rule);border-radius:10px;background:var(--paper);padding:24px 28px}
.article__body .post-checkliste__titel{font-family:var(--font-head);font-weight:900;font-size:19px;color:var(--ink);margin:0 0 14px}
.article__body .post-checkliste__list{list-style:none;margin:0;padding:0}
.article__body .post-checkliste__list li{position:relative;padding:9px 0 9px 32px;border-top:1px solid var(--rule);font-size:16px;line-height:1.55;color:var(--body)}
.article__body .post-checkliste__list li:first-child{border-top:none}
/* #560: der Haken ist ein Glyph, also Text — er faellt unter dieselbe Regel (slf 1.16,
   hypnosolve 1.53, mentivo 2.65). Ein Haken, den man nicht sieht, erfuellt seinen Zweck
   nicht; die farbige Fassung gehoert in die Brand-Gestalt. */
.article__body .post-checkliste__list li::before{content:"✓";position:absolute;left:4px;top:9px;color:var(--ink);font-weight:900}
@media(max-width:640px){
  .article__body .post-stat{grid-template-columns:1fr;gap:10px}
}

/* ============================================================================
   BLOG-TABELLE (#422) — harte Regeln statt Inline-Style-Zufall.
   Kopfzellen brechen NICHT um (Esteban: "über" landete auf einer eigenen Zeile). Konsistenter
   Rhythmus + Rahmen. Neue Posts sind klassen-basiert (.post-table) -> diese Regeln greifen voll;
   der Content-Auftrag hält Tabellen-Header kurz, damit nowrap auf Desktop nie überläuft.
   ============================================================================ */
/* #704 (Esteban, am gerenderten Blatt gemessen): «gewisse tabellen ueberlaufen, das sieht
   nicht gut aus». Der #621-Scroll-Fix darunter existierte, sass aber NUR in
   `@media(max-width:640px)`. Ueber 640 px gab es weiterhin keinen Ort, an dem die Breite haette
   aufhoeren koennen. Gemessen an den zwoelf Studien-Posts, Textblock 720 px:
     Desktop 1440 -> 13 von 29 Tabellen ragen aus dem Text, bis +701 px (Umzug, 1421 px breit)
     Tablet  900 -> 24 von 29, bis +749 px
     Handy   390 ->  0 (dort griff der Fix)
   Der Befund von #621 war also nie mobil-spezifisch, nur mobil AUFGEFALLEN. Der Scroll-Bereich
   gilt darum jetzt in JEDER Breite; der Media-Query darunter haelt nur noch, was wirklich
   handy-spezifisch ist (Schriftgrad, Polsterung). */
.article__body .post-table,.post-layout .article__body .post-table{
  width:100%;border-collapse:collapse;margin:36px 0;font-size:16px;
  display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;
  overscroll-behavior-x:contain;scrollbar-width:thin}
.article__body .post-table thead,.article__body .post-table tbody,
.post-layout .article__body .post-table thead,.post-layout .article__body .post-table tbody{display:table;width:100%}
/* `min-width:max-content` haelt breite Tabellen lesbar, statt die Spalten zusammenzuquetschen —
   aber es verbietet auch den Umbruch, und dann wird eine SCHMALE Tabelle unnoetig breit.
   Gemessen nach dem ersten Anlauf, Textblock 720 px: die zweispaltige «Was die Messung zeigt /
   Was sie nicht zeigt» wurde 1036 px, weil beide Zellen ganze Saetze tragen; die vierspaltige
   Auswertung 799 px. Beide passen ohne die Regel bequem, weil ihr Text umbrechen darf.
   Ab fuenf Spalten kippt es: dort ist Quetschen schlimmer als Scrollen. */
.article__body .post-table:has(th:nth-child(5)) thead,.article__body .post-table:has(th:nth-child(5)) tbody,
.post-layout .article__body .post-table:has(th:nth-child(5)) thead,
.post-layout .article__body .post-table:has(th:nth-child(5)) tbody{min-width:max-content}
/* Ab vier Spalten darf der Kopf umbrechen. #422 («"ueber" landete auf einer eigenen Zeile»)
   galt schmalen Tabellen mit kurzen Koepfen; dort bleibt `nowrap`. Bei vier und mehr Spalten
   ist `nowrap` dagegen der Breiten-Treiber, der die Tabelle ueberhaupt erst aus dem Textblock
   schiebt. `:has()` unterscheidet die beiden Faelle, ohne dass ein Autor etwas auszeichnen muss. */
.article__body .post-table:has(th:nth-child(4)) th,
.post-layout .article__body .post-table:has(th:nth-child(4)) th{white-space:normal}
/* #611 (Esteban-Befund M6, RunTheSim woertlich: «die Uebertitel von der Tabelle sind zu wenig
   markant, man checkt gar nicht, was das Uebertitel sind»): der Kopf unterschied sich vom
   Koerper nur durch `font-weight:700` — dasselbe Gewicht, das im Fliesstext jedes `strong`
   traegt. Bei einer Tabelle mit kurzen Zellen ist das kein Unterschied, den ein Auge im
   Ueberfliegen findet.
   Die Auszeichnung ist bewusst STRUKTURELL und farb-frei (Versalien + Sperrung + kraeftigere
   Linie), nicht farbig: Farbe waere Handschrift der Marke, und die Basis-Schicht faerbt seit
   der Lesbarkeits-Regel #559 keinen Text mehr. Dieselbe Auszeichnung, die der Quellen-Block
   schon traegt — ein Rezept, nicht zwei. Eine Marke kann sie in ihrer Handschrift jederzeit
   ueberschreiben. */
.article__body .post-table th{white-space:nowrap;text-align:left;padding:11px 14px;border-bottom:2.5px solid var(--rule-strong);font-family:var(--font-head,inherit);font-size:12.5px;letter-spacing:0.08em;text-transform:uppercase;font-weight:700;color:var(--ink)}
.article__body .post-table td{padding:12px 14px;border-bottom:1px solid var(--rule);vertical-align:top;line-height:1.55}
.article__body .post-table tbody tr:last-child td{border-bottom:none}
/* #621 (Esteban, an mehreren Marken gesehen): «wenn wir Tabellen machen in einem Blog-Post, egal
   auf welchem Brand, dann laufen die auf mobile ueber den Seitenrand.» Gemessen am Live-Post
   seo-audit-lesen-verstehen bei 390 px Viewport: die Tabelle ist 468 px breit, ihre rechte Kante
   liegt bei 492 px — 102 px jenseits des Rands. Die Zeile darunter (`white-space:normal`, #422)
   erlaubt zwar Umbruch, aber drei Spalten mit je 28 px Polsterung haben eine harte Mindestbreite,
   und der Elternteil `.article__body` traegt `overflow-x: visible`. Es gab also gar keinen Ort,
   an dem die Breite haette aufhoeren koennen.
   Die Tabelle bekommt darum einen EIGENEN Scroll-Bereich: sie darf breiter sein als die Spalte,
   nur die Seite darf es nicht. `display:block` am Rahmen macht ihn scrollbar, `display:table` an
   Kopf und Koerper haelt die Spalten trotzdem ausgerichtet (ohne das zerfaellt das Raster).
   Bewusst in der GETEILTEN Schicht: der Befund gilt laut Esteban markenuebergreifend, und
   `assets/blog.css` ist der eine Ort, den jeder Brand-Deploy mitschiebt (SHARED_KERN). */
/* SPEZIFITAET (#621, im Live-Test aufgefallen): der Selektor traegt zusaetzlich `.post-layout`.
   Grund: signex setzt in seiner Handschrift `.post-layout .article__body .post-table{… overflow:
   visible}` (ein Deko-Reset: border/radius/shadow raus). Diese Regel hat DREI Klassen und steht
   ausserhalb jedes Media-Query — sie schlaegt eine zweiklassige Regel also immer. Ergebnis beim
   ersten Anlauf: `display:block` griff, `overflow-x:auto` nicht, und die Tabelle lief SCHLIMMER
   ueber als vorher (Dokument 989 px bei 390 px Fenster). Mit derselben Klassen-Zahl gewinnt im
   Media-Query wieder die Basis, ohne dass eine Marken-Regel angefasst werden muss. */
/* #704: der Scroll-Bereich selbst steht jetzt oben und gilt in jeder Breite. Hier bleibt nur,
   was wirklich handy-spezifisch ist: kleinerer Grad, engere Polsterung, und `white-space:normal`
   fuer JEDEN Kopf (nicht erst ab vier Spalten, weil auf 342 px auch drei Spalten nicht passen). */
@media(max-width:640px){
  .article__body .post-table,.post-layout .article__body .post-table{font-size:15px;margin:28px 0}
  /* Auf 342 px Textbreite quetscht JEDE Tabelle, auch die zweispaltige. Hier gilt max-content
     darum wieder fuer alle: scrollen ist auf dem Handy die richtige Antwort. */
  .article__body .post-table thead,.article__body .post-table tbody,
  .post-layout .article__body .post-table thead,.post-layout .article__body .post-table tbody{min-width:max-content}
  .article__body .post-table th,.post-layout .article__body .post-table th{white-space:normal}
  .article__body .post-table th,.article__body .post-table td,
  .post-layout .article__body .post-table th,.post-layout .article__body .post-table td{padding:10px 12px}
}

/* ============================================================================
   BLOG-TYPOGRAFIE + LISTEN (#422) — kein einzelnes Wort allein auf der letzten Zeile.
   Esteban: "immer ein Wort auf der zweiten Zeile, sieht mega unschön aus" = Orphan/Widow.
   text-wrap:pretty bricht Absätze UND Bullets so um, dass die letzte Zeile nie ein Einzelwort
   ist (vererbte Property -> greift auf alle Body-Elemente). Plus: Body-Listen atmen (.post-list).
   ============================================================================ */
.article__body{text-wrap:pretty}
.article__body ul.post-list, .article__body ol.post-list{margin:0 0 28px 22px;padding:0}
/* balance (statt pretty) auf den kurzen Bullets: gleicht die Zeilen gleich lang aus -> nie ein
   Einzelwort auf der letzten Zeile (pretty allein liess "Fach-Jargon." noch orphan stehen). */
.article__body ul.post-list li, .article__body ol.post-list li{margin-bottom:14px;padding-left:6px;line-height:1.65;text-wrap:balance}
.article__body ul.post-list li:last-child, .article__body ol.post-list li:last-child{margin-bottom:0}

/* ============================================================================
   BLOG-LAYOUT 3-SPALTIG + SIDEBAR (#422) — Struktur der letsreachsuccess-Referenz.
   Artikel-Hauptspalte (max ~720px) + linke TOC-Leiste + rechte, sticky Sidebar (Suche +
   Verwandte Beiträge + faktische Betreiber-Info). Engine emittiert das Markup brand-agnostisch
   (publish.build_article_html + blog_sidebar_html); diese Klassen sind die Web-Schicht
   (seit #431 GETEILT: SoT web-engine/assets/blog.css, Kopien pro Site generiert).
   Mobile: Sidebar stapelt UNTER den Artikel.
   ============================================================================ */
/* 3-spaltig (#422, Esteban: rechts war zu viel los): LINKE TOC-Leiste (Navigation) + Artikel (Inhalt) +
   rechte Sidebar (Meta). Klare Hierarchie, beide Leisten sticky. Unter 1080px -> einspaltig, TOC oben. */
/* #552 KRITISCH — `color` als Basis der Scope-Wurzel. Vorher fehlte sie, und damit erbte JEDES
   Element, das blog.css nicht ausdruecklich einfaerbt (TOC, Sidebar-Bloecke, Blockquote,
   Pull-Zitat), die Textfarbe der SITE. Auf dunkel gestalteten Sites ist das ein helles Creme —
   und das landete auf dem hellen --paper des Artikels: gemessenes Kontrastverhaeltnis 1.00 bei
   mentivo (4 Elemente) und reset-box, 1.15 bei signalfabrik. Unsichtbarer Text auf zwei
   Kunden-Sites. Die Token-Bruecken waren dabei korrekt — sie wurden nur von der Vererbung
   umgangen. Eine Scope-Wurzel, die Tokens setzt, muss auch die Basis-Farbe setzen, sonst
   regieren die Tokens nur dort, wo zufaellig eine explizite Regel steht. */
/* #618 KRITISCH — die ANDERE Haelfte desselben Satzes: auch die FLAECHE.
   Der #552-Fix setzte die Tinte (`color:var(--body)`) und liess die Flaeche offen. Damit war
   die Paarung immer noch dem Zufall ueberlassen: die Tinte kam aus der Token-Bruecke, der Grund
   kam von der Spender-Site. Solange beide hell sind, faellt nichts auf. Bei den zwei Marken mit
   DUNKLER Site brach es in beide Richtungen, live gemessen am DOM (#618):
     signalfabrik  --body #0a0d0c (dunkel) auf `body.halle` = linear-gradient(#090c0a …)  -> 1.01
     mentivo       --body #F4EEE2 (hell)   auf `div.blatt`  = #F4EEE2 (die Site malt hell,
                                                              die Bruecke erwartet #2D2D2B)  -> 1.00
   Beide Male stimmten die Token; es fehlte, dass die Schicht ihr eigenes Papier auch AUFTRAEGT.
   Regel ab hier: **wer die Tinte setzt, setzt die Flaeche mit.** Danach ist die Lesbarkeit eine
   Eigenschaft der Blog-Schicht und keine Eigenschaft des Donors mehr — genau das ist der Punkt
   einer geteilten Schicht. Bewacht: `blog_mappe.py` misst gerendert ueber ALLE Marken. */
/* #557: die LESESPALTE hat Vorrang vor den Nebenspalten.
   Vorher standen 220px und 210px FIX. Das ging so lange gut, wie die Schicht die vollen
   1320px bekam — bei einem Donor, der den Artikel in eine engere Huelle wickelt, nicht mehr:
   mentivos `.blatt` ist 1116px breit, also blieben dem Text 461px, ein unlesbares Band.
   Die alte `@media(max-width:900px)`-Weiche griff nie, weil sie das FENSTER misst (1440),
   nicht den verfuegbaren Platz.
   Jetzt bekommt die Mitte ein Minimum und die Nebenspalten geben nach; `min(100%,...)`
   verhindert Ueberlauf, wenn der Platz auch dafuer nicht reicht. Brand-agnostisch: es gilt
   fuer jede Site und jeden kuenftigen Donor, ohne dass jemand eine Zahl nachpflegen muss. */
.post-layout{max-width:1320px;margin:0 auto;padding:0 var(--gutter);display:grid;
  grid-template-columns:minmax(0,220px) minmax(min(100%,600px),1fr) minmax(0,210px);
  column-gap:44px;align-items:start;color:var(--body);background:var(--paper)}
/* #729 — EINE SPALTE, WENN DIE MARKE KEINE NEBENSPALTEN FUEHRT.
   Waehlt eine Marke Inhaltsverzeichnis UND Sidebar ab (`ohne_elemente` im 0b-Wiring, erstmals
   roughly), setzt der Emitter `post-layout--solo`. Ohne diese Regel bleiben die beiden Spuren
   des Drei-Spalten-Rasters als LEERER Raum stehen: gemessen sass der Text 720px breit bei
   x=348 in einem 1320px-Raster, also sichtbar aus der Mitte geschoben — auf jeder Seite,
   auf jeder Breite. Die Marke bekommt damit eine echte, zentrierte Leseseite statt eines
   dreispaltigen Rasters mit zwei leeren Spalten.
   Der Modifikator haengt an der Element-Wahl der Marke, nicht an ihrem Namen: jede kuenftige
   Marke ohne Nebenspalten erbt ihn, ohne dass jemand eine Sonderregel schreibt. */
.post-layout.post-layout--solo{grid-template-columns:minmax(0,1fr);column-gap:0;max-width:768px}
/* #729: der Titel einer Grafik stand bis hierher als VERSALIEN im SVG-Inhalt (grafik.py rief
   `.upper()`). Damit konnte keine Handschrift ihn zurueckholen — roughlys Regeln verbieten
   Versalien mit Sperrung ausdruecklich. Die Auszeichnung liegt jetzt hier, wo sie hingehoert:
   die Basis setzt sie fuer alle (die zwoelf bestehenden Studien-Posts sehen unveraendert aus,
   weil `blog.css` bei jedem Laden frisch kommt), und eine Marke waehlt sie in ihrer Gestalt ab. */
.post-figure svg text[letter-spacing="2"]{text-transform:uppercase}
.post-main{min-width:0;max-width:720px}
.post-main .article__hero{padding-top:8px}
.post-main .article__body{padding-bottom:64px}
/* Beide Leisten oben angeheftet (#422, Esteban: passt oben besser) */
/* Sticky-Abstand als TOKEN (#557). Die 96px waren geraten: sie unterstellen, dass die Site
   entweder keinen klebenden Kopf hat oder einen niedrigeren als 96px. Bei hypnosolve ist der
   `header.site-header` selbst sticky und 125px hoch — die Spalte sass damit 29px IM Kopf
   (Esteban: «es verbaut sich oben in die Navigation»).
   Die Marke deklariert ihren Wert in IHRER HANDSCHRIFT (`<brand_home>/gestalt/elemente.css`,
   an `.post-layout`), nicht in `blog-overrides.css` — korrigiert #611. Der Wert haengt an der
   Site-Schale der Marke, nicht am Kanal Blog: eine kuenftige Landing-Page traegt dieselbe
   Navigation und erbt ihn ueber `.post-layout` automatisch mit, waehrend eine Blog-Override-Datei
   ihn nie weitergeben koennte (design-engine/ZIELARCHITEKTUR.md §1b-2). Ohne Deklaration
   bleibt es beim geratenen 96px-Default, und der ist bei keiner gemessenen Marke richtig.
   Faustregel: Hoehe des klebenden Kopfes + ~16px Luft. */
.post-toc{position:sticky;top:var(--blog-sticky-top,96px)}
.blog-sidebar{position:sticky;top:var(--blog-sticky-top,96px);display:flex;flex-direction:column;gap:24px}
/* TOC groesser (primaere Navigation), rechte Sidebar etwas kleiner (#422) */
.post-toc .sidebar-block__title{font-size:12px}
.post-toc .sb-toc a{font-size:15px}   /* #557: padding-left ist raus — es gehoert zum Marker
                                          (Balken/Punkt/Klammer) und damit in die Brand-Gestalt */
.post-toc .sb-toc li{margin-bottom:13px}
.blog-sidebar .sidebar-block__title{font-size:10px}
.blog-sidebar .sb-related a{font-size:13px}
.blog-sidebar .sb-search__form input{font-size:13px;padding:8px 10px}
.blog-sidebar .sb-betreiber__avatar{width:44px;height:44px}
.blog-sidebar .sb-betreiber__id strong{font-size:14px}
.blog-sidebar .sb-betreiber__mail{font-size:12px}
/* ----------------------------------------------------------------------------
   SIDEBAR-TITEL + INHALTSVERZEICHNIS — STRUKTUR + RHYTHMUS, KEIN LOOK (#557)
   ----------------------------------------------------------------------------
   Zweite Anwendung der Gestalt-Trennung (nach der Merken-Box). Estebans Befund: das
   «In diesem Artikel» sah bei allen 11 Brands identisch aus. Schrift, Farbe, Linien,
   Marker und Zustaende (hover/aktiv) leben ab jetzt in
   web-engine/brands/<slug>/blog-gestalt.css; hier bleibt nur, was die Navigation
   funktionieren laesst: Abstaende, Listen-Reset, Groessen-Hierarchie der zwei Spalten.
   ---------------------------------------------------------------------------- */
.sidebar-block__title{margin:0 0 12px}

/* Navigations-Links der beiden Spalten tragen KEINE Text-Unterstreichung (#557, Esteban).
   Das war ein LECK, keine Gestaltung: die Blog-Schicht sagte zur `text-decoration` nichts,
   also entschied die jeweilige Site — gemessen unterstrichen 8 von 11 Brands links UND
   rechts, und die drei sauberen waren es nur zufaellig (ihre Site-CSS schaltet es ab).
   Dieselbe Klasse wie die fehlende Basis-Farbe in #552: was der Blog-Scope nicht
   deklariert, erbt er ungefragt.
   Inhaltsverzeichnis und Sidebar sind NAVIGATION, keine Fliesstext-Links — der Zustand
   (aktiv/hover) wird ueber Farbe, Marker, Kante oder Flaeche gezeigt, das entscheidet die
   Brand-Gestalt. Eine Brand, die hier bewusst eine Linie will, setzt sie dort als
   `border-bottom` (so macht es hypnosolve) und ist damit unabhaengig von der Site. */
.sb-toc a, .blog-sidebar a{text-decoration:none}
/* Suche */
.sb-search__form{display:flex;gap:8px}
.sb-search__form input{flex:1;min-width:0;padding:10px 12px;border:1px solid var(--rule-strong);border-radius:8px;font-family:var(--font-body);font-size:14px;background:var(--paper);color:var(--ink)}
.sb-search__form input:focus{outline:none;border-color:var(--accent)}
/* #560 — der schlimmste Fund der Runde: `background:var(--accent); color:#fff`.
   Ein hartkodiertes Weiss auf einer Flaeche, deren Farbe JEDE Brand selbst bestimmt,
   kann gar nicht verlaesslich lesbar sein. Gemessen faellt es bei SECHS von elf durch
   (slf 1.31 · runthesim 1.49 · hypnosolve 1.65 · signalfabrik 2.73 · mentivo 3.06 ·
   seonar 3.77), und bei slf verletzt es zusaetzlich eine ausdrueckliche Marken-Regel.
   Der Knopf wird deshalb aus dem EIGENEN lesbaren Paar der Marke gebaut: ink-Flaeche,
   paper-Glyph. Dieses Paar ist per Definition lesbar, denn es traegt den Fliesstext.
   Wer den Akzent auf dem Knopf will, deklariert ihn in blog-gestalt.css — dort
   entscheidet ein Mensch, welcher Ton darauf lesbar ist, statt dass diese Datei es raet. */
.sb-search__form button{flex-shrink:0;width:42px;border:none;border-radius:8px;background:var(--ink);color:var(--paper);font-size:18px;font-weight:700;cursor:pointer;transition:opacity .2s}
.sb-search__form button:hover{opacity:0.82}
/* Verwandte Beiträge */
.sb-related ul{list-style:none;margin:0;padding:0}
.sb-related li{margin-bottom:14px;line-height:1.4}
.sb-related li:last-child{margin-bottom:0}
.sb-related a{color:var(--ink);font-weight:600;font-size:14px;border-bottom:1px solid transparent;transition:color .2s,border-color .2s}
/* #560: der Hover faerbte den Text in den Akzent (slf 1.16 · hypnosolve 1.53 · mentivo
   2.65 · seonar 3.77) — ausgerechnet im Moment der Interaktion wurde der Titel unlesbar.
   Jetzt bleibt die Textfarbe und die Linie kommt in der eigenen Farbe dazu. */
.sb-related a:hover{border-bottom-color:currentColor}
/* Betreiber-Info (faktisch, Tool-Frame) */
.sb-betreiber__id{display:flex;align-items:center;gap:12px;margin-bottom:10px;text-decoration:none;color:inherit}
.sb-betreiber__id:hover strong{text-decoration:underline;text-underline-offset:3px}
.sb-betreiber__avatar{width:52px;height:52px;border-radius:50%;object-fit:cover;object-position:center top;flex-shrink:0}
.sb-betreiber__id strong{font-family:var(--font-head);font-weight:900;font-size:15px;color:var(--ink);line-height:1.2}
/* #560: die Mail-Adresse stand im Akzent (slf 1.16 · hypnosolve 1.53 · mentivo 2.65 ·
   seonar 3.77). Eine Kontaktadresse ist die Stelle, an der Unlesbarkeit am teuersten ist.
   Sie erbt jetzt die Textfarbe und bleibt als Link an der Linie erkennbar. */
.sb-betreiber__mail{font-size:13px;color:inherit;font-weight:600;border-bottom:1px solid color-mix(in srgb, currentColor 42%, transparent)}
.sb-betreiber__mail:hover{border-bottom-color:currentColor}
/* Inhaltsverzeichnis (#422): Sprung-Links zu den Kapiteln (wie RunTheSim) */
.sb-toc ul{list-style:none;margin:0;padding:0}
.sb-toc li{margin-bottom:10px;line-height:1.35}
.sb-toc li:last-child{margin-bottom:0}
.sb-toc a{display:block;font-size:13.5px;transition:color .2s,border-color .2s,background-color .2s}
/* Scroll-Spy (#422): aktuell gelesenes Kapitel hervorgehoben */
/* Der AKTIVE Eintrag ist ein Zustand, kein Look: wie er sich zeigt (Farbe, Marker,
   Gewicht, Flaeche), entscheidet die Brand-Gestalt. Hier bleibt nichts. */
/* Sprung-Ziele unter der sticky Nav ausrichten + sanftes Scrollen
   (scroll-behavior steht auch in Site-CSS mancher Brands — doppelt ist harmlos) */
html{scroll-behavior:smooth}
/* #611: die 96 waren eine ZWEITE Kopie des geratenen Sticky-Defaults und folgten dem Token
   nicht. Sobald eine Marke ihren echten Wert setzt (seonar 81px bei 65px Nav-Hoehe), landete
   ein Klick im Inhaltsverzeichnis den Zwischentitel 96px tief statt 16px unter der Nav — die
   Sprungmarke zeigte auf eine Stelle, die es so nicht mehr gab. Zwei Wahrheiten ueber
   denselben Datenpunkt (Apex Prinzip 3); jetzt rechnet die Sprungmarke aus dem Token.
   OHNE Zuschlag: der Token traegt die Luft unter dem Kopf bereits (Faustregel Kopfhoehe +
   ~16px), ein zweiter Zuschlag wuerde sie verdoppeln. Am Blatt gemessen (hypnosolve, Kopf
   122px, Token 165px): mit dem rohen Token landet die Ueberschrift 43px unter der
   Kopf-Unterkante, mit Zuschlag 59px — die erste Zahl ist die gewollte. */
.article__body h2{scroll-margin-top:var(--blog-sticky-top,96px)}
@media(max-width:1080px){
  .post-layout{grid-template-columns:1fr;column-gap:0;max-width:720px}
  .post-main{max-width:none}
  .post-toc{position:static;transform:none;margin-bottom:8px}
  .blog-sidebar{position:static;transform:none;margin-top:56px;padding-top:40px;border-top:1px solid var(--rule)}
}

/* Dieselbe Weiche noch einmal — aber am verfuegbaren PLATZ statt am Fenster (#557).
   Die Media-Query oben misst das Browser-Fenster. Wickelt ein Donor den Artikel in eine
   engere Huelle (mentivo: `.blatt`, 1116px bei 1440px Fenster), feuert sie NIE, und die drei
   Spalten quetschen sich in den Rest: gemessen 145 / 600 / 145 px — Nebenspalten, die zu
   schmal sind, um zu nuetzen.
   `:has(> .post-layout)` haelt den Container-Kontext exakt am Blog-Artikel — kein anderes
   <article> der Site wird beruehrt.

   DREI STUFEN AM VERFUEGBAREN PLATZ (mittlere Stufe NEU #560, Esteban-Entscheid):
     > 1080px      drei Spalten (TOC links · Text · Sidebar rechts)
     950-1080px    ZWEI Spalten (TOC links · Text), Sidebar unter den Artikel
     < 950px       stapeln (TOC oben · Text · Sidebar unten)

   WARUM DIE MITTLERE STUFE (gemessen #560 an mentivo, Playwright, Fenster 1440):
   mentivos Kette ist `.wrap` 1180px minus 2x32px Rand = `.blatt` 1116px, minus dessen
   Innenrand 2x44px+2x1px = **1026px fuer den <article>**. Damit greift die Stapel-Stufe,
   und mentivo war die einzige Brand ohne Spalten. Drei Spalten passen dort ARITHMETISCH
   nicht: 1026 - 48 Innenabstand = 978px, davon mindestens 600px fuer den Text und 88px
   fuer zwei Zwischenraeume — fuer beide Seitenspalten blieben ~145px, exakt der in #557
   gemessene und verworfene Wert (TOC-Eintraege brechen dort auf 4-5 Zeilen).
   Zwei Spalten passen dagegen exakt: 200 + 44 + 734 = 978px, `.post-main` deckelt bei 720px.
   Bewusst brand-agnostisch statt als mentivo-Sonderfall (Esteban #557: Wurzel statt
   Einzelfall) — jeder kuenftige Donor mit engerer Huelle bekommt dasselbe, ohne dass
   jemand eine Zahl nachpflegt.
   Verworfen: mentivos Blatt fuer die Blog-Seite auf ~1400px weiten. Das Blatt ist ein
   bewusstes Gestaltungs-Element der Site; die Blog-Seite waere dann breiter als der Rest.

   Die mittlere Stufe haengt zusaetzlich an `@media (min-width:1081px)`: sie soll NUR den
   Fall «weites Fenster, enge Huelle» treffen. Ist das FENSTER selbst schmal, bleibt es
   beim bisherigen Stapeln (Zeile 287) — das Antwort-Verhalten der uebrigen zehn Brands
   aendert sich dadurch nicht. */
article:has(> .post-layout){container-type:inline-size}

@media (min-width:1081px){
  @container (min-width:950px) and (max-width:1080px){
    .post-layout{grid-template-columns:minmax(0,200px) minmax(min(100%,600px),1fr);column-gap:44px}
    .post-main{max-width:720px}
    /* Die Sidebar wandert unter den Artikel und legt ihre Bloecke NEBENEINANDER —
       als schmale Saeule waere sie auf ~978px Breite ein einsamer Streifen. */
    .blog-sidebar{
      grid-column:1 / -1;
      position:static;transform:none;
      flex-direction:row;flex-wrap:wrap;align-items:flex-start;gap:32px;
      margin-top:56px;padding-top:40px;border-top:1px solid var(--rule);
    }
    .blog-sidebar > .sidebar-block{flex:1 1 240px;min-width:0}
  }
}

@container (max-width:949.98px){
  .post-layout{grid-template-columns:1fr;column-gap:0;max-width:720px}
  .post-main{max-width:none}
  .post-toc{position:static;transform:none;margin-bottom:8px}
  .blog-sidebar{position:static;transform:none;margin-top:56px;padding-top:40px;border-top:1px solid var(--rule)}
}

/* Abschluss-CTA ([!CTA]-Block der Engine, .post-cta) — #514/E4: war NIRGENDS definiert,
   rendert sonst als nackter kleiner Absatz. Token-basiert (Brand-Farben via blog-tokens.css). */
/* #611 (Esteban-Befund M2, Seonar: «zwischen Quellen und Call to Action ist zu viel Abstand,
   der CTA kann ein bisschen hoeher»): 56px oben trennten den Abschluss vom Text, obwohl der
   Quellen-Block darueber schon eine Trennlinie plus 44px Eigenabstand mitbringt. 40px. */
.post-cta{margin:40px 0 8px;padding:28px 32px;background:var(--accent-tint,rgba(0,0,0,0.04));border:1px solid var(--accent,#0a0a0a);border-left:6px solid var(--accent,#0a0a0a);font-family:var(--font-head,inherit);font-weight:700;font-size:20px;line-height:1.5;color:var(--ink,inherit)}
/* #560: der Quellen-Block war in DIESER Datei ueberhaupt nicht deklariert — also entschied die
   jeweilige Site ueber seine Textfarbe. Genau die Leck-Klasse t-1106 («was der Blog-Scope nicht
   deklariert, erbt er ungefragt»), diesmal beim vierten Vorkommen: bei reset-box gemessen 3.41,
   unter der Schwelle. Er bekommt jetzt denselben ink-abgeleiteten Ton wie die Meta-Zeile.
   NACHTRAG im selben Lauf: mit `.article__body .post-sources` (zwei Klassen) gewann bei
   reset-box weiterhin die Site-Regel — 3.41 blieb stehen. Erst die Scope-Wurzel `.post-layout`
   davor setzt sich durch. Dieselbe Spezifitaets-Stufe, die auch die Brand-Gestalt benutzt.

   #561-BEFUND: genau dieser Nachtrag stand ausserhalb des Kommentars — der Block war eine
   Zeile darueber schon geschlossen, die Prosa danach stand nackt im Stylesheet. Der Parser
   las sie als SELEKTOR und verwarf die Regel darunter: die #560-Farbregel war nie im
   Browser. Gegen tinycss2 gemessen, der Selektor hiess woertlich «NACHTRAG im selben Lauf:
   mit .article__body .post-sources …».
   ZWEITE LEHRE, beim Reparieren selbst getreten: ein Kommentar-Ende-Zeichen IM Kommentartext
   schliesst den Block ebenfalls vorzeitig — beim Beschreiben des Fehlers also nie das Zeichen
   selbst schreiben. Beide Male meldet nichts einen Fehler; nur der Parser zeigt es. */
.post-layout .article__body .post-sources{color:color-mix(in srgb, var(--ink) 82%, var(--paper));font-size:13.5px;line-height:1.6}
.post-layout .article__body .post-sources a{color:inherit}

/* #561: die Struktur-Basis der drei entstylten Elemente. Vorher stand sie als `style=` im
   Post-HTML und war damit fuer die Brand-Gestalt unerreichbar (Inline schlaegt jede Regel) —
   eine Brand konnte nur umfaerben, nicht umformen. Hier steht bewusst NUR Rhythmus und
   Grundstruktur (Abstand, Polsterung, Aufzaehlungs-Mechanik); alles Charakterbildende
   (Kante, Flaeche, Radius, Polaritaet, Schrift) gehoert in blog-gestalt.css der Brand.
   Massstab ist die Merken-Box: geteilte Struktur, eigenes Geraet je Marke. */
.post-layout .article__body .post-sources{margin:44px 0 0;padding:14px 0 0;border-top:1px solid var(--rule)}
.post-layout .article__body .post-sources__label{font-size:10px;letter-spacing:0.14em;text-transform:uppercase;font-weight:700;margin-bottom:8px}
.post-layout .article__body .post-sources__list{margin:0;padding-left:16px;list-style:disc}
.post-layout .article__body .post-sources__item{margin-bottom:4px}
.post-layout .article__body .post-sources__item:last-child{margin-bottom:0}
/* Der CTA-Text erbt Schrift und Farbe vom Block (.post-cta), damit eine Brand mit EINER Regel
   die Polaritaet drehen kann (helles Panel <-> dunkles Panel) — genau das, was slfs Bauchbinde
   tut und was der alte Inline-Style unmoeglich machte. */
.post-layout .article__body .post-cta__text{margin:0;font:inherit;color:inherit}

/* #560: Farbe raus (Lesbarkeits-Regel). Gemessen als Akzent auf Papier: hypnosolve 1.53,
   mentivo 2.65, seonar 3.77. Der CTA-Link ist ohnehin schon strukturell hervorgehoben
   (fetter Block, Akzent-Kante links) und bleibt durch die Unterstreichung als Link kenntlich. */
.post-cta a{color:inherit;text-decoration:underline;text-underline-offset:3px}
.post-cta a:hover{text-decoration-thickness:2px}
/* #611 (Esteban-Befund M1, bei sieben von elf Marken: «kein richtiger Knopf, es ist einfach
   ein Text wo man dann darauf drueckt»). Die Basis hatte fuer den Handlungs-Slot des CTA
   (`-> [Text](Link)`, seit #566 von `next_content.md_to_html` als `.post-cta__knopf`
   gerendert) UEBERHAUPT KEINE Regel — gemessen 0 Treffer in dieser Datei. Acht der elf
   Handschriften gestalten ihn, drei nicht; eine Marke ohne Handschrift-Regel zeigte also
   einen nackten Link mit der Fliesstext-Unterlinie, und genau danach sieht ein Knopf nicht aus.

   Zwei Dinge muss die Basis leisten, und nur diese zwei:
   1. Ihn zum KNOPF machen — als Form, nicht als Farbe: eigener Block, echte Klickflaeche,
      sichtbare Kante. `currentColor` haelt das farb-neutral, damit die Lesbarkeits-Regel #559
      gilt und jede Marke ihre eigene Farbe darueberlegen kann.
   2. Ihm die LINK-LINIE nehmen. `.article__body a` zeichnet unter jeden Fliesstext-Link eine
      `border-bottom` — die traf bisher auch den Knopf und war der Grund, warum er selbst dort
      wie Text aussah, wo eine Marke ihn gestaltet hatte. Diese Regel ist spezifischer und
      loescht sie. */
.article__body .post-cta__knopf{display:inline-block;margin-top:20px;padding:13px 26px;border:2px solid currentColor;border-bottom:2px solid currentColor;font-family:var(--font-head,inherit);font-weight:700;font-size:16px;line-height:1.2;text-decoration:none;color:inherit}
/* Der Hover fuellt die Flaeche NICHT mit `currentColor` — das waere Schrift auf sich selbst
   und damit unsichtbar. Die Marke setzt eine Fuellung samt Gegenfarbe in ihrer Handschrift;
   bis dahin verstaerkt sich nur die Kante, und der Knopf bleibt in jedem Fall lesbar. */
.article__body .post-cta__knopf:hover{border-width:3px;padding:12px 25px}
@media (max-width:680px){.post-cta{padding:20px 22px;font-size:18px}}


/* ---------------- Brand-Gestalt (die Handschrift dieser Marke im Artikel;
   SoT: web-engine/brands/roughly/blog-gestalt.css) ---------------- */
/* ============================================================================================
   ROUGHLY — DIE HANDSCHRIFT DER MARKE (#729)
   ============================================================================================
   Heimat: <brand_home>/gestalt/elemente.css, aufgeloest ueber platform/_paths.gestalt_css().
   Kanal-neutral: `.post-layout` und `.post-layout .article__body` sind Platzhalter, die der Seitentyp aufloest
   (blog -> .post-layout / .post-layout .article__body). Dieselbe Datei traegt darum auch
   Landing-Pages und jeden kuenftigen Seitentyp, ohne dass eine zweite CSS entsteht
   (design-engine/ZIELARCHITEKTUR.md §1b-2).

   DIE QUELLE DIESER GESTALT IST NICHT ERFUNDEN
   --------------------------------------------
   roughly hat seine Leseseiten-Sprache bereits: `scratch/games-703/_shared/page.css` (About,
   Blog-Index) und `_shared/tokens.css`. Ein Blog-Post ist bei roughly keine neue Gattung,
   sondern dieselbe Leseseite mit anderem Inhalt. Diese Datei uebersetzt darum die Blog-
   Elemente in die BESTEHENDE Sprache, statt eine zweite danebenzustellen. Jede Regel unten
   hat ihr Vorbild dort, und wo eines fehlt, steht es im Kommentar.

   DIE HARTEN REGELN DER MARKE (brand-engine/brands/roughly/rules.md + konzept.md)
   -------------------------------------------------------------------------------
   · EINE Schrift: Onest. Keine zweite Schrift, nirgends. Die geteilte Blog-Schicht setzt an
     mehreren Stellen `var(--font-mono)` (Meta-Zeile, Etiketten, Tabellenkopf) — bei roughly
     ist das ein Fremdkoerper und wird hier ueberall zurueckgenommen.
   · Hierarchie aus KONTRAST und ABSTAND, nie aus geschrumpfter Schrift, nie aus Versalien mit
     Sperrung. Die geteilte Schicht zeichnet Meta-Zeile, Tabellenkopf und Quellen-Titel als
     `text-transform:uppercase; letter-spacing:.16em` aus — das ist die Sprache eines
     Mess-Etiketts, nicht die von roughly.
   · Keine Kaesten. Das weisse Blatt, Haarlinien, viel Luft. Wo die geteilte Schicht eine
     Flaeche mit Rahmen und Radius setzt (Stat-Karte, Checkliste, CTA), wird sie hier flach.
   · Die Signalfarbe ist Flaeche oder Kante, NIE Textfarbe (auch eine System-Regel seit #560).
   · Drei Tinten: --ink (Aussage), --ink-2 (Fliesstext), --ink-3 (Beschriftung, Quelle).
   · Beide Themen muessen tragen. Alles unten arbeitet ausschliesslich mit Token, kein Hex.

   DIE GERAETE (aus dem Produkt, nicht aus einem Muster-Katalog)
   -------------------------------------------------------------
   roughly hat eine ungewoehnlich klare Formenwelt, weil sie aus dem Spiel kommt:

     Das Blatt        `.fig__sheet` — die Reveal-Karte, die nach dem Tipp aufsteigt.
                      Weicher Radius, Schatten nach OBEN, ein Griff-Strich oben mittig.
                      -> die Merken-Box (der eine Satz, der haengen bleibt)
     Die grosse Zahl  `.fig__num` — --t-mega, Gewicht 700, tabellarische Ziffern, eine
                      kleine Einheit daneben.  -> die Stat-Karte
     Die Kurve        `.fig__area` / `.fig__line` — Flaeche in --accent-soft mit Kante in
                      --accent-line.  -> die Balken der Rangliste
     Die Zeilen       `.fig__keys` / `.rows` — Haarlinie oben, Haarlinie unten, zwei Spalten,
                      Werte rechts mit tabellarischen Ziffern.
                      -> Tabelle, Checkliste, Kernbefunde, nummerierte Liste
     Die Quelle       `.fig__src` — --t-xs, Gewicht 500, --ink-3, jede Zahl belegt.
                      -> der Quellen-Block
     Die Pille        `.page__btn` — --ink als Flaeche, --paper als Schrift, voll gerundet.
                      -> der Abschluss-CTA
     Die Kante        die Regenbogen-Leiste der OG-Bilder (manifest `colors.regenbogen`),
                      die zehn Farbtoene der Familie in einem Streifen.

   DER AKZENT (Esteban-Direktive #729)
   ------------------------------------
   «Nicht Akzentfarben, die Farbe des Spiels, von dem der Post handelt. Und unsere Hauptfarbe
   ist eigentlich Regenbogen per se, weil das umfasst ja alle Spiele.»
   · Der Akzent kommt aus `--hue` und folgt damit automatisch dem Spiel des Posts (Mechanik
     in tokens.css, Bruecke via colors.site_tokens).
   · Der Regenbogen ist die Marken-Farbe fuer alles, was fuer roughly als GANZES steht.
     Weil er als Flaeche Laerm waere, gibt es unten DREI Variationen, zwischen denen der
     Musterbogen umschaltet (`data-regenbogen` am <html>): siehe Abschnitt REGENBOGEN.
   ============================================================================================ */

/* --------------------------------------------------------------------------------------------
   0 · GRUNDLAGEN
   -------------------------------------------------------------------------------------------- */

/* Der Kopf der Leseseite klebt nicht (`.page__top` ist statisch), das Inhaltsverzeichnis ist
   abgewaehlt — der Wert haelt nur das Token-Gate zufrieden und beschreibt die Wahrheit. */
.post-layout{--blog-sticky-top:24px}

/* Die Lesespalte ist roughlys eigene: --pcol (720px) aus page.css, nicht eine zweite Zahl. */
.post-layout{max-width:calc(var(--pcol, 720px) + 2 * var(--s5, 24px))}

/* Fliesstext: 17px, Zeilenhoehe 1.5, zweite Tinte, hoechstens 62 Zeichen — exakt
   `.page__main p`. Die geteilte Schicht setzt 18px/1.75; das ist ein anderer Text. */
.post-layout .article__body{font-size:var(--t-md);line-height:1.5;color:var(--ink-2)}
.post-layout .article__body p{margin:0 0 var(--s3);max-width:62ch;text-wrap:pretty}

/* --------------------------------------------------------------------------------------------
   1 · META-ZEILE  (Kategorie · Datum · Lesezeit · Autor)
   -------------------------------------------------------------------------------------------
   Estebans Befund #729, wortwoertlich: «erstens mal hasse ich diese Schriftart». Gemessen stand
   dort JetBrains Mono, 11px, VERSALIEN, 1.76px Sperrung — drei Verstoesse gegen die harten
   Regeln der Marke in einer einzigen Zeile (zweite Schrift, Hierarchie durch Schrumpfen,
   Sperrung). Hier steht stattdessen roughlys Beschriftungs-Sprache: Onest, --t-xs, Gewicht 500,
   dritte Tinte, gemischte Schreibung. Vorbild `.fig__src` und `.rows__v`. */
.post-layout .article__meta{
  font-family:var(--font, var(--font-body));
  font-size:var(--t-xs);font-weight:500;letter-spacing:0;text-transform:none;
  /* ZWEITE Tinte, nicht die dritte: --ink-3 misst auf Papier GERENDERT 4.44 (das
     Manifest behauptet 4.6) und liegt damit unter der Schwelle fuer kleinen Text.
     Der Unterschied zum Fliesstext kommt hier aus Groesse und Gewicht, nicht aus
     einem Ton, der gerade noch durchgeht. Gemessen #729 am gerenderten Bogen. */
  color:var(--ink-2);gap:var(--s3);margin-bottom:var(--s5);
  font-variant-numeric:tabular-nums;
}
/* Die Kategorie traegt keine Schraegstriche und keine Signalfarbe: sie ist strukturell
   staerker (erste Tinte, Gewicht 600), wie ueberall bei roughly. */
.post-layout .article__meta .accent{color:var(--ink);font-weight:600}

/* --------------------------------------------------------------------------------------------
   2 · TITEL + LEAD
   --------------------------------------------------------------------------------------------
   `.page__main h1`: clamp(1.75rem, 3.4vw, 2.5rem), Gewicht 700, --tight, Zeilenhoehe 1.05.
   Die geteilte Schicht setzt 56px/900 plus `-webkit-text-stroke` — eine fettere Marke als die,
   die roughly ist (Onest 700 ist die Display-Stufe, siehe konzept.md). */
.post-layout .article__title{
  font-size:clamp(1.75rem, 3.4vw, 2.5rem);font-weight:700;
  letter-spacing:var(--tight);line-height:1.05;color:var(--ink);
  -webkit-text-stroke:0;margin-bottom:var(--s4);max-width:20ch;text-wrap:balance;
}
/* Der Lead ist kein Kasten und traegt keinen Akzent-Balken (geteilte Schicht:
   `border-left:3px solid var(--accent)`). Vorbild `.page__main h2 + p`: erste Tinte,
   Gewicht 500 — der Satz nach der Frage. */
.post-layout .article__lead{
  border-left:0;padding-left:0;font-size:var(--t-lg);font-weight:500;
  line-height:1.4;color:var(--ink);max-width:34ch;
}

/* --------------------------------------------------------------------------------------------
   3 · ZWISCHENUEBERSCHRIFTEN
   --------------------------------------------------------------------------------------------
   `.page__main h2`: --t-lg (20px), Gewicht 600, viel Luft darueber (--s8 = 64px), wenig
   darunter (--s3). Der Sprung entsteht aus dem ABSTAND, nicht aus 32px/900. */
.post-layout .article__body h2{
  font-size:var(--t-lg);font-weight:600;letter-spacing:-0.02em;line-height:1.25;
  color:var(--ink);-webkit-text-stroke:0;margin:var(--s8) 0 var(--s3);text-wrap:balance;
}
.post-layout .article__body h3{
  font-size:var(--t-md);font-weight:600;letter-spacing:-0.01em;
  color:var(--ink);margin:var(--s6) 0 var(--s2);
}
/* Der erste Absatz nach einer Ueberschrift traegt die Aussage (page.css `h2 + p`). */
.post-layout .article__body h2 + p{color:var(--ink);font-weight:500}

/* --------------------------------------------------------------------------------------------
   4 · LINKS IM FLIESSTEXT
   --------------------------------------------------------------------------------------------
   `.page__main p a`: erste Tinte, echte Unterstreichung in --line-strong, 3px Abstand, beim
   Zeigen wird die Linie zur Tinte. Kein Akzent als Textfarbe (harte Regel). */
.post-layout .article__body a{
  color:var(--ink);font-weight:500;border-bottom:0;
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:var(--line-strong);
}
.post-layout .article__body a:hover{color:var(--ink);text-decoration-color:var(--ink);border-bottom:0}
.post-layout .article__body a:focus-visible{outline:2px solid var(--accent-line);outline-offset:2px}

/* --------------------------------------------------------------------------------------------
   5 · MERKEN-BOX  =  DAS BLATT
   --------------------------------------------------------------------------------------------
   Das Gefaess fuer den einen Satz, den der Leser behaelt — bei roughly ist das die Karte, die
   nach dem Tipp aufsteigt (`.fig__sheet`): weicher Radius, Papier, Schatten nach OBEN, und der
   Griff-Strich oben mittig als Signatur. Bewusst OHNE Wort-Etikett: die geteilte Schicht sieht
   `content:var(--label-merken)` vor, aber ein Versal-Etikett («MERKEN») waere bei dieser Marke
   genau das Geschrei, das ihre Regeln verbieten. Der Griff ist die Marke. */
.post-layout .article__body .post-highlight{
  position:relative;max-width:420px;margin:var(--s6) auto;
  padding:var(--s6) var(--s5) var(--s5);
  background:var(--paper);border:0;border-radius:var(--r-lg);
  box-shadow:var(--shadow-up);
  font-size:var(--t-lg);font-weight:500;line-height:1.35;color:var(--ink);
}
/* Das Etikett ist AUSDRUECKLICH leer, nicht vergessen: die geteilte Schicht setzt
   `content:var(--label-merken)`, und ein deklariertes leeres Wort ist die einzige Art, dem
   Waechter zu sagen «diese Marke fuehrt kein Etikett» statt ihn raten zu lassen. Das Gefaess
   traegt seine Marke als Griff-Strich, nicht als Versal-Wort. */
.post-layout{--label-merken:""}
.post-layout .article__body .post-highlight::before{
  content:"";position:absolute;top:10px;left:50%;width:36px;height:5px;
  margin-left:-18px;border-radius:var(--r-full);background:var(--line);
  /* die geteilte Schicht macht daraus eine Etikett-Pille — hier ist es der Griff */
  padding:0;border:0;font-size:0;letter-spacing:0;
}
.post-layout .article__body .post-highlight p{margin:0;max-width:none;color:inherit;font-size:inherit}

/* --------------------------------------------------------------------------------------------
   6 · PULL-ZITAT  =  DER SATZ MIT DER WAHRHEIT
   --------------------------------------------------------------------------------------------
   Kein Kasten, keine Anfuehrungszeichen, keine Signalfarbe: zwei Haarlinien, viel Luft, und der
   Satz gross in erster Tinte. Vorbild `.fig__verdict` (der Satz, der den Reveal erklaert),
   eine Stufe groesser, weil er den Lesefluss unterbrechen soll. */
.post-layout .article__body .post-pull{
  margin:var(--s7) 0;padding:var(--s5) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  border-left:0;background:none;
  font-size:var(--t-xl);font-weight:600;letter-spacing:var(--tight);line-height:1.25;
  color:var(--ink);max-width:26ch;text-wrap:balance;
}
.post-layout .article__body .post-pull::before,.post-layout .article__body .post-pull::after{content:none}

/* --------------------------------------------------------------------------------------------
   7 · TABELLE  =  DIE ZEILEN
   --------------------------------------------------------------------------------------------
   `.rows` und `.fig__keys`: keine Rahmen, keine Zebra-Streifen, kein Radius. Haarlinie zwischen
   den Zeilen, Haarlinie unten, Kopf in erster Tinte und Gewicht 600 — OHNE Versalien und ohne
   Sperrung (die geteilte Schicht setzt beides). Zahlen tabellarisch, damit sie untereinander
   stehen; das ist bei einer Schaetz-Marke keine Kosmetik. */
.post-layout .article__body .post-table{
  border:0;border-radius:0;box-shadow:none;background:none;
  border-collapse:collapse;width:100%;margin:var(--s5) 0 var(--s6);
  font-size:var(--t-md);font-variant-numeric:tabular-nums;
}
.post-layout .article__body .post-table th{
  background:none;color:var(--ink);font-weight:600;
  font-family:var(--font, var(--font-body));
  font-size:var(--t-sm);letter-spacing:0;text-transform:none;
  padding:0 var(--s4) var(--s3) 0;border-bottom:1px solid var(--line-strong);
}
.post-layout .article__body .post-table td{
  padding:var(--s3) var(--s4) var(--s3) 0;border-bottom:1px solid var(--line);
  color:var(--ink-2);line-height:1.4;vertical-align:baseline;
}
/* Die erste Spalte ist der Schluessel (erste Tinte), die letzte der Wert (rechts, tabellarisch)
   — dieselbe Rollenverteilung wie in `.rows`. */
.post-layout .article__body .post-table td:first-child{color:var(--ink)}
.post-layout .article__body .post-table td:last-child:not(:first-child),
.post-layout .article__body .post-table th:last-child:not(:first-child){text-align:right;padding-right:0}
.post-layout .article__body .post-table tbody tr:last-child td{border-bottom:1px solid var(--line)}

/* --------------------------------------------------------------------------------------------
   8 · BLOCKQUOTE  =  FREMDE REDE
   --------------------------------------------------------------------------------------------
   Eingerueckt an einer Haarlinie, zweite Tinte, keine Anfuehrungszeichen-Grafik. Bewusst
   zurueckhaltender als das Pull-Zitat: das eine ist unsere Aussage, das andere jemandes Satz. */
.post-layout .article__body blockquote{
  margin:var(--s5) 0;padding:0 0 0 var(--s5);
  border-left:1px solid var(--line-strong);background:none;border-radius:0;
  font-size:var(--t-md);font-style:normal;color:var(--ink-2);line-height:1.5;
}
.post-layout .article__body blockquote p{margin:0 0 var(--s2)}
.post-layout .article__body blockquote p:last-child{margin:0}

/* --------------------------------------------------------------------------------------------
   9 · STAT-KARTE  =  DIE GROSSE ZAHL
   --------------------------------------------------------------------------------------------
   Das Herzstueck der Marke: eine Zahl, so gross, dass sie das Blatt traegt (`--t-mega`,
   56-72px), Gewicht 700, tabellarisch, in erster Tinte. KEINE Flaeche, kein Rahmen, kein
   Radius — die geteilte Schicht setzt eine Akzent-Flaeche mit Rahmen, und genau das ist der
   Kasten, den roughlys Regeln verbieten. Label und Kontext darunter in absteigender Tinte,
   die Quelle klein, wie im Reveal. */
.post-layout .article__body .post-stat{
  background:none;border:0;border-radius:0;box-shadow:none;
  margin:var(--s7) 0;padding:0;
  border-top:1px solid var(--line);padding-top:var(--s5);
}
.post-layout .article__body .post-stat__num{
  font-size:var(--t-mega);font-weight:700;letter-spacing:var(--tight);line-height:.95;
  color:var(--ink);font-variant-numeric:tabular-nums;display:block;
}
.post-layout .article__body .post-stat__label{
  font-size:var(--t-md);font-weight:500;color:var(--ink);
  letter-spacing:0;text-transform:none;margin-top:var(--s2);display:block;
}
.post-layout .article__body .post-stat__kontext,.post-layout .article__body .post-stat p{
  font-size:var(--t-sm);color:var(--ink-2);margin-top:var(--s2);max-width:52ch;
}
.post-layout .article__body .post-stat figcaption,.post-layout .article__body .post-figure figcaption{
  font-size:var(--t-xs);font-weight:500;color:var(--ink-3);margin-top:var(--s4);
  letter-spacing:0;text-transform:none;
}

/* --------------------------------------------------------------------------------------------
   10 · RANGLISTE  =  DIE KURVE ALS BALKEN
   --------------------------------------------------------------------------------------------
   Die Pflicht-Grafik des Studien-Posts. roughlys Sprache dafuer ist die Reveal-Kurve: Flaeche in
   --accent-soft, Kante in --accent-line, der Wert daneben tabellarisch. Damit traegt der Balken
   die Farbe des Spiels, um das der Post geht (Esteban #729), ohne dass Text je farbig wird. */
.post-layout .article__body .post-figure{
  background:none;border:0;border-radius:0;box-shadow:none;
  margin:var(--s6) 0;padding:0;
}
.post-layout .article__body .post-figure .post-rang__zeile,.post-layout .article__body .post-figure li{
  border-top:1px solid var(--line);padding:var(--s3) 0;
  display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:baseline;
  column-gap:var(--s4);font-size:var(--t-md);color:var(--ink);
}
.post-layout .article__body .post-figure li:last-child{border-bottom:1px solid var(--line)}
.post-layout .article__body .post-figure .post-rang__balken,.post-layout .article__body .post-figure .balken{
  background:var(--accent-soft);border:1px solid var(--accent-line);border-radius:2px;
}
.post-layout .article__body .post-figure .post-rang__wert,.post-layout .article__body .post-figure b{
  font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;text-align:right;
}

/* --------------------------------------------------------------------------------------------
   11 · CHECKLISTE + KERNBEFUNDE  =  DIE SCHLUESSEL-ZEILEN
   --------------------------------------------------------------------------------------------
   Beide rendern ueber `.post-checkliste`. Vorbild `.fig__keys`: Haarlinie oben je Zeile,
   Haarlinie unten am Schluss, kein Kasten, kein Haken in Signalfarbe. Der Marker ist ein
   kurzer Strich in --line-strong — ruhig, und er funktioniert in beiden Themen. */
.post-layout .article__body .post-checkliste{
  background:none;border:0;border-radius:0;box-shadow:none;
  margin:var(--s6) 0;padding:0;
}
.post-layout .article__body .post-checkliste__titel,.post-layout .article__body .post-checkliste > strong:first-child{
  display:block;font-size:var(--t-md);font-weight:600;color:var(--ink);
  letter-spacing:0;text-transform:none;margin-bottom:var(--s2);
}
.post-layout .article__body .post-checkliste__list,.post-layout .article__body .post-checkliste ul{
  list-style:none;margin:0;padding:0;
}
.post-layout .article__body .post-checkliste__list li,.post-layout .article__body .post-checkliste ul li{
  position:relative;padding:var(--s3) 0 var(--s3) var(--s5);
  border-top:1px solid var(--line);
  font-size:var(--t-md);line-height:1.4;color:var(--ink-2);
}
.post-layout .article__body .post-checkliste__list li:last-child,
.post-layout .article__body .post-checkliste ul li:last-child{border-bottom:1px solid var(--line)}
.post-layout .article__body .post-checkliste__list li::before,
.post-layout .article__body .post-checkliste ul li::before{
  content:"";position:absolute;left:0;top:calc(var(--s3) + 0.62em);
  width:12px;height:1px;background:var(--line-strong);border-radius:0;
  color:transparent;font-size:0;
}

/* --------------------------------------------------------------------------------------------
   12 · NUMMERIERTE LISTE
   --------------------------------------------------------------------------------------------
   Wenn die Reihenfolge zaehlt. Dieselben Zeilen, aber die Nummer traegt sie — tabellarisch,
   dritte Tinte, damit sie ordnet ohne zu rufen. */
.post-layout .article__body .post-list,.post-layout .article__body ol{
  list-style:none;counter-reset:rl;margin:var(--s5) 0;padding:0;
}
.post-layout .article__body .post-list li,.post-layout .article__body ol li{
  counter-increment:rl;position:relative;
  padding:var(--s3) 0 var(--s3) var(--s6);border-top:1px solid var(--line);
  font-size:var(--t-md);line-height:1.4;color:var(--ink-2);
}
.post-layout .article__body .post-list li:last-child,.post-layout .article__body ol li:last-child{border-bottom:1px solid var(--line)}
.post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
  content:counter(rl);position:absolute;left:0;top:var(--s3);
  font-size:var(--t-md);font-weight:600;color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}

/* --------------------------------------------------------------------------------------------
   13 · QUELLEN-BLOCK
   --------------------------------------------------------------------------------------------
   «Jede Zahl ist belegt» ist bei roughly Identitaet, nicht Pflichtuebung (rules.md). Der Block
   ist darum ruhig und selbstverstaendlich: `.fig__src`-Sprache, --t-xs, Gewicht 500, dritte
   Tinte, Links ohne Unterstreichung, beim Zeigen erste Tinte. Kein Kasten, keine Versalien. */
.post-layout .article__body .post-sources{
  background:none;border:0;border-radius:0;box-shadow:none;
  margin:var(--s7) 0 0;padding:var(--s4) 0 0;border-top:1px solid var(--line);
  font-size:var(--t-xs);font-weight:500;color:var(--ink-2);   /* siehe Meta-Zeile: --ink-3 misst 4.44 */
}
.post-layout .article__body .post-sources h2,.post-layout .article__body .post-sources h3,.post-layout .article__body .post-sources strong{
  font-size:var(--t-xs);font-weight:600;color:var(--ink);
  letter-spacing:0;text-transform:none;margin:0 0 var(--s2);
}
.post-layout .article__body .post-sources ul{list-style:none;margin:0;padding:0}
.post-layout .article__body .post-sources li{padding:var(--s2) 0;border:0;line-height:1.4}
.post-layout .article__body .post-sources a{
  color:inherit;text-decoration:none;border-bottom:0;font-weight:500;
}
.post-layout .article__body .post-sources a:hover{color:var(--ink);text-decoration:none}

/* --------------------------------------------------------------------------------------------
   14 · ABSCHLUSS-CTA  =  DIE PILLE
   --------------------------------------------------------------------------------------------
   Esteban #729: «einen Call-to-Action zu irgendeinem Daily, von uns selber», und der CTA war
   «extrem schlecht vom Design her». Gemessen war er eine 187px hohe Akzent-Flaeche mit Rahmen
   — ein Kasten, also genau das, was roughly nicht macht.
   Hier ist er das, was er im Spiel ist: eine Zeile Text und EINE Pille (`.page__btn`), --ink
   als Flaeche, --paper als Schrift, voll gerundet, 52px hoch (Fingergroesse). Darueber eine
   Haarlinie als Abschluss des Textes. Kein Kasten, keine zweite Flaeche. */
.post-layout .article__body .post-cta{
  background:none;border:0;border-radius:0;box-shadow:none;
  margin:var(--s8) 0 var(--s6);padding:var(--s5) 0 0;
  border-top:1px solid var(--line);
  text-align:left;
}
.post-layout .article__body .post-cta p,.post-layout .article__body .post-cta > *:first-child{
  font-size:var(--t-lg);font-weight:500;line-height:1.35;color:var(--ink);
  max-width:30ch;margin:0 0 var(--s4);
}
.post-layout .article__body .post-cta a,.post-layout .article__body .post-cta .post-cta__knopf{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:52px;padding:12px 24px;border-radius:var(--r-full);
  background:var(--ink);color:var(--paper);
  font-size:var(--t-md);font-weight:600;letter-spacing:-0.01em;
  text-decoration:none;border:0;
}
.post-layout .article__body .post-cta a:hover{background:var(--ink-2);color:var(--paper);text-decoration:none}
.post-layout .article__body .post-cta a:focus-visible{outline:2px solid var(--accent-line);outline-offset:3px}

/* ============================================================================================
   REGENBOGEN — DREI VARIATIONEN ZUR WAHL (Esteban #729: «muss ein bisschen spielen damit,
   mehrere Variationen machen»)
   ============================================================================================
   Der Regenbogen ist die Farbe der FAMILIE (alle zehn Spiele), im Gegensatz zum --hue, der die
   Farbe EINES Spiels ist. Als Flaeche waere er Laerm; die Frage ist also nicht ob, sondern WO
   und WIE SCHMAL. Drei Antworten, alle aus derselben Deklaration (manifest colors.regenbogen):

     A  DIE KANTE      Ein 3px-Streifen ueber dem Titel. Der Post beginnt mit der Familie und
                       geht dann in die Farbe seines Spiels ueber. Direkteste Uebersetzung der
                       OG-Bildsprache (dort liegt der Streifen an der Blatt-Kante).
     B  DER GRIFF      Nur der Griff-Strich der Merken-Box traegt ihn, 36x5px. Die leiseste
                       Variante: der Regenbogen taucht genau einmal auf, an dem Gegenstand,
                       der aus dem Spiel stammt.
     C  DIE NAHT       Eine 2px-Linie an jeder strukturellen Trennung (Pull, Stat, CTA), also
                       dort, wo der Text ohnehin atmet. Der Regenbogen wird zum Rhythmus der
                       Seite statt zu einem einzelnen Schmuckstueck.

   Umschalten im Musterbogen ueber den Knopf oben rechts (`data-regenbogen` am <html>).
   Was Esteban waehlt, wird der Default; die uebrigen bleiben als benannte Alternative stehen,
   damit die Entscheidung nachvollziehbar ist und nicht neu erfunden werden muss.
   ============================================================================================ */

/* MB-VARIANTEN: data-regenbogen = a:A Die Kante | b:B Der Griff | c:C Die Naht */

.post-layout{
  --regenbogen:linear-gradient(90deg in oklch,
    oklch(78% 0.14 40) 0%, oklch(78% 0.14 75) 11%, oklch(78% 0.14 150) 22%,
    oklch(78% 0.14 178) 33%, oklch(78% 0.14 205) 44%, oklch(78% 0.14 235) 56%,
    oklch(78% 0.14 262) 67%, oklch(78% 0.14 300) 78%, oklch(78% 0.14 320) 89%,
    oklch(78% 0.14 350) 100%);
}

/* ---- A · DIE KANTE (Default) ---------------------------------------------------------- */
[data-regenbogen="a"] .post-layout .article__hero,
:root:not([data-regenbogen]) .post-layout .article__hero{position:relative}
[data-regenbogen="a"] .post-layout .article__hero::before,
:root:not([data-regenbogen]) .post-layout .article__hero::before{
  content:"";display:block;width:64px;height:3px;border-radius:var(--r-full);
  background:var(--regenbogen);margin:0 0 var(--s5);
}

/* ---- B · DER GRIFF --------------------------------------------------------------------- */
[data-regenbogen="b"] .post-layout .article__body .post-highlight::before{
  background:var(--regenbogen);width:44px;
}

/* ---- C · DIE NAHT ---------------------------------------------------------------------- */
[data-regenbogen="c"] .post-layout .article__body .post-pull{border-top-color:transparent;position:relative}
[data-regenbogen="c"] .post-layout .article__body .post-pull::before{
  content:"";position:absolute;top:-1px;left:0;width:100%;height:2px;
  background:var(--regenbogen);
}
[data-regenbogen="c"] .post-layout .article__body .post-stat{border-top-color:transparent;position:relative}
[data-regenbogen="c"] .post-layout .article__body .post-stat::before{
  content:"";position:absolute;top:-1px;left:0;width:100%;height:2px;
  background:var(--regenbogen);
}
[data-regenbogen="c"] .post-layout .article__body .post-cta{border-top-color:transparent;position:relative}
[data-regenbogen="c"] .post-layout .article__body .post-cta::before{
  content:"";position:absolute;top:-1px;left:0;width:100%;height:2px;
  background:var(--regenbogen);
}

/* --------------------------------------------------------------------------------------------
   15 · NACHTRAEGE AUS DEM GERENDERTEN BOGEN (#729)
   --------------------------------------------------------------------------------------------
   Fuenf Dinge, die erst am Bild sichtbar waren und in der CSS unsichtbar sind. Genau dafuer ist
   der Bogen da; keine davon haette eine Quelltext-Pruefung gefunden. */

/* (a) DIE GRAFIKEN SCHREIBEN IN MONO. `grafik.py` zeichnet Rangliste und Split-Bar als SVG und
   setzt `font-family="var(--font-mono,monospace)"` als ATTRIBUT an die Textknoten (Titel, Werte,
   Basis-Zeile). Bei roughly ist jede zweite Schrift ein Regelbruch, und im Bild stand die halbe
   Grafik in JetBrains Mono neben Onest. CSS schlaegt Praesentations-Attribute, also greift die
   Korrektur hier ohne Eingriff in die Engine. */
.post-layout .article__body .post-figure svg text{font-family:var(--font, var(--font-body)) !important}
.post-layout .article__body .post-figure svg text[font-weight="700"]{font-weight:600}

/* (b) DER RAHMEN UM DIE GRAFIK. Die Figur trug im Bild einen Kasten mit Radius; die Regel
   sitzt tiefer als mein `.post-layout .article__body .post-figure`. roughly hat keine Kaesten, auch nicht um
   Grafiken: der Balken selbst ist die Form. */
.post-layout .article__body figure.post-figure,
.post-layout .article__body .article__body figure{
  background:none;border:0;border-radius:0;box-shadow:none;padding:0;
}

/* (c) DIE BILDUNTERSCHRIFT WAR KURSIV. Kursiv kommt in roughlys Schrift-Ordnung nicht vor
   (konzept.md: eine Familie, sechs Groessen, Gewichte 400-700 - keine Kursive). */
.post-layout .article__body figcaption,.post-layout .article__body .post-figure figcaption{
  font-style:normal;font-size:var(--t-xs);font-weight:500;color:var(--ink-2);
  margin-top:var(--s3);letter-spacing:0;text-transform:none;
}

/* (d) DER MARKER DER CHECKLISTE SASS ZU HOCH. Er ist an der ersten Textzeile auszurichten, nicht
   an der Kastenoberkante - bei zweizeiligen Punkten stand er sonst ueber dem Text statt daneben.
   (Dieselbe Klasse Fehler wie D2 in scratch/blog-gestalt-offen-557.md, dort fuer das
   Inhaltsverzeichnis.) */
.post-layout .article__body .post-checkliste__list li::before,
.post-layout .article__body .post-checkliste ul li::before{top:calc(var(--s3) + 0.72em)}

/* (e) DER QUELLEN-TITEL WAR EINE NORMALE UEBERSCHRIFT und die Liste erbte die Nummern der
   nummerierten Liste. Der Quellen-Block ist bei roughly der leiseste Teil der Seite: die
   Belege sind selbstverstaendlich, nicht ein Kapitel. Der Titel steht als h2 VOR dem Block,
   darum die Geschwister-Regel. */
.post-layout .article__body h2:has(+ .post-sources),
.post-layout .article__body .post-sources + h2{
  font-size:var(--t-sm);font-weight:600;color:var(--ink-2);
  margin:var(--s7) 0 var(--s2);letter-spacing:0;
}
.post-layout .article__body .post-sources ol,.post-layout .article__body .post-sources ul{list-style:none;margin:0;padding:0;counter-reset:none}
.post-layout .article__body .post-sources ol li,.post-layout .article__body .post-sources ul li{
  padding:var(--s2) 0;border:0;
}
.post-layout .article__body .post-sources ol li::before,.post-layout .article__body .post-sources ul li::before{content:none}

/* ============================================================================================
   16 · FARBE UND BEWEGUNG (#729, Esteban: «zu wenige Farben, alles ist so die gleiche, da
   brauchst du viel mehr Animationen; Tabelle geht besser, Checkliste geht besser»)
   ============================================================================================
   DIE FARB-STRATEGIE, in einem Satz
   roughly hat nicht eine Akzentfarbe, sondern ZEHN, eine je Spiel, und ihre Summe ist die
   Familie. Bisher nutzte der Post davon genau eine (den Farbton des Posts). Ab hier gilt:
   wo mehrere gleichrangige Posten nebeneinanderstehen (Rangliste, Checkliste, nummerierte
   Liste, Tabellen-Massstab), traegt JEDER seinen eigenen Farbton aus der Familie.

   Das ist eine Rolle, keine Deko: die Farbe kodiert Position in einer Reihe, genau wie auf der
   Landing, wo die zehn Spiele zehn Toene tragen. Und sie bleibt Flaeche oder Kante - die harte
   Regel «Signalfarbe nie als Textfarbe» ist unberuehrt, jeder Text steht weiter in Tinte.

   DIE ZEHN TOENE stehen im Manifest (colors.akzent_*) und in tokens.css als Farbton-Zahlen.
   Hier als Custom Property je Position, damit eine Zeile ohne JavaScript ihre Farbe kennt.

   HELL UND DUNKEL: die Toene sind gerechnet (oklch), nicht gesetzt. Im Hellen tiefe Farbe auf
   heller Flaeche, im Dunkeln helle Farbe auf tiefer - dieselbe Kurve wie in tokens.css, damit
   Blog und Spiel nicht auseinanderlaufen.
   ============================================================================================ */

.post-layout{
  --f1:40;  --f2:75;  --f3:150; --f4:178; --f5:205;
  --f6:235; --f7:262; --f8:300; --f9:320; --f10:350;
  /* Die Kurve je Thema: Balken kraeftig, Spur zurueckhaltend. post.js liest dieselben Werte. */
  --balken-l:50%; --balken-c:0.17; --spur-l:96%; --spur-c:0.025;
  --ton-flaeche-l:96%; --ton-flaeche-c:0.028;
  --ton-kante-l:52%;  --ton-kante-c:0.15;
}
:root[data-theme="dark"] .post-layout{
  --balken-l:78%; --balken-c:0.14; --spur-l:24%; --spur-c:0.04;
  --ton-flaeche-l:26%; --ton-flaeche-c:0.045;
  --ton-kante-l:78%;  --ton-kante-c:0.13;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .post-layout{
    --balken-l:78%; --balken-c:0.14; --spur-l:24%; --spur-c:0.04;
    --ton-flaeche-l:26%; --ton-flaeche-c:0.045;
    --ton-kante-l:78%;  --ton-kante-c:0.13;
  }
}

/* Ein Ton je Position. Zehn Regeln, dann wiederholt sich die Familie - so wie zehn Spiele. */
.post-layout .article__body .post-checkliste__list li:nth-child(10n+1),.post-layout .article__body .post-list li:nth-child(10n+1),.post-layout .article__body ol li:nth-child(10n+1),.post-layout .article__body .post-table tbody tr:nth-child(10n+1){--h:var(--f1)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+2),.post-layout .article__body .post-list li:nth-child(10n+2),.post-layout .article__body ol li:nth-child(10n+2),.post-layout .article__body .post-table tbody tr:nth-child(10n+2){--h:var(--f2)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+3),.post-layout .article__body .post-list li:nth-child(10n+3),.post-layout .article__body ol li:nth-child(10n+3),.post-layout .article__body .post-table tbody tr:nth-child(10n+3){--h:var(--f3)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+4),.post-layout .article__body .post-list li:nth-child(10n+4),.post-layout .article__body ol li:nth-child(10n+4),.post-layout .article__body .post-table tbody tr:nth-child(10n+4){--h:var(--f4)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+5),.post-layout .article__body .post-list li:nth-child(10n+5),.post-layout .article__body ol li:nth-child(10n+5),.post-layout .article__body .post-table tbody tr:nth-child(10n+5){--h:var(--f5)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+6),.post-layout .article__body .post-list li:nth-child(10n+6),.post-layout .article__body ol li:nth-child(10n+6),.post-layout .article__body .post-table tbody tr:nth-child(10n+6){--h:var(--f6)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+7),.post-layout .article__body .post-list li:nth-child(10n+7),.post-layout .article__body ol li:nth-child(10n+7),.post-layout .article__body .post-table tbody tr:nth-child(10n+7){--h:var(--f7)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+8),.post-layout .article__body .post-list li:nth-child(10n+8),.post-layout .article__body ol li:nth-child(10n+8),.post-layout .article__body .post-table tbody tr:nth-child(10n+8){--h:var(--f8)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n+9),.post-layout .article__body .post-list li:nth-child(10n+9),.post-layout .article__body ol li:nth-child(10n+9),.post-layout .article__body .post-table tbody tr:nth-child(10n+9){--h:var(--f9)}
.post-layout .article__body .post-checkliste__list li:nth-child(10n),.post-layout .article__body .post-list li:nth-child(10n),.post-layout .article__body ol li:nth-child(10n),.post-layout .article__body .post-table tbody tr:nth-child(10n){--h:var(--f10)}

/* --------------------------------------------------------------------------------------------
   16a · CHECKLISTE: aus dem Strich wird eine Marke
   -------------------------------------------------------------------------------------------
   Der kurze graue Strich war korrekt und leblos. Jetzt traegt jede Zeile eine kleine
   Farbflaeche mit dem Haken darin, in ihrem eigenen Ton, und die Zeile hebt sich beim Zeigen
   in derselben Farbe an. Die Flaeche ist rund wie die Piktogramm-Kacheln der Landing
   (`.ten10 i`) - dasselbe Geraet, ein Element weiter.
   Der Haken ist GEZEICHNET (zwei Kanten, gedreht), kein Unicode-Zeichen: der Craft-Floor
   verbietet Glyphen als Ikonografie, und in Onest saehe ein Haken ohnehin falsch aus. */
.post-layout .article__body .post-checkliste__list li,.post-layout .article__body .post-checkliste ul li{
  padding-left:calc(var(--s6) + var(--s2));
  transition:background var(--d-fast, 180ms) var(--ease, ease);
}
.post-layout .article__body .post-checkliste__list li::before,
.post-layout .article__body .post-checkliste ul li::before{
  content:"";left:0;top:calc(var(--s3) + 0.05em);
  width:26px;height:26px;border-radius:8px;
  background:oklch(var(--ton-flaeche-l) var(--ton-flaeche-c) var(--h, 255));
  border:1.5px solid oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255));
}
.post-layout .article__body .post-checkliste__list li::after,
.post-layout .article__body .post-checkliste ul li::after{
  content:"";position:absolute;left:8.5px;top:calc(var(--s3) + 0.05em + 8px);
  width:9px;height:5px;
  border-left:1.9px solid oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255));
  border-bottom:1.9px solid oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255));
  transform:rotate(-45deg);border-radius:1px;
}
.post-layout .article__body .post-checkliste__list li:hover,.post-layout .article__body .post-checkliste ul li:hover{
  background:oklch(var(--ton-flaeche-l) var(--ton-flaeche-c) var(--h, 255));
}

/* --------------------------------------------------------------------------------------------
   16b · NUMMERIERTE LISTE: die Nummer sitzt in ihrer Farbe
   -------------------------------------------------------------------------------------------- */
.post-layout .article__body .post-list li,.post-layout .article__body ol li{
  padding-left:calc(var(--s6) + var(--s2));
  transition:background var(--d-fast, 180ms) var(--ease, ease);
}
.post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
  left:0;top:calc(var(--s3) + 0.05em);
  width:26px;height:26px;border-radius:var(--r-full);
  display:grid;place-items:center;
  font-size:var(--t-xs);font-weight:700;
  color:oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255));
  background:oklch(var(--ton-flaeche-l) var(--ton-flaeche-c) var(--h, 255));
}
.post-layout .article__body .post-list li:hover,.post-layout .article__body ol li:hover{
  background:oklch(var(--ton-flaeche-l) var(--ton-flaeche-c) var(--h, 255));
}

/* --------------------------------------------------------------------------------------------
   16c · TABELLE: die Zahl ist eine LAENGE
   -------------------------------------------------------------------------------------------
   Das Kernstueck dieser Runde. Traegt die letzte Spalte lauter Zahlen derselben Art, zeichnet
   `post.js` unter jede einen Balken proportional zum groessten Wert. Damit liest man die
   Groessenordnung, bevor man die Ziffern liest - genau das, was die zehn Spiele beibringen,
   und der Grund, warum eine Schaetz-Marke keine graue Zahlenkolonne haben darf.
   Der Balken waechst beim ersten Erscheinen von null auf seine Laenge. */
.post-layout .article__body .post-table.has-mass td:last-child{position:relative;padding-bottom:calc(var(--s3) + 8px)}
.post-layout .article__body .post-mass{
  position:absolute;right:0;bottom:6px;
  display:block;height:3px;border-radius:var(--r-full);
  width:var(--ist, 0%);
  background:oklch(var(--balken-l) var(--balken-c) var(--h, 255));
  transition:width 700ms cubic-bezier(.16,1,.3,1);
}
/* Zeilen-Hover: die ganze Zeile bekommt die Flaeche ihres Balkens. Die Tabelle liest sich
   damit wie eine Liste, ueber die man mit dem Finger faehrt. */
.post-layout .article__body .post-table tbody tr{transition:background var(--d-fast, 180ms) var(--ease, ease)}
.post-layout .article__body .post-table tbody tr:hover{background:oklch(var(--ton-flaeche-l) var(--ton-flaeche-c) var(--h, 255))}
/* Der Kopf bekommt die Kante der Familie statt einer grauen Linie. */
.post-layout .article__body .post-table th{border-bottom:3px solid transparent;border-image:var(--regenbogen) 1;border-image-slice:1}

/* --------------------------------------------------------------------------------------------
   16d · PIKTOGRAMME: gezeichnet, wo wirklich von einem Spiel die Rede ist
   -------------------------------------------------------------------------------------------
   Die 88 Umrisse und die zehn Spiel-Zeichen sind echtes Marken-Material (aus echten Bildern
   nachgezeichnet, #709/#718). Sie stehen darum an genau zwei Stellen: in der Kategorie-Zeile,
   wenn die Kategorie ein Spiel IST, und im Abschluss-Knopf, wenn er in ein Spiel fuehrt.
   Nicht neben beliebigen Listenpunkten - dort waeren sie Schmuck. */
.post-layout .article__body .post-pikto,.post-layout .post-pikto{
  width:1.05em;height:1.05em;flex:none;vertical-align:-0.16em;margin-right:0.4em;
  fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;
}
.post-layout .article__meta .post-pikto{
  stroke:oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255));
  width:1.2em;height:1.2em;
}
.post-layout .article__body .post-cta a .post-pikto{stroke:var(--paper);width:1.15em;height:1.15em;margin-right:0.5em}

/* --------------------------------------------------------------------------------------------
   16e · BEWEGUNG: die drei Bewegungen des Spiels, sonst keine
   -------------------------------------------------------------------------------------------
   Der Reveal (die Zahl zaehlt hoch), der Aufbau (die Balken wachsen), die Zeichnung (das
   Piktogramm zieht sich) stehen in `post.js`, weil sie Werte brauchen. Hier steht, was CSS
   allein kann: die Zustaende. Alles kurz, alles aus roughlys Bewegungs-Token, nichts, das
   beim Lesen stoert. */
.post-layout .article__body a{transition:text-decoration-color var(--d-fast, 180ms) var(--ease, ease),
                      color var(--d-fast, 180ms) var(--ease, ease)}
.post-layout .article__body .post-cta a{
  transition:background var(--d-fast, 180ms) var(--ease, ease),
             transform var(--d-fast, 180ms) var(--ease-o, ease-out);
}
.post-layout .article__body .post-cta a:hover{transform:translateY(-1px)}
.post-layout .article__body .post-cta a:active{transform:translateY(0)}
.post-layout .article__body .post-sources a{
  transition:color var(--d-fast, 180ms) var(--ease, ease),
             text-decoration-color var(--d-fast, 180ms) var(--ease, ease);
  text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px;
}
.post-layout .article__body .post-sources a:hover{text-decoration-color:var(--line-strong)}
/* Die Merken-Box hebt sich beim Zeigen minimal - das Blatt reagiert, wie im Spiel. */
.post-layout .article__body .post-highlight{transition:transform var(--d-mid, 360ms) var(--ease-o, ease-out),
                                    box-shadow var(--d-mid, 360ms) var(--ease, ease),
                                    opacity var(--d-mid, 360ms) var(--ease, ease)}
.post-layout .article__body .post-highlight:hover{transform:translateY(-2px)}

@media (prefers-reduced-motion: reduce){
  .post-layout .article__body .post-cta a:hover{transform:none}
  .post-layout .article__body .post-highlight:hover{transform:none}
  .post-layout .article__body .post-mass{transition:none}
}

/* --------------------------------------------------------------------------------------------
   16f · DIE REGENBOGEN-KANTE traegt jetzt die volle Breite
   -------------------------------------------------------------------------------------------
   Variante A war ein 64px-Strich und ging im Weissraum unter. Als Linie ueber die ganze
   Lesespalte ist sie das, was sie auf den OG-Bildern ist: die Kante der Familie. */
[data-regenbogen="a"] .post-layout .article__hero::before,
:root:not([data-regenbogen]) .post-layout .article__hero::before{
  width:100%;height:4px;border-radius:2px;margin:0 0 var(--s6);
}

/* Der Grafik-Titel: keine Versalien, keine Sperrung (rules.md). Die geteilte Schicht setzt
   beides fuer alle Marken; roughly nimmt es zurueck und nutzt stattdessen Gewicht. */
.post-layout .article__body .post-figure svg text[letter-spacing="2"]{
  text-transform:none;letter-spacing:0;font-weight:600;
}
/* Kein Kasten um eine Grafik - auch nicht der, den die Basis-Schicht setzt. */
.post-layout .article__body .post-figure,.post-layout .article__body figure.post-figure,.post-layout .article__body .article__body > figure{
  border:0 !important;border-radius:0 !important;box-shadow:none !important;
  background:none !important;padding:0 !important;
}

/* Der Kasten sass am SVG selbst (die Basis-Schicht gibt `.post-figure svg` Rahmen, Radius und
   weisse Flaeche). Am Element gemessen, nicht aus der CSS geschlossen - im Quelltext war er
   nicht zu finden, weil er nicht am figure haengt. roughly zeichnet Grafiken ohne Gefaess. */
.post-layout .article__body .post-figure svg,.post-layout .article__body .post-figure > svg{
  border:0;border-radius:0;background:none;box-shadow:none;
}

/* ============================================================================================
   17 · KRAEFTIGER (#729, zweite Runde)
   ============================================================================================
   Estebans Urteil an der ersten Fassung, wortnah: Tabellen gefallen, der Regenbogenbalken oben
   gefaellt, die Richtung stimmt. Nicht gefallen: Checkliste, nummerierte Liste, Kernbefunde,
   und «die Checkmarks sehen komisch aus». Besser gehen: Merken-Box, Pull-Zitat, Blockquote,
   Stat-Karte. Und der Satz, der die erste Fassung erklaert: «muss noch ein bisschen mehr weg
   kommen von dem ruhigen, tut mir leid dass das so fest dich genommen hat, das will ich gar
   nicht.»

   WAS ICH FALSCH GELESEN HATTE
   `rules.md` sagt «ruhig und premium statt gamifiziertem Laerm». Ich habe daraus «grau» gemacht.
   Der Satz richtet sich aber gegen Konfetti, Streaks und Badges, nicht gegen Farbe und Form -
   dieselbe Marke haelt zehn Farbtoene, 88 gezeichnete Silhouetten und eine komplette
   Bewegungs-Sprache bereit. Ruhig heisst hier: keine Effekthascherei. Nicht: keine Gestalt.

   DIE REGEL, DIE BLEIBT
   Signalfarbe ist Flaeche oder Kante, nie Textfarbe im Fliesstext. Sie wird jetzt aber wirklich
   FLAECHE - gefuellt, nicht als 4-Prozent-Hauch - und der Text darauf ist Paper.
   ============================================================================================ */

/* Die Toene eine Stufe kraeftiger: die Flaeche traegt jetzt Text, also muss sie tragen. */
.post-layout{
  --ton-voll-l:52%;  --ton-voll-c:0.16;   /* gefuellte Flaeche, Paper-Text darauf */
  --ton-flaeche-l:94%; --ton-flaeche-c:0.045;
  --ton-kante-l:52%; --ton-kante-c:0.15;
}
:root[data-theme="dark"] .post-layout{
  --ton-voll-l:74%;  --ton-voll-c:0.14;   /* im Dunkeln traegt die Flaeche Ink */
  --ton-flaeche-l:28%; --ton-flaeche-c:0.06;
  --ton-kante-l:78%; --ton-kante-c:0.13;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .post-layout{
    --ton-voll-l:74%;  --ton-voll-c:0.14;
    --ton-flaeche-l:28%; --ton-flaeche-c:0.06;
    --ton-kante-l:78%; --ton-kante-c:0.13;
  }
}
/* Was auf einer gefuellten Flaeche steht: im Hellen Paper, im Dunkeln Ink. */
.post-layout{--auf-voll:var(--paper)}
:root[data-theme="dark"] .post-layout{--auf-voll:var(--ink)}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .post-layout{--auf-voll:var(--ink)}}

/* --------------------------------------------------------------------------------------------
   17a · CHECKLISTE: das Haekchen raus, das Spiel-Zeichen rein
   -------------------------------------------------------------------------------------------
   Ein Haken ist ein Formular-Zeichen. roughly hat eigene Zeichen, aus echten Bildern
   nachgezeichnet, und die geben jeder Zeile ein Gesicht statt eines Abhak-Rituals. `post.js`
   setzt je Zeile das Zeichen des Spiels an dieser Position; es zeichnet sich beim Erscheinen.
   Die Kachel ist GEFUELLT, nicht getoent: das ist die Farbe, die Esteban vermisst hat. */
.post-layout .article__body .post-checkliste__list li::before,
.post-layout .article__body .post-checkliste ul li::before,
.post-layout .article__body .post-checkliste__list li::after,
.post-layout .article__body .post-checkliste ul li::after{content:none !important}

.post-layout .article__body .post-marke{
  position:absolute;left:0;top:calc(var(--s3) - 1px);
  display:grid;place-items:center;
  width:38px;height:38px;border-radius:12px;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  color:var(--auf-voll);
  transition:transform var(--d-fast, 180ms) var(--ease-o, ease-out);
}
.post-layout .article__body .post-marke .post-pikto{
  width:21px;height:21px;margin:0;stroke:var(--auf-voll);stroke-width:2;
}
.post-layout .article__body .post-checkliste__list li.has-marke,
.post-layout .article__body .post-checkliste ul li.has-marke{
  padding-left:56px;min-height:38px;
  display:flex;align-items:center;
}
.post-layout .article__body .post-checkliste__list li:hover .post-marke,
.post-layout .article__body .post-checkliste ul li:hover .post-marke{transform:scale(1.06) rotate(-3deg)}

/* --------------------------------------------------------------------------------------------
   17b · NUMMERIERTE LISTE: die Zahl sitzt IN der Farbe
   -------------------------------------------------------------------------------------------
   Vorher ein blasser Kreis mit farbiger Ziffer. Jetzt umgekehrt: gefuellter Kreis, Ziffer in
   Paper. Dieselbe Logik wie die Runden-Punkte im Spiel - der Zaehler ist die Sache. */
.post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
  width:32px;height:32px;top:calc(var(--s3) - 2px);
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  color:var(--auf-voll);
  font-size:var(--t-sm);font-weight:700;font-variant-numeric:tabular-nums;
  transition:transform var(--d-fast, 180ms) var(--ease-o, ease-out);
}
.post-layout .article__body .post-list li,.post-layout .article__body ol li{padding-left:52px;min-height:32px;display:flex;align-items:center}
.post-layout .article__body .post-list li:hover::before,.post-layout .article__body ol li:hover::before{transform:scale(1.08)}

/* --------------------------------------------------------------------------------------------
   17c · KERNBEFUNDE: das Blatt, nicht die Liste
   -------------------------------------------------------------------------------------------
   Kernbefunde und Checkliste rendern durch denselben Renderer und sahen darum identisch aus -
   genau der Grund, warum Esteban beide zusammen abgelehnt hat. Sie sind aber verschiedene
   Dinge: die Checkliste ist etwas zum TUN, die Kernbefunde sind das ERGEBNIS einer Messung.
   Das Ergebnis gehoert bei roughly auf das Reveal-Blatt: weicher Radius, Schatten nach oben,
   Griff-Strich, und der Regenbogen an der Kante, weil ein Befund die ganze Familie betrifft.
   Der Kasten steht direkt unter der H1, ist also das Erste, was man sieht. */
.post-layout .article__body .post-checkliste.is-befund{
  position:relative;max-width:none;
  padding:var(--s6) var(--s5) var(--s5);
  background:var(--paper);border-radius:var(--r-lg);
  box-shadow:var(--shadow-up);overflow:hidden;
}
.post-layout .article__body .post-checkliste.is-befund::before{
  content:"";position:absolute;left:0;top:0;width:100%;height:4px;
  background:var(--regenbogen);
}

/* --------------------------------------------------------------------------------------------
   17d · MERKEN-BOX: das Blatt traegt jetzt Gewicht
   -------------------------------------------------------------------------------------------
   Der Satz, den man behaelt, ist bei einer Schaetz-Marke fast immer eine Zahl in einem Satz.
   Also: groesser, breiter, mit dem Regenbogen im Griff (Variante B war Estebans Kandidat und
   wird hier der Default des Elements) und dem Plusminus der Wortmarke als leiser Signatur. */
.post-layout .article__body .post-highlight{
  max-width:none;padding:var(--s7) var(--s6) var(--s6);
  font-size:var(--t-xl);font-weight:600;line-height:1.25;letter-spacing:var(--tight);
  border-radius:var(--r-lg);
}
.post-layout .article__body .post-highlight::before{
  width:52px;height:5px;background:var(--regenbogen);top:14px;margin-left:-26px;
}
/* Das Zeichen der Marke unten rechts, klein und ruhig: dasselbe Plusminus wie im Logo. */
.post-layout .article__body .post-highlight::after{
  content:"\00B1";position:absolute;right:var(--s5);bottom:var(--s4);
  font-size:var(--t-lg);font-weight:700;line-height:1;
  color:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));opacity:.5;
}

/* --------------------------------------------------------------------------------------------
   17e · PULL-ZITAT: die Aussage bekommt eine Stimme
   -------------------------------------------------------------------------------------------
   Vorher zwei graue Haarlinien um einen Satz. Jetzt: eine kraeftige Kante der Familie links,
   die Aussage gross, und die letzte Zeile als Zuschreibung (kleiner, Tinte 2, mit einem
   vorangestellten Strich). Wer nur einen Satz schreibt, bekommt nur die Aussage - die
   Zuschreibung erscheint, wenn eine zweite Zeile da ist. */
.post-layout .article__body .post-pull{
  border-top:0;border-bottom:0;
  border-left:4px solid transparent;border-image:var(--regenbogen) 1;border-image-slice:1;
  padding:var(--s2) 0 var(--s2) var(--s5);
  margin:var(--s7) 0;
  font-size:var(--t-xl);font-weight:600;line-height:1.28;letter-spacing:var(--tight);
  color:var(--ink);max-width:28ch;
}
.post-layout .article__body .post-pull p:last-child:not(:only-child){
  margin:var(--s3) 0 0;font-size:var(--t-sm);font-weight:500;letter-spacing:0;
  color:var(--ink-2);
}
.post-layout .article__body .post-pull p:last-child:not(:only-child)::before{content:"\2014\00A0"}

/* --------------------------------------------------------------------------------------------
   17f · BLOCKQUOTE: fremde Rede, mit Herkunft
   -------------------------------------------------------------------------------------------
   Deutlicher abgesetzt als vorher (getoente Flaeche statt einer Haarlinie), aber leiser als das
   Pull-Zitat: das eine ist unsere Aussage, das andere jemandes Satz. Die letzte Zeile ist
   wieder die Zuschreibung. */
.post-layout .article__body blockquote{
  border-left:3px solid oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h3, 150));
  background:oklch(var(--ton-flaeche-l) var(--ton-flaeche-c) var(--h3, 150));
  border-radius:0 var(--r-sm) var(--r-sm) 0;
  padding:var(--s4) var(--s5);margin:var(--s6) 0;
  font-size:var(--t-md);color:var(--ink);line-height:1.5;
}
.post-layout .article__body blockquote p:last-child:not(:only-child){
  margin:var(--s3) 0 0;font-size:var(--t-sm);color:var(--ink-2);
}
.post-layout .article__body blockquote p:last-child:not(:only-child)::before{content:"\2014\00A0"}

/* --------------------------------------------------------------------------------------------
   17g · STAT-KARTE: die Zahl bekommt ihre Kurve
   -------------------------------------------------------------------------------------------
   Der eigentliche Fehler der ersten Fassung: im Spiel steht die Zahl nie allein, unter ihr
   liegt die Kurve mit Flaeche, eigenem Strich und Wahrheit. `post.js` zeichnet sie jetzt.
   Die Kurve ist GEZEICHNET, nicht gemessen - darum traegt sie keine Beschriftung, die eine
   Spieler-Verteilung behaupten wuerde (dieselbe Ehrlichkeits-Regel wie auf About). */
.post-layout .article__body .post-stat{
  border-top:0;padding:var(--s5) 0 0;position:relative;
}
.post-layout .article__body .post-stat::before{
  content:"";position:absolute;left:0;top:0;width:72px;height:4px;border-radius:2px;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
}
.post-layout .article__body .post-stat__num{
  color:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  letter-spacing:-0.05em;
}
.post-layout .article__body .post-kurve{
  display:block;width:100%;max-width:420px;height:46px;margin:var(--s4) 0 0;overflow:visible;
}
.post-layout .article__body .post-kurve__flaeche{
  fill:oklch(var(--ton-flaeche-l) calc(var(--ton-flaeche-c) * 2) var(--h, 255));
}
.post-layout .article__body .post-kurve__linie{
  fill:none;stroke:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  stroke-width:1.6;vector-effect:non-scaling-stroke;
}
.post-layout .article__body .post-kurve__marke{
  stroke:var(--ink);stroke-width:1.2;stroke-dasharray:3 3;vector-effect:non-scaling-stroke;
}

/* --------------------------------------------------------------------------------------------
   17h · RANGLISTE: Label kraeftig, Wert in seiner Farbe
   -------------------------------------------------------------------------------------------
   Estebans zwei Fragen, beide berechtigt: «warum sind die Meter dort gruen» (der Renderer setzte
   den Wert hart auf --accent-dark, also Seonars Ton - jetzt traegt er die Farbe SEINER Zeile,
   gesetzt von post.js) und «warum sind die verschiedenen Dinge nur dunkel» (das Label stand in
   --body, dem leisesten Ton - jetzt Tinte und Gewicht 600, denn es benennt die Sache).
   Dazu: dickere Balken, mehr Zeilenhoehe, und die Spur sichtbar statt fast weiss. */
.post-layout .article__body .post-figure svg .rang__label{
  fill:var(--ink);font-weight:600;font-size:15px;
}
.post-layout .article__body .post-figure svg .rang__wert{
  font-family:var(--font, var(--font-body));font-weight:700;font-size:15px;
}
.post-layout .article__body .post-figure svg .rang__titel{
  fill:var(--ink-2);font-weight:600;text-transform:none;letter-spacing:0;
}
.post-layout .article__body .post-figure svg .rang__basis{
  fill:var(--ink-3);font-family:var(--font, var(--font-body));
}

/* ============================================================================================
   18 · NACHTRAEGE DER ZWEITEN RUNDE (#729) — alle sechs am gerenderten Blatt gemessen
   ============================================================================================ */

/* (a) DAS PULL-ZITAT STAND ZENTRIERT. Die Basis-Schicht setzt `text-align:center`; ein
   zentrierter Fliesstext-Block ist in dieser Marke nirgends zu Hause (jede Leseseite ist
   linksbuendig). Gemessen: align=center bei 519px Breite, also fuenf gefangene Zeilen. */
.post-layout .article__body .post-pull{text-align:left}

/* (b) DIE REGENBOGEN-KANTE ZEIGTE NUR EINE FARBE. Ein 90-Grad-Verlauf auf einer 4px BREITEN,
   200px HOHEN Kante schneidet genau das linke Ende heraus - man sah Orange und hielt es fuer
   den Akzent. Eine vertikale Kante braucht einen vertikalen Verlauf. */
.post-layout{
  --regenbogen-quer:linear-gradient(180deg in oklch,
    oklch(78% 0.14 40) 0%, oklch(78% 0.14 75) 11%, oklch(78% 0.14 150) 22%,
    oklch(78% 0.14 178) 33%, oklch(78% 0.14 205) 44%, oklch(78% 0.14 235) 56%,
    oklch(78% 0.14 262) 67%, oklch(78% 0.14 300) 78%, oklch(78% 0.14 320) 89%,
    oklch(78% 0.14 350) 100%);
}
.post-layout .article__body .post-pull{border-image:var(--regenbogen-quer) 1;border-image-slice:1}

/* (c) DAS PIKTOGRAMM SPRENGTE SEINE KACHEL (gemessen 52px in einer 38px-Kachel). Ein SVG ohne
   gesetzte Groesse nimmt seine viewBox-Einheiten; die em-Regel weiter oben greift nur, wo eine
   Schriftgroesse gilt. In der Kachel wird die Groesse hart gesetzt. */
.post-layout .article__body .post-marke .post-pikto,
.post-layout .article__body .post-marke svg{width:21px !important;height:21px !important;margin:0}

/* (d) DIE KURVE DER STAT-KARTE WAR 90px BREIT. `.post-stat` ist ein Flex-Container (die Zahl
   neben dem Label), das nachtraeglich angehaengte SVG wurde damit ein Flex-Kind und schrumpfte
   auf seinen Inhalt. Sie gehoert unter beides, ueber die volle Breite. */
.post-layout .article__body .post-stat{display:block}
.post-layout .article__body .post-kurve{width:100%;max-width:420px;height:46px;flex:none}

/* (e) DER KERNBEFUNDE-KASTEN IST JETZT EIN EIGENES GERAET. `grafik.py` setzt
   `post-checkliste--befund`, wenn der Block `art = befund` traegt. Das Ergebnis einer Messung
   gehoert bei roughly auf das Reveal-Blatt: weicher Radius, Schatten nach oben, und die
   Regenbogen-Kante oben, weil ein Befund die ganze Familie betrifft. */
.post-layout .article__body .post-checkliste--befund{
  position:relative;padding:var(--s7) var(--s5) var(--s5);
  background:var(--paper);border-radius:var(--r-lg);
  box-shadow:var(--shadow-up);overflow:hidden;margin:var(--s6) 0;
}
.post-layout .article__body .post-checkliste--befund::before{
  content:"";position:absolute;left:0;top:0;width:100%;height:4px;
  background:var(--regenbogen);
}
.post-layout .article__body .post-checkliste--befund .post-checkliste__titel{
  font-size:var(--t-lg);font-weight:600;margin-bottom:var(--s3);
}
/* Im Befund-Kasten traegt die Zeile keine Marke, sondern die ZAHL des Befunds: er ist ein
   Ergebnis, keine Aufgabe. Die Piktogramm-Kacheln bleiben der Checkliste. */
.post-layout .article__body .post-checkliste--befund .post-marke{display:none}
.post-layout .article__body .post-checkliste--befund li{padding-left:0 !important;display:block}
.post-layout .article__body .post-checkliste--befund li:first-child{border-top:0}

/* (f) DAS BLOCKQUOTE FEHLTE GANZ (gemessen: 0 im Dokument). Der Renderer erkennt nur
   aufeinanderfolgende `>`-Zeilen ohne Leerzeile dazwischen; mein Beispiel hatte eine. Das ist
   im Beispiel behoben. Hier bleibt die Gestalt: die letzte Zeile ist die Zuschreibung. */
.post-layout .article__body blockquote br + *{display:block}

/* (g) DER BEFUND-KASTEN HOB SICH NICHT AB. Weisses Blatt auf weisser Seite plus ein sehr
   weicher Schatten nach oben ergibt gemessen nichts Sichtbares. Das Reveal-Blatt im Spiel
   steht auf einer dunkleren Buehne; im Text uebernimmt die zweite Papier-Stufe diese Rolle,
   und die Regenbogen-Kante oben bleibt seine Marke. */
.post-layout .article__body .post-checkliste--befund{
  background:var(--paper-2);
  box-shadow:none;
  border:1px solid var(--line);
}
.post-layout .article__body .post-checkliste--befund li{border-top-color:var(--line-strong)}

/* (h) DAS ZEICHEN RAGTE AUS SEINER KACHEL. Gemessen 52x48 in einer 38er Kachel: ein SVG ohne
   width/height-Attribut nimmt seine viewBox-Einheiten, und die em-Regel greift erst, wenn
   ueberhaupt eine Box da ist. Groesse steht jetzt am Element (post.js); die Kachel klippt
   zusaetzlich, damit nichts uebersteht. */
.post-layout .article__body .post-marke{overflow:hidden}
.post-layout .article__body .post-marke svg{width:22px !important;height:22px !important;display:block}

/* ============================================================================================
   19 · DRITTE RUNDE (#729) — Estebans Urteil an Fassung 2
   ============================================================================================
   Behalten: Rangliste («ist geil»), Tabelle («sehr gut»), Pull-Zitat, Fliesstext+Link,
   Merken-Box, Befund-Kasten («gut, aber zu langweilig»).
   Neu: Checkliste (das Zeichen fehlte), nummerierte Liste, Stat-Karte («einfach eine Zahl mit
   einem Strich»), Blockquote («extrem scheisse»), Zwischenueberschriften, mehr Bewegung, und
   der Knopf mit dem Regenbogen-Hover der Navigation.
   ============================================================================================ */

/* --------------------------------------------------------------------------------------------
   19a · DAS ZEICHEN ALS MASKE (der vierte Anlauf, anderer Mechanismus)
   -------------------------------------------------------------------------------------------
   Drei Anlaeufe mit einem eingehaengten <svg> sind am selben Punkt gescheitert: gemessen rendert
   das Element 52x48, sein erstes <rect> aber 6x8 an der unteren Kante - die viewBox wird nicht
   angewandt. Kein CSS der Welt repariert das, weil nicht die Breite das Problem ist.
   Jetzt ist der Pfad die MASKE einer Farbflaeche: die Groesse macht `mask-size`, die Farbe das
   Thema, und es gibt kein skalierendes Element mehr. */
.post-layout .article__body .post-marke{
  position:absolute;left:0;top:calc(var(--s3) - 2px);
  display:block;width:40px;height:40px;border-radius:13px;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  overflow:hidden;
  transition:transform var(--d-fast, 180ms) var(--ease-o, ease-out),
             box-shadow var(--d-fast, 180ms) var(--ease, ease);
}
.post-layout .article__body .post-marke__z{
  display:block;width:100%;height:100%;
  background:var(--auf-voll);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:22px 22px;mask-size:22px 22px;
}
.post-layout .article__body .post-checkliste__list li.has-marke,
.post-layout .article__body .post-checkliste ul li.has-marke{
  padding-left:58px;min-height:40px;display:flex;align-items:center;
}
/* Beim Zeigen kippt die Kachel leicht und bekommt Tiefe - dieselbe kleine Reaktion wie die
   Geraete-Karten auf der Landing. */
.post-layout .article__body .post-checkliste__list li:hover .post-marke,
.post-layout .article__body .post-checkliste ul li:hover .post-marke{
  transform:rotate(-4deg) scale(1.06);
  box-shadow:0 4px 14px oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255) / .35);
}

/* Das Zeichen ausserhalb einer Kachel (Kategorie-Zeile, Knopf): dieselbe Maske, aber die
   Farbe der Zeile bzw. Paper auf dem Knopf. */
.post-layout .post-zeichen{
  display:inline-block;width:1.15em;height:1.15em;vertical-align:-0.2em;margin-right:0.45em;
  background:oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255));
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
}
.post-layout .article__body .post-cta .post-zeichen--knopf{
  background:var(--paper);width:1.2em;height:1.2em;margin-right:0.5em;
}

/* --------------------------------------------------------------------------------------------
   19b · NUMMERIERTE LISTE: die Zahl wird zum Runden-Punkt
   -------------------------------------------------------------------------------------------
   Vorher ein gefuellter Kreis mit Ziffer, also dasselbe Geraet wie die Checkliste in rund -
   und darum langweilig. roughly hat fuer eine Abfolge ein eigenes Zeichen: die fuenf
   Runden-Punkte unter der Marken-Zeile (`.pips`). Die Zeile bekommt darum links eine SPUR aus
   Punkten, von denen genau einer gefuellt ist: der aktuelle Schritt. Man sieht die Abfolge,
   bevor man die Zahlen liest. */
.post-layout .article__body .post-list,.post-layout .article__body ol{counter-reset:rl}
.post-layout .article__body .post-list li,.post-layout .article__body ol li{
  counter-increment:rl;position:relative;
  padding-left:64px;min-height:40px;display:flex;align-items:center;
  border-top:1px solid var(--line);
}
.post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
  content:counter(rl);
  position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:34px;height:34px;border-radius:var(--r-full);
  display:grid;place-items:center;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  color:var(--auf-voll);
  font-size:var(--t-sm);font-weight:700;font-variant-numeric:tabular-nums;
  transition:transform var(--d-fast, 180ms) var(--ease-o, ease-out),
             box-shadow var(--d-fast, 180ms) var(--ease, ease);
}
/* Der Faden zwischen den Schritten: eine Haarlinie in der Farbe des naechsten Punktes. */
.post-layout .article__body .post-list li::after,.post-layout .article__body ol li::after{
  content:"";position:absolute;left:16px;top:calc(50% + 17px);width:2px;height:calc(100% - 34px);
  background:oklch(var(--ton-flaeche-l) calc(var(--ton-flaeche-c) * 2) var(--h, 255));
}
.post-layout .article__body .post-list li:last-child::after,.post-layout .article__body ol li:last-child::after{display:none}
.post-layout .article__body .post-list li:hover::before,.post-layout .article__body ol li:hover::before{
  transform:translateY(-50%) scale(1.1);
  box-shadow:0 4px 14px oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255) / .35);
}

/* --------------------------------------------------------------------------------------------
   19c · STAT-KARTE: das Reveal-Blatt, nicht eine Zahl mit einem Strich
   -------------------------------------------------------------------------------------------
   Estebans Urteil war praezise: «einfach eine Zahl mit einem Strich, das sieht kacke aus». Der
   Fehler war, dass ich die Zahl NEBEN das Geraet gestellt habe statt hinein. Im Spiel ist der
   Reveal EIN Gegenstand: ein Blatt, das aufsteigt, mit der Zahl gross darauf, der Einordnung
   darunter, der Kurve am Fuss und der Quelle klein. Genau das wird die Stat-Karte jetzt.
   Der Farbton ist der des Posts; auf dem Blatt liegt eine getoente Flaeche derselben Familie. */
.post-layout .article__body .post-stat{
  position:relative;overflow:hidden;
  margin:var(--s7) 0;padding:var(--s6) var(--s5) var(--s5);
  background:var(--paper);border:0;border-radius:var(--r-lg);
  box-shadow:var(--shadow-up);
}
.post-layout .article__body .post-stat::before{
  content:"";position:absolute;left:0;top:0;width:100%;height:5px;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
}
/* Der Griff wie am Reveal-Blatt: der Gegenstand ist derselbe. */
.post-layout .article__body .post-stat::after{
  content:"";position:absolute;top:16px;left:50%;width:36px;height:5px;margin-left:-18px;
  border-radius:var(--r-full);background:var(--line);
}
.post-layout .article__body .post-stat__num{
  display:block;margin-top:var(--s4);
  font-size:var(--t-mega);font-weight:700;line-height:.92;letter-spacing:-0.05em;
  color:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  font-variant-numeric:tabular-nums;
}
.post-layout .article__body .post-stat__label{
  display:block;margin-top:var(--s2);
  font-size:var(--t-lg);font-weight:600;color:var(--ink);letter-spacing:var(--tight);
}
.post-layout .article__body .post-stat p{margin-top:var(--s2);font-size:var(--t-md);color:var(--ink-2);max-width:46ch}
.post-layout .article__body .post-stat figcaption{
  margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid var(--line);
  font-size:var(--t-xs);color:var(--ink-3);
}
.post-layout .article__body .post-kurve{
  display:block;width:100%;max-width:none;height:56px;margin:var(--s5) 0 0;
}
.post-layout .article__body .post-kurve__flaeche{fill:oklch(var(--ton-flaeche-l) calc(var(--ton-flaeche-c) * 2.4) var(--h, 255))}
.post-layout .article__body .post-kurve__linie{
  fill:none;stroke:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  stroke-width:2;vector-effect:non-scaling-stroke;
}
.post-layout .article__body .post-kurve__marke{stroke:var(--ink);stroke-width:1.4;stroke-dasharray:3 3;vector-effect:non-scaling-stroke}

/* --------------------------------------------------------------------------------------------
   19d · BLOCKQUOTE: fremde Rede bekommt ein Gefaess
   -------------------------------------------------------------------------------------------
   «Extrem scheisse» war die getoente Flaeche mit der duennen Kante: sie sah aus wie ein
   Hinweiskasten aus einem Baukasten, nicht wie ein Zitat. Jetzt: kein Kasten, sondern ein
   grosses Anfuehrungszeichen aus der eigenen Schrift als Marke, der Satz gross daneben, und
   die Zuschreibung als Zeile mit Strich darunter. Die Farbe traegt nur das Zeichen. */
.post-layout .article__body blockquote{
  position:relative;background:none;border:0;border-radius:0;
  margin:var(--s7) 0;padding:0 0 0 56px;
  font-size:var(--t-lg);font-weight:500;line-height:1.4;color:var(--ink);max-width:40ch;
}
.post-layout .article__body blockquote::before{
  content:"\201C";position:absolute;left:0;top:-14px;
  font-size:76px;line-height:1;font-weight:700;
  color:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h3, 150));
}
.post-layout .article__body blockquote p{margin:0 0 var(--s2);max-width:none;color:inherit;font-size:inherit}
.post-layout .article__body blockquote p:last-child:not(:only-child){
  margin-top:var(--s4);font-size:var(--t-sm);font-weight:500;color:var(--ink-2);
  padding-top:var(--s3);border-top:1px solid var(--line);
}
.post-layout .article__body blockquote p:last-child:not(:only-child)::before{content:none}

/* --------------------------------------------------------------------------------------------
   19e · BEFUND-KASTEN: weniger langweilig
   -------------------------------------------------------------------------------------------
   Er war «gut, aber zu langweilig»: eine graue Flaeche mit Zeilen. Jetzt traegt jede Zeile den
   Punkt ihrer Farbe, und der Kasten steht auf Papier mit der Regenbogen-Kante - er ist das
   Ergebnis, also das Hellste auf der Seite, nicht das Grauste. */
.post-layout .article__body .post-checkliste--befund{
  background:var(--paper);border:1px solid var(--line);
  box-shadow:var(--shadow-1);
}
.post-layout .article__body .post-checkliste--befund li{
  position:relative;padding-left:26px !important;
  border-top:1px solid var(--line);
}
.post-layout .article__body .post-checkliste--befund li::before{
  content:"";position:absolute;left:0;top:calc(var(--s3) + 0.55em);
  width:10px;height:10px;border-radius:var(--r-full);
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
}
.post-layout .article__body .post-checkliste--befund li:nth-child(10n+1){--h:var(--f1)}
.post-layout .article__body .post-checkliste--befund li:nth-child(10n+2){--h:var(--f2)}
.post-layout .article__body .post-checkliste--befund li:nth-child(10n+3){--h:var(--f3)}
.post-layout .article__body .post-checkliste--befund li:nth-child(10n+4){--h:var(--f4)}
.post-layout .article__body .post-checkliste--befund li:nth-child(10n+5){--h:var(--f5)}

/* --------------------------------------------------------------------------------------------
   19f · DER KNOPF MIT DEM REGENBOGEN DER NAVIGATION (Estebans Idee)
   -------------------------------------------------------------------------------------------
   «Du kannst ihn eventuell so machen wie auf der Navigation der Regenbogen ist, wenn man
   darueber hovert.» Die Nav macht es so (`play.css` .rb__over): ein Regenbogen-Layer laeuft
   dauerhaft, und eine MASKEN-Position schiebt ihn beim Zeigen von rechts nach links herein.
   Dieselbe Mechanik, nur als Flaeche statt als Textfuellung - und mit derselben Kurve und
   Dauer, damit Knopf und Navigation sich gleich anfuehlen. */
.post-layout .article__body .post-cta a{position:relative;overflow:hidden;isolation:isolate}
.post-layout .article__body .post-cta a::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:var(--regenbogen);background-size:200% 100%;
  animation:post-rb 3.2s linear infinite;
  -webkit-mask-image:linear-gradient(90deg,#000 0 40%,transparent 60% 100%);
  mask-image:linear-gradient(90deg,#000 0 40%,transparent 60% 100%);
  -webkit-mask-size:250% 100%;mask-size:250% 100%;
  -webkit-mask-position:100% 0;mask-position:100% 0;
  transition:-webkit-mask-position 1.1s cubic-bezier(.45,.05,.2,1),
             mask-position 1.1s cubic-bezier(.45,.05,.2,1);
}
.post-layout .article__body .post-cta a:hover::before,.post-layout .article__body .post-cta a:focus-visible::before{
  -webkit-mask-position:0 0;mask-position:0 0;
}
@keyframes post-rb{from{background-position:0 0}to{background-position:-200% 0}}
/* Auf dem Regenbogen steht Tinte, nicht Paper: die Farben sind hell. */
.post-layout .article__body .post-cta a:hover,.post-layout .article__body .post-cta a:focus-visible{
  background:var(--ink);color:var(--paper);
}
.post-layout .article__body .post-cta a:hover .post-zeichen--knopf{background:var(--paper)}

/* --------------------------------------------------------------------------------------------
   19g · ZWISCHENUEBERSCHRIFTEN: eine Spur mehr
   -------------------------------------------------------------------------------------------
   «Geht besser»: sie waren korrekt und unauffaellig. Jetzt traegt jede H2 links einen kurzen
   Strich in der Farbe des Posts - dieselbe Marke, die die Stat-Karte oben traegt, eine Stufe
   kleiner. Man sieht beim Ueberfliegen, wo ein Kapitel beginnt. */
.post-layout .article__body h2{position:relative;padding-left:0}
.post-layout .article__body h2::before{
  content:"";display:block;width:44px;height:4px;border-radius:2px;margin:0 0 var(--s3);
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
}

/* --------------------------------------------------------------------------------------------
   19h · MEHR BEWEGUNG, aber weiter mit Grund
   -------------------------------------------------------------------------------------------
   Estebans Wunsch nach mehr Bewegung, ohne dass es Rauschen wird: die Listen bauen sich
   gestaffelt auf, wenn sie in den Blick kommen (`post.js` setzt `is-da`). Das ist die
   Sibling-Staffelung aus der Motion-Doktrin - erlaubt, weil eine Liste wirklich als Liste
   erscheint - mit gedeckelter Gesamtdauer. */
.post-layout .article__body .post-checkliste li,.post-layout .article__body .post-list li,.post-layout .article__body ol li,
.post-layout .article__body .post-checkliste--befund li{
  transition:opacity 420ms var(--ease-o, ease-out), transform 420ms var(--ease-o, ease-out),
             background var(--d-fast, 180ms) var(--ease, ease);
}
.post-layout .article__body .is-still li{opacity:0;transform:translateY(8px)}
.post-layout .article__body .is-da li{opacity:1;transform:none}
.post-layout .article__body .is-da li:nth-child(1){transition-delay:0ms}
.post-layout .article__body .is-da li:nth-child(2){transition-delay:70ms}
.post-layout .article__body .is-da li:nth-child(3){transition-delay:140ms}
.post-layout .article__body .is-da li:nth-child(4){transition-delay:210ms}
.post-layout .article__body .is-da li:nth-child(5){transition-delay:280ms}
.post-layout .article__body .is-da li:nth-child(n+6){transition-delay:340ms}
@media (prefers-reduced-motion: reduce){
  .post-layout .article__body .is-still li{opacity:1;transform:none}
  .post-layout .article__body .post-cta a::before{animation:none}
}

/* (i) NACHTRAEGE ZUR STAT-KARTE, am Blatt gemessen:
   - Das Blatt hatte keine sichtbare Kante. Weiss auf Weiss plus ein sehr weicher Schatten nach
     oben ergibt eine Karte, die man nicht als Karte liest. Eine Haarlinie macht sie zum
     Gegenstand, ohne sie zum Kasten zu machen.
   - Die Kurve war ueber die volle Spaltenbreite gezogen (720px bei einer 200er viewBox mit
     preserveAspectRatio none) und darum fast flach. Eine Verteilung, die man nicht als
     Verteilung erkennt, ist keine. Sie bekommt ihre Breite zurueck. */
.post-layout .article__body .post-stat{border:1px solid var(--line)}
.post-layout .article__body .post-kurve{max-width:460px;height:64px}

/* (j) DIE PUNKTE DES BEFUND-KASTENS FEHLTEN. Die Checklisten-Regel weiter oben schaltet
   `::before` mit `content:none !important` ab (das war der Weg, das Haekchen loszuwerden), und
   die Befund-Regel hatte kein Gegengewicht. Ein `!important` gegen ein `!important` ist keine
   schoene Loesung, aber die ehrliche: beide Elemente teilen sich denselben Renderer, also auch
   dieselben Selektoren, und der Unterschied muss irgendwo erzwungen werden. */
.post-layout .article__body .post-checkliste--befund li::before{
  content:"" !important;
  position:absolute;left:0;top:calc(var(--s3) + 0.55em);
  width:10px;height:10px;border-radius:var(--r-full);
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
}
.post-layout .article__body .post-checkliste--befund li::after{content:none !important}

/* ============================================================================================
   20 · VIERTE RUNDE (#729) — WEGNEHMEN statt hinzufuegen
   ============================================================================================
   Estebans Urteil: die Kurve auf der Stat-Karte kommt weg («dieses Wellen-Diagramm nehme ich
   nicht»), der farbige Strich oben ist unnoetig, der Griff darunter auch. Die Checkliste
   braucht ihre Haken. Die nummerierte Liste soll «viel simpler» und dafuer eine gute Animation
   bekommen.

   Die Lehre der Runde: ich habe auf «mehr» mit «mehr Teilen» geantwortet. Was fehlte, war nicht
   Zubehoer, sondern Kraft an EINER Stelle. Hier wird darum abgeraeumt.
   ============================================================================================ */

/* --------------------------------------------------------------------------------------------
   20a · STAT-KARTE: nur noch die Zahl
   -------------------------------------------------------------------------------------------
   Weg: die Kurve, die Kante oben, der Griff, der Rahmen, der Schatten, das Blatt.
   Bleibt: die Zahl, so gross wie das Blatt sie traegt, in der Farbe des Posts, mit der
   Einordnung darunter. Genau das, was im Spiel nach dem Tipp zuerst da ist. Der einzige
   Schmuck ist die tabellarische Ziffernbreite, und die ist kein Schmuck, sondern Handwerk. */
.post-layout .article__body .post-stat{
  background:none !important;border:0 !important;border-radius:0 !important;
  box-shadow:none !important;overflow:visible;
  margin:var(--s7) 0;padding:0;
}
.post-layout .article__body .post-stat::before,.post-layout .article__body .post-stat::after{content:none !important}
.post-layout .article__body .post-kurve{display:none !important}
.post-layout .article__body .post-stat__num{
  display:block;margin:0;
  font-size:clamp(4rem, 12vw, 6.5rem);font-weight:700;line-height:.9;letter-spacing:-0.055em;
  color:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  font-variant-numeric:tabular-nums;
}
.post-layout .article__body .post-stat__label{
  display:block;margin-top:var(--s3);
  font-size:var(--t-lg);font-weight:600;color:var(--ink);letter-spacing:var(--tight);
}
.post-layout .article__body .post-stat p{margin-top:var(--s2);font-size:var(--t-md);color:var(--ink-2);max-width:46ch}
.post-layout .article__body .post-stat figcaption{
  margin-top:var(--s4);padding-top:0;border-top:0;
  font-size:var(--t-xs);color:var(--ink-3);
}

/* --------------------------------------------------------------------------------------------
   20b · CHECKLISTE: die Haken zurueck, diesmal gezeichnet
   -------------------------------------------------------------------------------------------
   «Bei der Checkliste brauche ich Checkmarks, diese Haken da.» Der erste Versuch war ein Haken
   aus zwei CSS-Kanten - der sass schief und sah darum komisch aus. Jetzt ist er ein echter,
   gezeichneter Pfad in derselben Strichstaerke wie die Spiel-Zeichen, als Maske gesetzt (der
   Mechanismus, der bei den Piktogrammen funktioniert hat), und er ZEICHNET sich beim
   Erscheinen: ein Haken, der gesetzt wird, ist eine Bewegung, die etwas bedeutet. */
.post-layout .article__body .post-marke__z{
  -webkit-mask-image:var(--haken) !important;mask-image:var(--haken) !important;
  -webkit-mask-size:20px 20px;mask-size:20px 20px;
}
.post-layout{
  --haken:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 12.5 L9.5 17.5 L19.5 6.5'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------------------------
   20c · NUMMERIERTE LISTE: viel simpler
   -------------------------------------------------------------------------------------------
   «Sieht auch scheisse aus, viel simpler, und eine geile Animation.»
   Weg: der gefuellte Kreis, der Faden, die Haarlinien zwischen den Zeilen, die zweite
   Farbflaeche. Bleibt: die Zahl selbst, gross, tabellarisch, in der Farbe ihrer Position, und
   der Satz daneben. Kein Gefaess - die Ziffer IST das Gefaess.
   Die Animation: die Zahl zaehlt beim Erscheinen von der vorigen hoch und die Zeile schiebt
   sich aus ihr heraus (`post.js`, Klasse `is-da`). Gestaffelt, gedeckelt, einmal. */
.post-layout .article__body .post-list li,.post-layout .article__body ol li{
  border-top:0 !important;
  padding:var(--s3) 0 var(--s3) 62px;min-height:0;
  display:block;position:relative;
  font-size:var(--t-md);line-height:1.45;color:var(--ink-2);
}
.post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
  content:counter(rl);
  position:absolute;left:0;top:calc(var(--s3) - 0.06em);transform:none;
  width:auto;height:auto;border-radius:0;background:none !important;box-shadow:none !important;
  display:block;text-align:left;
  font-size:2.1rem;font-weight:700;line-height:1;letter-spacing:-0.05em;
  font-variant-numeric:tabular-nums;
  color:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  transition:transform var(--d-mid, 360ms) var(--ease-o, ease-out),
             opacity var(--d-mid, 360ms) var(--ease, ease);
}
.post-layout .article__body .post-list li::after,.post-layout .article__body ol li::after{content:none !important}
.post-layout .article__body .post-list li:hover,.post-layout .article__body ol li:hover{background:none}
.post-layout .article__body .post-list li:hover::before,.post-layout .article__body ol li:hover::before{transform:translateY(-2px)}

/* Die Staffelung fuer die simple Liste: die Ziffer kommt zuerst, der Satz zieht nach. */
.post-layout .article__body .is-still li::before{opacity:0;transform:translateY(10px)}
.post-layout .article__body .is-da li::before{opacity:1;transform:none}
.post-layout .article__body .is-da li:nth-child(1)::before{transition-delay:60ms}
.post-layout .article__body .is-da li:nth-child(2)::before{transition-delay:130ms}
.post-layout .article__body .is-da li:nth-child(3)::before{transition-delay:200ms}
.post-layout .article__body .is-da li:nth-child(4)::before{transition-delay:270ms}
.post-layout .article__body .is-da li:nth-child(n+5)::before{transition-delay:330ms}
@media (prefers-reduced-motion: reduce){
  .post-layout .article__body .is-still li::before{opacity:1;transform:none}
}

/* ============================================================================================
   21 · FUENFTE RUNDE (#729) — SCROLLGEBUNDENE BEWEGUNG, und beide Listen neu
   ============================================================================================
   Estebans Urteil: «Checkliste, nummerierte Liste gefallen mir immer noch nicht. Ich brauche
   wirklich scrollbasierte Animationen.»

   WAS DER UNTERSCHIED IST, und warum die bisherigen Versuche daneben lagen
   Ich habe bisher AUSLOESER gebaut: ein Beobachter meldet «Element sichtbar», dann laeuft eine
   Animation ihre feste Zeit ab. Das ist Bewegung NEBEN dem Scrollen, nicht dadurch. Wer
   langsam scrollt, sieht sie zu frueh; wer schnell scrollt, verpasst sie.
   Scrollgebunden heisst: die Scroll-Position IST die Zeitachse. Man zieht die Bewegung mit dem
   Finger, und sie laeuft rueckwaerts, wenn man zurueckscrollt. Genau das kann roughly
   gebrauchen, weil im Spiel jede Bewegung an einer Geste haengt: ziehen, drehen, zeichnen.

   MECHANIK: `animation-timeline: view()` mit `animation-range`. Kein JavaScript, keine
   Beobachter, kein Ruckeln - der Compositor rechnet es. `animation-fill-mode: both` haelt den
   Endzustand, wenn das Element durch ist.

   FALLBACK, und er ist Pflicht: wo die Zeitachse fehlt, laeuft KEINE Animation und alles steht
   auf seinem Endzustand. Der ganze Block liegt darum in einem `@supports`, und die Regeln
   ausserhalb beschreiben den fertigen Zustand. Das ist dieselbe Regel, an der ich in dieser
   Session dreimal aufgelaufen bin: Bewegung darf Inhalt nur verdecken, wenn sie wirklich laeuft.
   ============================================================================================ */

/* --------------------------------------------------------------------------------------------
   21a · CHECKLISTE, NEU: die Zeile wird abgehakt, waehrend man sie liest
   -------------------------------------------------------------------------------------------
   Weg: die Farbkachel. Sie war ein Kasten, und drei Kaesten untereinander sind eine Tabelle mit
   Deko, kein Geraet.
   Das neue Geraet: die Zeile selbst. Links ein grosser, gezeichneter Haken in der Farbe ihrer
   Position, rechts der Satz, darunter eine Haarlinie, die von links nach rechts durchlaeuft.
   Beim Scrollen wird der Haken gezogen und die Linie waechst mit - man hakt die Liste
   buchstaeblich ab, indem man sie liest. */
.post-layout .article__body .post-checkliste__list li.has-marke,
.post-layout .article__body .post-checkliste ul li.has-marke{
  position:relative;display:block;
  padding:var(--s4) 0 var(--s4) 52px;min-height:0;
  border-top:0;border-bottom:0;
  font-size:var(--t-lg);font-weight:500;line-height:1.35;color:var(--ink);
}
/* Die Linie unter der Zeile: im Ruhezustand voll, scrollgebunden waechst sie. */
.post-layout .article__body .post-checkliste__list li.has-marke::after,
.post-layout .article__body .post-checkliste ul li.has-marke::after{
  content:"" !important;position:absolute;left:0;bottom:0;height:2px;width:100%;
  background:linear-gradient(90deg,
    oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255)) 0%,
    oklch(var(--ton-flaeche-l) calc(var(--ton-flaeche-c) * 2) var(--h, 255)) 100%);
  transform-origin:left center;
}
/* Der Haken: keine Kachel mehr, nur das Zeichen - gross, in der Farbe der Zeile. */
.post-layout .article__body .post-marke{
  position:absolute;left:0;top:calc(var(--s4) - 1px);
  width:34px;height:34px;border-radius:0;background:none !important;
  box-shadow:none !important;overflow:visible;transform:none !important;
}
.post-layout .article__body .post-marke__z{
  display:block;width:34px;height:34px;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255));
  -webkit-mask-size:34px 34px;mask-size:34px 34px;
}
.post-layout .article__body .post-checkliste__list li:hover .post-marke,
.post-layout .article__body .post-checkliste ul li:hover .post-marke{transform:none !important;box-shadow:none}

/* --------------------------------------------------------------------------------------------
   21b · NUMMERIERTE LISTE, NEU: eine Bahn, an der die Schritte haengen
   -------------------------------------------------------------------------------------------
   Weg: die freistehenden Ziffern. Sie waren simpel, aber sie zeigten keine ABFOLGE, und genau
   das ist der Zweck des Elements.
   Das neue Geraet: eine senkrechte Bahn am linken Rand, an der die Schritte sitzen. Beim
   Scrollen faehrt die Bahn mit - sie fuellt sich von oben nach unten, waehrend man liest. Die
   Ziffer sitzt auf der Bahn, gross und tabellarisch. Das ist die Fortschritts-Anzeige einer
   Runde, in Textform. */
.post-layout .article__body .post-list,.post-layout .article__body ol{position:relative;padding-left:0;margin:var(--s6) 0}
.post-layout .article__body .post-list::before,.post-layout .article__body ol::before{
  content:"";position:absolute;left:17px;top:12px;bottom:12px;width:2px;
  background:var(--line);
}
/* Die gefuellte Bahn: im Ruhezustand ganz, scrollgebunden waechst sie von oben. */
.post-layout .article__body .post-list::after,.post-layout .article__body ol::after{
  content:"";position:absolute;left:17px;top:12px;bottom:12px;width:2px;
  background:linear-gradient(180deg,
    oklch(var(--ton-voll-l) var(--ton-voll-c) var(--f1)) 0%,
    oklch(var(--ton-voll-l) var(--ton-voll-c) var(--f3)) 50%,
    oklch(var(--ton-voll-l) var(--ton-voll-c) var(--f7)) 100%);
  transform-origin:top center;
}
.post-layout .article__body .post-list li,.post-layout .article__body ol li{
  position:relative;display:block;border-top:0 !important;
  padding:var(--s3) 0 var(--s5) 52px;min-height:0;
  font-size:var(--t-md);line-height:1.45;color:var(--ink-2);
}
.post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
  content:counter(rl);
  position:absolute;left:0;top:var(--s3);transform:none;
  width:36px;height:36px;border-radius:var(--r-full);
  display:grid;place-items:center;
  background:oklch(var(--ton-voll-l) var(--ton-voll-c) var(--h, 255)) !important;
  color:var(--auf-voll);
  font-size:var(--t-sm);font-weight:700;line-height:1;letter-spacing:0;
  font-variant-numeric:tabular-nums;
  box-shadow:0 0 0 5px var(--paper) !important;   /* die Bahn wird ausgespart */
}
.post-layout .article__body .post-list li::after,.post-layout .article__body ol li::after{content:none !important}
.post-layout .article__body .post-list li:hover::before,.post-layout .article__body ol li:hover::before{transform:none}

/* --------------------------------------------------------------------------------------------
   21c · DIE SCROLLGEBUNDENE SCHICHT
   -------------------------------------------------------------------------------------------
   Alles hier ist ein Zusatz. Faellt `animation-timeline` aus, steht oben schon der Endzustand.
   `animation-range` ist bewusst kurz: die Bewegung soll fertig sein, wenn das Element gelesen
   wird, nicht waehrend man es liest. */
@supports (animation-timeline: view()){
  /* Der Haken wird gezogen, waehrend die Zeile hereinkommt. */
  @keyframes rgh-haken{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
  .post-layout .article__body .post-marke__z{
    animation:rgh-haken linear both;
    animation-timeline:view();
    animation-range:entry 15% cover 32%;
  }
  /* Die Linie unter der Zeile waechst mit. */
  @keyframes rgh-linie{from{transform:scaleX(0)}to{transform:scaleX(1)}}
  .post-layout .article__body .post-checkliste__list li.has-marke::after,
  .post-layout .article__body .post-checkliste ul li.has-marke::after{
    animation:rgh-linie linear both;
    animation-timeline:view();
    animation-range:entry 15% cover 40%;
  }
  /* Die Zeile selbst hebt sich herein - kurz, damit es nicht nach Baukasten aussieht. */
  @keyframes rgh-zeile{from{opacity:.35;transform:translateY(10px)}to{opacity:1;transform:none}}
  .post-layout .article__body .post-checkliste__list li.has-marke,
  .post-layout .article__body .post-checkliste ul li.has-marke,
  .post-layout .article__body .post-list li,.post-layout .article__body ol li{
    animation:rgh-zeile linear both;
    animation-timeline:view();
    animation-range:entry 5% cover 28%;
  }
  /* Die Bahn der nummerierten Liste fuellt sich ueber die GANZE Liste, nicht je Zeile:
     der Fortschritt gehoert der Abfolge, nicht dem einzelnen Schritt. */
  @keyframes rgh-bahn{from{transform:scaleY(0)}to{transform:scaleY(1)}}
  .post-layout .article__body .post-list::after,.post-layout .article__body ol::after{
    animation:rgh-bahn linear both;
    animation-timeline:view();
    animation-range:entry 0% exit 20%;
  }
  /* Die Ziffer schwillt an, wenn ihr Schritt dran ist. */
  @keyframes rgh-ziffer{
    from{transform:scale(.72);opacity:.5}
    40%{transform:scale(1.04);opacity:1}
    to{transform:scale(1);opacity:1}
  }
  .post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before{
    animation:rgh-ziffer linear both;
    animation-timeline:view();
    animation-range:entry 10% cover 30%;
  }
  /* Die grosse Zahl der Stat-Karte faehrt beim Hereinkommen aus ihrer Grundlinie hoch.
     Der Zaehler in post.js bleibt: der eine sagt WIE VIEL, der andere WOHER. */
  /* KEIN Startwert auf null (#729, zum vierten Mal dieselbe Lehre): scrollgebundene
   Animationen sind REVERSIBEL. Wer zurueckscrollt, sieht wieder den Anfangszustand, und
   der ist bei `opacity:0` eine leere Stelle. Am Probe-Post gemessen: die grosse Zahl der
   Stat-Karte war nach dem Zurueckscrollen verschwunden. Ab 0.15 ist immer etwas da. */
@keyframes rgh-zahl{from{opacity:.15;transform:translateY(24px)}to{opacity:1;transform:none}}
  .post-layout .article__body .post-stat__num{
    animation:rgh-zahl linear both;
    animation-timeline:view();
    animation-range:entry 10% cover 30%;
  }
}

/* Reduzierte Bewegung: die Zeitachse bleibt, aber nichts bewegt sich mehr. */
@media (prefers-reduced-motion: reduce){
  @supports (animation-timeline: view()){
    .post-layout .article__body .post-marke__z,
    .post-layout .article__body .post-checkliste__list li.has-marke::after,
    .post-layout .article__body .post-checkliste ul li.has-marke::after,
    .post-layout .article__body .post-checkliste__list li.has-marke,
    .post-layout .article__body .post-checkliste ul li.has-marke,
    .post-layout .article__body .post-list li,.post-layout .article__body ol li,
    .post-layout .article__body .post-list::after,.post-layout .article__body ol::after,
    .post-layout .article__body .post-list li::before,.post-layout .article__body ol li::before,
    .post-layout .article__body .post-stat__num{animation:none !important}
  }
}

/* (k) RHYTHMUS DER CHECKLISTE, am Blatt nachjustiert: die Linie klebte am Text der Folgezeile
   und der Haken sass auf ihrer Hoehe statt beim Satz. Mehr Luft unten, Haken an der Textzeile
   ausgerichtet. */
.post-layout .article__body .post-checkliste__list li.has-marke,
.post-layout .article__body .post-checkliste ul li.has-marke{
  padding:var(--s3) 0 var(--s5) 52px;
}
.post-layout .article__body .post-marke{top:calc(var(--s3) - 4px)}
.post-layout .article__body .post-checkliste__list li.has-marke:last-child::after,
.post-layout .article__body .post-checkliste ul li.has-marke:last-child::after{opacity:.5}

/* (l) DIE LINIE LIEF DURCH DEN TEXT. Die alte Haken-Regel (Abschnitt 16a) setzte `top` am
   selben `::after`; meine neue Regel setzte nur `bottom`. Beide gesetzt heisst: das Element
   wird ueber die ganze Zeilenhoehe gespannt, und eine 2px-Linie mit `height:2px` landet dann
   dort, wo `top` sie hinschiebt. Wer `position` neu belegt, muss die alten Offsets mit
   zuruecknehmen - dieselbe Falle wie beim Musterbogen-Etikett in #587. */
.post-layout .article__body .post-checkliste__list li.has-marke::after,
.post-layout .article__body .post-checkliste ul li.has-marke::after{
  top:auto !important;bottom:0 !important;left:0 !important;
  width:100% !important;height:2px !important;
  border:0 !important;transform-origin:left center;border-radius:1px;
}

/* (m) DIE BAHN LIEF DURCH DIE ZIFFERN. Die Bahn ist ein `::after` der LISTE, die Ziffern sind
   `::before` der Zeilen - im Stapel liegt die Liste damit oben, und die Aussparung per
   box-shadow half nichts, weil sie unter der Bahn lag. Die Zeilen bekommen darum eine eigene
   Ebene ueber der Bahn. */
.post-layout .article__body .post-list li,.post-layout .article__body ol li{position:relative;z-index:1}
.post-layout .article__body .post-list::before,.post-layout .article__body ol::before,
.post-layout .article__body .post-list::after,.post-layout .article__body ol::after{z-index:0}

/* ============================================================================================
   22 · DIE META-ZEILE VERLINKT (#729)
   ============================================================================================
   Kategorie und Autor sind seit dieser Runde Links (Engine: `publish._meta_ziele`, deklariert
   in der 0b-Config). Sie duerfen darum nicht wie Fliesstext-Links aussehen: keine
   Unterstreichung, keine zweite Farbe. Sie bleiben, was sie waren, und zeigen erst beim Zeigen,
   dass sie fuehren. Die Kategorie traegt dabei die Farbe ihres Spiels. */
.post-layout .article__meta a{
  color:inherit;text-decoration:none;border-bottom:0;font-weight:inherit;
  transition:color var(--d-fast, 180ms) var(--ease, ease);
}
.post-layout .article__meta .accent a{color:var(--ink);font-weight:600}
.post-layout .article__meta .accent a:hover{color:oklch(var(--ton-kante-l) var(--ton-kante-c) var(--h, 255))}
.post-layout .article__meta a[rel="author"]:hover{color:var(--ink)}
.post-layout .article__meta a:focus-visible{outline:2px solid var(--accent-line);outline-offset:3px;border-radius:3px}
