/* sections.css — Feinlayout: Segmentraster, Module, Bedienelemente.

   ABSTÄNDE ZWISCHEN TEXTEN STEHEN IN em, NICHT IN rem (DEV-LOG [23]).
   rem hängt an der Wurzelgröße, die zwischen 820 px und der Einfrierbreite
   (--maxw, 1440 px) fluid von 13 px auf 16 px läuft. Die Schriftgrößen der
   Rollen schalten am Breakpoint aber zusätzlich auf ihren Mobilwert um —
   dadurch lief beides auseinander: `margin-top: 1.9rem` waren auf dem Handy
   24,7 px neben 12,4 px Text, also die doppelte Schrifthöhe, während dasselbe
   Verhältnis auf Desktop 1,27 betrug. Genau das war als "Absatz-Abstände viel
   zu groß" gemeldet.

   DIE ABSTÄNDE DER SEKTIONEN STEHEN SEIT DEM SEGMENT-UMBAU IN DEN DATEN
   (DEV-LOG [32]). Ein Segment trägt --pad-t/--pad-b als Faktor von
   --sec-pad-y; hier steht dafür keine Regel mehr. Nur Hero und Footer haben
   ihre Abstände weiterhin im CSS — sie sind der Rahmen der Seite und keine
   Bauklotz-Segmente.                                                        */

