/* ============================================================
   digitalantrieb / 05 - SEKTIONEN A
   Hero, Kinetik-Band, Leistungen, Vorteile.
   ============================================================ */

/* ------------------------------------------------------------
   01 HERO
   Dunkle Buehne. Das Bild sitzt bündig an der oberen Kante und
   laeuft rechts aus dem Format. Die Headline schneidet seine
   untere Ecke an. Kein Text-links-Bild-rechts.

   Unter dem Fussbereich steht die Leistungsleiste: vier
   Eintraege mit Preis. Wer die Seite oeffnet, sieht sofort,
   was es gibt und was es kostet.
   ------------------------------------------------------------ */
.hero {
  position: relative;

  /* Nicht mehr stur die volle Bildschirmhoehe.

     Seit die drei Versprechen nebeneinander stehen, ist die
     Schlagzeile eine Zeile statt drei - der ganze Block ist um
     rund 130 Pixel geschrumpft. Bei erzwungenen 100svh
     verteilte sich der Rest als je gut 200 Pixel Leere ueber
     und unter dem Inhalt. Die Flaeche war voll, der Bildschirm
     aber leer.

     46rem sind so hoch, dass Auszeichnung, Schlagzeile, Lede,
     Knoepfe und die drei Pakete bequem stehen, und niedrig
     genug, dass auf hohen Bildschirmen die naechste Sektion
     unten hereinschaut. Das ist kein Schoenheitsfehler,
     sondern die Einladung weiterzulesen. */
  min-height: min(100svh, 46rem);
  /* Oben bleibt die Navigationszeile frei, sonst laeuft die
     Auszeichnung unter das Logo. Der seitliche Innenabstand
     sitzt in .hero__inner, damit das Bild ohne Rechnerei bis
     an die Formatkante laufen kann. */
  padding: calc(72px + 0.75rem) 0 clamp(1.5rem, 3.5vh, 3rem);
  display: flex;
  flex-direction: column;

  /* Frueher flex-end: der Block klebte an der Unterkante und
     alles, was uebrig blieb, sammelte sich als Loch zwischen
     Logo und Auszeichnung. Das ging auf, solange die Schlag-
     zeile drei Zeilen à 180 Pixel hoch war. Seit sie kleiner
     ist und Lede, Knopf und Paketleiste darunter stehen,
     blieben oben rund 180 Pixel Leere - genau dort, wo der
     Besucher zuerst hinsieht.

     center verteilt den Rest gleichmaessig: oben so viel Luft
     wie unten, und die Auszeichnung rueckt an die Navigation
     heran, ohne sie zu beruehren. */
  justify-content: center;
  overflow: clip;
}

/* ------------------------------------------------------------
   DIE FIGUR

   Sitzt dort, wo bis eben das Foto sass: oben rechts, gut die
   halbe Breite. Die Masse sind absichtlich dieselben geblieben,
   damit die Komposition der Seite stehen bleibt - nur der
   Inhalt der Flaeche ist ein anderer.
   ------------------------------------------------------------ */
.hero__figur {
  position: absolute;
  top: 0;
  right: 0;
  width: min(58vw, 62rem);
  height: min(74vh, 56rem);
  z-index: 0;
  pointer-events: none;

  /* Der Takt des Fadens steht hier, an einer Stelle, und alle
     vier Bahnen nehmen ihn von hier. Vorher stand die Dauer
     viermal einzeln im Stylesheet - wer sie aendern wollte,
     musste vier Zahlen finden und durfte keine vergessen, sonst
     laufen Kopf und Spur auseinander.

     Der Versatz des zweiten Zuges haengt mit dran: Er ist immer
     ein knappes Sechstel des Taktes, damit das a im selben
     Verhaeltnis nachzieht, egal wie schnell es laeuft.

     Die Zahl allein sagt wenig - entscheidend ist, wie lange
     das Einlaufen dauert, und das sind 42 Prozent des Taktes:

       Takt  6 s  ->  2,5 s einlaufen  (war zu schnell)
       Takt 10 s  ->  4,2 s einlaufen  (jetzt)

     Rund ein Drittel langsamer also, und der Halt in der Mitte
     ist dabei schon abgezogen. */
  --faden-takt: 10s;
  --faden-versatz: calc(var(--faden-takt) / 6);
}

/* Die Glut hinter dem Zeichen. Ein weicher Schein, kein Kreis
   mit Kante - deshalb ein Verlauf mit langem Auslauf und ohne
   Weichzeichner: blur() ueber eine halbe Bildschirmflaeche
   kostet auf schwaecheren Geraeten jedes zweite Bild, ein
   Verlauf kostet nichts.

   Sie atmet, aber nur in Deckkraft und Groesse. Beides laeuft
   auf der Grafikkarte. */
.hero__glut {
  position: absolute;
  inset: -10%;
  background: radial-gradient(
    46% 42% at 56% 46%,
    color-mix(in srgb, var(--signal) 17%, transparent) 0%,
    color-mix(in srgb, var(--signal) 6%, transparent) 42%,
    transparent 72%
  );
  opacity: 0.55;
  will-change: transform, opacity;
  animation: glut-atmen 11s ease-in-out infinite alternate;
}
@keyframes glut-atmen {
  from { opacity: 0.38; transform: scale(1); }
  to   { opacity: 0.72; transform: scale(1.07); }
}

