/* ============================================================================
   BECRO Trading — becro-motion.css
   Der Stilanteil der Bewegungs-Schicht (GSAP + ScrollTrigger, becro-motion.js).
   Nur index.html bindet die Datei ein, und zwar NACH becro-dark.css.

   Hier steht ausschliesslich, was Bewegung ueberhaupt erst moeglich macht —
   keine Farbe, keine Groesse, kein Abstand. Alles haengt an `html.motion`;
   diese Klasse setzt becro-motion.js selbst, und nur dann, wenn es wirklich
   animiert. Bei `prefers-reduced-motion` oder ausgefallenem CDN bleibt sie
   weg und es gilt unveraendert das Verhalten aus becro-dark.css.

   Der ?v=N-Parameter muss bei jeder Aenderung hochgezaehlt werden.
   ========================================================================== */


/* ══ 1 · Das Einblenden gehoert GSAP ═══════════════════════════════════════
   becro-dark.css blendet `.reveal` ueber `translate` + `transition` ein. Laeuft
   die Bewegungs-Schicht, macht GSAP dieselbe Arbeit ueber `transform`, Bild
   fuer Bild. Bliebe die CSS-Transition daneben stehen, daempfte sie jeden
   dieser Frames und die Bewegung liefe traege hinterher — deshalb ist sie aus,
   solange ein Element noch nicht drin ist.

   `translate: none` nimmt zusaetzlich den 20px-Versatz aus becro-dark.css
   weg: GSAP bringt seine eigenen 25px mit, beides zusammen waeren 45px.

   Nach dem Lauf traegt das Element `in`, seine Inline-Werte sind wieder
   entfernt und die Transitions sind zurueck — sonst schluege der von GSAP
   gesetzte `transform` das Anheben beim Hover (Inline gewinnt gegen alles). */
html.motion .reveal { translate: none; }
html.motion .reveal:not(.in) { transition: none; }


/* ══ 2 · Die Marken-Linie messbar machen ═══════════════════════════════════
   Die kurze Linie neben „01 Der Ansatz" ist ein ::after — an Pseudoelemente
   kommt kein Skript heran. Ihre Breite laeuft deshalb ueber eine Variable, die
   GSAP am Element selbst animiert. Der Rueckfallwert ist exakt die alte
   Breite: greift die Animation nicht, steht die Linie da wie bisher. */
html.motion .kicker-rule::after { width: var(--kicker-w, 84px); }


/* ══ 3 · Logo-Band als Marquee ═════════════════════════════════════════════
   Den Wrapper `.logo-marquee` baut becro-motion.js zur Laufzeit um die Reihe
   und legt eine zweite, identische Gruppe daneben; die Spur laeuft genau um
   eine Gruppenbreite plus einen Abstand weiter und faengt dann von vorn an —
   an der Nahtstelle steht dann wieder dasselbe Bild.

   Ohne Skript passiert nichts davon: `.logo-row` bleibt die zentrierte,
   umbrechende Reihe aus becro-dark.css, Abschnitt 11.

   Der Abstand ist derselbe Wert wie dort; er steht hier ein zweites Mal, weil
   ihn die geklonte Gruppe ebenfalls braucht. Aendert er sich drueben, muss er
   hier mitwandern. */
.logo-marquee {
  --logo-gap: clamp(1.8rem, 5vw, 3.6rem);
  overflow: hidden;
  /* Weiche Kanten statt hartem Schnitt am Rand des Bandes. Reine Alpha-Maske,
     sie faerbt nichts um. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.logo-marquee .logo-row {
  flex-wrap: nowrap;
  justify-content: flex-start;
  width: max-content;
  gap: var(--logo-gap);
  /* Die Spur wird dauerhaft verschoben — eigene Ebene, damit das Band auf
     dem Handy nicht bei jedem Bild neu gerastert wird. */
  will-change: transform;
}
.logo-group {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: var(--logo-gap);
}


