/* ==========================================================================
   components.css
   Wiederverwendbare Komponenten: Header/Nav, Footer, CTA-Block, Buttons
   ========================================================================== */

/* --- Site Header ------------------------------------------------------------
   Struktur exakt aus Figma Dev-Mode (m-nav Komponente, per Figma-MCP
   ausgelesen): Logo-Zelle mit eigenem unteren Rand + 3 gerahmte Nav-Boxen
   ("Funktionen"/"Versprechen"/"Kontakt", je mit kleinem Quadrat-Icon), NICHT
   einfache Textlinks mit Hover-Unterstreichung wie in der ersten Version.
   Sprachumschalter (EN/DE) und mobiles Menü kommen in Figma in keiner der
   ausgelesenen Nav-Varianten vor — als 4. (schmalere) Box neben den 3
   Hauptpunkten ergänzt, bitte mit Design gegenchecken, ob das so gewollt ist.
   ---------------------------------------------------------------------- */

.site-header {
  background: var(--surface-light-default);
  /* NICHT sticky (war vorher position:sticky/top:0) — der Footer
     wiederholt dieselbe 3er-Nav, was nur Sinn ergibt, wenn der Header
     normal mit der Seite mitscrollt statt permanent sichtbar zu bleiben. */
  position: relative; /* kein visueller Effekt (kein top/left gesetzt),
    aber eigener Stapelkontext - hebt Header (Linien, Nav-Boxen, Logo)
    über den .experiment-layer, damit die feinen Struktur-Elemente dort
    immer scharf im Vordergrund bleiben statt vom Grün überdeckt zu
    wirken (User-Feedback: sah wie ein Rendering-Fehler aus). */
  z-index: 10000;
}

/* Kontakt-Seite: Header liegt auf dunklem Grund (m-nav / lg-1728 aus dem
   Kontakt-Figma-Frame), exakt wie .feature-grid weiter unten eingefärbt. */
.site-header--dark {
  background: var(--surface-dark-default);
}
.site-header--dark .site-header__logo-cell {
  color: var(--grey-3); /* Test grey-3 statt grey-2, nur auf der
    Kontakt-Seite - siehe .site-header__logo-cell fuer die helle Variante
    (grey-4). */
  border-color: var(--line-dark-subtler); /* gleiche Linienfarbe wie
    Nav-Rahmen/intro-marquee-Trenner, statt dem hellen Standard-Stroke */
}
.site-header--dark .site-nav__link,
.site-header--dark .nav-toggle {
  color: var(--text-inverted-default);
}
.site-header--dark .site-nav__item,
.site-header--dark .nav-toggle {
  border-color: var(--line-dark-subtler);
}
.site-header--dark .site-nav__link:hover,
.site-header--dark .site-nav__link.is-active {
  background: var(--surface-dark-subtlest);
}

.site-header__inner {
  display: flex;
  align-items: center;
  padding: 24px 64px 0 64px; /* KEIN eigenes height:84px mehr (Bug: mit
    box-sizing:border-box blieben von den 84px nur 60px Content-Höhe nach
    Abzug von padding-top übrig — die 84px hohe Nav (Logo-Zelle/Nav-Items
    setzen ihre 84px selbst) ragte dadurch 12px oben UND unten aus dem
    Header heraus. Fiel vorher nicht auf, weil der Header position:sticky
    hatte; seit dem Entfernen von sticky überlappte das sichtbar mit dem
    Hero darunter. Höhe jetzt einfach vom Inhalt bestimmen lassen (wie
    bereits bei den beiden Mobile-Breakpoints unten). */
}

@media (max-width: 900px) {
  .site-header__inner {
    padding: 24px 40px 0 40px;
  }
}
@media (max-width: 600px) {
  .site-header__inner {
    padding: 12px 20px 0 20px;
    align-items: flex-end;
  }
}

.site-header__logo-cell {
  display: flex;
  align-items: flex-end;
  flex: 0 0 38%;
  min-width: 160px;
  box-sizing: border-box;
  height: 84px;
  padding: 8px 8px 28px 0;
  border-bottom: 1px solid var(--line-subtler);
  color: var(--grey-4); /* User-Wunsch: nicht ganz Schwarz, dezenter.
    Farbe hier statt am SVG selbst, damit .site-header--dark
    (Kontakt-Seite) sie wie gewohnt invertieren kann - das Logo erbt sie
    jetzt per currentColor. */
}

.site-header__logo {
  height: 18px; /* exakt aus Figma (Desktop) */
  width: auto;
}

@media (max-width: 600px) {
  .site-header__logo {
    height: 16px; /* exakt aus Figma (Mobile) */
  }
  .site-header__logo-cell {
    height: 56px;
    padding: 8px 8px 22px 0;
  }
}

.site-nav {
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  min-width: 0;
}

.site-nav__list {
  display: flex;
  width: 100%;
}

.site-nav__item {
  flex: 1 0 0;
  display: flex;
  height: 84px; /* muss hier stehen, nicht nur am Link — sonst addiert der
                   1px-Rahmen des Items oben+unten drauf und die Box wird
                   86px hoch statt 84px (Randversatz zur Nachbar-Box) */
  border: 1px solid var(--line-subtler);
  margin-left: -1px;
}
.site-nav__item:first-child {
  margin-left: 0;
}
.site-nav__item--lang {
  flex: 0 0 auto;
  width: 84px; /* User-Wunsch: quadratisch (Höhe ist bereits 84px, siehe
    .site-nav__item) */
}

.site-nav__link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  height: 100%; /* füllt die Höhe des Items (siehe .site-nav__item), nicht fix 84px */
  padding: 8px 12px;
  font-size: var(--fs-copy-small);
  font-weight: var(--fw-regular);
  color: var(--text-default-default);
  white-space: nowrap;
}

.site-nav__link svg {
  width: 12px;
  height: auto; /* arrow-point-right ist kein Quadrat mehr wie das alte square-outline */
  flex-shrink: 0;
}

.site-nav__link:hover,
.site-nav__link.is-active {
  background: var(--surface-light-subtlest);
}

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex: 1 1 auto;
  height: 84px;
  border: 1px solid var(--line-subtler);
  background: none;
  font-size: var(--fs-copy-small);
  font-weight: var(--fw-regular);
  color: var(--text-default-default);
}

.nav-toggle svg {
  width: 12px;
  height: auto; /* arrow-point-right ist kein Quadrat mehr wie das alte square-outline */
  flex-shrink: 0;
}

/* Nav-Boxen weichen ab 900px einem einzelnen "Menü"-Umschalter, exakt wie
   in Figma für m-nav / sm-375 (dort einzige belegte Mobile-Variante). */
@media (max-width: 900px) {
  /* Bleibt layoutmäßig immer als fixes Overlay vorhanden (display:flex),
     offen/zu wird nur über opacity/visibility geschaltet — so kann beim
     Schliessen (z.B. automatisch durchs Scrollen, siehe main.js) sanft
     weggefadet werden, statt hart zu verschwinden. Der "visibility"-Teil
     der transition ist verzögert (0s linear delay), damit das Menü beim
     Schliessen erst nach dem Fade wirklich aus dem Klickfluss/der
     Accessibility-Tree verschwindet, beim Öffnen aber sofort da ist.
     pointer-events zusätzlich abgesichert, falls visibility allein nicht
     ausreicht. */
  .site-nav__list {
    /* Menü schließt direkt an den Header an (User-Wunsch): gleiche Breite
       wie der Header-Inhalt (Seitenrand = .site-header__inner-Padding) und
       Oberkante 1px über dem Header-Unterrand, damit die oberste Menülinie
       exakt auf der Header-Linie (Logo-Zelle/Menü-Button, border-bottom)
       liegt statt eine doppelte Linie zu ergeben. Header-Höhe: 24px Padding
       + 84px Nav = 108px (601-900px), 12px + 56px = 68px (≤600px, siehe
       unten). */
    --site-header-h: 108px;
    --menu-gutter: 40px;
    display: flex;
    flex-direction: column;
    position: fixed;
    top: calc(var(--site-header-h) - 1px);
    left: var(--menu-gutter);
    right: var(--menu-gutter);
    width: auto; /* sonst gewinnt die Desktop-Regel width:100% gegen left/right */
    bottom: auto;
    box-sizing: border-box;
    height: calc(100vh - var(--site-header-h) + 1px);
    height: calc(100dvh - var(--site-header-h) + 1px); /* dvh statt bottom:0,
      sonst verdeckt die einblendende Browser-Leiste (mobile Safari) den
      letzten Menüpunkt */
    background: var(--surface-light-default);
    padding: 0;
    z-index: 99;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.3s ease, visibility 0s linear 0.3s;
  }
  .nav-toggle {
    display: flex;
  }
  /* Kontakt-Seite: Links im Overlay sind hell (siehe .site-header--dark),
     das Overlay selbst war aber immer hell → weiß auf weiß, nur der aktive
     Eintrag war sichtbar. */
  .site-header--dark .site-nav__list {
    background: var(--surface-dark-default);
  }
}
@media (max-width: 600px) {
  .nav-toggle {
    height: 56px;
  }
  .site-nav__list {
    --site-header-h: 68px;
    --menu-gutter: 20px;
  }
}

/* Wenn die mobile Navigation offen ist (JS setzt .nav-is-open auf <body>) */
@media (max-width: 900px) {
  body.nav-is-open .site-nav__list {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.3s ease;
  }
  body.nav-is-open .site-nav__item:not(.site-nav__item--lang) {
    flex: 1 1 0;
    min-height: 0; /* darf schrumpfen, damit alle Punkte auch auf niedrigen Displays passen */
  }
  body.nav-is-open .site-nav__item {
    height: 56px; /* Item-Höhe muss mit dem Link mitwandern, siehe Kommentar oben */
    margin-left: 0;
    margin-top: -1px;
  }
  body.nav-is-open .site-nav__item:first-child {
    margin-top: 0;
  }
  body.nav-is-open .site-nav__item--lang {
    width: 100%; /* im Mobile-Menü volle Breite statt Desktop-Quadrat */
  }
  body.nav-is-open .site-nav__link {
    justify-content: flex-start;
  }
}

/* --- Buttons ---------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: 4px;
  font-size: var(--fs-button-small);
  font-weight: var(--fw-semibold);
  border: 1px solid transparent;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn--primary {
  background: var(--surface-dark-default);
  color: var(--text-inverted-default);
}
.btn--primary:hover {
  background: var(--grey-5);
}

.btn--secondary {
  border-color: var(--stroke-default);
  color: var(--text-default-default);
}
.btn--secondary:hover {
  background: var(--surface-light-subtlest);
}

/* --- Section-Overline (wiederverwendet: Feature-Grid, Teaser-Grid,
   Text-Feature-List, CTA-Block) ---------------------------------------------- */

.section-overline {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  font-size: var(--fs-copy-small);
  font-weight: var(--fw-semibold); /* Figma nutzt "Bold" (700), dafür liegt keine
                                       Schriftdatei vor — Semibold (600) ist die
                                       nächste verfügbare Type-Scale-Stufe */
  margin: 0;
}
.section-overline svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* --- Text-Link ("mehr erfahren", Feature-Grid + Text-Feature-List) ---------- */

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 12px; /* exakt aus Figma, geändert von 16px (space-3) */
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line-subtler);
  font-size: var(--fs-copy-small);
  color: var(--text-default-default);
}
.text-link svg {
  width: 16px; /* exakt aus Figma, geändert von 12px (square-outline → arrow-point-right) */
  height: auto;
  flex-shrink: 0;
}

/* --- Feature-Grid (dunkler Banner, Home) -------------------------------------
   Werte exakt aus Figma Dev-Mode (m-feature-grid, per Figma-MCP ausgelesen).
   ACHTUNG Platzhalter-Content: Titel Nr. 4 heißt wörtlich "Weiteres Feature",
   der Fließtext ist bei allen 4 Kacheln identisch — siehe PROJECT-CONTEXT.md.
   ---------------------------------------------------------------------------- */

.feature-grid {
  background: var(--surface-dark-default);
  color: var(--text-inverted-default);
  padding: 64px 64px 120px 64px;
  display: flex;
  flex-direction: column;
  gap: 80px;
}
.feature-grid .section-overline,
.feature-grid .text-link {
  color: var(--text-inverted-default);
}
.feature-grid .text-link {
  border-bottom-color: var(--line-dark-subtler);
}

.feature-grid__top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-5);
  width: 100%;
  border-top: 1px solid var(--line-dark-subtler);
  padding-top: var(--space-6); /* 40px, exakt aus Figma */
}

.feature-grid__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4); /* 16px, exakt aus Figma */
  max-width: 1195px; /* exakt aus Figma */
}

.feature-grid__intro-text {
  font-size: var(--fs-h2);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  margin: 0;
}
.feature-grid__intro-text .is-muted {
  color: var(--accent-green-text); /* #4DE8A5, geändert von grau — exakt aus Figma */
}

.feature-grid__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); /* Grid statt Flex-Wrap:
    verhindert, dass eine allein umgebrochene Kachel per flex-grow auf volle
    Breite gezogen wird — bei ungleichmäßigem Umbruch bleiben Zellen leer */
  gap: 21px; /* exakt aus Figma */
  width: 100%;
  align-items: stretch; /* explizit statt dem Default "normal" — Kacheln
    sollen unterschiedlich langen Copy-Text trotzdem gleich hoch anzeigen
    (User-Wunsch), siehe .feature-grid__tile unten */
}

/* War früher .feature-tile — Namenskollision mit dem GLEICHNAMIGEN, aber
   völlig anderen .feature-tile in m-feature-select (Funktionen-Seite,
   weiter unten in dieser Datei) behoben: dessen Regeln (u.a.
   aspect-ratio, justify-content:space-between, align-items:center)
   überschrieben durch die spätere Position im Stylesheet ungewollt Teile
   dieser Regel hier, DESHALB wurden die 4 Kacheln unterschiedlich hoch
   UND nicht mehr linksbündig — kein Zufall, sondern genau dieser Bug. */
.feature-grid__tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3); /* 12px zwischen Header (Icon+Titel) und Copy -
    war früher der interne Abstand von .feature-tile__body, siehe dort */
  min-width: 0;
  height: 100%; /* mit align-items:stretch oben zusammen: alle Kacheln in
    einer Zeile gleich hoch, unabhängig von der Copy-Text-Länge */
}

/* Icon + Titel gruppiert (statt Titel+Copy wie vorher in .feature-tile__body)
   - auf Mobile werden Icon+Titel nebeneinander in einer Zeile mit
   Trennlinie darunter dargestellt (User-Wunsch, Figma-Vorlage), auf
   Desktop sieht das dank column-Ausrichtung identisch aus wie vorher
   (Icon oben, Titel darunter). */
.feature-tile__header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-5); /* 32px, war der Abstand icon-box -> body */
  width: 100%;
}

.feature-tile__icon-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 384 / 356; /* exakt aus Figma */
  border: 2px solid var(--line-dark-subtler);
  box-sizing: border-box;
  padding: var(--space-2);
}
.feature-tile__icon-box svg {
  width: 148px;
  height: 148px;
  color: var(--accent-green); /* Icon ist jetzt Outline statt Filled + grün statt weiß/grau, exakt aus Figma */
}
.feature-tile__icon-box svg path {
  fill: none; /* User-Wunsch: home/workspaces/people/projects gibt es nur
    gefüllt (18x18-Icon-Set), hier per CSS in Outline umgewandelt statt
    gefüllte Flächen zu zeigen - überschreibt das fill="currentColor" am
    <path> (Inline-Attribut hat niedrigere Spezifität als jede CSS-Regel). */
  stroke: currentColor;
  stroke-width: 0.55; /* relativ zur 18x18-viewBox, ~gleiche optische
    Strichstärke wie z.B. projects-outline (3.08/104.833 ≈ 0.55/18) */
}

