/* ==========================================================================
   TESTIMONIALS
   Sitzt direkt unter Services (site-services.php) und teilt sich die
   Slider-Engine (assets/js/slider.js) mit blocks/latest-slider.php. Anders
   als dort liegt der Viewport INNERHALB von .wrapper (kein Full-Bleed, s.
   Snippet) — Karte und .slider-controls (components.css) bleiben dadurch
   auf Wrapper-Breite begrenzt. Pro Ansicht ist immer genau eine Stimme
   sichtbar (.testimonials__item { flex: 0 0 100% }); der Track bekommt
   bewusst KEIN eigenes padding-inline — bei einem scroll-snap-Track
   erzeugt Container-Padding nur am Anfang/Ende des Scrollbereichs Raum,
   nicht zwischen den Items, wodurch die jeweils nächste Karte am Rand
   angeschnitten hereinragen würde. Ohne Padding füllt jede Karte die
   sichtbare Breite exakt, die nächste Karte bleibt vollständig außerhalb.

   Hintergrund nutzt --color-heading-badge-background (wie .tag,
   .placeholder-box, .services__row-number, s. tokens.css).
   Individuelle Panel-Farben (designColorStyle(), Präfix "tm") überschreiben
   Hintergrund/Textfarbe optional via --tm-bg/--tm-fg; alle abgeleiteten
   Töne (Rolle, Trennlinie) laufen über currentColor, damit sie in beiden
   Fällen automatisch mitziehen. Prev/Next-Buttons: s. .slider-controls in
   components.css (geteilt mit blocks/latest-slider.php).
   ========================================================================== */

.testimonials {
  padding-block: var(--space-2xl);
  background: var(--tm-bg, var(--color-heading-badge-background));
  color: var(--tm-fg, var(--color-font-dark));
}

/* Glaseffekt-Hintergrund (Design-Tab "Bild statt Farbe verwenden", s.
   testimonials.yml/testimonials-section.php): --tm-bg bleibt in diesem
   Modus bewusst ungesetzt (designColorStyle()), .testimonials__bg legt sich
   stattdessen als eigener Layer darüber. position:relative + overflow:hidden
   rahmen den überstehenden Blur-Rand (s. inset:-10% unten) sauber ein. */
.testimonials--image-bg {
  position: relative;
  overflow: hidden;
}

.testimonials__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* inset:-10% + scale schieben den weichgezeichneten Bildrand aus dem
   sichtbaren Bereich — der blur()-Filter hellt Kanten sonst sichtbar auf.
   Zwei identische, übereinanderliegende Layer (s. Markup) wechseln sich als
   Crossfade ab: slider.js blendet bei Slide-Wechsel den jeweils
   unsichtbaren Layer mit dem neuen Bild ein, statt hart umzuschalten. */
.testimonials__bg-image {
  position: absolute;
  inset: -10%;
  background-size: cover;
  background-position: center;
  filter: blur(60px) saturate(1.05);
  transform: scale(1.15);
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease-standard);
}

.testimonials__bg-image.is-visible {
  opacity: 1;
}

/* Der angefragte Farbton "in der Mischung": legt sich über beide Bild-Layer
   und imitiert damit den transparenten Glaseffekt, ohne die Bilder selbst
   anzufassen. Hell (Default) passt zu dunkler Schrift, .-dark (Design-Tab
   "Dunklen statt hellen Schleier") kehrt das für helle Schrift um. */
.testimonials__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.55);
}

.testimonials--image-bg-dark .testimonials__bg::after {
  background: rgba(0, 0, 0, 0.55);
}

/* Content-Ebenen (Überschrift + Viewport) müssen über .testimonials__bg
   (z-index:0) liegen, sonst verschwinden sie dahinter. */
.testimonials--image-bg .wrapper {
  position: relative;
  z-index: 1;
}

/* Optik von .testimonials__heading kommt von .section-heading
   (components.css) — Klasse steht im Markup neben dieser BEM-Klasse, die
   hier nur als Hook für künftige section-spezifische Overrides erhalten
   bleibt. */

/* --testimonial-panel-bg: eine Quelle für den Glas-Weißton, den
   .testimonial__quote UND die Slider-Buttons teilen (s. dort) — auf dem
   Viewport (Vorfahre von beiden) statt auf .testimonial__quote selbst
   definiert, damit die Custom Property auch bei den Buttons ankommt (deren
   .testimonial-Geschwister sonst außer Reichweite läge). */
.testimonials__viewport {
  position: relative;
  --testimonial-panel-bg: rgb(255 255 255 / 50%);
}

