/* ==========================================================================
   Der Traumfänger · DAS JOURNAL - journal.html und article.html

   WAS DIESE DATEI IST: eine ZWEITE Schicht über css/tc2.css, keine zweite
   Gestaltung. Jede Farbe, jede Schriftgrösse, jeder Abstand, jede Kurve kommt
   aus den Tokens, die tc2.css schon definiert. Hier steht KEIN neuer Farbwert,
   KEINE neue Schriftart, KEINE neue Zeitkurve. Wer hier eine rohe Hexzahl
   einsetzt, hat den Punkt verfehlt: die Seite soll nicht aussehen wie ein Blog
   mit Café-Farben, sie soll aussehen wie dasselbe Haus, eine Tür weiter.

   WARUM NICHT IN tc2.css: die Startseite soll diese Regeln nicht laden müssen.
   tc2.css bleibt Byte für Byte, wie es war; diese Datei wird nur von den zwei
   Journalseiten geholt und ist klein genug, dass das nichts kostet.

   GELIEHENES VOKABULAR - nichts davon ist hier erfunden:
     .bahn / .bahn-eng   die Bühnenbreite der ganzen Seite
     .kopf / kopf-strich der Abschnittskopf mit dem gezeichneten Strich
     .mal                die gesperrte Kleinschrift (Datum, Rubrik)
     .wink               der Zwischenruf in Erwachsenenstimme
     .knopf              die Pille
     .reif               der Ring mit Zeichnung darin
     --radius-arch       die Bogennische (das Formzeichen des Hauses)
     die Rippe           das geriffelte Band aus .fuss-rippe / .bestellen::before
     das Sandzeichen     die kleine Düne aus .lernen-liste li::before

   BEWEGUNG: reine CSS-Animationen mit animation-fill-mode:both. Es gibt auf
   diesen zwei Seiten KEINEN Zustand, in dem Inhalt auf Bewegung wartet - fällt
   ein Skript aus, ist die Seite trotzdem vollständig und ruhig da. Das ist
   Absicht und nicht verhandelbar: ein Artikel, der sich nicht lesen lässt, weil
   ein Observer nicht gefeuert hat, ist kaputt.
   ========================================================================== */

/* ==========================================================================
   0 · GETEILTES - beide Journalseiten
   ========================================================================== */

/* Die Rippe: dasselbe geriffelte Band, das unter dem Fuss und über der
   Bestellstation liegt. Hier trennt sie die Stationen des Journals. */
.jo-rippe{
  height:16px;
  background-image:repeating-linear-gradient(90deg,
    var(--surface-raised) 0 var(--flute-w),
    var(--tfc-creme-deep) var(--flute-w) calc(var(--flute-w) + var(--flute-gap)));
  border-bottom:var(--line) solid var(--border);
}

/* «Du bist hier»: dieselbe Auszeichnung, die tc2.js beim Scrollen auf der
   Startseite setzt (.is-hier). Auf den Journalseiten steht sie fest im HTML,
   weil die Antwort nicht vom Scrollstand abhängt. */
.deck-weg a[aria-current="page"]{color:var(--ink);border-bottom-color:var(--accent);}

/* Der gezeichnete Strich unter dem Kopf. tc2.css lässt ihn im Ruhezustand
   gezeichnet (stroke-dashoffset:0) und versteckt ihn nur unter .motion-on -
   eine Klasse, die diese Seiten nicht setzen. Also wird hier gezeichnet, mit
   fill-mode both: der Strich endet IMMER vollständig, auch wenn die Animation
   nie startet. */
.jo-strich{color:var(--accent);}
@media (prefers-reduced-motion:no-preference){
  .jo-strich path{animation:jo-zeichnen 900ms var(--ease-settle) 220ms both;}
}
@keyframes jo-zeichnen{from{stroke-dashoffset:110;}to{stroke-dashoffset:0;}}

@keyframes jo-auf{
  from{opacity:0;transform:translateY(14px);}
  to{opacity:1;transform:none;}
}

/* Zurück zum Journal. Der Pfeil ist ein ::before, damit er mitwandert, wenn
   der Betrieb den Text ändert. */
