/* Basis-Typografie der HTML-Elemente.
 *
 * Diese Werte sind NICHT aus dem Elementor-Kit abgeleitet, sondern am 2026-08-19 im Browser
 * auf lifespin.health gemessen (computed styles, sechs Viewports, work/measure-elements.py,
 * Rohdaten in work/elements-measured.json). Das Kit setzt fuer h1-h6 nur Familie und
 * Gewicht; die Groessen kommen aus dem Astra-Stack und waeren aus keiner Konfigurationsdatei
 * ablesbar gewesen.
 *
 * Gemessen wird auf /datenschutz_apotheke/ — die einzige Seite, deren Inhalt komplett aus
 * rohem HTML in EINEM text-editor-Widget besteht, also ohne Elementor-Overrides. Auf
 * /datenschutz/ und /impressum/ liegen widget-eigene Ueberschriftengroessen (h2 22px,
 * h3 18px) darueber; die gehoeren an das jeweilige Element, nicht in diese Basis.
 *
 * Ohne diesen Block greift die ACSS-Ueberschriftenskala und macht aus einem h3 74 px statt 24.
 * Betrifft jeden Text, der als rohes HTML im Inhalt steht (Impressum, Datenschutz, …).
 *
 * Reihenfolge: nach ACSS laden, sonst gewinnt ACSS.
 */

body {
  font-family: 'Public Sans', sans-serif;
  font-weight: 400;
  font-size: 16px;
  /* Als Variable, weil derselbe Wert weiter unten als Knopf-Strut gebraucht wird
     (siehe `.brxe-button { min-height }`). Ein zweites Mal hingeschriebene 28
     waere ein Handwert; so ist es derselbe geportete Wert. */
  --ls-strut: 28px;
  line-height: var(--ls-strut);
  color: #161616;
}

h1, h2, h3, h4, h5, h6 {
  font-family: 'Exo', sans-serif;
  color: #000000;
  margin-top: 0;
  margin-bottom: 20px;
}

/* R59 (Fall 245) — Ueberschriften in FREMDEM Elementor-Markup, das den Abbau
 * ueberlebt hat. The Events Calendar speichert unter `tribe_events_before_html`
 * einen HTML-Baustein, der als Option in der Datenbank liegt und deshalb
 * unveraendert weiterrendert, obwohl Elementor deaktiviert ist:
 *   <div class="elementor-widget-container event-btitle">
 *     <h1 class="elementor-heading-title elementor-size-default">Meet us</h1>
 *
 * Auf Live setzt Elementors eigenes Stylesheet dafuer
 * `.elementor-heading-title { margin-bottom: 0 }`. Faellt das Plugin weg, greift
 * stattdessen die h1-h6-Regel darueber mit ihren 20px. Weil `.tribe-events-before-html`
 * keinen eigenen Block-Formatting-Context aufspannt, kollabiert dieser Aussenabstand
 * nach aussen und schiebt den GESAMTEN nachfolgenden Event-Inhalt nach unten —
 * gemessen /event/medtech-world-europe/ @1440: Live gegen Dev 20px Versatz ueber
 * den kompletten Inhaltsblock, @390 rund 7px (dort daempft eine abweichende
 * Zeilenhoehe desselben H1 den Effekt teilweise).
 *
 * Der Bestand ist klein und vollstaendig ausgezaehlt (21 Seiten + Detailrouten,
 * `grep -o` auf das gerenderte Dev-HTML): die Klasse kommt auf genau zwei Routen
 * vor, /event/<slug>/ (1x) und /events/ (2x), beide aus derselben TEC-Option.
 * Uebernommen wird deshalb Elementors Regel im Wortlaut statt eines auf
 * `.tribe-events-before-html` verengten Sonderfalls: sie ist die treue Portierung
 * und traegt auch, wenn dasselbe Fremdmarkup an einer weiteren Stelle auftaucht. */
.elementor-heading-title {
  margin-bottom: 0;
  /* Die ZEILENHOEHE dieser Ueberschrift steht bewusst nicht hier, sondern in
   * `events.css` (Block R45/R59): dort liegt bereits eine Regel mit derselben
   * Spezifitaet, und `events.css` laedt spaeter — eine zweite Deklaration an
   * dieser Stelle waere toter Code. */
}

/* R38 — Zeilenhoehe als `em`, NICHT einheitenlos. Live (Astra `h1..h4`, Kit `h2/h3`)
 * schreibt ueberall `1.4em` bzw. `1.3em`. Beide Schreibweisen ergeben denselben
 * computed value (getComputedStyle meldet auf beiden Staenden `22.4px`), sie runden
 * aber verschieden auf Layouteinheiten: Live's h4 ist 22.40625 px hoch, mit
 * einheitenlosem 1.4 sind es 22.390625 — eine einzige Layouteinheit (1/64 px).
 * Auf /privacy-statement/ mit rund 43 Ueberschriften summiert sich das auf 0,64 px
 * und erzeugte ein Band an der Fusszeilenkante. Gemessen per CDP
 * `CSS.getMatchedStylesForNode` (diag/r38-whylh.py), nicht aus dem computed value —
 * der ist auf beiden Staenden identisch und haette nichts gezeigt. */
h1 { font-size: 45px; line-height: 1.4em; font-weight: 400; }
h2 { font-size: 33px; line-height: 1.4em; font-weight: 400; }
h3 { font-size: 24px; line-height: 1.4em; font-weight: 500; }
/* h4-h6 kommen im rohen Inhalt nicht vor und sind daher nicht am Live-Stand messbar.
 * Werte aus dem Elementor-Kit, beim ersten Vorkommen gegen Live pruefen. */
h4 { font-size: 20px; line-height: 1.4em; font-weight: 400; }
h5 { font-size: 20px; line-height: 1.4em; font-weight: 400; }
h6 { font-size: 15px; line-height: 1.4em; font-weight: 500; }

/* Fliesstext erbt die Groesse vom body und haelt das Verhaeltnis 1.4 — NICHT 16px fest.
 * Astra verkleinert die Basis ab 880px auf 91.2% (14.592px), und der Absatz geht mit.
 * Mit festen 16px stand /privacy-statement/ auf dem Tablet durchgaengig zu gross
 * (219 Abweichungen), auf dem Desktop war es nicht zu sehen, weil beide Werte dort 16px
 * sind. Gemessen auf /imprint/ bei 1440/880/768/390 am 2026-08-19. */