.feature-tile__title {
  font-size: var(--fs-h6);
  font-weight: var(--fw-semibold);
  line-height: 1.35;
  margin: 0;
  padding: 0 var(--space-3) 0 var(--space-1); /* pr-16 pl-4, exakt aus Figma -
    war vorher am umschließenden .feature-tile__body */
}

.feature-tile__copy {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--fs-copy-small);
  line-height: 1.4;
  margin: 0;
  padding: 0 var(--space-3) 0 var(--space-1); /* siehe .feature-tile__title */
  width: 100%;
  box-sizing: border-box;
}
.feature-tile__copy svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 0.2em;
}

@media (max-width: 900px) {
  .feature-grid {
    padding: 40px 40px 64px 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    gap: 48px;
  }
  .feature-tile__icon-box {
    aspect-ratio: auto;
    height: 280px;
  }
}

@media (max-width: 600px) {
  .feature-grid {
    padding-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    padding-right: 20px;
    gap: var(--space-7); /* User-Wunsch: mehr Abstand feature-grid__top ->
      feature-grid__tiles (war 48px vom 900px-Breakpoint geerbt) */
  }
  .feature-grid__tiles {
    gap: 40px; /* User-Wunsch: mehr vertikaler Abstand zwischen den
      Kacheln, die hier einspaltig gestapelt sind (war 21px wie im
      Desktop-Grid) */
  }

  /* Mobile-Layout laut Figma-Vorlage (User-Wunsch): Icon+Titel stehen
     nebeneinander in einer Zeile statt Icon groß/quadratisch über dem
     Titel, darunter eine Trennlinie, dann die Copy volle Breite. Inhalte
     (Titel/Icon/Copy) bleiben unser echter Stand, nur das Layout ändert
     sich. */
  .feature-tile__header {
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    padding-bottom: 0; /* Icon-Unterkante sitzt direkt auf der Trennlinie,
      User-Wunsch - kein Abstand mehr dazwischen */
    border-bottom: 1px solid var(--line-dark-subtler); /* gleicher Ton
      wie der Rahmen der Icon-Box, .feature-grid ist eine dunkle Section */
  }
  .feature-tile__icon-box {
    width: 64px;
    height: 64px;
    flex: 0 0 auto;
    padding: var(--space-2);
    border-width: 1px; /* dünner als der Desktop-Wert (2px), User-Wunsch */
    border-bottom-width: 0; /* die Trennlinie des Headers übernimmt das -
      sonst läge hier eine doppelte Linie (Icon-Rand + Trennlinie) */
  }
  .feature-tile__icon-box svg {
    width: 32px;
    height: 32px;
  }
  .feature-tile__title {
    padding: 0;
  }
  .feature-tile__copy {
    padding: 0;
  }
}

/* --- Teaser-Grid (Projekt-Cards, Home) ---------------------------------------
   Werte exakt aus Figma Dev-Mode (m-teaser-grid, per Figma-MCP ausgelesen).
   Projekte sind ECHT (keine Platzhalter), Bilder sind noch Screenshot-
   Platzhalter — siehe PROJECT-CONTEXT.md. --------------------------------- */

.teaser-grid {
  background: var(--surface-light-default);
  padding: 64px;
  display: flex;
  flex-direction: column;
  gap: 56px; /* exakt aus Figma */
}

/* ZURÜCKGEBAUT (2026-09-23): hier stand testweise `margin-top: -100vh`
   auf .feature-scroll-mobile + .teaser-grid, um den "Leerraum" nach dem
   sticky-Release von m-feature-scroll zu kompensieren. Rechenfehler
   entdeckt (User-Screenshot zeigte echten Overlap): ein Element wird
   sichtbar, sobald es von UNTEN ins Fenster hineinragt — das passiert
   eine volle Bildschirmhöhe VOR seiner eigenen Oberkante. Da das Sticky-
   Element davon nichts weiß und stur bis zu seiner EIGENEN Freigabe-
   Bedingung klebt, entsteht bei JEDEM `margin-top` negativer als -64px
   ein echter Overlap (per Scroll-Messung bestätigt: bei -100vh begann
   der Overlap-Bereich 704px VOR der tatsächlichen Sticky-Freigabe). Der
   "Leerraum", der das eigentlich motivierte, war größtenteils ein
   Artefakt von Voll-Seiten-Screenshot-Tools (sticky-Elemente werden dort
   nicht wie im echten Scrollen "entfaltet", siehe PROJECT-CONTEXT.md) —
   beim tatsächlichen Scrollen ist das, was danach kommt, größtenteils die
   normal wegscrollende zusammengefaltete letzte Zeile, kein echter Gap.
   Falls doch noch ein spürbarer Rest-Abstand stört: NICHT mit negativem
   margin auf teaser-grid lösen (s.o. warum), sondern die Sticky-Fenster-
   Höhe selbst anpassen oder mit dem User erneut per echtem Scrollen
   verifizieren, was genau noch stört. */

.teaser-grid__overline-divider {
  border-bottom: 1px solid var(--line-subtler);
  padding: var(--space-3) 0; /* exakt aus Figma */
  width: 100%;
  box-sizing: border-box;
}

.teaser-grid__cards {
  display: flex;
  gap: var(--space-6); /* User-Wunsch: rechts ca. doppelt so viel Abstand wie
    links (Rahmen -> Text links = --space-4 = 24px, Text -> nächster Rahmen
    rechts jetzt --space-6 = 48px; vorher --space-4) */
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* alte Edge/IE */
}
.teaser-grid__cards::-webkit-scrollbar {
  display: none; /* Chrome/Safari — kein Umbruch mehr, horizontal
    scrollbar statt dessen, der Anschnitt der letzten Kachel zeigt das an
    (User-Wunsch) */
}

/* --- Slider-Steuerung (c-slider, nur Mobile/sm-375, node 181:6092) ------
   Pfeil-Buttons scrollen die Karten per JS (siehe main.js) um eine
   Kartenbreite weiter, der Fortschrittsbalken bekommt pro Karte ein
   Segment und zeigt die aktuell sichtbare Karte an (Segment-Anzahl richtet
   sich live nach der tatsächlichen Kartenzahl im DOM, nicht hart auf 3). */
.teaser-grid__slider {
  display: none; /* nur ≤600px eingeblendet, siehe Media Query unten */
  align-items: center;
  padding-block: 0;
  margin-top: -24px; /* User-Wunsch: näher an die Karten - .teaser-grid hat 40px
    gap zwischen den Blöcken, -24px ergibt 16px Abstand (vorher 40px Gap
    + 40px Padding) */
  width: 100%;
  box-sizing: border-box;
}
.teaser-grid__slider-track {
  min-height: 4px;
  display: flex;
  flex: 1 1 auto;
  gap: 4px;
}
.teaser-grid__slider-segment {
  /* <button> (User-Wunsch: klickbar, springt zur jeweiligen Karte, siehe
     main.js) - Button-Standardlook zurücksetzen */
  border: 0;
  padding: 0;
  cursor: pointer;
  position: relative;
  flex: 1 1 0;
  height: 4px; /* User-Wunsch: etwas dicker (vorher 2px) */
  background: var(--stroke-subtler);
}
.teaser-grid__slider-segment::before {
  content: '';
  position: absolute;
  inset: -14px 0; /* größere Klickfläche (4px Balken allein wäre schwer zu treffen) */
}
.teaser-grid__slider-segment.is-active {
  background: var(--text-default-default);
}

.project-tile {
  flex: 0 0 521px; /* fest statt schrumpfend, exakt aus Figma — erzeugt
    den Anschnitt am Rand statt umzubrechen */
  scroll-snap-align: start;
  border-left: 1px solid var(--line-subtler);
  padding: var(--space-2) 0 var(--space-2) var(--space-4); /* py-8 pl-20, exakt aus Figma */
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--space-6); /* 40px */
  min-width: 0;
}

.project-tile__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-1); /* 4px */
}

.project-tile__title-row {
  display: flex;
  align-items: flex-start; /* User-Wunsch: Titel oben anheften statt mittig;
    die ganze Zeile (Titel + Pfeil) ist jetzt der Link */
  color: inherit;
  min-height: 64px; /* Platz für bis zu 2 Titelzeilen (32px Schrift, line-height 1)
    reservieren, damit Tags/Bild bei allen Karten einer Reihe auf gleicher
    Höhe bleiben, unabhängig davon, ob der Titel umbricht */
}

.project-tile__title {
  font-size: 32px;
  font-weight: var(--fw-regular);
  line-height: 1;
  margin: 0;
  color: var(--text-default-default);
  hyphens: auto; /* Projekttitel kommen live von den Plattformen, teils lange
    Wörter ohne Leerzeichen — Silbentrennung reduziert unschöne Umbrüche */
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2; /* auf max. 2 Zeilen kappen statt beliebig zu wachsen */
  transition: color 0.15s ease;
}
.project-tile__title.is-fitted {
  /* JS (fitProjectTitles in main.js) kürzt den Titel selbst auf 2 Zeilen
     mit "…" + Pfeil dahinter - die CSS-Kappung würde den Pfeil mit
     abschneiden. Ohne JS bleibt die CSS-Kappung als Fallback aktiv. */
  display: block;
  overflow: visible;
}
.project-tile__title-row:hover .project-tile__title {
  color: #21ae71; /* User-Wunsch: grüner Hover; dasselbe Grün wie
    .is-muted-underline (Text auf hellem Grund, --accent-green wäre zu
    blass) */
}
.project-tile__title-row svg {
  width: 24px;
  height: 20px;
  display: inline-block;
  vertical-align: -2px; /* User-Wunsch: leicht unter der Grundlinie war besser als höher */
  margin-left: 12px; /* User-Wunsch: leichter Abstand zum Text. Pfeil schließt
    an das letzte Wort an (steht im Fließtext des Titels) */
  color: var(--text-default-default);
  opacity: 0.5;
  transition: color 0.15s ease, opacity 0.15s ease;
}
.project-tile__title-end {
  white-space: nowrap; /* letztes Wort + Pfeil bleiben zusammen, der Pfeil
    rutscht nie allein in eine neue Zeile */
}
.project-tile__title-row:hover svg {
  color: #21ae71; /* Pfeil neben dem Titel zieht beim Hover mit */
  opacity: 1;
}

.project-tile__authors {
  font-size: var(--fs-copy-small);
  line-height: 1.4;
  margin: 0;
  color: var(--text-default-default);
  min-height: 2.8em; /* Platz für bis zu 2 Zeilen (line-height 1.4 × 2) reservieren,
    in em statt px, damit es mit dem responsiven copy-small mitskaliert —
    gleiches Prinzip wie bei .project-tile__title-row */
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2; /* lange Autoren-Listen aus der API auf 2 Zeilen kappen statt
    beliebig zu wachsen, gleiches Prinzip wie bei .project-tile__title */
}

.project-tile__tags {
  display: flex;
  flex-direction: column;
  gap: var(--space-1); /* 4px */
  align-items: flex-start;
}

.project-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  max-width: 100%; /* Live-Daten aus der API können sehr lange Fachgruppen-/
    Uni-Namen liefern — Tag darf nicht breiter werden als die Karte */
  box-sizing: border-box;
  padding: 4px 8px; /* war 4px 8px 0 8px (0 unten) — dieselbe vertikale
    Zentrierungs-Korrektur wie bei .tag-pill (m-hero), siehe dort für die
    ausführliche Begründung (asymmetrisches Padding verschiebt die
    Content-Box gegenüber der sichtbaren Box-Mitte) */
  border-radius: 4px;
  font-size: var(--fs-copy-small);
  color: var(--text-default-default);
}
.project-tag--outline {
  border: 1px solid var(--line-subtler);
}
.project-tag--filled {
  background: var(--surface-light-subtlest);
  transition: background 0.15s ease, color 0.15s ease;
}
.project-tag--filled:hover {
  background: var(--accent-green); /* User-Wunsch: grüner Hover wie .tag-pill,
    Text immer schwarz (--grey-6, im Darkmode würde --text-default-default
    weiß). Nur die gefüllte Uni-Pille ist ein Link, die Outline-Pille
    (Fachgruppe) ist ein <span> und bekommt bewusst keinen Hover. */
  color: var(--grey-6);
}
.project-tag svg {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
}
.project-tag__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0; /* Flex-Item würde sonst nicht unter Inhaltsbreite schrumpfen
    und die Ellipsis-Kürzung wirkungslos bleiben */
}

.project-tile__image {
  background: var(--surface-light-subtlest); /* Platzhalterfarbe, solange das Bild noch lädt */
  width: 100%;
  height: 364px; /* exakt aus Figma */
  overflow: hidden; /* schneidet ab, was object-fit nicht ins Format quetscht */
  box-sizing: border-box;
}

.project-tile a,
.project-tile__image-img {
  -webkit-user-drag: none; /* kein "Link/Bild ziehen"-Geisterbild beim Wischen mit der Maus */
}
.sk {
  background: var(--surface-light-subtlest); /* Platzhalter-Balken der Skeleton-Karten, solange die Projekte laden */
  border-radius: 4px;
}
.project-tile--skeleton .project-tile__authors {
  margin: 0;
}
.project-tile__image picture {
  display: block;
  width: 100%;
  height: 100%;
}
.project-tile__image-img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* füllt die Fläche unabhängig vom Quellformat, ohne zu verzerren */
  display: block;
}

@media (max-width: 900px) {
  .teaser-grid {
    padding: 40px 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    gap: 40px;
  }
  .project-tile__image {
    height: 240px;
  }
}

@media (max-width: 600px) {
  .teaser-grid {
    padding-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    padding-right: 20px;
  }
  /* Update nach Figma-Änderung (m-teaser-grid / sm-375, node 181:6092):
     Karten bleiben AUCH auf Mobile horizontal scrollbar/swipebar (nicht
     mehr gestapelt, siehe Git-Historie für die vorherige Stapel-Variante)
     — dafür jetzt mit eigenen Pfeil-Buttons + Fortschrittsbalken darunter
     (.teaser-grid__slider), da Wisch-Gesten allein auf einer Content-Seite
     nicht selbsterklärend sind. */
  /* User-Wunsch: die Pfeil-Navigation war nicht selbsterklärend. Stattdessen
     eine etwas schmalere Karte, von der nächsten schaut rechts ein Streifen
     (~48px) heraus - das signalisiert "hier geht's weiter", ohne Buttons.
     Der Scroll-Bereich läuft dafür bis zum rechten Bildschirmrand (negativer
     Margin gleicht das 20px-Seitenpadding aus), die erste Karte bleibt am
     linken Seitenrand ausgerichtet. Snap "mandatory": eine Karte rastet
     immer ganz sichtbar ein. */
  .teaser-grid__cards {
    gap: var(--space-4);
    margin-right: -20px;
    padding-right: 20px; /* letzte Karte endet mit 20px Rand statt bündig am Bildschirmrand */
    scroll-snap-type: x mandatory;
  }
  .project-tile {
    flex: 0 0 calc(100vw - 92px); /* 20px Rand links + 24px Gap + ~48px Anschnitt */
  }
  .teaser-grid__slider {
    display: flex;
  }
}

/* --- Text-Feature-List / Versprechen-Teaser (Home) ---------------------------
   Werte exakt aus Figma Dev-Mode (m-text-feature-list, per Figma-MCP
   ausgelesen). ACHTUNG Platzhalter-Content: Intro-Headline und Fließtext
   aller 3 Punkte sind wortgleich — siehe PROJECT-CONTEXT.md. ---------------- */

.promise-teaser {
  background: var(--surface-light-default);
  padding: 40px 64px 120px 64px;
  display: flex;
  flex-direction: column;
}

