/* ============================================================
   REITER-WERZIN — website stylesheet
   Palette: warm beige / graphite. Quiet, editorial, rounded.
   ============================================================ */

/* Fonts are self-hosted — no external requests, no Google Fonts.
   Files live in files/rw/theme/media/fonts/ (latin subset, see fonts/README.md). */
@font-face{ font-family:'Inter'; font-style:normal; font-weight:400; font-display:swap;
  src:url('../../files/rw/theme/media/fonts/Inter-Regular.woff2') format('woff2'); }
@font-face{ font-family:'Inter'; font-style:normal; font-weight:500; font-display:swap;
  src:url('../../files/rw/theme/media/fonts/Inter-Medium.woff2') format('woff2'); }
@font-face{ font-family:'Inter'; font-style:normal; font-weight:600; font-display:swap;
  src:url('../../files/rw/theme/media/fonts/Inter-SemiBold.woff2') format('woff2'); }
@font-face{ font-family:'Inter'; font-style:normal; font-weight:700; font-display:swap;
  src:url('../../files/rw/theme/media/fonts/Inter-Bold.woff2') format('woff2'); }

/* Metrisch angeglichener Fallback: bis Inter geladen ist, rendert die lokale
   Systemschrift mit denselben Zeilen- und Zeichenmaßen. Der Wechsel bleibt
   dadurch ohne Umbruch- oder Höhensprung — das „Nachrutschen" beim ersten
   Seitenaufruf entfällt. Werte aus dem Metrik-Vergleich Inter/Arial. */
@font-face{
  font-family:'Inter Fallback';
  src: local('Arial'), local('Helvetica Neue'), local('Liberation Sans');
  size-adjust: 107.12%;
  ascent-override: 90.20%;
  descent-override: 22.48%;
  line-gap-override: 0%;
}

:root{
  --bg: #F2EEE5;
  --bg-alt: #E9E3D5;
  --card: #FBF9F4;
  --ink: #24221E;
  /* Auf WCAG 2.1 AA (>=4.5:1) abgestimmt — gegen --bg, --bg-alt UND --card.
     Korrektur 2026-08-10: --ink-faint war #6B6658 und erreichte auf --bg zwar
     4.95, auf dem dunkleren --bg-alt der Fußzeile aber nur 4.48 — knapp unter der
     Anforderung. Lighthouse und die WCAG-Prüfung haben das beide gemeldet
     (Copyright-Zeile und E-Mail-Adresse im Fuß).
     Ein Schritt pro Kanal abgedunkelt, das reicht:
        alt  #6B6658 → --bg 4.95 | --bg-alt 4.48 ✗ | --card 5.44
        neu  #6A6557 → --bg 5.02 | --bg-alt 4.54 ✓ | --card 5.53
     --ink-soft (#666254) lag mit 4.77 auf --bg-alt bereits im grünen Bereich und
     bleibt deshalb unverändert. */
  --ink-soft: #666254;
  --ink-faint: #6A6557;
  --line: #DCD5C3;
  --line-strong: #C7BC9F;
  --white: #FFFFFF;

  --radius-lg: 28px;
  --radius-md: 18px;
  --radius-sm: 10px;

  --maxw: 1180px;
  --measure: 660px;

  --pad: clamp(20px, 4vw, 64px);
  --section-y: clamp(56px, 9vw, 112px);

  --font: 'Inter', 'Inter Fallback', -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}