/* ── Hero ──────────────────────────────────────────────────────────────── */
.sec--hero {
  --pad-t: 0; --pad-b: 0;
  /* Der Keil ist FEST — Form in HERO_WEDGE_POINTS, Höhe hier. Bewusst keine
     Einstellung und bewusst nicht über ckStyle(): an ihm ist nur noch die
     Füllfarbe dynamisch, und die steht als Attribut am <polygon>. */
  --wedge-h: 48px;
  /* Der Keil hängt unter der nominellen Hero-Höhe: an seiner tiefsten Stelle
     reicht das Video um genau --wedge-h weiter nach unten. */
  height: calc(var(--hero-h) + var(--wedge-h));
  /* Untergrenze für sehr flache Viewports (Handy quer): darunter wäre das
     Keyvisual ein Streifen. Auf Mobil niedriger, sonst schlüge sie die
     eingestellten 50 svh (bei ~700 px Gerätehöhe = 350 px) einfach nieder. */
  min-height: 420px;
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-video { width: 100%; height: 100%; object-fit: cover; }
/* Solange kein Video hinterlegt ist: das Grün der Vorlage als Platzhalter. */
.hero-video--ph { background: #05ff39; }

/* ── Segmentraster ─────────────────────────────────────────────────────────
   Ein Segment ist ein- oder zweispaltig; Verhältnis, Abstand und vertikale
   Ausrichtung kommen aus segmentProps() — als Variable (--seg-split,
   --seg-gap) oder als Klasse. Hier steht deshalb keine einzige Regel für
   einen bestimmten Inhalt: was "Text neben Bildraster" bis E5 als eigener
   Blocktyp war, ist jetzt ein zweispaltiges Segment mit zwei Modulen.      */
.mseg {
  display: grid;
  gap: var(--seg-gap, var(--col-gap));
}
.mseg--c1 { grid-template-columns: 1fr; }
.mseg--c2 { grid-template-columns: var(--seg-split, 1fr 1fr); }
.mseg--c3 { grid-template-columns: var(--seg-split, 1fr 1fr 1fr); }

.mseg--v-center { align-items: center; }
.mseg--v-start  { align-items: start; }
.mseg--v-end    { align-items: end; }

/* ── Trennlinien zwischen den Spalten (segmentProps()['divider'], DEV-LOG [99])
   Die Klasse wählt die Höhe, die Farbe kommt als --seg-div-c (Token, Regel 2).

   GEZEICHNET VON DER RASTERBOX, NICHT VON DEN ZELLEN. Eine Zelle ist bei
   „Spalten vertikal: Mittig" nur so hoch wie ihr Inhalt — eine Linie daran
   wäre neben einem hohen Bild ein Strich neben dem Text. Ein ABSOLUT
   positioniertes Kind eines Grids nimmt dagegen den Rasterbereich, den
   grid-row/grid-column nennen, als umschließenden Block — und nimmt an der
   automatischen Platzierung NICHT teil, die Zellen rücken also nicht weg.
   100 % Höhe ist damit die Höhe der Zeile, und left die Kante der Spalte:
   die halbe Fuge davor ist die Mitte des Spalts.
   ::before sitzt vor Spalte 2, ::after (nur dreispaltig) vor Spalte 3.     */
.mseg--div-100 { --seg-div-h: 100%; }
.mseg--div-75  { --seg-div-h: 75%; }
.mseg--div-50  { --seg-div-h: 50%; }
.mseg--div-25  { --seg-div-h: 25%; }
:is(.mseg--div-100, .mseg--div-75, .mseg--div-50, .mseg--div-25) { position: relative; }
:is(.mseg--div-100, .mseg--div-75, .mseg--div-50, .mseg--div-25)::before,
:is(.mseg--div-100, .mseg--div-75, .mseg--div-50, .mseg--div-25).mseg--c3::after {
  content: "";
  position: absolute;
  grid-row: 1;
  grid-column: 2;
  left: calc(var(--seg-gap, var(--col-gap)) / -2);
  top: calc((100% - var(--seg-div-h)) / 2);
  height: var(--seg-div-h);
  /* EIN RAHMEN, KEINE FLÄCHE — und kein transform (DEV-LOG [100]). Bis dahin
     stand hier width: 1px + background + translateX(-50%): der halbe Pixel
     Versatz und die gebrochene Spaltenkante (fr) legten die Linie ZWISCHEN
     zwei Gerätepixel, ein transform rastet nicht ein. Gemessen: bei 100 %
     Skalierung jede Linie 2 px halbhell, bei 150 % je Linie mal 2, mal 3
     Gerätepixel, unabhängig voneinander beim Ziehen des Fensters. Eine
     Rahmenbreite rundet der Browser auf ganze Gerätepixel, und eine Box ohne
     transform rastet ihre Kante ein. Der halbe Pixel Versatz zur Fugenmitte
     ist unsichtbar. */
  width: 0;
  border-left: 1px solid var(--seg-div-c, var(--ci-white));
  pointer-events: none;
}
:is(.mseg--div-100, .mseg--div-75, .mseg--div-50, .mseg--div-25).mseg--c3::after { grid-column: 3; }

.mcell--a-start  { text-align: start; }
.mcell--a-center { text-align: center; }
.mcell--a-end    { text-align: end; }

/* ── Modul "Text" ──────────────────────────────────────────────────────────
   EIN Feld, beliebig viele Absätze (E12). Hier steht deshalb nichts mehr:

   Bis E12 hatte das Modul vier feste Felder, und jedes trug seinen Abstand
   (.mtext__sub 1.03em, __copy 1.13em, __sig 1.07em) sowie die Signatur ihr
   Kursiv (.mtext__sig). Die Klassen gibt es nicht mehr — es gibt die Felder
   nicht mehr. Der Abstand zwischen Absätzen kommt jetzt aus .rich > * + *
   (base.css) und gilt relativ zur Schriftgröße des jeweiligen Absatzes, also
   zu seiner ROLLE statt zur Feldbox darum. Kursiv steht im Text selbst.

   Die BÜNDIGKEIT stand hier schon seit DEV-LOG [52] nicht mehr fest; seit
   E12 ist sie zusätzlich je ABSATZ einstellbar, seit DEV-LOG [83] über die
   Formatierungsleiste — und seit DEV-LOG [95] entscheidet in einem Text NUR
   noch der Absatz: die Ebenen Feld (.mtext--a-*) und Textzelle gibt es nicht
   mehr, ihre gespeicherten Werte stehen beim Laden an den Absätzen.        */

/* ── Bündigkeit je ABSATZ — DER ABSATZ GEWINNT (DEV-LOG [83]) ──────────────

   Geschichte in drei Schritten, alle Vorgabe des Betreibers:
   - E12 / DEV-LOG [61]: Zelle > Feld > Absatz. Eine Bündigkeit an der SPALTE
     war die Ansage für die ganze Spalte.
   - DEV-LOG [83]: Absatz > Feld > Zelle. Seit es die Formatierungsleiste gibt,
     setzt man die Bündigkeit am Text selbst — und ein Klick darauf, der
     sichtbar nichts tut, weil die Spalte etwas anderes sagt, ist ein Fehler.
     Feld und Zelle sind jetzt die VORGABE für Absätze ohne eigene Angabe.
   - DEV-LOG [95]: nur der Absatz. Feld und Textzelle tragen keine Klasse
     mehr; die Zellregeln unten gelten nur noch Bilderbox und Player (deren
     Bildunterschrift ist ein <p>) und treffen einen Fließtext nie.

   Damit drei Ebenen überhaupt vergleichbar sind, müssen alle drei DASSELBE
   Element treffen: den Absatz. Alle Regeln liegen bei 0,1,0, die RANGFOLGE
   macht deshalb die Reihenfolge, genau wie schon bei "mobil vor Desktop",
   nur eine Ebene tiefer. Kein !important, nirgends. (Mit reiner Vererbung
   gewönne zwar ebenfalls die innerste Angabe — aber nur, solange Feld und
   Zelle den Absatz nicht selbst treffen; mobil müssen sie das, siehe unten.)

   JEDER ABSATZ WIRD GETROFFEN, nicht nur der mit eigenem Attribut. Bis
   2026-08-24 stand hier [data-a] auf der rechten Seite, und das war der
   Fehler: ein Absatz OHNE Angabe erbte weiter von .mtext--a-* bzw.
   .mcell--a-*, und dort entscheidet die VERERBUNG — also gewann die innerste
   Angabe, das Feld. Die Rangfolge galt damit ausgerechnet fuer den
   Normalfall nicht (DEV-LOG [63]).

   :is() STATT :where() UM DEN VORFAHREN. :where() nullt die Spezifitaet,
   :is() nimmt die seines staerksten Arguments — die Klasse zaehlt also mit
   (0,1,0), waehrend :where(p,h1,h2,li) rechts bei 0 bleibt. So liegen alle
   Regeln wieder gleichauf bei 0,1,0 und die REIHENFOLGE macht die Rangfolge.
   Mit :where() links waeren sie 0,0,0 und verloeren gegen [data-a].

   Die Absatzliste muss zu SANITIZE_PARA passen (lib/sanitize.php) — der
   Selbsttest prueft das, sonst faellt eine spaeter erlaubte Absatzart hier
   still heraus.

   Reihenfolge von schwach nach stark: Zelle < Absatz. Der Selbsttest
   prüft sie im Dateitext (lib/selftest.php, „Rangfolge der Bündigkeit").   */
:is(.mcell--a-start)  :where(p, h1, h2, li) { text-align: start; }
:is(.mcell--a-center) :where(p, h1, h2, li) { text-align: center; }
:is(.mcell--a-end)    :where(p, h1, h2, li) { text-align: end; }

:where(.rich) [data-a="start"]      { text-align: start; }
:where(.rich) [data-a="center"]     { text-align: center; }
:where(.rich) [data-a="end"]        { text-align: end; }

/* ── Buttons ───────────────────────────────────────────────────────────────
   HIER STEHT NUR DIE BASISREGEL. Welches Preset welche Werte hat, sagt
   theme.json (schemaCollections()['btn'], DEV-LOG [111]): der Betreiber legt
   Presets an, benennt sie und löscht sie. Die Regel je Preset erzeugt deshalb
   btnPresetsCss() und gibt sie im Style-Block aus — bis [111] standen hier
   drei Regeln mit den drei festen Namen, und ein selbst angelegtes Preset
   hätte keine gehabt (dieselbe Lehre wie bei den Schriftrollen in [110]).

   Die Presetschlüssel sind zugleich die Whitelist, gegen die sanitizeWalk()
   das Attribut data-btn prüft — ein unbekannter Wert fällt weg und der Button
   bleibt ein Link.

   DIE FARBEN STEHEN ALS RÜCKFALL IN DER ERZEUGTEN REGEL, NICHT ALS WERT IM
   PRESET. Ein Preset auf "automatisch" gibt --btn-<preset>-bg/-fg gar nicht
   erst aus; dann greift der Rückfall auf --btn-bg/--btn-fg, die contentBg()
   pro Sektion setzt (auf der CI-Hauptfarbe invertiert). Das kann nicht im
   Preset stehen: eine Variable, die auf :root eine andere Variable
   referenziert, wird BEIM DEKLARIEREN aufgelöst — dort gibt es kein --btn-bg,
   und der Button bliebe durchsichtig (DEV-LOG [32]). Ein fester Token im
   Preset sticht den Rückfall aus. Welcher Rückfall gilt, sagt die FORM des
   Presets (btnForms()).

   inline-flex statt inline-block seit [111]: mit einer Mindesthöhe muss die
   Beschriftung darin mittig stehen. Ohne Mindestmaße (Vorgabe 0) ist das
   Ergebnis dasselbe wie vorher.

   button[data-btn] seit DEV-LOG [120]: der Abschickknopf eines Formulars
   benutzt dieselben Presets. cursor, weil der Reset in base.css ihn nicht
   setzt und ein <button> sonst den Pfeil zeigt.                             */
.btn, a[data-btn], button[data-btn] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--_bmw, 0); min-height: var(--_bmh, 0);
  padding: var(--_bpy) var(--_bpx);
  border: var(--_bbw) solid var(--_bbc);
  border-radius: var(--_brd);
  background: var(--_bbg);
  color: var(--_bfg);
  font-family: var(--_bff); font-size: var(--_bfs); font-weight: var(--_bfw);
  letter-spacing: var(--_bls); line-height: var(--_blh); text-transform: var(--_btt);
  text-decoration: none;
  transition: transform 0.15s, filter 0.15s;
}
.btn:hover, a[data-btn]:hover, button[data-btn]:hover { filter: brightness(1.08); }
.btn:active, a[data-btn]:active, button[data-btn]:active { transform: translateY(1px); }
button[data-btn] { cursor: pointer; }
button[data-btn]:disabled { cursor: progress; opacity: 0.6; filter: none; transform: none; }