p  { font-size: 1em; line-height: inherit; font-weight: inherit; margin-top: 0; margin-bottom: 20px; }
ul, ol { font-size: 1em; line-height: inherit; font-weight: inherit; margin-top: 16px; margin-bottom: 16px; }
li { font-size: 1em; line-height: inherit; font-weight: inherit; margin-top: 0; margin-bottom: 0; }
a  { color: #870A09; font-weight: 400; }

/* Bis 1024px sind alle Werte identisch mit Desktop — Astra skaliert erst ab 880px. */

@media (max-width: 880px) {
  body { font-size: 14.592px; }
  h1 { font-size: 40px; }
  h2 { font-size: 25px; }
  h3 { font-size: 20px; }
  h4 { font-size: 18.24px; }
}

/* Unter 767px hebt das Kit h2 und h3 wieder an — kein Tippfehler, so steht es live.
 *
 * h4 und die Zeilenhoehe von h1 haben hier bis R39 GEFEHLT (Fall 193). Solange
 * Elementor lief, lieferte `.elementor-kit-9 h1..h4` die Werte auf Dev gratis mit;
 * mit dem Abbau fielen sie weg. Vollstaendig aus dem Kit ausgelesen (alle Regeln
 * .elementor-kit-9 h1..h6 samt Media Queries):
 *   @media(max-width:767px){ h1 33px/1.4em · h2 28px/1.3em · h3 24px/1.3em · h4 20px/1.2em }
 *
 * Warum h4 beim Aufmass in Phase 3 durchgerutscht ist: die Kundenregel
 * `.privacy-statement h4 { font-size: 1em }` ist spezifischer und macht daraus auf
 * der Datenschutzseite 14,592 px — dort sah h4 unauffaellig aus. Auf /imprint/,
 * wo die Regel nicht gilt, standen 18,24 gegen Lives 20 px.
 * Folge des Fehlens: /privacy-statement/ @390 war 186 px hoeher als Live
 * (28 H4 mit 1.4 statt 1.2 Zeilenhoehe, Summe exakt +185,85).                      */
@media (max-width: 767px) {
  h1 { font-size: 33px; line-height: 1.4em; }
  h2 { font-size: 28px; line-height: 1.3em; }
  h3 { font-size: 24px; line-height: 1.3em; }
  h4 { font-size: 20px; line-height: 1.2em; }
}

/* Grundstil des Text-Widgets aus dem Elementor-Kit (system_typography "Text").
 *
 * Elementor gibt ihn JEDEM text-editor-Widget mit, auch wenn im Widget selbst keine
 * Typografie gesetzt ist — die Regel steht als `.elementor-widget-text-editor
 * { font-size: var(--e-global-typography-text-font-size) }` in Elementors globalem CSS.
 * Im Widget-JSON ist davon nichts zu sehen, genau wie beim globalen Button-Stil.
 * Auf dem Desktop faellt das Fehlen nicht auf (16px = Basisgroesse), ab 880px schon:
 * dort verkleinert Astra die Basis auf 14.592px, der Text-Baustein bleibt aber 16px.
 * Gilt fuer alle Bausteine, die Elementor diese Typografie mitgibt — Text, Liste,
 * Akkordeon, Zeitstrahl. Rohes HTML (Elementors html-Widget, etwa auf /imprint/ und
 * /privacy-statement/) bekommt sie NICHT und erbt die verkleinerte Basis; das ist der
 * Grund, warum die Absatzregel weiter unten mit 1em arbeitet.
 * Ein benannter Kit-Style (.txt-*) laedt spaeter und ueberstimmt diesen Grundstil —
 * genau die Reihenfolge, die Elementor auch hat.
 */
/* R17 — die Handliste fuer den Abstand des LETZTEN Absatzes ist ERSATZLOS weg.
 *
 * Was hier bis R16 stand: die Grundregel
 *     main .brxe-text > p:last-child { margin-bottom: 0 }
 * und darunter VIER von Hand gepflegte Gegenausnahmen mit zusammen 28 Element-IDs
 * (R6, R11, R13, R16), die den Abstand fuer einzelne Bausteine wieder auf 20px
 * setzten. Jede Runde kamen welche dazu.
 *
 * Die Unterscheidung, um die es geht, steckt im Elementor-QUELLTEXT des Bausteins:
 * steht dort roher Text, rendert Elementor ihn ohne <p> und ohne Abstand; steht dort
 * ein Absatz, bleibt der Abstand. Genau diese Unterscheidung bildet der Konverter
 * seit R11 im MARKUP ab (`Converter.kein_wpautop`, work/convert.py Z. 762 ff.):
 * rohen Inhalt legt er in einen `<div>`-Mantel, damit Bricks' `wpautop()` keinen
 * Absatz erfindet; Inhalt mit Block-Tag laesst er unangetastet.
 *
 * Erhoben ueber ALLE 21 Seiten und die drei Vorlagen (work/diag/r17a-textscan.py,
 * SQL ueber `_elementor_data`, oberste Ebene in Block- und Rohtext-Laeufe zerlegt):
 *     64 Bausteine nur Block  |  64 Bausteine nur Rohtext  |  1 leer  |  0 gemischt
 * Es gibt also KEINEN Baustein, in dem beide Formen zusammentreffen — der
 * `<div>`-Mantel des Konverters deckt den Rohtextfall vollstaendig ab.
 *
 * Damit war die Grundregel nur noch schaedlich: sie traf ausschliesslich Bausteine,
 * deren <p> Live ebenfalls hat, und nahm ihnen die 20px. Die Ausnahmeliste hat das
 * fuer 28 bekannte IDs wieder repariert, fuer die uebrigen nicht.
 *
 * Gemessen am gerenderten Stand, `work/diag/r17a-mb.py <pfad> 1440`: je Dev-
 * `.brxe-text` der computed `margin-bottom` des letzten Kindes, gegen das TIEFSTE
 * Live-Element mit demselben normalisierten Text. Ueber alle 21 Seiten,
 * 281 Dev-Textbausteine:
 *     vorher (Grundregel + 28er Liste): 277 gleich, 2 abweichend, 2 ohne Gegenpart
 *     nachher (beides entfernt):        279 gleich, 0 abweichend, 2 ohne Gegenpart
 * Die zwei behobenen Faelle sind `#brxe-630f09` (/investor-relations/) und
 * `#brxe-6ebcba` (/datenschutz/) — Live 20px, Dev 0px, in keiner Handliste.
 * Die zwei „ohne Gegenpart" sind Paarungsluecken des Messwerkzeugs, keine Funde:
 * `#brxe-708073` und `#brxe-adef94` haben auf Live einen minimal anderen Text.
 * Rohdaten: work/diag/r17a/mb-vor/, work/diag/r17a/mb-nach/.
 *
 * Bausteine, die Bricks ein <p> gibt, das Live NICHT hat, gibt es nach dieser
 * Messung keinen einzigen. Wo der Konverter Text OHNE Mantel ablegt
 * (Icon-Box- und Bild-Box-Beschreibung, `raw_text`), setzt er selbst
 * `#brxe-<id> > p { margin: 0 }` — eine ID-Regel, die von der geloeschten
 * Klassenregel ohnehin nie abhing.
 */

.brxe-text,
.brxe-text-basic,
.brxe-list,
.brxe-accordion,
.ls-timeline__text {
  font-family: 'Public Sans', sans-serif;
  font-size: 16px;
  font-weight: 300;
  line-height: 24px;
}

/* Globaler Button-Stil aus dem Elementor-Kit (button_* im Kit, s.
   work/design-system-elementor.json). Er stand bisher nirgends: Elementor gibt ihn
   pauschal an jedes Button-Widget, in den einzelnen Widgets steht dazu KEINE Einstellung.
   Ohne diesen Block erben Bricks-Buttons die ACSS-Vorgaben und rendern 16px statt 18px.
   Bewusst OHNE Tag im Selektor (kein a.bricks-button): das waere spezifischer als die
   benannten Kit-Styles .txt-* und wuerde sie ueberstimmen — Buttons mit dem Stil
   "Button Text" (16px) sind dann faelschlich 18px gross. */
/* letter-spacing: Bricks gibt jedem Knopf ueber `.bricks-button { letter-spacing: .5px }`
   (frontend-layer.min.css, @layer bricks) eine Sperrung mit, die Elementor nicht hat —
   auf Live steht an jedem Knopftext `letter-spacing: normal` (gemessen). Die 0.5px je
   Zeichen machen jeden Knopf sichtbar breiter: "Explore the science" 141 -> 150.5,
   "Sample Report" 126 -> 132.5, "Explore products & services" 201 -> 215. */
.brxe-button, .bricks-button {
  font-family: 'Exo', sans-serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 24px;
  letter-spacing: normal;
  color: #FFFFFF;
  background-color: #870A09;
  border: 1px solid #870A09;
  border-radius: 3px;
  padding: 12px 25px;
  /* Fall 154 — Elementors Knopf-Rahmen ist ein BLOCK, sein <a> ein inline-block darin.
     Die Zeilenbox dieses Blocks ist mindestens so hoch wie der Strut, also wie die
     geerbte Zeilenhoehe. Ein Bricks-Knopf IST der <a> und hat keine Zeilenbox um sich;
     ohne diese Untergrenze ist er genau so hoch wie seine Beschriftung.
     Bestand gemessen (work/diag/r35-strutall.py): 537 Knopf-Rahmen ueber 21 Seiten x
     3 Breiten, AUSNAHMSLOS line-height 28px — der Body-Wert, weil Elementors
     Typografie-Regler des Knopfes den <a> treffen und nie den Rahmen. Die Untergrenze
     ist damit site-weit derselbe Wert und keine Einzelfallmessung.
     Wirksam an genau 4 Knoepfen (alle ohne eigenes Polster); alle uebrigen sind
     gepolstert und ueberragen den Strut, dort ist die Angabe wirkungslos.
     align-items: Bricks' Knopf ist display:flex mit `normal` = stretch, der Zusatzraum
     landet sonst vollstaendig UNTER der Beschriftung. Live verteilt ihn ueber die
     Grundlinie (gemessen 3/3 bzw. 5/3.41); `center` ist die naechste Abbildung und bei
     gepolsterten Knoepfen wirkungslos.
     NICHT abgedeckt: /metabopro-regensburg/ @1440, zweizeilige Beschriftung 39,19 px in
     einem 44,19 px hohen Rahmen. Dort liegt der Knopf UEBER dem Strut, die 5 px sind
     die Unterlaenge unter der Grundlinie eines inline-block. Das ist ohne echten
     Rahmenknoten nicht abbildbar (s. work/diag/r32-strut.md). */
  min-height: var(--ls-strut);
  align-items: center;
}

.brxe-button:hover, .bricks-button:hover {
  color: #FFFFFF;
  background-color: #320303;
  border-color: #320303;
}

/* color: Astra faerbt Formularbeschriftungen ueber `label, legend { color:
   var(--ast-global-color-2) }` (inline im astra-theme-css-inline-css). Der aufgeloeste
   Wert ist #1E293B — auf /contact/ gemessen, nicht der Fallback #111827 aus der Regel.
   Ohne die Angabe erben die Labels die Body-Farbe #161616. */
label, legend { line-height: 20px; font-weight: 500; color: #1E293B; }
/* letter-spacing: Bricks sperrt jede Formularbeschriftung ueber
   `:where(.brxe-form) .label, :where(.brxe-form) label { letter-spacing: .4px }`
   (frontend-layer.min.css, @layer bricks — per CDP `CSS.getMatchedStylesForNode` an
   „First name:" auf /contact/ als Verursacher nachgewiesen). Auf Live steht an allen acht
   Beschriftungen `letter-spacing: normal` (gemessen). 0,4px je Zeichen laufen ueber die
   Beschriftung sichtbar auf; keine der Text-/Bild-/Ikonenmessungen sieht das, bcmp meldete
   es als 8x `letter-sp: normal -> 0.4px`. Dies ist der LIVE-Wert, keine Breitenkorrektur. */
.brxe-form label, .brxe-form .label { text-transform: none; font-weight: inherit; letter-spacing: normal; }
/* Gegenausnahme zur Astra-Regel eine Zeile hoeher. Auf /contact/ gemessen: die SICHTBAREN
   Feldbeschriftungen tragen auf Live rgb(22,22,22) — Elementor faerbt sie ueber
   `.elementor-field-label` und schlaegt damit Astras `label, legend`. Nur der Honeypot-
   Beschriftung („Alternative:", in der 1x1-Box .altEmail_container) bleibt Astras #1E293B.
   Ohne diese Zeile faerbt die Astra-Regel alle sechs sichtbaren Labels falsch:
   gemessen 33 -> 36 Abweichungen auf /contact/, also 6 kaputt fuer 1 unsichtbare Heilung. */
.brxe-form .form-group > label { color: #161616; }
#brx-content p a { font-weight: 400; }

/* Globaler Ueberschriften-Baustein aus dem Elementor-Kit. Elementor schreibt
   `.elementor-widget-heading .elementor-heading-title { color: var(--e-global-color-primary) }`
   (= #000000) und gibt ihn JEDEM heading-Widget mit, unabhaengig vom gewaehlten Tag.
   Im Widget-JSON steht davon nichts, genau wie beim globalen Button-Stil oben.
   Die h1-h6-Regel weiter oben deckt nur die echten Ueberschriften ab; ein
   heading-Element mit Tag p (die Jahreszahlen in den Publikations- und Newslisten auf
   /science-and-technology/ und /newsroom/, 20 Faelle) faellt sonst auf die Body-Farbe
   #161616 zurueck. Spezifitaet 0,1,0 und Ladeposition VOR typography.css, site.css und
   generated.css: ueberstimmt also weder einen benannten Kit-Style noch eine am Element
   gesetzte Farbe. */
.brxe-heading {
  color: #000000;
}

/* Ueberschriften-WIDGETS tragen keinen eigenen Abstand nach unten.
 *
 * Elementor setzt `.elementor-heading-title { margin: 0 }` — der Abstand zwischen
 * Ueberschrift und Folgeinhalt kommt dort aus dem Container (gap), nicht aus dem Element.
 * Die h1-h6-Regel weiter oben mit `margin-bottom: 20px` ist am ROHEN HTML gemessen
 * (Impressum, Datenschutz), wo sie richtig ist — auf ein Bricks-heading-Element angewandt
 * addiert sie dagegen 20px, die es auf Live nicht gibt.
 * Gemessen auf /imprint/: weisse Karte 1215 statt 1195 px hoch, bei identischem Text und
 * identischem Innenabstand; die 20px liefen als Hoehenabweichung bis auf die Seitenhoehe
 * durch (2094 statt 2074).
 * Gilt bewusst nur fuer .brxe-heading — Ueberschriften INNERHALB eines Text- oder
 * html-Elements sind rohes HTML und behalten ihren Abstand.
 *
 * Die Farbregel weiter oben bleibt bewusst auf 0,1,0: sie DARF von einem benannten
 * Kit-Style ueberstimmt werden. */
.brxe-heading {
  margin-bottom: 0;
}

/* NACHTRAG r6 — Ueberschriften-Baustein mit Tag `p`.
 *
 * Auf / ist die Einleitung „Understanding how the human metabolism works …" ein
 * heading-Baustein, der als `<p id="brxe-aa34d0" class="brxe-heading">` gerendert wird.
 * Die Regel eine Zeile hoeher (0,1,0) griff dort NICHT. Verursacher per CDP
 * `CSS.getMatchedStylesForNode` eindeutig: `.elementor-kit-9 p { margin-block-end: 20px }`
 * aus der portierten Kit-Datei — Spezifitaet 0,1,1 und spaeter im Ladeweg.
 * Gemessen (1440): Baustein Live 378 / Dev 398, Abschnitt „Metabolomics and Human Health"
 * Live 771 / Dev 791; die 20px liefen bis auf die Seitenhoehe durch.
 *
 * Bewusst `main p.brxe-heading` (0,1,2) und NICHT die Regel oben angehoben:
 * mit `body main .brxe-heading` (ebenfalls 0,1,2) schlug sie auch
 * `.ls-posts__title { margin: 0 0 5px }` aus loops.css (0,1,0) und machte jede
 * News-Karte auf / 5px zu flach — gemessen als Sprung von 6 auf 10 Flaechenmeldungen.
 * Dieser Selektor fasst nur den Fall, um den es geht: Ueberschrift mit Tag p.
 * Fuer echten Fliesstext bleibt die Kit-Regel richtig und unangetastet. */
main p.brxe-heading {
  margin-bottom: 0;
}

/* Kontaktformular /contact/. Der Bricks-Nachbau erbt die ACSS-/Bricks-Standardoptik;
   am Live-Stand gemessen (1440, .elementor-form):
     6 Felder + Select + Textarea  background #F4F4F4 (Dev: weiss bzw. Select transparent)
     Textarea                      155px hoch          (Dev: 90px)
     Absendeknopf                  966x50 = volle Breite, #870A09 auf Weiss
                                   (Dev: 179x50 schwarz — schwarz kommt aus dem
                                   Elementor-Kit `.elementor-kit-9 button` =
                                   --e-global-color-primary, Spezifitaet 0,1,1, das
                                   schlaegt .brxe-button aus elements.css; die
                                   Selektoren hier liegen mit 0,3,1 darueber)
   Der Honeypot #alt_s ist bewusst NICHT gepatcht: sein Container .altEmail_container
   ist auf Live UND Dev identisch 1x1 mit overflow:hidden — er ist auf beiden Seiten
   geclippt, es gibt keinen Unterschied zu beheben. */
/* Bewusst ueber .form-group eingegrenzt: das Honeypot-Feld #alt_s ist ebenfalls ein
   input[type=text], liegt aber in .altEmail_container und ist auf Live weiss. Ohne die
   Eingrenzung faerbt die Regel es mit und erzeugt ein FEHLT/EXTRA-Paar (gemessen). */
.brxe-form.cnt-form .form-group input[type="text"],
.brxe-form.cnt-form .form-group input[type="email"],
.brxe-form.cnt-form .form-group input[type="tel"],
.brxe-form.cnt-form .form-group select,
.brxe-form.cnt-form .form-group textarea {
  /* R54 (Fall 236): Flaeche und Rahmen standen hier als Handwert
     (`background-color:#f4f4f4; border:none`). Beides sind Regler am Formular-Widget
     (field_background_color, field_border_width, field_border_color) und kommen jetzt
     aus convert.py. Der Handwert war beim Rahmen schlicht falsch: Live traegt an jedem
     Feld eine 1px-Linie unten in #8D8D8D.

     Was hier BLEIBT, ist Astras Feldschatten: er steht in keiner Einstellung, sondern
     in Astras dynamischem Customizer-CSS (`astra-theme-css-inline-css`, per CDP am
     Live-Stand nachgewiesen) und faellt mit dem Theme weg. Gemessen an allen sechs
     Feldern UND am Absendeknopf: rgba(0,0,0,.05) 0 1px 2px 0. */
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

/* R59 (Fall 248) — der waagerechte Innenabstand der Felder. Er steht in KEINER
 * Elementor-Einstellung: `field_text_padding` und `input_size` sind am Widget
 * (post 10771, a7e2961) beide ungesetzt, nachgesehen in `_elementor_data`. Der
 * Wert entsteht erst im Browser, und zwar aus ZWEI verschiedenen Fremdquellen,
 * deren Rangfolge je Feldtyp KIPPT:
 *
 *   Astra (Customizer-Inline-CSS, `astra-theme-css-inline-css`)
 *       input[type="text"], … , select, textarea { padding: 12px 16px }
 *   Elementor Pro (frontend.min.css)
 *       .elementor-field-textual { padding: 5px 14px }
 *
 * Astras Selektor trifft die Eingabefelder ueber `input[type="text"]` (0,1,1) und
 * schlaegt damit Elementors Klasse (0,1,0) — dort gewinnen 16px. Bei Select und
 * Textarea trifft derselbe Astra-Block nur ueber den nackten Tagnamen (0,0,1) und
 * VERLIERT gegen dieselbe Elementor-Klasse — dort gewinnen 14px. Am Select kommt
 * `.elementor-field-group .elementor-select-wrapper select { padding-inline-end:
 * 20px }` hinzu, das nur die rechte Seite fuer den Pfeil aufweitet.
 *
 * Beide Quellen fallen mit dem Abbau weg, Bricks setzt stattdessen pauschal
 * `input, select, textarea { padding: 0 12px }` (frontend.min.css). Gemessen
 * /contact/ @1440 und @390, an allen sechs Feldern, zusaetzlich am tatsaechlich
 * gerenderten Textbeginn gegengeprueft (Feld leer gegen Feld mit Testtext):
 *   Eingabefeld  Live 16 / 16   Dev 12 / 12
 *   Select       Live 14 / 20   Dev 12 / 12
 *   Textarea     Live 14 / 14   Dev 12 / 12
 *
 * Uebernommen wird nur die WAAGERECHTE Achse — das ist der gemessene Befund. Die
 * Feldhoehen decken sich bereits, und Astras senkrechte 12px hier mitzuschreiben
 * wuerde sie ohne Not verschieben. Das Suchfeld im Kopf und die Zustimmungs-
 * kaestchen sind nicht betroffen (auf beiden Staenden gleich, mitgemessen). */
.brxe-form.cnt-form .form-group input[type="text"],
.brxe-form.cnt-form .form-group input[type="email"],
.brxe-form.cnt-form .form-group input[type="tel"] {
  padding-left: 16px;
  padding-right: 16px;
}

.brxe-form.cnt-form .form-group select {
  padding-left: 14px;
  padding-right: 20px;
}

.brxe-form.cnt-form .form-group textarea {
  padding-left: 14px;
  padding-right: 14px;
}

/* Derselbe Astra-Schatten am Absendeknopf (Live gemessen, identischer Wert). */
.brxe-form.cnt-form button.bricks-button {
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

/* Live hat am Select KEINEN Pfeil: appearance:none UND background-image:none (gemessen).
   Bricks zeichnet stattdessen einen CSS-Pfeil aus zwei linearen Verlaeufen. */
.brxe-form.cnt-form .form-group select {
  background-image: none;
}

/* Feldraster des Kontaktformulars. Elementor legt die Felder in einen Rahmen mit
 * negativem Aussenabstand und gibt jeder Feldgruppe 12px Innenabstand links und rechts
 * (`.elementor-form-fields-wrapper{margin:0 -12px}`, `.elementor-field-group{padding:0 12px}`).
 * Zwischen zwei Feldern einer Zeile stehen dadurch 24px, und die Felder selbst sind
 * schmaler als ihre Gruppe. Am Live-Stand gemessen (1440):
 *   Gruppe 1  18..513 (495 breit),  Feld  30..501  (471)
 *   Gruppe 2  513..1008 (495),      Feld  525..996 (471)
 * Der Nachbau hat den Rahmen nicht: Gruppen 30..513 und 513..996, Felder volle 483 breit,
 * Luecke 0. scmp meldete das als `BREITE 471 -> 483` (4x) und `X 525 -> 513` (4x).
 * Bewusst KEINE feste Feldbreite, sondern derselbe Innenabstand wie bei Elementor —
 * die 50%-Spaltenaufteilung bleibt unangetastet.
 *
 * Senkrecht ebenso: Live traegt die Gruppe 25px Aussenabstand nach unten und die
 * Beschriftung 8px Innenabstand nach unten (Zeilenabstand der Feldzeilen gemessen 105px);
 * Dev hatte 20px bzw. 5px, macht 97px. */
/* NACHTRAG r6: auch NACH UNTEN ein negativer Aussenabstand.
 * Am Element gemessen (1440): Live `.elementor-form-fields-wrapper { margin: 0 -12px -25px }`.
 * Die -25px heben den Abstand der LETZTEN Feldgruppe wieder auf — der Rahmen ist damit
 * 664px hoch, obwohl die Gruppen zusammen 689px ergeben.
 * Dev hatte nur den waagerechten Ausgleich; das Formular war 689px hoch, der Abschnitt
 * 889 statt 864 und die Seite 2370 statt 2345. Alle Feldzeilen lagen dabei bereits exakt
 * auf den Live-y-Werten (552/552/657/657/762/867/1079/1166) — es fehlte nur der Abschluss. */
.brxe-form.cnt-form {
  margin-inline: -12px;
  margin-bottom: -25px;
  width: calc(100% + 24px);
  max-width: none;
}

.brxe-form.cnt-form .form-group {
  padding-inline: 12px;
  padding-bottom: 0;
  margin-bottom: 25px;
}

/* R8 (C8) — auf Mobil steht jedes Feld allein in seiner Zeile.
 *
 * Am Element gemessen, Feldgruppen 1-4 („First name", „Last name", „Email", „Phone"):
 *
 *   Breite   1440        768         390
 *   Live     495 (50%)   366 (50%)   **354 (100%)**
 *   Dev      495         366         **177 (50%)**
 *
 * Die Felder blieben auf Dev zweispaltig und damit 153 statt 330px breit
 * (`BREITE 330 -> 153 [bg] rgb(244,244,244)` 4x); /contact/ sprang dadurch von
 * 1 Restpunkt bei 1440/768 auf 8 bei 390.
 *
 * Ursache: convert.py gibt die Spaltenbreite des Elementor-Feldes NUR fuer Desktop aus —
 * `#brxe-b29bdc .form-group:nth-child(1..4) { width: 50% }` (Seiten-CSS im <head>,
 * Spezifitaet 1,1,0). Elementor fuehrt `_column_size` je Haltepunkt; auf Mobil steht dort
 * 100. Die Breakpoint-Variante fehlt im Nachbau ganz — derselbe Fall wie `text_padding`
 * (r6-konverter Fund 6). Gehoert langfristig nach convert.py.
 *
 * Bis dahin hier, an die Element-ID gebunden. Spezifitaet: die Konverterregel ist
 * `#brxe-b29bdc .form-group:nth-child(1)` = 1,2,0 (`:nth-child()` zaehlt wie eine Klasse —
 * mit `main #brxe-b29bdc .form-group` = 1,1,1 blieb sie unveraendert bei 177px, im Browser
 * nachgeprueft). `[role="group"]` hebt auf 1,2,1 und traegt genau eine Stufe hoeher.
 * Sobald convert.py die mobile Variante selbst ausgibt, kann der Block ersatzlos weg.
 * 767px ist Elementors Mobil-Haltepunkt (bei 768 sind Live und Dev uebereinstimmend
 * zweispaltig, gemessen).
 *
 * NACHTRAG R10 — ENTSCHEIDUNG: DER NOTNAGEL BLEIBT. Nachgemessen, nicht abgewogen.
 * Der Konverter-Agent hat die Regel als ueberfluessig gemeldet, weil convert.py inzwischen
 * selbst eine mobile Variante ausgibt (generated.css:
 * `@media (max-width:767px){ #brxe-b29bdc .form-group { width:100% } }`).
 * Sie greift aber nicht — nicht wegen der Ladereihenfolge, sondern wegen der Spezifitaet:
 *
 *   Bricks-Seiten-CSS   #brxe-b29bdc .form-group:nth-child(1)  { width:50%  }   1,2,0
 *   generated.css       #brxe-b29bdc .form-group               { width:100% }   1,1,0
 *
 * `:nth-child()` zaehlt wie eine Klasse; die Konverterregel steht damit EINE Stufe unter
 * der, die sie ueberstimmen soll, und zwar bei jeder Bildschirmbreite.
 *
 * Gegenprobe im Browser, diese Regel probeweise entfernt, /contact/ bei 390, die vier
 * Feldgruppen 1-4 (`diag/r10/probe.py form 390`, dreimal wiederholt, identisch):
 *
 *   Live  354.0 x=18   354.0 x=18   354.0 x=18   354.0 x=18
 *   ohne  177.0 x=18   177.0 x=195  177.0 x=18   177.0 x=195     <- wieder zweispaltig
 *   mit   354.0 x=18   354.0 x=18   354.0 x=18   354.0 x=18      = Live
 *
 * Ersatzlos wegfallen kann der Block erst, wenn convert.py die mobile Variante mit
 * MINDESTENS derselben Spezifitaet ausgibt wie die Desktopvariante — also ebenfalls als
 * `#brxe-b29bdc .form-group:nth-child(n) { width:100% }`. */
@media (max-width: 767px) {
  main #brxe-b29bdc .form-group[role="group"] {
    width: 100%;
  }
}

.brxe-form.cnt-form .form-group > label {
  margin-bottom: 0;
  padding-bottom: 8px;
}

/* Honigtopf-Feld. Sein Container .altEmail_container ist auf beiden Seiten 1x1 und
 * geclippt — die Beschriftung „Alternative:" wird von scmp trotzdem als Textknoten
 * erfasst und meldete `WEIGHT 500 -> 300`, `LEADING 1.45 -> 1.70`, `BREITE 9 -> 78`.
 * Auf Live greift an ihr Astras `label, legend { font-weight:500; line-height:20px }`,
 * weil Elementors `.elementor-field-label` sie nicht erfasst (sie hat die Klasse nicht)
 * und sie inline bleibt. Im Nachbau zog die Regel `.brxe-form label { font-weight:inherit }`
 * weiter oben sie auf 300 und Bricks machte einen Block daraus.
 * ID-Selektor, weil convert.py der Form die Beschriftungstypografie als
 * `#brxe-b29bdc label { font-weight:300; line-height:24px }` mitgibt (1,0,1). Fuer die
 * SICHTBAREN Beschriftungen ist das richtig — auf Live sind sie tatsaechlich 300/24px —,
 * nur der Honigtopf ist die Ausnahme. */
/* Der Honigtopf-Container liegt NICHT in einer .form-group und bekommt deshalb die 12px
   Innenabstand des Feldrasters nicht zurueck — mit dem negativen Aussenabstand am Formular
   stand er bei x=18 statt 30 (gemessen). */
main #altEmail_container {
  margin-left: 12px;
}

/* `overflow-wrap: break-word` steht auf Live an der Beschriftung: im 1px breiten Container
   bricht „Alternative:" dort zeichenweise um (gemessen 9px breit, 324px hoch = 16 Zeilen
   a 20px). Ohne die Angabe bleibt das Wort im Nachbau in einer Zeile (80x16) und scmp
   meldet `BREITE 9 -> 80`. */
main #altEmail_container label {
  overflow-wrap: break-word;
  display: inline;
  font-weight: 500;
  line-height: 20px;
  margin: 0;
  padding: 0;
}

/* Dasselbe fuer das Honigtopf-Eingabefeld. Der Kommentar oben („kein Unterschied zu
 * beheben") stimmt fuer die Sichtbarkeit, nicht fuer die Messung: scmp erfasst den Kasten
 * und meldete `BREITE 34 -> 26` und `RADIUS 4 -> 0`. Live gemessen 34x48 mit
 * padding 12px 16px und border-radius 4px; Dev 26x48 mit padding 0 12px und Radius 0
 * (ACSS-Formularvorgaben). Beide liegen im 1x1 geclippten Container, sichtbar wird davon
 * nichts — es geht nur darum, dass die Messung nicht dauerhaft zwei Scheintreffer meldet. */
main #altEmail_container input {
  padding: 12px 16px;
  border-radius: 4px;
}

.brxe-form.cnt-form textarea {
  height: 155px;
}

.brxe-form.cnt-form .submit-button-wrapper {
  width: 100%;
}

.brxe-form.cnt-form button.bricks-button {
  width: 100%;
  height: 50px;
  background-color: #870a09;
  border-color: #870a09;
  color: #ffffff;
}

/* Zeilenumbruch wie auf Live.
 *
 * ACSS setzt `body { text-wrap: var(--text-text-wrap) }` und dieselbe Regel fuer h1-h6
 * ueber `--heading-text-wrap`; beide standen auf `pretty`. Live hat diese Regel gar nicht
 * und bricht mit dem Browser-Standard `wrap`.
 *
 * `pretty` zieht Umbrueche vor, um kurze Schlusszeilen zu vermeiden — es aendert also auf
 * JEDEM mehrzeiligen Absatz die Umbruchstellen. Gemessen auf /imprint/: gleicher Text,
 * gleiche Containerbreite (880px), gleiche Zeilenbreite (885.00px), trotzdem anderer
 * Umbruch. Das schlaegt site-weit als Breiten- und Hoehenabweichung durch.
 *
 * Bewusst nur die beiden Variablen ueberschrieben statt der Regeln: ACSS' eigene
 * Opt-in-Klassen (.balance, .text--pretty, .unbalance) bleiben damit funktionsfaehig. */
:root {
  --text-text-wrap: wrap;
  --heading-text-wrap: wrap;
}

/* Zaehler-Baustein (Elementor counter, auf / vier Stueck: "Human Profiles", …).
 *
 * Elementors Markup ist Titel ZUERST, Zahl danach — gedreht wird im CSS:
 *   .elementor-counter { display:flex; flex-direction: column-reverse; gap:10px }
 * (auf lifespin.health am Element gemessen). Die Zahl steht dadurch OBEN, die Beschriftung
 * darunter. Der Bricks-Nachbau uebernimmt die DOM-Reihenfolge, aber nicht die Drehung:
 * auf Dev stand "Human Profiles" ueber der Zahl. Im Bild sofort sichtbar, in der Messung
 * nur als X-/BREITE-Rauschen.
 * Die Konverter-Klassen ls-counter__title / ls-counter__value werden von convert.py
 * vergeben, gestylt hat sie bisher niemand (kein Treffer in irgendeiner CSS des Themes).
 * :has() greift den Rahmen, der selbst keine eigene Klasse traegt.
 *
 * NACHTRAG r6: die Regel stand hier schon, wirkte aber NICHT. Ursache mit CDP
 * (CSS.getMatchedStylesForNode am .ls-counter) nachgewiesen: der Konverter gibt zu
 * demselben Element `#brxe-f0a476 { display:flex; flex-direction:column }` aus.
 * Spezifitaet 1,0,0 gegen 0,2,0 — die ID gewinnt, unabhaengig von der Ladereihenfolge.
 * Gemessen auf Dev: Titel „Human Profiles" y=2702 (oben), Zahl y=2736 (darunter);
 * Live umgekehrt: Zahl y=792, Titel y=892. Schriftgroessen sind auf beiden Seiten
 * gleich (Titel 24px/400/Exo 2, Zahl 90px/600/Exo) — nur die Reihenfolge war falsch.
 * Deshalb !important, dieselbe Begruendung wie bei `width: fit-content !important`
 * in layout.css. Sobald convert.py die Drehung selbst ausgibt, kann das hier weg. */
main .ls-widget:has(> .ls-counter__title),
main .ls-widget.ls-counter {
  flex-direction: column-reverse !important;
}

/* Zahl, Vor- und Nachsilbe liegen bei Elementor in einer Flex-ZEILE
 * (.elementor-counter-number-wrapper{display:flex}); die Zahl ist damit so breit wie ihre
 * Ziffern (gemessen 59px), die Nachsilbe schliesst direkt an (x=823). Als Block-Element
 * rendert Bricks sie zwar optisch gleich, aber die Textausrichtung des Widgets (center)
 * greift dann auf die volle Kastenbreite durch — scmp meldete "ALIGN center -> left". */
main .ls-counter__value {
  display: flex;
}

/* Autorenkasten des Rothman-Zitats auf / (Elementor author-box).
 *
 * Live: .elementor-author-box { display:flex; flex-direction:row; align-items:center }
 * — Portraet links (100x100, x 764..864), Textspalte rechts (x 889..1116), 25px dazwischen.
 * Der Nachbau legt Bild, Name und Kurztext als drei Geschwister in eine Spalte, das Foto
 * stand dadurch UEBER dem Text. Ein blosses flex-direction:row wuerde alle drei
 * nebeneinander stellen; mit Grid bekommt das Bild beide Zeilen der zweiten Spalte.
 * .dr-james ist die im Elementor-Baustein gesetzte eigene Klasse und wird vom Konverter
 * mituebernommen — es gibt sonst keinen Anker an diesem Kasten. */
main .dr-james {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: 25px;
  width: fit-content;
}

main .dr-james > img {
  grid-column: 1;
  grid-row: 1 / span 2;
  /* R34 — der Avatar ist auf Live ein KREIS. In den Elementor-Einstellungen des
     Widgets steht dazu nichts: der Wert ist eine Vorgabe aus Elementor Pros eigenem
     Stylesheet, `.elementor-author-box__avatar img { border-radius: 500px }`
     (elementor-pro/assets/css/widget-author-box.min.css) — dieselbe Datei und
     dieselbe Familie wie `__bio { margin-bottom: .8em }` aus R29 an genau diesem
     Widget. Faellt mit dem Plugin weg, muss also mitkommen.
     Woertlich als 500px uebernommen, nicht als abgelesenes 50%. */
  border-radius: 500px;
}

main .dr-james > .brxe-heading {
  grid-column: 2;
  grid-row: 1;
  margin-bottom: 7px;
}

main .dr-james > .brxe-text {
  grid-column: 2;
  grid-row: 2;
}

/* Die Zahl ist bei Elementor mittig gesetzt (computed text-align: center am
   .elementor-counter-number). Weil sie dort in einer Flex-Zeile nur so breit ist wie ihre
   Ziffern, sieht man es nicht — messbar ist es trotzdem ("ALIGN center -> left"). */
main .ls-counter__value {
  text-align: center;
}

/* Vor- und Nachsilbe erben diese Mitte NICHT. Elementor setzt sie eigens:
   `.elementor-counter-number-prefix { text-align: end }` und
   `.elementor-counter-number-suffix { text-align: start }` — auf lifespin.health am
   Element gemessen (Nachsilbe „+", computed text-align: start). Ohne die Gegenregel
   erbt die Nachsilbe im Nachbau die center-Angabe eine Zeile hoeher; scmp meldete
   „ALIGN center -> left" am Knoten „+". */
main .ls-counter__value .prefix { text-align: end; }
main .ls-counter__value .suffix { text-align: start; }

/* NACHTRAG r6 — dieselbe Elementor-Regel setzt an Vor- und Nachsilbe zusaetzlich
   `white-space: pre-wrap`, damit ein fuehrendes oder abschliessendes Leerzeichen im
   Zaehlerzusatz erhalten bleibt. Auf / am Knoten „+" gemessen: Live `pre-wrap`,
   Dev `normal`. Nur die vierte Messung (bcmp) sieht das — scmp vergleicht white-space
   nicht. Die Vorsilbe ist auf / leer und daher nicht messbar; sie bekommt die Angabe
   mit, weil Elementor beide in derselben Deklaration fuehrt. */
main .ls-counter__value .prefix,
main .ls-counter__value .suffix { white-space: pre-wrap; }

/* R37 — der Rest derselben Plugin-Regel, einmal ganz gelesen statt zum fuenften Mal
 * einzeln nachgemessen.
 *
 * Die vier Bloecke darueber sind ueber vier Runden entstanden: erst `display:flex`,
 * dann `text-align:center`, dann `text-align:end/start`, dann `white-space:pre-wrap` —
 * jeder fuer sich am Live-Stand abgelesen, jeder mit eigener Begruendung. ALLE VIER
 * stehen woertlich in EINER Datei des Plugins,
 * `elementor/assets/css/widget-counter.min.css`:
 *
 *   .elementor-counter                       { align-items:stretch; display:flex;
 *                                              flex-direction:column-reverse;
 *                                              justify-content:center }
 *   .elementor-counter-number                { flex-grow:var(--counter-number-grow,0) }
 *   .elementor-counter-number-wrapper        { display:flex; flex:1; font-size:69px;
 *                                              font-weight:600; line-height:1;
 *                                              text-align:center }
 *   .elementor-counter-number-prefix         { flex-grow:var(--counter-prefix-grow,1);
 *                                              text-align:end; white-space:pre-wrap }
 *   .elementor-counter-number-suffix         { flex-grow:var(--counter-suffix-grow,1);
 *                                              text-align:start; white-space:pre-wrap }
 *   .elementor-counter-title                 { align-items:center; display:flex; flex:1;
 *                                              justify-content:center; line-height:2.5;
 *                                              font-size:19px; font-weight:400;
 *                                              margin:0; padding:0 }
 *
 * Gefehlt haben genau die WAAGERECHTEN Ausrichtungen — und die sind sichtbar:
 * auf / bei 390 stand die Zahl auf Live mittig (x=92,5), auf Dev am linken Rand
 * (x=30), die Beschriftung ebenso. Im Bild sofort, in der Bandmessung nicht:
 * der Bandzaehler hat die Stelle zwar gemeldet, aber wegen der laufenden
 * Hochzaehl-Animation, die den echten Befund verdeckt hat.
 *
 * 1) Die Zahl wird NICHT durch `justify-content` zentriert, sondern dadurch, dass
 *    Vor- und Nachsilbe wachsen (`flex-grow: 1`) und die Zahl nicht (`0`).
 *    Bricks rendert keine leere Vorsilbe -> `::before` als Platzhalter, damit die
 *    freie Strecke wie auf Live auf BEIDE Seiten faellt.
 *    Nachgerechnet bei 390: frei = 330 - 177 (Zahl) - 28 ("+") = 125, haelftig 62,5
 *    -> Zahl bei 30+62,5 = 92,5, Nachsilbe bei 269,5. Beides exakt die Live-Werte.
 * 2) Die Beschriftung ist ein Flex-Kasten mit `justify-content: center`.
 *
 * BEWUSST NICHT uebernommen: font-size, font-weight und line-height. Die setzt der
 * Konverter aus der Widget-Typografie, und die deckt sich bereits mit Live (Titel
 * 24px/400/Exo 2, Zahl 90px/600/Exo). Wer die Plugin-Vorgaben zusaetzlich
 * hinschreibt, ueberschreibt eine gemessen richtige Angabe mit einer generischen.
 * `align-items:stretch` und `flex-grow:0` an der Zahl sind ohnehin die Vorgaben. */
/* Die Mitte kommt NICHT von `justify-content` — der Wrapper steht bei Elementor auf
 * `normal`. Sie entsteht allein daraus, dass Vor- und Nachsilbe wachsen. Ein
 * zusaetzliches `justify-content: center` waere wirkungslos (wachsende Kinder lassen
 * keine freie Strecke uebrig) und wuerde bei `stretch` sogar falsch wirken. */
main .ls-counter__value::before { content: ""; flex-grow: var(--counter-prefix-grow, 1); }
main .ls-counter__value .prefix { flex-grow: var(--counter-prefix-grow, 1); }
main .ls-counter__value .suffix { flex-grow: var(--counter-suffix-grow, 1); }
main .ls-counter__value .count  { flex-grow: var(--counter-number-grow, 0); }

/* `justify-content: center` ist hier die PLUGIN-VORGABE, nicht der gemessene Wert:
 * der Regler `title_horizontal_alignment` ist responsiv, und wo er gesetzt ist,
 * ueberschreibt ihn convert.py je Stufe mit `#brxe-<id>` (1,2,0). Auf / steht er auf
 * `start` und erst ab 767 px auf `center` — eine pauschale Mitte hier hat 1440 und 768
 * von 0 auf je 2 Baender getrieben. Dasselbe gilt fuer `number_position` an der Zahl. */
main .ls-counter__title {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Elementors Bild-Baustein ist mittig: `.elementor-widget-image { text-align: center }`,
   das Bild darin ist inline-block. Gemessen auf /products-and-services/: Zelle 306..532
   (226 breit), Bild 200 breit, Live x=319 = mittig, Dev x=306 = links.
   In Bricks ist das img selbst das Element und damit ein Block; margin-inline:auto stellt
   dieselbe Mitte her, ohne breitere Bilder zu beeinflussen.
   Eine am Element gesetzte Ausrichtung des Konverters (#brxe-…) schlaegt diese Regel. */
main img.brxe-image,
main .brxe-image > img {
  margin-inline: auto;
}

/* Bilder sind auf Live nicht abgerundet — auf /products-and-services/ und / traegt auf Live
   KEIN img einen border-radius, auf Dev alle 5px (ACSS-Vorgabe ueber --image-radius).
   R34 — die Einschraenkung auf `main` war zu eng: das Fusszeilen-Logo liegt AUSSERHALB
   und behielt deshalb auf JEDER Seite die 5px, waehrend Live dort 0 hat. Der
   Bildvergleich meldet das nicht (zu wenig Flaeche), gemessen am Wert ueber alle
   Bilder von vier Seiten (work/diag/r34-radius.py).
   Gefahrlos ohne `main`, seit der Konverter einen am Bild gesetzten
   `image_border_radius` als `#brxe-<eid>`-Regel ausgibt — die schlaegt diese hier
   (1-0-0 gegen 0-1-2) und ist damit die einzige Quelle fuer einen echten Radius. */
img.brxe-image,
.brxe-image > img {
  border-radius: 0;
}

/* R8 — Das Bild einer image-box sitzt auf der Grundlinie, nicht in der Zeilenmitte.
 *
 * Ursache der 9px, um die JEDE Karte der drei Kit-Seiten zu niedrig war
 * (`HOEHE 416 -> 407`, `384 -> 375`, `403 -> 394`, `365 -> 356` … 1440/768/390).
 * Am Element gemessen (/kit-information-plasma/, Karte 1, 1440):
 *   LIVE  img  display:block, line-height:0, margin:0
 *         eingehuellt in figure.elementor-image-box-img
 *         display:inline-block, vertical-align:BASELINE, margin-bottom:15px
 *         -> Zeilenkasten = 160 + 15 (Rand) + 9 (Unterlaenge des Strichs bei
 *            line-height 28px / font-size 16px) = 184
 *   DEV   img  display:inline-block, vertical-align:MIDDLE, margin-bottom:15px
 *         -> mittig ausgerichtet, kein Platz unter der Grundlinie = 175
 * Differenz exakt 9px, gemessener Innenkasten Live 276 / Dev 267.
 *
 * `vertical-align: middle` kommt aus Bricks' Bildreset und gilt auf Live genauso
 * fuer das <img> — nur ist dort das <figure> das inline-block-Element, und ein
 * <figure> hat vertical-align:baseline. Der Konverter hat im Nachbau keine Huelle
 * mehr und setzt display:inline-block ans Bild selbst
 * (generated.css: `#brxe-… > img, #brxe-… > figure { display:inline-block;
 * margin-inline:auto; margin-bottom:15px }`) — damit wandert das va:middle des
 * Bildresets vom Bild in die Zeilenlage und schluckt die 9px.
 *
 * Geltungsbereich `.ls-widget > img.brxe-image`: NUR Bilder INNERHALB eines
 * Widget-Kastens, also genau die image-box-Bilder. Der eigenstaendige
 * Bild-Baustein traegt `ls-widget` an sich selbst und liegt in einem `.ls-con` —
 * er wird nicht getroffen (und ist ohnehin display:block, wo vertical-align
 * wirkungslos ist). Bei image-box-Position `left` ist das Bild ein Flex-Kind,
 * dort ist die Angabe ebenfalls folgenlos.
 * Der Konverter setzt zu diesen Elementen KEIN vertical-align; es gibt also
 * keinen Konflikt mit generated.css. */
main .ls-widget > img.brxe-image {
  vertical-align: baseline;
}

/* R8 — Listen-Bausteine ohne senkrechten Aussenabstand.
 *
 * `ul, ol { margin-top:16px; margin-bottom:16px }` weiter oben ist die
 * Browser-/Astra-Vorgabe fuer Fliesstextlisten (z. B. /privacy-statement/, dort
 * auf Live UND Dev `8px 0 16px 24px` aus dem Seiten-CSS — unberuehrt).
 * Elementors icon-list-Widget setzt dagegen `.elementor-icon-list-items
 * { margin:0; padding:0; list-style:none }`; alle 7 Listen im <main> von
 * /kit-information-plasma/ haben auf Live gemessen `margin: 0px`, auf Dev
 * `16px 0px`.
 * Im Nachbau IST die Liste das Flex-Kind der Karte (auf Live steckt sie in einem
 * Widget-Rahmen und ihre Raender liegen INNEN), also schlagen 16+16 = 32px voll
 * auf die Kartenhoehe durch: `HOEHE 438 -> 461` und `478 -> 501` auf allen drei
 * Kit-Seiten (zusammen mit den -9px des Bildes oben ergibt das die +23). */
main .brxe-list {
  margin-block: 0;
}

/* Knoepfe, die nicht aus Bricks stammen (hier der Downloadknopf des Sample-Report-Plugins
   im shortcode-Baustein auf /products-and-services/), stehen auf Live auf der
   Browser-Vorgabe text-align:center; auf Dev setzt der ACSS-/Bricks-Formularreset sie auf
   start. Gemessen: gleicher Knopf 47..413, Text 256 breit, Live x=102, Dev x=73. */
main button:not([class*="brxe-"]):not(.bricks-button) {
  text-align: center;
}

/* Symbol-Baustein: Grundfarbe wie im Elementor-Kit.
 *
 * Elementor gibt jedem icon-Widget `.elementor-icon { color: var(--e-global-color-primary) }`
 * (= #000000) — dieselbe Herkunft wie die Ueberschriftenfarbe weiter oben. Auf /contact/
 * gemessen: Live `SPAN.elementor-icon` und das svg darin rgb(0,0,0), Dev `svg.brxe-icon`
 * rgb(22,22,22) (geerbte Body-Farbe).
 * Sichtbar ist davon hier nichts, weil die drei Symbole ihre Flaechen selbst faerben;
 * messbar schon: bcmp meldete es als `deco-color: rgb(0,0,0) -> rgb(22,22,22)` am
 * `<style>`-Knoten INNERHALB des svg (der erbt die Textfarbe). Fuer Symbole, deren Flaeche
 * auf `currentColor` steht, ist es der Unterschied zwischen #000 und #161616.
 * Spezifitaet 0,1,1 — eine am Element gesetzte Farbe des Konverters (#brxe-…) gewinnt. */
main .brxe-icon {
  color: #000000;
}

/* Trennlinie des divider-Bausteins.
 *
 * Bricks zeichnet die Linie ueber `.brxe-divider .line { border-top: 1px solid }` ohne
 * Farbangabe — sie erbt damit currentColor, auf Dev also die Textfarbe #161616 und steht
 * als fast schwarzer Strich im Layout. Elementor faerbt sie am Widget.
 * Am Element gemessen (1440, computed border-top-color der `.elementor-divider-separator`):
 *   /science-and-technology/   8x  rgb(222,222,222)
 *   /kit-information-plasma/   1x  rgb(222,222,222)
 *   /metabopro-regensburg/     2x  rgb(222,222,222) + 1x rgb(229,229,229)
 *   /products-and-services/    4x  rgb(219,219,219)
 * #DEDEDE ist damit der belegte Regelfall, /products-and-services/ die Ausnahme.
 * Keine der drei Messungen sieht das: scmp vergleicht Rahmen nur an Flaechen MIT
 * Hintergrund, und die Linie hat keinen. Im Bild ist der Unterschied deutlich. */
main .brxe-divider .line {
  border-top-color: #DEDEDE;
}

main #brxe-444f60 .line,
main #brxe-c7b82a .line,
main #brxe-df0b89 .line,
main #brxe-dec97b .line {
  border-top-color: #DBDBDB;
}

/* Sample-Report-Plugin: die Eingabefelder sind auf Live 4px rund, auf Dev 8px
   (ACSS-Formularvorgabe). Am Element gemessen, beide 366x48. */
main .spdfed-input {
  border-radius: 4px;
}

/* Akkordeon der Landingpages (.land-faq auf /metabopro-regensburg/ und
 * /metabopro-event-de/).
 *
 * Gegenstueck zum bereits vorhandenen Block fuer `.faq-block` in site.css:
 * dort war das Bricks-Akkordeon schon einmal auf Elementors Grundmasse
 * zurechtgerueckt worden, die zweite Bauform blieb liegen. Am gerenderten
 * DOM gemessen (1440, /metabopro-regensburg/, `diag/r9/`):
 *
 *   Live  .elementor-accordion        margin 0, Widgetkasten padding 50px 0 0
 *         .elementor-accordion-item   padding 0, border-bottom 1px #dedede
 *         .elementor-tab-title        padding 20px 0
 *         .elementor-accordion-title  margin 0
 *         .elementor-tab-content      padding 0 30px 30px 15px
 *         ganzes Akkordeon                                    607.6 px
 *   Dev   ul.brxe-accordion           margin 16px 0 (aus `ul,ol` weiter oben)
 *         li.accordion-item           padding-top 50px JE EINTRAG, kein Rahmen
 *         .accordion-title-wrapper    padding 15px 0, margin-bottom -1px
 *         .accordion-title .title     margin-bottom 20px (aus `h1..h6` oben)
 *         .accordion-content-wrapper  padding 0 0 15px
 *         ganzes Akkordeon                                   1056.6 px
 *
 * 449 px Mehrhoehe, im Bild sofort sichtbar (Eintraege doppelt so weit
 * auseinander, keine Trennlinien).
 *
 * Die 50px waren Elementors Polster des WIDGETS — einmal ueber dem ganzen
 * Akkordeon; convert.py legte sie auf jeden Eintrag. Das ist seit R10 in
 * convert.py behoben (Polster steht am <ul>), die Gegenregel dazu ist unten
 * ersatzlos entfallen — siehe den NACHTRAG R10 an ihrer Stelle.
 *
 * Die uebrigen Regeln sind Grundmasse, keine Widgeteinstellungen; sie stehen
 * bewusst mit niedriger Spezifitaet, damit site.css (`.faq-block`, 0,3,x) und
 * das Seiten-CSS des Konverters (1,x,x) weiterhin gewinnen. */
main .brxe-accordion {
  margin-block: 0;
}
main ul.brxe-accordion.land-faq > li.accordion-item {
  border-bottom: 1px solid #DEDEDE;
}
/* NACHTRAG R10 — ENTFERNT. Hier stand
 *   main ul.brxe-accordion.land-faq > li.accordion-item + li.accordion-item
 *     { padding-top: 0 !important }
 * gegen das Widgetpolster, das convert.py auf JEDEN Eintrag gelegt hatte.
 * Der Konverter-Agent hat die Ursache inzwischen behoben: das Polster steht jetzt
 * EINMAL am <ul> (im ausgelieferten Seiten-CSS von /metabopro-regensburg/ ist
 * `#brxe-dc68ad .accordion-item { padding-top: 50px }` verschwunden, das <ul> hat
 * computed `padding: 50px 0 0`).
 *
 * Nachgemessen (diag/r10/probe.py acc 1440), Akkordeonhoehe und Polster je Eintrag,
 * mit und ohne die Regel — Ergebnis identisch, die Regel war wirkungslos geworden:
 *
 *   /metabopro-regensburg/  Live 607.6  Dev 657.6   Eintraege 144.2 + 7x66.2 = Live
 *   /metabopro-event-de/    Live 541.4  Dev 591.4   Eintraege 144.2 + 6x66.2 = Live
 *   padding-top je Eintrag  Live 0px    Dev 0px     (mit UND ohne die Regel)
 *
 * Die verbliebenen 50px sind dieselbe Buchhaltung wie in R9 beschrieben: auf Live
 * liegen sie im Widgetkasten UEBER dem Akkordeon, auf Dev im Polster des <ul> —
 * im Bild dieselbe Stelle, keine Verschiebung.
 * Die uebrigen .land-faq-Regeln bleiben: sie tragen Rahmen, Kopfpolster,
 * Titelabstand und Inhaltspolster und sind weiterhin noetig (Eintragshoehe 66.2
 * = Live nur mit ihnen). */
main ul.brxe-accordion.land-faq .accordion-title-wrapper {
  padding: 20px 0;
  margin: 0;
}
main ul.brxe-accordion.land-faq .accordion-title .title {
  margin: 0;
}
main ul.brxe-accordion.land-faq .accordion-content-wrapper {
  padding: 0 30px 30px 15px;
}

/* Inhaltsspalte der zusammengesetzten Bausteine (icon-box, image-box).
 *
 * convert.py setzt Elementors icon-box und image-box aus Einzelteilen zusammen
 * und legt Titel und Text in einen HUELLBLOCK ohne eigene Klassen — im HTML
 * genau `<div class="brxe-block">`. Bricks gibt jedem Block
 * `.brxe-block { display:flex; flex-direction:column; align-items:flex-start }`
 * (frontend.min.css). `flex-start` laesst Titel und Text auf ihre Textbreite
 * schrumpfen; Elementors Gegenstueck `.elementor-icon-box-content` ist ein
 * schlichter Block, dort fuellen beide die Spalte.
 *
 * Folge ist ein falscher UMBRUCHKASTEN, nicht nur eine falsche Kastenbreite.
 * Gemessen an den zehn Icon-Boxen von /metabopro-regensburg/ (1440,
 * `diag/r9/`): Spalte 176.7 breit, der Beschreibungstext lief aber je nach
 * Inhalt in 77 / 107 / 151 / 159 / 164 px und brach entsprechend frueher um.
 * Live: durchgaengig 171.7. Der Titel der breiten Box "Umfassend &
 * verstaendlich" mass 199 statt 719.
 *
 * `[class="brxe-block"]` trifft exakt die Huelle: jeder vom Konverter
 * uebersetzte Container traegt zusaetzlich `ls-el`/`ls-con`, nur die
 * eingeschobene Huelle nicht. */
main .ls-widget > div[class="brxe-block"] {
  align-items: stretch;
}

/* ---------------------------------------------------------------------------
 * Wortumbruch in langen Woertern — Grundstil des alten Stacks, nicht portiert.
 *
 * Astra setzt `overflow-wrap: break-word` auf Fliesstext und Ueberschriften.
 * Auf Dev fehlte das. Der Bildvergleich sieht davon NICHTS: er misst Baender,
 * und ein 4 px ueber den Rand ragendes Wort erzeugt kein Band. Gefunden ueber
 * die Fensterbreite — `document.documentElement.scrollWidth` auf /datenschutz/
 * bei 390: Live 390, Dev 394. Ursache war die H1 "Datenschutzerklaerung":
 * 334 px breit in einem 330 px breiten Kasten. Live bricht das Wort um, Dev
 * liess es ueberlaufen und erzeugte damit eine waagerechte Bildlaufleiste.
 *
 * Das Element selbst verraet es nicht — `getBoundingClientRect()` der H1 ist
 * auf beiden Staenden 330 breit. Sichtbar wird es nur an den Zeilenkaesten des
 * TEXTKNOTENS (`Range.getClientRects()`).
 *
 * Auswahl exakt nach der Messung des berechneten Wertes auf Live:
 * p, h1, h2, h3, li, span tragen dort `break-word`, body, a und div nicht. */
main p, main h1, main h2, main h3, main h4, main h5, main h6,
main li, main span {
  overflow-wrap: break-word;
}

/* Symbolleiste (social-icons): Groesse aus dem Inhalt, nicht gleichmaessig verteilt.
 *
 * Bricks' Frontend-CSS gibt jedem Eintrag `flex: 1 1 0%`:
 *   .brxe-social-icons .repeater-item,
 *   .brxe-social-icons .repeater-item > a { display: flex; flex: 1 }
 * Die Symbole teilen sich damit die Breite des Widgets. Elementor laesst sie auf ihrer
 * eigenen Groesse stehen (`.elementor-social-icon { display: inline-flex }`) und regelt
 * den Abstand ueber `--grid-column-gap` (Vorgabe 5px).
 * Gemessen (1440, /about-us/, Fusszeile): Live Link 24x24, Dev 330x24 — der Hintergrund
 * #161616 lief ueber die volle Spaltenbreite. Sichtbar wird das erst auf hellem Grund;
 * messbar ist es ueberall.
 * Der Abstand kommt seit R18 aus dem Konverter (`_columnGap`), nicht aus dieser Regel.
 * Spezifitaet: Bricks' Regel ist 0,2,0 und wird NACH dem Child-Theme geladen — eine
 * gleich starke Regel verliert also (gemessen: beide Regeln matchen, Bricks gewinnt).
 * Deshalb ueber `.has-link`/`.no-link` auf 0,3,0 angehoben; das sind genau die beiden
 * Klassen, die Bricks selbst an jeden Eintrag schreibt.
 */
.brxe-social-icons .repeater-item.has-link,
.brxe-social-icons .repeater-item.no-link,
.brxe-social-icons .repeater-item.has-link > a {
	flex: 0 0 auto;
}

/* R33 (Fall 159) — Hoehe des Untermenue-Pfeils.
   Live's Zeichen traegt Elementors Klasse `e-font-icon-svg`, und deren einzige
   Regel im Plugin-Stylesheet lautet `{ height: 1em }` (assets/css/frontend.min.css).
   Sie steht in KEINER Einstellung und faellt mit Elementor weg — dieselbe Familie
   wie `.elementor-author-box__bio { margin-bottom: .8em }` (R29) und die
   TEC-Widget-Sammelregel (R22). Ohne sie ergibt sich die Hoehe aus dem
   Seitenverhaeltnis des caret-Pfads (320:512) zu 25,6 statt 16 px.
   Bewusst als `1em` uebernommen, nicht als abgelesener Pixelwert. */
.brx-submenu-toggle button > svg { height: 1em; }

/* ── Elementor-Kit-Vorgabe fuer nackte <button> (Fall 192) ─────────────────
   Auf Live stylt das Elementor-Kit generisch JEDEN Knopf:
     .elementor-kit-9 button, … input[type=submit], … .elementor-button {
       background-color: var(--e-global-color-primary);   (= #000000)
       font-family:"Exo"; font-size:18px; font-weight:500; line-height:24px;
       color:#FFF; border:1px solid var(--e-global-color-primary);
       border-radius:3px; padding:12px 25px }
   Der Absende-Knopf des Gated-Download-Formulars (Fremd-Shortcode
   coreessentials-email-gated-downloads) bezog sein gesamtes Aussehen daher.
   Mit dem Elementor-Abbau faellt die Regel weg — der Knopf war danach 46
   statt 74 px hoch, was die Seite auf allen drei Breiten 28 px verkuerzt hat.

   BEWUSST auf .spdfed-button gescopt statt woertlich generisch: im Bestand
   gibt es site-weit 304 klassenlose <button> (Bricks' Untermenue-Umschalter,
   h=22, padding 3px 0). Eine generische Regel mit padding 12/25 wuerde die
   alle aufblaehen. Alle uebrigen Knoepfe (Borlabs, Splide, TEC, Bricks)
   bringen ihr eigenes Styling mit und stehen im Bildvergleich auf 0.
   Kommt spaeter ein weiterer Fremd-Shortcode-Knopf dazu, gehoert er hier
   dazu — die Vorgabe gilt auf Live fuer jeden Knopf ohne eigenes Styling.
   `html ` fuer eine Stufe mehr Spezifitaet gegen .spdfed-button{padding:…},
   gleiche Loesung wie harden_ids() — kein !important.
   Hover am Live-Stand gemessen: #320303, transition 0.2s ease-in-out.        */
html .spdfed-button {
  background-color: #000000;
  color: #FFFFFF;
  font-family: "Exo", sans-serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 24px;
  border: 1px solid #000000;
  border-radius: 3px;
  padding: 12px 25px;
  transition: background-color .2s ease-in-out, border-color .2s ease-in-out;
}
html .spdfed-button:hover {
  background-color: #320303;
  border-color: #320303;
}
