/* ==========================================================================
   SERVICES
   Intro (Heading + Text) unverändert. Jede Service-Reihe alterniert
   Bild/Content, mit Nummer + Titel als nebeneinanderliegende Badges,
   Tag-Liste, Beschreibungstext und optionalen "Work"-Projektlinks.
   ========================================================================== */

.services {
  padding-block: var(--space-2xl);
  background: var(--color-background);
}

.services__intro {
  display: grid;
  /* minmax(0, 1fr) statt reinem 1fr (= minmax(auto, 1fr)): verhindert, dass
     die Spalte durch .services__intro-texts explizite width:50vw über ihre
     50%-Spaltenbreite hinaus aufgebläht wird und Wrapper/Body breiter als
     der Viewport werden lässt (Grid-"Blowout", s. gleicher Fix an
     .project-fan__intro, project-fan.css, für den identischen Fall). */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  /* row-gap bewusst 0: Die vertikalen Abstände kommen ausschließlich aus
     den margin-bottom-Werten der Elemente selbst (.section-heading:
     --space-lg, .services__heading: s. u.) — vorher addierte sich der
     row-gap zusätzlich zu diesen Margins, wodurch der Abstand unter der
     Bereichsüberschrift in jeder Section anders ausfiel (Latest/
     Testimonials: nur Margin; hier: Margin + Gap). */
  gap: 0 var(--space-lg);
  margin-bottom: var(--space-2xl);
}

.services__label {
  grid-column: 1 / -1;
}

/* Schriftfamilie/-größe/-stil, Zeilenhöhe und Trennungsverhalten kommen
   komplett von der geteilten .intro-heading-Utility (components.css) —
   .project-fan__lead (project-fan.css) erbt denselben Stil darüber. Hier
   nur, was section-spezifisch bleibt: Breite/Grid-Platzierung. Bewusst KEIN
   eigenes font-size mehr hier (s. Kommentar an .intro-heading), damit die
   Größe zentral über --fs-intro-heading (tokens.css) einstellbar bleibt. */
.services__heading {
  grid-column: 1 / -1;
  width: 80%;
  /* --space-lg statt --space-md: gleicher Abstand wie unter allen
     .section-heading-Überschriften (components.css) — der frühere
     row-gap des Intro-Grids (s. o.) ist hier bereits eingerechnet. */
  margin-bottom: var(--space-lg);
}

/* Schriftfamilie + -größe kommen von der geteilten .section-introduction-
   Utility (components.css, im Markup neben dieser Klasse gesetzt) — s. dort
   für die Begründung, warum die Farbe bewusst NICHT Teil der Utility ist.
   Hier nur Layout + das section-spezifische font-weight.
   width bewusst als vw-Einheit statt der Default-Stretch-Breite (100% der
   1fr-Spalte): .wrapper deckelt bei var(--container-max) (base.css) — auf
   sehr breiten Desktop-Viewports jenseits dieser Grenze wächst die Spalte
   selbst nicht mehr mit, wodurch die Box unter 50vw geblieben wäre statt
   proportional mit dem Viewport weiterzuwachsen. justify-self:end hält die
   Box dabei weiterhin rechtsbündig am Wrapper-Rand (Spalte 1 der Zeile, in
   der .services__intro-text landet, bleibt ungenutzt — ein Überlappen mit
   .services__heading, das eine Zeile darüber die volle Breite einnimmt, ist
   dadurch ausgeschlossen). */
.services__intro-text {
  grid-column: 2;
  justify-self: end;
  width: 50vw;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  font-weight: var(--fw-light);
}

.services__rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