/* Steht der Button allein in einem Absatz, ist er optisch ein eigener Block
   und braucht den Abstand eines solchen. Der Absatz bringt 0.9em der
   Fließtextgröße mit (.rich), der Rest kommt hier — zusammen sind es die
   1.48em der Buttonschrift, mit denen der Button bis E5 an der Textspalte
   hing. Mitten im Satz bleibt er dagegen auf der Zeile. */
.rich > p > a[data-btn]:only-child { margin-top: 0.4em; }

/* ── Footer ────────────────────────────────────────────────────────────── */
/* Ergänzung 13: Der Footer war "viel zu fett" — ×1.75/×1.85 auf einem
   ohnehin großen --sec-pad-y. Zusammen mit der kleineren Schrift ergibt ×0.9
   rund ein Drittel der früheren Bandhöhe. */
.sec--footer { --pad-t: calc(var(--sec-pad-y) * 0.9); --pad-b: calc(var(--sec-pad-y) * 0.9); }
.ft {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--col-gap);
}
/* Der Footer ist enger gesetzt als redaktioneller Fließtext — deshalb nicht
   die 0.9em aus .rich, sondern 1.36em. Zwei Klassen tief, damit die Regel
   gegen .rich gewinnt, ohne dass eine der beiden !important braucht. */
