/* Layout-Defaults fuer den Elementor-Nachbau.
 *
 * ACSS bringt eigene Strukturvorgaben mit:
 *
 *   :where(section:not(section section))  padding-block: var(--section-padding-block);
 *                                         padding-inline: var(--gutter);
 *   section:where(:not(.bricks-shape-divider))       display:flex; align-items:center;
 *                                                    gap: var(--container-gap);
 *   section > div:where(:not(.bricks-shape-divider)) display:flex; align-items:flex-start;
 *                                                    gap: var(--content-gap);
 *
 * Gemessen auf lifespin.health am 2026-08-19: Elementors .e-con ist flex/column mit
 * align-items:normal und gap:normal, Padding kommt ausschliesslich aus dem Element selbst.
 * Die ACSS-Defaults addieren dagegen 90px Block-Padding, 60px Gutter, 67.5px Container-Gap
 * und 30px Content-Gap auf JEDEN Abschnitt — auf /datenschutz_apotheke/ allein 2.400 px
 * Mehrhoehe. align-items:flex-start laesst zusaetzlich jede Ueberschrift auf ihre Textbreite
 * schrumpfen statt auf volle Spaltenbreite zu stehen.
 *
 * Geltungsbereich bewusst nur <main>: Header, Footer und Popups werden nativ in Bricks
 * gebaut und duerfen ACSS' Defaults behalten.
 *
 * Specificity: 0,1,2 bzw. 0,1,3 — schlaegt ACSS (0,0,0 bis 0,0,2), verliert aber gegen
 * Bricks' elementeigene #brxe-xxxxxx-Regeln. Der Konverter behaelt damit das letzte Wort.
 */

main section.brxe-section {
	padding-block: 0;
	padding-inline: 0;
	align-items: normal;
	gap: normal;
}

main section.brxe-section > div {
	align-items: normal;
	gap: normal;
}

/* Bricks' eigene Vorgabe steht in frontend-layer.min.css in @layer bricks:
 *   .brxe-block     { align-items: flex-start; display: flex; flex-direction: column }
 *   .brxe-container { align-items: flex-start; ... }
 * Elementors .e-con steht dagegen auf align-items: normal (stretch) — am 2026-08-20 auf
 * lifespin.health gemessen. Die beiden Regeln oben fassen nur den Abschnitt und dessen
 * DIREKTE Kinder; der Konverter schachtelt aber section > .ls-inner > .ls-con > .ls-widget,
 * und ab Ebene zwei schrumpft jede Ueberschrift wieder auf Textbreite — auf / stand
 * "Metabolomics and Human Health" 619 statt 1380 px breit, und Zeilencontainer ziehen ihre
 * Karten nicht mehr auf gleiche Hoehe.
 *
 * Geltungsbereich bewusst auf die Konverter-Klassen ls-con/ls-inner/ls-widget begrenzt und
 * NICHT auf .brxe-block allgemein: die von Hand gebauten Schleifenvorlagen (loops.css,
 * .ls-posts__*) rechnen mit Bricks' flex-start. Mit dem breiteren Selektor stieg /newsroom/
 * von 172 auf 195 und / von 99 auf 133 Abweichungen.
 * Unlayered und damit staerker als @layer bricks — Spezifitaet spielt hier keine Rolle. */
main .ls-con,
main .ls-inner,
main .ls-widget {
	align-items: normal;
}

/* Gegenausnahme. Elementor rendert Knopf, Textlink, Symbol und Formular als inline-block
 * INNERHALB eines gedehnten Widget-Rahmens; die Box haengt am Inhalt, nicht am Container.
 * Bricks setzt das Element selbst an diese Stelle — ohne die Ausnahme wird der Knopf
 * "Explore more" auf / 621 statt 176 px breit.
 *
 * BEWUSST `width: fit-content` statt `align-self: flex-start`.
 * Beides verhindert das Dehnen, aber align-self ueberschreibt zusaetzlich das align-items
 * des Elternkastens — und genau darueber setzt Elementor die Ausrichtung. Auf
 * /products-and-services/ steht der Knopf "Sample Report" in einem Kasten mit
 * align-items: flex-end (auf Live UND Dev identisch gemessen, .e-con-full bzw. .ls-con,
 * beide 750..1349); Live rendert ihn deshalb bei x=1134, Dev mit align-self:flex-start bei
 * x=750. Ebenso "Learn more about lifespin" auf / (Live x=614 zentriert, Dev x=56) und
 * "Contact us" (Live 1281, Dev 631). Mit fit-content bleibt align-items wirksam und der
 * Knopf steht wieder da, wo Elementor ihn setzt. */
main .brxe-button,
main .bricks-button,
main .brxe-text-link,
main .brxe-icon,
main .brxe-social-icons,
main .brxe-shortcode,
main .brxe-form {
	width: fit-content;
	max-width: 100%;
}

/* ENTFALLEN IN R43 — die folgende Herleitung beschreibt eine Regel, die es nicht mehr
 * gibt. Sie steht als Begruendung stehen, weil sie den Mechanismus erklaert; die
 * Aufloesung steht am Ende des Blocks.
 *
 * … und dasselbe noch einmal mit !important, aber NUR fuer Knoepfe, die ein a-Element sind.
 *
 * Elementor traegt die Breite eines Bausteins am WIDGET-RAHMEN
 * (.elementor-widget__width-initial { width: 476px }); der Knopf darin ist inline-block und
 * bleibt so breit wie sein Text. Der Konverter hat in Bricks keinen Rahmen mehr und schreibt
 * die Breite an das Element selbst — der Knopf traegt aber den roten Hintergrund.
 * Gemessen auf /company/, Knopf "Explore more":
 *   Live  Rahmen 136..612 (476px, unsichtbar), a 136..312 (176px, rot)
 *   Dev   a 50..526 (476px, rot)  -> die Flaechenmeldung "BREITE 176 -> 476, rgb(135,10,9)"
 * Die Regel des Konverters steht als #brxe-xxxxxx (1,0,0) und schlaegt jede Klassenregel,
 * deshalb !important.
 * Bewusst nur a[class]: der Absendeknopf des Kontaktformulars ist ein button-Element und
 * ist auf Live tatsaechlich 966px breit (siehe elements.css, .cnt-form). */