.services__row {
  display: grid;
  /* 5 Spalten (0.5fr + 4×1fr) statt schlicht 4: die 0.5fr-Spalte zählt zu
     Media dazu (s. .services__row-media unten) und liegt IMMER auf der
     Bild-Außenseite (hier links, für --reverse-Zeilen — die
     :not(--reverse)-Regel unten hängt dieselbe Spalte stattdessen rechts
     an) — Media läuft dadurch bis an den jeweils nächstgelegenen
     Wrapper-Rand statt eine Spalte davor zu enden. Content bleibt in
     BEIDEN Zeilenrichtungen bei 3fr auf derselben Spaltensumme (4.5fr),
     Media bei 1.5fr — Voraussetzung dafür, dass .services__row-text (s. u.)
     unabhängig von Zeilenrichtung/Viewport-Breite immer gleich breit
     läuft. grid-template-rows (3 Tracks: Titel / Tag-Liste / Rest) ist die
     Grundlage für das subgrid unten, über das die Media-Spalte exakt auf
     Höhe der Tag-Liste beginnen kann. */
  grid-template-columns: 0.5fr repeat(4, 1fr);
  grid-template-rows: auto auto 1fr;
  row-gap: var(--space-lg);
  /* --reverse-Zeilen (Bild links, 2., 4., 6. …) nutzen diesen Wert direkt
     als Content-Media-Abstand. Normale Zeilen (1., 3., 5. …, Bild rechts)
     überschreiben ihn unten auf ein Viertel (var(--space-md)) — die Basis
     steht deshalb schon auf dem vierfachen Wert, statt ihn separat auf
     .services__row--reverse zu duplizieren. */
  column-gap: calc(var(--space-md) * 4);
  align-items: stretch;
}

/* Nur normale Zeilen (1., 3., 5. … — Bild rechts vom Text) rücken näher an
   den Text heran (ein Viertel des column-gap der Basis-Regel oben). 5. Spalte
   (0.5fr statt 1fr — schmaler als die anderen) zählt zu Media (grid-column
   4/6, s. .services__row-media unten): Content (1/4) bleibt bei 3 Spalten,
   Bild bei 1.5 (4 + die schmale 5.) und läuft damit bündig bis an den
   Wrapper-Rand statt eine Spalte davor zu enden. --reverse (Basis-Regel
   oben) spiegelt dieselbe 5-Spalten-Aufteilung — die 0.5fr-Spalte liegt
   dort links statt rechts, aus demselben Grund (Bild bündig zum Rand auf
   der linken Seite). */
.services__row:not(.services__row--reverse) {
  grid-template-columns: repeat(4, 1fr) 0.5fr;
  column-gap: var(--space-md);
}

/* Content nimmt Spalte 1-3, Media Spalte 4 (normale Zeilen) — bei
   --reverse gespiegelt auf Spalte 3-6 bzw. 2-3 (s. u.), weil dort die freie
   0.5fr-Spalte links statt rechts liegt (Basis-Regel oben). Explizite
   grid-column statt vormals order: Zeilen-Reihenfolge (oben/unten) und
   Spalten-Reihenfolge (links/rechts) sind damit unabhängig voneinander
   steuerbar, was das subgrid unten braucht. */
.services__row-content {
  grid-column: 1 / 4;
  /* Spannt alle 3 Zeilen der Row und gibt sie per subgrid an die eigenen
     Kinder weiter (Titel/Tag-Liste/Rest — s. .services__row-top unten),
     damit .services__row-media unten exakt auf der Tag-Liste-Zeile
     aufsetzen kann statt nur grob am Content-Block insgesamt. */
  grid-row: 1 / -1;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: var(--space-sm);
}

.services__row--reverse .services__row-content {
  grid-column: 3 / 6;
}

/* Löst sich als Box auf: Titel und Tag-Liste (ihre beiden Kinder) werden
   dadurch direkte Subgrid-Items von .services__row-content und landen
   automatisch in Zeile 1 bzw. 2 der 3 Zeilen oben (auto-placement in
   Dokumentreihenfolge) — Voraussetzung dafür, dass .services__row-media
   unten in Zeile 2 (Tag-Liste) statt nur in Zeile 1 (Titel) starten kann. */
.services__row-top {
  display: contents;
}

/* Gleiche max-width wie .services__row-text (s. u.) — Tag-Liste bricht
   dadurch auf derselben Breite um wie der Absatz darunter, statt (als
   Subgrid-Item ohne eigene Breite) die volle Content-Spalte auszunutzen. */
.services__row-top .tag-list {
  max-width: 50vw;
}

.services__row-media {
  /* 4/6 statt 4/5: nimmt die schmale 5. Spalte (s. .services__row oben)
     mit dazu, damit das Bild bündig am rechten Wrapper-Rand endet statt
     eine Spalte davor. */
  grid-column: 4 / 6;
  /* Start in Zeile 2 (= Tag-Liste-Zeile, s. o.): Bild/Video beginnt damit
     oben bündig mit der Tag-Liste statt mit dem (oft höheren, weil
     zeilenumbrechenden) Titel darüber. */
  grid-row: 2 / -1;
  display: flex;
  align-items: flex-start;
}