.ft .mtext__body > * + * { margin-top: 1.36em; }
.ft a:hover { text-decoration-thickness: 2px; }

/* ── Einfache Inhaltsseiten: Impressum, Datenschutz ───────────────────────
   Rechtstexte sind Lesestoff, keine Bühne. Sie liefen bisher in der normalen
   Seitentypografie (--t-body-size = 1.65rem ≈ 26 px) — deutlich zu groß für
   mehrere Bildschirmseiten Fließtext, und die ungestylten <h1>/<h2> kamen mit
   dem Browser-Default von 2em obendrauf.

   .t-body liest seine Größe aus --_fs (base.css), deshalb genügt es, diese
   eine Variable zu überschreiben — alles andere (Familie, Farbe, Laufweite)
   bleibt am Tokensystem. Werte in rem, also weiterhin an die Wurzelgröße
   gekoppelt und damit responsiv.                                           */
.ck-simple { --sec-bg: var(--ci-3); --sec-fg: var(--ci-white); }

/* Rechtstext und Fehlerseite sind KEINE Content-Blöcke — contentBg() setzt
   --btn-bg/--btn-fg nur dort. Ohne diese Zeile bliebe ein Button hier
   durchsichtig: die Rückfälle in a[data-btn="solid"] zeigen auf zwei
   Variablen, die es auf diesem Weg nirgends gibt (DEV-LOG [32]).
   Invertiert statt in einer CI-Farbe: --sec-fg und --sec-bg sind hier ein
   festes Kontrastpaar, ein Token wäre eines, dessen Lesbarkeit nach der
   nächsten Farbänderung im Bedienfeld niemand nachrechnet.                */
