/* ============================================================
   akte.css — Startseite unterhalb der Falz (Paket 2, Runde 2)
   ============================================================
   Block 8 (Lesegrund-Scrims) und Block 9 (scroll-craft-Akte) sind aus
   css/layering.css hierher gezogen: alles, was erst unterhalb der Falz
   wirkt, in einer Datei. Geladen wird sie wie jedes Stylesheet blockierend
   ueber <link> in index.html. Der Plan, sie asynchron nachzuladen (Runde 2,
   Lighthouse mobil), ist verworfen: jede Stylesheet-Aktivierung nach dem
   ersten Paint laesst Chrome die Fern-Ebene des festen Betts als
   Layout-Shift zaehlen (0,63-0,71), Begruendung am <link> in index.html,
   Bisektion im internen Messprotokoll dokumentiert.
   Cache-Version haengt am <link> (?v=) wie bei allen anderen Dateien.

   Nutzt ausschliesslich Variablen aus dem :root von index.html; keine neuen
   Farben. Wird von keiner Unterseite geladen.
   ============================================================ */

/* ============================================================
   8) NACHBESSERUNG RUNDE 1 (05.09.2026) — Lesegrund auf dem Foto
   ============================================================
   Anlass: PRUEFUNG-v2.md, Befund HOCH-1. Seit das Bett aus echten Fotos
   besteht, liegt Fliesstext stellenweise auf der hellen Schneeflanke von
   mitte-a1.webp. Am schlechtesten Pixel unter der Textzeile gemessen (nicht
   im Mittel — genau dieser Mittelwert hatte den Fehler in Runde 1 verdeckt):
   .trust-note 1,49:1, FAQ-Ueberschrift 2,29:1, .step-num 2,27:1 — Schwelle
   ist 4,5:1 bzw. 3:1 fuer grossen Text.

   Warum ein Scrim und kein globales Abdunkeln: der Skill verbietet den
   "full-frame dark overlay to fix contrast" und verlangt "a scrim only where
   the text sits". Ein Deckel auf die Ebenen-Deckkraft haette die Bergwelt
   ueberall totgedimmt; er ist nur so weit gegangen, wie er der Dramaturgie
   ohnehin nutzt (siehe die --berg-licht-Leitern in berg.css).

   Warum in DIESER Datei: layering.css wird ausschliesslich von index.html
   geladen (nachgewiesen per grep -l ueber alle sieben Seiten). Alles hier ist
   damit automatisch auf die Startseite begrenzt, ohne dass eine Klasse in die
   sechs Unterseiten wandern muss — und ohne eine einzige Aenderung am Markup.

   Form: ein Plateau von 82 % Deckung ueber der Textflaeche, an allen vier
   Seiten weich auslaufend (vertikal per Verlauf, horizontal per Maske).
   Keine harte Kante, kein sichtbarer Kasten — es liest sich als Dunst, nicht
   als Box. z-index:-1 legt es hinter den Text, aber vor das Bett: die
   Sektionen sind position:relative ohne eigenen z-index, erzeugen also keinen
   Stapelkontext, und main steht auf z-index:1 ueber dem Bett (z-index:0). */
.ly-lesegrund, .marquee-label{ position:relative; }
/* Flankenlaengen (Paket 2): Standard fuer alle Lesegrund-Scrims. */
.ly-lesegrund,
section[data-berg-station="trust"] .ly-anchor-trail,
#services .svc-titel,
#prozess .pz-grid,
#founder .founder-grid > div + div,
#faq .faq-wrap,
.news .wrap{ --sr-y:84px; --sr-x:24px; --sr-a:.88; }
/* Die lange waagerechte Flanke (Rahmen -120 px) nur, wenn neben .wrap
   (1160 px) auch nach Abzug der Scrollleiste mindestens 120 px Rand bleiben:
   1160 + 2*120 + 17 = 1417. Darunter stehen 24 px Flanke (Rahmen -40 px =
   genau der Innenabstand von .wrap), sonst waechst document.scrollWidth —
   bei 768/1024 px gemessen: 120 px Overflow. */