.jo-zurueck{
  display:inline-flex;align-items:center;gap:.5rem;
  font-size:var(--text-small);color:var(--accent-ink);text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--accent-ink) 26%,transparent);
  padding-bottom:.1rem;
}
.jo-zurueck::before{content:"\2190";font-size:1.05em;line-height:1;}
.jo-zurueck:hover{border-bottom-color:var(--accent-ink);}

/* Die gesperrte Zeile über dem Titel: Datum, Lesezeit, Rubrik.
   TRENNZEICHEN-REGEL: der Punkt hängt als ::before am FOLGENDEN Feld, nie als
   eigenes <span> dazwischen. Fällt ein optionales Feld weg (der Renderer
   entfernt es oder leert es), verschwindet sein Punkt mit ihm und es bleibt
   kein verwaister Trenner stehen. Beide Fälle sind abgedeckt: das Entfernen
   durch den Geschwisterselektor, das Leeren durch :not(:empty).

   Die Schrift ist dieselbe gesperrte Kleinschrift wie .mal auf der Startseite,
   und sie gilt auf BEIDEN Journalseiten - sonst liest sich das Datum im
   Verzeichnis anders als im Artikel und die zwei Seiten fallen auseinander. */
.jo-meta{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:0;
  margin:0 0 var(--space-2);color:var(--brand-ink);
  font-size:var(--text-label);letter-spacing:var(--ls-caps);text-transform:uppercase;
  font-weight:500;line-height:1.4;
  font-variant-numeric:tabular-nums lining-nums;
}
.jo-meta > *{margin:0;}
/* Der Punkt haengt NACHGESTELLT an jedem Feld, das noch ein gefuelltes Feld
   nach sich hat - nicht vorangestellt am folgenden. Beides entfernt den
   verwaisten Trenner gleich gut, aber beim Umbruch ist der Unterschied
   sichtbar: ein vorangestellter Punkt wandert mit seinem Feld in die neue
   Zeile und steht dort als erstes Zeichen (bei 390 bricht diese Zeile um).
   Ein nachgestellter bleibt am Zeilenende, wo ein Trenner hingehoert. */
.jo-meta > :not(:empty):has(~ :not(:empty))::after{
  content:"\00B7";color:var(--ink-muted);opacity:.5;margin:0 .6em;font-weight:400;
}
.jo-meta .jo-rubrik{color:var(--accent-ink);}

/* ==========================================================================
   1 · journal.html - DIE TAFEL

   Kein Kachelraster. Die Startseite hat ihr Kartenraster schon (.karte-tafel),
   und ein zweites wäre genau der Blog-Baukasten, den diese Seite nicht sein
   darf. Stattdessen die Tafel: breite Zeilen mit Haarlinie dazwischen, das
   Datum in Tabellenziffern, das Bild in der Bogennische. So hängt im Café eine
   Tafel, und so liest sich eine Liste von Einträgen mit Datum.
   ========================================================================== */
/* KEIN Ausgleich fuer die Kopfleiste. .v2-hinweis und .deck sind position:
   sticky, nicht fixed - sie stehen im Fluss und nehmen ihren Platz selbst ein.
   Ein Aufschlag von --kopf-h obendrauf war schlicht 98px totes Feld. */
.jo-auftakt{
  background:var(--surface-sand);
  padding-block:var(--space-6);
  position:relative;
}
.jo-auftakt .mal{display:block;color:var(--brand-ink);margin-bottom:.7rem;}
.jo-auftakt .kopf{max-width:24ch;}
.jo-auftakt-satz{
  color:var(--ink-muted);max-width:52ch;font-size:var(--text-lead);
  margin-top:var(--space-3);
}
.jo-auftakt .wink{margin-top:var(--space-2);}

.jo-tafel-raum{background:var(--surface);padding-block:var(--space-6) var(--space-7);}
/* Mobil-Audit F3: derselbe Rhythmus wie auf den anderen Stationen - die
   104px Fussluft unter dem "Bald"-Kaertchen wirkte auf dem Handy wie eine
   Luecke. */
@media (max-width:819px){
  .jo-tafel-raum{padding-block:3.5rem 2.5rem;}
}

.jo-tafel{display:block;}

/* EINE Zeile = EIN Artikel. Das ist die Markierung, die der Renderer klont,
   also ist die Struktur in jeder Zeile identisch. Dass die erste Zeile grösser
   ist, macht ausschliesslich CSS (:first-child) - nicht anderes Markup. Sonst
   würde der Klon die Sonderbehandlung mitnehmen und JEDE Zeile wäre gross. */