.ck-simple { --btn-bg: var(--sec-fg); --btn-fg: var(--sec-bg); }
/* Den Platz für den Seitenkopf setzt seit E11 .main--nohero (layout.css) —
   für JEDE Seite ohne Keyvisual und damit auch für diese. Hier stand er bis
   dahin ein zweites Mal; sobald die Fehlerseite ihren Footer bekam, addierten
   sich beide. Bleibt die Mindesthöhe: ein kurzer Rechtstext soll den Footer
   nicht auf halber Höhe stehen lassen.                                     */
.sec--simple { min-height: 70vh; }

.ck-simple .t-body { --_fs: 1.2rem; --_lh: 1.5; }

.ck-simple h1 { font-size: 2.3rem; font-weight: 300; line-height: 1.15; margin-bottom: 1.6rem; }
.ck-simple h2 { font-size: 1.45rem; font-weight: 400; margin-top: 2.8rem; margin-bottom: 0.9rem; }
.ck-simple h3 {
  font-size: 0.88rem; font-weight: 700;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--ci-1);
  margin-top: 2rem; margin-bottom: 0.5rem;
}
.ck-simple h4 { font-size: 1rem; font-weight: 700; margin-top: 1.5rem; margin-bottom: 0.35rem; }

/* Der abschließende Knopf (Fehlerseite) braucht Luft zu dem, was über ihm
   steht — die Absätze der Rechtstexte bringen ihren Abstand aus .rich mit,
   dieser hier steht außerhalb davon. */
.ck-simple .ck-actions { margin-top: 2.2rem; }

.ck-simple address { font-style: normal; line-height: 1.8; margin: 0.7rem 0 1rem; }
.ck-simple ul { list-style: disc; padding-left: 1.4rem; margin-top: 0.8rem; }
/* Nummerierte Klauseln (AGB). base.css nimmt allen Listen die Zaehlung —
   in einem Rechtstext sind die Ziffern aber der Bezugspunkt jedes
   Querverweises ("Ziff. VI.1"), also hier wiederherstellen. */
.ck-simple ol { list-style: decimal; padding-left: 1.7rem; margin-top: 0.8rem; }
.ck-simple li > ul { margin-top: 0.5rem; }
.ck-simple li + li { margin-top: 0.5rem; }

/* Trennt die Fußzeile (Quellenangabe, Querverweise) vom letzten Abschnitt —
   ohne sie klebten die Links direkt unter dem Text. */