@media (min-width: 1420px){
  .ly-lesegrund,
  section[data-berg-station="trust"] .ly-anchor-trail,
  #services .svc-titel,
  #prozess .pz-grid,
  #founder .founder-grid > div + div,
  #faq .faq-wrap,
  .news .wrap{ --sr-x:104px; }
}
.ly-lesegrund::after{
  content:"";
  position:absolute; z-index:-1; pointer-events:none;
  /* Flanken in PIXELN, nicht in Prozent: prozentuale Stops haengen an der
     Blockhoehe/-breite, und genau dadurch stand das erste bzw. letzte Element
     eines Blocks (.sec-label oben, .trust-note unten) in der weichen Flanke
     statt im Plateau — auf einem 306 px hohen Block sind 13 % schon 40 px.
     Der Rahmen (inset) ist immer um 12 px / 16 px groesser als die Flanke,
     der Inhalt liegt also garantiert im Plateau.

     PAKET 2 (Nebenpunkt "rechteckige Oberkante"): die Flanke war ein linearer
     Verlauf von 0 auf .88 ueber 30 px — an beiden Enden ein Knick, den das
     Auge als Kante liest (Mach-Band). Jetzt: Flankenlaenge als Variable
     (--sr-y senkrecht, --sr-x waagerecht, Plateau --sr-a) und je Flanke fuenf
     Stuetzstellen auf einer S-Kurve (0 / .11 / .50 / .89 / 1), die den Knick
     an beiden Enden nimmt. Desktop 84 px / 104 px statt 30 / 40. Messbeleg in
     Messprotokoll, Paket 2. */
  inset:calc(-1 * var(--sr-y) - 12px) calc(-1 * var(--sr-x) - 16px);
  background:linear-gradient(to bottom,
    rgba(5,8,15,0) 0,
    rgba(5,8,15,calc(var(--sr-a) * .11)) calc(var(--sr-y) * .25),
    rgba(5,8,15,calc(var(--sr-a) * .50)) calc(var(--sr-y) * .5),
    rgba(5,8,15,calc(var(--sr-a) * .89)) calc(var(--sr-y) * .75),
    rgba(5,8,15,var(--sr-a)) var(--sr-y),
    rgba(5,8,15,var(--sr-a)) calc(100% - var(--sr-y)),
    rgba(5,8,15,calc(var(--sr-a) * .89)) calc(100% - var(--sr-y) * .75),
    rgba(5,8,15,calc(var(--sr-a) * .50)) calc(100% - var(--sr-y) * .5),
    rgba(5,8,15,calc(var(--sr-a) * .11)) calc(100% - var(--sr-y) * .25),
    rgba(5,8,15,0) 100%);
  -webkit-mask-image:linear-gradient(to right,
    transparent 0,
    rgba(0,0,0,.11) calc(var(--sr-x) * .25), rgba(0,0,0,.50) calc(var(--sr-x) * .5), rgba(0,0,0,.89) calc(var(--sr-x) * .75),
    #000 var(--sr-x), #000 calc(100% - var(--sr-x)),
    rgba(0,0,0,.89) calc(100% - var(--sr-x) * .75), rgba(0,0,0,.50) calc(100% - var(--sr-x) * .5), rgba(0,0,0,.11) calc(100% - var(--sr-x) * .25),
    transparent 100%);
  mask-image:linear-gradient(to right,
    transparent 0,
    rgba(0,0,0,.11) calc(var(--sr-x) * .25), rgba(0,0,0,.50) calc(var(--sr-x) * .5), rgba(0,0,0,.89) calc(var(--sr-x) * .75),
    #000 var(--sr-x), #000 calc(100% - var(--sr-x)),
    rgba(0,0,0,.89) calc(100% - var(--sr-x) * .75), rgba(0,0,0,.50) calc(100% - var(--sr-x) * .5), rgba(0,0,0,.11) calc(100% - var(--sr-x) * .25),
    transparent 100%);
}

/* Die Textbloecke, die ohne eigene Flaeche direkt auf dem Bett liegen.
   Karten-Sektionen (uc-card, trust-card, br-item, cta-panel) brauchen das
   nicht — sie haben eine eigene Flaeche; bei .uc-card ist stattdessen nur
   deren Deckkraft angehoben worden (siehe unten). */
section[data-berg-station="trust"] .ly-anchor-trail,
#services .svc-titel,
#prozess .pz-grid,
#founder .founder-grid > div + div,
#faq .faq-wrap,
.news .wrap{ position:relative; }