/* NACHTRAG R10 — die Regel gilt jetzt nur noch oberhalb 768px, und darunter nur noch an
 * dem EINEN Element, das sie dort wirklich braucht.
 *
 * Der Konflikt: Elementors `elementor-mobile-align-justify` heisst am Knopf „auf volle
 * Containerbreite strecken". Der Konverter uebersetzt das richtig; Bricks gibt daraus
 * `@media (max-width:767px){ #brxe-xxxxxx { width:100% } }` aus (1,0,0). Ein `!important`
 * an einer Klassenregel schlaegt das — 24 Knoepfe auf 11 Seiten standen deshalb auf Mobil
 * auf Textbreite statt auf voller Breite. Der Konverter hat mit einer eigenen ID-Regel
 * `a#brxe-xxxxxx { width:100% !important }` dagegengehalten.
 *
 * Nachgemessen statt geschaetzt (diag/r10/wscan.py, alle 21 ausgelieferten Dev-Seiten,
 * jede `#brxe-…{…width…}`-Regel aus Bricks' Seiten-CSS nach Haltepunkt sortiert):
 *
 *   width am Knopf OHNE Haltepunkt (= Elementors Widget-Rahmenbreite):  2 Knoepfe
 *       /company/                #brxe-346312   486px
 *       /science-and-technology/ #brxe-5d0723   800px
 *   width am Knopf NUR in `max-width:767px` (= justify):               24 Knoepfe
 *
 * Gegenprobe im Browser (diag/r10/btn.py, Regel probeweise ganz entfernt, Live gegen Dev,
 * jeder sichtbare Knopf jeder Seite): genau diese zwei weichen ab, sonst kein einziger.
 *
 *   1440   science „Get in touch"  Live 164 / Dev 731.6      company „Explore more" Live 176 / Dev 476
 *    768   science „Get in touch"  Live 164 / Dev 648        company „Explore more" Live 166 / Dev 486
 *    390   —                                                 company „Explore more" Live 166 / Dev 330
 *
 * Bei 390 faellt `5d0723` heraus, weil dort Bricks' eigene Haltepunktregel (`width:100%`,
 * gleiche Spezifitaet, spaeter in der Datei) die 800px ueberstimmt — Live misst dort
 * ebenfalls volle 330px. Uebrig bleibt unterhalb 768 ein einziger Knopf.
 *
 * Die Behauptung „die meisten Knoepfe brauchen die Regel auch unter 768" trifft nicht auf
 * DIESE Regel zu, sondern auf die Klassenregel darueber (0,2,0, ohne !important). Die
 * bleibt unveraendert fuer alle Breiten stehen und haelt alle uebrigen Knoepfe auf
 * fit-content; nur gegen ID-Regeln ist sie machtlos, und ID-Regeln mit einer Breite gibt
 * es an Knoepfen eben nur zweimal.
 *
 * ==> Der Konverter-Agent kann seine Gegenregel
 *     `a#brxe-…{width:100%!important}` / `a.brxe-…{width:100%!important}`
 *     (convert.py, btn_justify-Zweig) ERSATZLOS ZURUECKNEHMEN. */
/* R43 — hier standen bis Runde 42 ZWEI Ausnahmen:
 *   @media (min-width:768px){ main a.brxe-button, main a.bricks-button
 *                             { width: fit-content !important } }
 *   :where(body.page-id-15307) main a#brxe-346312 { width: fit-content !important }
 * Beide gab es nur, weil die Rahmenbreite aus `_element_custom_width` auf dem KNOPF
 * landete (die zwei oben genannten ID-Regeln). Seit R43 baut convert.py dafuer einen
 * echten Rahmenknoten (Fall 204) — die Breite liegt am `div.ls-btnwrap`, an keinem Knopf
 * der Site steht mehr eine `width` ohne Haltepunkt. Damit ist auch das `!important`
 * ueberfluessig: die Klassenregel darueber (0,2,0) haelt alle Knoepfe auf fit-content,
 * und die einzige verbliebene ID-Breite an Knoepfen ist Elementors `align: justify`
 * (`max-width:767px`, `width:100%`) — die SOLL gewinnen.
 * A/B belegt auf /company/ und /science-and-technology/ ueber 1900/1440/768/390. */

/* Das Bricks-Text-Element traegt rohes HTML (Elementors text-editor). Als Flex-Container
 * bekaeme jeder Absatz zusaetzlich den Content-Gap und Margins kollabieren nicht mehr.
 * Elementor rendert den Block ganz normal im Flussmodell. */
main .brxe-text {
	display: block;
}

/* Bricks zieht Bilder per .brxe-image img{width:100%} auf Containerbreite. Elementor tut das
 * nicht — dort gilt max-width:100% bei width:auto, die Groesse kommt aus dem Element.
 * Auf /metabopro-regensburg/ rendert ein 56x71-Icon sonst 1140 px breit.
 * Setzt der Konverter eine Breite, gewinnt dessen #brxe-…-Regel (1,0,0) gegen diese hier. */
main .brxe-image img,
main figure.brxe-image img {
	width: auto;
	max-width: 100%;
}

/* Elementor setzt auf JEDEN Container und jedes Widget `min-width: 0`
 * (frontend.css: `.e-con{min-width:0}` und `.e-con .elementor-widget{min-width:0}`).
 * Bricks tut das nicht — Flex-Kinder haben dann `min-width: auto` und koennen nicht unter
 * ihre Inhaltsbreite schrumpfen. Auf /products-and-services/ standen dadurch drei Bloecke
 * zu je 1100 px in einer 1380 px breiten Zeile und die Seite lief auf 3330 px auf.
 * Betrifft ebenso Grid-Spalten: ohne min-width:0 sprengt breiter Inhalt die Spur. */
main [class*="brxe-"] {
	min-width: 0;
}

/* Der INNENcontainer fuellt die Hoehe seines Abschnitts.
 *
 * Elementor gibt jedem `.e-con-inner` `flex-grow: 1` (am 2026-08-20 auf lifespin.health
 * am Element gemessen: computed flex-grow 1). Der Innencontainer ist damit immer so hoch
 * wie der Polsterkasten seines Abschnitts, und seine eigene Ausrichtung
 * (justify-content) verteilt den Inhalt DARIN.
 * Im Nachbau ist `.ls-inner` ein gewoehnliches Flex-Kind mit flex-grow 0 und deshalb nur
 * so hoch wie sein Inhalt; ein `justify-content: center` am .ls-inner bleibt wirkungslos.
 *
 * Gemessen auf /products-and-services/, Kopfabschnitt („Products and Services“), 1440:
 *   Live  Abschnitt 72..452 (min-height 380), e-con-inner 380 hoch, Polster 60,
 *         justify-content: center -> Inhalt (211 hoch) bei y=157, oben wie unten 85 Luft.
 *   Dev   Abschnitt 72..452 (min-height 380), .ls-inner nur 191 hoch, oben buendig
 *         -> Ueberschrift und Knoepfe sassen 25px zu hoch.
 * Im Browser gegengeprueft: mit dieser Regel .ls-inner 191 -> 260 = Polsterkasten,
 * und die Zentrierung greift.
 * Sichtbar nur dort, wo der Abschnitt hoeher ist als sein Inhalt (min-height/Hero);
 * sonst ist flex-grow wirkungslos, weil es keinen freien Platz gibt. */
main .ls-inner {
  flex-grow: 1;
}

/*
 * Elementor gibt JEDEM Container position: relative (frontend.css: `.e-con { position:
 * relative }`). Bricks tut das nicht. Ein absolut positioniertes Element bezieht sich
 * dadurch auf den naechsten positionierten Vorfahren — im Zweifel auf die Seite selbst.
 * Auf /company/ war das Hintergrundlogo deshalb 900 statt 711px breit (100% von 1440,
 * begrenzt durch max-width) und sass an der falschen Stelle.
 */
.ls-con {
  position: relative;
}