.jo-zeile{
  display:grid;
  grid-template-columns:132px minmax(0,1fr);
  gap:0 clamp(1.3rem,2.6vw,2.4rem);
  align-items:start;
  text-decoration:none;color:inherit;
  border-top:var(--line) solid var(--border);
  padding-block:var(--space-4);
  transition:border-color var(--dur-micro) linear,transform var(--dur-standard) var(--ease-serve);
}
.jo-zeile:last-child{border-bottom:var(--line) solid var(--border);}
.jo-zeile:hover{border-top-color:var(--border-strong);transform:translateY(-3px);}
.jo-zeile:hover .jo-zeile-titel{color:var(--accent-ink);}

/* Die Bogennische. Sie ist das Formzeichen des Hauses (--radius-arch) und
   kommt auf jedem Bild der Startseite vor.
   ZWEI Kinder, nicht fünf: das Bild und EIN Wortblock. Damit braucht die Zeile
   kein grid-row-span, und ein weggelassenes optionales Feld (der Auszug) kann
   keine leere Geisterzeile im Raster hinterlassen. */
.jo-zeile-bogen{
  display:block;
  border-radius:var(--radius-arch);overflow:hidden;
  background:var(--surface-sand);
  aspect-ratio:3 / 4;
}
.jo-zeile-bogen img{width:100%;height:100%;object-fit:cover;}
.jo-zeile-wort{display:block;min-width:0;}

.jo-zeile .jo-meta{margin-bottom:.45rem;}
.jo-zeile-datum{color:var(--brand-ink);}
.jo-zeile-titel{
  font-family:var(--font-display);font-weight:400;line-height:var(--lh-display);
  font-size:var(--text-h3);margin:0 0 .5rem;max-width:30ch;
  transition:color var(--dur-micro) linear;
}
.jo-zeile-satz{
  margin:0;font-size:var(--text-small);color:var(--ink-muted);max-width:62ch;
}
/* Die Zeile ist als Ganzes ein Link. Das Wort «weiterlesen» trägt die
   Affordanz, ohne ein zweites Ziel aufzumachen. */
.jo-zeile-weiter{
  display:inline-block;margin-top:.7rem;font-size:var(--text-small);
  color:var(--accent-ink);
  border-bottom:1px solid color-mix(in srgb,var(--accent-ink) 26%,transparent);
}
.jo-zeile:hover .jo-zeile-weiter{border-bottom-color:var(--accent-ink);}

/* Der neueste Eintrag führt. NUR CSS, kein eigenes Markup: der Renderer klont
   die erste Zeile, also würde jede Sonderbehandlung im Markup auf ALLE Zeilen
   mitwandern. :first-child wandert nicht mit. */
.jo-zeile:first-child{
  border-top-width:0;padding-top:0;
  grid-template-columns:240px minmax(0,1fr);
}
.jo-zeile:first-child .jo-zeile-bogen{max-width:38vw;}
.jo-zeile:first-child .jo-zeile-titel{font-size:var(--text-h2);max-width:24ch;}
.jo-zeile:first-child .jo-zeile-satz{font-size:var(--text-body);max-width:56ch;}

@media (prefers-reduced-motion:no-preference){
  .jo-zeile:nth-child(-n+5){animation:jo-auf 700ms var(--ease-settle) both;}
  .jo-zeile:nth-child(1){animation-delay:60ms;}
  .jo-zeile:nth-child(2){animation-delay:140ms;}
  .jo-zeile:nth-child(3){animation-delay:220ms;}
  .jo-zeile:nth-child(4){animation-delay:300ms;}
  .jo-zeile:nth-child(5){animation-delay:380ms;}
}

