/* ==========================================================================
   VENTIVA — 02 Base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--v-mist);
  color: var(--v-ink);
  font-family: var(--v-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;

  /* Sicherheitsnetz gegen horizontales Wackeln auf Telefonen.
     Bewusst clip und bewusst nur am body — NICHT overflow-x: hidden am html:
     Das macht das Wurzelelement zum Scroll-Container und legt damit
     position: sticky lahm, also genau unseren Header. clip erzeugt keinen
     Scroll-Container und lässt sticky in Ruhe. */
  overflow-x: clip;
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .2em; }

:focus-visible {
  outline: 2px solid var(--v-heat);
  outline-offset: 3px;
  border-radius: 3px;
}

/* --- Überschriften ------------------------------------------------------ */
.v-h1, .v-h2, .v-h3 {
  font-family: var(--v-display);
  font-weight: 600;
  font-stretch: 112%;          /* Archivo variable width — breit, technisch */
  letter-spacing: -.022em;
  margin: 0;
  text-wrap: balance;
}
.v-h1 { font-size: var(--fs-h1); line-height: var(--lh-tight); font-stretch: 118%; }
.v-h2 { font-size: var(--fs-h2); line-height: var(--lh-snug); }
.v-h3 { font-size: var(--fs-h3); line-height: 1.2; font-stretch: 106%; }

.v-lead { font-size: var(--fs-lg); color: var(--v-ink-60); max-width: 46ch; margin: 0; }

/* Eyebrow / Messwert-Label: Mono, weil es im Ventiva-Kontext immer
   um gemessene Größen geht (Grad, kPa, Prozent). */
.v-eyebrow {
  font-family: var(--v-mono);
  font-size: var(--fs-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--v-ink-60);
  margin: 0 0 1.1rem;
  display: flex;
  align-items: center;
  gap: .7rem;
}
.v-eyebrow::before {
  content: "";
  width: 26px;
  height: 1px;
  background: currentColor;
  flex: none;
}

/* --- Layout ------------------------------------------------------------- */
.v-shell {
  width: min(100% - (var(--v-gutter) * 2), var(--v-max));
  margin-inline: auto;
}
.v-section { padding-block: var(--v-section); }
.v-section--tight { padding-block: calc(var(--v-section) * .6); }

.v-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--v-col-gap);
}

/* --- Buttons ------------------------------------------------------------ */
.v-btn {
  --btn-bg: var(--v-heat);
  --btn-fg: var(--v-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .65rem;
  padding: 1.02rem 1.9rem;
  border: 0;
  border-radius: 999px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--v-body);
  font-size: var(--fs-base);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--v-fast) var(--v-ease),
              transform var(--v-fast) var(--v-ease);
}
.v-btn:hover  { --btn-bg: var(--v-heat-deep); }
.v-btn:active { transform: translateY(1px); }

.v-btn--ghost {
  --btn-bg: transparent;
  --btn-fg: currentColor;
  box-shadow: inset 0 0 0 1px var(--v-line);
}
.v-btn--ghost:hover { --btn-bg: rgba(18, 58, 52, .06); }
.v-invert .v-btn--ghost:hover { --btn-bg: rgba(255, 255, 255, .08); }

.v-btn--block { width: 100%; }

/* --- Druckskala: das Signature-Element --------------------------------- */
/* Kalt (Petrol) = entlastet, heiß (Amber) = Druckspitze. Taucht im Hero,
   im Showcase und als Mikro-Element in den Trust-Badges wieder auf.       */
.v-scale {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-family: var(--v-mono);
  font-size: var(--fs-mono);
  color: var(--v-ink-60);
}
.v-scale__bar {
  height: 4px;
  width: 100%;
  min-width: 90px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--v-cool) 0%, #8FA86B 46%, var(--v-heat) 100%);
}

/* --- Scroll-Reveal ------------------------------------------------------ */
/* Nur wenn JavaScript läuft, darf etwas unsichtbar starten — sonst bekäme
   niemand ohne JavaScript den Inhalt je zu sehen (die Markierung setzt
   header.php). */