.promise-teaser__overline-divider {
  border-bottom: 1px solid var(--line-subtler);
  padding: var(--space-3) 0;
  width: 100%;
  box-sizing: border-box;
}

.promise-teaser__content {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--space-6);
}

.promise-teaser__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4); /* 24px, exakt aus Figma */
  padding-top: var(--space-6); /* 48px, exakt aus Figma */
  max-width: 655px; /* exakt aus Figma */
}

.promise-teaser__intro-text {
  font-size: var(--fs-h2);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  margin: 0;
}

.promise-list {
  display: flex;
  flex-direction: column;
  max-width: 845px; /* exakt aus Figma */
  flex: 1 1 480px;
  min-width: 0;
}

.promise-item {
  display: flex;
  align-items: flex-start;
  gap: 25px; /* exakt aus Figma */
  border-bottom: 1px solid var(--line-subtler); /* war border-block (oben
    UND unten) — dadurch doppelte Linie zwischen zwei Items (unterer Rand
    von Item N + oberer Rand von Item N+1). Nur noch unten, User-Wunsch. */
  padding: var(--space-5); /* 40px, exakt aus Figma */
  box-sizing: border-box;
}
.promise-item:last-child {
  border-bottom: none; /* User-Wunsch: letztes Item ohne Trennlinie */
}

.promise-item__body {
  display: flex;
  flex-direction: column;
  gap: 91px; /* exakt aus Figma (großer Abstand Titel → Fließtext) */
  flex: 1 1 auto;
  min-width: 0;
}

.promise-item__title {
  font-size: var(--fs-h2);
  font-weight: var(--fw-semibold);
  letter-spacing: -0.2px;
  line-height: 1.15;
  margin: 0;
}

.promise-item__copy {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--fs-copy-small);
  line-height: 1.4;
  margin: 0;
}
.promise-item__copy svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 0.2em;
}

.promise-item__icon {
  width: 90px;
  height: 90px;
  flex-shrink: 0;
  color: var(--text-default-default);
}

@media (max-width: 900px) {
  .promise-teaser {
    padding: 40px 40px 64px 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  }
  .promise-teaser__content {
    flex-direction: column;
  }
  .promise-teaser__intro {
    max-width: none;
    padding-top: var(--space-5);
  }
  .promise-list {
    max-width: none;
    width: 100%;
  }
  .promise-item {
    flex-direction: column;
  }
  .promise-item__body {
    gap: var(--space-4);
  }
  .promise-item__icon {
    width: 60px;
    height: 60px;
    align-self: flex-end; /* User-Wunsch (mobil/gestapelt): Icon rutscht an den rechten Rand */
  }
}

@media (max-width: 600px) {
  .promise-teaser {
    padding-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    padding-right: 20px;
  }
}

/* --- CTA-Block / m-contact (dunkler Bereich vor dem Footer) ------------------
   Werte exakt aus Figma Dev-Mode (m-contact, per Figma-MCP ausgelesen).
   Ersetzt die frühere Platzhalter-Version (3 kleine Buttons) — Figma zeigt
   stattdessen 3 große gerahmte Karten. ------------------------------------- */

.cta-block {
  background: var(--surface-dark-default);
  color: var(--text-inverted-default);
  padding: 120px 64px; /* exakt aus Figma */
  display: flex;
  flex-direction: column;
  gap: 96px; /* exakt aus Figma */
}

.cta-block__top {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-5); /* 32px, exakt aus Figma */
  width: 100%;
}

.cta-block__overline-divider {
  border-bottom: 1px solid var(--line-dark-subtler);
  width: 100%;
  padding: var(--space-3) 0;
  box-sizing: border-box;
}

.cta-block__heading {
  font-size: var(--fs-h2);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  margin: 0;
  max-width: 1214px; /* exakt aus Figma */
}

.cta-block__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); /* Grid statt Flex-Wrap,
    siehe .feature-grid__tiles-Kommentar */
  gap: var(--space-4); /* 20px, exakt aus Figma */
  width: 100%;
}

.cta-card {
  border: 1px solid var(--line-dark-subtler);
  min-width: 0;
  height: 290px; /* exakt aus Figma */
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--space-5) var(--space-4); /* py-32 px-24, exakt aus Figma */
  color: var(--text-inverted-default); /* war an .cta-card__link - jetzt
    hier, damit Label + Link-Text auf Hover gemeinsam umfärben (color:
    inherit an beiden Kindern) */
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.cta-card:hover {
  background: var(--accent-green); /* User-Wunsch: ganze Karte verlinkt +
    Hover grün - dunkler Text/Icon auf Grün statt dem bisherigen hellen
    Text auf dunklem Grund, analog zu .feature-tile.is-active */
  border-color: transparent;
  color: var(--grey-6);
}

.cta-card__label {
  font-size: var(--fs-copy-small);
  padding-left: var(--space-3);
  color: inherit;
}
.cta-card__link {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--space-3);
  color: inherit; /* war var(--text-inverted-default), jetzt an .cta-card */
}

.cta-card__link-line {
  display: block;
  font-size: var(--fs-h2);
  font-weight: var(--fw-semibold);
  letter-spacing: -0.2px;
  line-height: 1.15;
  margin: 0;
}
.cta-card__link-line--arrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 15px; /* exakt aus Figma */
}

.cta-card__arrow {
  width: 37px;
  height: 9px;
  flex-shrink: 0;
}

@media (max-width: 900px) {
  .cta-block {
    padding: 64px 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    gap: 48px;
  }
}

@media (max-width: 600px) {
  .cta-block {
    padding-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    padding-right: 20px;
  }
}

/* --- Hero / Intro (Home) ----------------------------------------------------
   Struktur + Werte exakt aus Figma Dev-Mode (m-intro Komponente, per
   Figma-MCP ausgelesen).

   Die 3 Deko-Icons standen in Figma an absoluten Pixelkoordinaten, die aber
   nur deshalb passen, weil der Original-Text manuelle Leerzeichen als
   Platzhalter für die Icon-Breite enthält (z.B. "    Plattform für"). Ohne
   diesen Hack lag das Icon über dem Text. Deshalb hier stattdessen: Icons
   fließen inline mit dem Text (je Zeile ein eigener Flex-Container) — nicht
   pixelgenau wie in Figma, aber robust bei jeder Breite/Umbruch und ohne
   Überlappung. -------------------------------------------------------- */

.hero {
  padding: 0 var(--space-7) var(--space-2) var(--space-7);
}

.hero__inner {
  display: flex;
  align-items: flex-end; /* zurück auf unten bündig (Figma-Original) — die
    eigentliche Ursache für das Nach-oben-Wachsen war ein anderer Bug (siehe
    .site-header__inner), nicht dieser Wert. Die Hochschul-Box bleibt damit
    unten angedockt und behält ihre eigene, natürliche Höhe (kein Stretchen
    auf die Zeilenhöhe, sonst wirkt sie bei kurzen Listen unschön
    aufgebläht); .hero__intro bekommt stattdessen align-self:stretch (siehe
    dort), damit bei einer LANGEN Hochschul-Liste nicht die Box nach oben,
    sondern der Freiraum zwischen Headline und .hero__lead nach unten
    wächst — .hero__lead rutscht mit runter statt dass es eine Kollision
    mit dem Header gibt. */
  flex-wrap: wrap;
  gap: 0; /* Intro-Spalte + Hochschul-Box sollen IMMER lückenlos aneinanderstoßen (Rahmen der
             Intro-Spalte reicht dadurch bis zur Box) UND die Box soll — wie Nav/Hero-Bild —
             rechts bündig mit dem Seitenrand abschließen. Deshalb wächst die Intro-Spalte
             unbegrenzt (kein max-width mehr) und füllt exakt den Platz, der nach der fest
             655px breiten Box übrig bleibt, statt beide auf 945+655=1600px (Figma bei 1728px
             Frame-Breite) zu deckeln. */
}

.hero__intro {
  flex: 1 1 945px;
  min-width: 945px; /* nie schmaler quetschen als die Figma-Breite — sonst bricht die 96px-Headline
                        Wort für Wort um (siehe z.B. 1512px MacBook-Breite). Passt kein Platz mehr für
                        Intro(945px)+Box(655px) nebeneinander, bricht die Zeile stattdessen komplett um
                        (flex-wrap oben) und beide stehen untereinander wie im Figma-Tablet-Layout. */
  align-self: stretch; /* füllt die volle Zeilenhöhe (= Höhe der Hochschul-
    Box, wenn die länger ist als Headline+Lead) — dadurch kann .hero__lead
    unten (margin-top:auto) nach unten rutschen, siehe dort */
  display: flex;
  flex-direction: column;
}

.hero__heading-row {
  padding: 72px 64px 64px 0; /* exakt aus Figma */
}

.hero__heading {
  font-size: var(--fs-headline-decorative);
  font-weight: var(--fw-ultrabold);
  line-height: 1; /* User-Wunsch */
  letter-spacing: -0.48px; /* exakt aus Figma Dev-Mode (Desktop 96px) */
  margin: 0;
  max-width: 945px; /* exakt aus Figma — bleibt gedeckelt, auch wenn die Intro-Spalte selbst breiter wird */
}

/* Zwischenbereich Tablet (900px) bis Figma-Desktop (1728px), z.B. MacBook 14"
   bei 1512px: Bei voller 96px-Größe bleibt der Intro-Spalte dort zu wenig
   Platz neben der 655px breiten Hochschul-Box (nur noch ~700-750px statt
   945px) — dann bricht die Zeile nach fast jedem Wort einzeln um. Deshalb
   hier testweise kleinere Schrift + passend reduzierte Mindestbreite, damit
   die 2-Spalten-Ansicht bei typischen Laptop-Breiten erhalten bleibt statt
   zu früh umzubrechen. Nicht aus Figma (dort nur 1728px + 900px bekannt) —
   bitte visuell gegenchecken, ob 80px/670px gut aussieht oder nachjustiert
   werden muss. */
@media (max-width: 1720px) and (min-width: 901px) {
  .hero__heading {
    font-size: 80px;
    letter-spacing: -0.4px;
  }
  .hero__intro {
    /* flex-basis (nicht nur min-width!) muss mit runter, sonst rechnet
       flex-wrap beim Umbruch-Entscheid weiterhin mit der 945px-Basis aus
       der Grundregel und bricht trotzdem um. */
    flex: 1 1 670px;
    min-width: 670px;
  }
}

/* Figmas manuelle Zeilenumbrüche ("Plattform für" / "gestaltende
   Hochschulen &" / "Universitäten") passen nur, weil dort die Textbox frei
   überlaufen darf. Im Responsive-Layout lassen wir den Text stattdessen
   natürlich fließen/umbrechen — die Icons hängen an ihrem Ankerwort statt
   an einer festen Zeile, dadurch gibt es bei keiner Breite mehr ein
   Überlaufen/Überlappen mit der Hochschul-Box. */
.hero__heading-icon {
  display: inline-block;
  width: 0.68em; /* Rollback auf feste quadratische Box (width:auto liess
    die breiten Icons wie workspace-filled/72x30 zu groß werden, brachte
    den Zeilenumbruch bei "Hoch-" durcheinander). Optischer Ausgleich
    (User-Feedback): people-filled (1. Icon) besteht aus 4 Kreisen, die
    exakt an den Rand der Box stoßen - wirkt dadurch voller/größer als
    projects-filled (3. Icon, 4 Rechtecke MIT Lücken dazwischen), obwohl
    beide dieselbe Boxgröße haben. Default etwas kleiner, das letzte
    Icon per :last-of-type wieder größer, siehe unten. */
  height: 0.68em;
  vertical-align: -0.02em;
  color: var(--text-default-default);
}
.hero__heading-icon:last-of-type {
  width: 0.75em;
  height: 0.75em;
}

.hero__lead {
  border-block: 1px solid var(--line-subtler);
  padding-block: var(--space-6);
  width: 100%; /* Rahmen zieht sich über die ganze Intro-Spalte bis zur Hochschul-Box, exakt aus Figma */
  box-sizing: border-box;
  margin-top: auto; /* schiebt sich innerhalb der (gestretchten) Intro-Spalte
    nach unten, sobald die Hochschul-Box höher ist als Headline+Lead
    zusammen — dadurch bleibt der untere Rand von Lead und Box immer auf
    gleicher Höhe, ohne dass die Box nach oben wachsen muss */
}

.hero__lead-text {
  font-size: var(--fs-copy-display);
  font-weight: var(--fw-regular);
  line-height: 1.35; /* 135%, exakt aus Figma Dev-Mode */
  margin: 0;
  max-width: 723px; /* Lesebreite, exakt aus Figma — Rahmen bleibt aber volle Breite */
}

.hero__partners {
  display: flex;
  flex-direction: column;
  gap: var(--space-4); /* exakt aus Figma (right-wrapper) */
  width: 655px;
  max-width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--line-subtler);
  padding: var(--space-6); /* exakt aus Figma (right-wrapper) */
}

/* Unterhalb von ca. 1453px reicht auch die reduzierte 670px-Breite nicht
   mehr neben der 655px-Box (670+655+128 Rand = 1453px) — dann bricht
   hero__partners in die nächste Zeile um. Bleibt dabei trotzdem rechts
   ausgerichtet (wie Nav/Hero-Bild), statt links/volle Breite wie bei
   echtem Mobile. Oberer Rand der Box weg, weil sonst zusammen mit dem
   unteren Lead-Rahmen eine doppelte Linie entsteht.
   WICHTIG: muss NACH den jeweiligen Grundregeln stehen (border-Shorthand
   dort überschreibt sonst wieder, gleiche Spezifität + spätere Reihenfolge
   gewinnt). */
@media (max-width: 1452px) and (min-width: 901px) {
  .hero__partners {
    margin-left: auto;
  }
}
/* Oberer Rand der Box immer weg (ab 901px): entweder liegt sie direkt unter
   dem Nav-Rahmen (Desktop, neben dem Intro) oder unter dem Lead-Rahmen
   (umgebrochen) — beides ergäbe eine doppelte Linie. */
@media (min-width: 901px) {
  .hero__partners {
    border-top: none;
  }
}

.hero__overline {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-copy-small);
  font-weight: var(--fw-semibold);
  margin: 0;
}

.hero__overline svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2); /* exakt aus Figma Dev-Mode (tag-wrapper) */
}

.tag-list li {
  min-width: 0; /* Flexbox-Fallstrick: ein Flex-Item schrumpft standardmäßig
    nicht unter seine "min-content"-Breite (bei Text = Breite des längsten
    Worts, da Text an Wortgrenzen umbrechen kann) — genau DAS ließ den
    Hochschulnamen bisher innerhalb der Pille mehrzeilig umbrechen, statt
    dass die Pille schmal bleibt und der Text abgeschnitten wird. */
}
.tag-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 40px; /* war fix height:40px — siehe .tag-pill__label unten
    für die eigentliche Ein-Zeilen-Lösung (Ellipsis statt Umbruch) */
  min-width: 0; /* siehe Kommentar bei .tag-list li */
  max-width: 100%; /* darf nicht breiter werden als sein Container, sonst
    greift der min-width:0-Schrumpf-Mechanismus unten nicht */
  padding: 8px 12px; /* war 8px 12px 0 12px (0 unten) — dadurch lag die
    vertikale Mitte des Inhalts spürbar unter der Mitte der Pille
    (User-Feedback "vertikal mittig zentrieren"), symmetrisch behebt das */
  border-radius: 4px;
  background: var(--surface-light-subtlest);
  color: var(--text-default-default);
  font-size: var(--fs-copy-display);
  box-sizing: border-box;
  transition: background 0.15s ease, color 0.15s ease;
}
.tag-pill:hover {
  background: var(--accent-green); /* User-Wunsch: grüner Hover, Text immer
    schwarz (--grey-6), da --text-default-default im Darkmode weiß wird */
  color: var(--grey-6);
}
.tag-pill:hover svg {
  color: var(--grey-6);
}