/* … und die Gegenausnahme fuer den INNENcontainer der `right-btn`-Abschnitte.
 *
 * Im Bild gefunden, von keiner der drei Messungen gemeldet: scmp vergleicht bewusst keine
 * y-Lage, und der Knopf „Explore products & services" auf / stand dadurch unbemerkt 100px
 * zu tief — auf Live neben der Ueberschrift, auf Dev darunter.
 *
 * Gemessen (1440), Lage des Knopfes relativ zur Oberkante seines Abschnitts:
 *   Live  +106   Dev  +206
 * Beide Seiten positionieren den Knopf absolut mit `top: 66px; right: 0`
 * (`.right-btn .my-btn`, aus dem urspruenglichen Astra-Child-CSS). Der Unterschied liegt
 * im BEZUGSRAHMEN:
 *   Live: `.right-btn .e-con-inner{position:relative}`; der Abschnitt hat `padding: 0 30px`,
 *         das 100px-Polster sitzt am e-con-inner. Dessen Polsterkasten beginnt also GENAU
 *         an der Abschnittsoberkante -> 66 + 40 = 106.
 *   Dev:  site.css portiert die Regel wortgleich auf `.right-btn .ls-inner`, aber im
 *         Nachbau traegt der <section> das Polster (`padding: 100px 30px`) und .ls-inner
 *         beginnt 100px tiefer -> 206.
 * Dasselbe Polster-Verschiebungsmuster wie beim Wasserzeichen weiter unten.
 *
 * Mit `position: static` ist der Bezugsrahmen wieder der Abschnitt selbst; dessen
 * Polsterkasten beginnt an der Abschnittsoberkante, genau wie Elementors e-con-inner.
 * Ergebnis 66 + 40 = 106 = Live.
 *
 * ACHTUNG fuer den Schleifen-/Nachbau-Agenten: `.right-btn .my-btn { margin-top: 0 }` in
 * loops.css ist damit FALSCH. Die 40px sind auf Live real vorhanden — dort als
 * Innenabstand im Widget-Rahmen (Rahmen 88px hoch, Knopf 48px, 40px darueber), hier als
 * margin-top am Knopf. Ohne sie steht der Knopf 40px zu hoch. */
main section.right-btn > .ls-inner {
  position: static;
}

/* Waagerechter Ausgleich zur Regel darueber — OHNE Zahl.
 *
 * NACHTRAG R8 (K5). Hier stand `right: 30px`. Die 30px sind das Seitenpolster des
 * Abschnitts und stimmen nur dort, wo der Innencontainer die volle Inhaltsbreite hat.
 * Am Element gemessen (1440):
 *
 *   Seite        Abschnitt   Innencontainer            Live rechte Kante des Knopfes
 *   /            0..1440     x=30  b=1380 (voll)       1410  = 1440 - 30
 *   /newsroom/   0..1440     x=105 b=1230 (width:1230, margin-inline:auto -> 75px)
 *                                                      1335  = 1440 - 105
 *
 * Der Rinnstein ist also 30 bzw. 105 px; mit dem festen Wert stand der Knopf auf
 * /newsroom/ 75px zu weit rechts, sichtbar ueber die Inhaltsspalte hinaus
 * (`X 1203 -> 1278 [t] More news`, dazu `More events` und 4 Ikonenwerte).
 *
 * Live leitet den Wert aus KEINER Zahl ab: dort ist `.e-con-inner` der Bezugsrahmen
 * (`position: relative`) und der Knopf steht schlicht auf `right: 0`. Genau diese
 * Ableitung wird hier wiederhergestellt, ohne den Bezugsrahmen zu wechseln (der muss
 * fuer die SENKRECHTE Lage der Abschnitt bleiben, s. Regel darueber):
 *
 *   `right: auto` (statt 0 aus site.css) laesst das absolut gesetzte Element auf seiner
 *   STATISCHEN Lage stehen — also dort, wo es im Fluss seines Elternkastens saesse.
 *   Der Elternkasten ist `.ls-inner`, und fuer ein absolutes Kind eines Flex-Kastens
 *   bestimmt `align-self` diese statische Lage (CSS Box Alignment 4, in Chrome umgesetzt).
 *   `.ls-inner` ist flex/column, die Querachse ist damit die waagerechte:
 *   `align-self: flex-end` = rechte Kante des Innencontainers.
 *
 * Im Browser gegengeprueft (Regel injiziert, `diag/r8/t_btn.py`):
 *   /          "Explore products & services" x=1131 (Live 1131), rechte Kante 1410
 *              "Latest news"                 x=1243 (Live 1243), rechte Kante 1410
 *   /newsroom/ "More news"                   x=1177 (Live 1177), rechte Kante 1335
 *              "More events"                 x=1166 (Live 1166), rechte Kante 1335
 * Der Wert stellt sich auf jeder Seite selbst ein; die Breite des Innencontainers
 * steht nirgends mehr in dieser Datei.
 *
 * Geltungsbereich `@media (min-width: 1025px)` wie die Ursprungsregel in site.css:
 * darunter ist der Knopf KEIN absolutes Element mehr, sondern ein gewoehnliches
 * Flex-Kind — dort wuerde `align-self: flex-end` ihn tatsaechlich verschieben. */
@media (min-width: 1025px) {
  main section.right-btn .my-btn {
    right: auto;
    align-self: flex-end;
  }
}

/* ---------------------------------------------------------------------------
 * Einzelfaelle, die der Konverter (noch) nicht abbildet.
 *
 * work/convert.py kennt Elementors Transform-Gruppe (_transform_translateX_effect u.a.)
 * nicht — im ganzen Skript kommt "translate" nicht vor, und generated.css enthaelt zu
 * keinem Element eine transform-Regel. Ebenso wenig uebertraegt es Elementors
 * Ausrichtungsklasse .elementor-align-center des Button-Bausteins.
 * Solange das so ist, stehen die betroffenen Elemente hier. Die Regeln sind bewusst an die
 * Bricks-Element-ID gebunden und mit derselben Spezifitaet (1,0,0) geschrieben wie die des
 * Konverters; generated.css laedt NACH layout.css und ueberstimmt sie damit automatisch,
 * sobald convert.py die Eigenschaften selbst ausgibt. Dann koennen sie ersatzlos weg.
 *
 * NACHTRAG R10 — ID-SELEKTOREN SIND AN IHRE SEITE GEBUNDEN.
 * Bricks-Element-IDs sind NICHT seitenweit eindeutig. Ein Element, das aus derselben
 * Elementor-Vorlage stammt, traegt auf jeder Seite dieselbe `brxe-xxxxxx`. Nachgezaehlt
 * ueber alle 21 ausgelieferten Dev-Seiten (`diag/r10/html/`, `grep -l`):
 *
 *   #brxe-6c6336   company + products-and-services + science-and-technology   <-- geblutet
 *   alle uebrigen IDs dieser Datei                                            eindeutig
 *
 * Der Schaden war sichtbar: `#brxe-6c6336::before { background-image: global-map.svg }`
 * legte die Weltkarte auf /products-and-services/ quer ueber den Kasten „Standard
 * phlebotomy" und ebenso auf /science-and-technology/ (Bild: work/diag/r9s/
 * pas-globalmap-leck.png). Auf Live traegt die Grafik nur /company/ — belegt am
 * ausgelieferten Live-HTML: `data-dce-background-overlay-image-url` kommt auf /company/
 * zweimal vor (global-map.svg, event-graphic.svg) und auf den beiden anderen Seiten
 * KEIN EINZIGES Mal.
 *
 * Dass heute nur eine ID kollidiert, ist Zufall und keine Zusage — jede weitere
 * Konverterrunde kann neue Doppelungen erzeugen. Deshalb sind ALLE ID-Selektoren dieser
 * Datei an ihre Seite gebunden, nicht nur der eine Schadensfall.
 *
 * Bewusst `:where(body.page-id-NNNN)` und NICHT `body.page-id-NNNN`:
 * `:where()` steuert null zur Spezifitaet bei. Die oben beschriebene Buchhaltung bleibt
 * damit exakt erhalten — die Regeln stehen weiterhin bei 1,0,0 bzw. 1,0,1 und werden von
 * generated.css automatisch ueberstimmt, sobald convert.py sie selbst ausgibt. Mit einer
 * gewoehnlichen Klasse waeren sie auf 1,1,0 gestiegen und haetten den Konverter dauerhaft
 * blockiert.
 * Seiten-IDs: home 101 (dort `body.home`), contact 10771, products-and-services 14418,
 * company 15307, science-and-technology 12494.
 * ------------------------------------------------------------------------- */