.v-js .v-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--v-slow) var(--v-ease-out),
              transform var(--v-slow) var(--v-ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.v-js .v-reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .v-js .v-reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

/* --- A11y --------------------------------------------------------------- */
.v-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Blätter im Wind -----------------------------------------------------
   Übergang zwischen zwei Sektionen. Bewusst sparsam: fünf Blätter, langsame
   Drift, reine CSS-Transforms. Kein Canvas, kein Parallax — beides kostet
   beim Scrollen mehr, als die Deko wert ist.

   Die Leiste liegt zwischen den Blöcken, nicht darüber: Sie überlagert nie
   Text und kann deshalb auch nichts unlesbar machen.
   -------------------------------------------------------------------------- */
.v-wind {
  position: relative;
  /* Etwas höher als früher: Die Windlinien sind lang und flach, in einer
     64-px-Leiste läge die Hälfte von ihnen ausserhalb und würde am
     overflow abgeschnitten. */
  height: clamp(78px, 6.5vw, 120px);
  overflow: hidden;
  pointer-events: none;
}
.v-wind--hell   { background: var(--v-mist); color: var(--v-cool); }
.v-wind--dunkel { background: var(--v-deep); color: rgba(255, 255, 255, .30); }

/* --- Nur für Hilfsmittel ---------------------------------------------
   Text, der vorgelesen, aber nicht gezeigt wird. Kein display: none und kein
   visibility: hidden — beides nimmt das Element auch aus dem Screenreader.
   Die Ein-Pixel-Box mit clip-path ist der Weg, der überall funktioniert.
   -------------------------------------------------------------------------- */
.v-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  white-space: nowrap;
  border: 0;
  clip-path: inset(50%);
}

/* --- Karte ------------------------------------------------------------
   Geteiltes Bauteil: Startseite (Aufbau-Raster) und Produktseite (Testhinweis)
   geben dieselbe Karte aus. Lag früher in 03-home.css, das die Produktseite
   nicht lädt — dort kam die Karte ohne Rahmen, Grund und Innenabstand heraus.
   Die Platzierung im Raster bleibt seitenweise in 03-home.css.
   -------------------------------------------------------------------------- */
.v-card {
  position: relative;
  padding: clamp(1.6rem, 1rem + 1.4vw, 2.4rem);
  border-radius: var(--v-radius);
  background: var(--v-paper);
  box-shadow: var(--v-shadow);
  height: 100%;
}
.v-card__index {
  font-family: var(--v-mono);
  font-size: var(--fs-mono);
  color: var(--v-heat-deep);
  letter-spacing: .1em;
  display: block;
  margin-bottom: 1.1rem;
}
.v-card__title { margin: 0 0 .7rem; }
.v-card__text  { margin: 0; color: var(--v-ink-60); font-size: var(--fs-sm); line-height: 1.65; }
.v-card__media {
  border-radius: calc(var(--v-radius) - 4px);
  overflow: hidden;
  margin-bottom: 1.4rem;
  background: var(--v-mist);
  aspect-ratio: 16 / 11;
}
.v-card__media img { width: 100%; height: 100%; object-fit: cover; }

.v-card--deep {
  background: var(--v-deep);
  color: #F2F6F3;
  box-shadow: none;
}
.v-card--deep .v-card__text { color: var(--v-paper-70); }
.v-card--deep .v-card__index { color: var(--v-heat); }

/* --- Vertrauens-Zeile --------------------------------------------------
   Produktseite, Warenkorb und Kasse geben über ventiva_trust_list() dieselben
   Zusagen aus. Die Regeln lagen in 04-product.css und griffen deshalb im
   Kaufweg nicht: ventiva_icon() liefert ein SVG ohne width und height, und
   ein solches Element füllt ohne Vorgabe die volle Spaltenbreite — im
   Warenkorb wurde aus einem 16-Pixel-Symbol ein 350-Pixel-Quadrat.
   -------------------------------------------------------------------------- */
/* Vertrauens-Zeile direkt unter dem Preis — vier harte Zusagen. */
.v-trust {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .7rem 1.2rem;
  padding: 1.1rem 1.2rem;
  margin-bottom: 1.8rem;
  border-radius: var(--v-radius);
  background: rgba(18, 58, 52, .06);
}
.v-trust__item {
  display: grid;
  grid-template-columns: 16px 1fr;
  gap: .6rem;
  align-items: start;
  font-size: var(--fs-sm);
  line-height: 1.35;
  color: var(--v-ink);
}
.v-trust__item svg { width: 16px; height: 16px; margin-top: .18rem; color: var(--v-deep); }