.testimonials__track {
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: auto;
  scroll-snap-type: x mandatory;
  /* pan-x pan-y statt nur pan-x: reines pan-x lässt vertikale Gesten, die
     AUF dem Slider starten, ohne native Browser-Behandlung — Page-Scroll
     funktionierte dadurch nur noch vom Viewport-Rand aus. pan-x pan-y
     behält die native Richtungs-Arbitrierung (horizontal → Slider,
     vertikal → Page-Scroll), nur Pinch-/Doubletap-Zoom bleiben unterbunden
     (s. gleicher Fix in project-fan.css). */
  touch-action: pan-x pan-y;
  scrollbar-width: none;
  cursor: grab;
}

.testimonials__track::-webkit-scrollbar {
  display: none;
}

.testimonials__track.is-dragging {
  scroll-snap-type: none;
  cursor: grabbing;
  user-select: none;
}

.testimonials__item {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
  /* Zentriert die media-lose Variante von .testimonial (max-width, s.u.),
     ohne dass .testimonial selbst dafür einen margin braucht. */
  display: flex;
  justify-content: center;
}

/* --- Einzelne Stimme: Bild links, Zitat rechts (wie .services__row) ------
   margin:0 nötig: <figure> bekommt sonst den UA-Default-Margin (1em 40px)
   des Browsers, kein Reset dafür in base.css (nur h1-h3/p/ul/ol). Gleich
   breite Spalten (1fr/1fr), damit Bild- und Zitat-Box wie die zwei
   gleich breiten Karten im latest-slider wirken (s. slider.css). */
.testimonial {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  /* --space-md: derselbe Abstand wie zwischen den zwei Karten im
     latest-slider (.latest-slider__track, s. slider.css). */
  gap: var(--space-md);
  /* stretch (statt center): Zitat-Box übernimmt exakt die Höhe der
     Bild-Box (von deren aspect-ratio vorgegeben), statt an ihrem eigenen,
     kürzeren Inhalt auszurichten. */
  align-items: stretch;
  width: 100%;
  margin: 0;
}

.testimonial:not(:has(.testimonial__media)) {
  grid-template-columns: minmax(0, 1fr);
  max-width: 46rem;
  text-align: center;
}

/* height:100% + min-height/-width:0: Chrome leitet die Höhe eines
   Grid-Items auch ganz ohne eigene height-Angabe aus align-items:stretch
   ab und reicht sie an Kinder mit height:100% (das img) durch. Firefox tut
   das in dieser Konstellation nicht zuverlässig — ohne eigene, explizite
   height auf .testimonial__media bleibt dessen Höhe dort unbestimmt, die
   height:100% des img-Kinds hat nichts zum Auflösen und die ganze Media-Box
   kollabiert (nur die Quote-Box bleibt sichtbar). min-height/-width:0
   überschreibt zusätzlich den UA-Default min-height:auto der Grid-Items,
   der sonst ebenfalls gegen die vorgegebene Stretch-Höhe arbeiten kann. */
.testimonial__media {
  height: 100%;
  min-height: 0;
  min-width: 0;
}

/* height:100% (statt der aspect-ratio von .placeholder-box) füllt exakt
   die von align-items:stretch vorgegebene Box-Höhe — bleibt so immer genau
   so hoch wie die Zitat-Box daneben, unabhängig von der Zitatlänge. */
.testimonial__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* margin:0 aus demselben Grund wie .testimonial: <blockquote>-UA-Default.
   background/padding/radius machen daraus eine eigene Box (analog zur
   Bild-Box daneben), s. Anfrage "zwei Boxen" oben. */
.testimonial__quote {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-lg);
  margin: 0;
  /* Bewusst reines #fff statt --color-white (#f8f4f7, s. tokens.css) —
     Anfrage: reines Weiß bei 50% Deckkraft. Als --testimonial-panel-bg
     (.testimonials__viewport oben) definiert, damit die Slider-Buttons
     denselben Ton teilen können. */
  background: var(--testimonial-panel-bg);
  padding: var(--space-lg);
  border-radius: var(--radius-sm);
}

/* justify-content:center auf .testimonial__quote (statt hier flex:1 +
   align-items:center) zentriert Zitat + Autor-Zeile als EINE Gruppe in der
   von align-items:stretch vorgegebenen Box-Höhe (s.o.) — der Leerraum
   verteilt sich dadurch gleichmäßig ÜBER und UNTER der Gruppe, statt (wie
   zuvor mit flex:1 hier) nur innerhalb der Zitat-Box selbst zu liegen und
   den Abstand zur Autor-Zeile bei kurzen Zitaten unnötig aufzublähen.
   display:flex hier bleibt trotzdem nötig: begrenzt die Zeilenbreite des
   <p> auf den Inhalt (justify-content:center), sonst liefe text-align:center
   unten ins Leere, weil der Text sonst die volle Box-Breite einnähme. */