section[data-berg-station="trust"] .ly-anchor-trail::after,
#services .svc-titel::after,
#prozess .pz-grid::after,
#founder .founder-grid > div + div::after,
#faq .faq-wrap::after,
.news .wrap::after{
  content:"";
  position:absolute; z-index:-1; pointer-events:none;
  /* Flanken in PIXELN, nicht in Prozent: prozentuale Stops haengen an der
     Blockhoehe/-breite, und genau dadurch stand das erste bzw. letzte Element
     eines Blocks (.sec-label oben, .trust-note unten) in der weichen Flanke
     statt im Plateau — auf einem 306 px hohen Block sind 13 % schon 40 px.
     Der Rahmen (inset) ist immer um 12 px / 16 px groesser als die Flanke,
     der Inhalt liegt also garantiert im Plateau.

     PAKET 2 (Nebenpunkt "rechteckige Oberkante"): die Flanke war ein linearer
     Verlauf von 0 auf .88 ueber 30 px — an beiden Enden ein Knick, den das
     Auge als Kante liest (Mach-Band). Jetzt: Flankenlaenge als Variable
     (--sr-y senkrecht, --sr-x waagerecht, Plateau --sr-a) und je Flanke fuenf
     Stuetzstellen auf einer S-Kurve (0 / .11 / .50 / .89 / 1), die den Knick
     an beiden Enden nimmt. Desktop 84 px / 104 px statt 30 / 40. Messbeleg in
     Messprotokoll, Paket 2. */
  inset:calc(-1 * var(--sr-y) - 12px) calc(-1 * var(--sr-x) - 16px);
  background:linear-gradient(to bottom,
    rgba(5,8,15,0) 0,
    rgba(5,8,15,calc(var(--sr-a) * .11)) calc(var(--sr-y) * .25),
    rgba(5,8,15,calc(var(--sr-a) * .50)) calc(var(--sr-y) * .5),
    rgba(5,8,15,calc(var(--sr-a) * .89)) calc(var(--sr-y) * .75),
    rgba(5,8,15,var(--sr-a)) var(--sr-y),
    rgba(5,8,15,var(--sr-a)) calc(100% - var(--sr-y)),
    rgba(5,8,15,calc(var(--sr-a) * .89)) calc(100% - var(--sr-y) * .75),
    rgba(5,8,15,calc(var(--sr-a) * .50)) calc(100% - var(--sr-y) * .5),
    rgba(5,8,15,calc(var(--sr-a) * .11)) calc(100% - var(--sr-y) * .25),
    rgba(5,8,15,0) 100%);
  -webkit-mask-image:linear-gradient(to right,
    transparent 0,
    rgba(0,0,0,.11) calc(var(--sr-x) * .25), rgba(0,0,0,.50) calc(var(--sr-x) * .5), rgba(0,0,0,.89) calc(var(--sr-x) * .75),
    #000 var(--sr-x), #000 calc(100% - var(--sr-x)),
    rgba(0,0,0,.89) calc(100% - var(--sr-x) * .75), rgba(0,0,0,.50) calc(100% - var(--sr-x) * .5), rgba(0,0,0,.11) calc(100% - var(--sr-x) * .25),
    transparent 100%);
  mask-image:linear-gradient(to right,
    transparent 0,
    rgba(0,0,0,.11) calc(var(--sr-x) * .25), rgba(0,0,0,.50) calc(var(--sr-x) * .5), rgba(0,0,0,.89) calc(var(--sr-x) * .75),
    #000 var(--sr-x), #000 calc(100% - var(--sr-x)),
    rgba(0,0,0,.89) calc(100% - var(--sr-x) * .75), rgba(0,0,0,.50) calc(100% - var(--sr-x) * .5), rgba(0,0,0,.11) calc(100% - var(--sr-x) * .25),
    transparent 100%);
}
/* Elemente, die selbst das .wrap SIND (Rahmen = Viewport unter 1240 px):
   seitlich nie ueber die eigene Kante hinaus. Steht bewusst NACH den
   ::after-Regeln oben: gleiche Spezifitaet, die spaetere gewinnt (im ersten
   Lauf stand sie davor — 40 px Overflow bei 768/1024 px). */