.ck-simple hr {
  border: 0;
  border-top: 1px solid color-mix(in srgb, var(--sec-fg) 25%, transparent);
  margin-top: 3.2rem; margin-bottom: 1.8rem;
}

/* Die Sperrseite vor einer Seite mit Passwort (templates/pages/pagepw.php,
   DEV-LOG [129]). Das Feld wie im Kontaktformular (.fm__in, form.css), nur
   hier ausgeschrieben: form.css lädt die Seite erst, wenn ein Formular darauf
   steht. Feld und Knopf nebeneinander, schmal untereinander. */
.ck-pw { margin-top: 2.2rem; max-width: 30rem; }
.ck-pw__lab { display: block; font-size: 0.95rem; margin-bottom: 0.4rem; }
.ck-pw__row { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: stretch; }
.ck-pw__in {
  flex: 1 1 14rem; min-width: 0;
  margin: 0; padding: 0.7em 0.85em;
  font: inherit; font-size: 1.1rem; color: inherit;
  border: 1px solid color-mix(in srgb, var(--sec-fg) 45%, transparent);
  border-radius: 0.25rem;
  background: color-mix(in srgb, var(--sec-fg) 8%, transparent);
  appearance: none;
}
.ck-pw__in:focus { outline: none; }
.ck-pw__in:focus-visible { outline: 2px solid var(--sec-fg); outline-offset: 2px; }
.ck-pw__in[aria-invalid="true"] { border-color: var(--ci-1); }
.ck-pw__err { margin-top: 0.8rem; color: var(--ci-1); }

/* ── Nur Desktop / nur Mobil (segmentProps()['device'], DEV-LOG [104]) ─────
   Die Klasse steht an der Sektion ('seccls'); ausgeblendet wird per
   Media-Query, nicht per Markup — für den Besucher display:none. Im
   Bearbeitungsmodus wird daraus ein grauer Balken (admin.css), sonst wäre das
   Segment in der anderen Ansicht nirgends mehr anzuklicken.
   .sec.sec--dev-* (0,2,0), weil .sec--seg in layout.css display:flex setzt.
   567px = BP_MOBILE + 1, dieselbe Grenze wie in nav.js.                     */
@media (min-width: 567px) {
  .sec.sec--dev-m { display: none; }
}

/* ── Mobil ─────────────────────────────────────────────────────────────────
   566px muss zu BP_MOBILE in lib/schema.php passen.                        */