.faden {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Gemeinsame Werte aller vier Bahnen eines Zuges. Die
   Strichstaerken stehen in Nutzereinheiten, nicht in Pixeln:
   So waechst der Strich mit dem Zeichen mit, statt auf einem
   grossen Bildschirm zum Haar zu werden. */
.faden path {
  fill: none;
  stroke: var(--signal);
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}

/* Die Werte sind zweimal gesenkt worden, und zwar aus einem
   Grund: Der erste Versuch war schoen und falsch. Eine Spur mit
   85 Prozent Deckkraft ist kein Hintergrund mehr, sie ist eine
   zweite Schlagzeile - und "Mehr Umsatz." lief mitten durch
   einen leuchtenden Kreis.

   Was hier steht, sieht man erst, wenn man hinsieht. Genau das
   soll es: Wer auf die Seite kommt, liest das Versprechen. Wer
   einen Moment bleibt, merkt, dass sich hinten etwas zeichnet. */

/* Der Hof: breit und fast durchsichtig. Er macht aus dem
   Strich ein Leuchten, ohne dass ein Filter rechnen muss. */
.faden__hof     { stroke-width: 0.7;  opacity: 0.055; }
/* Die Spur: der Faden selbst. */
.faden__spur    { stroke-width: 0.085; opacity: 0.45; }
/* Der Kopf: das helle Stueck, das vorne zieht, und sein Hof.
   Er darf heller sein als die Spur - er ist klein, bewegt sich
   und ist der einzige Teil, der wirklich auffallen soll. Zwei
   Striche in der Laenge von zwei Hundertsteln der Bahn, deshalb
   steht in dasharray 2 98 statt 100. */
/* Mit dem Elementnamen davor, und das ist keine Schoenheit:
   .faden path setzt stroke-dasharray: 100 und hat als
   Kombination aus Klasse und Element die hoehere Spezifitaet
   als eine Klasse allein. Ohne das "path" hier gewann also die
   Grundregel - der "Kopf" bekam die volle Bahnlaenge statt
   zwei Hundertsteln und leuchtete als dicker Strich ueber den
   ganzen Faden mit. Das war der zu laute Strich. */
.faden path.faden__kopfhof { stroke-width: 0.42; stroke-dasharray: 2 98; }
.faden path.faden__kopf    { stroke-width: 0.13; stroke-dasharray: 2 98; stroke: color-mix(in srgb, var(--signal) 55%, #fff); }

/* ------------------------------------------------------------
   DIE BEWEGUNG

   pathLength="100" im Markup ist der Trick, der das hier
   einfach macht: Es normiert jede Bahn auf die Laenge 100,
   egal wie lang sie in Wirklichkeit ist. Dadurch laufen
   Schaft-plus-Bauch und der kuerzere zweite Zug mit demselben
   Keyframe, und es muss nichts ausgemessen werden.

   Ein Durchgang dauert --faden-takt und hat drei Abschnitte:

     0  - 42 %   einlaufen   (4,2 s)
     42 - 58 %   stehen      (1,6 s)  <- das fertige Zeichen
     58 - 100 %  auslaufen   (4,2 s)

   Zum Halt: Er war einmal draussen, weil er mit fast einem
   Drittel der Zeit zu lang war - daraus wurden drei Ereignisse
   statt einer Bewegung. Mit anderthalb Sekunden ist er das,
   was er sein soll: ein Atemzug, in dem das Zeichen einmal
   ganz dasteht.

   Zur Fluessigkeit - und das ist der Teil, der Rechnerei
   gekostet hat:

   Eine einzige Kurve ueber den ganzen Einlauf zieht am Anfang
   an und schleicht am Ende; eine rein lineare Bewegung rammt
   in den Halt und reisst wieder an. Beides sieht man.

   Deshalb ist jeder Lauf zweigeteilt: Der lange Teil laeuft
   streng gleichmaessig, nur das letzte Stueck bremst weich aus,
   und nach dem Halt spiegelt sich das. Damit an der Naht
   zwischen beiden kein Ruck entsteht, muessen dort beide
   Geschwindigkeiten gleich sein - und das ist keine
   Geschmacksfrage, sondern eine Rechnung:

     gerader Teil   0 -> 33 %, Versatz 100 -> 12
                    macht 88 Einheiten auf 33 Prozent,
                    also 2,667 Einheiten je Prozent

     Bremsweg      33 -> 42 %, also 9 Prozent Zeit.
                    Wer aus 2,667 gleichmaessig auf null
                    abbremst, legt dabei die Haelfte zurueck:
                    2,667 x 9 / 2 = 12 Einheiten. Genau die
                    12, die noch offen sind.

   Die Kurve dafuer ist cubic-bezier(0.25, 0.5, 0.5, 1): Ihre
   Steigung am Anfang ist 0,5/0,25 = 2, und 2 ist genau das
   Tempo des geraden Teils, umgerechnet auf diesen Abschnitt.
   Am Ende ist die Steigung null. Nahtlos hinein, sauber zum
   Stehen.

   Der Versatz laeuft von +100 auf -100. Solange er faellt,
   schiebt sich der Anfang des Fadens die Bahn entlang; ab null
   zieht das Ende nach.
   ------------------------------------------------------------ */
@keyframes faden-ziehen {
  0%   { stroke-dashoffset: 100;  animation-timing-function: linear; }
  33%  { stroke-dashoffset: 12;   animation-timing-function: cubic-bezier(0.25, 0.5, 0.5, 1); }
  42%  { stroke-dashoffset: 0;    animation-timing-function: linear; }
  58%  { stroke-dashoffset: 0;    animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0.5); }
  67%  { stroke-dashoffset: -12;  animation-timing-function: linear; }
  100% { stroke-dashoffset: -100; }
}

/* Der Kopf zieht nur, solange gezeichnet wird. Danach ist er
   weg - ein Leuchtpunkt, der auf einer fertigen Linie stehen
   bleibt, sieht aus wie ein Fehler.

   Zwei getrennte Bildfolgen fuer Kern und Hof, obwohl sie
   dasselbe tun. Grund: Eine Bildfolge, die opacity anfasst,
   ueberschreibt den Wert aus der Klassenregel fuer die ganze
   Laufzeit. Mit einer gemeinsamen Folge haetten beide dieselbe
   Deckkraft bekommen - der Hof waere so hell geworden wie der
   Kern, und aus dem Schein ein zweiter Strich. */
/* Lauf und Licht sind getrennte Bildfolgen, und das hat einen
   Grund: Der Kopf muss dieselbe Kurve fahren wie die Spur,
   sonst laeuft er ihr am Ende des Einlaufs davon - die Spur
   bremst in den Halt, er nicht. Zwischenwerte fuer die Deckkraft
   wuerden diese Kurve aber in Abschnitte zerlegen und damit
   kaputtmachen. Zwei Bildfolgen auf demselben Element, jede fuer
   ihre eigene Eigenschaft: Der Lauf behaelt die Kurve der Spur,
   das Licht schaltet unabhaengig davon. */
@keyframes faden-kopf-lauf {
  0%   { stroke-dashoffset: 100; animation-timing-function: linear; }
  33%  { stroke-dashoffset: 12;  animation-timing-function: cubic-bezier(0.25, 0.5, 0.5, 1); }
  42%  { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: 0; }
}
@keyframes faden-kopf-licht {
  0%   { opacity: 0; }
  4%   { opacity: 0.9; }
  37%  { opacity: 0.9; }
  43%  { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes faden-kopfhof-licht {
  0%   { opacity: 0; }
  4%   { opacity: 0.2; }
  37%  { opacity: 0.2; }
  43%  { opacity: 0; }
  100% { opacity: 0; }
}

/* linear steht hier als Grundwert. Die eigentlichen Kurven
   setzen die Bildfolgen selbst, je Abschnitt - siehe oben. */
html[data-motion="on"] .faden__hof,
html[data-motion="on"] .faden__spur {
  animation: faden-ziehen var(--faden-takt) linear infinite;
}
html[data-motion="on"] .faden__kopf {
  animation: faden-kopf-lauf var(--faden-takt) linear infinite,
             faden-kopf-licht var(--faden-takt) linear infinite;
}
html[data-motion="on"] .faden__kopfhof {
  animation: faden-kopf-lauf var(--faden-takt) linear infinite,
             faden-kopfhof-licht var(--faden-takt) linear infinite;
}
/* Das a zieht mit einem Sechstel Versatz nach. Zwei Zuege, nicht
   zwei Animationen nebeneinander. Der Versatz gilt fuer beide
   Bildfolgen eines Elements - deshalb reicht der eine Wert. */
html[data-motion="on"] .faden__zug--a path { animation-delay: var(--faden-versatz); }

/* Ausserhalb des Bildschirms steht die Bewegung still. Gesetzt
   wird die Klasse in modules/hero.js. */
html .hero__figur.ist-ruhig * { animation-play-state: paused; }

/* Ohne Bewegung steht das Zeichen einfach da. Das ist kein
   Notbetrieb: Ein gezeichnetes Zeichen ist auch ohne die
   Bewegung ein Bild. */
html[data-motion="off"] .faden__hof,
html[data-motion="off"] .faden__spur { stroke-dashoffset: 0; }
html[data-motion="off"] .faden__kopf,
html[data-motion="off"] .faden__kopfhof { display: none; }
html[data-motion="off"] .hero__glut { animation: none; opacity: 0.6; }

@media (prefers-reduced-motion: reduce) {
  .faden__hof, .faden__spur { animation: none; stroke-dashoffset: 0; }
  .faden__kopf, .faden__kopfhof { display: none; }
  .hero__glut { animation: none; opacity: 0.6; }
}

/* Waehrend der Eroeffnung ist die Figur noch nicht da. Sie
   blendet in intro.js auf, zusammen mit der Schlagzeile. */
html[data-motion="on"]:not(.is-ready) .hero__figur { opacity: 0; }

/* Alles, was nach dem Foto kommt, startet unsichtbar. */
html[data-motion="on"]:not(.is-ready) .hero__eyebrow,
html[data-motion="on"]:not(.is-ready) .hero__lede,
html[data-motion="on"]:not(.is-ready) .hero__cta,
html[data-motion="on"]:not(.is-ready) .hero__meta,
html[data-motion="on"]:not(.is-ready) .hero__strip,
html[data-motion="on"]:not(.is-ready) .nav__right,
html[data-motion="on"]:not(.is-ready) .axis {
  opacity: 0;
}

/* ------------------------------------------------------------
   HIER FLOG FRUEHER DAS ZEICHEN

   Ein eigenes, fest positioniertes Logo startete in der Bild-
   mitte und flog in den Kopf der Seite. Das ist raus: Die
   erste Sekunde gehoert dem Versprechen, nicht der Marke.
   Jetzt fliegen die Worte der Schlagzeile ins Bild, und das
   Zeichen im Kopf steht vom ersten Frame an, wo es hingehoert.

   Damit entfaellt auch die Regel, die es dort zwischenzeitlich
   unsichtbar gemacht hat. Siehe scripts/modules/intro.js.
   ------------------------------------------------------------ */

/* Die Schlagzeile faehrt aus einer leicht groesseren Lage auf
   ihre Ruhegroesse zurueck. Der Startwert steht hier und nicht
   im Skript - aus demselben Grund wie alles andere in diesem
   Block: Skripte laufen erst nach dem ersten Bild. */
html[data-motion="on"]:not(.is-ready) .hero__title {
  transform: scale(1.06);
  transform-origin: 0% 100%;
}

/* Die Headline nutzt die volle Formatbreite, der Fussbereich
   bleibt im Raster. Dadurch bekommt die Zeile Luft, ohne dass
   der Text darunter auseinanderfaellt. */
.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-inline: var(--gutter);
}

.hero__eyebrow {
  margin-bottom: clamp(1rem, 2.5vh, 2rem);
  color: color-mix(in srgb, var(--chalk) 52%, transparent);
}

.hero__title {
  position: relative;
  margin-bottom: clamp(1.5rem, 3.5vh, 2.75rem);

  /* Kleiner als die Mega-Groesse des Systems, aber groesser als
     in der einzeiligen Fassung.

     Die Zwischenstufe, in der alle drei Versprechen
     nebeneinander standen, hat die Groesse diktiert: 36 Zeichen
     in einer Zeile passen bei 1920 Pixeln Fensterbreite nur bis
     rund 77 Pixel Schriftgroesse, mit Sicherheitsabstand 58.
     Untereinander faellt diese Fessel weg - die laengste Zeile
     ist "Mehr Kunden." mit zwoelf Zeichen.

     Die Grenze ist jetzt nicht mehr die Breite, sondern die
     Hoehe: Unter der Schlagzeile stehen Lede, Knoepfe und die
     drei Pakete mit Preis, und die gehoeren auf denselben
     Bildschirm. Die urspruenglichen 9,4vw waren dreimal 180
     Pixel und haben den Preis unter die Falz gedrueckt. Das
     beeindruckt, verkauft aber nichts.

     4,8vw sind bei 1920 Pixeln 92. Der Fliesstext daneben steht
     bei 24 - das ist knapp das Vierfache, und darum geht es
     hier: Ein Versprechen, das nur anderthalbmal so gross ist
     wie der Absatz darunter, liest sich wie eine Zwischen-
     ueberschrift. Erst ab etwa dem Dreifachen entsteht das
     Gefaelle, das dem Auge sagt, was zuerst dran ist.

     (2026-11-08: Hier stand ein vorzeitiges Kommentarende. Der
     Browser hat dadurch die font-size unten verschluckt, und der
     Titel lief mit --t-mega - Preise rutschten unter die Falz.)

     Die Untergrenze von 2,6rem ist nicht willkuerlich: Am
     Telefon steht der Fliesstext bei 18,4 Pixeln. Mit 4,8vw
     waere die Schlagzeile dort nur 19 Pixel gross, also
     genauso gross wie der Absatz darunter - kein Gefaelle,
     keine Schlagzeile. 41,6 Pixel halten das Verhaeltnis bei
     gut dem Doppelten, und "MEHR KUNDEN." passt damit noch in
     eine Zeile von 320 Pixeln Breite. */
  /* 2026-11-08: Mit wieder greifender Regel wirkte 4,8vw am
     Desktop zu zurueckhaltend, darunter blieb Luft. Jetzt waechst
     die Zeile mit der Breite UND der Hoehe: min(6,4vw, 11svh)
     haelt die Preise auch auf 1366x768 ueber der Falz. */
  font-size: clamp(2.6rem, min(6.4vw, 11svh), 8rem);

  /* 118% waere die Mega-Breite: auseinandergezogen. In einer
     Zeile mit 36 Zeichen kostet jedes Prozent Breite direkt
     Schriftgroesse - von 118% auf 100% sind es rund zwoelf
     Pixel mehr Hoehe. Die Normalbreite ist hier also nicht
     Rueckzug, sondern das, was die Zeile gross haelt. */
  font-stretch: 100%;
  letter-spacing: -0.04em;
}

/* Untereinander, eine Aussage pro Zeile.

   Als Flex-Spalte und nicht einfach als drei Bloecke: So steht
   die Richtung an einer Stelle, und der Wechsel zwischen
   nebeneinander und untereinander ist eine Zeile Aenderung,
   keine Umbaustelle. Kein row-gap - den Zeilenabstand macht die
   Zeilenhoehe der Schrift, sonst reisst der Satz auseinander. */
.hero__title {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  row-gap: 0;
}
.hero__title .line-mask { display: block; }

.hero__foot {
  max-width: var(--maxw);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(1rem, 2vw, 2rem);
  row-gap: var(--stack-3);
  align-items: end;
}
/* Die Lede laeuft in Instrument Sans, also in derselben
   Schrift wie jeder Absatz der Seite. Sie ist Fliesstext und
   gehoert damit zum Text, nicht zur Schlagzeile darueber. */
.hero__lede { grid-column: 1 / span 4; }
/* Fuenf statt vier Spalten, weil hier jetzt zwei Knoepfe
   nebeneinander stehen: anfragen und die Demos ansehen. Die
   Lede gibt die Spalte ab, die sie dafuer braucht - sie ist
   ohnehin auf 34 Zeichen begrenzt und wird dadurch nicht
   schmaler gesetzt, nur frueher umgebrochen. */
.hero__cta {
  grid-column: 5 / span 6;
  justify-self: start;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.9rem;
}
.hero__cta-reihe {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}
.hero__second { color: var(--on-stage-2); }
.hero__meta {
  grid-column: 11 / span 2;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  text-align: right;
  align-items: flex-end;
}
.hero__meta b { color: var(--signal); font-weight: 500; }

/* Leistungsleiste. Vier Felder, Hairline dazwischen, Preis in
   Signalfarbe. Beim Hovern faehrt die Flaeche von unten ein. */
.hero__strip {
  margin-top: clamp(2rem, 5vh, 3.5rem);
  max-width: var(--maxw);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: var(--hair) solid var(--rule);
}
.hero__strip li { border-left: var(--hair) solid var(--rule); }
.hero__strip li:first-child { border-left: 0; }
.hero__strip a {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: clamp(0.85rem, 1.6vw, 1.3rem) clamp(0.75rem, 1.4vw, 1.25rem);
  isolation: isolate;
  overflow: hidden;
}
.hero__strip a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--chalk) 7%, transparent);
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform 0.45s var(--e-out);
}
.hero__strip b {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 108%;
  font-size: clamp(0.95rem, 1.5vw, 1.35rem);
  letter-spacing: var(--track-lg);
  text-transform: uppercase;
  line-height: 1;
}
.hero__strip em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--signal);
  white-space: nowrap; /* "499 €" nie zwischen Zahl und Waehrung trennen */
}
@media (hover: hover) and (pointer: fine) {
  .hero__strip a:hover::before { transform: scaleY(1); transform-origin: top center; }
}