@media (max-width: 1419px){
  #prozess .pz-grid::after,
  #faq .faq-wrap::after,
  /* RUNDE 3 (BLOCKER, Pruefung r3 Nr. 1): .svc-titel traegt selbst die
     .wrap-Masse (max-width:1160px, index.html:490) und gehoert damit in diese
     Gruppe. Ohne sie ragte der Scrim seitlich um --sr-x + 16 px hinaus:
     scrollWidth 414/808/1064 statt 390/768/1024 und — schwerwiegender — vor
     dem Start von berg.js weitete Chrome deswegen den mobilen Layout-Viewport
     auf 436x871; sobald html.berg-akt kam, sprang er auf 412x823 zurueck und
     riss Fern-Ebene und Nav-Wrapper mit: CLS 0,102. */
  #services .svc-titel::after,
  .ly-lesegrund.wrap::after,
  .news .wrap::after{ inset:calc(-1 * var(--sr-y) - 12px) 0; }
}

/* Prozess (Paket 2): EIN Band hinter dem ganzen Raster (.pz-grid = Kopf +
   Route + Schritt) statt je einem Kasten je Spalte — zwei Kaesten mit kurzen
   Flanken lasen sich im ersten Screenshot-Lauf als Kaesten. Das Band liegt
   ausserhalb der Wischfront (die beschneidet nur den Schritt), flackert also
   nicht mit. Mit -120 px Rahmen reicht es fast von Rand zu Rand. */
/* Der Founder-Textspalte reicht weniger, das Foto daneben bringt eigene Flaeche mit. */

/* Karten, deren Flaeche nach unten in die Transparenz auslief: .uc-card ging
   von .5 auf .15, .trust-card von .45 auf 0. Ueber dem flachen Grund von
   Runde 3 war das ein feiner Verlauf, ueber dem Foto stand der Text unten
   praktisch direkt auf dem Schnee (.uc-badge 1,79:1, .trust-metric 1,79:1).
   Kein Scrim noetig — die Karte IST die Flaeche, sie muss nur eine bleiben.
   Der Verlauf bleibt als Gestaltungsmittel erhalten, nur flacher.

   Spezifitaet mit Absicht ueber Sektions-Selektoren erhoeht: der
   <style>-Block von index.html steht IM DOKUMENT NACH dem <link> auf diese
   Datei, eine gleich spezifische Regel hier wuerde also verlieren. */
#usecases .uc-card{ background:linear-gradient(180deg, rgba(13,21,38,.90), rgba(13,21,38,.84)); }
/* PAKET 2: Das ROI-Panel lief unten in .40 aus; seit die Seite laenger ist,
   liegt sein Fuss ueber der Schneeflanke, und die 12-px-Datenschutzzeile
   (--faint) stand bei 3,93:1. Fuss jetzt .84 wie bei den Karten. */
#roi .roi-panel{ background:linear-gradient(180deg, var(--surface), rgba(13,21,38,.84)); }
/* RUNDE 2: Das Kontakt-Panel (.cta-panel, index.html) laeuft unten in .35 aus;
   .ly-peak (Block 7, .92) verliert gegen die spaetere .cta-panel-Regel gleicher
   Spezifitaet. Ueber dem Foto standen die --blue-Ziffern der Schrittliste und der
   Link bei 4,3:1, die Formular-Labels mobil bei 4,2:1. --blue (#4F7DF9) erreicht
   auf --surface 4,89:1; mit .96 Deckung bleibt am hellsten Schneepixel 4,57:1. */
#kontakt .cta-panel.ly-peak{ background:linear-gradient(180deg, var(--surface), var(--surface-2)); } /* Vollabtastung 1920: mit .96 blieb der Link bei 4,28:1 — jetzt deckend, --blue auf --surface-2 4,64:1 */
section[data-berg-station="trust"] .trust-card{ background:linear-gradient(180deg, rgba(13,21,38,.90), rgba(13,21,38,.84)); }

/* (Runde-1-Regel .svc-list.ly-panel entfernt: die Service-Liste ist seit
   Paket 2 eine Rail aus einzelnen ly-panel-Karten, siehe Block 9.) */

/* .sec-label (11 px) und .uc-badge (11,5 px) stehen beide in --blue (#4F7DF9). Diese Farbe erreicht 4,5:1 nur
   gegen einen sehr dunklen Grund — auf dem blanken Seitenhintergrund (#070C16)
   sind es 5,0:1, mehr gibt sie von Haus aus nicht her. Unter dem Blockscrim
   (88 %) blieb ueber der hellsten Schneeflanke rgb(51,59,70) stehen: 3,04:1.
   Statt die Marken-Farbe zu wechseln oder den ganzen Block noch dunkler zu
   machen, bekommt nur die Eyebrow-Zeile selbst eine kleine, weich auslaufende
   Unterlage — sie stellt dort genau den Zustand her, den die Zeile auf dem
   blanken Hintergrund ohnehin hat. Bei .sec-label ist ::before bereits vom
   Strich belegt, deshalb ::after; .uc-badge sitzt in einer Karte mit
   overflow:hidden, die Unterlage wird dort sauber am Kartenrand beschnitten. */