/* /company/ — zwei Spalten mit Elementor-Transform.
 * Live gemessen (computed transform am Spaltencontainer):
 *   Textspalte "Careers"            matrix3d(… -106.613 …) = translateX(-15%) von 710.75px
 *   Textspalte "Investor Relations" matrix3d(…   86.4   …) = translateX(+15%) von 576px
 * Ohne sie sass der gesamte Careers-Block 106px zu weit rechts (X 673 -> 779, Logo 593 -> 699)
 * und der gesamte Investor-Block 86px zu weit links (X 136 -> 50).
 *
 * R13 — NUR OBERHALB 880px. Die Regel stand ohne Haltepunkt und hat unterhalb
 * davon einen WAAGERECHTEN UEBERLAUF erzeugt: dort sind die beiden Spalten
 * volle Viewportbreite, 15% davon schieben sie ueber den Rand hinaus.
 * Gemessen (`document.documentElement.scrollWidth`, /company/):
 *
 *            Live      Dev vorher            Dev nachher
 *   768      768       883  (+115.2 px)      768
 *   390      390       449  (+58.5  px)      390
 *
 * Bis wohin Live die Verschiebung ueberhaupt anwendet, ist ausgemessen —
 * computed transform der Spalte `.elementor-element-bacc161`, Viewport
 * schrittweise verkleinert:
 *
 *   1440 -> +86.4   1200 -> +72   1025 -> +61.5   900 -> +54   881 -> +52.9
 *    880 -> 0        860 -> 0      840 -> 0       822 -> 0     768 -> 0
 *
 * Die Kante liegt exakt zwischen 880 und 881 (Elementors Tablet-Haltepunkt
 * dieser Seite; `elements.css` benutzt dieselbe 880 bereits). Der Bildvergleich
 * konnte den Fehler nicht melden, sondern ist daran ABGESTUERZT: bei
 * unterschiedlicher Seitenbreite bricht `vdiff.py` in `compare()` ab, /company/
 * fiel im 768er-Lauf mit `FEHLER` aus der Messung. */
@media (min-width: 881px) {
  :where(body.page-id-15307) #brxe-0538f5 { transform: translateX(-15%); }
  :where(body.page-id-15307) #brxe-5eb70f { transform: translateX(15%); }
}

/* / — Knopf "Learn more about lifespin" im Abschlussblock.
 * Live traegt der Widget-Rahmen die Klasse .elementor-align-center; der inline-block-Knopf
 * wird dadurch ueber text-align zentriert (Live x=588..852 in einem 30..1410 breiten Kasten).
 * In Bricks ist der Knopf selbst das Element, Zentrierung geht nur ueber align-self. */
:where(body.home) #brxe-794253 { align-self: center; }

/* / — Wasserzeichen „lifespin" (site-logo.svg) im Abschlussblock am Seitenende.
 *
 * Zwei Abweichungen, beide am Element gemessen (1440):
 *
 * a) DECKKRAFT. Live traegt das img `opacity: 0.21` (Elementors Bild-Einstellung,
 *    ueber neun Scrollpositionen konstant gemessen — kein Motion-Effect), Dev 1.
 *    Das Logo stand dadurch als volldeckende rote Grafik im Block statt als blasses
 *    Wasserzeichen. In scmp.py taucht das nicht auf: der Bildstrom vergleicht
 *    Datei, Masse und x-Offset, keine Deckkraft.
 *
 * b) LAGE. Beide Seiten positionieren das Bild absolut, 1440x407, im 600px hohen
 *    Abschnitt. Live sitzt es 96.3px unter der Abschnittsoberkante, Dev 57.3px —
 *    39px zu hoch. Ursache: bei Elementor traegt der INNENcontainer .e-con-inner
 *    das 100px-Polster und ist volle 600px hoch; die Statiklage des absoluten
 *    Widgets ist dessen Inhaltsbox (400px) und damit die Abschnittsmitte.
 *    Im Nachbau liegt das Polster am <section>, .ls-inner ist nur 322px hoch
 *    (Inhaltshoehe), und die Statiklage liegt entsprechend 39px hoeher.
 *    top/bottom:0 mit margin-block:auto zentriert wieder im Polsterkasten des
 *    Abschnitts — rechnerisch (600-407)/2 = 96.5, also Live-Lage. */
:where(body.home) #brxe-ce8cec {
	opacity: .21;
	top: 0;
	bottom: 0;
	margin-block: auto;
}

/* /company/ — Knopf "Explore more".
 * Sein Elternkasten ist eine Zeile mit justify-content:flex-end (Live wie Dev identisch).
 * Auf Live faellt das nicht auf, weil der Widget-Rahmen mit seinen 476px den Kasten ohnehin
 * ausfuellt und der Knopf darin links steht (x=136). Auf Dev ist der Knopf selbst das
 * Element; ohne den Rahmen schiebt flex-end ihn nach rechts (gemessen x=436 statt 136).
 * margin-right:auto nimmt die Rolle des Rahmens ein.
 *
 * NACHTRAG r6: die Regel stand als `#brxe-346312` und war wirkungslos geworden.
 * convert.py gibt zu demselben Element inzwischen
 * `#brxe-346312 { margin-right: calc(0px + 0px); width: 486px }` aus (Elementors
 * Widget-Rahmenmasse). Gleiche Spezifitaet 1,0,0, generated.css laedt spaeter — also
 * gewinnt der Konverter, und der Knopf sass wieder bei x=436 statt 136.
 * `main #…` hebt die Regel auf 1,0,1 und stellt die Absicht wieder her; die 486px
 * Breite faengt weiterhin `width: fit-content !important` weiter oben ab (gemessen 176). */