/* ------------------------------------------------------------
   DIE PAKETLEISTE

   Frueher standen hier die vier Leistungen. Das beantwortete
   die Frage "was machst du" - gesucht wird aber "was kostet
   es". Ein Besucher, der einen Preis sucht und keinen findet,
   geht wieder; und er geht zu dem, der ihn hingeschrieben hat.

   Deshalb zwei Felder statt vier, und die Reihenfolge im Feld
   umgedreht: Der Betrag ist jetzt die grosse Zeile, der
   Paketname die kleine daruber. Gekauft wird der Preis.

   Zwei Pakete, zwei Spalten: Website oder der ganze Auftritt.
   Wer waehlen soll, waehlt leichter zwischen zwei Dingen.
   ------------------------------------------------------------ */
.hero__strip--pakete { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.hero__strip--pakete b {
  font-size: clamp(0.72rem, 0.95vw, 0.85rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: color-mix(in srgb, var(--chalk) 62%, transparent);
}
.hero__strip--pakete em {
  font-variant-numeric: tabular-nums;
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 108%;
  font-size: clamp(1.25rem, 2.2vw, 2rem);
  letter-spacing: var(--track-lg);
  line-height: 1;
  text-transform: none;
}
.hero__strip-note {
  font-size: var(--t-meta);
  line-height: 1.35;
  color: color-mix(in srgb, var(--chalk) 55%, transparent);
}

@media (max-width: 1024px) {
  .hero__lede { grid-column: 1 / span 8; }
  .hero__cta  { grid-column: 1 / span 12; flex-direction: row; align-items: center; gap: 1.5rem; }
  .hero__meta { grid-column: 1 / span 12; text-align: left; align-items: flex-start; }
  .hero__strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero__strip li:nth-child(3) { border-left: 0; }
  .hero__strip li:nth-child(n + 3) { border-top: var(--hair) solid var(--rule); }

  /* Zwei Pakete passen hier ohnehin nebeneinander. Die
     Beschreibungszeile bleibt am Tablet stehen (2026-11-08):
     Ohne sie stand 199 gegen 499 Euro ohne Begruendung. Erst am
     Telefon faellt sie weg, dort zaehlt jede Zeile ueber der
     Falz - die Begruendung steht dann im Preisblock. */
  .hero__strip--pakete .hero__strip-note { font-size: var(--t-meta); }
}
@media (max-width: 560px) {
  .hero__strip--pakete .hero__strip-note { display: none; }
}

@media (max-width: 900px) {
  /* ----------------------------------------------------------
     DAS FOTO IST NICHT MEHR DAS ERSTE, WAS MAN SIEHT

     Hier lag ein Bildband ueber der Schlagzeile, 46svh hoch -
     also fast die halbe Bildschirmhoehe. Wer die Seite am
     Telefon oeffnete, sah zuerst eine Zimmerpflanze und erfuhr
     erst in der unteren Haelfte, worum es ueberhaupt geht.

     Auf einer Seite, die verkaufen soll, ist das die teuerste
     halbe Bildschirmhoehe, die es gibt: Genau dort entscheidet
     sich, ob jemand bleibt. Und am Telefon kommen die meisten.

     Jetzt liegt das Foto hinter dem Text, wie am grossen
     Bildschirm auch, nur ueber die ganze Flaeche. Es traegt die
     Stimmung, der Text traegt die Sache.
     ---------------------------------------------------------- */
  .hero {
    min-height: min(100svh, 42rem);
    padding-top: calc(72px + 0.5rem);
    padding-bottom: var(--stack-4);
    justify-content: center;
  }
  /* Die Figur nimmt die ganze Flaeche und rueckt nach oben:
     Am Telefon steht der Text darauf, nicht daneben. Das
     Zeichen liegt also hinter der Schlagzeile - gross genug,
     um als Form zu wirken, leise genug, um nicht mitzulesen. */
  .hero__figur {
    inset: 0;
    width: auto;
    height: auto;
  }
  .hero__glut { inset: -18% -25%; }

  /* Das Zeichen rueckt nach oben und ein Stueck nach rechts.

     In einem hohen, schmalen Format landet es sonst genau in
     der Mitte - und in der Mitte stehen am Telefon die beiden
     Knoepfe. Ein Kreis, der quer durch "Demos ansehen" laeuft,
     ist kein Hintergrund, sondern Unruhe an der Stelle, an der
     geklickt werden soll. Oben kreuzt er nur die Schlagzeile,
     und die ist weiss und fett genug, um das zu tragen. */
  .faden { transform: translate(7%, -15%); }

  /* Und deutlich blasser. Auf dreissig Zentimetern Armlaenge
     wirkt derselbe Strich kraeftiger als auf einem Monitor in
     zwei Metern Abstand. */
  .faden__spur { opacity: 0.26; stroke-width: 0.08; }
  .faden__hof  { opacity: 0.045; }

  /* Die Glut wird ueber die Farbe zurueckgenommen, nicht ueber
     die Deckkraft: An der Deckkraft haengt die Bildfolge, die
     sie atmen laesst - ein Wert hier wuerde von ihr sofort
     ueberschrieben und waere wirkungslos. */
  .hero__glut {
    background: radial-gradient(
      46% 42% at 56% 46%,
      color-mix(in srgb, var(--signal) 11%, transparent) 0%,
      color-mix(in srgb, var(--signal) 4%, transparent) 42%,
      transparent 72%
    );
  }

  /* Hier stand die Treppe: drei Zeilen, jede weiter eingerueckt
     als die vorige, und spaeter die Umstellung auf Spalte. Beides
     ist raus - die Versprechen stehen jetzt auf jeder Breite
     untereinander, das steht einmal oben und gilt ueberall. */
}

/* ------------------------------------------------------------
   TELEFON: DIE HANDLUNGEN UNTEREINANDER

   Ab 1024 Pixeln stehen Knoepfe und der Verweis auf die Preise
   in einer Reihe. Am Telefon ging das nicht mehr auf: Die
   Knoepfe waren so breit, dass sie untereinander rutschten,
   der Verweis "Preise ansehen" blieb aber daneben haengen und
   stand plötzlich rechts neben den Knoepfen in der Luft.

   Untereinander, in der Reihenfolge der Wichtigkeit. Dafuer
   werden die Knoepfe etwas flacher - die Hoehe, die das spart,
   fehlt sonst unten bei den Preisen.
   ------------------------------------------------------------ */
@media (max-width: 700px) {
  .hero__cta {
    flex-direction: column;
    align-items: stretch;
    gap: 0.85rem;
  }
  .hero__cta-reihe {
    flex-direction: column;
    align-items: stretch;
    gap: 0.6rem;
  }
  .hero__cta .btn {
    justify-content: space-between;
    padding: 0.95rem 1.25rem;
    gap: 1rem;
  }
  .hero__second { align-self: flex-start; }
}

@media (max-width: 560px) {
  /* Der Fliesstext ist nach der Schlagzeile der hoechste Block
     im Hero - auf 360 Pixeln bricht er in sechs Zeilen um. Eine
     Spur kleiner und enger gesetzt spart rund dreissig Pixel,
     und dreissig Pixel entscheiden hier darueber, ob das dritte
     Paket noch ueber der Falz steht. Am Satz selbst aendert
     sich nichts: Was auf dem grossen Bildschirm verkauft,
     verkauft auf dem kleinen genauso. */
  .hero__lede { font-size: 1.05rem; line-height: 1.34; }
  /* Volle Breite statt 8 von 12 Spalten: am Telefon liess die
     Spannweite aus dem Tablet-Umbruch ein Drittel der Zeile leer
     und machte den Absatz unnoetig lang (2026-11-08). */
  .hero__lede { grid-column: 1 / -1; max-width: 36ch; }
  .hero__foot { row-gap: 1.1rem; }

  .hero__strip { grid-template-columns: 1fr; }
  .hero__strip li { border-left: 0; border-top: var(--hair) solid var(--rule); }
  .hero__strip li:first-child { border-top: 0; }
  .hero__strip a { flex-direction: row; align-items: baseline; justify-content: space-between; gap: 1rem; }

  /* Am Telefon eine Preisliste: Name links, Betrag rechts.
     Drei Zeilen untereinander lesen sich schneller als drei
     Spalten, die jede fuer sich zu schmal geworden waeren. */
  .hero__strip--pakete { grid-template-columns: 1fr; }
  .hero__strip--pakete li { border-left: 0; border-top: var(--hair) solid var(--rule); }
  .hero__strip--pakete li:first-child { border-top: 0; }
  .hero__strip--pakete b { font-size: 0.8rem; }
  .hero__strip--pakete em { font-size: 1.35rem; }
}

/* ------------------------------------------------------------
   02 KINETIK-BAND
   Eine Zeile, die ihre Richtung aus dem Scrollen bezieht.
   Der einzige Laufschriftmoment der Seite.
   ------------------------------------------------------------ */
.band {
  padding-block: clamp(2.25rem, 5vw, 4.5rem);
  overflow: hidden;
  border-block: var(--hair) solid var(--rule);
}
.band__track {
  display: flex;
  width: max-content;
  will-change: transform;
}
.band__cell {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  padding-right: clamp(1.5rem, 4vw, 3.5rem);
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 118%;
  font-size: clamp(2.6rem, 9vw, 9rem);
  line-height: 0.9;
  letter-spacing: var(--track-mega);
  text-transform: uppercase;
  white-space: nowrap;
}
.band__cell em { font-style: normal; }
.band__dot {
  flex: none;
  width: clamp(0.5rem, 1.4vw, 1.1rem);
  aspect-ratio: 1;
  background: var(--signal);
  transform: rotate(45deg);
}

/* ------------------------------------------------------------
   03 LEISTUNGEN
   Keine Kacheln. Vier begehbare Baender ueber die volle Breite,
   jedes mit Nutzen und Preis. Auf dem Zeigegeraet folgt ein
   Bild dem Cursor, auf Touch klappt die Zeile auf.
   ------------------------------------------------------------ */
.svc { position: relative; }

.svc__head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(1rem, 2vw, 2rem);
  row-gap: var(--stack-3);
  align-items: end;
  margin-bottom: clamp(2.5rem, 6vw, 4.5rem);
}
.svc__head h2 { grid-column: 1 / span 8; }
.svc__head .body { grid-column: 9 / span 4; }
@media (max-width: 1024px) {
  .svc__head h2, .svc__head .body { grid-column: 1 / -1; }
}

.svc__list { border-top: var(--hair) solid var(--rule); }

.svc__row {
  position: relative;
  display: grid;
  grid-template-columns: 4rem minmax(0, 1fr) minmax(0, 22rem) 9rem 2.5rem;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.5rem);
  width: 100%;
  padding-block: clamp(1.4rem, 2.8vw, 2.4rem);
  border-bottom: var(--hair) solid var(--rule);
  text-align: left;
  isolation: isolate;
  overflow: hidden;
  color: inherit;
}
.svc__row::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--signal);
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform 0.55s var(--e-out);
}
.svc__idx {
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  letter-spacing: 0.1em;
  color: var(--signal);
  transition: color 0.4s var(--e-out), transform 0.55s var(--e-out);
}
.svc__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 112%;
  font-size: clamp(1.4rem, 4.6vw, 4.2rem);
  line-height: 0.94;
  letter-spacing: var(--track-xl);
  text-transform: uppercase;
  transition: transform 0.55s var(--e-out);
}
.svc__desc {
  font-size: var(--t-sm);
  line-height: 1.5;
  color: var(--on-stage-2);
  transition: color 0.4s var(--e-out), transform 0.55s var(--e-out), opacity 0.4s var(--e-out);
}
/* Der Nutzen steht auf einer eigenen Zeile und in der
   Textfarbe: er ist das Verkaufsargument, nicht die Fussnote. */