.services__row--reverse .services__row-media {
  /* Spiegelt die :not(--reverse)-Regel oben: 1/3 nimmt die schmale 1.
     Spalte (hier links, s. .services__row oben) mit dazu, damit das Bild
     bündig am linken Wrapper-Rand endet. */
  grid-column: 1 / 3;
}

/* Bild/Video füllt die eigene Grid-Spalte komplett aus — kein Hintergrund,
   kein festes Seitenverhältnis mehr (aspect-ratio: auto überschreibt das
   feste --placeholder-ratio der Basisklasse), damit das Motiv in seinem
   natürlichen Format ohne Letterboxing/Farbfläche erscheint. */
.services__row-media a.placeholder-box,
.services__row-media video.placeholder-box {
  width: 100%;
  aspect-ratio: auto;
  background: none;
  /* border-radius erbt .placeholder-box (components.css) zwar schon, aber
     ohne Hintergrund/festes Seitenverhältnis (s. o.) rundet das allein
     nicht mehr sichtbar ab — overflow:hidden schneidet dafür explizit die
     Ecken des <img> innen (bzw. beim <video> direkt sich selbst) auf
     var(--radius-sm) zu, derselben Variable wie überall sonst im Projekt. */
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.services__row-media a.placeholder-box img {
  display: block;
  width: 100%;
  height: auto;
}

/* Nummer über statt neben dem Titel, beide linksbündig — vormals nur im
   Mobile-Breakpoint (s. u.), jetzt global. */
.services__row-title {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-xs);
  margin: 0;
}

.services__row-number {
  display: inline-block;
  border-radius: var(--radius-sm);
  /* Gleiches Rezept wie .tag (components.css): Pixel-Grotesk, line-height 1,
     asymmetrisches Nudge-Padding, --ls-btn-tag — vorher lief die Nummer in
     Space Mono (--font-logo) mit eigenem letter-spacing und wich damit als
     einzige Pille vom site-weiten Tag-Design ab. */
  line-height: 1;
  padding-inline: 0.9em;
  padding-block: calc(0.35em - var(--font-pixel-grotesk-nudge)) calc(0.35em + var(--font-pixel-grotesk-nudge));
  /* Gleiches Schwarz wie der aktive Nav-Button und die .placeholder-box
     oben (--color-nav-button-active-background) statt des transparenten
     --color-heading-badge-background — dazu helle statt dunkle Schrift
     (--color-font-bright), sonst nicht mehr lesbar auf deckendem Schwarz. */
  background: var(--color-nav-button-active-background);
  font-family: var(--font-pixel-grotesk);
  font-size: var(--fs-tag);
  color: var(--color-font-bright);
  text-transform: uppercase;
  letter-spacing: var(--ls-btn-tag);
}

/* Eigenes Badge pro Phrase statt einer Box um den gesamten Titel — gleiches
   Muster wie .section-heading/.section-heading__word (components.css),
   hier mit der größeren Row-Title-Schriftgröße statt --fs-h2. PHP zerlegt
   den Titel dafür bereits an &/,/+ in .services__row-title-word-Spans
   (sectionHeadingPhrases(), helpers.php) statt einem einzigen Textknoten —
   mehrere Wörter zwischen zwei Trennzeichen bleiben dabei in einem
   gemeinsamen Badge; scramble.js wrapped darin bei Sichtbarkeit zusätzlich
   jedes Wort nochmal in .scramble — kein Konflikt, genau diese Kombination
   läuft an h2.section-heading (Latest/Testimonials/Project-Fan) schon
   länger. */
.services__row-title-text {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-pixel-grotesk);
  /* --fs-section-heading (tokens.css): exakt derselbe responsive Wert wie
     .section-heading (components.css) — ein früherer fixer 2.9rem-Wert
     (nur das --fs-h2-Maximum) blieb auf schmaleren Viewports größer als die
     tatsächlich responsiv schrumpfende .section-heading daneben, wodurch
     beide H2/H3-Badge-Überschriften der Seite nicht mehr gleich groß
     liefen. */
  font-size: var(--fs-section-heading);
  line-height: var(--lh-tight);
  color: var(--color-font-dark);
}