/* R43 — hier stand bis Runde 42
 *   :where(body.page-id-15307) main #brxe-346312 { margin-right: auto }
 * Sie hat den fehlenden Widget-Rahmen ERSETZT. Mit dem echten Rahmen aus Fall 204 ist
 * sie ersatzlos entfallen: der Knopf ist im Blockkasten wieder inline-flex und wird —
 * wie auf Live — vom `text-align` des Rahmens ausgerichtet, nicht von auto-Abstaenden.
 * Ein inline-Kasten verzehrt ohnehin keine auto-Margins; genau daran ist die
 * Zentrierung bei 390 zuerst gescheitert (Live x=112, Dev x=30). */

/* R37 — hier stand bis Runde 36 eine Handausnahme
 *   :where(body.home) main #brxe-a16216 { margin-inline: 0 }
 * gegen die Sammelregel `main img.brxe-image { margin-inline: auto }` in
 * elements.css. Sie ist ERSATZLOS ENTFALLEN: convert.py erkennt seit R36 selbst,
 * wann Elementors Bild-Rahmen auf die Bildbreite schrumpft (scan_img_shrink,
 * Fall 180) und schreibt dann ausdrueckliche Nullen als Elementeinstellung —
 * die schlagen als #brxe-<eid> (1-0-0) die Sammelregel (0-1-2).
 * A/B belegt: / bei 1440/768/390 Band fuer Band unveraendert (0/0/1), und am
 * WERT gemessen (diag/r37-img.py) liegt die Grafik auf beiden Staenden bei
 * x=30 mit margin 0/0 — bei 1440, 1200 und 1024.
 * NICHT entfernen: die zweite Ausnahme fuer /products-and-services/ bei 390,
 * die geht in die GEGENRICHTUNG (dort zentriert Live und der Nachbau nicht). */


/* / — dieselbe Grafik, die zweite Haelfte des Befundes: sie ist 3px zu hoch.
 * R13, am gerenderten <img> gemessen (1440):
 *
 *                                   Live          Dev vorher
 *   natuerliche Groesse             991x336       991x336
 *   width/height-Attribut am <img>  991 / 335     fehlt
 *   gerenderte Breite               991.234       1000
 *   gerenderte Hoehe                335.719       338.688
 *   computed width                  991.234px     1000px      (max-width beidesmal 1000px)
 *
 * Elementor gibt dem Bild KEINE Breite; es rendert auf seiner natuerlichen
 * Breite 991.23, die unter der max-width bleibt. `generated.css` setzt
 * `img#brxe-a16216 { width: 100% }` (1,0,1) — damit fuellt es die 1000px aus
 * und wird 3px hoeher. Diese 3px schieben die beiden folgenden Abschnitte
 * nach unten; im Bildvergleich sind das die zwei staerksten Baender der
 * Startseite (y 3976 Staerke 28.5 und y 4576 Staerke 29.8, beides
 * Abschnittskanten). Der Versatzausgleich von `vdiff.py` rechnet auf dem um
 * Faktor 8 verkleinerten Bild und kann Versaetze unter 8px nicht wegrechnen —
 * deshalb erscheinen 3px als starker Fund.
 * Abschnittshoehen zum Beleg, dass es genau diese eine Stelle ist
 * (`diag/r13sect.py / 1440`): Abschnitt 0/1/2 dh 0.0, Abschnitt 3 dh +3.0,
 * Abschnitt 5 dh 0.0 bei dtop +3.0, Abschnitt 6 dtop +3.0.
 *
 * ==> Gehoert an den Konverter-Agenten (`convert.py`): ein Bild ohne
 * Breitenangabe in Elementor darf nicht `width: 100%` bekommen, sondern
 * `width: auto`. Der Konverter kennt die Unterscheidung bereits — in
 * `generated.css` stehen beide Formen nebeneinander (`img#brxe-0c5ae2 {
 * width: auto }` gegen 86x `width: 100%`). Bis dahin dieser Notnagel;
 * `main img#…` hebt auf 1,0,2 und braucht kein !important. */
:where(body.home) main img#brxe-a16216 { width: auto; }

/* / — dieselbe Ursache an der MOBILFASSUNG derselben Grafik
 * (`digital-twins-mob-graphic.svg`, `#brxe-cc23a2`), und dort viel groesser.
 * Gemessen bei 768:
 *
 *              Live               Dev vorher
 *   natuerlich 468x336            468x336
 *   gerendert  468 x 336          600 x 431      (max-width beidesmal 600px)
 *
 * `generated.css img#brxe-cc23a2 { width: 100% }` blaeht die Grafik auf die
 * volle max-width auf: 132 px breiter und 95 px hoeher als auf Live. Im
 * Bildvergleich bei 768 ist das das staerkste Band der Startseite
 * (y 4312..4688, Staerke 38.0) — im Bild zwei deutlich verschieden grosse
 * Menschfiguren nebeneinander.
 * Bei 390 greift auf beiden Staenden `max-width: 300px` und beide rendern
 * 300x215 — dort ist der Fall gegenstandslos. Deshalb `width: auto` ohne
 * Haltepunkt: es aendert nur, wo die natuerliche Breite unter der max-width
 * liegt, und genau das ist Elementors Verhalten.
 * ==> Ursache in `convert.py`, wie bei `#brxe-a16216`. */
:where(body.home) main img#brxe-cc23a2 { width: auto; }

/* /contact/ — die drei Kontaktspalten („Phone numbers", „Follow lifespin", …) stehen
 * zusammengedraengt.
 * Gemessen: Live drei gleiche Spalten a 433.33px bei x=30/503/977 in einem 1380px
 * breiten Zeilencontainer (Luecke 40px: 3x433.33 + 2x40 = 1380).
 * Dev: drei Spalten a 320px bei x=30/390/750 in einem 1040px breiten Container
 * (3x320 + 2x40 = 1040) — daher die scmp-Meldungen X 503->390 und X 977->750 an
 * „Phone numbers", „General:", „E-Mail:", „Follow lifespin", „LinkedIn" u.a.
 * Ursache ist eine EINZELNE Regel, die convert.py ausgibt: `#brxe-bb7d53 { width: 1040px }`.
 * Auf Live hat der entsprechende Container keine Breitenangabe, er ist die vollen 1380px
 * (= 100% von .e-con-inner). Die 1040 sind im Elementor-Baum nicht belegt.
 * Das ist ein Konverter-Fehler und gehoert nach convert.py; bis dahin dieser Notnagel.
 * Bewusst `width: 100%` (nicht 1380px): keine feste Breite, sondern dieselbe Ableitung,
 * die Elementor hat. */
:where(body.page-id-10771) main #brxe-bb7d53 { width: 100%; }

/* /products-and-services/ — die beiden „Contact us"-Zeilen teilen sich falsch auf.
 *
 * Gemessen (1440), Zeile „For individuals": Live Textspalte 899 / Knopfspalte 431,
 * Dev 525 / 805. Der Absatz lief dadurch auf Dev vierzeilig und die Zeile 36px zu hoch
 * (scmp: `BREITE 854 -> 523`). Zeile „For corporate partners": Live 916 / 414,
 * Dev 931 / 399.
 *
 * Ursache, in Elementors Seiten-CSS nachgelesen und am Element bestaetigt:
 *   .elementor-element-32cc151.e-con { --flex-grow: 0; --flex-shrink: 0 }   (Textspalte)
 *   .elementor-element-d0f9023.e-con { --flex-grow: 0; --flex-shrink: 0 }   (Knopfspalte)
 * Genau EINE der beiden Spalten je Zeile darf nicht schrumpfen; die andere gibt nach.
 * Auf Dev stehen beide auf flex-shrink 1 und teilen sich den Fehlbetrag anteilig.
 * convert.py uebertraegt Elementors Container-Einstellung `flex_shrink` nicht.
 *
 * Im Browser gegengeprueft (Regel injiziert): 525/805 -> 899/431 und 931/399 -> 916/414,
 * beides exakt die Live-Werte. */