.svc__desc b {
  display: block;
  margin-top: 0.5rem;
  font-weight: 500;
  color: var(--on-stage);
}
.svc__tag {
  justify-self: start;
  font-family: var(--font-mono);
  font-size: var(--t-sm);
  letter-spacing: 0.04em;
  color: var(--signal);
  white-space: nowrap;
  transition: color 0.4s var(--e-out);
}
.svc__arrow {
  justify-self: end;
  width: 1.5rem;
  transition: transform 0.55s var(--e-out);
}
.svc__arrow line, .svc__arrow polyline { stroke: currentColor; stroke-width: 1.5; fill: none; }

@media (hover: hover) and (pointer: fine) {
  .svc__row:hover::before { transform: scaleY(1); transform-origin: top center; }
  .svc__row:hover { color: var(--on-signal); }
  .svc__row:hover .svc__idx { color: color-mix(in srgb, var(--on-signal) 75%, transparent); }
  .svc__row:hover .svc__desc { color: color-mix(in srgb, var(--on-signal) 85%, transparent); }
  .svc__row:hover .svc__desc b { color: var(--on-signal); }
  .svc__row:hover .svc__tag { color: var(--on-signal); }
  .svc__row:hover .svc__name { transform: translateX(clamp(0.6rem, 1.6vw, 1.6rem)); }
  .svc__row:hover .svc__arrow { transform: translate(0.5rem, -0.5rem); }
}
.svc__row:focus-visible { outline-offset: -3px; color: var(--on-signal); }
.svc__row:focus-visible::before { transform: scaleY(1); transform-origin: top center; }