/* ══ 3b · Der Lauf selbst: eine CSS-Animation ════════════════════════
   Früher zog GSAP die Spur Bild für Bild ueber `x`. Auf dem Handy hing das
   sichtbar: jeder Frame lief durch den Haupt-Thread, und der war beim Scrollen
   ohnehin beschaeftigt. Eine CSS-Animation auf `transform` laeuft dagegen im
   Compositor — kein Skript, kein Layout, kein Ruckeln.

   becro-motion.js misst nur noch und schreibt zwei Werte auf die Spur:
     --marquee-span : die Strecke einer Gruppe plus Abstand (px)
     --marquee-dur  : wie lange die Spur fuer diese Strecke braucht (s)
   Weil an der Nahtstelle wieder dasselbe Bild steht, sieht man den Sprung von
   100% zurueck auf 0% nicht.

   Richtung: dieselben Keyframes rueckwaerts — `reverse` laeuft von -span auf
   0, also nach rechts. Ein zweiter Keyframe-Satz waere dieselbe Strecke
   doppelt gepflegt. */
@keyframes becro-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-1 * var(--marquee-span, 0px))); }
}
.marquee-track {
  animation: becro-marquee var(--marquee-dur, 40s) linear infinite;
  /* Eigene Compositor-Ebene, damit die Spur nicht bei jedem Bild neu
     gerastert wird. Steht auch bei `.logo-marquee .logo-row` und
     `.t-rail .t-row` — hier noch einmal, weil die Klasse das Skript setzt und
     die Regel damit unabhaengig von der jeweiligen Reihe gilt. */
  will-change: transform;
}
.marquee-rail[data-dir="right"] .marquee-track { animation-direction: reverse; }
/* Angehalten wird ueber den Rahmen: ausserhalb des Bildes (IntersectionObserver)
   und, bei den Bewertungsreihen, unter dem Mauszeiger. */
.marquee-rail.is-paused .marquee-track { animation-play-state: paused; }

/* Auf dem Handy ein gutes Drittel langsamer. Die Spur ist dort kuerzer und
   die Logos stehen dichter beieinander — mit dem Desktop-Tempo huschen sie
   durchs Bild, statt gelesen werden zu koennen. Langsamer heisst ausserdem
   weniger neu zusammengesetzte Flaeche pro Bild, waehrend daneben gescrollt
   wird.

   Umschaltpunkt 900px statt 640px: 640 traf nur das Hochformat, im
   Querformat (bis 926px auf den grossen Geraeten) lief die Spur weiter im
   Desktop-Tempo. `pointer: coarse` nimmt die Tablets dazu — dort gilt
   dasselbe Argument. */
@media (max-width: 900px), (pointer: coarse) {
  .marquee-track { animation-duration: calc(var(--marquee-dur, 40s) * 1.4); }
}

@media (prefers-reduced-motion: reduce) {
  /* Sicherheitsnetz. becro-motion.js baut die Marquees in diesem Fall gar
     nicht erst auf; sollte die Klasse trotzdem einmal am Element landen,
     steht die Spur still. */
  .marquee-track { animation: none; }
}


/* ══ 4 · Bewertungs-Reihen als Marquee ═════════════════════════════════════
   Zwei gegenlaeufige Reihen, endlos, ohne Skript. Das Standardmuster:

     .t-rail   klippt und liegt randlos ueber die volle Fensterbreite
     .t-track  traegt den Kartensatz ZWEIMAL und wandert 0 -> -50%
     .t-set    ein Satz Karten; alles ausser dem ersten ist eine Kopie

   Bei -50% ist die Spur um genau eine Haelfte gewandert — dort steht dann die
   zweite, identische Haelfte an der Stelle der ersten. Der Ruecksprung auf 0
   ist deshalb unsichtbar, und es braucht weder Messung noch Klonen zur
   Laufzeit. Die alte Fassung liess das Skript die Strecke ausrechnen und
   Kopien nachlegen; verrechnete es sich, lief die Reihe leer oder riss eine
   Luecke auf — genau das ist hier baulich nicht mehr moeglich.

   Der Abstand zwischen den Karten haengt am `margin-right` der KARTE, nicht
   an `gap` der Spur. Das ist der Kern des Musters: mit `gap` waere die Spur
   `2 x Satz + 1 Abstand` breit und -50% laege um einen halben Abstand
   daneben — ein kleiner, aber bei jeder Runde sichtbarer Ruck. Mit
   `margin-right` traegt jede Karte ihren Abstand selbst, die Spur ist exakt
   `2 x Satz` breit, und -50% trifft die Naht auf das Pixel.

   Die zweite Bedingung steht im Markup: eine Haelfte muss mindestens so
   breit sein wie das Fenster. Sonst faengt die Spur zwar sauber von vorn an,
   aber am rechten Rand steht nichts mehr. */