.tag-pill__label {
  overflow: hidden;
  white-space: nowrap; /* User-Wunsch: kein Umbruch mehr, stattdessen... */
  text-overflow: ellipsis; /* ...Abschneiden mit "…", wenn der Hochschulname
    nicht in die verfügbare Breite passt */
  min-width: 0; /* derselbe Flexbox-Fallstrick wie bei .tag-pill/li oben,
    ohne das würde text-overflow:ellipsis nie greifen */
}

.tag-pill svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--text-default-subtlest);
}

@media (max-width: 900px) {
  .hero {
    padding: 0 40px var(--space-2) 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  }
  .hero__heading-row {
    padding: var(--space-6) 0 var(--space-4) 0;
  }
  .hero__intro {
    /* Grundregel setzt min-width/flex-basis:945px fürs Desktop-Layout — ohne
       Reset hier zwingt das den Container auch auf schmalen Handys auf
       945px Breite, wodurch der Text seitlich über den Rand hinausläuft. */
    flex-basis: auto;
    min-width: 0;
  }
  .hero__partners {
    width: 100%;
  }
  .hero__lead {
    border-bottom: none; /* exakt aus Figma: ab md-900 nur noch oberer Rahmen */
  }
}

@media (max-width: 600px) {
  .hero {
    padding: 0 20px var(--space-2) 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  }
  .hero__partners {
    padding: var(--space-4);
  }
}

/* --- Hero Media (Bild unter dem Intro) -------------------------------------- */

.hero-media {
  padding: var(--space-6) var(--space-7); /* exakt aus Figma Dev-Mode (m-media) */
}

@media (max-width: 900px) {
  .hero-media {
    padding: var(--space-6) 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  }
}

@media (max-width: 600px) {
  .hero-media {
    padding: var(--space-4) 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  }
}

.hero-media__img {
  width: 100%;
  height: auto;
  display: block;
}

@media (max-width: 600px) {
  .hero-media {
    padding: var(--space-4);
  }
}

/* --- Site Footer ------------------------------------------------------------
   Struktur + Werte exakt aus Figma Dev-Mode (m-footer Komponente, per
   Figma-MCP ausgelesen). Footer-Nav ist bewusst dieselbe 3er-Box-Optik wie
   der Header (Funktionen/Versprechen/Kontakt) — KEIN separates Legal-Menü
   an dieser Stelle, das kommt weiter unten als einfache Unterstrich-Links
   (Twitter/Impressum/Datenschutz). Kein Copyright-Zeile, da in Figma nicht
   vorhanden. -------------------------------------------------------------- */

.site-footer {
  background: var(--surface-light-default);
}

.site-footer__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 80px; /* exakt aus Figma (Desktop) */
  padding: 80px 64px; /* exakt aus Figma (Desktop) */
}

.site-footer__top {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-5); /* 32px, exakt aus Figma */
  width: 100%;
}

.site-footer__row {
  display: flex;
  align-items: center;
  width: 100%;
}

.site-footer__logo-cell {
  display: flex;
  align-items: flex-end;
  height: 84px;
  flex: 0 0 636px; /* exakt aus Figma */
  max-width: 100%;
  box-sizing: border-box;
  padding: 8px 8px 8px 0;
  border-top: 1px solid var(--line-subtler);
}

.site-footer__logo {
  height: 56px; /* exakt aus Figma (Desktop) */
  width: auto;
  color: var(--grey-2); /* exakt aus Figma (#CECED0) — heller als der Header-Logo-Standard */
}

/* Zwischenbereich Tablet (900px, dort greift schon die volle Mobile-
   Stapelung) bis Figma-Desktop (1728px), z.B. iPad Pro bei 1024px: die
   feste 636px-Logo-Zelle lässt der Nav daneben kaum noch Platz (bei
   1024px z.B. nur ~260px für 3 Items übrig), Menüpunkte brechen um.
   Deshalb hier Logo-Zelle + Logo verkleinert, exakt das gleiche Muster
   wie beim Hero-Heading weiter oben (kein Figma-Wert für diese
   Zwischenbreite bekannt, bitte visuell gegenchecken). */
@media (max-width: 1300px) and (min-width: 901px) {
  .site-footer__logo-cell {
    flex: 0 0 280px;
  }
  .site-footer__logo {
    height: 36px;
  }
}

.footer-nav {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
}

.footer-nav__list {
  display: flex;
  width: 100%;
}

.footer-nav__item {
  flex: 1 0 0;
  display: flex;
  height: 84px; /* muss hier stehen, nicht nur am Link — sonst addiert der
                   1px-Rahmen des Items oben+unten drauf, siehe .site-nav__item */
  border: 1px solid var(--line-subtler);
  margin-left: -1px;
}
.footer-nav__item:first-child {
  margin-left: 0;
}

.footer-nav__link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  height: 100%; /* füllt die Höhe des Items (siehe .footer-nav__item), nicht fix 84px */
  padding: 8px 12px;
  font-size: var(--fs-copy-small);
  font-weight: var(--fw-regular);
  color: var(--text-default-default);
}
.footer-nav__link svg {
  width: 12px;
  height: auto; /* arrow-point-right ist kein Quadrat mehr wie das alte square-outline */
  flex-shrink: 0;
}
.footer-nav__link:hover,
.footer-nav__link.is-active {
  background: var(--surface-light-subtlest);
}

.site-footer__text {
  max-width: 540px; /* exakt aus Figma */
  color: var(--text-default-default);
}

.site-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: flex-end; /* war space-between, solange noch das
    "100% Facebook free"-Badge links stand (User-Wunsch: entfernt, siehe
    footer.php) — mit nur noch einem Kind (.site-footer__links) würde
    space-between es sonst nach links rutschen lassen statt rechtsbündig
    wie zuvor stehen zu bleiben. */
  width: 100%;
  padding-top: var(--space-4); /* 24px, exakt aus Figma */
  border-top: 1px solid var(--line-subtler);
}

.site-footer__links {
  display: flex;
  align-items: center;
  gap: var(--space-7); /* 64px, exakt aus Figma (Desktop) */
}

.site-footer__link {
  padding: var(--space-2);
  font-size: var(--fs-copy-small);
  color: var(--text-default-default);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.site-footer__link:hover {
  color: var(--text-default-subtlest);
}

@media (max-width: 900px) {
  .site-footer__inner {
    gap: var(--space-7); /* 64px, exakt aus Figma (Mobile) */
    padding: 40px 20px; /* exakt aus Figma — 40/20 liegen NICHT auf der 8er-Skala,
      darum hier literal statt var(--space-6)/var(--space-4) (48/24, falscher Wert) */
  }
  .site-footer__row {
    flex-direction: column;
  }
  .site-footer__logo-cell {
    flex: none;
    width: 100%;
    justify-content: center;
    height: auto;
    padding: var(--space-5) 0;
  }
  .site-footer__logo {
    height: 38px; /* exakt aus Figma (Mobile) */
  }
  /* Jetzt wie in Figma (m-footer / sm-375): 3 volle Boxen gestapelt.
     War vorher ausgeblendet (Header war sticky, Nav dort immer erreichbar)
     — jetzt wo der Header wieder normal mitscrollt, macht die Wiederholung
     unten wieder Sinn (User-Wunsch). */
  .footer-nav {
    display: flex;
    width: 100%;
  }
  .footer-nav__list {
    flex-direction: column;
    width: 100%;
  }
  .footer-nav__item {
    width: 100%;
    margin-left: 0;
    margin-top: -1px; /* Rahmen-Überlappung jetzt vertikal statt horizontal */
  }
  .footer-nav__item:first-child {
    margin-top: 0;
  }
  .site-footer__bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
  }
  .site-footer__links {
    align-items: center;
    justify-content: space-between; /* Datenschutz rechtsbündig (User-Wunsch) */
    width: 100%;
    gap: var(--space-3); /* 16px, exakt aus Figma (Mobile) */
    /* Impressum + Datenschutz stehen mobil nebeneinander (User-Wunsch,
       weicht von der gestapelten Figma-Variante ab). */
  }
}

/* --- 2-Spalten-Intro (Funktionen-Seite, m-intro/2-column-text) --------------
   Werte exakt aus Figma Dev-Mode, per Figma-MCP ausgelesen. -------------- */

.intro-2col {
  padding: 80px 64px 0 64px; /* exakt aus Figma */
  display: flex;
  flex-direction: column;
  gap: var(--space-7); /* 80px, exakt aus Figma */
}

.intro-2col__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 162px; /* exakt aus Figma */
  padding-inline: var(--space-4); /* 24px, exakt aus Figma */
}

.intro-2col__heading {
  flex: 1 1 0;
  min-width: 280px;
  font-size: 64px;
  font-weight: var(--fw-ultrabold);
  letter-spacing: -0.96px;
  line-height: 1;
  margin: 0;
}

.intro-2col__lead {
  flex: 1 1 0;
  min-width: 280px;
  font-size: var(--fs-h4);
  font-weight: var(--fw-regular);
  line-height: 1.2;
  margin: 0;
}
.intro-2col__lead .is-muted-underline {
  color: #21ae71; /* User-Wunsch: grün statt grau (#76777A) */
  text-decoration: underline;
  text-underline-offset: 2px;
}

.intro-2col__divider {
  border-top: 1px solid var(--line-subtler);
  width: 100%;
}

@media (max-width: 900px) {
  .intro-2col {
    padding: var(--space-6) 40px 0 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    gap: var(--space-6);
  }
  .intro-2col__row {
    flex-direction: column;
    align-items: flex-start;
    padding-inline: 0;
    gap: var(--space-5);
  }
  .intro-2col__heading,
  .intro-2col__lead {
    min-width: 0;
    width: 100%;
  }
  .intro-2col__heading {
    font-size: 40px;
    letter-spacing: -0.4px;
  }
}

@media (max-width: 600px) {
  .intro-2col {
    padding-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    padding-right: 20px;
  }
}

/* --- Text-Scroll (Funktionen-Seite, m-text-scroll) ---------------------------
   Gepinnte Sektion: .text-scroll-pin reserviert 300vh Scroll-Budget, der
   sichtbare Inhalt (.text-scroll-pin__sticky) bleibt per position:sticky
   fixiert, während im Hintergrund gescrollt wird — dieselbe Technik wie
   bei godaylight.com/about (siehe m-feature-scroll-Recherche). Dadurch
   haben wir volle, planbare Kontrolle über die Scroll-Distanz statt uns
   auf die tatsächliche (kleine) Höhe der Textzeilen verlassen zu müssen
   (mehrere Fehlversuche vorher, siehe Git-Historie).
   Phasen innerhalb der gepinnten Zeit (0-25%/75-100% = Ein-/Ausblenden,
   noch nicht gepinnt):
   - 25%-50%: Wort-Reveal, gedimmter Text (--text-scroll-muted) wird
     Wort für Wort schwarz, per CSS Scroll-Driven Animation
     (animation-timeline an --text-scroll-progress gebunden), kein JS
   - 50%-75%: schwebende Icons/Bild aus Figma parallaxen nach oben
   Alle Prozentwerte kommen aus PHP ($textScrollTextPhaseStart etc. in
   funktionen.php/features.php), damit Markup und CSS dieselbe Quelle
   haben. --------------------------------------------------------------- */

.text-scroll-pin {
  height: 300vh;
  position: relative;
  view-timeline-name: --text-scroll-progress;
}
.text-scroll-pin__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center; /* zurück auf zentriert (Kompromiss, siehe
    .text-scroll-Kommentar unten) — flex-start ließ den ganzen Leerraum
    nach unten wandern statt ihn zu beseitigen, wirkte dort genauso
    störend wie vorher oben. */
}

.text-scroll {
  padding: var(--space-8) 60px; /* 96px, war var(--space-7)/64px (Figma:
    80px) — bewusst vergrößert (Kompromiss-Lösung): Inhalt füllt dadurch
    mehr vom 100vh-Fenster, der bei Zentrierung verbleibende Leerraum
    oben+unten wird spürbar kleiner statt sich einseitig zu stapeln. */
  display: flex;
  flex-direction: column;
  gap: var(--space-8); /* war var(--space-7)/64px, aus demselben Grund vergrößert */
  width: 100%;
  position: relative; /* Bezugsrahmen für .text-scroll__deco (position:absolute) */
  box-sizing: border-box;
}

.text-scroll__overline-divider {
  border-top: 1px solid var(--line-subtler);
  padding: var(--space-3) 0;
  width: 100%;
  box-sizing: border-box;
}

.text-scroll__heading {
  display: flex;
  flex-direction: column; /* jede Zeile als eigener Block — für den Versatz
    zwischen den Zeilen (exakt aus Figma), statt als ein durchlaufender Fließtext */
  font-size: min(calc(var(--fs-h1) * 1.25), calc((100vw - 120px) / 12.3)); /*
    User-Wunsch: größer (1.25 × --fs-h1, 100px auf großem Desktop). Zweiter
    Wert deckelt nach unten: die breiteste Zeile ("intelligenten
    Gegenüber.") ist 12.0em breit und läuft per nowrap nie von selbst um -
    ohne Deckel hing sie zwischen ~1350px und 600px über den Body hinaus.
    120px = 2 × 60px Seitenpadding von .text-scroll, 12.3 = 12.0em + ~2%
    Reserve (100vw enthält ggf. die Scrollbar). Ab ≈1350px greift weiter
    der unveränderte 100px-Wert. */
  font-weight: var(--fw-ultrabold);
  letter-spacing: -0.5px;
  line-height: 1;
  margin: 0;
  max-width: 60%; /* User-Wunsch: 60% der Breite statt fixer 1039px -
    siehe Mobile-Breakpoint weiter unten für den Reset auf 100% */
}
.text-scroll__line {
  display: block;
  white-space: nowrap; /* Zeilenumbrüche sind manuell pro Zeile gesetzt
    (siehe PHP) - darf sich bei max-width:60% (siehe .text-scroll__heading)
    nicht nochmal selbst umbrechen, sonst reißt es z.B. "Kommunikation"
    mitten im Wort auseinander. Überlappt dadurch ggf. knapp die 60%-Spalte,
    das ist hier gewollt (großzügige Display-Typografie). */
}
.text-scroll__line--indent {
  margin-left: 5ch; /* Versatz exakt aus Figma (5 Leerzeichen vor "Kommunikation"
    im Original) — hier als margin statt literaler Leerzeichen im Text, damit
    HTML-Whitespace-Kollabierung das nicht kaputt macht */
}
.text-scroll__char {
  color: var(--text-scroll-muted);
  /* Zeichenweise statt wortweise (User-Wunsch): bei unserer proportionalen
     Schrift (nicht Monospace wie im CodePen-Vorbild) schneidet eine
     ch-breiten-basierte Aufdeckung sonst mitten durch einzelne Buchstaben
     — jeder Buchstabe ist deshalb sein eigenes Element mit eigenem,
     schmalem animation-range statt eines gemeinsamen background-clip-Tricks.
     Langform-Properties statt animation-Shorthand: das Shorthand setzt
     alle nicht genannten Teil-Eigenschaften zurück, darunter mittlerweile
     auch animation-timeline/animation-range — das kann die Scroll-Kopplung
     unbeabsichtigt aushebeln.
     Alle Zeichen hängen an derselben benannten Timeline der gepinnten
     Sektion (--text-scroll-progress, siehe .text-scroll-pin) — dadurch
     bekommt jedes Zeichen seine eigene, in PHP berechnete animation-range
     (Inline-Style) innerhalb der Text-Phase (25%-50%), unabhängig von der
     tatsächlichen Y-Position der Zeile. */
  animation-name: text-scroll-char-reveal;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --text-scroll-progress;
  /* animation-range wird pro Zeichen per Inline-Style gesetzt (siehe PHP) */
}
@keyframes text-scroll-char-reveal {
  to { color: var(--text-default-default); }
}
@supports not (animation-timeline: view()) {
  /* Browser ohne Scroll-Driven-Animations-Support: sofort volle (schwarze)
     Farbe zeigen statt dauerhaft blass hängenzubleiben, Pin deaktivieren
     (normal scrollen) */
  .text-scroll-pin {
    height: auto;
  }
  .text-scroll-pin__sticky {
    position: static;
    height: auto;
    overflow: visible;
  }
  .text-scroll__char {
    animation-name: none;
    color: var(--text-default-default);
  }
  .text-scroll__deco {
    display: none;
  }
}
.text-scroll__heading .is-aligned-right {
  display: block;
  width: max-content;
  max-width: 100%;
  white-space: nowrap; /* siehe .text-scroll__line - bei max-width:60%
    brach sonst z.B. "mit einem einfachen" zwischen den beiden Segmenten
    um (eigentlicher Desktop-Wunsch: eine durchlaufende Zeile, siehe
    PHP-Kommentar bei $textScrollRawLines) */
  margin-left: auto; /* ersetzt text-align:right */
}