/* ------------------------------------------------------------
   HIER GILT DER NORMALE MAUSZEIGER

   Frueher lief ueber den Leistungszeilen ein Bild mit der Maus
   mit, und der Systemcursor war ausgeblendet. Das sah gut aus
   und war schlecht zu bedienen: Ein Zeiger, den man nicht
   sieht, macht das Treffen einer Zeile zur Schaetzaufgabe, und
   ein Bild von 24 rem Breite verdeckt genau den Text, den es
   bebildern soll.

   Der Cursor-Zustand wird in modules/cursor.js umgeschaltet,
   die Regeln dazu stehen in 04-chrome.css. Auf Touch klappen
   die Zeilen weiterhin auf; das Bild dafuer liegt als
   .svc__thumb in der Zeile selbst.
   ------------------------------------------------------------ */
.svc__list { cursor: default; }
.svc__row { cursor: pointer; }

/* Touch-Alternative: das Bild liegt in der Zeile und oeffnet sich beim Antippen */
.svc__thumb {
  display: none;
  grid-column: 1 / -1;
  height: 0;
  overflow: hidden;
  transition: height 0.6s var(--e-drawer);
}
.svc__thumb img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) contrast(1.08); }

/* Enger wird nicht gestapelt, sondern umsortiert. Alle Felder
   bekommen dabei ihren Platz ausdruecklich zugewiesen: sobald
   ein Element in eine andere Zeile rutscht, waere die
   automatische Platzierung sonst nicht mehr vorhersagbar und
   Name und Preis lägen uebereinander. */