@media (max-width:720px){
  .jo-zeile,.jo-zeile:first-child{grid-template-columns:104px minmax(0,1fr);}
  .jo-zeile:first-child .jo-zeile-bogen{width:100%;max-width:none;}
  .jo-zeile:first-child .jo-zeile-titel{font-size:var(--text-h3);}
  .jo-zeile-titel{font-size:1.22rem;}
  /* Der Auszug bleibt auf dem Handy STEHEN, auf zwei Zeilen gekürzt. Er zuerst
     ganz auszublenden war falsch: dann steht in der Zeile nur noch ein Titel
     und ein Datum, und genau auf dem Handy entscheidet man am ehesten anhand
     der ersten zwei Sätze, ob man etwas liest. */
  .jo-zeile-satz{
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;
    overflow:hidden;
  }
}
@media (max-width:430px){
  .jo-zeile,.jo-zeile:first-child{grid-template-columns:92px minmax(0,1fr);}
}

/* ---- Blättern ------------------------------------------------------------
   Spec §4.3, Slots data-cms-article-nav="newer|older|page|pages".

   DREI FESTE SPALTEN, nicht space-between. Eine Richtung ohne Ziel wird vom
   Renderer ENTFERNT, und mit space-between wandert dann alles Übrige: auf
   Seite 1 (kein «neuer») stünde der Seitenstand plötzlich rechts aussen. Mit
   festen Spalten bleibt der Stand in der Mitte und jeder Link auf seiner
   Seite, egal welche der drei Stellen fehlt. */
.jo-blaettern{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  gap:var(--space-2) var(--space-3);
  margin-top:var(--space-5);padding-top:var(--space-3);
  border-top:var(--line) solid var(--border-strong);
  font-size:var(--text-small);
}
.jo-blaettern [data-cms-article-nav="newer"]{grid-column:1;justify-self:start;}
.jo-blaettern-stand{grid-column:2;justify-self:center;margin:0;color:var(--ink-muted);}
.jo-blaettern [data-cms-article-nav="older"]{grid-column:3;justify-self:end;}
.jo-blaettern-weg{
  display:inline-flex;align-items:center;gap:.45rem;
  color:var(--accent-ink);text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--accent-ink) 26%,transparent);
  padding-bottom:.1rem;
}
.jo-blaettern-weg:hover{border-bottom-color:var(--accent-ink);}
/* Dieselben Pfeile wie beim Zurück-Link, also dieselbe Sprache im ganzen
   Journal: der Pfeil zeigt in die Richtung, in die man geht. */
.jo-blaettern [data-cms-article-nav="newer"]::before{content:"\2190";line-height:1;}
.jo-blaettern [data-cms-article-nav="older"]::after{content:"\2192";line-height:1;}
/* Eine Seite insgesamt: der Renderer entfernt beide Richtungen, und dann hat
   die Leiste nichts mehr zu sagen. Braucht keine Mitarbeit des Renderers. */
.jo-blaettern:not(:has(a)){display:none;}
/* Gar kein Artikel: die Leiste hat erst recht nichts zu sagen. */
.jo-tafel:not(:has(.jo-zeile)) ~ .jo-blaettern{display:none;}
@media (max-width:560px){
  .jo-blaettern{grid-template-columns:1fr;justify-items:center;text-align:center;}
  .jo-blaettern [data-cms-article-nav="newer"],
  .jo-blaettern-stand,
  .jo-blaettern [data-cms-article-nav="older"]{grid-column:1;justify-self:center;}
}

/* ---- Die leere Tafel ----------------------------------------------------
   Runde 2, Stapel 2: geprüft wird die Klasse .jo-zeile, NICHT mehr das
   Attribut data-cms-article-item. Das Attribut entfernt der Renderer beim
   Veröffentlichen aus jedem Eintrag; mit ihm galt die Tafel auf der echten
   Seite IMMER als leer, und der erste veröffentlichte Beitrag wäre unter dem
   Leer-Kasten verschwunden. Die Klasse bleibt erhalten.
   Sichtbar genau dann, wenn in der Tafel kein Eintrag steht. Das braucht
   KEINE Mitarbeit des Renderers: entfernt er beim Veröffentlichen ohne
   Artikel alle [data-cms-article-item], greift :has() von allein.
   Ohne :has()-Unterstützung bleibt der Kasten verborgen - dann ist die Tafel
   leer statt falsch, und das ist die richtige Richtung zum Scheitern. */
.jo-leer{display:none;}
.jo-tafel:not(:has(.jo-zeile)) + .jo-leer{display:block;}
.jo-tafel:not(:has(.jo-zeile)){display:none;}