.sec-label, .uc-badge{ position:relative; }
/* RUNDE 2: .marquee-label (11 px, --faint, direkt auf dem Foto: 2,72:1 mobil,
   3,88 desktop) bekommt dieselbe Unterlage. Dafuer ist es in index.html auf
   display:table gesetzt, sonst waere die Pille so breit wie die Sektion. */
.sec-label::after, .uc-badge::after, .marquee-label::after{
  content:"";
  position:absolute; z-index:-1; pointer-events:none;
  inset:-9px -20px;
  border-radius:999px;
  /* Kern voll deckend: damit steht die Zeile ueberall exakt so da wie auf dem
     blanken Seitengrund (#05080F) — 5,0:1, der Bestwert, den --blue in 11 px
     ueberhaupt hergibt. Der Rand laeuft weich aus, es bleibt eine Lichtung im
     Dunst, kein Kasten. */
  background:radial-gradient(130% 170% at 50% 50%,
    rgba(5,8,15,1) 0%, rgba(5,8,15,.98) 62%, rgba(5,8,15,0) 100%);
}

/* .founder-badge liegt auf dem Founder-Foto (nicht auf dem Bett) und stand mit
   rgba(5,8,15,.8) an der hellsten Stelle des Fotos bei 4,17:1. Gleiche Optik,
   nur traegerer Grund — der backdrop-filter bleibt unangetastet. */
.founder-badge{ background:rgba(5,8,15,.93); }

/* Schmale Viewports: die Scrims ragten mit -52 px seitlich ueber den
   Viewport hinaus und haben document.scrollWidth aufgeblaeht (horizontaler
   Overflow, in der Nachmessung aufgefallen — body{overflow-x:hidden} kaschiert
   das optisch, die Seite meldet aber trotzdem eine zu grosse Scrollbreite).
   .wrap hat auf dieser Breite 24 px Innenabstand, -18 px bleiben also sicher
   innerhalb. Die weiche Flanke der Maske bleibt dadurch sogar besser sichtbar. */
@media (max-width: 760px){
  /* Schmale Viewports (Paket 2): senkrechte Flanke 48 px (Rahmen -60 px),
     waagerecht KEINE Flanke — der Rahmen endet exakt am Viewport-Rand
     (-24 px = Innenabstand von .wrap), und ein Band, das von Rand zu Rand
     laeuft, hat keine Kante, die man sehen koennte (Skill: .sc-scrim--band).
     Kein Overflow: -24 px liegt innerhalb der 24 px Innenabstand. */
  .ly-lesegrund,
  section[data-berg-station="trust"] .ly-anchor-trail,
  #services .svc-titel,
  #prozess .pz-grid,
  #founder .founder-grid > div + div,
  #faq .faq-wrap,
  .news .wrap{ --sr-y:48px; --sr-x:0px; --sr-a:.90; }
  .ly-lesegrund::after,
  section[data-berg-station="trust"] .ly-anchor-trail::after,
  #founder .founder-grid > div + div::after{ inset:-60px -24px; }
  /* .faq-wrap und .news .wrap SIND das .wrap und damit auf 390 px bereits
     viewportbreit — jeder negative Seitenwert erzeugt echten horizontalen
     Overflow (gemessen: scrollWidth 442 statt 390 bei -56 px). Seitlich 0.
     RUNDE 3: .svc-titel gehoert aus demselben Grund hierher (Pruefung r3
     Nr. 1) und ist oben aus der -24px-Gruppe herausgenommen. */
  #faq .faq-wrap::after,
  #prozess .pz-grid::after,
  #services .svc-titel::after,
  .ly-lesegrund.wrap::after,
  .news .wrap::after{ inset:-60px 0; }
  /* RUNDE 4: Die FAQ-Antworten stehen am unteren Rand des Plateaus; mit dem
     neuen Mitte-Bild liegt dort hellerer Fels und eine Antwort kam auf
     4,06:1 (gemessen bei 390, Position 85 %). Nur hier laenger und dichter,
     nicht in der ganzen Gruppe — sonst dunkelt die Bergwelt ueberall nach. */
  #faq .faq-wrap{ --sr-y:72px; --sr-a:.95; }
  #faq .faq-wrap::after{ inset:-88px 0; }
}