*{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
body{
  margin:0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
img{ max-width:100%; height:auto; display:block; }
a{ color: inherit; text-decoration: none; }
button{ font-family: inherit; }

.container{
  max-width: var(--maxw);
  margin: 0 auto;
  padding-left: var(--pad);
  padding-right: var(--pad);
}

.featured-post h2 { max-width: var(--measure); }
.measure{ max-width: var(--measure); }

/* ---------- eyebrow / labels ---------- */
.eyebrow{
  display:inline-block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 14px;
}

/* ---------- headings ---------- */
h1,h2,h3,h4{
  font-family: var(--font);
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.15;
  margin: 0 0 .5em;
}
h1{ font-size: clamp(34px, 5vw, 56px); font-weight: 700; }
h2{ font-size: clamp(26px, 3.4vw, 36px); }
h3{ font-size: 20px; }
/* Section headings that sit one level below the page title but read at h3 size:
   correct document outline, unchanged appearance. */
h2.h3{ font-size: 20px; }
p{ margin: 0 0 1em; color: var(--ink); }
.lede{ font-size: 20px; color: var(--ink-soft); line-height: 1.55; }
.muted{ color: var(--ink-soft); }
.small{ font-size: 14px; }

/* ---------- skip link ---------- */
.skip-link{
  position:absolute;
  left:-9999px;
  top:0;
  z-index:100;
  background: var(--ink);
  color: var(--bg);
  font-size:15px;
  font-weight:600;
  padding:12px 20px;
}
.skip-link:focus{ left:0; }
main:focus{ outline:none; }

/* ---------- nav ---------- */
/* Das banner-Landmark <header> trägt die Sticky-Positionierung, nicht mehr .nav:
   ein sticky-Element kann sich nur innerhalb seines Elternelements bewegen,
   und der Wrapper ist genauso hoch wie die Navigation. Optisch unverändert. */
.site-header{
  position: sticky;
  top: 0;
  z-index: 50;
}
.nav{
  background: rgba(242,238,229,.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.nav .container{
  display:flex;
  align-items:center;
  justify-content:space-between;
  height: 76px;
}
.wordmark{
  font-weight: 700;
  font-size: 20px;
  letter-spacing: .01em;
  color: var(--ink);
}
.wordmark .full{ display:inline; }
.nav-links{
  display:flex;
  align-items:center;
  gap: 34px;
}
.nav-links a{
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-soft);
  transition: color .15s ease;
}
.nav-links a:hover, .nav-links a:focus-visible{ color: var(--ink); }
.nav-links a.current{ color: var(--ink); }
.nav-cta{
  background: var(--ink);
  color: var(--bg) !important;
  padding: 10px 22px;
  border-radius: 999px;
  font-weight: 600 !important;
}
.nav-cta:hover{ opacity:.88; }
.nav-toggle{
  display:none;
  background:none; border:none; cursor:pointer;
  padding: 0;
  width: 44px; height:44px;
  flex-direction: column;
  align-items:center; justify-content:center;
}
.nav-toggle span, .nav-toggle::before, .nav-toggle::after{
  content:"";
  display:block;
  width: 22px; height: 2px;
  background: var(--ink);
  transition: transform .2s ease, opacity .2s ease;
}
.nav-toggle span{ margin: 5px 0; }
.nav-toggle.open span{ opacity: 0; }
.nav-toggle.open::before{ transform: translateY(7px) rotate(45deg); }
.nav-toggle.open::after{ transform: translateY(-7px) rotate(-45deg); }

/* The nav uses backdrop-filter, which makes it the containing block for
   fixed descendants — so the panel is positioned against the nav instead. */
.mobile-panel{
  display:none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: calc(100dvh - 76px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background: var(--bg);
  z-index: 49;
  padding: 32px var(--pad) 48px;
}
.mobile-panel a{
  display:block;
  font-size: 24px;
  font-weight: 600;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.mobile-panel.open{ display:block; }
body.nav-open{ overflow: hidden; }

@media (max-width: 780px){
  .nav-links{ display:none; }
  .nav-toggle{ display:flex; }
}

/* ---------- buttons ---------- */
/* .widget-submit .submit ist der Absende-Button des Formulargenerators. Die
   Klasse wird nicht im Backend gesetzt, weil Contao die CSS-Klasse eines
   Formularfelds auch auf den umgebenden <div> schreibt — der würde dann
   ebenfalls wie ein Button aussehen. */
.btn, .widget-submit .submit{
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 15px;
  border: 1px solid transparent;
  cursor:pointer;
  transition: transform .15s ease, opacity .15s ease, background .15s ease;
}
.btn-primary, .widget-submit .submit{ background: var(--ink); color: var(--bg); }
.btn-primary:hover, .widget-submit .submit:hover{ opacity:.88; }
.btn-outline{ background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn-outline:hover{ background: var(--card); }
/* button, select und summary standen bisher nicht in der Liste — dort griff der
   Standardring des Browsers. Sichtbar wird das nur bei Tastaturbedienung; die
   Optik ist damit einheitlich statt browserabhängig. */
.btn:focus-visible, .widget-submit .submit:focus-visible,
a:focus-visible, input:focus-visible, textarea:focus-visible,
button:focus-visible, select:focus-visible, summary:focus-visible{
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* ---------- sections ---------- */
section{ padding: var(--section-y) 0; }
.section-alt{ background: var(--bg-alt); }
.hairline-top{ border-top: 1px solid var(--line); }
.hairline{ height:1px; background: var(--line); border:none; margin: 0; }

/* ---------- hero ---------- */
.hero{
  display:grid;
  grid-template-columns: 1.05fr .95fr;
  gap: clamp(28px, 5vw, 64px);
  align-items:center;
  padding-top: clamp(40px, 7vw, 80px);
  padding-bottom: clamp(40px, 7vw, 80px);
}
.hero-copy .credibility{
  margin-top: 28px;
  display:inline-flex;
  align-items:center;
  gap:8px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 2px;
}
.hero-copy .credibility:hover{ border-color: var(--ink); }
@media (max-width: 900px){
  .hero{ grid-template-columns: 1fr; }
  .hero-media{ order: -1; }
}

/* Das Bild mobil in den Textblock einsortieren — zwei Varianten.

   Standard ist das Bild über dem gesamten Textblock (.hero-media{order:-1}).
   Mitten hinein kommt man mit `order` allein nicht, weil das Bild ein Geschwister
   von .hero-copy ist und nicht von dessen Kindern. `display: contents` löst den
   Wrapper auf: seine Kinder werden selbst zu Rasterzellen und lassen sich gegen
   das Bild sortieren. Alles hinter dem Ankerelement wandert per
   Geschwisterselektor hinter das Bild, der Rest bleibt in Quellreihenfolge davor.

   `rw-hero-media-mid`      — Anker ist der Lead. Startseite (Bild zwischen Lead
                              und Fließtext) und About (dort steht nichts mehr
                              hinter dem Lead, das Bild schließt den Block ab).
   `rw-hero-media-after-h1` — Anker ist die Überschrift. Die beiden Blogseiten,
                              damit das Bild zwischen h1 und Kategorie-Filtern
                              steht.

   Der Zeilenabstand des Rasters muss dafür auf 0: er läge sonst zwischen jedem
   Absatz. Die Abstände kommen wie bisher aus den Elementen selbst, nur das Bild
   bekommt eigene.
   Der Hero ist von der reveal-Animation ohnehin ausgenommen (siehe dort), das
   fehlende Box-Modell an .hero-copy kostet hier also nichts.
   Beide Klassen werden im Backend im Feld „CSS-Klasse" des Hero-Elements
   gesetzt. */
@media (max-width: 900px){
  .rw-hero-media-mid .hero,
  .rw-hero-media-after-h1 .hero{ row-gap: 0; }

  .rw-hero-media-mid .hero-copy,
  .rw-hero-media-after-h1 .hero-copy{ display: contents; }

  .rw-hero-media-mid .hero-copy > .lede ~ *,
  .rw-hero-media-after-h1 .hero-copy > h1 ~ *{ order: 2; }

  .rw-hero-media-mid .hero-media,
  .rw-hero-media-after-h1 .hero-media{ order: 1; margin: 8px 0 28px; }
}

/* ---------- Spaltenbreite gegen lange Wörter absichern ----------

   fr-Spalten haben implizit min-width:auto, also die Min-Content-Breite. Ein
   einzelnes langes Wort in der Textspalte kann dadurch mehr Platz beanspruchen
   als sein fr-Anteil und die Bildspalte zusammendrücken.

   Aufgefallen an der deutschen Startseite: „Kartellrechtsboutique." misst in der
   Hero-Schriftgröße 606px, der Spaltenanteil sind 519px. Das Hero-Bild war
   dadurch nur 363px breit statt 469px wie in der englischen Fassung — dasselbe
   Bild, gleiche Bildschirmbreite. Knapp war es auch auf der deutschen
   Expertise-Seite: „Wettbewerbsrecht" 507px bei 513px Spaltenbreite.

   min-width:0 nimmt der Textspalte die Möglichkeit, sich die Breite zu holen.
   Damit das lange Wort dann nicht überläuft, wird es getrennt: hyphens:auto
   greift auf die Silbentrennung des Browsers zurück und braucht dafür ein
   lang-Attribut — das steht am <html> je Sprachbaum. Deshalb :lang(de): im
   Deutschen entstehen die langen Komposita, im Englischen gibt es sie nicht,
   und dort soll die Typografie unverändert bleiben.

   overflow-wrap bleibt als letzte Rückfallebene, falls ein Browser für eine
   Sprache keine Trennmuster mitbringt. */
.hero > *,
.row > *{ min-width: 0; }

:lang(de) h1,
:lang(de) h2,
:lang(de) h3{
  -webkit-hyphens: auto;
  hyphens: auto;
}

h1, h2, h3{ overflow-wrap: break-word; }

/* ---------- image placeholders ---------- */
.ph{
  border-radius: var(--radius-lg);
  border: 1.5px dashed var(--line-strong);
  background: linear-gradient(155deg, #EFEAE0 0%, #E3DCC9 100%);
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap: 10px;
  text-align:center;
  color: var(--ink-soft);
  padding: 24px;
  width: 100%;
}
.ph svg{ width:30px; height:30px; opacity:.55; }
.ph .ph-label{ font-size: 13px; font-weight: 600; color: var(--ink-soft); }
.ph .ph-caption{ font-size: 12.5px; color: var(--ink-faint); max-width: 240px; }
.ph-portrait{ aspect-ratio: 4 / 5; }
.ph-square{ aspect-ratio: 1 / 1; }
.ph-wide{ aspect-ratio: 16 / 9; }
.ph-tall-hero{ aspect-ratio: 3 / 4; }
.ph-sm{ border-radius: var(--radius-md); }

/* ---------- pillars / grid cards ---------- */
.pillars{
  display:grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
}
.pillar{ padding-right: 8px; }
.pillar .num{
  font-size: 13px;
  color: var(--ink-faint);
  font-weight: 600;
  margin-bottom: 10px;
  letter-spacing: .1em;
}
@media (max-width: 860px){
  .pillars{ grid-template-columns: 1fr; gap: 32px; }
}

.card-grid{
  display:grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
@media (max-width: 720px){ .card-grid{ grid-template-columns: 1fr; } }
.card{
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 32px;
}

/* ---------- alternating rows (expertise) ---------- */
.row{
  display:grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 5vw, 64px);
  align-items:center;
  padding: 44px 0;
}
.row.reverse .row-media{ order: 2; }
.row.reverse .row-copy{ order: 1; }
@media (max-width: 860px){
  .row, .row.reverse{ grid-template-columns: 1fr; }
  .row .row-media, .row.reverse .row-media{ order: -1; }
}
/* Die Blätterfunktion trägt dieselbe Pillenform wie die Chips. Contao rendert
   sie über eine Twig-Komponente, die per {% use %} eingebunden wird — ein
   Template-Override kann dort kein {% extends %} verwenden. Die Anpassung
   läuft deshalb komplett über CSS auf dem Standard-Markup. */
.tag,
.pagination a,
.pagination strong{
  display:inline-block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--ink-soft);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  padding: 5px 12px;
  margin: 0 8px 8px 0;
}

/* ---------- CTA band ---------- */
.cta-band{
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--radius-lg);
  padding: clamp(36px, 6vw, 64px);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.cta-band h2{ color: var(--bg); margin:0; max-width: 560px; }
.cta-band .btn-primary{ background: var(--bg); color: var(--ink); }

/* ---------- footer ---------- */
footer{
  background: var(--bg-alt);
  border-top: 1px solid var(--line);
  padding: 56px 0 28px;
}
.footer-grid{
  display:grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 32px;
  padding-bottom: 32px;
}
.footer-grid h4, .footer-grid .footer-heading{ font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 14px; }
.footer-grid a{ display:block; font-size: 15px; color: var(--ink); padding: 6px 0; }
.footer-grid a:hover{ color: var(--ink-soft); }
.footer-bottom{
  display:flex;
  justify-content:space-between;
  align-items:center;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-faint);
  flex-wrap: wrap;
  gap: 12px;
}
@media (max-width: 720px){
  .footer-grid{ grid-template-columns: 1fr; }
}

/* ---------- page header (non-home pages) ---------- */
.page-head{
  padding-top: clamp(48px, 8vw, 88px);
  padding-bottom: clamp(24px, 4vw, 40px);
}

/* ---------- experience list ---------- */
.matter-list{ list-style:none; margin:0; padding:0; }
.matter-list li{
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
  display:grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
.matter-list li:first-child{ border-top: 1px solid var(--line); }

/* ---------- form ----------
   Der Entwurf setzt .field-Wrapper, der Contao-Formulargenerator gibt .widget
   aus. Statt die Kern-Templates zu überschreiben, gelten dieselben Regeln für
   beide Klassen — das Formular bleibt damit reines Bordmittel. */
.field, .widget{ margin-bottom: 18px; }
.field label, .widget > label{ display:block; font-size: 13px; font-weight: 600; color: var(--ink-soft); margin-bottom: 6px; }
.field input, .field textarea,
.widget input[type="text"], .widget input[type="email"], .widget input[type="tel"],
.widget input[type="url"], .widget input[type="number"], .widget textarea, .widget select{
  width:100%;
  font-family: var(--font);
  font-size: 15px;
  padding: 13px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--ink);
}
.field textarea, .widget textarea{ resize: vertical; min-height: 120px; }
.field input::placeholder, .field textarea::placeholder,
.widget input::placeholder, .widget textarea::placeholder{ color: var(--ink-faint); opacity: 1; }
.field .req, .widget label .mandatory{ color: var(--ink-soft); }

/* Ankreuzfelder (und Auswahlfelder, gleiches Markup).

   Der Formulargenerator gibt aus:
   div.widget-checkbox > fieldset.checkbox_container > span > input + label.
   Das <fieldset> bringt Rahmen und Innenabstand des Browsers mit — beides muss
   weg, sonst steht die Zeile in einem Kasten, den der Entwurf nicht kennt.

   Die Beschriftung ist hier bewusst Fließtext (15px, volle Textfarbe) und nicht
   die kleine Feldbeschriftung: sie steht neben dem Kästchen und wird gelesen wie
   ein Satz, nicht wie ein Feldname. Die kleine Beschriftung bleibt dem <legend>
   vorbehalten, das Contao nur ausgibt, wenn im Backend ein Feldtitel gesetzt ist.

   Kästchenfarbe über `accent-color` wie beim Antispam-Feld — eine eigene Grafik
   dafür wäre mehr Fläche für Fehler als Gewinn. */
.widget-checkbox .checkbox_container,
.widget-radio .radio_container{
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}
.widget-checkbox legend,
.widget-radio legend{
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  padding: 0;
  margin: 0 0 8px;
}
.widget-checkbox .checkbox_container span,
.widget-radio .radio_container span{
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.widget-checkbox .checkbox_container span + span,
.widget-radio .radio_container span + span{ margin-top: 10px; }

/* flex:none, damit das Kästchen bei mehrzeiliger Beschriftung nicht schrumpft;
   margin-top gleicht die Oberkante optisch an die erste Textzeile an. */
.widget-checkbox input[type="checkbox"],
.widget-radio input[type="radio"]{
  flex: none;
  width: 17px;
  height: 17px;
  margin: 2px 0 0;
  accent-color: var(--ink);
}
.widget-checkbox .checkbox_container label,
.widget-radio .radio_container label{
  display: inline;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.45;
  color: var(--ink);
  margin: 0;
  cursor: pointer;
}

/* Hilfetext (im Entwurf der Vertraulichkeitshinweis unter dem Textfeld) und
   Fehlermeldungen des Formulargenerators. */
.widget .help{ font-size: 14px; color: var(--ink-soft); margin: 8px 0 0; }
.widget .error{ font-size: 14px; color: #b3261e; margin: 0 0 8px; }
.widget input[aria-invalid="true"], .widget textarea[aria-invalid="true"]{ border-color: #b3261e; }

/* Der Absenden-Button trägt im Backend die Klassen „btn btn-primary"; die
   Zeile darunter braucht keinen Abstand mehr. */
.widget-submit{ margin-bottom: 0; }

/* Antispam-Feld: Altcha bringt eigenes CSS mit (assets/altcha/css/altcha.min.css)
   und rendert ins normale DOM, nicht in einen Shadow-Root. Die Optik läuft daher
   über die dokumentierten Custom Properties, damit die Box wie ein Eingabefeld
   des Formulars aussieht; nur Innenabstand und Schriftgröße werden direkt
   nachgezogen, weil Altcha dafür rem-Werte fest verdrahtet. */
.widget-altcha altcha-widget{
  display:block;
  --altcha-color-base: var(--card);
  --altcha-color-border: var(--line-strong);
  --altcha-color-border-focus: var(--ink);
  --altcha-color-text: var(--ink);
  --altcha-color-active: var(--ink);
  --altcha-border-radius: var(--radius-sm);
  --altcha-max-width: 320px;
}
.widget-altcha .altcha-main{ padding: 12px 16px; gap: 10px; }
.widget-altcha .altcha-label{ font-size: 15px; }
.widget-altcha .altcha-checkbox input{ accent-color: var(--ink); }

/* Bestätigung nach dem Absenden. */
.form-confirmation{
  padding: 20px 24px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--card);
}
.form-confirmation > p:first-child{ margin-top: 0; }
.form-confirmation > p:last-child{ margin-bottom: 0; }

/* ---------- reveal-on-scroll ---------- */
/* Progressive enhancement: content is visible by default and only hidden for the
   animation once script.js has confirmed JS is running. Without JS, when printing,
   or if the observer never fires, everything stays readable. */
.js .reveal{ opacity: 0; transform: translateY(14px); transition: opacity .6s ease, transform .6s ease; }
.js .reveal.visible{ opacity: 1; transform: none; }

/* Der erste Bildschirm wird von der Animation ausgenommen.

   Gemessen am 2026-08-10 unter Lighthouse-Mobilbedingungen (4x CPU-Drosselung):
   Der Hero stand von 846ms bis 1699ms auf opacity:0 — rund 850ms, in denen der
   Inhalt fertig geladen, aber unsichtbar war. Ursache ist die Reihenfolge: das CSS
   versteckt .reveal, sobald es geparst ist; sichtbar wird es erst, wenn main.js
   laeuft und der IntersectionObserver feuert.

   WICHTIG zur Einordnung: Ein A/B-Test mit und ohne diese Regel (je 3 Laeufe,
   gleiche Drosselung) ergab **keine** messbare LCP-Verbesserung — die Differenzen
   lagen mit +-24ms im Rauschen. Lighthouse simuliert das Rendern ueber ein
   Netzwerk-/CPU-Modell und beruecksichtigt Opazitaet dabei nicht.

   Diese Regel steht hier also NICHT wegen der Punktzahl, sondern weil eine knappe
   Sekunde unsichtbarer Inhalt oberhalb der Falz auf langsamen Geraeten schlicht
   schlecht ist. Etwas einzublenden, das beim Laden ohnehin schon im Sichtfeld
   steht, bringt gestalterisch nichts. Alles weiter unten animiert unveraendert. */
.js .hero .reveal,
.js .page-head .reveal{ opacity: 1; transform: none; transition: none; }
@media (prefers-reduced-motion: reduce){
  .js .reveal{ opacity:1; transform:none; transition:none; }
  html{ scroll-behavior: auto; }
}
@media print{
  .js .reveal, .reveal{ opacity:1 !important; transform:none !important; }
  .nav, .mobile-panel, .skip-link{ display:none !important; }
  body{ background:#fff; }
  a[href^="http"]::after{ content:" (" attr(href) ")"; font-size:11px; color:#555; }
}

/* ---------- misc ---------- */
.divider-lg{ height: 1px; background: var(--line); margin: 0; border:none; }
.stack > * + *{ margin-top: 14px; }
.center{ text-align:center; }
.mx-auto{ margin-left:auto; margin-right:auto; }
.mt-lg{ margin-top: var(--section-y); }
.note-callout{
  border-left: 3px solid var(--line-strong);
  padding: 4px 0 4px 18px;
  color: var(--ink-soft);
  font-size: 14.5px;
  font-style: italic;
}

/* ---------- brand assets ---------- */
.nav-logo{ display:flex; align-items:center; }
.nav-logo img{ height: 30px; width:auto; display:block; }
/* Die Wortmarke kommt aus der Bildpipeline und damit als <picture> mit <source>.
   Ohne diese Regel steht ein inline-Element zwischen Link und Bild, was die
   Ausrichtung im Flex-Container verschiebt — derselbe Fall wie beim Byline-Avatar
   und beim .photo-frame weiter unten. */
.nav-logo picture,
.footer-mark picture{ display:block; }
.footer-wordmark img{ height: 15px; width:auto; display:block; margin-bottom:14px; opacity:.9; }
.brand-italic{ font-style: italic; }

/* ---------- blog (Between the lines) ---------- */
.blog-filters{ display:flex; flex-wrap:wrap; gap:8px; margin: 20px 0 8px; }
.featured-post{
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(28px, 4vw, 48px);
  margin-bottom: 28px;
}
.post-meta{
  display:flex; gap:14px; align-items:center;
  font-size: 13px; color: var(--ink-faint);
  margin-bottom: 10px;
  flex-wrap:wrap;
}
.post-meta .cat{
  font-weight:600; color: var(--ink-soft);
  border:1px solid var(--line-strong); border-radius:999px; padding:3px 10px;
}
.post-list{ list-style:none; margin:0; padding:0; }
.post-list li{
  padding: 28px 0;
  border-bottom: 1px solid var(--line);
}
.post-list li:first-child{ border-top: 1px solid var(--line); }
.post-list h3 a:hover{ color: var(--ink-soft); }
.readmore{ font-weight:600; font-size:15px; border-bottom:1px solid var(--line-strong); padding-bottom:2px; }
.readmore:hover{ border-color: var(--ink); }
.post-body h2 { max-width: var(--measure); }
.post-body p{ max-width: var(--measure); }
.post-body h3, .post-body h2.h3{ margin-top: 36px; }

/* ---------- language switch ---------- */
.lang-switch{
  display:flex;
  align-items:center;
  gap:6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  margin-left: 8px;
}
.lang-switch a{ color: var(--ink-soft); padding: 4px 2px; }
.lang-switch a.current, .lang-switch a:hover{ color: var(--ink); }
/* Trennstrich zwischen EN und DE. Lag mit --line-strong (#C7BC9F) bei 1.63:1 —
   das ist eine Linienfarbe, hier steht damit aber echter Text (WCAG 1.4.3, A6).
   #716B5B ist der hellste Wert im selben warmen Farbton, der 4.5 noch schafft:
      alt  #C7BC9F  1.63 ✗
      neu  #716B5B  4.57 ✓   (57 % der alten Helligkeit)
   Bewusst nicht --ink-faint: das kippt ins Graubraune der Schrift, der Strich soll
   sichtbar zur Linienfamilie gehoeren und nicht wie ein drittes Wort wirken.
   Die Linien selbst (--line-strong an Raendern) bleiben unveraendert. */
.lang-switch span{ color: #716B5B; }
/* Der <nav>-Wrapper des changelanguage-Moduls wird im Header-Template entfernt
   (er erzeugte zwei unbenannte Navigations-Landmarks je Seite). Die Regeln
   greifen deshalb direkt auf .lang-switch; die .mod_changelanguage-Fassungen
   bleiben als Rückfallebene stehen, falls der Wrapper je zurückkommt. */
@media (max-width: 780px){
  .nav .container > .lang-switch,
  .nav .container > .mod_changelanguage{ display:none; }
}
.mobile-panel .lang-switch{ font-size:16px; }
.mobile-panel .lang-switch a{ padding:6px; }
/* Ersetzt den Inline-Abstand des Entwurfs am mobilen Sprachwechsler. */
.mobile-panel .lang-switch,
.mobile-panel .mod_changelanguage{ margin-top: 20px; }

/* ---------- accessibility ---------- */
/* .invisible ist die Klasse, die Contao für Screenreader-Text vergibt
   (z. B. „Pflichtfeld" vor dem Label im Formulargenerator). */
/* .pagination > p ist Contaos „Seite x von y" — bleibt für Screenreader
   erhalten, im Entwurf gibt es dafür keine sichtbare Entsprechung. */
.sr-only, .invisible, .pagination > p{
  position:absolute;
  width:1px; height:1px;
  padding:0; margin:-1px;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
  border:0;
}

/* ---------- about hero logo mark ---------- */
.about-mark{
  height: 64px;
  width:auto;
  display:block;
  margin: 4px 0 18px;
}

/* ---------- footer mark (RW logo, replacing the wordmark) ---------- */
.footer-mark img{
  height: 34px;
  width: auto;
  display:block;
  margin-bottom: 14px;
  opacity: .92;
}

/* ---------- real photo frames (replacing placeholders) ---------- */
.photo-frame{
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-alt);
}
.photo-frame img{
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---------- byline avatar ---------- */
/* Contao gibt das Bild als <picture> aus und global gilt img{display:block} —
   ohne diese beiden Zeilen bricht der Autorname unter den Avatar. */
.post-meta picture{ display: inline; }
.byline-avatar{
  display: inline-block;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  object-fit: cover;
  vertical-align: middle;
  margin-right: 6px;
  position: relative;
  top: -1px;
}

/* ============================================================
   Contao-Integration — rein additiv, ändert das Design nicht
   ============================================================ */

/* Contao gibt responsive Bilder als <picture> mit <source> aus. Ohne diese
   Regel greift height:100% am <img> nicht mehr, weil das <picture> dazwischen
   keine Höhe hat — der Bildausschnitt im .photo-frame würde zusammenfallen. */
.photo-frame picture{ display:block; width:100%; height:100%; }

/* Hero mit oben ausgerichteten Spalten (Insights-Seite, statt vertikal zentriert) */
.hero-top{ align-items: flex-start; }

/* Band für gestapelte Zeilen in einer Contao-Elementgruppe: übernimmt die
   Aufgabe des <section> im Entwurf (Trennlinie oben, Abstand unten), während
   die Zeilen selbst nur ihren Container mitbringen. Die Klasse wird nicht von
   Hand gesetzt, sondern kommt aus der Template-Variante
   templates/content_element/element_group/rw_band.html.twig. */
.rw-band{ border-top: 1px solid var(--line); padding-bottom: var(--section-y); }

/* Karten-Elemente im Band: 20px Abstand untereinander wie im Entwurf, und der
   Block startet 36px unter der Trennlinie (promise.html: padding-top:36px). */
.rw-cards + .rw-cards{ margin-top: 20px; }
.rw-cards > .card + .card{ margin-top: 20px; }
.rw-band .rw-cards:first-child{ padding-top: 36px; }

/* Textband (v2-Entwurf, Startseite): einzelne, ruhige Karte als Abschnittsbruch.
   Der Entwurf setzt max-width/margin/text-align inline — hier als Klasse, die
   Zentrierung übernehmen die vorhandenen Helfer .mx-auto und .center. */
.card-narrow{ max-width: 660px; }

/* Der Lead kommt aus dem Rich-Text-Editor und bringt eigene <p> mit —
   die äußeren Abstände übernimmt der Wrapper. */
.lede > p:first-child{ margin-top: 0; }
.lede > p:last-child{ margin-bottom: 0; }

/* Textelement-Variante „stack": die Überschrift kommt aus dem Standardfeld und
   trägt keine Klasse, liest aber wie h2.h3 (about.html). */
.stack > h2{ font-size: 20px; }
.stack + .stack{ margin-top: 44px; }

/* Mandatsliste: Abstand zur darüberliegenden Lead-Zeile wie im Entwurf. */
.rw-matterlist .matter-list{ margin-top: 24px; }

/* Zwei-Spalten-Notizen: weiterer Spaltenabstand als beim Kartenraster,
   und die Links tragen die feine Unterlinie aus dem Entwurf.
   Der Entwurf setzt hier ein festes 1fr/1fr-Raster ohne Umbruchpunkt — mobil
   bleibt es dort zweispaltig. Hier bricht es ab 860px auf eine Spalte um. */
.rw-notes .card-grid{ gap: 48px; }
@media (max-width: 860px){ .rw-notes .card-grid{ grid-template-columns: 1fr; gap: 32px; } }
.rw-note-link{ border-bottom: 1px solid var(--line-strong); }

/* Hero mit kompakten Abständen (about.html: section ohne Abstand nach unten,
   Hero-Raster mit kleinerem Abstand nach oben). */
.hero-compact{ padding-bottom: 0; }
.hero-compact .hero{ padding-top: clamp(32px, 6vw, 64px); }

/* Kontaktkarte: Abstand zwischen Porträt und Name wie im Entwurf. */
.rw-contactcard .photo-frame{ margin-bottom: 28px; }

/* ---------- Blog: Contao-Module an den Entwurf angeschlossen ---------- */

/* Die Chips im Hero sind im Entwurf dekorative <span>; hier filtern sie
   tatsächlich, sind also Links. Die aktive Kategorie bleibt ein <span>. */
a.tag:hover{ border-color: var(--ink); color: var(--ink); }
.tag.is-active{ background: var(--ink); border-color: var(--ink); color: var(--bg); }

/* Das Kategorienmodul steht in der Textspalte des Heros und bringt seinen
   eigenen Wrapper mit — der darf keine zusätzlichen Abstände erzeugen. */
.hero-copy .mod_newscategories{ margin: 0; }

/* Beitragsliste: der Entwurf setzt padding-top:36px per Inline-Style. */
.rw-blog-list{ padding-top: 36px; }

/* Leere Kategorie: dieselbe Karte wie der hervorgehobene Beitrag, nur ruhig und
   zentriert — sonst steht die Meldung als nackter Fließtext im Weiß. */
.rw-empty{
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(32px, 5vw, 56px);
  text-align: center;
  color: var(--ink-soft);
}
.rw-empty p{ color: inherit; margin: 0 0 20px; }

/* Blätterfunktion: Form und Farbe kommen aus der .tag-Regel weiter oben, hier
   nur Anordnung, aktive Seite und die Pfeile vor „Zurück" / hinter „Weiter". */
.pagination{ margin-top: 28px; }
.pagination ul{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px;
  list-style:none; margin:0; padding:0;
}
.pagination a, .pagination strong{ margin: 0; }
.pagination a:hover{ border-color: var(--ink); color: var(--ink); }
.pagination strong.active{ background: var(--ink); border-color: var(--ink); color: var(--bg); }
.pagination li.previous a::before{ content: "← "; }
.pagination li.next a::after{ content: " →"; }

/* Beitragsseite: die drei Inline-Styles aus post-example.html als Klassen. */
.rw-post-title{ max-width: 820px; }
.rw-post-body{ padding-top: 40px; }
.rw-post-lede{ max-width: 660px; }
.rw-post-rule{ margin: 48px 0; }

/* Rechtstexte (Impressum, Datenschutz): der Entwurf rückt den Abschnitt dichter
   an den Seitenkopf als die Inhaltsseiten (padding-top:24px am <section> plus
   margin-top:24px am ersten Block). Die Klasse wird im Backend im Feld
   „CSS-Klasse" der Elementgruppe gesetzt, das Band selbst bleibt rw_measure. */
.rw-tight-top{ padding-top: 48px; }

/* Fließtext-Links: a{} setzt global text-decoration:none, im Fließtext wäre ein
   Link sonst nicht als solcher erkennbar. Der Entwurf löst das im Impressum per
   Inline-Style (border-bottom) — hier als Regel. */
.stack a{ border-bottom: 1px solid var(--line-strong); }
.stack a:hover{ border-color: var(--ink); }

/* Links im Lead: dieselbe Begründung wie bei .stack a — global gilt
   text-decoration:none, ein Link im Fließtext wäre sonst nur an der Farbe zu
   erkennen (WCAG 1.4.1). Betrifft in der Praxis die Linkzeile der Fehlerseiten;
   .lede erbt sonst --ink-soft, der Link steht bewusst in voller Textfarbe. */
.lede a{ color: var(--ink); border-bottom: 1px solid var(--line-strong); }
.lede a:hover{ border-color: var(--ink); }

/* Fehlerseiten (404): die Linkzeile „Start · Expertise · Kontakt" steht als
   eigener Absatz im Lead und braucht etwas mehr Luft als ein Fließtextabsatz.
   Die Klasse kommt aus dem Lead-Feld des Seitenkopf-Elements. */
.page-head-links{ margin-top: 22px; }

/* Der Seitenkopf steht auf den Fehlerseiten allein — ohne diese Regel endet der
   Fußbereich auf hohen Fenstern mitten im Bild und darunter bleibt eine leere
   Fläche. Body als Spalte, <main> nimmt den Rest: klassischer Sticky Footer,
   der auf allen anderen Seiten nichts ändert (dort ist der Inhalt länger).
   Das sticky positionierte <header> bleibt als Flex-Element unverändert. */
body{ min-height: 100vh; display: flex; flex-direction: column; }
body > main{ flex: 1 0 auto; }

/* Gruppen-Variante „rw_split_2": zwei gleich breite Spalten. Der Entwurf
   kennt keinen Umbruchpunkt — hier bricht das Raster mobil auf eine Spalte.
   .rw-split ersetzt den Inline-Style padding-top:36px des Entwurfs. */
.rw-split{ padding-top: 36px; }
.rw-split-2{ display: grid; grid-template-columns: 1fr 1fr; gap: 64px; }
@media (max-width: 860px){ .rw-split-2{ grid-template-columns: 1fr; gap: 40px; } }