.jo-leer-kasten{
  border-radius:var(--radius-arch);
  border:var(--line) solid var(--border-strong);
  background:var(--surface-raised);
  padding:var(--space-6) var(--space-4) var(--space-5);
  text-align:center;
  max-width:520px;margin-inline:auto;
  box-shadow:var(--shadow-1);
}
.jo-leer .reif{width:84px;margin:0 auto var(--space-3);}
.jo-leer-titel{
  font-family:var(--font-display);font-size:var(--text-h3);line-height:var(--lh-display);
  margin:0 0 .6rem;
}
.jo-leer-satz{color:var(--ink-muted);margin:0 auto;max-width:34ch;}
.jo-leer .wink{margin:var(--space-3) auto 0;}

/* ==========================================================================
   2 · article.html - EIN ARTIKEL

   Das Mass: 66ch. Darüber verliert das Auge die Zeile, darunter wird der
   Zeilenumbruch zum Stolperstein. Die Bühne bleibt .bahn-eng, also dieselbe
   schmale Spur, die die Station «Bald sind wir da» schon benutzt.
   ========================================================================== */
.jo-artikel{background:var(--surface);padding-bottom:var(--space-7);}

.jo-kopfzeile{padding-top:var(--space-4);padding-bottom:var(--space-3);}

.jo-titelblock{padding-bottom:var(--space-4);}
.jo-titel{
  font-size:var(--text-h2);max-width:30ch;margin:0 0 var(--space-2);
}
.jo-vorspann{
  font-size:var(--text-lead);color:var(--ink-muted);
  max-width:56ch;margin:var(--space-3) 0 0;
}
@media (prefers-reduced-motion:no-preference){
  .jo-titelblock{animation:jo-auf 700ms var(--ease-settle) both;}
  .jo-schau{animation:jo-auf 800ms var(--ease-settle) 120ms both;}
}

/* Die Schau: das Aufmacherbild in der Bogennische, so breit wie die Bühne.
   Breiter als die Textspalte, damit der Artikel atmet - aber nie randlos: die
   Startseite hat EIN randloses Bild, den Tresen, und das bleibt einmalig. */
.jo-schau{
  margin:0 0 var(--space-5);
  border-radius:var(--radius-arch);overflow:hidden;
  background:var(--surface-sand);
  aspect-ratio:3 / 2;
}
.jo-schau img{width:100%;height:100%;object-fit:cover;}
@media (max-width:560px){.jo-schau{aspect-ratio:4 / 3;}}

/* ---- Der Textkörper ----------------------------------------------------
   Alles hier drin kommt aus body_mdx und trägt KEINE Klassen. Also wird jedes
   Element getroffen, das in einem Artikel vorkommen kann - auch die, die die
   heutige Erlaubnisliste noch nicht durchlässt. Wenn sie erweitert wird, ist
   diese Seite am selben Tag richtig gesetzt und nicht erst eine Runde später. */
/* DAS MASS. NICHT in ch: ch ist die Laufweite der Ziffer «0» und in Work Sans
   deutlich breiter als ein Durchschnittsbuchstabe - 66ch ergaben GEMESSENE 85
   Zeichen pro Zeile. Gemessen wird der echte Wert in render-sample.mjs: 32em
   waren mit 58 Zeichen zu KURZ, 36em landen bei rund 66 - mitten in der Spanne,
   in der das Auge den Zeilenanfang ohne Suchen wiederfindet. */
.jo-text{
  max-width:36em;
  font-size:var(--text-lead);line-height:1.8;
}
.jo-text > *:first-child{margin-top:0;}
.jo-text p{margin:0 0 var(--space-3);}
/* Der Einstieg trägt eine Spur mehr Gewicht, wie eine gesprochene Begrüssung. */
.jo-text > p:first-of-type{font-size:1.26rem;line-height:1.72;color:var(--ink);}

/* Überschriften IM Text. Das Sandzeichen davor ist dieselbe kleine Düne, die
   auf der Startseite die Punkte der Liste «Was der Sand mit einem Kind macht»
   markiert - das einzige Listenzeichen, das dieses Haus besitzt. */