/* ============================================================
   9) PAKET 2 — Akte nach scroll-craft (pin / pan / kinetic / scrub)
   ============================================================
   Alles hier greift nur unter html.berg-akt. Die Klasse setzt js/berg.js,
   und zwar nie bei prefers-reduced-motion — ohne sie ist jede Sektion ein
   normaler Fluss-Abschnitt (das ist zugleich der No-JS-Zustand). Bewegt
   werden ausschliesslich transform / translate / clip-path; Text bekommt
   nie eine Opacity unter 1 (Ziel: 4,5:1 auch in Zwischenzustaenden).
   Ein Akt mit data-berg-akt-aus (Guard aus berg.js: Inhalt passt nicht in
   100svh) faellt auf genau diesen Fluss zurueck. */

/* --- Stage: klebt 100svh lang, Inhalt vertikal mittig, Luft fuer die Navbar (76 px) --- */
html.berg-akt [data-berg-akt]:not([data-berg-akt-aus]){ padding-top:0; padding-bottom:0; }
html.berg-akt [data-berg-akt]:not([data-berg-akt-aus]) > .akt-buehne{
  position:-webkit-sticky; position:sticky; top:0;
  height:100vh; height:100svh;
  overflow:hidden; overflow:clip;
  display:flex; flex-direction:column; justify-content:center;
  padding:96px 0 28px;
}

/* --- pan: die Service-Rail ---
   Basis-Layout (vertikale Liste) steht in index.html. Hier die Rail-Form:
   Flex-Reihe in max-content-Breite, seitlicher Rand = Kante von .wrap, damit
   der Kopf buendig mit den anderen Sektionen steht. Den Weg (scrollWidth -
   Viewport) schreibt js/berg.js als transform auf die Rail. */
.svc-rail{ --akt-rand:24px; }
@media (min-width: 640px){ .svc-rail{ --akt-rand:max(40px, calc((100vw - 1160px) / 2 + 40px)); } }
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-rail{
  display:flex; align-items:center; gap:22px;
  /* RUNDE 2 (BLOCKER-1): die Basis-Rail traegt .wrap-Masse (max-width 1160,
     margin auto). Die blieben hier aktiv, die Rail war eine zentrierte
     1160-px-Box, aus der die Karten herausragten, und berg.js mass den
     Ueberhang ab der Box-Linken: Karte /04 bei 1440 um 140 px abgeschnitten,
     bei 1920 nie sichtbar. Jetzt ausdruecklich aufgehoben. */
  max-width:none; margin:0;
  width:max-content; padding:0 var(--akt-rand);
  will-change:transform;
}
/* Die vier Karten: gleiche Groesse, gleiche Hoehe (stretch), kein Versatz,
   keine Ueberlappung (Runde 2). */
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-karten{
  display:flex; align-items:stretch; gap:22px;
}
/* PAKET 3: Mindestbreite von 270 auf 340 px angehoben.
   Bei 1024 px lieferte 27vw nur 276 px Karte (224 px Text nach Innenabstand)
   — zu wenig fuer die Vorgabe „Ueberschrift 1 Zeile, Beschreibung 2 Zeilen,
   Haekchen 1 Zeile". Bei 1440/1920 aendert sich nichts (27vw ueberschreitet
   dort ohnehin den Maximalwert 380). */
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-row{
  flex:0 0 clamp(340px, 27vw, 380px);
}
/* Der Titel-Halt (Runde 2): der Kopf liegt als eigene Ebene ueber der
   Stage, zentriert, gross. --akt-t (0..1, js/berg.js) ist der Zoom: der Block
   waechst auf 2,4x und faehrt 130vh nach oben aus dem Bild — nur transform,
   nichts wird transparent; die Stage beschneidet am Bildrand. Sein Lesegrund
   (::after, Block 8) skaliert mit. Waehrend des Halts stehen die Karten
   rechts ausserhalb des Bildes (js/berg.js schiebt die Rail um eine
   Viewportbreite heraus und faehrt sie im Zoom herein). */
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel{
  /* Eigene Box (nicht inset:0): so umfasst der Lesegrund (::after) nur den
     Textblock, nicht die ganze Stage. Mitte der Stage abzueglich Kopfzeile:
     (96 - 28) / 2 = 34 px unter der Viewportmitte. translate(-50%, -50%)
     zentriert die Box, der Zoom skaliert um ihre Mitte (transform-origin). */
  position:absolute; left:50%; top:calc(50% + 34px); z-index:2;
  width:min(100%, 1160px); margin:0; max-width:none;
  display:flex; flex-direction:column; align-items:center;
  text-align:center; padding:0 24px;
  transform:translate3d(-50%, calc(-50% + var(--akt-t, 0) * -130vh), 0) scale(calc(1 + var(--akt-t, 0) * 1.4));
  transform-origin:50% 50%; will-change:transform; pointer-events:none;
}
/* RUNDE 2, selbst gefunden: die Regel oben blieb bei position WIRKUNGSLOS.
   Block 8 verankert den Lesegrund mit `#services .svc-titel{position:relative}`
   (Zeile 116) — eine ID, die die Akt-Regel schlaegt. Folge: der Titel stand auf
   relative, blieb im Flex-Fluss der Stage und belegte dort 834 px; top/left
   verschoben ihn nur optisch. Die Kartenreihe wurde dadurch aus der Mitte
   gedraengt (gemessen bei p=1: Kartenmitte 657 statt 484 bei 1440, gleicher
   Versatz bei 390/768/1024/1920). Hier die ID gespiegelt, damit die Akt-Regel
   gewinnt; der Lesegrund bleibt korrekt verankert, weil auch ein absolut
   positionierter Block Bezugsrahmen fuer sein ::after ist.
   Nachweis: r2-check.mjs rail (Kartenmitte gegen Stage-Mitte). */