/* Eine Spalte, sobald es eng wird — gilt für alle drei Einsatzorte. */
@media (max-width: 61.24em) {
  .v-trust { grid-template-columns: 1fr; }
}

/* --- Zitat / Rückmeldung ----------------------------------------------
   Geteiltes Bauteil: Startseite, Stress-Landingpage und Produktseite geben
   dieselbe Karte aus. Es lag früher in 03-home.css — dort greift es auf der
   Produktseite nicht, weil die diesen Layer nicht lädt. Die Rasterung (wie
   viele Spalten, welche Karte breit) bleibt seitenweise in 03 und 04.
   -------------------------------------------------------------------------- */
.v-quote {
  padding: 1.6rem 1.8rem;
  border-radius: var(--v-radius);
  background: var(--v-paper);
  box-shadow: var(--v-shadow);
}
.v-quote p { margin: 0 0 1rem; font-size: var(--fs-lg); line-height: 1.5; letter-spacing: -.01em; }
/* ventiva_quote_list() gibt <figcaption> aus, nicht <footer> — bisher griff
   diese Regel deshalb gar nicht und die Namenszeile lief als Fliesstext mit.
   Beide Selektoren, damit auch von Hand gesetzte Zitate passen. */
.v-quote footer,
.v-quote figcaption {
  font-family: var(--v-mono);
  font-size: var(--fs-mono);
  /* 60 statt 40 Prozent: Bei 11,5 px Mono kommt --v-ink-40 auf 2,6:1 Kontrast
     und --v-paper-45 in dunklen Sektionen auf 3,2:1 — beides unter den 4,5:1,
     die WCAG AA für Text dieser Größe verlangt. Die 60er-Stufe liegt bei 4,8
     bzw. 5,5:1 und ist in .v-invert bereits auf --v-paper-70 gemappt, gilt
     also in beiden Kontexten. */
  color: var(--v-ink-60);
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* --- Windlinien -------------------------------------------------------

   Ohne sie sieht man nur fliegende Blätter und muss sich den Wind dazu denken.

   Drei Dinge halten sie davon ab, wie Laserstrahlen auszusehen:

   1. Sie sind gefüllte Flächen mit verjüngten Enden, keine Striche gleicher
      Stärke (die Formen stehen in ventiva_leaf_wind).
   2. Sie werden beim Durchziehen vorn aufgedeckt und hinten wieder zugedeckt,
      statt als fertiges Objekt hindurchzufahren. Das übernimmt clip-path —
      mit einer gefüllten Fläche gibt es kein stroke-dasharray mehr.
   3. Die Bahn schwingt vertikal und die Form atmet dabei leicht.

   Der Takt ist 3,5 s, also die halbe Böendauer der Blätter (7 s). Dadurch
   fällt jede Linie mit einem der beiden Schübe zusammen, die v-wind-gust den
   Blättern gibt. Zufällige Zeiten hätten Linie und Blattbewegung entkoppelt,
   und genau daran erkennt das Auge Deko.
   -------------------------------------------------------------------------- */
.v-wind__defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.v-wind__streak {
  position: absolute;
  left: -46%;
  width: 40vw;
  opacity: .85;
  /* top bezeichnet die Mitte der Linie, nicht ihre Oberkante — sonst müsste
     man bei jeder Breitenänderung die Höhen nachrechnen, weil das SVG seine
     Höhe aus der Breite ableitet. transform ist hier frei: Die Bahn läuft
     über translate, die Neigung über rotate, das Atmen über scale am svg. */
  transform: translateY(-50%);
  will-change: translate, rotate;
  animation: v-wind-streak 3.5s linear infinite;
}
.v-wind__streak svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
  fill: currentColor;
  /* Die Form atmet: Der Ausschlag wird flacher und tiefer, während die Linie
     zieht. Ohne das bliebe die Kurve eine starre Silhouette. Eigener, kürzerer
     Takt als die Bahn, damit sich beides nicht deckt. */
  animation: v-wind-wave 2.3s ease-in-out infinite;
}
.v-wind__streak use {
  /* Aufdecken und Zudecken über eine wandernde Maske statt über clip-path:
     clip-path hat eine harte Kante, und eine Windlinie, die mitten im Lauf
     abgeschnitten wird, sieht aus wie ein Fehler. Der Verlauf ist doppelt so
     breit wie das Element, läuft an beiden Enden aus und wird von links nach
     rechts darübergeschoben — die Linie wächst weich heran und löst sich
     ebenso wieder auf. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 26%, #000 74%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 26%, #000 74%, transparent);
  -webkit-mask-size: 200% 100%;
          mask-size: 200% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: v-wind-reveal 3.5s ease-in-out infinite;
}

/* Verschiedene Höhen, Längen und Startpunkte. Die Verzögerungen sind über den
   Zyklus verteilt, damit nie alle vier gleichzeitig als Reihe durchs Bild
   fahren — das sah aus wie eine Treppe. */
.v-wind__streak--1,
.v-wind__streak--1 svg,
.v-wind__streak--1 use { animation-delay: 0s; }
.v-wind__streak--2,
.v-wind__streak--2 svg,
.v-wind__streak--2 use { animation-delay: -0.95s; }
.v-wind__streak--3,
.v-wind__streak--3 svg,
.v-wind__streak--3 use { animation-delay: -1.8s; }
.v-wind__streak--4,
.v-wind__streak--4 svg,
.v-wind__streak--4 use { animation-delay: -2.65s; }

.v-wind__streak--1 { top: 20%; width: 44vw; opacity: .9;  }
.v-wind__streak--2 { top: 44%; width: 38vw; opacity: .6;  }
.v-wind__streak--3 { top: 62%; width: 46vw; opacity: .8;  }
.v-wind__streak--4 { top: 84%; width: 30vw; opacity: .45; }

/* Die Bahn: drei flache Bögen quer durch die Leiste, mit passender Neigung.
   Die Rotation bleibt klein — eine Windlinie kippt, sie überschlägt sich nicht. */
@keyframes v-wind-streak {
  0%   { translate:    0 0px;   rotate:  0deg;   }
  30%  { translate:  34vw -7px; rotate: -2.5deg; }
  55%  { translate:  62vw  6px; rotate:  2deg;   }
  80%  { translate:  96vw -4px; rotate: -1.5deg; }
  100% { translate: 132vw 0px;  rotate:  0deg;   }
}

/* Nur die Y-Achse wird gestaucht und gestreckt: Die Linie behält ihre Länge
   und ändert allein ihren Ausschlag. */
@keyframes v-wind-wave {
  0%, 100% { scale: 1 0.85; }
  40%      { scale: 1 1.35; }
  72%      { scale: 1 1.05; }
}

/* Die Maske wandert über das Element hinweg: erst liegt ihr auslaufendes
   Ende darauf (Linie erscheint), dann ihr deckender Mittelteil (Linie ganz
   da), dann das andere auslaufende Ende (Linie geht wieder). */
@keyframes v-wind-reveal {
  0%   { -webkit-mask-position: -105% 0; mask-position: -105% 0; }
  100% { -webkit-mask-position:  105% 0; mask-position:  105% 0; }
}

/* Die Leisten geben ihren Blättern per color eine gedämpfte Farbe. Für eine
   Fläche, die an den Enden auf null ausläuft, ist das zu wenig — sie
   verschwindet, während das Blatt daneben noch trägt. */
.v-wind--hell   .v-wind__streak { color: var(--v-deep); }
.v-wind--dunkel .v-wind__streak { color: rgba(255, 255, 255, .8); }

.v-wind__leaf {
  position: absolute;
  top: 50%;
  left: -8%;
  width: 20px;
  height: 20px;
  opacity: 0;

  /* Drei getrennte Achsen statt einer transform-Kette: translate trägt die
     Drift, rotate das Taumeln, transform die Bö. Als Einzel-Properties darf
     jede ihre eigene Dauer haben. Läge alles in einer transform-Kette,
     müssten sich alle drei einen Keyframe-Takt teilen — und genau der
     Gleichtakt ist es, der eine Blattbewegung mechanisch aussehen lässt. */
  will-change: translate, rotate, transform;
  animation:
    v-wind-drift  14s   linear      infinite,
    v-wind-tumble  2.6s ease-in-out infinite,
    v-wind-gust    7s   ease-in-out infinite;
}
.v-wind__leaf svg { width: 100%; height: 100%; }

/* Versetzte Startzeiten und Höhen, damit kein Muster entsteht.
   Die Listen folgen der Reihenfolge oben: drift, tumble, gust.

   Die Bö hat bei allen fünf Blättern dieselbe Dauer und keinen Versatz —
   eine Bö erfasst nun einmal alle gleichzeitig. Wären auch hier die Zeiten
   verschoben, sähe es aus wie Konfetti, nicht wie Wind.

   Der Taumel-Versatz ist negativ: Das Blatt startet damit mitten in der
   Drehung statt flach. Sonst kippen beim Laden alle fünf im Gleichschritt. */
.v-wind__leaf--1 { animation-duration: 13s, 2.4s, 7s; animation-delay:  0s,   -0.3s, 0s; --y: -18px; }
.v-wind__leaf--2 { animation-duration: 17s, 3.1s, 7s; animation-delay:  2.6s, -1.2s, 0s; --y:   6px; width: 15px; height: 15px; }
.v-wind__leaf--3 { animation-duration: 11s, 2.0s, 7s; animation-delay:  5.2s, -0.7s, 0s; --y: -30px; width: 24px; height: 24px; }
.v-wind__leaf--4 { animation-duration: 19s, 3.6s, 7s; animation-delay:  7.8s, -2.1s, 0s; --y:  18px; width: 13px; height: 13px; }
.v-wind__leaf--5 { animation-duration: 15s, 2.7s, 7s; animation-delay: 10.4s, -1.6s, 0s; --y:  -6px; }

/* Grunddrift quer durch die Leiste. Die Höhe schwankt in drei Bögen statt
   einmal linear — eine gerade Bahn liest sich als Fließband. */
@keyframes v-wind-drift {
  0%   { translate:    0 var(--y, 0px);                opacity: 0; }
  8%   {                                               opacity: 1; }
  25%  { translate:  29vw calc(var(--y, 0px) - 12px); }
  50%  { translate:  58vw calc(var(--y, 0px) + 16px); }
  75%  { translate:  87vw calc(var(--y, 0px) -  8px); }
  92%  {                                               opacity: 1; }
  100% { translate: 116vw var(--y, 0px);               opacity: 0; }
}

/* Taumeln um die eigene Achse: hin und her, nicht durchdrehend. Ein Blatt
   im Wind rollt nicht gleichmäßig, es kippt und fängt sich wieder.
   Gestaucht wird nur die X-Achse — das liest sich als Blatt, das sich mit
   der Schmalseite zum Betrachter dreht, statt als Blatt, das kleiner wird. */
@keyframes v-wind-tumble {
  0%   { rotate:   0deg; scale: 1    1; }
  25%  { rotate:  34deg; scale: 0.45 1; }
  50%  { rotate:   6deg; scale: 1    1; }
  75%  { rotate: -28deg; scale: 0.6  1; }
  100% { rotate:   0deg; scale: 1    1; }
}

/* Die Bö selbst: zwei Schübe nach vorn und leicht nach oben, dazwischen
   Abflauen. Sie addiert sich auf die Drift, statt sie zu ersetzen — deshalb
   wird das Blatt hier schneller und dort langsamer, ohne je rückwärts zu
   laufen. */
@keyframes v-wind-gust {
  0%, 100% { transform: translate(   0,    0); }
  12%      { transform: translate(3.5vw, -6px); }
  30%      { transform: translate(  1vw,  2px); }
  55%      { transform: translate(  5vw, -9px); }
  78%      { transform: translate(0.5vw,  3px); }
}

/* Ohne Bewegung bleibt eine ruhige Trennfläche stehen — die Blätter selbst
   verschwinden, statt eingefroren mitten im Bild zu hängen. */
@media (prefers-reduced-motion: reduce) {
  .v-wind__leaf,
  .v-wind__streak { display: none; }
  .v-wind { height: clamp(32px, 3vw, 48px); }
}

/* Auf schmalen Screens sind 40 vw kaum mehr als eine Handbreit — dort tragen
   längere Linien besser, dafür weniger davon. */
@media (max-width: 40em) {
  .v-wind__streak--1 { width: 78vw; }
  .v-wind__streak--2 { width: 66vw; }
  .v-wind__streak--3 { width: 84vw; }
  .v-wind__streak--4 { display: none; }
}

/* Browser ohne die Einzel-Properties translate/rotate/scale würden nur die
   Bö sehen: Das Blatt bliebe stehen und würde bloß ein- und ausblenden.
   Dann lieber gar kein Blatt. */
@supports not (translate: 1px 1px) {
  .v-wind__leaf,
  .v-wind__streak { display: none; }
}