.jo-text h2{
  font-family:var(--font-display);font-weight:400;line-height:var(--lh-display);
  font-size:var(--text-h3);margin:var(--space-5) 0 var(--space-2);
  position:relative;padding-left:1.7rem;
}
.jo-text h2::before{
  content:"";position:absolute;left:0;top:.46em;width:14px;height:13px;
  background:var(--brand);
  clip-path:polygon(0 100%,0 45%,50% 0,100% 45%,100% 100%);
}
/* h3 muss deutlich GRÖSSER sein als der Fliesstext, nicht nur anders gefärbt.
   Erster Versuch waren 1.22rem gegen einen Fliesstext von 1.1875rem: ein halber
   Pixel Unterschied, und die Zwischenüberschrift las sich im Screenshot wie ein
   verirrter Absatz. Jetzt: 27px (h2) > 23px (h3) > 19px (Text). */
.jo-text h3{
  font-family:var(--font-display);font-weight:400;line-height:var(--lh-display);
  font-size:1.42rem;color:var(--brand-ink);
  margin:var(--space-5) 0 .55rem;
}
/* h4 in --brand-ink, NICHT in --ink-muted: eine Überschrift darf nie leiser
   sein als der Text, den sie überschreibt. Die Rangfolge liest sich jetzt an
   Grösse UND Farbe: h2 tintenschwarz gross · h3 salbei mittel · h4 salbei
   klein und gesperrt. */
.jo-text h4{
  font-family:var(--font-text);font-size:var(--text-label);font-weight:500;
  letter-spacing:var(--ls-caps);text-transform:uppercase;color:var(--brand-ink);
  margin:var(--space-4) 0 .4rem;
}

/* ZWEI ÜBERSCHRIFTEN DIREKT ÜBEREINANDER GEHÖREN ZUSAMMEN.
   Der Abstand über einer Überschrift trennt sie vom vorigen ABSCHNITT. Folgt
   sie aber unmittelbar auf eine grössere Überschrift, gibt es keinen vorigen
   Abschnitt: dann sind die beiden ein Paar, und die vollen 3rem rissen sie
   auseinander (im Belastungstest gemessen: 48px zwischen h2 und h3, die
   zusammengehören). Markdown liefert diese Folge regelmässig. */
.jo-text h2 + h3,
.jo-text h2 + h4,
.jo-text h3 + h4{margin-top:.9rem;}

/* Listen. tc2.css setzt list-style:none für die ganze Seite, also hätte eine
   Liste aus dem Artikeltext ÜBERHAUPT KEIN Zeichen mehr. Hier kommt es zurück,
   in der Form des Hauses. */
.jo-text ul,.jo-text ol{margin:0 0 var(--space-3);padding:0;}
.jo-text li{position:relative;padding-left:1.7rem;margin-bottom:.5rem;}
.jo-text ul > li::before{
  content:"";position:absolute;left:.15rem;top:.62em;width:12px;height:11px;
  background:var(--brand);
  clip-path:polygon(0 100%,0 45%,50% 0,100% 45%,100% 100%);
}
.jo-text ol{counter-reset:jo-zahl;}
.jo-text ol > li{counter-increment:jo-zahl;}
.jo-text ol > li::before{
  content:counter(jo-zahl) ".";position:absolute;left:0;top:0;
  color:var(--accent-ink);font-variant-numeric:tabular-nums lining-nums;font-weight:500;
}
.jo-text li > ul,.jo-text li > ol{margin-top:.5rem;margin-bottom:0;}

.jo-text a{
  color:var(--accent-ink);text-decoration:none;
  border-bottom:1px solid color-mix(in srgb,var(--accent-ink) 34%,transparent);
}
.jo-text a:hover{border-bottom-color:var(--accent-ink);}
.jo-text strong,.jo-text b{font-weight:600;}
.jo-text em,.jo-text i{font-style:italic;}

.jo-text blockquote{
  margin:var(--space-4) 0;padding:0 0 0 var(--space-3);
  border-left:3px solid var(--accent);
  font-family:var(--font-display);font-size:var(--text-h3);line-height:1.4;
  color:var(--ink);
}
.jo-text blockquote p{margin:0;font-size:inherit;line-height:inherit;}

/* Bilder im Text. Sie dürfen die Spalte NICHT sprengen: bis 1100px sitzen sie
   exakt im Mass, darüber treten sie kontrolliert je 3rem heraus, damit der
   Artikel Luft bekommt, ohne dass die Zeile wandert. */