html.berg-akt #services[data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel{ position:absolute; }
@media (min-width: 640px){
  html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel{ padding:0 40px; }
}
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel h2{
  font-size:clamp(2.6rem, 7.4vw, 6.6rem); max-width:11em; margin-top:22px; line-height:1.06;
}
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel .sec-sub{
  max-width:36em; margin:22px auto 0; font-size:1.12rem;
}
html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel .sec-label{
  align-self:center;
}
@media (max-width: 640px){
  html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel h2{ font-size:clamp(2.2rem, 10.5vw, 4rem); }
  html.berg-akt [data-berg-akt="pan"]:not([data-berg-akt-aus]) .svc-titel .sec-sub{ font-size:1rem; }
}

/* --- pin: der Prozess als Kartenreihe (RUNDE 2) ---
   Vierter Anlauf. Wischfront verzahnte Texte, der Schub schnitt Zeilen, das
   Kartendeck ueberlappte (Vorgabe: Karten duerfen sich nie ueberschneiden).
   Jetzt: die drei Schritte sind gleich hohe Karten in EINER Reihe (flex,
   stretch), jede mit eigenem Platz; ab data-berg-cue="von" kommt Karte k vom
   unteren Viewport-Rand in ihren Platz (js/berg.js, nur transform). Auf
   Desktop passen alle drei nebeneinander (Platzbreite = (Wrap - 2 Luecken)/3);
   auf schmalen Viewports ist ein Platz so breit wie der Bildschirm und die
   Reihe rueckt mit jeder neuen Karte um einen Platz nach links (Weg misst
   berg.js: Reihenbreite minus Containerbreite, geteilt durch n-1). */
/* minmax(0,1fr): sonst misst die Rasterspalte die max-content-Reihe (drei
   Plaetze) und zieht Kopf und Route mit ueber den Viewport hinaus (gesehen bei
   390 px). Die Reihe darf ueberstehen, die Sektion beschneidet (akt-clip). */
html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .pz-grid{ gap:34px; grid-template-columns:minmax(0, 1fr); }
html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .process-flow{ min-width:0; }
html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .pz-steps{
  --pz-slot:calc((min(1160px, 100vw) - 80px - 44px) / 3);
  display:flex; align-items:stretch; gap:22px; width:max-content; will-change:transform;
}
html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .pz-steps > .step{
  flex:0 0 var(--pz-slot); will-change:transform;
}
@media (max-width: 899px){
  html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .pz-steps{ --pz-slot:calc(100vw - 48px); }
  html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .pz-grid{ gap:26px; }
  html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .pz-kopf .sec-sub{ margin-top:12px; font-size:.98rem; }
  html.berg-akt [data-berg-akt="pin"]:not([data-berg-akt-aus]) .process-line{ margin-bottom:28px; }
}