/* --- Schwebende Deko-Icons + Bild (Phase 2, Parallax) ------------------
   Prozentual/responsiv statt Figmas festen 1728px-Pixelkoordinaten,
   da Figma diese Elemente selbst als "für eine Scroll-Animation gedacht"
   markiert hat — kein statisches Pixel-Layout gemeint. Alle 4 nutzen
   dieselbe Timeline + denselben Zeitbereich (per Inline-Style aus PHP),
   unterschiedliche Verschiebungsweite pro Element erzeugt die
   Tiefenwirkung (Parallax). */
.text-scroll__deco {
  position: absolute;
  inset: 0;
  z-index: 999999; /* War 1, reichte aber nicht gegen das geheime
    ?exp=-Experiment-Feature (.experiment-text-fg span/li auf
    z-index:9999, siehe weiter unten in dieser Datei) - nicht der
    Normalfall, aber so liegen die Icons auch im Experiment-Modus vorne */
  pointer-events: none;
}
.text-scroll__deco-image {
  position: absolute;
  right: 8%;
  top: 8%;
  width: 26%;
  aspect-ratio: 3 / 2; /* User-Wunsch: normales Querformat statt Quadrat -
    die 3 echten Screenshots sind alle querformatig (Verhältnis ca.
    1.3-1.8:1), bei 1:1 wurde per object-fit:cover viel vom rechten
    Bildrand abgeschnitten */
  background: var(--surface-light-subtlest); /* Lückenfüller/Fallback, falls
    ein Frame noch lädt oder zwischen zwei Crossfades kurz alle bei
    opacity<1 stehen */
  overflow: hidden; /* falls ein Bild-Seitenverhältnis nicht exakt 3:2 ist */
  animation-name: text-scroll-parallax-slow;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --text-scroll-progress;
}
/* 1 statisches Bild (User-Wunsch, ersetzt die vorherige Überblendung
   zwischen 3 Screenshots - daher kein eigenes Opacity/Crossfade mehr
   nötig, das Einblenden übernimmt weiterhin die Parallax-Animation des
   umschließenden .text-scroll__deco-image). */
.text-scroll__deco-image-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top left; /* Bildausschnitt bewusst immer oben links
    beginnen (Logo/Branding sitzt dort), statt der object-fit:cover-
    Vorgabe (Mitte) zu folgen */
}
.text-scroll__deco-icon {
  position: absolute;
  z-index: 1; /* User-Wunsch: Icons im Vordergrund - sicherstellen, dass sie
    immer über .text-scroll__deco-image liegen (bisher nur zufällig durch
    DOM-Reihenfolge der Fall), auch bei künftigen Änderungen */
  width: 96px; /* User-Wunsch: etwas größer (war 72px) */
  height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-green); /* User-Wunsch: grün statt weiß */
  border: 1px solid var(--line-subtler);
  padding: var(--space-4); /* User-Wunsch: mehr Platz ums Icon (war --space-2/8px) */
  box-sizing: border-box;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --text-scroll-progress;
}
.text-scroll__deco-icon svg {
  width: 100%;
  height: 100%;
  color: var(--text-default-default);
}
.text-scroll__deco-icon--message {
  right: 4%;
  top: 40%;
  animation-name: text-scroll-parallax-medium;
}
.text-scroll__deco-icon--people {
  right: 22%;
  top: 66%;
  animation-name: text-scroll-parallax-fast;
}
.text-scroll__deco-icon--reply {
  left: 8%;
  top: 58%;
  animation-name: text-scroll-parallax-medium;
}
@keyframes text-scroll-parallax-slow {
  from { opacity: 0; transform: translateY(30vh); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes text-scroll-parallax-medium {
  from { opacity: 0; transform: translateY(55vh); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes text-scroll-parallax-fast {
  from { opacity: 0; transform: translateY(80vh); }
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 900px) {
  .text-scroll-pin {
    height: auto; /* Pin/Parallax nur Desktop — auf kleineren Screens
      wirkt ein 300vh-Scroll-Jack unangenehm, Text einfach normal scrollen */
  }
  .text-scroll-pin__sticky {
    position: static;
    height: auto;
    overflow: visible;
  }
  .text-scroll__char {
    animation: none;
    color: var(--text-default-default); /* direkt schwarz statt animiert */
  }
  .text-scroll__deco {
    display: none;
  }
  .text-scroll {
    padding: var(--space-6) 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    gap: var(--space-6);
  }
  .text-scroll__heading {
    font-size: min(calc(var(--fs-h1) * 1.25), calc((100vw - 80px) / 12.3)); /*
      wie oben, aber 2 × 40px Seitenpadding auf Tablet (601-900px); ≤600px
      setzt unten wieder die Mobile-Größe */
  }
}

@media (max-width: 600px) {
  .text-scroll {
    padding-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    padding-right: 20px;
  }
  .text-scroll__heading {
    max-width: 100%; /* 60% (Desktop) wäre auf Mobile viel zu schmal -
      die per Messung gewählten Zeilen-Versätze unten gehen ohnehin von
      voller Breite aus */
    font-size: var(--fs-h1); /* Desktop-Vergrößerung (*1.25) zurückgesetzt -
      zusammen mit nowrap unten lief der Text sonst über den Bildschirmrand
      hinaus (die Zeilen-Versätze sind auf die alte, kleinere Mobile-Größe
      gemessen) */
  }
  .text-scroll__line,
  .text-scroll__heading .is-aligned-right {
    white-space: normal; /* nowrap ist ein Desktop-Fix (siehe dort) - auf
      Mobile sollen/müssen die Zeilen weiterhin regulär umbrechen können */
  }
  /* Die Desktop-Versätze (5ch-Einzug bei "Kommunikation", rechtsbündig bei
     den letzten beiden Zeilen) sind exakt aus Figma, aber auf schmalen
     Screens zu groß — "Kommunikation" brach dadurch zusätzlich selbst um
     ("Kommuni"/"kation"), die rechtsbündigen Zeilen sahen durch den
     Zeilenumbruch ungleichmäßig aus. Eigener, kleinerer Mobile-Versatz pro
     Zeile (kein Figma-Beleg für Mobile — eigene Entscheidung, bitte
     gegenchecken): jede der 5 Zeilen bekommt einen eigenen, unterschied-
     lichen Einzug (User-Wunsch "jede Zeile unterschiedlich versetzt")
     statt der 3 Desktop-Varianten (normal/indent/rechtsbündig). */
  .text-scroll__heading .is-aligned-right {
    width: auto;
    max-width: 100%;
    margin-left: 0; /* Rechtsbündigkeit auf Mobile aus, siehe Versatz pro Zeile unten */
  }
  /* Werte per Messung der tatsächlichen Textbreite pro Zeile gewählt (nicht
     geraten) — jede Zeile bekommt so viel Versatz wie möglich, ohne selbst
     ein weiteres Mal umzubrechen. Zeile 4/5 bekommen HIER kein margin-left
     mehr (siehe .text-scroll__line-group weiter unten) — die sind jetzt
     jeweils 2 eigene Segmente, die sich per flex links/rechts ausrichten. */
  .text-scroll__heading > *:nth-child(1) { margin-left: 0; }   /* "Mehr effiziente", Breite bestimmt die Spalte, max. sicherer Versatz ~40px */
  .text-scroll__heading > *:nth-child(2) { margin-left: 24px; } /* "Kommunikation", max. sicherer Versatz ~30px */
  .text-scroll__heading > *:nth-child(3) { margin-left: 72px; } /* "im Studium", max. sicherer Versatz ~113px */
  .text-scroll__heading > *:nth-child(4) { margin-left: 0; }
  .text-scroll__heading > *:nth-child(5) { margin-left: 0; }

  /* Testweise (User-Wunsch): statt Zeile 4/5 ("mit einem einfachen",
     "intelligenten Gegenüber.") als EIN rechtsbündiger Block, jedes der 2
     Wort-Segmente als eigene Zeile mit ABWECHSELNDER Ausrichtung — erstes
     Segment links, zweites rechts. Auf Desktop bleiben beide Segmente eine
     durchlaufende Zeile (siehe .text-scroll__segment ohne Media Query). */
  .text-scroll__heading .is-aligned-right.text-scroll__line-group {
    display: flex; /* schlägt .text-scroll__heading .is-aligned-right
      (ebenfalls 2 Klassen Spezifität) nur, weil hier zusätzlich noch
      .text-scroll__line-group mit angegeben ist (3 Klassen) — nur
      .text-scroll__line-group allein (1 Klasse) reichte nicht aus */
    flex-direction: column;
    width: 100%;
    max-width: 100%;
  }
  .text-scroll__line-group .text-scroll__segment:nth-child(1) {
    align-self: flex-start;
  }
  .text-scroll__line-group .text-scroll__segment:nth-child(2) {
    align-self: flex-end;
  }
}

/* --- Feature-Scroll (Funktionen-Seite, m-feature-scroll) --------------------
   Vierte Iteration. User-Feedback nach genauer Beobachtung von
   godaylight.com/about: es ist wie eine Tabelle mit sichtbaren Zeilen/
   Zelllinien, 3-5 Zeilen gleichzeitig sichtbar (oben/unten angeschnitten),
   ALLES (Bilder + Linien) schiebt sich beim Scrollen gemeinsam nach oben
   (eine Einheit, kein unabhängiges Versetzt-Sein zwischen den Spalten mehr
   wie in Version 2 angenommen) — die Tabellenansicht wirkt wie eine
   Maskenebene über den Bildern. Der Text in der Mitte ist davon komplett
   UNABHÄNGIG: er fadet ein/aus, bleibt dabei aber positionell fix in der
   Bildschirmmitte, immer nur einer sichtbar.
   Architektur: Pin-Wrapper (Scroll-Budget) → gepinntes, maskiertes
   Fenster (.feature-scroll-pin__window, overflow:hidden) → darin ZWEI
   unabhängige Ebenen:
   1. .feature-scroll-pin__track — die "Tabelle" (alle 4 Zeilen inkl.
      sichtbarer border-bottom-Linien), läuft als EIN Stück kontinuierlich
      nach oben (eine translateY-Animation über die Pin-Dauer)
   2. .feature-scroll-pin__text-overlay — 4 Text-Layer, die per Opacity
      ein-/ausfaden (0→1→1→0 je Kachel, animation-range pro Kachel aus
      PHP), OHNE jede Positionsänderung — dadurch kein Risiko der
      sticky+transform-Falle aus Version 3.
   Beide Ebenen hängen an DERSELBEN benannten Timeline
   (--feature-scroll-progress, view-timeline-name auf .feature-scroll-pin),
   Langform-animation-Properties statt Shorthand (siehe m-text-scroll für
   die Begründung).
   Auf ≤900px eigene, einfach gestapelte Mobile-Fallback-Struktur
   (.feature-scroll-mobile, siehe PHP). ---------------------------------- */

.feature-scroll {
  padding: 0 64px 0 64px; /* unten bewusst 0 (User-Wunsch, war 64px) -
    betrifft nur Desktop, Mobile nutzt .feature-scroll-mobile mit eigenem
    Padding */
}

.feature-scroll__overline-divider {
  border-bottom: 1px solid var(--line-subtler);
  padding: var(--space-3) 0;
  width: 100%;
  box-sizing: border-box;
  margin-bottom: var(--space-6);
}

.feature-scroll-pin {
  height: 350vh; /* Scroll-Budget für 4 Zeilen */
  position: relative;
  view-timeline-name: --feature-scroll-progress;
}
.feature-scroll-pin__window {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden; /* die "Maskenebene" — schneidet Zeilen oben/unten ab */
}

.feature-scroll-pin__track {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  animation-name: feature-scroll-track-drift;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --feature-scroll-progress;
  animation-range: cover 5% cover 95%; /* etwas Puffer am Anfang/Ende */
}
@keyframes feature-scroll-track-drift {
  from { transform: translateY(0); }
  to { transform: translateY(-1500px); } /* 3 x 500px Zeilenhöhe — zeigt alle
    4 Zeilen nacheinander durchs Fenster */
}

.feature-scroll-row {
  display: flex;
  align-items: stretch;
  justify-content: center; /* nötig, sobald .feature-scroll-cell--empty
    unten gedeckelt ist: die beiden 450px-Bildspalten sind schon lange
    gedeckelt, nur die Mittelspalte wuchs bisher unbegrenzt mit — auf
    großen Monitoren zu groß (User-Feedback). Sobald alle 3 Spalten ihre
    max-width erreicht haben, bleibt Restplatz übrig; center verteilt den
    symmetrisch an beiden Außenkanten statt ihn (mit dem Default
    flex-start) einseitig rechts als Lücke stehen zu lassen. */
  border-bottom: 1px solid var(--line-subtler); /* Zeilenlinie, läuft mit
    dem Track mit statt statisch im Hintergrund zu stehen */
  height: 500px; /* exakt aus Figma */
  flex-shrink: 0;
  box-sizing: border-box;
}
/* Dieselben Flex-Breiten wie .feature-scroll-pin__text-spacer unten —
   dadurch liegt das Text-Overlay exakt über der leeren Mittelspalte jeder
   Zeile, ganz ohne CSS Grid/subgrid (schwächerer Browser-Support). */
.feature-scroll-cell--media {
  flex: 1 1 450px; /* 450px exakt aus Figma, darf aber schrumpfen */
  max-width: 450px;
  min-width: 180px;
  height: 100%;
  box-sizing: border-box;
}
.feature-scroll-cell--empty {
  flex: 1 1 400px;
  min-width: 450px; /* war 240px — bei mittleren Fensterbreiten (z.B.
    ~1024px) blieb der Spalte dadurch kaum Platz (feste 80px Padding pro
    Seite auf .feature-scroll-pin__text-layer fraßen fast alles auf), Text
    brach wort- bzw. silbenweise um (User-Feedback: "sieht nicht so gut
    aus", Screenshot). 450px lässt auch am unteren Rand des clamp()
    (32px Schrift) noch komfortabel ~290px für den eigentlichen Text. */
  max-width: 800px; /* User-Feedback: auf großem Monitor viel zu breit —
    war bisher als einzige der 3 Spalten ungedeckelt, wuchs also
    unbegrenzt mit der Fensterbreite mit. Muss exakt denselben Wert wie
    .feature-scroll-pin__text-col unten haben (siehe Kommentar dort) */
}
.feature-scroll-cell--media:first-child {
  border-right: 1px solid var(--line-subtler);
}
.feature-scroll-cell--media:last-child {
  border-left: 1px solid var(--line-subtler);
}

.feature-scroll-cell--media.feature-scroll-cell--image {
  padding-block: var(--space-4); /* 24px, exakt aus Figma */
}
.feature-scroll-cell--image .img-placeholder {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
.feature-scroll-cell__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.feature-scroll-cell__img-mask {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}
.feature-scroll-cell--image .feature-scroll-cell__img {
  position: absolute;
  top: -80px;
  left: 0;
  width: 100%;
  height: calc(100% + 160px); /* Reserve für die Parallax-Wanderung, damit
    beim Scrollen nie Leerraum am Rand sichtbar wird */
  animation-name: feature-scroll-image-parallax;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --feature-scroll-progress;
  /* animation-range wird pro Zeile per Inline-Style gesetzt (siehe PHP,
    dieselben text_start/text_end-Werte wie beim Text-Crossfade) — sonst
    verteilt sich die Bewegung über die GANZE Sektion und wirkt bei den
    mittleren Zeilen (ohne den Seiten-Scroll-Bonus der ersten/letzten
    Zeile) viel zu schwach */
}
@keyframes feature-scroll-image-parallax {
  from { transform: translateY(-80px); }
  to { transform: translateY(80px); }
}
.feature-scroll-cell--icon {
  display: flex;
  align-items: center;
  justify-content: center;
}
.feature-scroll-cell--icon svg {
  width: 120px;
  height: auto;
  color: var(--stroke-subtler);
}
.feature-scroll-cell--icon svg.feature-scroll-cell__icon--phone {
  width: 80px; /* quadratische ViewBox, optisch so groß wie der Brief daneben */
}

.feature-scroll-pin__text-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: stretch;
  justify-content: center; /* muss zum justify-content:center von
    .feature-scroll-row passen, sonst driftet das Text-Overlay von den
    Zeilen-Trennlinien darunter weg, sobald Restplatz übrig bleibt */
}
.feature-scroll-pin__text-spacer {
  flex: 1 1 450px;
  max-width: 450px;
  min-width: 180px;
}
.feature-scroll-pin__text-col {
  flex: 1 1 400px;
  min-width: 450px; /* exakt derselbe Wert wie .feature-scroll-cell--empty oben */
  max-width: 800px; /* exakt derselbe Wert wie .feature-scroll-cell--empty
    oben — Text-Overlay muss immer genau über der leeren Mittelspalte der
    Zeile liegen, siehe Kommentar bei .feature-scroll-cell--media */
  position: relative;
}
.feature-scroll-pin__text-layer {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2); /* eng, "Kommunikation" direkt über der Headline */
  padding: 0 80px; /* exakt aus Figma (80 liegt nicht auf der 8er-Skala) —
    schmälere Textspalte hilft zusätzlich zum fluiden Font-Size (clamp),
    den Text konsistenter auf ~4 Zeilen umbrechen zu lassen */
  text-align: center;
  box-sizing: border-box;
  background: var(--surface-light-default); /* deckt den durchlaufenden
    Track dahinter ab, während dieser Text aktiv ist */
  opacity: 0;
  animation-name: feature-scroll-text-crossfade;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-fill-mode: both;
  animation-timeline: --feature-scroll-progress;
  /* animation-range wird pro Kachel per Inline-Style gesetzt (siehe PHP) */
}
@keyframes feature-scroll-text-crossfade {
  0% { opacity: 0; }
  15% { opacity: 1; }
  85% { opacity: 1; }
  100% { opacity: 0; }
}

@supports not (animation-timeline: view()) {
  /* Browser ohne Scroll-Driven-Animations-Support: Pin deaktivieren, nur
     die erste Kachel statisch zeigen statt dauerhaft leer/unsichtbar */
  .feature-scroll-pin {
    height: auto;
  }
  .feature-scroll-pin__window {
    position: static;
    height: auto;
    overflow: visible;
    display: block;
  }
  .feature-scroll-pin__track {
    animation: none;
    transform: none;
  }
  .feature-scroll-pin__text-overlay {
    display: none; /* erste Kachel ist über den Track ohnehin sichtbar */
  }
}

.feature-row__label {
  font-size: var(--fs-copy-small);
  font-weight: var(--fw-semibold);
  line-height: 1.1;
  margin: 0;
  width: 100%;
}

.feature-row__heading {
  /* fluid statt fix: die Textspalte wird zwischen den beiden 450px-Rand-
     spalten breiter, je breiter das Fenster — mit fixer var(--fs-h2)
     bricht der Text bei sehr breiten Fenstern nur noch 1-2-zeilig um.
     clamp() skaliert die Schrift mit der Fensterbreite mit, damit die
     Zeilenzahl (~4) über verschiedene Desktop-Breiten ähnlich bleibt. */
  font-size: clamp(32px, 2.6vw, 64px);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  margin: 0;
  width: 100%;
}

/* --- Feature-Scroll Mobile-Fallback (≤900px) ---------------------------
   Pin+Parallax nur Desktop (gleiche Begründung wie m-text-scroll: ein
   Scroll-Jack wirkt auf kleineren Screens unangenehm) — stattdessen
   dieselben 4 Kacheln als einfache gestapelte Liste, exakt wie die
   ursprüngliche (Vor-Pin) Version dieser Sektion. Desktop-Pin ist hier
   ausgeblendet, siehe unten. ------------------------------------------- */

.feature-scroll-mobile {
  display: none;
}

@media (max-width: 900px) {
  .feature-scroll {
    display: none; /* 3-Spalten-Layout passt nicht auf schmale Screens,
      eigene gestapelte Mobile-Struktur übernimmt */
  }
  /* Layout nach Figma (Tablet+Mobile, User-Wunsch): pro Block Label +
     Überschrift zentriert, darunter Trennlinie, Bild (seitlich
     eingerückt, quadratisch), Trennlinie. Die Linien laufen über die volle
     Bildschirmbreite (Randlinien statt Seitenpadding am Section-Container),
     Overline und Text bekommen ihren Seitenrand einzeln. */
  .feature-scroll-mobile {
    display: block;
    padding: 0 0 var(--space-6) 0;
  }
  .feature-scroll-mobile__overline-divider {
    border-bottom: 1px solid var(--line-subtler);
    padding: var(--space-3) 0;
    margin: 0 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    box-sizing: border-box;
  }
  .feature-scroll-mobile__row {
    display: flex;
    flex-direction: column;
    width: 100%;
  }
  .feature-scroll-mobile__text {
    padding: clamp(32px, 7vw, 64px) 40px;
    text-align: center;
  }
  .feature-scroll-mobile .feature-row__label {
    margin-bottom: var(--space-3);
  }
  .feature-scroll-mobile .feature-row__heading {
    font-size: var(--fs-h3); /* fest statt fluid (clamp der Desktop-
      Spalte), gestapeltes Layout hat hier keine variable Spaltenbreite */
  }
  .feature-scroll-mobile__media {
    border-block: 1px solid var(--line-subtler);
    padding-inline: 12%; /* Bild bündig zwischen den Linien, seitlich
      eingerückt - proportional zur Breite, wirkt auf Tablet und Mobile
      gleich */
  }
  .feature-scroll-mobile__media .feature-scroll-cell__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    object-fit: cover;
  }
}

@media (max-width: 600px) {
  .feature-scroll-mobile__overline-divider {
    margin-left: 20px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    margin-right: 20px;
  }
  .feature-scroll-mobile__text {
    padding-left: 20px;
    padding-right: 20px;
  }
}

/* --- Feature-Select (Funktionen-Seite, horizontal scrollbare Kachelauswahl)
   Figma: m-feature-select (Node 143:2211), urspr. 5 Kacheln gezeigt,
   tatsächlich 7 (ggf. später mehr) — Reihe ist laut Vorgabe horizontal
   scrollbar mit "Anschnitt" (angeschnittene Kachel) am Rand statt Umbruch.
   Feste Kachelbreite (kein Schrumpfen/Wrap) + normales Seiten-Padding auf
   dem Scroll-Container sorgt dafür, dass am rechten (und beim Scrollen ans
   Ende: linken) Rand automatisch eine Kachel angeschnitten sichtbar ist,
   weil 7 Kacheln immer breiter sind als jeder Viewport. */

.feature-select {
  padding-top: var(--space-7);
  padding-bottom: var(--space-1); /* User-Wunsch: Abstand zu text-scroll-pin
    weiter verkleinern (war var(--space-7)/64px symmetrisch, dann
    var(--space-4)/24px, jetzt var(--space-1)/4px) — oben unverändert
    gelassen, da nicht Teil der Anfrage */
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

.feature-select__tiles {
  display: flex;
  gap: 20px; /* exakt aus Figma, liegt nicht auf der 8er-Skala */
  padding: 0 64px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-left: 64px;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* alte Edge/IE */
}
.feature-select__tiles::-webkit-scrollbar {
  display: none; /* Chrome/Safari — Karussell braucht keine sichtbare Scrollbar */
}

.feature-tile {
  flex: 0 0 385px; /* fest statt schrumpfend — erzeugt den Anschnitt am Rand */
  aspect-ratio: 385 / 361;
  scroll-snap-align: start;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-5); /* 32px */
  border: 1px solid var(--line-subtler);
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 0.2s ease, border-color 0.2s ease;
}
@media (hover: hover) {
  .feature-tile:not(.is-active):hover {
    background: color-mix(in srgb, var(--accent-green) 55%, transparent); /* User-Wunsch:
      grüner Hover, aber dezenter als die aktive Kachel (volles Grün).
      Nur auf Geräten mit echtem Hover (kein "klebender" Hover auf Touch). */
    border-color: transparent;
  }
}
.feature-tile.is-active {
  border-color: transparent;
  background: var(--accent-green); /* Figma-Variable "green/dark-bg", #66E4AD — geändert von hellgrau */
}
.feature-select__tiles.has-not-scrolled .feature-tile:first-child {
  /* Erste Kachel ist von Anfang an links angeschnitten, gleicher
     "Anschnitt"-Effekt wie am rechten Rand — rein per CSS (negativer
     Margin schiebt die Kachel teils vor den Scroll-Anfang), damit es
     ohne JS/scrollLeft-Trick und ohne Lade-Flackern funktioniert. Klasse
     "has-not-scrolled" wird per JS beim ersten Scrollen entfernt, siehe
     main.js — danach bleibt die Kachel auch am linken Anschlag voll
     sichtbar. */
  margin-left: -120px; /* 56px Anschnitt + 64px Seiten-Padding */
}

.feature-tile__top {
  display: flex;
  flex-direction: column;
  gap: var(--space-2); /* 8px */
  width: 100%;
}
.feature-tile__number {
  font-size: var(--fs-copy-small);
  margin: 0;
}
.feature-tile__icon-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1); /* 4px */
}
.feature-tile__icon-label svg {
  width: 148px;
  height: auto;
  color: var(--stroke-subtler);
}
.feature-tile.is-active .feature-tile__icon-label svg {
  color: var(--text-default-default);
}
/* Outline im Ruhezustand, gefüllt sobald die Kachel aktiv ist (User-
   Wunsch) — dieselbe SVG für beide Zustände (siehe icons.php-Kommentar),
   nur fill/stroke werden per CSS umgeschaltet. vector-effect:
   non-scaling-stroke hält die Outline-Linie bei jeder Icon-Größe (148px
   Desktop, kleiner auf Tablet/Mobile) gleich dünn, unabhängig vom
   SVG-Skalierungsfaktor. */