@media (max-width: 566px) {
  .sec--hero { min-height: 300px; --wedge-h: 22px; }
  .sec.sec--dev-d { display: none; }

  /* Aus zwei oder drei Spalten wird eine, Reihenfolge immer wie im Dokument
     (Vorgabe des Betreibers, 2026-08-23). Wer auf dem Handy das Bild zuerst
     will, tauscht die Module in den Zellen. */
  .mseg--c2, .mseg--c3 { grid-template-columns: 1fr; }

  /* Übereinander gibt es keine senkrechte Fuge — die Trennlinien fallen weg
     (DEV-LOG [99]; deshalb auch kein Mobil-Zwilling in der Registry). */
  :is(.mseg--div-100, .mseg--div-75, .mseg--div-50, .mseg--div-25)::before,
  :is(.mseg--div-100, .mseg--div-75, .mseg--div-50, .mseg--div-25).mseg--c3::after { display: none; }

  /* Die mobile Reihenfolge der Zellen (segmentProps()['order_m'], E12).
     Gedreht wird die ANZEIGE, nicht die Daten — "Zellen spiegeln" bleibt die
     Aktion, die wirklich vertauscht; in der Mobilansicht schreibt sie diesen
     Zustand statt der Daten.
     Feste Werte 3/2/1 gelten fuer zwei UND drei Zellen (bei zweien fehlt 'm'
     einfach). Die drei Zeilen haengen an segCellSets(): eine vierte Spalte
     braucht hier eine vierte, so wie sie auch .mseg--c4 braucht.
     BEWUSSTER KOMPROMISS: Tabreihenfolge und Screenreader folgen dem DOM, die
     Augen dem 'order' (WCAG 1.3.2). Bei Text/Bild-Paaren vertretbar. */
  .mseg--om-rev > .mcell--l { order: 3; }
  .mseg--om-rev > .mcell--m { order: 2; }
  .mseg--om-rev > .mcell--r { order: 1; }

  /* Mobil-Override der Bündigkeit an der BOX (cellProps()['align_m'],
     DEV-LOG [52]; die Feldebene gibt es seit DEV-LOG [95] nicht mehr).

     Diese drei gelten allem, was KEIN Absatz ist — der verkleinerten
     Bilderbox etwa. Für Absätze entscheiden die Regeln weiter unten, und
     zwar am Absatz selbst.                                                 */
  .mcell--am-start  { text-align: start; }
  .mcell--am-center { text-align: center; }
  .mcell--am-end    { text-align: end; }

  /* Der Footer bleibt mobil linksbündig — siehe „Ergänzung 15" weiter unten,
     wo der Rest seiner Mobilregeln steht. Die Zeile MUSSTE hierher, weil sie
     seit 2026-08-24 den Absatz direkt trifft: stünde sie unten, käme sie
     hinter die Ebenen und wäre eine Sperre statt einer Vorgabe.
     Hier ist sie beides richtig herum — sie schlägt die DESKTOP-Regeln (die
     stehen früher in der Datei, gleiche Spezifität) und lässt sich von einer
     in der Mobilansicht gesetzten Bündigkeit überstimmen.

     :where(.ft) statt .ft: sonst läge die Regel bei 0,2,0 und gewönne über
     die Spezifität gegen alles — auch gegen das, was der Betreiber einstellt. */
  :where(.ft) .mcell :where(p, h1, h2, li) { text-align: left; }

  /* DIE MOBILEN EBENEN, alle am ABSATZ und alle bei 0,1,0 — die Reihenfolge
     macht die Rangfolge (E12, repariert in DEV-LOG [63], seit [95] ohne Feld).

     Sie stehen HINTER den Desktopregeln und im @media-Block; "mobil vor
     Desktop" bleibt damit die stärkere Achse: eine mobile Absatzbündigkeit
     sticht eine Desktop-Zellenbündigkeit (bestätigt, Betreiber 2026-08-24).

     Effektive Staffelung, von stark nach schwach (seit DEV-LOG [95]):
       Text:              Absatz mobil > Absatz
       Bilderbox, Player: Zelle mobil  > Zelle

     Rechts steht :where(p, h1, h2, li) und nicht [data-am]: ein Absatz ohne
     eigene Mobilangabe muss von der Zellenregel ERREICHT werden,
     sonst bleibt an ihm die Desktopregel stehen und keine Einstellung in der
     Mobilansicht kommt dagegen an (DEV-LOG [63]).                          */
  :is(.mcell--am-start)  :where(p, h1, h2, li) { text-align: start; }
  :is(.mcell--am-center) :where(p, h1, h2, li) { text-align: center; }
  :is(.mcell--am-end)    :where(p, h1, h2, li) { text-align: end; }

  :where(.rich) [data-am="start"]     { text-align: start; }
  :where(.rich) [data-am="center"]    { text-align: center; }
  :where(.rich) [data-am="end"]       { text-align: end; }

  /* Ergänzung 15: Der Footer BLEIBT zweispaltig — der Platz rechts ist da und
     wurde bisher verschenkt. Deshalb steht .ft nicht in der Einspalten-Regel
     oben. Linksbündig statt zentriert: zwei zentrierte Spalten auf 390 px
     lesen sich als ein zerfallener Block. */
  .ft { gap: calc(var(--col-gap) * 0.75); }
  /* Das Gegenstück für die Absätze steht weiter oben, mitten in der
     Bündigkeitskaskade — dort und nur dort hat es die richtige Stellung. */
  .ft .mcell { text-align: left; }
}