/* Schriftfamilie + -größe kommen von der geteilten .section-introduction-
   Utility (components.css) — dieselbe Formatierung wie
   .project-fan__subtext/.services__intro-text, s. dort. Nur Layout hier. */
.testimonial__text {
  display: flex;
  justify-content: center;
  text-align: center;
  margin: 0;
  /* Kontert body's hyphens:auto (base.css) — in der schmalen Zitat-Box
     trennte das sonst einzelne Wörter mit sichtbarem Trennstrich. Gleiches
     Muster wie .no-word-break (components.css). */
  hyphens: none;
}

.testimonial__by {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-md);
  padding-top: var(--space-sm);
}

.testimonial:not(:has(.testimonial__media)) .testimonial__by {
  justify-content: center;
}

.testimonial__who {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.testimonial__name {
  font-family: var(--font-pixel-grotesk);
  font-weight: var(--fw-bold);
  font-size: calc(var(--fs-body) * 2);
  line-height: var(--lh-tight);
}

.testimonial__role {
  font-family: var(--font-pixel-serif);
  font-size: var(--fs-small);
  line-height: var(--lh-tight);
  color: var(--color-font-dark);
}

.testimonial__logo {
  max-height: 1.75rem;
  width: auto;
  object-fit: contain;
}

/* Prev/Next-Buttons: Optik kommt aus der geteilten .slider-controls-Regel
   (components.css, auch von blocks/latest-slider.php genutzt), Position
   hier aber komplett zurückgesetzt statt des dortigen randbündigen
   Overlays (position:absolute/inset:0/top:40%) — das Overlay legte sich
   bei kurzen Zitaten/schmalem Viewport über den Zitat-Text (s. Anfrage).
   Buttons laufen dadurch stattdessen im normalen Textfluss NACH der Karte,
   rechtsbündig darunter, in jeder Breakpoint-Breite gleich. */
.testimonials__viewport .slider-controls {
  position: static;
  justify-content: flex-end;
  gap: calc(var(--space-xs) * 2 / 3);
  margin-top: var(--space-sm);
}

/* Ecken-Optik aus components.css (.slider-controls .btn: border-radius:0,
   [data-slider-prev|next]:hover: nur innere Ecke rund) war für das
   randbündige Overlay gedacht, wo die Buttons optisch mit der
   Viewport-Kante verschmelzen sollten — hier stattdessen normales
   .btn-icon-Verhalten: allseitig gerundet, unverändert bei Hover. Kein
   Hover-Lift (transform) und kein Radius-Wechsel: die Klasse "scramble" auf
   dem Pfeil-Zeichen (Markup) übernimmt das Hover-Feedback stattdessen über
   den Text-Scramble-Effekt (scramble.js) — gleiches Muster wie
   .next-project__overview (project.css). */
.testimonials__viewport .slider-controls .btn {
  background: var(--testimonial-panel-bg);
  border-radius: var(--radius-sm);
}

.testimonials__viewport .slider-controls .btn:hover {
  transform: none;
}

/* scramble.js hängt den Hover-Trigger direkt ans .scramble-Element (s.
   Datei-Kommentar dort), dessen Hoverfläche ohne dies nur die schmale
   <>-Glyphe selbst wäre statt der ganzen 2.75rem-Button-Fläche
   (.btn-icon, components.css). width/height:100% + eigenes Zentrieren
   lässt den Span die komplette Button-Fläche einnehmen, der Effekt löst
   dadurch beim Hover irgendwo im Button aus, nicht erst über der Schrift. */
.testimonials__viewport .slider-controls .btn .scramble {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* bp: --bp-mobile (640px) */
@media (max-width: 640px) {
  .testimonial,
  .testimonial:not(:has(.testimonial__media)) {
    grid-template-columns: 1fr;
    max-width: none;
    text-align: left;
    gap: 0;
  }

  .testimonial:not(:has(.testimonial__media)) .testimonial__by {
    justify-content: space-between;
  }

  .testimonial__quote {
    padding: calc(var(--space-lg) / 2);
  }

  /* Bild (oben) und Zitat-Box (unten) stoßen dank gap:0 (s.o.) direkt
     aneinander — an dieser gemeinsamen Kante wirken die sonst separat
     gerundeten Ecken beider Boxen wie ein Bruch. Nur an der Stoßkante
     eckig, außen (oben am Bild, unten am Zitat) bleibt die Rundung
     erhalten. Scoped auf :has(.testimonial__media): ohne Bild bleibt die
     Zitat-Box weiterhin allseitig gerundet (zentrierte Solo-Variante). */
  .testimonial:has(.testimonial__media) .testimonial__media img {
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  }

  .testimonial:has(.testimonial__media) .testimonial__quote {
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  }
}