:where(body.page-id-14418) #brxe-340341 { flex-shrink: 0; }   /* Textspalte „For individuals" */
:where(body.page-id-14418) #brxe-3bed32 { flex-shrink: 0; }   /* Knopfspalte „For corporate partners" */

/* /products-and-services/ — Trennlinien-Bausteine ohne senkrechten Abstand.
 *
 * Elementors divider-Widget hat eine Einstellung „Gap", die als
 * `.elementor-divider { padding-block: N }` ausgegeben wird. Am Element gemessen (1440):
 *   4f7f770  60px/60px  -> Widget 121px hoch (60 + 1 Linie + 60)
 *   c5d4eb8  20px/20px  -> 41px      \
 *   02223e6  20px/20px  -> 41px       > die drei Linien im Abschnitt „For corporate …"
 *   13cee76  20px/20px  -> 41px      /
 * Auf Dev sind alle vier Bausteine 1px hoch: weder convert.py noch eine Theme-Datei gibt
 * dem `.brxe-divider` ein Polster. Fehlbetrag 120 + 3x40 = 240px — der groesste Einzelposten
 * der 284px, um die die Seite auf Dev zu kurz war (Live 5298, Dev 5014).
 *
 * Der Wert ist eine Einstellung je Baustein und gehoert deshalb nach convert.py; bis dahin
 * hier als Einzelfall mit Spezifitaet 1,0,0, damit generated.css ihn automatisch ueberstimmt,
 * sobald der Konverter ihn selbst ausgibt.
 * Gemessen sind auf weiteren Seiten: /science-and-technology/ 8x 10px, /kit-information-plasma/
 * 40px, /metabopro-regensburg/ 25px (dort bereits in site.css) — nicht meine Seiten,
 * in work/diag/r6-layout.md an den Konverter uebergeben. */
/* /company/ — Wasserzeichen „lifespin" im Careers-Band.
 * Derselbe Fall wie Fund 2 auf / (site-logo.svg als blasse Grafik), nur an einem anderen
 * Element. Am Element gemessen (1440): Bild 711x201 bei y=1613 auf BEIDEN Seiten,
 * Live `opacity: 0.21`, Dev `1` — der Schriftzug stand auf Dev als kraeftige helle Schrift
 * ueber dem Farbverlauf. scmp vergleicht am Bild nur Datei, Masse und x-Offset,
 * keine Deckkraft; im Bildvergleich sofort zu sehen. */
:where(body.page-id-15307) #brxe-287990 { opacity: .21; }

/* /company/ — die Karten „Newsroom" und „Meet us" ohne ihre Hintergrundgrafik.
 *
 * Von KEINER der vier Messungen erfasst: die Grafik liegt auf Live in einem
 * `::before`-Pseudoelement, und Pseudoelemente stehen in keinem DOM-Durchlauf.
 * Gefunden im Bildvergleich (vis/r6l/co-live.png gegen co-dev.png): auf Live traegt die
 * linke Karte eine Weltkarte, die rechte eine Veranstaltungsgrafik; auf Dev waren beide
 * Karten leer.
 *
 * Am Pseudoelement gemessen (1440, computed):
 *   content "", position absolute, inset -1px, 670x400,
 *   background-image url(global-map.svg) bzw. url(event-graphic.svg),
 *   background-size cover, background-position 50% 50%, no-repeat, opacity 0.8
 * Der Kasten selbst: position relative, border-radius 12px (Live wie Dev identisch).
 * Herkunft ist Elementors „Background Overlay" (im Markup als
 * `data-dce-background-overlay-image-url` sichtbar); convert.py kennt die Gruppe nicht.
 * Beide Dateien liegen auf Dev bereits im Uploads-Ordner (HTTP 200 geprueft).
 * `border-radius: inherit`, damit die Grafik der abgerundeten Kartenecke folgt. */
:where(body.page-id-15307) #brxe-6c6336::before,
:where(body.page-id-15307) #brxe-a8a145::before {
  content: "";
  position: absolute;
  inset: -1px;
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: cover;
  border-radius: inherit;
  opacity: .8;
}

:where(body.page-id-15307) #brxe-6c6336::before {
  background-image: url("/wp-content/uploads/2025/10/global-map.svg");
}

:where(body.page-id-15307) #brxe-a8a145::before {
  background-image: url("/wp-content/uploads/2025/10/event-graphic.svg");
}

:where(body.page-id-14418) #brxe-444f60 { padding-block: 60px; }
:where(body.page-id-14418) #brxe-c7b82a,
:where(body.page-id-14418) #brxe-df0b89,
:where(body.page-id-14418) #brxe-dec97b { padding-block: 20px; }

/* R13 — dieselbe Luecke auf den VIER Seiten, die oben nur als Randnotiz standen.
 *
 * Der Kommentar bei „Trennlinien-Bausteine ohne senkrechten Abstand" nennt sie
 * bereits („/science-and-technology/ 8x 10px, /kit-information-plasma/ 40px"),
 * behoben war aber nur /products-and-services/. Vollstaendig nachgemessen mit
 * `diag/r13div.py 1440` — alle 21 Seiten, Trennlinien ueber die Reihenfolge
 * gepaart (Klassen und IDs sind auf beiden Staenden verschieden, die
 * Reihenfolge ist gleich):
 *
 *   Seite                                Live-Hoehe   Dev-Hoehe   Polster Live
 *   science-and-technology  8 Linien     8x 21        8x 1        10px/10px
 *   kit-information-plasma  1 Linie         81           1         40px/40px
 *   kit-information-serum-professional      81           1         40px/40px
 *   blutentnahme-kit-serum-kit              81           1         40px/40px
 *   products-and-services   4 Linien     121/41/41/41  gleich      (schon behoben)
 *   metabopro-regensburg / -event-de        51           50        25px/25px  (s.u.)
 *   datenschutz, impressum                  50           50        25px/25px  (gleich)
 *
 *   Summe ueber alle Seiten: -402 px, davon 400 px aus diesen vier Seiten.
 *
 * Auf /science-and-technology/ ist das der groesste Einzelposten der 92 px, um
 * die die Seite auf Dev zu kurz ist (Live 10161, Dev 10069) — 8 x 20 = 160 px,
 * die von anderen Stellen teilweise wieder aufgefuellt werden. Genau diese
 * Stauchung erzeugt den aufgelaufenen Versatz, den der Bildvergleich als
 * „mittlerer Versatz +80 px" und acht Baender meldet.
 *
 * Wie oben: der Wert ist eine Einstellung JE BAUSTEIN (10/20/25/40/60 px sind
 * alle belegt) und gehoert deshalb nach convert.py. Bis dahin Einzelfaelle mit
 * Spezifitaet 1,0,0, damit generated.css sie automatisch ueberstimmt, sobald
 * der Konverter sie selbst ausgibt.
 * Seiten-IDs: science-and-technology 12494, kit-information-plasma 16423,
 * kit-information-serum-professional 16425, blutentnahme-kit-serum-kit 17212. */