.t-rows {
  /* Feste Kartenbreite. Nicht `clamp`: eine Breite, die stufenlos an der
     Fensterbreite haengt, veraendert die Satzbreite bei jedem Pixel
     Groessenaenderung — und damit das Tempo. */
  --t-card: 360px;
  --t-gap: 16px;
}

/* Die Reihen laufen ueber die volle Fensterbreite, nicht nur ueber die
   Spalte — sonst stuenden links und rechts leere Streifen und die Karten
   kaemen nicht aus dem Rand, sondern aus dem Nichts.

   `50% - 50vw` zieht den Rahmen aus der Spalte heraus bis an die
   Fensterkante. 100vw zaehlt die Scrollleiste mit, das sind ein paar Pixel
   zu viel; `overflow-x: clip` am Abschnitt faengt sie ab, ohne — anders als
   `hidden` — einen Scrollcontainer aufzumachen. Die Maske hat den Rand an
   dieser Stelle ohnehin schon auf null gezogen, man sieht davon nichts. */
#beleg { overflow-x: clip; }

.t-rail {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
  /* Platz nach oben und unten fuer das Anheben beim Hover samt Streulicht;
     die negativen Aussenabstaende nehmen ihn dem Layout wieder weg, sodass
     der Abstand der Reihen bleibt, wie er im Raster war. */
  padding-block: 8px;
  margin-block: -8px;
  /* Weiche Kanten statt hartem Schnitt. Reine Alpha-Maske, sie faerbt
     nichts um. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}

@keyframes becro-testi {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.t-track {
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  width: max-content;
  /* Linear und ohne Pause: eine Reihe, die beschleunigt oder kurz steht,
     liest sich als Fehler, nicht als Gestaltung. */
  animation: becro-testi var(--t-dur, 70s) linear infinite;
  /* Eigene Compositor-Ebene — die Spur wird dauerhaft verschoben und soll
     auf dem Handy nicht bei jedem Bild neu gerastert werden. */
  will-change: transform;
}

/* Untere Reihe nach rechts: dieselben Keyframes rueckwaerts, also von -50%
   auf 0. Ein zweiter Keyframe-Satz waere dieselbe Strecke doppelt gepflegt. */
.t-rail[data-dir="right"] .t-track { animation-direction: reverse; }

/* Angehalten wird ueber den Rahmen — becro-motion.js setzt die Klasse unter
   dem Mauszeiger und ausserhalb des Bildes. Das ist das EINZIGE, was ein
   Skript an diesen Reihen tut; bewegt wird ausschliesslich hier. */
.t-rail.is-paused .t-track { animation-play-state: paused; }

.t-set {
  display: flex;
  align-items: stretch;
  flex: 0 0 auto;
}

/* Feste Breite und fester Abstand an der Karte selbst — siehe oben, davon
   haengt die Genauigkeit der Naht ab. Die Hoehe macht `stretch`: alle Karten
   einer Reihe sind so hoch wie die hoechste. */
.t-rail .t-card {
  flex: 0 0 var(--t-card);
  width: var(--t-card);
  margin-right: var(--t-gap);
}

/* Damit "so hoch wie die hoechste" nicht heisst "so hoch wie die laengste
   Bewertung": nach fuenf Zeilen ist Schluss. Der Rest steht bei Trustpilot,
   und dorthin fuehrt die Karte ohnehin. */