@media (max-width: 1200px) and (hover: hover) {
  .svc__row { grid-template-columns: 3.5rem minmax(0, 1fr) minmax(0, 18rem) 2.5rem; row-gap: 0.4rem; }
  .svc__idx  { grid-area: 1 / 1; }
  .svc__name { grid-area: 1 / 2; }
  .svc__desc { grid-area: 1 / 3; }
  .svc__arrow{ grid-area: 1 / 4; }
  .svc__tag  { grid-area: 2 / 2; }
}
@media (max-width: 900px) and (hover: hover) {
  .svc__row { grid-template-columns: 3rem minmax(0, 1fr) 2.5rem; row-gap: 0.4rem; }
  .svc__idx  { grid-area: 1 / 1; }
  .svc__name { grid-area: 1 / 2; }
  .svc__arrow{ grid-area: 1 / 3; }
  .svc__desc { display: none; }
  .svc__tag  { grid-area: 2 / 2; justify-self: start; }
}

/* Touch: die Zeile traegt alles und klappt beim Antippen das
   Bild auf. Der Pfeil dreht sich dabei. */
@media (hover: none), (pointer: coarse) {
  .svc__row { grid-template-columns: 3rem minmax(0, 1fr) 2rem; row-gap: 0.6rem; align-items: start; }
  .svc__idx  { grid-area: 1 / 1; padding-top: 0.35em; }
  .svc__name { grid-area: 1 / 2; }
  .svc__arrow{ grid-area: 1 / 3; align-self: center; }
  .svc__desc { grid-area: 2 / 2 / auto / 4; display: block; }
  .svc__tag  { grid-area: 3 / 2 / auto / 4; justify-self: start; }
  .svc__thumb { display: block; grid-row: 4; }
  .svc__row[aria-expanded="true"] .svc__thumb { height: clamp(11rem, 42vw, 18rem); margin-top: 1rem; }
  .svc__row[aria-expanded="true"] .svc__arrow { transform: rotate(90deg); }
}

/* Sehr schmale Geraete: die Randspalten geben Platz ab, damit
   auch das laengste Wort in eine Zeile passt. */
@media (max-width: 480px) {
  .svc__row {
    grid-template-columns: 2rem minmax(0, 1fr) 1.25rem;
    column-gap: 0.5rem;
  }
  .svc__arrow { width: 1rem; }
}

/* ------------------------------------------------------------
   04 VORTEILE
   Drei Saetze unter den Leistungen. Kein eigener Bildschirm,
   nur der Einwand, der sonst im Kopf bleibt.
   ------------------------------------------------------------ */
.usp {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
}
.usp__item {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-top: clamp(1rem, 2vw, 1.5rem);
  border-top: 2px solid var(--signal);
}
.usp__n {
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  letter-spacing: 0.1em;
  color: var(--on-stage-2);
}
.usp__item b {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 108%;
  font-size: clamp(1.1rem, 1.7vw, 1.5rem);
  letter-spacing: var(--track-lg);
  text-transform: uppercase;
  line-height: 1;
}
.usp__item p { font-size: var(--t-sm); color: var(--on-stage-2); max-width: 32ch; }

@media (max-width: 900px) {
  .usp { grid-template-columns: 1fr; gap: 1.5rem; }
}