:where(body.page-id-12494) #brxe-49d67b,
:where(body.page-id-12494) #brxe-3c448b,
:where(body.page-id-12494) #brxe-92bf10,
:where(body.page-id-12494) #brxe-70dad1,
:where(body.page-id-12494) #brxe-f77884,
:where(body.page-id-12494) #brxe-eb414b,
:where(body.page-id-12494) #brxe-482ffc,
:where(body.page-id-12494) #brxe-f129c4 { padding-block: 10px; }

:where(body.page-id-16423) #brxe-80c575,
:where(body.page-id-16425) #brxe-de0c10,
:where(body.page-id-17212) #brxe-de0c10 { padding-block: 40px; }

/* /products-and-services/ @390 — clinical-way.png und self-way.png stehen links
 * statt mittig (R12).
 *
 * Gemessen (`diag/r12-geo.py /products-and-services/ 390`):
 *   Live  x = 95   (Bild 200 px in einem 270 px breiten Kasten ab x=60)
 *   Dev   x = 60
 * Auf Live zentriert Elementor ueber `text-align: center` am
 * .elementor-widget-container, in dem das <img> als inline-block sitzt. In
 * Bricks ist das Bild selbst das Rasterkind; dafuer gibt es in elements.css
 * die allgemeine Regel `main img.brxe-image { margin-inline: auto }`.
 *
 * Die greift hier NICHT — nachgesehen mit CSS.getMatchedStylesForNode,
 * Gewinner ist Bricks' Element-Inline-CSS:
 *   elements.css                      main img.brxe-image  margin-inline: auto   0,1,2
 *   bricks-frontend-inline-inline-css #brxe-36ed63          margin: 0 0 10px 0    1,0,0  <- gewinnt
 * Die Inline-Regel steht NUR bei 390 (bei 1440 taucht sie nicht auf, dort
 * stimmen beide Bilder) — sie ist der mobile Aussenabstand aus den
 * konvertierten Elementeinstellungen.
 *
 * Bewusst kein !important und bewusst nur `margin-inline`: der
 * margin-bottom: 10px des Konverters bleibt unangetastet, ueberschrieben wird
 * allein die waagerechte Aussenkante. `main img#…` ist (1,0,1) und schlaegt
 * (1,0,0) unabhaengig von der Ladereihenfolge. An die Seite gebunden, weil
 * Bricks-Element-IDs nicht seitenweit eindeutig sind. */
@media (max-width: 767px) {
  :where(body.page-id-14418) main img#brxe-36ed63,
  :where(body.page-id-14418) main img#brxe-e10d31 {
    margin-inline: auto;
  }
}

/* Nachtrag 2026-08-21 (Runde 18, Template-Phase).
 *
 * Die Annahme im Kopf dieser Datei — "Header, Footer und Popups werden nativ in Bricks
 * gebaut und duerfen ACSS' Defaults behalten" — ist mit der Template-Phase hinfaellig:
 * Kopf- und Fusszeile kommen aus DEMSELBEN Konverter wie die Seiten und brauchen deshalb
 * dieselbe Ruecksetzung. Ohne sie legte ACSS auf den Kopfabschnitt 90px Block-Padding und
 * 60px Gutter: gemessen auf /about-us/ 1440 war .header_wrapper 269px hoch statt 81px.
 *
 * Bewusst als EIGENE Regeln statt durch Erweitern der Selektoren oben: `main` bleibt damit
 * unangetastet, die 21 Inhaltsseiten aendern sich um kein Byte. `:where()` haelt die
 * Spezifitaet an Tag/Klasse (0,1,1 bzw. 0,1,2) — schlaegt ACSS, verliert gegen Bricks'
 * elementeigene #brxe-xxxxxx-Regeln, genau wie das Original. */
:where(#brx-header, #brx-footer) section.brxe-section {
	padding-block: 0;
	padding-inline: 0;
	align-items: normal;
	gap: normal;
}

:where(#brx-header, #brx-footer) section.brxe-section > div {
	align-items: normal;
	gap: normal;
}