.services__row-title-word {
  padding-inline: 0.3rem;
  /* Asymmetrisch statt "padding: 0.5rem 0.3rem" — s. --font-pixel-grotesk-
     nudge (tokens.css). */
  padding-block: calc(0.5rem - var(--font-pixel-grotesk-nudge)) calc(0.5rem + var(--font-pixel-grotesk-nudge));
  /* Schwarz statt --color-badge-background (s. --color-heading-badge-background
     in tokens.css) — geteilt mit .section-heading (components.css). */
  background: var(--color-heading-badge-background);
  border-radius: var(--radius-sm);
}

/* Trennzeichen (&, ,, +) zwischen den Badges: jetzt selbst ein Badge, 1:1
   dasselbe Rezept wie .services__row-title-word (padding-inline/
   Hintergrund/Radius) statt vorher unsichtbar im Fließtext zu stehen. Das
   padding-block-Rezept (s. --font-pixel-grotesk-nudge, tokens.css) war
   schon vorher identisch übernommen. */
.services__row-title-separator {
  padding-inline: 0.3rem;
  padding-block: calc(0.5rem - var(--font-pixel-grotesk-nudge)) calc(0.5rem + var(--font-pixel-grotesk-nudge));
  background: var(--color-heading-badge-background);
  border-radius: var(--radius-sm);
  line-height: var(--lh-tight);
}

/* Dunkle Variante — zusätzliche Modifier-Klasse auf .services__row-title-text
   (Markup ergänzen, .services__row-title-word/-separator selbst bleiben
   unverändert), analog zu .tag--dark (components.css). Gleiches
   Schwarz/Hell-Paar wie .services__row-number oben
   (--color-nav-button-active-background/--color-font-bright) statt des
   halbtransparenten --color-heading-badge-background/--color-font-dark der
   Basis-Variante — echtes Schwarz statt der 10%-Deckkraft-Mischung, weil
   hier (anders als bei .section-heading--dark, components.css) kein
   dunkler Section-Hintergrund darunterliegt, auf dem ein Glas-Effekt
   Kontrast bräuchte. color auf dem Text-Container reicht: die Badges
   selbst setzen keine eigene color, erben sie also von hier. */
.services__row-title-text--dark {
  color: var(--color-font-bright);
}

.services__row-title-text--dark .services__row-title-word,
.services__row-title-text--dark .services__row-title-separator {
  background: var(--color-nav-button-active-background);
}

.services__row-bottom {
  /* Zeile 3 des subgrid (s. .services__row-content oben) — align-self:end
     hält Text/CTA unten in dieser (durch 1fr) flexiblen Zeile, statt dass
     sie direkt unter der Tag-Liste kleben: der übrige Weißraum entsteht
     dadurch oberhalb von .services__row-bottom, nicht darunter. */
  grid-row: 3;
  align-self: end;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-md);
  flex-wrap: wrap;
}

.services__row-text {
  flex: 1;
  /* Gleicher Wert wie .services__intro-text (s. o.): Struct-Texte der
     einzelnen Rows sollen optisch gleich breit laufen wie der
     Einleitungstext, statt an einer eigenen ch-Breite zu hängen. */
  max-width: 50vw;
  font-size: var(--fs-body);
}

.services__row-cta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex-shrink: 0;
  gap: var(--space-2xs);
  text-align: right;
}

/* Typografie wie .tag/.tracking-wide (components.css) statt Space Mono —
   s. Kommentar an .services__row-number oben. */
.services__row-cta-label {
  font-family: var(--font-pixel-grotesk);
  font-size: var(--fs-tag);
  text-transform: uppercase;
  letter-spacing: var(--ls-btn-tag);
  color: var(--color-font-dark);
}