.feature-tile__icon-label svg path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5px;
  vector-effect: non-scaling-stroke;
}
.feature-tile.is-active .feature-tile__icon-label svg path {
  fill: currentColor;
  stroke: none;
}
.feature-tile__label {
  font-size: var(--fs-h4);
  font-weight: var(--fw-regular);
  margin: 0;
}
.feature-tile.is-active .feature-tile__label {
  font-weight: var(--fw-semibold); /* Figma "Bold", siehe Konvention oben (Font-Datei fehlt) */
}

.feature-tile__arrow {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--stroke-subtler);
}
.feature-tile__arrow svg {
  width: 12px;
  height: 12px;
  transform: rotate(90deg); /* Basis-Icon zeigt hoch-rechts, Figma dreht auf runter-rechts */
}
.feature-tile.is-active .feature-tile__arrow {
  color: var(--text-default-default);
}

/* User-Wunsch: im OS-Darkmode (--text-default-default kippt global auf
   Weiß, siehe tokens.css) bleibt die aktive Kachel trotzdem mit
   schwarzem Text/Icon auf dem hellgrünen --accent-green-Hintergrund -
   sonst schlechter Kontrast (weiß auf hellgrün). --grey-6 statt der
   semantischen Variable, da die (anders als --text-default-default)
   NICHT vom Darkmode-Media-Query umgeschaltet wird. */
@media (prefers-color-scheme: dark) {
  .feature-tile.is-active .feature-tile__icon-label svg,
  .feature-tile.is-active .feature-tile__label,
  .feature-tile.is-active .feature-tile__arrow,
  .feature-tile.is-active .feature-tile__number {
    color: var(--grey-6);
  }
}

.feature-select__detail {
  display: flex;
  gap: 20px; /* exakt aus Figma */
  align-items: flex-start;
  padding: 0 64px; /* Seitenrand exakt an Header (m-nav) angeglichen */
  box-sizing: border-box;
}

.feature-select__image-col {
  flex: 1 1 925px; /* 925px exakt aus Figma, darf schrumpfen — siehe .feature-row__media */
  max-width: 925px;
  min-width: 220px;
  aspect-ratio: 925 / 502;
  box-sizing: border-box;
}
.feature-select__image {
  display: none;
  width: 100%;
  height: 100%;
  object-fit: cover; /* <video> statt Platzhalter-<div>, füllt die Zelle wie zuvor der img-placeholder */
}
.feature-select__image.is-active {
  display: block; /* block statt flex — <video> braucht kein Flex-Layout, ist selbst kein Container */
}

.feature-select__text-col {
  flex: 1 1 400px;
  min-width: 240px;
  padding-top: var(--space-5); /* 32px */
  padding-left: var(--space-3); /* 16px */
  box-sizing: border-box;
}
.feature-select__panel {
  display: none;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4); /* 24px */
}
.feature-select__panel.is-active {
  display: flex;
}

.feature-select__desc {
  font-size: var(--fs-h4);
  line-height: 1.2;
  margin: 0;
  color: var(--text-default-default);
}
@media (min-width: 2000px) {
  /* User-Wunsch: .feature-select__text-col hat keine eigene max-width und
     wächst als Flex-Kind (flex: 1 1 400px) unbegrenzt mit dem restlichen
     Platz mit, sobald .feature-select__image-col bei 925px gedeckelt ist —
     auf sehr breiten Screens (>=2000px) wird die Zeilenlänge dadurch
     unangenehm lang. Textbreite hier auf 2/3 der ihr zugewiesenen Spalte
     begrenzen, statt die Spalte selbst zu deckeln (Panel-Layout/Gap
     bleibt unverändert). */
  .feature-select__desc {
    max-width: 66%;
  }
}
.feature-select__desc .is-muted {
  color: var(--text-default-subtlest); /* #595A5D, exakt aus Figma */
}