/* --- kinetic: Ueberschrift in Zeilenmasken ---
   js/berg.js splittet [data-berg-kinetic] in .kin-line-Bloecke (je eine echte
   Zeile) und faehrt den inneren Span hoch (up) bzw. von rechts herein
   (right). Die Maske bekommt Luft fuer Ober- und Unterlaengen — eine Maske,
   die exakt am Zeilenkasten endet, schneidet g, j, p und Umlaute an. */
.kin-line{ display:block; overflow:hidden; padding:.08em 0 .14em; margin:-.08em 0 -.14em; }
.kin-line > span{ display:block; will-change:transform; }
/* RUNDE 2: Variante "words" (FAQ-Kopf): jedes Wort in seiner eigenen Maske,
   inline-block, damit der Zeilenumbruch normal bleibt. Die Woerter setzen
   sich einzeln, gestaffelt, aus der Zeile heraus. */
.kin-wort{ display:inline-block; overflow:hidden; vertical-align:top; padding:.08em 0 .14em; margin:-.08em 0 -.14em; }
.kin-wort > span{ display:inline-block; will-change:transform; }
/* RUNDE 2: Gipfel-Enthuellung (Kontakt-Kopf). Nicht am Scroll, sondern am
   LICHT: --berg-licht laeuft an der Station "kontakt" gelerpt von .7 (Newsletter)
   auf 1 (Gipfel); die Ueberschrift wird von oben freigelegt, als fiele das
   Licht auf den Gipfel. clip-path, also nie halbtransparent. Nur unter
   html.berg-akt — ohne JS steht --berg-licht auf .3 und die Zeile bliebe
   sonst versteckt. */
html.berg-akt .akt-gipfel{
  clip-path:inset(0 0 calc((1 - clamp(0, (var(--berg-licht, 1) - .7) / .3, 1)) * 100%) 0);
  will-change:clip-path;
}

/* --- reveal: Fliesstext baut sich wortweise auf (RUNDE 3) ---
   js/berg.js zerlegt [data-berg-reveal="words"] in .rv-wort-Spans und schreibt
   je Wort opacity + kleinen Y-Versatz aus dem geglaetteten Scroll. Kein
   overflow/Maske wie bei .kin-wort: ein Masken-Slide je Wort macht einen ganzen
   Absatz unruhig (Skill: "words for a short punch line"). Ohne JS und bei
   reduzierter Bewegung bleibt der Text unveraendert sichtbar — hier steht
   bewusst KEIN Startzustand mit opacity:0. */
.rv-wort{ display:inline-block; will-change:auto; }
@media (prefers-reduced-motion: reduce){
  .rv-wort{ opacity:1 !important; transform:none !important; }
}

/* --- scrub: --u (0..1) aus der Lage des Elements im Viewport --- */
.akt-clip{ overflow-x:clip; }
/* Trust: EIN Wischer von links ueber das ganze Raster, die Zitate von unten.
   Negative Innenwerte, damit Schatten und Hover-Lift nicht beschnitten werden. */
.akt-wischer{ clip-path:inset(-24px calc((1 - var(--u, 1)) * 100%) -24px -24px); will-change:clip-path; }
.akt-wischer-auf{ clip-path:inset(calc((1 - var(--u, 1)) * 100%) -24px -24px -24px); will-change:clip-path; }
/* Founder: Foto faehrt von links herein (die Parallax auf .founder-photo
   schreibt transform, das hier ist translate — unabhaengig). */
.akt-slide-links{ translate:calc((1 - var(--u, 1)) * -72px) 0px; }
@media (max-width: 640px){ .akt-slide-links{ translate:calc((1 - var(--u, 1)) * -40px) 0px; } }

/* --- reduzierte Bewegung: Ruhelage, egal was inline steht --- */
@media (prefers-reduced-motion: reduce){
  .kin-line > span, .kin-wort > span{ transform:none !important; }
  .akt-gipfel{ clip-path:none !important; }
  .akt-slide-links{ translate:none !important; }
  .akt-wischer, .akt-wischer-auf{ clip-path:none !important; }
  [data-berg-cue]{ transform:none !important; }
  [data-berg-rail]{ transform:none !important; }
}