.jo-text figure{margin:var(--space-5) 0;}
/* width:auto, NICHT width:100%. Mit 100% wird jedes Bild auf Spaltenbreite
   aufgeblasen - ein 192px-Signet erschiene 684px breit, also als hochgerechnete
   Scheinpixel. Genau das verbietet die Regel gegen aufgeblasene Derivate.
   max-width haelt das grosse Bild in der Spalte, width:auto laesst das kleine
   klein. */
.jo-text img{
  display:block;width:auto;max-width:100%;height:auto;
  border-radius:var(--radius-md);background:var(--surface-sand);
}
.jo-text figcaption{
  margin-top:.6rem;font-size:var(--text-small);color:var(--ink-muted);max-width:54ch;
}
/* DER KONTROLLIERTE AUSTRITT - und warum er NICHT fuer <p><img></p> gilt.

   Erster Versuch war `.jo-text > p:has(> img:only-child) > img`, um genau das
   Bild zu treffen, das allein in seinem Absatz steht (die Form, in der Markdown
   ein ![alt](bild) ausliefert). Das ist GESCHEITERT, und zwar lautlos:
   :only-child zaehlt ELEMENTE, nicht Textknoten. Ein Absatz aus «Text <img>
   mehr Text» hat ebenfalls genau ein Element-Kind, passt also auf denselben
   Selektor - gemessen ist das Signet mitten im Satz um 48px links UND rechts
   aus der Spalte getreten. CSS kann die beiden Faelle nicht unterscheiden,
   weil es Textinhalt nicht pruefen kann.

   Also treten nur Formen aus, die per Definition allein stehen: eine <figure>
   und ein <img> als direktes Kind von .jo-text. Ein Bild in einem Absatz bleibt
   IMMER in der Spalte. Das ist nie falsch, nur manchmal bescheidener.

   Die Verbesserung gehoert in den Renderer, nicht hierher: wenn er einen
   Absatz, der nichts als ein Bild enthaelt, zu einer <figure> normalisiert
   (was Markdown-Konverter ueblicherweise anbieten), bekommt jedes freistehende
   Bild den vollen Austritt, ohne dass eine einzige Zeile hier sich aendert. */
@media (min-width:1100px){
  .jo-text > figure,
  .jo-text > img{
    width:calc(100% + 2 * var(--space-5));max-width:none;
    margin-left:calc(-1 * var(--space-5));
  }
  .jo-text figcaption{margin-left:var(--space-5);}
}
/* Ein Bild in einem Absatz bleibt in der Spalte. Ausnahmslos. */
.jo-text p img{max-width:100%;}

/* Ein Trennstrich im Artikel ist die Rippe. */
.jo-text hr{
  border:0;height:16px;margin:var(--space-5) 0;
  background-image:repeating-linear-gradient(90deg,
    var(--surface-raised) 0 var(--flute-w),
    var(--tfc-creme-deep) var(--flute-w) calc(var(--flute-w) + var(--flute-gap)));
  border-block:var(--line) solid var(--border);
}

.jo-text table{
  width:100%;border-collapse:collapse;margin:var(--space-4) 0;font-size:var(--text-small);
}
.jo-text th,.jo-text td{
  text-align:left;padding:.55rem .7rem;border-bottom:var(--line) solid var(--border);
}
.jo-text th{color:var(--brand-ink);font-weight:500;letter-spacing:.04em;}

/* ---- Der Schluss ------------------------------------------------------- */
.jo-ende{
  margin-top:var(--space-6);padding-top:var(--space-4);
  border-top:var(--line) solid var(--border-strong);
  display:flex;flex-wrap:wrap;gap:var(--space-3) var(--space-4);
  align-items:center;justify-content:space-between;
}
.jo-ende-wort{margin:0;flex:1 1 20rem;max-width:42ch;}
.jo-ende-gruss{
  font-family:var(--font-script);font-weight:600;font-size:var(--text-script);
  color:var(--brand-ink);margin:0 0 .2rem;line-height:1.1;
}

@media (max-width:560px){
  .jo-text{font-size:var(--text-body);line-height:1.75;}
  .jo-text > p:first-of-type{font-size:var(--text-lead);}
  .jo-ende{flex-direction:column;align-items:flex-start;}
}