.t-rail .quote {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
}
/* Die Zeile mit Name und Datum sitzt unten, auch wenn das Zitat kuerzer ist —
   sonst schwimmt sie in jeder Karte auf einer anderen Hoehe. */
.t-rail .t-meta { margin-top: auto; padding-top: 1.2rem; }

/* Tempo. Die obere Reihe traegt acht Karten je Haelfte, die untere neun —
   die untere Haelfte ist also 9/8 so breit. Damit beide Reihen mit
   demselben Tempo laufen und nicht nur in derselben Zeit ankommen, bekommt
   die untere die um 9/8 laengere Dauer. Beides bleibt im Rahmen von 60-80
   Sekunden je Durchlauf: rund 43 Pixel pro Sekunde, eine Karte braucht knapp
   neun Sekunden durchs Bild. */
.t-rows > .t-rail:nth-child(1) { --t-dur: 70s; }
.t-rows > .t-rail:nth-child(2) { --t-dur: 79s; }

/* Auf dem Handy eine Karte, die das Bild fuellt: 80vw laesst rechts genau so
   viel von der naechsten stehen, dass klar ist, dass die Reihe weiterlaeuft.

   `vw` und nicht `px`: eine feste Breite ist auf 320px zu breit und auf
   430px zu schmal, und die Reihe soll auf jedem Geraet dasselbe Bild
   zeigen. Weil die Kartenbreite in die Satzbreite eingeht und die Dauer
   gleich bleibt, laeuft die Reihe auf dem Handy ohnehin langsamer — der
   Faktor darunter legt noch etwas drauf. */
@media (max-width: 767px) {
  .t-rows { --t-card: 80vw; }
}

/* Umschaltpunkt 900px statt 640px: 640 traf nur das Hochformat, im
   Querformat (bis 926px auf den grossen Geraeten) lief die Spur weiter im
   Desktop-Tempo. `pointer: coarse` nimmt die Tablets dazu — dort gilt
   dasselbe Argument. Langsamer heisst ausserdem weniger neu zusammengesetzte
   Flaeche pro Bild, waehrend daneben gescrollt wird. */
@media (max-width: 900px), (pointer: coarse) {
  .t-track { animation-duration: calc(var(--t-dur, 70s) * 1.3); }
}

/* Reduzierte Bewegung: statisches Raster, genau wie vor dem Umbau. Die
   Kopien verschwinden, der erste Satz wird wieder zur Spalte, und der Rahmen
   gibt seine Fensterbreite samt Maske ab. Es gibt genau zwei Zustaende, nie
   eine Mischung. */