.services__row-cta-list {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Gleiches Pill-Rezept wie .tag (components.css) inkl. Hintergrundfarbe —
   vorher opakes --color-badge-background + Space-Mono-Typo, die dritte
   abweichende Pill-Variante auf der Startseite. Der Hover (s. u.) bleibt
   als Link-spezifische Interaktion erhalten. */
.services__row-cta-list a {
  display: inline-flex;
  align-items: center;
  line-height: 1;
  padding-inline: 0.9em;
  padding-block: calc(0.35em - var(--font-pixel-grotesk-nudge)) calc(0.35em + var(--font-pixel-grotesk-nudge));
  background: var(--color-heading-badge-background);
  color: var(--color-badge-font);
  font-family: var(--font-pixel-grotesk);
  font-size: var(--fs-tag);
  text-transform: uppercase;
  letter-spacing: var(--ls-btn-tag);
  border-radius: var(--radius-sm);
  text-decoration: none;
  white-space: nowrap;
}

.services__row-cta-list a:hover,
.services__row-cta-list a:focus-visible {
  background: var(--color-border);
}

/* bp: --bp-tablet (1024px) — im 5-spaltigen Grid würde ein fixer Gap sonst
   auf schmaleren Viewports der Bildspalte den nötigen Platz nehmen und sie
   unter das eigentliche Seitenverhältnis drücken. Stattdessen schrumpft
   hier der Gap, damit Bild und Text-Inhalt ihr Breitenverhältnis
   (Basis-Regel: 4.5 Spalten, Content span 3) und das eigene (natürliche)
   Seitenverhältnis der Bilder behalten. */
@media (max-width: 1024px) {
  .services__row {
    gap: var(--space-md);
  }
}

/* bp: --bp-mobile (640px) */
@media (max-width: 640px) {
  .services__intro {
    grid-template-columns: 1fr;
  }

  .services__heading {
    width: 100%;
    max-width: none;
  }

  .services__intro-text {
    width: 100%;
    /* grid-column: Basis-Regel setzt 2 (services.css oben) — im 1-Spalten-
       Grid hier würde der Browser dafür sonst eine implizite zweite Spalte
       anlegen und .services__intro-text landet neben statt unter
       .services__heading. */
    grid-column: 1;
  }

  /* .services__row:not(.services__row--reverse) explizit mitgeführt: die
     Regel dort (services.css oben) hat höhere Spezifität als ein einfaches
     .services__row und würde diesen Reset für normale Zeilen sonst
     überstimmen. */
  .services__row,
  .services__row--reverse,
  .services__row:not(.services__row--reverse) {
    grid-template-columns: 1fr;
  }

  /* Im 1-Spalten-Grid gestapelt statt nebeneinander: die subgrid-Kopplung
     von Content und Media an die 3 Zeilen der Row (Basis-Regel oben) macht
     hier keinen Sinn mehr — beide bekommen ihre Grid-Platzierung zurückgesetzt
     und Content wechselt zurück auf ein normales Flex-Layout, in dem
     display:contents (s. u.) wieder frei nach order sortieren kann.
     .services__row--reverse .services__row-content explizit mitgeführt:
     die --reverse-Regeln (Basis + Tablet-Breakpoint oben) haben höhere
     Spezifität als ein einfaches .services__row-content und würden diesen
     Reset sonst überstimmen. */
  .services__row-content,
  .services__row--reverse .services__row-content {
    grid-column: 1;
    grid-row: auto;
    display: flex;
    flex-direction: column;
  }

  /* Dasselbe für Media: sowohl die --reverse- als auch die :not(--reverse)-
     Regel (Basis + Tablet-Breakpoint oben) haben höhere Spezifität als ein
     einfaches .services__row-media. */
  .services__row-media,
  .services__row--reverse .services__row-media,
  .services__row:not(.services__row--reverse) .services__row-media {
    grid-column: 1;
    grid-row: auto;
  }

  /* .services__row-top löst sich bereits ab der Basis-Regel als Box auf
     (display:contents); .services__row-bottom zieht hier nach — ihre Kinder
     (Titel, Tag-Liste, Text, CTA) werden dadurch direkte Flex-Items von
     .services__row-content und lassen sich per order neu anordnen: Tags
     sollen hier unter .services__row-text stehen statt wie im Desktop-
     Layout neben dem Titel. Der gap von .services__row-content (services.css
     oben) übernimmt automatisch den Abstand zwischen allen vier Items. */
  .services__row-bottom {
    display: contents;
  }

  .services__row-title {
    order: 1;
  }

  .services__row-text {
    order: 2;
    /* Explizite volle Breite statt weiterhin auf den fit-content-Effekt von
       align-items:flex-start (s. o.) zu vertrauen. (.project-fan__subtext hat
       seit der .section-introduction-Utility keine Layout-Klasse mehr mit
       .services__row-text gemeinsam und setzt sein eigenes width:100% direkt
       in project-fan.css, gleicher Breakpoint.) */
    width: 100%;
  }

  .services__row-top .tag-list {
    order: 3;
  }

  .services__row-cta {
    order: 4;
  }

  .services__row-cta,
  .services__row-cta-list {
    align-items: flex-start;
    text-align: left;
  }
}