:where(#brx-header, #brx-footer) .ls-con,
:where(#brx-header, #brx-footer) .ls-inner,
:where(#brx-header, #brx-footer) .ls-widget {
	align-items: normal;
}

/* Astras Grundabstaende fuer rohen Inhalt (elements.css: `ul, ol { margin-block: 16px }`)
 * treffen auch die <ul> der Bricks-Menues: Bricks setzt sie zwar auf 0, aber nur in einer
 * `:where(.brxe-nav-menu) .bricks-nav-menu`-Regel mit Spezifitaet 0,0,0 — die verliert.
 * Auf Live gewinnt an derselben Stelle Elementors `.elementor-nav-menu { margin: 0 }`.
 * Folge ohne diese Regel: 32px Mehrhoehe in jedem Menue (Kopfzeile 89 statt 81px). */
.brxe-nav-menu ul,
.brxe-nav-menu ol {
	margin-block: 0;
}

/* Zeilenhoehe der Menues: Elementor setzt sie ausdruecklich auf `normal`, Bricks laesst
 * sie erben.
 *   Live  `.elementor-nav-menu, .elementor-nav-menu li, .elementor-nav-menu ul
 *          { line-height: normal }`      -> <li> 26px hoch (= Hoehe des inline-block <a>)
 *   Dev   erbt ueber `p, li { line-height: var(--text-line-height) }` die 1,7 des Body
 *                                        -> Zeilenkasten 28px, <li> 28px hoch
 * Gemessen (1440, /about-us/, Fusszeilenmenue "Discover"): fuenf Punkte je 2px zu hoch,
 * das Menue 140 statt 130px. Ueber die drei Fusszeilenmenues und die Kopfzeile summiert
 * sich das; die Fusszeile stand dadurch 14px zu hoch (621 statt 607).
 * Der <a> darin bleibt bei 26px (line-height 20px + 2x3px Polster) — der Unterschied
 * liegt allein im Zeilenkasten des <li>, nicht am Link.
 */
.brxe-nav-menu,
.brxe-nav-menu li,
.brxe-nav-menu ul {
	line-height: normal;
}

/* ---------------------------------------------------------------------------
   R45 — 404-Seite: Astras Abstand unter dem Inhalt.

   Astra bringt fuer die 404-Seite eine eigene Regel mit, die mit dem Theme
   weggefallen ist:
       @media (min-width:922px){ .error404.ast-separate-container #primary
                                 { margin-bottom: 4em } }
   Am Live-Knoten per CDP nachgewiesen, font-size dort 16px -> 64 px.
   Der Inhalt selbst ist auf beiden Staenden exakt 553 px hoch; die 64 px waren
   die gesamte Differenz. Dev hat Astras `#primary`-Wrapper nicht — der Abstand
   gehoert deshalb an Bricks' Inhaltswurzel.

   Die Schwelle 922 px ist ASTRAS Haltepunkt, nicht einer aus diesem Projekt;
   sie ist woertlich uebernommen, damit die schmalen Breiten wie auf Live
   ohne diesen Abstand rendern.
   --------------------------------------------------------------------------- */
@media (min-width: 922px) {
  body.error404 main#brx-content { margin-bottom: 4em; }
}
/* Unterhalb der Schwelle druckt Astra denselben Abstand als POLSTER aus, oben
   UND unten, und der Aussenabstand faellt weg:
       .ast-separate-container #primary { padding: 4em 0 }
   Gemessen ueber vier Breiten (diag/r45-404c.py): 1440 -> padding 0 / margin 64,
   900, 768 und 390 -> padding 58,368 je Seite / margin 0. Die krummen 58,368 px
   sind 4em bei Astras reduzierter Wurzelschrift (html 91,2 % -> 14,592 px);
   Dev traegt an diesem Knoten dieselbe Schriftgroesse, deshalb `em` statt eines
   abgelesenen Pixelwerts. */
@media (max-width: 921px) {
  body.error404 main#brx-content { padding: 4em 0; }
}
/* Und die Flaeche, die dieser Abstand freilegt: Astras Seitenhintergrund
   `.ast-separate-container { background-color: #f5f5f5 }`. Auf Live scheint er
   in der Luecke zwischen Inhalt und Fusszeile durch, auf Dev war sie weiss
   (gemessen: body-Hintergrund live rgb(245,245,245), dev rgb(255,255,255)).
   BEWUSST nur auf der 404-Seite: dort ist es die einzige Stelle, an der die
   Flaeche ueberhaupt sichtbar wird — auf allen uebrigen Seiten deckt der Inhalt
   sie ab, und eine site-weite Aenderung waere ein Eingriff ohne Messgrund. */
body.error404 { background-color: #f5f5f5; }
body.error404 main#brx-content { background-color: #fff; }

/* ---------------------------------------------------------------------------
   R60 — Stellen-Einzelseite: Astras Polster am Inhaltsrahmen.

   Gleiche Familie wie der 404-Block oben, andere Route und andere Schwelle.
   Astra bringt fuer seinen "separate container" mit:
       .ast-separate-container #primary { padding: 4em 0 }
   Am Live-Knoten per CDP nachgewiesen (Astra, ueber die LiteSpeed-Kombidatei
   ausgeliefert). Dev hat Astras `#primary`-Wrapper nicht — der Abstand gehoert
   deshalb an Bricks' Inhaltswurzel.

   Die Schwelle ist ASTRAS, nicht eine aus diesem Projekt, und ueber sechs
   Breiten abgetastet (diag/r60-job-em.py, Polster an #primary auf LIVE):
       1900 / 1440 -> 0 px      (dort auch kein Aussenabstand: 0/0 gemessen)
       992 / 960   -> 64 px
       768 / 390   -> 58,368 px
   Deshalb `max-width: 992px`. Die zwei Stufen 64 / 58,368 kommen mit EINEM
   Wert, weil Astra unterhalb 922 px die Wurzelschrift auf 91,2 % zieht und
   `4em` mitzieht. Am Zielknoten nachgemessen (diag/r60-job-em2.py): die
   Schriftgroesse des Knotens ist auf BEIDEN Staenden 16 bzw. 14,592 px, `4em`
   ergibt also beidseitig denselben Wert. Ein abgelesener Pixelwert waere hier
   ein Schuldschein und wuerde die 922er-Stufe verlieren.
   (Achtung: Devs WURZEL-Schriftgroesse ist 10 px — `4rem` waere falsch.)

   Bestand vor dem Einbau ausgezaehlt (diag/r60-primary-bestand.log, alle 28
   Routen bei 768): genau ZWEI Routen tragen dieses Polster auf Live, die
   404-Seite (oben schon abgebildet) und diese. Die uebrigen 26 haben 0 px.
   Deshalb auf `body.single-job-offer` eingeschraenkt.
   --------------------------------------------------------------------------- */
@media (max-width: 992px) {
  body.single-job-offer main#brx-content { padding: 4em 0; }
}

/* ---------------------------------------------------------------------------
   Fall 260: Borlabs' Zustimmungskasten traegt `height: 100%`. In einem Bricks-
   Element (`display:flex; flex-wrap:wrap`) mit unbestimmter Hoehe fuehrt das zu
   einer Groessenbestimmung, die den Kasten auf ein Vielfaches aufblaeht.
   Elementors Gegenstueck ist ein schlichter `display:block`-Wrapper — dort
   loest `height:100%` gegen einen `height:auto`-Vorfahren regelkonform zu
   `auto` auf, der Kasten bekommt seine Inhaltshoehe.

   Der Kasten erscheint NUR ohne erteilte Zustimmung. Der Bildvergleich misst
   mit Zustimmung und kann diese Klasse von Fehlern deshalb prinzipiell nicht
   melden — gefunden ueber einen eigenen Bestandsscan (diag/r69-bestand.py).

   Gemessen bei 390 px, ohne Zustimmung, Live gegen Dev (diag/r69-fix2.py):
       default-Blocker      LIVE  207,0    DEV vorher 2905,5
       google-maps-Blocker  LIVE  326,4    DEV vorher  674,5

   Wirkungslos und deshalb NICHT eingebaut (jeweils exakt 0 px Aenderung
   gemessen, mit greifendem Selektor und !important):
       height:auto am Blocker · min-height:0 · flex-basis · align-items
   Es wirkt ausschliesslich `flex-wrap` am ELTERNTEIL.

   Der Selektor trifft ueber `> ` genau den direkten Elternknoten, nicht die
   ganze Vorfahrenkette. Bewusst generisch statt auf die Element-IDs
   (#brxe-b12abe / #brxe-0fc6cd): der Mechanismus haengt an Borlabs, nicht an
   diesen zwei Seiten, und ein Blocker kann bei jedem neuen Einbettungscode
   entstehen. `flex-wrap` ist an einem Container mit einem einzigen Kind
   wirkungslos — der Eingriff kann dort also nichts kaputt machen; die
   Gegenprobe MIT Zustimmung (dann steht statt des Kastens das echte iframe)
   ist gemessen und unveraendert.
   NACHTRAG: die Regel braucht eine ID-Stufe. Bricks schreibt die vom Konverter
   uebernommene Container-Einstellung als `#brxe-<eid> { flex-wrap: wrap }` (1-0-0)
   und schlaegt damit jeden Klassenselektor. Am Elternknoten per CDP
   `CSS.getMatchedStylesForNode` nachgewiesen (diag/r69-cascade.py) — die Regel stand
   sauber im Stylesheet und traf den richtigen Knoten, verlor aber die Kaskade.
   Gehoben ueber den im Projekt eingefuehrten `:is(#brx-body,html)`-Vorspann
   (Fall 237), nicht ueber `!important`.
   --------------------------------------------------------------------------- */
:is(#brx-body, html) *:has(> .brlbs-cmpnt-content-blocker) { flex-wrap: nowrap; }