@media (max-width: 900px) {
  .feature-select__tiles {
    padding: 0 40px; /* Seitenrand exakt an Header (m-nav) angeglichen */
    scroll-padding-left: 40px;
  }
  .feature-select__detail {
    padding-left: 40px;
    padding-right: 40px;
  }
  .feature-tile {
    flex-basis: 300px;
  }
  .feature-select__tiles.has-not-scrolled .feature-tile:first-child {
    margin-left: -84px; /* 44px Anschnitt + 40px Seiten-Padding */
  }
  .feature-tile__icon-label svg {
    width: 96px;
  }
  .feature-select__detail {
    flex-direction: column;
  }
  .feature-select__image-col {
    max-width: 100%;
    width: 100%;
    flex-basis: auto; /* derselbe Bug wie im sm-375-Breakpoint weiter unten:
      .feature-select__detail wechselt hier auf flex-direction:column,
      wodurch die von Desktop geerbten "flex: 1 1 925px" die 925px als
      HÖHE statt Breite anwenden würden — hier zwar weniger dramatisch
      als bei column-reverse auf Mobile (aspect-ratio 925/502 x 100%
      Breite ergäbe ~486px erwartete Höhe statt fälschlich 925px), aber
      derselbe Fehler. */
  }
  .feature-select__text-col {
    padding-left: 0;
    width: 100%;
    flex-basis: auto; /* derselbe Flex-Basis-Bug wie bei .feature-select__image-col
      oben: "flex: 1 1 400px" von Desktop wirkt bei flex-direction:column
      als Höhe statt Breite, hier weniger sichtbar da min-content-Höhe des
      Textes oft nah an 400px liegt, aber bei kürzeren Texten (wie hier)
      bleibt sichtbarer Leerraum am Ende der Spalte übrig. */
  }
}

@media (max-width: 600px) {
  /* Ab hier eigener Figma-Frame "m-feature-select / sm-375" (Node 182:5636),
     nicht nur eine verkleinerte Desktop-Kachel: Kacheln werden zu
     kompakten Icon+Label-Chips (nebeneinander statt gestapelt, kein
     Nummer/Pfeil mehr), Kachel-Reihe bleedet rechts bis zum Rand (nur
     links 20px Padding), Bild/Text-Panel in umgekehrter Reihenfolge (Text
     zuerst, Bild danach). */
  .feature-select__tiles {
    padding-left: 20px;
    padding-right: 0; /* Reihe bleedet bis zum rechten Rand, exakt aus Figma */
    gap: 16px; /* exakt aus Figma, Desktop/Tablet nutzen 20px */
    scroll-padding-left: 20px;
  }
  .feature-select__detail {
    flex-direction: column-reverse; /* Text zuerst, Bild danach — exakt aus Figma, umgekehrt zu Tablet */
    gap: 32px; /* exakt aus Figma, abweichend von den 20px auf Desktop/Tablet */
    padding-left: 20px;
    padding-right: 20px;
  }
  .feature-select__image-col {
    aspect-ratio: 355 / 372; /* 372px exakt aus Figma bei 375px Frame-Breite minus 20px Padding */
    flex-basis: auto; /* WICHTIG: die Desktop-Regel "flex: 1 1 925px" oben
      setzt flex-basis auf 925px für die (dort horizontale) Haupt-Achse.
      .feature-select__detail wechselt hier aber auf
      flex-direction:column-reverse — die Haupt-Achse ist jetzt VERTIKAL,
      wodurch dieselben 925px plötzlich als HÖHE wirken und die
      aspect-ratio-Berechnung überstimmen (Bug: riesiger Abstand oben+unten
      auf Mobile). flex-basis:auto lässt die Höhe wieder aus der
      aspect-ratio hervorgehen. */
  }
  .feature-select__text-col {
    padding-top: var(--space-2); /* 8px, exakt aus Figma (Desktop/Tablet: 32px) */
    padding-left: 0;
    flex-basis: auto; /* User-Report "zu viel Abstand nach oben" (über dem
      Video, da column-reverse Text zuerst zeigt): "flex: 1 1 400px" von
      Desktop wirkte hier als Mindest-HÖHE der Textspalte (400px), obwohl
      der eigentliche Inhalt (Text + "mehr erfahren"-Link) oft deutlich
      weniger Platz braucht — die Differenz war als Leerraum zwischen Link
      und Video sichtbar. Exakt derselbe Flex-Basis-Bug wie bei
      .feature-select__image-col oben, nur auf der Text-Spalte. */
  }

  .feature-tile {
    flex: 0 0 auto; /* Chip wächst mit Inhalt statt fixer Breite */
    aspect-ratio: auto;
    flex-direction: row; /* Icon + Label nebeneinander statt gestapelt, exakt aus Figma */
    align-items: center;
    justify-content: flex-start;
    gap: var(--space-2); /* 8px, exakt aus Figma */
    padding: 12px 24px; /* exakt aus Figma, abweichend von den 32px auf Desktop/Tablet */
  }
  .feature-select__tiles.has-not-scrolled .feature-tile:first-child {
    margin-left: -40px; /* Chip-Breite ist jetzt variabel (Inhalt-abhängig), grob geschätzter Anschnitt statt exakt berechnet */
  }
  .feature-tile__top {
    width: auto;
  }
  .feature-tile__number,
  .feature-tile__arrow {
    display: none; /* im sm-375-Frame nicht vorhanden */
  }
  .feature-tile__icon-label {
    flex-direction: row; /* Icon links neben Label statt darüber, exakt aus Figma */
    gap: var(--space-2); /* 8px */
  }
  .feature-tile__icon-label svg {
    width: 48px; /* exakt aus Figma (Desktop 148px, Tablet 96px) */
  }
  .feature-tile.is-active .feature-tile__label {
    font-weight: var(--fw-regular); /* im sm-375-Frame bleibt Label auch selektiert Regular statt Bold */
  }
}

/* =========================================================================
   Versprechen-Seite (137:2496) — Komponenten, die nur hier vorkommen.
   m-nav/m-teaser-grid/m-contact/m-footer sind bereits vorhandene, geteilte
   Komponenten und werden unverändert wiederverwendet.
   ========================================================================= */

/* --- m-intro / copy: Fließtext mit Hervorhebung + Trennlinie ------------- */
.promise-intro {
  padding: var(--space-7) var(--space-7) 0 var(--space-7);
  display: flex;
  flex-direction: column;
  gap: var(--space-7); /* 64px, exakt aus Figma */
}
.promise-intro__text {
  font-size: var(--fs-h2);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  margin: 0;
  max-width: 1059px; /* exakt aus Figma */
}
.promise-intro__text .is-accent {
  color: #21ae71; /* exakt aus Figma, kein bestehendes Token deckungsgleich
    (weder --accent-green #66E4AD noch --accent-green-text #4DE8A5) */
}
.promise-intro__text .is-muted-underline {
  color: #21ae71; /* User-Wunsch, gleiche Klasse wie bei
    .intro-2col__lead (Funktionen-Seite) - dort auf diesen Kontext
    gescoped, hier eigene Regel für denselben Effekt */
  text-decoration: underline;
  text-underline-offset: 2px;
}
.promise-intro__divider {
  border-bottom: 1px solid var(--line-subtler);
  width: 100%;
}

/* --- m-fact-grid: 4 Kacheln mit Zahl/Label + Beschreibung ---------------- */
.fact-grid {
  padding: 0 var(--space-7) var(--space-7) var(--space-7);
}
.fact-grid__overline-divider {
  border-top: 1px solid var(--line-subtler);
  padding: var(--space-3) 0;
  margin-bottom: var(--space-6); /* 48px, exakt aus Figma */
}
.fact-grid__tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr)); /* festes 2x2-Raster,
    exakt aus Figma (nicht volle Breite: max-width 1331px, rechtsbündig).
    minmax(0, 1fr) statt nur 1fr: sonst zieht sich die Spalte mit dem
    "breiteren" Inhalt (z.B. "DSGVO-konform" als ein Wort) automatisch
    breiter als die andere — 1fr allein rechnet mit auto-min (= Content-
    Breite), minmax(0, 1fr) erzwingt wirklich gleich breite Spalten */
  gap: var(--space-4); /* 20px, exakt aus Figma */
  max-width: 1331px;
  margin-left: auto; /* rechtsbündig, exakt aus Figma (items-end) */
}
@media (max-width: 700px) {
  .fact-grid__tiles {
    grid-template-columns: 1fr;
  }
}
.fact-tile {
  border: 1px solid var(--line-subtler);
  box-sizing: border-box;
  padding: 56px; /* exakt aus Figma (Desktop-Frame), liegt nicht auf der 8er-Skala */
  min-height: 490px; /* exakt aus Figma Desktop (493-529px, je nach Textlänge) */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.fact-tile__number {
  font-size: 64px; /* exakt aus Figma Desktop, abweichend von --fs-h2 (40px) */
  font-weight: var(--fw-semibold); /* Figma nutzt "Bold" (700), siehe .section-overline-Kommentar */
  line-height: 1;
  letter-spacing: -0.96px;
  margin: 0;
  hyphens: none; /* verhindert Wörterbuch-Trennung MITTEN in einem Wort wie
    "kon-form" oder "DS-GVO" (geerbt von body{hyphens:auto}). Der normale
    Bindestrich in "DSGVO-konform" bleibt als Umbruchstelle erlaubt (das ist
    laut User explizit gewünscht) — nur die zusätzliche automatische
    Silbentrennung INNERHALB von "DSGVO" bzw. "konform" soll weg. */
  overflow-wrap: anywhere; /* Notbruch mitten in einem langen Wort OHNE
    Bindestrich, nur falls nötig (z.B. "Hochschulnah" -> "Hochschul"/"nah",
    exakt wie in Figma) — bei "DSGVO-konform" bricht es trotzdem zuerst am
    reguldären "-", weil das schon ein normaler Umbruchpunkt ist. */
}
.fact-tile__copy {
  font-size: var(--fs-copy-display);
  font-weight: var(--fw-regular);
  line-height: 1.35;
  margin: 0;
}

/* Mobile-Frame (Figma-Node 183:6881, "m-fact-grid / md-900"): eigene, engere
   Werte statt der Desktop-Maße oben skaliert zu übernehmen — Kachel-Padding
   56px->32px, Zahl 64px->40px (= --fs-h2), Abstand Zahl/Copy über gap statt
   über min-height+space-between (Kachel wird nicht mehr künstlich hochgehalten,
   Höhe ergibt sich aus dem Inhalt). Bricht mit derselben Breakpoint wie der
   Wechsel auf 1-spaltiges Grid (siehe .fact-grid__tiles oben). */
@media (max-width: 700px) {
  .fact-tile {
    padding: 32px;
    gap: 32px;
    min-height: 0;
    justify-content: flex-start;
  }
  .fact-tile__number {
    font-size: 40px; /* exakt aus Figma-Mobile — bewusst NICHT var(--fs-h2),
      das skaliert bei <=600px auf 24px runter, hier soll aber fix 40px
      bleiben (Figma-Node 183:6881 zeigt denselben Wert auf allen Mobile-
      Breiten, keine weitere Verkleinerung unter 700px) */
    letter-spacing: -0.6px; /* exakt aus Figma-Mobile für diese Instanz */
  }
}

/* --- m-logo-wall: horizontal scrollbare Reihe von Kunden-Logos ----------
   10 Logos auf dunklem Grund, Karussell wie .feature-select__tiles (kein
   Anschnitt-Trick nötig, startet bündig am linken Seitenrand). Logos sind
   schwarze Vektor-Dateien auf transparentem Grund (Original-Assets der
   Hochschulen) — per CSS-Filter auf Weiß gedreht statt neu eingefärbter
   SVGs, funktioniert unabhängig vom Original-Pfadaufbau jeder Datei. */
.logo-wall {
  background: var(--surface-dark-default);
  padding: var(--space-7) 0 var(--space-6) 0; /* 64px oben, 48px unten — Seitenrand kommt von den Kindern (Header links, Tiles-Reihe links+rechts) */
  display: flex;
  flex-direction: column;
  gap: var(--space-7); /* 64px, exakt aus Figma */
}
.logo-wall__top {
  padding: 0 var(--space-7);
  border-top: 1px solid var(--line-dark-subtler);
  padding-top: var(--space-6); /* 40px, exakt aus Figma */
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
}
.logo-wall__top .section-overline {
  color: var(--text-inverted-default);
}
.logo-wall__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-4); /* 16px, exakt aus Figma */
  max-width: 1195px;
}
.logo-wall__heading {
  font-size: var(--fs-h2);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  color: var(--text-inverted-default);
  margin: 0;
}
.logo-wall__heading .is-accent {
  color: var(--accent-green);
}
.logo-wall .text-link {
  color: var(--text-inverted-default);
  border-bottom-color: var(--line-dark-subtler);
}

.logo-wall__tiles {
  display: flex;
  gap: 21px; /* exakt aus Figma */
  padding: 0 var(--space-7); /* Seitenrand exakt an Header angeglichen */
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-left: var(--space-7);
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.logo-wall__tiles::-webkit-scrollbar {
  display: none;
}
.logo-tile {
  flex: 0 0 386px; /* fest statt schrumpfend, exakt aus Figma */
  aspect-ratio: 1 / 1;
  scroll-snap-align: start;
  box-sizing: border-box;
  border: 1px solid var(--line-dark-subtler);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6); /* 56px, exakt aus Figma */
  transition: background 0.15s ease, border-color 0.15s ease; /* User-Wunsch:
    ganze Kachel verlinkt + Hover grün */
}
.logo-tile:hover {
  background: var(--accent-green);
  border-color: transparent;
}
.logo-tile__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  filter: brightness(0) invert(1); /* schwarze Original-Vektordatei → Weiß,
    unabhängig von internen Klassen/Opacity-Layern der jeweiligen SVG */
  opacity: 0.9; /* exakt aus Figma (leicht gedämpft gegenüber reinem Weiß) */
  transition: filter 0.15s ease, opacity 0.15s ease;
}
.logo-tile:hover .logo-tile__img {
  filter: brightness(0); /* auf Hover zurück zu Schwarz statt Weiß - besser
    lesbar auf dem jetzt grünen Hintergrund, analog zu .cta-card:hover */
  opacity: 1;
}

@media (max-width: 900px) {
  .logo-wall__top,
  .logo-wall__tiles {
    padding-left: 40px;
    padding-right: 40px;
  }
}
@media (max-width: 600px) {
  .logo-wall__top,
  .logo-wall__tiles {
    padding-left: 20px;
    padding-right: 20px;
  }
  /* Statt einer festen Breite (Anschnitt fehlte dadurch auf schmalen
     Viewports) hier 1,5 Tiles sichtbar, damit der Anschnitt des zweiten
     Tiles am rechten Rand als Scroll-Hinweis funktioniert (User-Wunsch,
     anders als bei .teaser-grid/.project-tile, das auf Mobile stattdessen
     eigene Pfeil-Buttons + Fortschrittsbalken hat). */
  .logo-tile {
    flex: 0 0 calc((100vw - 40px - 21px) / 1.5);
    padding: var(--space-4); /* 24px statt 48px, sonst zu wenig Platz fürs Logo bei der kleineren Kachel */
  }
}

/* --- m-text / 2-column: Headline + Fließtext, statisch (keine Scroll-
   Animation, anders als .text-scroll auf der Funktionen-Seite) ----------- */
.text-2col__overline-divider {
  border-bottom: 1px solid var(--line-subtler);
  padding: var(--space-3) 0;
  width: 100%;
  box-sizing: border-box;
}
.text-2col {
  padding: var(--space-7) var(--space-7) 120px var(--space-7); /* 120px exakt aus Figma, liegt nicht auf der 8er-Skala */
  display: flex;
  flex-direction: column;
  gap: 72px; /* exakt aus Figma */
}
.text-2col__row {
  display: flex;
  flex-wrap: wrap;
  gap: 133px; /* exakt aus Figma */
  align-items: flex-start;
}
.text-2col__heading {
  font-size: var(--fs-h1);
  font-weight: var(--fw-ultrabold);
  line-height: 1;
  letter-spacing: -0.4px;
  margin: 0;
  max-width: 677px;
  flex: 1 1 500px;
}
.text-2col__copy {
  font-size: 16px; /* User-Wunsch: kleiner kursiver Text als "Schraffur"/Textur
    (vorher --fs-copy-small = 18px am Desktop); nie unter 13px, damit er
    lesbar bleibt */
  font-style: italic;
  font-weight: var(--fw-regular);
  line-height: 1.35;
  margin: 0;
  max-width: 655px;
  flex: 1 1 400px;
  color: color-mix(in srgb, var(--text-default-default) 15%, transparent); /* etwas
    zurückgenommen, damit die Textur gegenüber dem grünen Satz zurücktritt,
    Kontrast bleibt deutlich über AA */
}
.text-2col__copy .is-muted-underline {
  color: var(--grey-3); 
  font-style: normal;
  font-weight: var(--fw-semibold);
  hyphens: manual; /* keine automatische Silbentrennung in der großen Schrift */
  line-height: 1; 
  letter-spacing:0.8px;

  font-size: clamp(26px, 3.2vw, 36px); /* User-Wunsch: der Kernsatz groß, im
    Fließtext (inline) eingebettet. Mindestens 26px, da #21ae71 auf Weiß nur
    ~3:1 Kontrast hat (reicht nur für große, fette Schrift) */
   
}