@media (prefers-reduced-motion: reduce) {
  .t-rail {
    width: auto;
    margin-inline: 0;
    overflow: visible;
    padding-block: 0;
    margin-block: 0;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .t-track {
    display: block;
    width: auto;
    animation: none;
    will-change: auto;
  }
  .t-set {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
  }
  /* Zwei Klassen, damit die Regel gegen `.t-set` darueber gewinnt — beide
     haetten sonst dieselbe Spezifitaet und die spaetere setzte sich durch. */
  .t-set.t-dup { display: none; }
  .t-rail .t-card {
    flex: 0 1 auto;
    width: auto;
    margin-right: 0;
  }
}


/* ══ 5 · Wege, die aus der Spalte laufen ═══════════════════════════════════
   Abschnitt 01 klappt auf: die drei Kacheln kommen von LINKS, der Textblock
   von RECHTS. Abschnitt 05 macht dasselbe mit Portrait und Text. Auf dem Weg
   dorthin stehen die Elemente bis zu 80px neben ihrem Platz — auf einem
   schmalen Schirm also neben dem Bild.

   `overflow-x: clip` faengt das ab. Nicht `hidden`: das machte aus dem
   Abschnitt einen Scroll-Container, und ein Scroll-Container faengt
   `scrollIntoView` und Ankersprünge ab. `clip` schneidet nur. Dieselbe
   Loesung wie bei `#beleg` weiter oben und bei der Timeline in
   becro-dark.css.

   Senkrecht bleibt sichtbar (`clip` erzwingt nichts auf der anderen Achse) —
   Streulicht und Schatten der Kacheln laufen also weiterhin frei. */
html.motion #ansatz,
html.motion #ueber { overflow-x: clip; }


/* ══ 6 · Das Skyline-Band: Wort fuer Wort ══════════════════════════════════
   becro-motion.js zerlegt „Verständnis. Klarheit. Performance." in drei
   Woerter. Damit sich ein Wort ueberhaupt verschieben laesst, braucht es
   eine eigene Box — ein `<span>` im Textfluss ist `display: inline` und
   ignoriert `transform`.

   `inline-block` und nicht `block`: die drei Woerter sollen in EINER Zeile
   stehen bleiben (und auf schmalen Schirmen normal umbrechen duerfen), nicht
   untereinander. */
.band-line .bw { display: inline-block; }


/* ══ 7 · Einmalige Licht-Blitze ════════════════════════════════════════════
   Drei Stellen bekommen beim Ankommen einen kurzen Schein: das
   Trustpilot-Abzeichen (gruen), die Einstiegskarte in Abschnitt 04 und das
   CTA-Panel in Abschnitt 06 (beide im Markenblau).

   Gebaut wie die Punkte der Handelstag-Timeline in becro-dark.css: der
   Schein steht FERTIG im Pseudoelement — Rahmenfarbe, Streulicht, alles
   statisch. Animiert werden ausschliesslich `opacity` und `transform`.
   Ein Verlauf auf `box-shadow` saehe genauso aus und muesste die Flaeche in
   jedem Bild neu malen; so rechnet das der Compositor.

   Eine Animation, kein Uebergang: sie soll einmal laufen und fertig sein.
   becro-motion.js nimmt die Klasse danach wieder ab, damit ein spaeteres
   Neuvermessen sie nicht ein zweites Mal zuendet. */
html.motion {
  /* GSAPs power3.out als CSS-Kurve — dieselbe wie `--tl-ease` an der
     Timeline, damit die ganze Seite eine Handschrift hat. */
  --mo-ease: cubic-bezier(.215, .61, .355, 1);
}

html.motion .rating,
html.motion .plan.featured,
html.motion .access { position: relative; }

html.motion .rating::after,
html.motion .plan.featured::after,
html.motion .access::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
  /* Der Blitz liegt ueber der Flaeche, aber unter dem Inhalt. `.panel-hero`
     setzt seine Kinder auf `position: relative`, damit sie ueber dem
     Hintergrund liegen — dasselbe gilt hier. */
  z-index: 0;
}

/* Gruen: das Abzeichen ist ein Beleg, kein Angebot. Es traegt die Farbe der
   Sterne, nicht die der Marke. */
html.motion .rating::after {
  border: 1px solid rgba(118, 202, 40, .85);
  box-shadow: 0 0 20px 2px rgba(118, 202, 40, .45),
              inset 0 0 14px rgba(118, 202, 40, .22);
}
html.motion .plan.featured::after,
html.motion .access::after {
  border: 1px solid rgba(var(--glow-rgb), .85);
  box-shadow: 0 0 24px 3px rgba(var(--glow-rgb), .48),
              inset 0 0 18px rgba(var(--glow-rgb), .22);
}
/* `.panel-hero` klippt (`overflow: hidden`), der Schein des CTA-Panels
   bleibt deshalb innen. Genau richtig: dort ist er ein aufleuchtender
   Rahmen, kein Hof. */

html.motion .is-burst::after { animation: becro-edge-burst 640ms var(--mo-ease) 1; }

@keyframes becro-edge-burst {
  0%   { opacity: 0;   transform: scale(.988); }
  26%  { opacity: .95; transform: scale(1.008); }
  100% { opacity: 0;   transform: scale(1.028); }
}

@media (prefers-reduced-motion: reduce) {
  /* Sicherheitsnetz wie bei den Marquees: `html.motion` wird in diesem Fall
     gar nicht erst gesetzt, becro-motion.js steigt vorher aus. Sollte die
     Klasse trotzdem einmal am Element haengen, blitzt nichts. */
  html.motion .is-burst::after { animation: none; }
}