@media (max-width: 900px) {
  .promise-intro,
  .fact-grid,
  .text-2col {
    padding-left: 40px;
    padding-right: 40px;
  }
  .logo-wall__top {
    padding-left: 40px;
    padding-right: 40px;
  }
}
@media (max-width: 600px) {
  .promise-intro,
  .fact-grid,
  .text-2col {
    padding-left: 20px;
    padding-right: 20px;
  }
  .logo-wall__top {
    padding-left: 20px;
    padding-right: 20px;
  }
}

/* =========================================================================
   Kontakt-Seite (156:5006) — Komponenten, die nur hier vorkommen.
   m-nav (siehe .site-header--dark oben) und m-footer sind bereits
   vorhandene, geteilte Komponenten. m-contact ist HIER kein reines Include
   von partials/footer.php (das würde den geteilten CTA-Block doppelt
   zeigen) — footer.php bekommt stattdessen $skipCta = true.
   ========================================================================= */

/* --- m-intro / marquee: endlos scrollende Textreihe -----------------------
   Figma zeigt nur einen statischen Ausschnitt ("Interesse geweckt?" 3x mit
   Icons dazwischen, am Rand angeschnitten) — der Name "marquee" und das
   überschneidende overflow-clip legen aber eindeutig eine echte
   Endlos-Scroll-Animation nahe (gleiches Muster wie bei .text-scroll/
   .feature-scroll: Interaktion/Bewegung aus Figmas Statik ableiten, nicht
   blind 1:1 nachbauen). prefers-reduced-motion wird bereits global in
   base.css abgefangen (animation-iteration-count:1). */
.intro-marquee {
  background: var(--surface-dark-default);
  padding-top: var(--space-7); /* 64px, exakt aus Figma */
  overflow: hidden;
}
.intro-marquee__track {
  display: flex;
  align-items: center;
  gap: 32px; /* exakt aus Figma */
  width: max-content;
  padding-bottom: var(--space-7);
  margin-left: -300px; /* noch deutlicherer Anschnitt (User-Beispiel-
    Screenshot: "sse geweckt?" statt nur des ersten Buchstabens sichtbar)
    — Wert = tatsächliche Breite von "Intere" bei dieser Schriftgröße
    (gemessen, nicht geschätzt). Unabhängig von der animation-transform,
    verschiebt nur die Ruhe-/Loop-Position insgesamt nach links. */
  animation: intro-marquee-scroll 40s linear infinite;
  animation-play-state: paused; /* steht still, genau wie im Figma-
    Standbild (angeschnitten) — läuft erst bei :hover los, umgedreht vom
    ursprünglichen Verhalten (lief permanent, pausierte bei :hover) */
}
.intro-marquee:hover .intro-marquee__track {
  animation-play-state: running;
}
.intro-marquee__text {
  font-size: var(--fs-headline-decorative);
  font-weight: var(--fw-ultrabold);
  letter-spacing: -0.48px;
  line-height: 1;
  color: var(--text-inverted-default);
  white-space: nowrap;
  margin: 0;
  flex-shrink: 0;
}
.intro-marquee__icon {
  width: 80px;
  height: 80px;
  color: var(--accent-green);
  flex-shrink: 0;
}
@keyframes intro-marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); } /* Track-Inhalt wird 1x dupliziert
    (siehe PHP) — bei -50% ist die Kopie exakt an der Startposition,
    dadurch nahtlose Schleife ohne sichtbaren Sprung */
}
.intro-marquee__divider {
  border-bottom: 1px solid var(--line-dark-subtler);
  width: 100%;
}

/* --- m-contact (Kontakt-Seite, eigene Instanz ohne Overline) ------------- */
.kontakt-contact {
  background: var(--surface-dark-default);
  color: var(--text-inverted-default);
  padding: var(--space-7) var(--space-7) 120px var(--space-7); /* 120px exakt aus Figma, liegt nicht auf der 8er-Skala */
  display: flex;
  flex-direction: column;
  gap: 96px; /* exakt aus Figma */
}

@media (max-width: 900px) {
  .kontakt-contact {
    padding: var(--space-7) 40px 64px 40px;
    gap: 48px;
  }
  .intro-marquee__text {
    font-size: 56px;
  }
  .intro-marquee__icon {
    width: 56px;
    height: 56px;
  }
  .intro-marquee__track {
    margin-left: -175px; /* proportional zur kleineren Schrift (56/96), siehe Desktop-Kommentar */
  }
}
@media (max-width: 600px) {
  .kontakt-contact {
    padding-left: 20px;
    padding-right: 20px;
  }
  .intro-marquee__text {
    font-size: 40px;
  }
  .intro-marquee__icon {
    width: 40px;
    height: 40px;
  }
  .intro-marquee__track {
    margin-left: -125px; /* proportional zur kleineren Schrift (40/96), siehe Desktop-Kommentar */
  }
}

/* =========================================================================
   Rechtsseiten (Impressum 126:1688, Datenschutz analog) — geteilte
   Komponenten. m-nav/m-contact/m-footer sind unverändert die geteilten
   Partials (m-contact hat hier — anders als auf der Kontakt-Seite — die
   normale "Kontakt"-Overline, deckt sich 1:1 mit dem Footer-CTA-Block,
   braucht also KEIN $skipCta).
   ========================================================================= */

/* --- m-intro / headline: großer Seitentitel + Trennlinie ----------------- */
.legal-intro {
  padding: var(--space-7) 120px; /* 120px exakt aus Figma (mehr als der
    sonst übliche 64px-Seitenrand) */
  display: flex;
  flex-direction: column;
  gap: var(--space-7); /* 64px, exakt aus Figma */
}
.legal-intro__heading {
  font-size: var(--fs-h1);
  font-weight: var(--fw-ultrabold);
  letter-spacing: -0.4px;
  line-height: 1;
  margin: 0;
}
.legal-intro__divider {
  border-bottom: 1px solid var(--line-subtler);
  width: 100%;
}

/* --- m-richtext: Fließtext-Sektion mit schmaler Lesespalte --------------- */
.richtext {
  padding: 0 334px 200px 334px; /* exakt aus Figma — deutlich schmalere
    Lesespalte als der Rest der Seite */
}
.richtext__2col {
  display: flex;
  gap: 155px; /* exakt aus Figma */
}
.richtext__col-left {
  flex: 0 0 250px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.richtext__col-right {
  flex: 1 1 0;
  min-width: 0;
}
.richtext__pair {
  margin-top: 56px; /* exakt aus Figma, Abstand zwischen Headline/Copy-Paaren */
}
.richtext__col-left .richtext__pair:first-child,
.richtext__col-right .richtext__pair:first-child {
  margin-top: 0;
}
.richtext__headline {
  font-size: var(--fs-h5);
  font-weight: var(--fw-semibold); /* Figma nutzt "Bold" (700), siehe .section-overline-Kommentar */
  line-height: 1.35;
  margin: 0 0 16px 0; /* exakt aus Figma */
}
.richtext__headline-medium {
  /* c-richtext / headline-medium (Datenschutz-Seite): größere Zwischen-
     überschrift, Regular statt Bold, anders als .richtext__headline */
  font-size: var(--fs-h2);
  font-weight: var(--fw-regular);
  line-height: 1.15;
  margin: 0 0 40px 0; /* exakt aus Figma (nur bei der ersten Instanz, die
    zweite hat keinen expliziten Abstand — übernimmt aber ohnehin den
    margin-top des folgenden .richtext__pair, siehe dort) */
}
.richtext__copy {
  font-size: var(--fs-copy-display);
  font-weight: var(--fw-regular);
  line-height: 1.35;
  margin: 0;
}
.richtext__copy p {
  margin: 0 0 24px 0; /* Abstand zwischen mehreren eigenständigen Absätzen
    (z.B. Datenschutz-Fließtext) */
}
.richtext__copy p:last-child {
  margin-bottom: 0;
}
.richtext__copy a {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.richtext__copy a:hover {
  color: #21ae71; /* wie die übrigen grünen Hover-Effekte */
}
.richtext__copy--tight p {
  margin: 0; /* Adresszeilen/Kontaktdaten (Impressum): keine Absätze,
    Zeilen sollen eng aneinander stehen, exakt aus Figma (mb-0) */
}
.richtext__divider {
  border-top: 1px solid var(--line-subtler);
  margin: 80px 0; /* exakt aus Figma */
}

@media (max-width: 1200px) {
  .richtext {
    padding-left: 64px;
    padding-right: 64px;
  }
  .richtext__2col {
    flex-direction: column;
    gap: 56px;
  }
  .richtext__col-left {
    flex-basis: auto;
  }
}
@media (max-width: 900px) {
  .legal-intro {
    padding-left: 40px;
    padding-right: 40px;
  }
  .richtext {
    padding-left: 40px;
    padding-right: 40px;
    padding-bottom: 120px;
  }
}
@media (max-width: 600px) {
  .legal-intro {
    padding-left: 20px;
    padding-right: 20px;
  }
  .richtext {
    padding-left: 20px;
    padding-right: 20px;
  }
}

/* --- FAQ (Häufige Fragen): aufklappbare Fragen, <details>/<summary> -------
   Schmale Lesespalte wie .richtext (Klasse wird mitgenutzt). Alle Antworten
   stehen im HTML (auch zugeklappt), für Menschen wie Maschinen lesbar. */
.faq__item {
  border-bottom: 1px solid var(--line-subtler);
}
.faq__question {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) 0;
  font-size: var(--fs-h3); /* User-Wunsch: Frage deutlich größer als die Antwort */
  font-weight: var(--fw-regular);
  line-height: 1.2;
  cursor: pointer;
  list-style: none;
}
.faq__question::-webkit-details-marker {
  display: none;
}
.faq__question::after {
  content: '+';
  flex-shrink: 0;
  font-size: var(--fs-h3);
  line-height: 1;
}
.faq__item[open] > .faq__question::after {
  content: '\2212';
}
.faq__question:hover {
  color: #21ae71;
}
.faq__question:focus-visible {
  outline: 2px solid var(--stroke-default);
  outline-offset: 4px;
}
.faq__answer {
  padding: 0 0 var(--space-5) 0;
  max-width: 70ch;
  font-size: var(--fs-copy-small); /* User-Wunsch: Antwort kleiner (18px statt 24px) */
}
.faq__answer ul {
  margin: 0;
  padding-left: 1.4em;
  list-style: disc; /* User-Wunsch: Listenzeichen (der Reset entfernt sie sonst) */
}
.faq__answer li::marker {
  color: var(--text-default-default);
}
.faq__answer li + li {
  margin-top: var(--space-2);
}
.faq__answer a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- Grüne Rechtecke als Overlay-Layer ---------------------------------
   Variante 2 (dokument-verankert) ist seit dem Feedback von Marcus fest
   eingebaut und läuft ohne Query; ?exp=1/3 bleiben als Alternativen
   abrufbar, kein sichtbarer Button - siehe main.js.
   pointer-events:none, damit Klicks auf den echten Inhalt durchgehen.
   ?exp=1: Layer bleibt am Bildschirm hängen (position:fixed) - Rechtecke
   sind bildschirm-verankert. ?exp=2: Layer bekommt stattdessen
   .experiment-layer--page (position:absolute, kein overflow:hidden) -
   Rechtecke sind dokument-verankert und scrollen mit dem Inhalt aus dem
   Sichtfeld, statt am Bildschirm zu kleben. Rechtecke werden per JS
   erzeugt, siehe main.js. --------------------------------------------------- */
.experiment-layer {
  position: fixed;
  inset: 0;
  z-index: 9998;
  overflow: hidden;
  pointer-events: none;
}
.experiment-layer--page {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: auto;
  overflow: visible;
}
.experiment-layer__rect {
  position: absolute;
  background: var(--accent-green);
  opacity: 0;
  transition: opacity 1.8s ease; /* User-Wunsch: insgesamt langsamer */
  mix-blend-mode: multiply; /* User-Wunsch: deckendes Grün, das aber
    "unterliegend" wirkt - liegt weiterhin ueber dem Inhalt (fixed Layer),
    aber durch multiply bleibt dunkler Text on top lesbar, statt vom Grün
    verdeckt zu werden. Bei voller opacity:1 sah der Fade-Übergang
    (halbtransparent) verwaschen/deckend aus, daher User-Wunsch: 0.8 statt
    1 als Zielwert - blendet sich sanfter ein. */
}
.experiment-layer__rect.is-visible {
  opacity: 0.6; /* User-Wunsch: dezenter/hintergründiger als 0.8 */
}
@media (prefers-color-scheme: dark) {
  .experiment-layer__rect.is-visible {
    opacity: 0.4; /* Test (User-Wunsch): im Darkmode dezenter als 0.6 */
  }
}
.experiment-layer__rect.is-outline {
  background: transparent; /* exp=3, User-Wunsch: abwechselnd gefüllt/nur
    Rahmen statt immer voll gefüllt */
  border: 2px solid var(--accent-green);
  box-sizing: border-box; /* Rahmen wächst nicht über die gesetzte
    Breite/Höhe hinaus - sonst könnte das am rechten/unteren Rand minimal
    überstehen */
}

/* --- Experiment ?exp=3: Text pauschal ueber den Layer heben (User-Idee,
   Alternative zur is-on-dark-Reduzierung oben). NUR aktiv, wenn
   body.experiment-text-fg gesetzt ist (main.js, ausschliesslich bei
   ?exp=3) - bewusst nicht sitewide/permanent, da z.B. die scroll-
   animierten <span class="text-scroll__char"> auf der Funktionen-Seite
   (Zeichen-für-Zeichen-Animation über animation-range) und mehrere
   position:absolute-Komponenten in Text-Containern (z.B.
   .feature-scroll-pin__text-layer) nicht ungeprüft sitewide ein eigenes
   position:relative bekommen sollten. Unter ?exp=3 ist das isoliert
   testbar, ohne das Standardverhalten der Seite zu berühren. */
.experiment-text-fg h1,
.experiment-text-fg h2,
.experiment-text-fg h3,
.experiment-text-fg p,
.experiment-text-fg a:not(.visually-hidden):not(.tag-pill),
.experiment-text-fg span,
.experiment-text-fg li:not(:has(> .tag-pill)) {
  position: relative;
  z-index: 9999;
}
/* Ausnahme-Bereiche (User-Wunsch, Einwand von Jacky): Elemente mit
   data-exp-skip liegen komplett ÜBER dem Experiment-Layer (z-index 9999 >
   Layer 9998) - die Rechtecke scheinen dort nicht durch. Funktioniert nur,
   weil der Bereich selbst einen deckenden Hintergrund hat (z.B. .logo-wall
   mit --surface-dark-default). Gilt für alle ?exp-Modi. Neue Bereiche:
   einfach data-exp-skip ans Element setzen. */
.experiment-text-fg [data-exp-skip] {
  position: relative;
  z-index: 9999;
}
