/* ==================================================================
   DER PREISABSCHNITT STEHT NICHT MEHR HIER (20.09.2026)
   ==================================================================
   Die Startseite hatte eine eigene Fassung des Preisabschnitts, und
   dieser Teil der Datei hat sie gestaltet: Vierspalter, eigene
   Reiterpille, eigene Kartendichte, eigene Preisgroesse.

   Seit Arpads Satz "wenn ich in der heropage herunterscrolle sollte der
   Preissession die selbe sein wie wenn man auf Pricing druecken. design
   und alles" ist dort derselbe Block wie auf pricing.html, und er wird
   von css/design/preise.css gestaltet -- dort traegt jede Regel einen
   Zwilling auf `body.startseite .preisgruppen`.

   Diese Regeln mussten deshalb WEG, nicht nur uebersteuert werden: Sie
   hingen an `#pricing`, und eine ID schlaegt jeden Klassenzwilling.
   GEMESSEN war genau das der Rest: nach dem Einhaengen von preise.css
   blieben 539 Stilunterschiede, praktisch alle aus diesem Block --
   Kartenbreite 242 statt 291 px, Preis 38 statt 44 px, Knopf 44 statt
   50 px hoch.

   Die alte Fassung liegt in der Versionsgeschichte, falls jemand
   nachsehen will, was hier stand. */

/* startseite.css — die seiteneigenen Regeln der Startseite (S1, 12.09.2026).
 *
 * EINGEGRENZT AUF body.startseite. Eine Klasse statt des data-page-Attributs,
 * das download.css benutzt: tests/test_website_design.py koppelt den Marker
 * `<body data-page>` an die Premium-Schicht (premium.css), und die Startseite
 * laedt diese Schicht seit W3 nicht mehr — ein Marker ohne Schicht waere dort
 * ein Versprechen an niemanden.
 *
 * VERLINKT HINTER <!-- chrome:mittel:ende -->, also nach bauteile.css, damit
 * der Chrome-Bau die Zeile stehen laesst. Die Regeln gewinnen ueber ihre
 * Spezifitaet (body.startseite …), nicht ueber die Reihenfolge.
 *
 * NICHTS HIER IST ERFUNDEN. Jede Zahl steht im Konzept (bauteile.css) oder in
 * boxen.css; wo eine Regel einen Wert von anderswo uebernimmt, steht die
 * Quelle daneben. Die Datei tut drei Dinge:
 *   1. Anordnen, wo das Konzept keine Antwort hat: sechs Karten statt vier
 *      (Spannweite 4/6/12), der Reiterverbund mit drei Bildstrecken, ein
 *      Formular mit Auswahlfeld, der Zahlungsschalter.
 *   2. Die Elementregeln des Konzepts, die K1 absichtlich nicht portiert hat
 *      (p, details, summary, label, input, textarea), eingegrenzt auf die
 *      Bauteile, die sie brauchen (.faq-list, .contact-form).
 *   3. Die Kollisionen mit thalassa.css aufloesen, die der Bericht K1
 *      angekuendigt hat (.hero, .faq, .price, .on-dark a:hover).
 */

/* ------------------------------------------------------------------ Grund */

/* Kein Wort und kein Satz wird mitten gebrochen (Arpad, 12.09.2026). Lange
   deutsche Woerter tragen &shy; im Markup, sonst gibt es keine Trennung.

   Die Ueberschriften stehen AUSDRUECKLICH mit drin, nicht nur ueber die
   Vererbung: thalassa.css traegt `:lang(de) h1, :lang(de) h2, :lang(de) h3
   { hyphens: auto }`, und eine Regel, die das Element direkt trifft, schlaegt
   jeden geerbten Wert — unabhaengig von der Spezifitaet. Gemessen am
   12.09.2026: auf /de/ rechneten h1, .section-title und .price-name `auto`,
   waehrend `main` `manual` sagte. :is() erbt die Spezifitaet seines staerksten
   Arguments (hier ein Element), die Regel steht damit bei (0,1,3) gegen
   (0,1,1) und gewinnt auch dort. */
body.startseite main,
body.startseite main :is(h1, h2, h3) { hyphens: manual; }

/* Die p-Regel des Konzepts (`p { color: var(--muted); line-height: 1.65; }`),
   die K1 als Elementregel nicht portiert hat. :where() haelt die Spezifitaet
   bei (0,0,1), damit jede Bauteilregel mit eigener Farbe gewinnt
   (.hero-copy > p, .contact-panel p, .product-section .section-lede …). */
:where(body.startseite main) p { color: var(--muted); line-height: 1.65; }

/* ------------------------------------------------------------------- Hero */

/* thalassa.css .hero traegt padding-block (W3); das Konzept legt den Abstand
   in .hero-grid (86px 0 96px). Beides zusammen waere ein Abschnitt zu viel. */
body.startseite .hero { padding-block: 0; }

/* thalassa.css `.on-dark a:hover` faerbt jeden Verweis auf dunklem Grund hell
   — auch die Aufschrift des Primaerknopfs (Tinte auf Knopfgruen, Konzept). */
body.startseite .on-dark a.btn--primary:hover { color: var(--button-primary-text); }

/* --------------------------------------------- Die sechs Boxen (Abschnitt 3) */

/* Sechs Karten statt vier: drei je Zeile auf 1240, zwei unter 1100, eine
   unter 900 (Auftrag S1). `1 / -1` statt `span 12`, weil bauteile.css das
   Raster unter 760 px auf EINE Spalte stellt — ein `span 12` liefe dort in
   implizite Spalten und ueber den Rand. */
body.startseite .moment-grid > .moment-card { grid-column: span 4; }
@media (max-width: 1100px) {
  body.startseite .moment-grid > .moment-card { grid-column: span 6; }
}
@media (max-width: 900px) {
  body.startseite .moment-grid > .moment-card { grid-column: 1 / -1; }
}

/* Abwechseln, nicht sechs weisse Boxen: Karte 2 und 3 toent das Konzept
   selbst (#eef8f3); Karte 4 traegt Tinte, Karte 6 Mist — die Grundfarben aus
   boxen.css, hier wiederholt, weil `.moment-card { background: white }` in
   bauteile.css spaeter laedt als boxen.css und sonst gewinnt. */
body.startseite .moment-card.box--ink {
  background: var(--ink); color: var(--white); border-color: var(--ink-3);
}
body.startseite .moment-card.box--mist { background: var(--mist); }
body.startseite .moment-card.box--ink .text-link { color: var(--white); }
/* Die Rubrik-Kapsel traegt im Konzept --mist auf WEISSEM Kartengrund. Auf den
   getoenten Karten faellt sie mit dem Grund zusammen und ist keine Kapsel mehr
   — Karte 2 und 3 toent das Konzept selbst (#eef8f3), Karte 6 traegt --mist
   (#edf2ed), gemessen 12.09.2026 Kapsel und Grund identisch. Dort steht sie
   auf Weiss, dem Kartengrund der uebrigen; kein neuer Wert.

   `:not(.box--ink)` IST DER KERN DIESER REGEL, nicht Beiwerk. Die Regel
   setzt nur die eine Haelfte eines Farbpaars — den Grund. Die Schriftfarbe
   kommt aus boxen.css: `.box--ink .moment-tag { color: var(--emerald-pale);
   background: var(--ink-3) }`, blasses Gruen auf dunkler Kapsel. Trifft die
   Regel hier die Tintenkarte, bleibt das blasse Gruen stehen und die Kapsel
   wird weiss: gemessen 1,13:1, im Bild eine leere weisse Pille.

   Genau das ist am 20.09.2026 passiert. Die Auswahl zaehlt Karten, und die
   Umsortierung aus Auftrag 4.6 hat die Tintenkarte von Platz 4 auf Platz 2
   geschoben — die Regel traf sie, ohne dass jemand sie angefasst hat. Wer
   das Raster wieder umstellt, prueft diese Zeile mit. Die Tintenkarte hat
   ihre eigene Regel in boxen.css und braucht von hier nichts. */
body.startseite .moment-card:nth-child(2):not(.box--ink) .moment-tag,
body.startseite .moment-card:nth-child(3):not(.box--ink) .moment-tag,
body.startseite .moment-card.box--mist .moment-tag { background: var(--white); }

/* Reihenfolge in der Box: Rubrik, Titel, Text, „Weiterlesen", Verweis. boxen.js
   haengt den Knopf ans Ende der Box; `order` stellt den Verweis dahinter, und
   der Verweis nimmt den Restraum (margin-top: auto aus boxen.css .box__mehr),
   der Knopf bleibt direkt unter dem Text. 18px = Rasterabstand des Konzepts. */
body.startseite .moment-card .text-link { order: 2; margin-top: auto; align-self: flex-start; }
body.startseite .moment-card .box__mehr { margin-top: 0; margin-bottom: 18px; }
/* Die Rubrik ist eine Kapsel (inline-flex im Konzept); als Kind der Flex-Box
   wuerde sie sonst auf Kartenbreite gedehnt. */
body.startseite .moment-card .moment-tag { align-self: flex-start; }

/* Die drei freigegebenen Fotos sitzen in der angeschnittenen Konzept-Sphaere.
   Bei den Querformaten lag der Kopf genau in den 44 px, die oberhalb der
   Karte verschwinden. `object-position` verschiebt nur den Bildausschnitt,
   nicht Kreis, Karte oder Text; die horizontale Lage ist je Motiv auf das
   Gesicht gesetzt. */
body.startseite #use-cases .box__bild[src$="use-case-executive-meeting.webp"] {
  object-position: 50% calc(50% + 40px);
}
body.startseite #use-cases .box__bild[src$="use-case-job-interview.webp"] {
  object-position: 65% calc(50% + 40px);
}
body.startseite #use-cases .box__bild[src$="use-case-study-session.webp"] {
  object-position: 62% calc(50% + 42px);
}

/* --------------------------------------- Produkt in Aktion (Abschnitt 5) */

/* Die drei Reiterfelder liegen in EINER .screen-shell; die weisse Notiz des
   Konzepts steht darunter fuer alle drei. Ohne Rahmen um die Bildstrecke
   (bauteile.css) braucht die Notiz ihren eigenen Abstand und die kleine
   Rundung des Konzepts (--radius-sm). 24px = .hero-trust margin-top. */
body.startseite .screen-shell .screen-note { margin-top: 24px; border-radius: var(--radius-sm); }

/* ------------------------------------------------ Vergleich (Abschnitt 6) */
/* Nichts eigenes: unter 760 px rollt die Karte waagerecht, wie im Konzept
   (.comparison-card { overflow-x: auto }, .comparison-row { min-width: 680px }). */

/* ------------------------------------------------- Preise (Abschnitt 7) */



/* Jahressumme und Steuerhinweis (thalassa.css: Tinte / gedaempft) auf der
   hervorgehobenen Karte in der Absatzfarbe des Konzepts
   (.price-card--featured > p: rgba(255,255,255,.62)). */



/* ----------------------------------------------------- FAQ (Abschnitt 8) */
/* Die details/summary-Regeln des Konzepts, eingegrenzt auf .faq-list
   (BAUTEILE.md, Geruest 8). thalassa.css traegt eigene .faq-Regeln
   (Winkel statt Plus, Flex-Zeile) — hier ueberschrieben. */
body.startseite .faq-list details { border-top: 0; border-bottom: 1px solid var(--line); padding: 0; }
body.startseite .faq-list summary {
  display: block; position: relative; padding: 24px 44px 24px 0;
  font-size: 17px; font-weight: 800; line-height: inherit; color: inherit;
  list-style: none; cursor: pointer;
}
body.startseite .faq-list summary::-webkit-details-marker { display: none; }
body.startseite .faq-list summary::after {
  position: absolute; right: 4px; top: 24px; width: auto; height: auto;
  margin: 0; border: 0; transform: none;
  color: var(--emerald-dark); font-size: 24px; line-height: 1; content: "+";
}
body.startseite .faq-list details[open] summary::after { content: "−"; transform: none; margin-top: 0; }
body.startseite .faq-list details p { padding: 0 44px 23px 0; margin: 0; max-width: none; font-size: 15px; color: var(--muted); }

/* ------------------------------------------------ Kontakt (Abschnitt 9) */
/* Die Formular-Elementregeln des Konzepts (label, input, textarea,
   ::placeholder), eingegrenzt auf .contact-form (BAUTEILE.md, Geruest 9).
   Das Auswahlfeld (Betreffliste) gibt es im Konzept nicht; es traegt die
   Werte von input. Die Liste selbst zeichnet der Browser — dort Tinte auf
   Weiss, sonst stuende Weiss auf Weiss. */
body.startseite .contact-form label { color: rgba(255,255,255,.78); font-size: 12px; font-weight: 800; letter-spacing: .04em; }
body.startseite .contact-form input,
body.startseite .contact-form select,
body.startseite .contact-form textarea {
  width: 100%; border: 1px solid rgba(255,255,255,.18); border-radius: 12px;
  color: var(--white); background: rgba(255,255,255,.06);
}
body.startseite .contact-form input,
body.startseite .contact-form select { height: 50px; padding: 0 15px; }
body.startseite .contact-form textarea { min-height: 112px; padding: 14px 15px; resize: vertical; }
body.startseite .contact-form input::placeholder,
body.startseite .contact-form textarea::placeholder { color: rgba(255,255,255,.34); }
body.startseite .contact-form option { color: var(--ink); background: var(--white); }

/* Die Vorzeile auf dem dunklen Kontaktgrund in der hellen Fassung, die das
   Konzept fuer seinen dunklen Abschnitt setzt (.product-section .eyebrow). */
body.startseite .footer-cta .eyebrow { color: #7ce9c7; }

/* Der Statusabsatz traegt die Meldungen von js/home-wire.js — „Nachricht wird
   gesendet", „Senden gerade nicht moeglich, schreiben Sie an …". Er sitzt in
   der Huelle `.form-foot small`, und die ist im Konzept ein RUHENDER Hinweis:
   rgba(255,255,255,.45), auf #0b2b24 gerechnet 3,5:1 — unter den 4,5:1, die
   Fliesstext braucht. Eine Fehlermeldung, die man nicht liest, ist keine.
   Er traegt deshalb die Beschriftungsfarbe des Konzepts (.contact-form label,
   rgba(255,255,255,.78) = 8,3:1); der ruhende Hinweis daneben bleibt, wie er ist. */
body.startseite .contact-form #contactNote { color: rgba(255, 255, 255, .78); }


/* VIER PREISKARTEN IN EINER REIHE (Arpad, 12.09.2026).

   Das Konzept zeigt drei (bauteile.css: `repeat(3, 1fr)`). Die Startseite
   zeigt seither auch Compliance, an dritter Stelle; hervorgehoben bleibt
   Premium. Die Regel steht HIER und nicht in bauteile.css, weil
   /pricing.html dieselbe Klasse traegt und beim Dreispalter des Konzepts
   bleibt.

   JEDE FASSUNG STEHT IN EINER MEDIA QUERY. Das ist der Punkt, an dem der
   erste Versuch am 12.09.2026 gescheitert ist: `body.startseite .price-grid`
   wiegt (0,2,1), die Handy-Regel in bauteile.css
   (`@media (max-width: 1080px) { .price-grid { grid-template-columns: 1fr } }`)
   nur (0,1,0). Eine Media Query erhoeht die Spezifitaet NICHT. Der
   Vierspalter stand ohne Abfrage da und gewann deshalb auch bei 390 px —
   gemessen: die Startseite lief 527 px (EN) bzw. 551 px (DE) ueber den
   rechten Rand, genau der Fehler, den Arpad fuer Mobil ausgeschlossen hat.
   Wer hier eine Zeile ergaenzt, gibt ihr eine Abfrage, sonst schlaegt sie
   nach unten durch.

   Die drei Stufen:
     >= 1240 px  vier Spalten. Container ist `min(100% - 40px, 1240px)`,
                 also 1200 px; (1200 - 3 x 18) / 4 = 286 px je Karte,
                 abzueglich 2 x 34 px Innenrand 218 px Textbreite.
     1081-1239   zwei Reihen zu zwei. Vier Spalten waeren hier zu eng, und
                 vier Karten teilen sich sauber — keine steht allein.
     <= 1080 px  eine Spalte, aus bauteile.css. Hier steht bewusst NICHTS,
                 damit die Konzeptregel greift. */
@media (min-width: 1240px) {
}

@media (min-width: 1081px) and (max-width: 1239px) {
}

/* ------------------------------------------------------- Hero-Schriftgrad */
/* Punkt 5 (Arpad, 15.09.2026): „ein Tick zu gross, und die Bilder sind in
   manchen Konstellationen aufeinander gerutscht."

   GEMESSEN auf der Startseite bei 1440 px Fensterbreite: Die h1 steht auf
   90 px (bauteile.css: clamp(52px, 6.8vw, 90px)) in einer 496 px breiten
   Spalte — der Satz „Your next answer is already in your documents."
   bricht dort auf FUENF Zeilen und wird 432 px hoch. Zusammen mit
   Vorzeile, Fliesstext, zwei Knoepfen und der Merkmalzeile passt die
   Spalte nicht mehr neben die Buehne, und in der Mitte zwischen 1081 und
   1239 px stossen beide Spalten aneinander.

   EINE STUFE KLEINER, nicht zwei: 90 -> 76 px ist der Schritt der
   Typoskala (Faktor 1,18; premium.css rechnet mit demselben Verhaeltnis
   zwischen --t-h1 und --t-display). Bei 1440 px sind es damit 76 px und
   vier Zeilen statt fuenf; unter 1100 px greift weiter der untere Wert
   der Klammer, dort war nie etwas zu eng.

   Die Spalten dazu um acht Hundertstel umverteilt: Die Textspalte
   gewinnt 35 px, die Buehne verliert sie. bauteile.css bleibt
   unangetastet — tests/test_bauteile.py liest es woertlich gegen das
   Konzept; die Startseite darf abweichen, aber nur hier. */
/* LAUFWEITE: -.04em STATT -.058em (20.09.2026, A.2). Arpad sah in
   "high" das `i` am `g` kleben. Das Konzept setzt -.058em; bei 76 px sind
   das -4,4 px zwischen zwei Buchstaben, und Inter traegt das an engen
   Paaren nicht.

   -.04em IST GEMESSEN, NICHT GESCHAETZT. Im Fenster durchprobiert
   (1440/1000/390, EN und DE), jeweils die Hoehe der H1 abgelesen:

     -.058em (Konzept)  1440: 219px   1000: 167px   390: 132px
     -.04em             1440: 219px   1000: 167px   390: 132px
     -.03em             1440: 219px   1000: 167px   390: 177px  <- Zeile mehr
     -.03em (DE)        1440: 292px                             <- Zeile mehr

   -.04em ist der letzte Wert, der auf KEINER Breite und in KEINER Sprache
   eine Zeile kostet, und bringt trotzdem 1,4 px Luft bei 76 px. -.03em
   waere luftiger und wuerde die Ueberschrift auf dem Telefon und auf der
   deutschen Startseite um eine Zeile laenger machen. */
body.startseite .hero h1 {
  /* NOCH EINE STUFE KLEINER (20.09.2026, zweiter Durchgang). -.04em hat
     das `ig` in "high" auf Arpads Mac nicht auseinandergebracht -- im
     Cloud-Fenster stiess sich zeichenweise gemessen ohnehin nichts, die
     Schriftdarstellung auf macOS ist eine andere. Arpad: "mach die
     Schrift ein tick kleiner, vielleicht hilft das." Enge Paare skalieren
     mit der Groesse: Bei 70 px sind -.04em nur noch -2,8 px statt -3,0. */
  font-size: clamp(44px, 5.4vw, 70px);
  letter-spacing: -.04em;
  /* ZEILENABSTAND 1.2 STATT --lh-tight (.96). ARPAD HAT DEN FEHLER
     RICHTIG GESTELLT, ich hatte ihn zweimal falsch: Das `i` und das `g`
     stossen nicht NEBENeinander, sondern UEBEReinander -- die Unterlaenge
     des `g` in "high" (Zeile 2) trifft den Punkt des `i` in "meetings"
     (Zeile 3). Laufweite und Schriftgroesse konnten das nie beheben.

     AUS DER SCHRIFT GEMESSEN, im Fenster ueber die Zeichenmasse von
     Inter bei 70 px:

       Oberlaenge "hi"   54 px   (Buchstabe plus i-Punkt)
       Unterlaenge "g"   16 px
       zusammen          70 px   = genau eine Zeilenhoehe

     Der Beruehrungspunkt liegt also bei line-height 1.0. Das Konzept
     setzt .96 -- die Tinte zweier Zeilen ueberlappte sich um 2,8 px, und
     zwar immer, nicht nur in dieser Ueberschrift. 1.2 laesst 14 px Luft.

     DAZU DAS ZWEITE, das Arpad wollte: Die linke Spalte soll unten dort
     enden, wo die rechte endet. Gemessen bei 1440 px, EN:

       .96   links 522   rechts 575   Differenz +53
       1.1   links 552   rechts 575   Differenz +23
       1.2   links 573   rechts 575   Differenz  +2
       1.3   links 594   rechts 575   Differenz -19

     1.2 trifft beides. Auf Deutsch bleiben 40 px Unterschied -- die
     rechte Spalte traegt dort schlicht mehr Text; das ist eine Frage der
     Uebersetzung, nicht des Zeilenabstands. */
  line-height: 1.2;
}
body.startseite .hero-copy > p { font-size: 18px; }

@media (min-width: 1081px) {
  body.startseite .hero-grid { grid-template-columns: .92fr 1.08fr; }
}

/* ------------------------------------------------- Hero-Buehne und Loop */
/* Punkte 1 und 2 (Arpad, 15.09.2026): „Alle App-Animationen sehen
   abgeschnitten aus" und „hinter der Animation ist ein anderer gruener
   Hintergrund zu sehen, das muss weg."

   BEIDES STAND IM VIDEO, NICHT IM CSS. Gemessen am Standbild
   web/assets/produkt/hero/hero-en.avif (Stand 11.09.2026):

     Leinwand           1920 x 1080, deckend rgb(5,78,58)
                        (--surface-inverse, gebacken; Video kennt kein Alpha)
     Fenster darin      x 340..1579, y 40..1079  ->  1240 x 1040 sichtbar
     tatsaechlich hoch  1280 (620 x 640 logisch, Skalierung 2)

   Das Fenster war also 240 Bildpunkte hoeher als die Leinwand: Der gruene
   Antwortknopf wurde MITTEN DURCH geschnitten. Und rechts und links des
   Fensters standen je 340 Punkte deckendes Gruen, das nicht zum Verlauf
   des Abschnitts passt (.hero: #071b17 -> #0b2620 -> #0c342a) — das war
   der „andere gruene Hintergrund".

   ERSTER VERSUCH, VERWORFEN: auf 1240 x 950 beschneiden. Der gruene Kasten
   war damit weg, der Schnitt aber nur verschoben. Arpad, sofort und zu
   Recht: „das ganze Overlay muss hier sichtbar sein, kein Kompromiss."

   JETZT NEU GERENDERT auf 1240 x 1280 — die Leinwand IST das Fenster, ganz
   (tools/szenen_render.py, HERO_LEINWAND). Kein Grund mehr im Bild ausser
   in den vier runden Zwickeln der Fensterecken, und nichts abgeschnitten.

   HIER BLEIBT ZWEIERLEI ZU TUN:
     1. Das Seitenverhaeltnis der Buehne von 16:9 auf 1240:1280 stellen.
        NICHT in bauteile.css — tests/test_bauteile.py liest dort
        `.hero-shot { aspect-ratio: 16/9 }` woertlich gegen das Konzept.
     2. Den Grund des Videos loeschen (szene.css setzt --surface-inverse
        fuer die alte, gebackene Flaeche) und die Ecken runden: Die
        Fensterecken sind im Bild rund (Radius 28 von 1240 = 2,26 % der
        Breite, 2,19 % der Hoehe), und in den Zwickeln dahinter steht das
        Gruen der Leinwand. Etwas mehr Radius als gemessen, damit kein Haar
        stehen bleibt.

   KEINE Ausblendung der Unterkante mehr — es gibt keine Kante mehr.

   Der gruene Lichtkreis (.stage-glow, 560 px, rgba(16,185,129,.16), 45 px
   Weichzeichnung) geht mit: Er war die zweite gruene Flaeche hinter dem
   Fenster und hatte mit dem Verlauf des Abschnitts nichts zu tun. */
body.startseite .stage-glow { display: none; }

/* 1240:1280 = 31:32. Das Fenster ist hochkant — die Buehne wird dadurch
   hoeher als breit; .product-stage (min-height 570px, bauteile.css) waechst
   mit, weil sie ein Flexcontainer ohne feste Hoehe ist. */
body.startseite .hero-shot { aspect-ratio: 31 / 32; }

body.startseite .hero-shot video.szene-hero,
body.startseite .hero-shot img {
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  object-fit: contain;
  background: transparent;
  border-radius: 2.6% / 2.5%;
}

/* Punkt 1c (Arpad, 15.09.2026, an der zweiten Vorschau): „die Overlay obere
   und untere Linien laufen nicht parallel."

   URSACHE: bauteile.css kippt die Buehne —
   `.app-frame { transform: perspective(1400px) rotateY(-5deg) rotateX(1deg) }`.
   Eine Drehung MIT Perspektive ist keine Drehung, sondern eine
   Zentralprojektion: Die vom Betrachter weiter entfernte Kante wird kuerzer,
   aus dem Rechteck wird ein Trapez, und Ober- und Unterkante laufen
   aufeinander zu. Das ist dem Kipp eigen und laesst sich nicht
   „geradestellen" — nur weglassen.

   Am alten Ausschnitt (16:9, 680 x 383) betrug der Hoehenunterschied der
   beiden senkrechten Kanten wenige Punkte und ging im Bild unter. Das ganze
   Fenster ist 680 x 702 — fast doppelt so hoch, und derselbe Winkel zeigt
   sich doppelt so deutlich.

   Die Buehne steht deshalb auf der Startseite gerade. bauteile.css bleibt
   unangetastet: tests/test_bauteile.py liest die Regel dort woertlich gegen
   das Konzept (AUSNAHMEN, „.app-frame"), und auf den Landingpages mit ihrem
   breiten Ausschnitt bleibt der Kipp richtig. */
body.startseite .app-frame { transform: none; }

/* ============================================================
   DREI-WEGE-SCHALTER AUF DER STARTSEITE
   Students | Normal | Meeting credits only (Auftrag 4.4, 19.09.2026)
   ============================================================

   Dieselbe Pille wie auf der Preisseite, aber hier eigenstaendig
   aufgeschrieben: index.html laedt preise.css NICHT, und dort haengt jede
   Regel an `body[data-page="pricing"]`. Die Alternative -- preise.css auf
   die Startseite holen -- brachte 700 Zeilen Preisseiten-Formen mit, von
   denen die Startseite keine braucht.

   Die Form ist woertlich die des Zeitraum-Schalters daneben
   (bauteile.css, `.region-switch`): weisse Pille, Rand in --line, der
   gewaehlte Eintrag weiss auf --ink. Zwei Schalter in einer Zeile, die
   sich verschieden ausdruecken, laesst sie wie zwei verschiedene Dinge
   aussehen -- und sie tun dasselbe.

   OHNE JAVASCRIPT GREIFT NICHTS DAVON. Der Abschnitt traegt `data-ansicht`
   erst, wenn js/ansicht.js gelaufen ist; bis dahin stehen alle drei Felder
   offen und der Zeitraum-Schalter ist sichtbar. Genau so ist es gemeint. */






@media (max-width: 760px) {
}




/* DER LAENGSTE REITER PASST NICHT AUF EIN TELEFON (19.09.2026, gemessen).
   „Nur Meeting-Guthaben" ist 151 px breit; mit den beiden anderen wird die
   Pille 311 px und traegt die deutsche Seite bei 320 px ueber den Rand --
   Startseite und Preisseite gleichermassen. Die englische Fassung
   („Meeting credits only", 129 px) passt knapp.

   Gekuerzt statt umgebrochen: Ein zweizeiliger Reiter in einer klebenden
   Leiste kostet Hoehe, und Hoehe ist auf dem Telefon das Knappste. Der
   Wortlaut bleibt im Markup vollstaendig -- nur das mittlere Wort faellt
   unter 420 px weg: „Nur Guthaben" / „Meeting credits". */
@media (max-width: 420px) {
}

/* ============================================================
   HERO, ZWEISPALTIG — und die gestaffelte Komposition darunter
   (Auftrag 4.6 / D.2 und 4.7, 19.09.2026)
   ============================================================

   Der Hero vom 12.09. hatte links den Text und rechts die Buehne. Die
   Buehne steht jetzt DARUNTER (.hero-film) und ragt per negativem Abstand
   in diesen Abschnitt hinein; rechts vom Text stehen zwei Zeilen.

   Die Spalten sind 11fr / 9fr, nicht 1fr / 1fr: Die H1 ist die laengste
   Zeile der Seite und bekommt den groesseren Teil. */
body.startseite .hero__raster {
  /* UEBER DER DEKORATION, NICHT DARUNTER (Befund 21.09.2026, Arpad: „das
     Video kann nicht angeklickt werden ... es ist wohl nicht richtig
     verdrahtet").

     Es war richtig verdrahtet. Der Knopf „Watch the 2-minute video" zeigt
     auf #product, und den Abschnitt gibt es. Nur kam der Klick nie an:
     `.hero::before` (bauteile.css) legt ein Rastermuster ueber die ganze
     Sektion — absolut, inset 0, 1425 x 760 px. Ein positioniertes
     Pseudoelement wird NACH dem stehenden Inhalt gemalt, also darueber,
     und nahm jeden Klick im Hero an.

     GEMESSEN am Live-Stand: `elementFromPoint` in der Mitte des Knopfes
     lieferte SECTION.hero statt A.btn. Mit diesen zwei Zeilen liefert es
     A.btn.

     DIE SCHUTZREGEL GAB ES SCHON, sie griff nur nicht mehr: bauteile.css
     setzt `.hero-grid { position: relative; z-index: 1 }` aus genau
     diesem Grund. Die Kampagnenseiten benutzen `.hero-grid` weiter und
     waren nie betroffen; die Startseite heisst seit dem Redesign
     `.hero__raster`, und die zwei Zeilen sind beim Umbenennen nicht
     mitgewandert. Nebenwirkung, die niemand gemeldet hat: Das
     Rastermuster lag auch ueber der Schrift statt hinter ihr. */
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 11fr) minmax(0, 9fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}
body.startseite .hero-copy { text-align: left; }
body.startseite .hero-copy h1 { max-width: 18ch; margin-inline: 0; }
body.startseite .hero-eyebrow {
  margin: 0 0 18px;
  color: var(--akzent-auf-dunkel);
  font-size: 12px;
  font-weight: 850;
  letter-spacing: .14em;
  text-transform: uppercase;
}
body.startseite .hero-sub { max-width: 62ch; margin: 18px 0 0; }

/* Die Haken: Liste im Markup (drei Zusagen, nicht Dekor), Haken per
   ::before statt per SVG — vier gleiche Inline-SVG waren vier Kopien
   desselben Pfades. */
body.startseite .hero-checks {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  font-size: 15px;
}
body.startseite .hero-checks li { position: relative; padding-left: 26px; }
body.startseite .hero-checks li::before {
  position: absolute;
  left: 0;
  color: var(--akzent-auf-dunkel);
  font-weight: 900;
  content: "✓";
}
body.startseite .hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 32px 0 0;
}

/* Die zwei Zeilen rechts. Sie stehen optisch tiefer als die H1 — ein
   gleicher Oberkantenanschluss laesst sie wie eine zweite Ueberschrift
   aussehen, und sie sind eine Fussnote zum Gespraech, keine. */
/* DIE RECHTE SPALTE ENDET WIEDER MIT DER LINKEN (20.09.2026).
   Arpad am selben Tag: "das block endet genau dort wo die rechte seite
   endet unten." Mit sechs Punkten stimmte das (573 gegen 575 bei 1440
   EN). Die Verkuerzung auf vier hat die rechte Spalte um 155 px
   verkuerzt -- GEMESSEN: linke Spalte 115..688, Punkte 115..533.

   Die Luecke wird nicht mit einem festen Abstand zugeschoben, sondern
   verteilt: `.hero-neben` nimmt die volle Zeilenhoehe (`align-self:
   stretch` gegen das `align-items: start` des Rasters), und die vier
   Punkte verteilen sich mit `align-content: space-between` darueber.
   Damit endet der letzte Punkt auf derselben Linie wie der Knopf --
   bei jeder Fensterbreite und in beiden Sprachen, ohne dass irgendwo
   eine gemessene Pixelzahl fest eingetragen ist, die beim naechsten
   Textwechsel wieder falsch waere.

   Unter 960 px steht alles untereinander; dort gibt es keine zweite
   Spalte, an der etwas ausgerichtet werden koennte, und `stretch`
   bleibt wirkungslos. */
body.startseite .hero-neben {
  display: grid;
  gap: 32px;
  padding-top: clamp(24px, 4vw, 72px);
  align-self: stretch;
  align-content: stretch;
}
/* DIE SCHRIFTFARBE FEHLTE, und der Hero ist dunkel. Gemessen am
   19.09.2026: Die Zeile erbte `--muted` (#586861) und stand damit bei
   1,9:1 auf dem Hero-Verlauf -- unlesbar, und zwar schon vor der neuen
   Farbwelt (auf dem alten, fast schwarzen Grund waren es 2,6:1). Der
   Kontrasttest prueft Tokenpaare, keine geerbten Farben; im Fenster
   faellt es sofort auf, im Quelltext nie.

   rgba(255,255,255,.82) statt --white: Die Zeile ist Nebentext neben der
   H1, sie soll weniger laut sein -- aber lesbar. Gemessen 9,0:1. */
/* SECHS PUNKTE STATT ZWEI ZEILEN (20.09.2026, A.1). `.hero-zeile` ist
   damit ohne Verwendung und faellt hier weg statt als Leiche stehen zu
   bleiben -- der Farbbefund von gestern (geerbtes --muted bei 1,9:1 auf
   dem Hero) zieht in die neue Regel mit, er war die Lehre, nicht die
   Zeile.

   `gap: 18px` und `font-size: 14px`: Sechs Punkte statt zweier muessen in
   dieselbe Spaltenhoehe wie die H1 samt Unterzeile, Haken und Knoepfen
   links. Gemessen im Fenster, nicht geschaetzt. */
body.startseite .hero-punkte {
  display: grid;
  gap: 18px;
  margin: 0;
  padding: 0;
  max-width: 52ch;
  list-style: none;
  align-content: space-between;
}
/* DIE FARBIGE KANTE (20.09.2026). Aus derselben Rueckmeldung wie die
   Verkuerzung auf vier Punkte: "beleraknek valami kis grafikai elemet,
   mondjuk egy alteralo szinekkel epitkezo blokkba" -- ein kleines
   grafisches Element, das mit wechselnden Farben baut.

   Es ist eine Kante, keine Flaeche. Eine getoente Flaeche haette
   Innenabstand gebraucht und die Spalte hoeher gemacht; die Rueckmeldung
   lautete aber "kevesebb sokszor tobb". Drei Pixel links kosten keine
   Hoehe und trennen die vier trotzdem sichtbar.

   BEIDE TOENE STEHEN SCHON IN DER PALETTE, keiner ist neu:
   --akzent-auf-dunkel (#7ce9c7) traegt bereits die Titel, --knopf-gruen
   (#3ee0ad) den Hauptknopf. Es sind Rand- und Flaechenfarben, keine
   Schrift -- die Kontrastschwellen fuer Text gelten hier nicht, und die
   Schriftfarbe der Punkte bleibt unveraendert. */
body.startseite .hero-punkte li {
  margin: 0;
  padding-left: 14px;
  border-left: 3px solid var(--akzent-auf-dunkel);
  color: rgba(255, 255, 255, .82);
  font-size: 14px;
  line-height: 1.55;
}
body.startseite .hero-punkte li:nth-child(even) {
  border-left-color: var(--knopf-gruen);
}
/* Der Titel steht als eigene Zeile darueber, nicht als fettes Wort im
   Satz: Titel im Fliesstext waeren Stolperstellen. KEINE Versalien --
   bei zwei kurzen Etiketten ("Before", "During") war das eine Marke,
   bei ganzen Titeln waere es geschrien. (Seit 20.09.2026 sind es vier
   Titel, nicht sechs.) */
/* 16px STATT 14px (20.09.2026, zweiter Durchgang). Arpad: "mach die
   Ueberschriften ein tick groesser, damit sie sofort ins auge kommen."
   Der Titel steht damit ueber dem Satz, nicht daneben -- zwei Punkte
   Unterschied reichen, weil die Farbe schon traegt. */
body.startseite .hero-punkte b {
  display: block;
  margin-bottom: 3px;
  color: var(--akzent-auf-dunkel);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .01em;
}

@media (max-width: 960px) {
  body.startseite .hero__raster { grid-template-columns: 1fr; }
  body.startseite .hero-neben { padding-top: 0; }
}

/* ---------------------------------------------- die Komposition (4.7) */
/* GEMESSEN, NICHT UEBERNOMMEN (19.09.2026). Der Auftrag 4.7 nennt
   clamp(-84px, -6vw, -48px) als RICHTWERT und daneben die eigentliche
   Vorgabe: Beim Laden bei 1440 x 900 sollen 120-200 px der Rahmenoberkante
   ohne Scrollen im Bild stehen, als Scrollhinweis. Mit dem Richtwert sind
   es 109 px -- knapp darunter. Gemessen ueber vier Werte:

     -84 px  -> Rahmen oben 791, sichtbar 109 px, Abstand zum CTA 137 px
    -110 px  -> Rahmen oben 765, sichtbar 135 px, Abstand zum CTA 111 px
    -130 px  -> Rahmen oben 745, sichtbar 155 px, Abstand zum CTA  91 px
    -150 px  -> Rahmen oben 725, sichtbar 175 px, Abstand zum CTA  71 px

   -130 px trifft die Mitte der Vorgabe und laesst dem Kaufknopf noch
   91 px Luft (deutsch 120 px). -150 px waere auch im Band, rueckt die
   Komposition aber spuerbar an den Knopf. */
body.startseite .hero-film {
  margin-top: clamp(-130px, -9vw, -48px);   /* ragt in den Hero hinein */
}
body.startseite .hero-film__komposition {
  --hero-scroll: 0;                        /* 0…1, vom Skript */
  --hero-video-lift: 0px;                  /* Hub, vom Skript */
  --hero-video-reserve: min(18vw, 225px);
  position: relative;
  padding-bottom: max(0px, calc(var(--hero-video-reserve) - var(--hero-video-lift)));
  isolation: isolate;
}
body.startseite .hero-film__hintergrund-rahmen {
  position: relative;
  z-index: 0;
  width: 100%;
  aspect-ratio: 1920 / 1008;     /* Bild ist 1032 hoch — oben werden 24 px gekappt */
  overflow: hidden;
  border: 1px solid var(--border-subtle);
  border-radius: 24px;
  box-shadow: var(--shadow-lg);
}
body.startseite .hero-film__hintergrund {
  position: absolute;
  top: -2.4%;
  left: 0;
  width: 100%;
  height: 102.4%;
  max-width: none;
  object-fit: cover;
  opacity: calc(1 - var(--hero-scroll) * .02);
  filter: blur(calc(var(--hero-scroll) * 3px));
  transform: scale(calc(1 + var(--hero-scroll) * .006));
  transform-origin: center;
  will-change: filter, transform;
}
body.startseite .hero-film .hero__buehne {
  position: absolute;
  top: min(21vw, 260px);         /* Ausgangshoehe = Hubweite */
  left: 50%;
  z-index: 1;
  width: min(48%, 620px);
  overflow: hidden;
  border-radius: 20px;
  box-shadow: 0 24px 64px rgba(5, 25, 22, .24);
  transform: translate(-50%, calc(-1 * var(--hero-video-lift)));
  will-change: transform;
}
/* `position: static` IST DIE EIGENTLICHE ZEILE HIER (20.09.2026, A.3).
   bauteile.css setzt `.stage-caption` auf `position: absolute; left: 22px;
   bottom: -42px` -- eine Bildunterschrift, die im Konzept am Rahmen
   klebt. Diese Regel stellte bisher nur `display`, `margin-top` und
   `text-align` um und liess die absolute Lage stehen: Die Zeile hing halb
   ueber der Komposition und halb daneben, gesehen von Arpad am
   20.09.2026. Wer `position` vergisst, ordnet einen Kasten um, der gar
   nicht im Fluss steht. Dieselbe Falle wie bei der weissen Kapsel auf der
   Tintenkarte -- eine Regel setzt die eine Haelfte eines Paars. */
body.startseite .hero-film .stage-caption {
  position: static;
  display: block;
  margin-top: 18px;
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  body.startseite .hero-film__hintergrund,
  body.startseite .hero-film .hero__buehne { will-change: auto; }
}

@media (max-width: 760px) {
  body.startseite .hero-film { margin-top: 32px; padding-bottom: 12px; }
  body.startseite .hero-film__komposition { --hero-video-reserve: min(34vw, 140px); }
  body.startseite .hero-film .hero__buehne { width: min(62%, 420px); }
}

/* ============================================================
   LAUFBAND DER GESPRAECHSPROGRAMME (Auftrag 4.8)
   ============================================================

   Trennbalken zwischen Hero-Komposition und Wechselzeilen: feine Linie
   oben und unten, dazwischen die Namen im Umlauf.

   DER UMLAUF IST NAHTLOS, WEIL DIE SPUR ZWEIMAL DASTEHT und die Animation
   um genau eine Gruppenbreite schiebt (-50 % der Spur). Im Moment, in dem
   die erste Gruppe links herausgelaufen ist, steht die zweite exakt an
   ihrer Ausgangsposition — der Sprung zurueck ist unsichtbar.

   PAUSIERT ALS GRUNDZUSTAND. `.ist-sichtbar` kommt von js/szene.js beim
   ersten Eintritt ins Bild; ohne JavaScript steht das Band still und ist
   vollstaendig lesbar. Das ist kein Mangel: Ein stehendes Band nennt
   dieselben Namen. */
body.startseite .laufband {
  padding: 28px 0;
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}
/* MITTIG (21.09.2026). Arpad: "center it in the middle." Die Zeile
   stand linksbuendig im .container, das Band darunter laeuft ueber die
   volle Breite und blendet an beiden Raendern aus -- die Ueberschrift
   hing dadurch an der linken Ecke von etwas, das sichtbar keine Ecken
   hat. Ueber der Mitte gehoert sie zum Band, nicht neben es.

   `text-align` genuegt: Der .container mittet sich schon selbst, die
   Zeile ist ein Block darin und braucht nur die Ausrichtung. */
body.startseite .laufband__titel {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  text-align: center;
}
body.startseite .laufband__fenster {
  position: relative;
  overflow: hidden;
  /* Die Raender weichen aus, statt hart abzuschneiden — sonst sieht es
     aus, als traete jeder Name aus einer Kante. */
  -webkit-mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
/* 98s STATT 48s (20.09.2026, A.5). Die Bildfolge schiebt um -50 Prozent
   der SPUR, nicht um eine feste Pixelzahl -- das Tempo haengt also an der
   Breite der Gruppe. Aus fuenf Namen wurden sechsundzwanzig, und mit den
   alten 48 s waere das Band gut doppelt so schnell gelaufen.

   GEMESSEN, nicht gerechnet (Gruppenbreite im Fenster, altes Tempo aus
   48 s zurueckgerechnet, daraus die noetige neue Dauer):

     EN 1440   alt 1987 px   neu 4366 px   41,4 px/s   -> 105 s
     EN  390   alt 1462 px   neu 3167 px   30,5 px/s   -> 104 s
     DE 1440   alt 2153 px   neu 4449 px   44,9 px/s   ->  99 s
     DE  390   alt 1596 px   neu 3234 px   33,2 px/s   ->  97 s

   101 s ist die Mitte der vier (nachgemessen, nachdem Proton Meet als
   siebenundzwanzigster Name dazukam -- die Zahl haengt an der Liste). Genauer geht es mit einer festen Dauer
   nicht: Die Gruppe ist auf Deutsch breiter als auf Englisch und auf dem
   Telefon schmaler als am Schreibtisch. Wer die Liste aendert, misst
   nach -- sonst laeuft das Band schneller oder langsamer, ohne dass es
   jemand beschlossen hat. */
body.startseite .laufband__spur {
  display: flex;
  width: max-content;
  animation: laufband 101s linear infinite;
  animation-play-state: paused;
}
body.startseite .laufband.ist-sichtbar .laufband__spur { animation-play-state: running; }
body.startseite .laufband__fenster:hover .laufband__spur,
body.startseite .laufband__fenster:focus-within .laufband__spur { animation-play-state: paused; }
body.startseite .laufband__gruppe {
  display: flex;
  align-items: center;
  gap: clamp(36px, 4vw, 64px);
  padding-right: clamp(36px, 4vw, 64px);
}
body.startseite .laufband__marke {
  white-space: nowrap;
  color: var(--ink);
  font-size: clamp(17px, 1.6vw, 22px);
  font-weight: 800;
  letter-spacing: -.01em;
  opacity: .72;
}

@keyframes laufband {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  body.startseite .laufband__spur { animation: none; }
}

/* ============================================================
   WECHSELZEILEN (Auftrag D.3) und ZAHLENBAND (D.4)
   ============================================================

   DER WECHSEL PASSIERT UEBER `order`, nicht ueber die Reihenfolge im
   Markup: Dort steht immer erst das Bild, dann der Text. Wer vorlesen
   laesst oder ohne Stilblatt liest, bekommt sechsmal dieselbe, logische
   Reihenfolge — das Zickzack ist Darstellung, nicht Inhalt. Auf dem
   Telefon faellt es weg, und die Umkehr muss mit: sonst stuende in der
   Haelfte der Zeilen das Bild unter seinem Text. */
/* DIE BILDSPALTE IST DIE BREITERE (20.09.2026).
   Arpad: "auch bei den liegenden screenshots brauchen wir keinen
   hintergrund und die duerfen groesser sein. mach es so gross wie der
   jetzige Hintergrund. je groesser desto besser, achte jedoch dabei
   darauf, dass der block von oben nach unten einheitlich ist."

   Der Rand ist an der Quelle gefallen (tools/schirmbilder_web.py). Was
   hier dazukommt, ist die Breite: 1,6 zu 1 statt 1 zu 1. GEMESSEN bei
   1440 px -- Behaelter 1240, Abstand 72, also 1168 fuer beide Spalten:

     1 zu 1     Bild 580, Text 580   ->  Fensterhoehe 366 px
     1,6 zu 1   Bild 719, Text 449   ->  Fensterhoehe 454 px

   Gegen heute (311 px sichtbares Fenster) sind das 46 Prozent mehr. Der
   Text behaelt 449 px; seine Absaetze stehen auf `max-width: 56ch` und
   brechen dort ohnehin.

   DIE SPALTEN TAUSCHEN MIT (ungerade Zeilen): Das Zickzack entsteht ueber
   `order`, nicht ueber das Markup -- ohne den Tausch der Spaltenbreiten
   landete das Bild in jeder zweiten Zeile in der SCHMALEN Spalte, und
   der Block waere genau das nicht mehr, was er sein soll. */
body.startseite .wechsel {
  /* Ohne sichtbare Abschnittsueberschrift wirkten die 112 px des
     Grundbauteils oberhalb der ersten Zickzack-Zeile wie eine leere
     Zusatzsektion. Nur diesen oberen Abstand halbieren; die nachfolgende
     Use-Case-Sektion und ihre Ueberschrift bleiben unangetastet. */
  padding-top: clamp(40px, 4vw, 56px);
}
body.startseite .wechsel-zeile {
  display: grid;
  grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr);
  gap: clamp(36px, 5vw, 80px);
  align-items: center;
  /* ABSTAND ZWISCHEN ZWEI ZEILEN, halbiert am 20.09.2026. Arpad: "die
     Abstaende zwischen den Zigzag elemente sind auch zu gross, mach es
     kleiner, etwa die haelfte wie jetzt."

       vorher  clamp(56px, 7vw, 104px)   bei 1440 px: 101 px
       jetzt   clamp(28px, 3.5vw, 52px)  bei 1440 px:  50 px

     Alle drei Werte halbiert, nicht nur der obere: Sonst waere der
     Abstand auf schmalen Schirmen gleich geblieben und der Rhythmus
     haette sich mit der Fensterbreite geaendert. Der Spaltenabstand
     INNERHALB einer Zeile (`gap`) bleibt, wie er ist -- gemeint war der
     Abstand zwischen den Zeilen. */
  margin-top: clamp(28px, 3.5vw, 52px);
}
body.startseite .wechsel-zeile:nth-child(odd) {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr);
}
body.startseite .wechsel-zeile:first-child { margin-top: 0; }
/* UNGERADE ZEILEN: TEXT LINKS. D.3 gibt die Folge vor — 1 Text links,
   2 Bild links, 3 Text links … Im Markup steht das Bild immer zuerst,
   also muss es in den UNGERADEN Zeilen nach rechts wandern. */
body.startseite .wechsel-zeile:nth-child(odd) .wechsel-zeile__bild { order: 2; }

/* KEIN RAHMEN MEHR UM DAS BILD.
   Rahmen, Radius und Schatten sassen an der <figure>, weil das Bild eine
   graue Leinwand mitbrachte: ein Fenster in einer Flaeche, die Flaeche in
   einem Kasten. Die Leinwand ist weg, und damit auch der Grund fuer den
   Kasten -- das Fenster bringt seine eigene Form mit, samt runder Ecken
   (im Bild durchsichtig gemacht, nicht per `border-radius` beschnitten:
   ein fester Radius waechst beim Skalieren nicht mit, die Durchsichtigkeit
   schon).

   `drop-shadow` statt `box-shadow`: Der Kastenschatten legte sich um das
   Rechteck der <figure>. Dieser folgt der Deckung des Bildes und damit
   den runden Ecken. `overflow: hidden` muss weg, es haette ihn
   abgeschnitten.

   ZWEI KASTENFORMATE, EINE SPALTE (zweiter Durchgang, 20.09.2026).
   Arpad: "im zigzag haben wir immer noch zu kleine Screenshots (liegende
   auch groesser, stehende viel groesser)."

   Der erste Durchgang hatte alle sechs auf DIESELBE Hoehe gebracht. Das
   war meine Lesart von "einheitlich von oben nach unten", und sie kostete
   die hochformatigen Assistenzfenster genau das, was sie sind: hoch. In
   einem querformatigen Kasten blieben von 719 px Spaltenbreite 286 px
   Fenster uebrig, der Rest war Luft.

   Einheitlich heisst jetzt: dieselbe Spalte, derselbe Rhythmus, zwei
   Kastenformate -- eines je Aufnahmeart. Die Bildspalte waechst von 1,6
   auf 1,9 Teile, und die hochformatigen Zeilen bekommen einen hoeheren
   Kasten.

   GERECHNET bei 1440 px (Behaelter 1240, Abstand 72, Spalte 765), Stand
   des vierten Durchgangs:
     quer  1710/1080  ->  Kasten 765 x 483, Fenster 765 x 483 (vorher 719 x 454)
     hoch  1710/1555  ->  Kasten 765 x 696, Fenster 439 x 696 (vorher 286 x 454)
   Das Assistenzfenster wird damit gut 50 Prozent breiter und gut 50
   Prozent hoeher als im ersten Durchgang; die App-Aufnahmen wachsen
   um 6 Prozent. Der Text behaelt 403 px -- seine Absaetze stehen auf
   `max-width: 56ch` und brechen dort ohnehin.

   `:has()` waehlt die Zeile nach dem Bild, das sie traegt. Kein zweiter
   Klassenname im Markup, der beim naechsten Bildwechsel falsch waere. */
body.startseite .wechsel-zeile__bild {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  aspect-ratio: 1710 / 1080;
  /* `min-height: 0` IST DIE ZEILE, OHNE DIE ES NICHT GEHT (gemessen).
     Die <figure> ist ein Rasterkind, und ein Rasterkind hat von Haus aus
     `min-height: auto` -- seine Mindesthoehe ist die seines Inhalts. Das
     Assistenzfenster ist 1080 px hoch, also wurde der Kasten 1080 px hoch
     und das Seitenverhaeltnis stillschweigend ueberstimmt: GEMESSEN
     standen die Kastenhoehen bei [454, 1080] statt bei [454, 454] --
     genau die Ungleichheit, die hier nicht sein darf. */
  min-height: 0;
}
/* Hochformat: dieselbe Spalte, hoeherer Kasten -- aber nicht doppelt.

   VIERTER DURCHGANG, 20.09.2026. Der dritte stand auf 1710/2160, also
   genau doppelt so hoch wie quer, und Arpad darauf: "mach die stehende
   kleiner, es sind riesig, die ligenden sind ok, kleiner heisst: 80%
   der jetzigen Groesse." Also 80 Prozent, und zwar von der Hoehe des
   KASTENS -- weil das Fenster darin mit `contain` an der Hoehe haengt
   und seine Breite mitzieht:

     2160 x 0,8 = 1728

     vorher   Kasten 765 x 966   Fenster 609 x 966
     dann     Kasten 765 x 773   Fenster 487 x 773

   609 -> 487 und 966 -> 773 sind beide genau 80 Prozent; das Fenster
   schrumpft also gleichmaessig, nicht nur in einer Richtung.

   FUENFTER DURCHGANG, 20.09.2026. Arpad: "noch 10% kleiner die
   stehende."

     1728 x 0,9 = 1555

     jetzt    Kasten 765 x 696   Fenster 439 x 696

   Das ist 72 Prozent des dritten Durchgangs und das 1,44fache des
   querformatigen Kastens.

   DER QUERFORMATIGE KASTEN BLEIBT UNANGETASTET (1710/1080, 765 x 483)
   -- "die ligenden sind ok", und das steht seit dem vierten Durchgang.
   Wer hier weiter verkleinert, aendert NUR diese eine Zahl: 1555 ist
   die Hoehe des hochformatigen Kastens auf 1710 Breite gerechnet, und
   die gemalte Fensterbreite folgt daraus von selbst
   (1555 x 681/1080 = 981 von 1710, also 439 von 765). */
body.startseite .wechsel-zeile__bild:has(img[src*="/overlay/"]) {
  aspect-ratio: 1710 / 1555;
}
/* `object-fit: contain` STATT `height: 100%` (gemessen). Die
   Mindestgroesse hatte das Bild ein zweites Mal ueberstimmt -- diesmal
   als Flex-Kind: Kasten 454 px hoch, Bild trotzdem 681 x 1080 und damit
   ueber den Kasten hinaus. Man kann das mit `min-height: 0` erschlagen;
   `contain` sagt dasselbe, ohne dass jemand spaeter raten muss, wogegen
   die Null steht: Das Bild passt sich in den Kasten ein, mittig, ohne
   sein Seitenverhaeltnis zu aendern.

   `drop-shadow` folgt dabei den wirklich gezeichneten Pixeln, nicht dem
   Elementkasten -- das Assistenzfenster bekommt seinen Schatten also um
   seine eigenen 286 px Breite, nicht um die 719 des Kastens. */
/* DAS <picture> STEHT DAZWISCHEN, und das ist der Grund, warum
   `height: 100%` am Bild zunaechst nichts tat. `<picture>` ist von Haus
   aus `inline` und damit kein Bezug fuer eine Prozenthoehe: Das Bild
   rechnete seine 100 % gegen eine Hoehe, die es nicht gab, und fiel auf
   `auto` zurueck -- GEMESSEN Kasten 454 px, Bild 1080 px. Das <picture>
   bekommt deshalb den Kasten, und das Bild bekommt das <picture>. */
body.startseite .wechsel-zeile__bild picture {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
}
body.startseite .wechsel-zeile__bild img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  filter: drop-shadow(0 18px 40px rgba(7, 27, 23, .16))
          drop-shadow(0 2px 6px rgba(7, 27, 23, .08));
}
/* HELLER GRUND, also die dunkle Variante. `var(--accent)` stand hier
   bis zum 19.09.2026 und mass 2,54:1 auf Weiß — dieselbe Zahl, wegen der
   W1 den Fokusring von der Akzentfarbe genommen hat. Der Kontrasttest
   prueft TOKENPAARE, nicht die Regeln, die sie benutzen; deshalb ist es
   durchgerutscht. Seit heute faengt es test_kein_text_traegt_die
   _akzentfarbe. */
body.startseite .wechsel-zeile__label {
  margin: 0 0 12px;
  color: var(--emerald-dark);
  font-size: 12px;
  font-weight: 850;
  letter-spacing: .14em;
  text-transform: uppercase;
}
body.startseite .wechsel-zeile__text h3 {
  margin: 0 0 14px;
  max-width: 20ch;
  font-size: clamp(24px, 2.4vw, 34px);
  line-height: 1.12;
}
body.startseite .wechsel-zeile__text p { max-width: 56ch; }

@media (max-width: 900px) {
  body.startseite .wechsel-zeile,
  body.startseite .wechsel-zeile:nth-child(odd) { grid-template-columns: 1fr; }
  body.startseite .wechsel-zeile:nth-child(odd) .wechsel-zeile__bild { order: 0; }
  /* Einspaltig gibt es keine zweite Spalte, an der etwas auszurichten
     waere: Hier darf jedes Bild seine eigene Hoehe haben, sonst stuende
     ein Assistenzfenster in einer fast leeren Zeile.

     BEIDE SELEKTOREN, UND DAS IST DER PUNKT (Befund 21.09.2026, Arpad mit
     vier Aufnahmen vom Telefon: "hier sind die Probleme mobilansicht").

     Hier stand nur `.wechsel-zeile__bild`. Das hochformatige
     Seitenverhaeltnis weiter oben steht aber an
     `.wechsel-zeile__bild:has(img[src*="/overlay/"])`, und `:has()`
     erbt die Spezifitaet seines staerksten Arguments: (0,0,3,2) gegen
     (0,0,2,1) hier. Die Zeile darunter hat das Seitenverhaeltnis also NIE
     zurueckgesetzt -- auf dem Telefon nicht und in keinem Test, weil kein
     Test den ueberlaufenden Kasten gemessen hat.

     WAS DARAUS WURDE, gemessen bei 360x640:
       Kasten 328 x 298 (aus 1710/1555), Bild 328 x 397 (aus max-height 62vh)
     Das Bild stand also 50 px ueber und 49 px unter seinem Kasten. Oben
     legte es sich ueber den Text der vorigen Zeile -- halbdurchsichtig,
     weil die Einblendung dort noch laeuft, sodass der fremde Text
     durchschien. Unten legte es sich auf die Marke der eigenen Zeile
     ("ON SCREEN", "DISCRETION", ...). Genau die vier Bilder.

     Nach der Korrektur: Kasten 397, Bild 397, kein Ueberlauf. */
  body.startseite .wechsel-zeile__bild,
  body.startseite .wechsel-zeile__bild:has(img[src*="/overlay/"]) {
    aspect-ratio: auto;
  }
  body.startseite .wechsel-zeile__bild picture { height: auto; }
  body.startseite .wechsel-zeile__bild img { width: 100%; height: auto; }
  body.startseite .wechsel-zeile__bild img[src*="/overlay/"] {
    width: auto;
    max-height: 62vh;
  }
}

/* =====================================================================
   BEWEGUNG BEIM SCROLLEN IM ZICKZACK
   =====================================================================

   Arpad am 20.09.2026: "versuch mal ein scroll animation effect
   hinzufuegen, was das scrollen ein wenig impressive macht bei zigzag."

   ZWEI REGELN, DIE HIER NICHT VERHANDELBAR SIND.

   1. BEWEGUNG IST ZIERDE UND DARF NICHTS TRAGEN. Das steht so schon in
      site.css, und es steht dort, weil es einmal schiefging: Die
      Fusszeile bekam ihre dunkle Flaeche von parallax.js, und auf den
      32 Unterseiten ohne dieses Skript stand weisse Schrift auf Weiss.
      Deshalb ist der ENDZUSTAND JEDER KEYFRAME-REGEL HIER GENAU DER
      ZUSTAND OHNE ANIMATION: Deckung 1, keine Verschiebung, Groesse 1.
      Faellt die Bewegung aus -- alte Rechner, abgeschaltete Animation,
      Ausdruck -- steht der Zickzack da, wie er jetzt dasteht.

   2. KEIN JAVASCRIPT. Das hier sind scrollgesteuerte CSS-Animationen
      (`animation-timeline: view()`): Der Browser koppelt den Ablauf an
      die Lage des Elements im Fenster, ohne Skript, ohne
      IntersectionObserver, ohne Ruckeln beim schnellen Scrollen. Zwei
      Schalter davor:

        @supports (animation-timeline: view())  -- Chrome/Edge ab 115,
              Safari ab 26, Firefox noch nicht. Wo es fehlt, greift
              KEINE der Regeln, und nichts ist unsichtbar.
        @media (prefers-reduced-motion: no-preference) -- wer Bewegung
              abgestellt hat, bekommt keine. Dieselbe Bauart wie der
              Kachel-Schwebeeffekt in boxen.css.

   DER ABLAUF endet bei `entry 100%`, also in dem Moment, in dem die
   Zeile vollstaendig im Fenster steht. Das ist Absicht und nicht nur
   Geschmack: Eine Zeile, die in der Mitte des Fensters steht, ist damit
   IMMER im Endzustand. Sonst haette jede Messung -- meine eigene und
   die der Tests -- die Zeile mitten in der Bewegung erwischt und um bis
   zu 34 px daneben gelegen.

   DIE SEITENWAHL folgt dem Zickzack selbst: In den ungeraden Zeilen
   steht das Bild rechts (`order: 2`), es kommt also von rechts herein
   und der Text von links; in den geraden umgekehrt. Unter 900 px gibt
   es nur eine Spalte und damit keine Seite -- dort bleibt nur das
   Heben. */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* --- Das Bild: heben, aufklaren, auf Groesse kommen ------------ */
    @keyframes zz-bild-auf {
      from { opacity: 0; transform: translate3d(0, 34px, 0) scale(.955); }
      to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
    }
    body.startseite .wechsel-zeile__bild .mockup-reveal {
      animation: zz-bild-auf linear both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 100%;
    }

    /* --- Der Text: dieselbe Bewegung, in drei Stufen versetzt ------ */
    /* Marke, Ueberschrift und Absatz laufen denselben Weg, nur jeweils
       ein Stueck spaeter. Der Versatz steckt im Bereich, nicht in einer
       Verzoegerung: `animation-delay` zaehlt Zeit, und hier gibt es
       keine Zeit, nur Scrollweg.

       KEINE DECKUNG AM TEXT. Bis zum 20.09.2026 stand hier
       `from { opacity: 0 }`, und Arpad hat zwei Ueberschriften verloren:
       "2 Ueberschriften verschwunden: die letzte und die vierte."

       Nachstellen liess es sich hier nicht -- durchgescrollt bei drei
       Fensterhoehen, neu geladen mit wiederhergestelltem Scrollstand:
       alle sechs Zeilen standen auf Deckung 1. Das ist aber kein
       Freispruch, sondern der Beweis, dass die Regel falsch gebaut war:
       Eine Ueberschrift, die nur dann sichtbar ist, wenn eine Animation
       in JEDEM Browser sauber anlaeuft, haengt an der Zierde. Genau das
       verbietet der Kopf dieses Abschnitts, und ich habe es selbst
       gebrochen.

       Der Text bewegt sich also, aber er ist immer lesbar. Die Stufen
       bleiben -- eine Kaskade aus reiner Verschiebung sieht man
       genauso. Die Deckung bleibt dem BILD vorbehalten: ein Bild, das
       einen Wimpernschlag fehlt, ist Zierde; eine Ueberschrift nicht. */
    @keyframes zz-text-auf {
      from { transform: translate3d(0, 22px, 0); }
      to   { transform: translate3d(0, 0, 0); }
    }
    body.startseite .wechsel-zeile__label,
    body.startseite .wechsel-zeile__text h3,
    body.startseite .wechsel-zeile__text p,
    body.startseite .wechsel-zeile__text .text-link {
      animation: zz-text-auf linear both;
      animation-timeline: view(block);
    }
    body.startseite .wechsel-zeile__label          { animation-range: entry 0%  entry 62%; }
    body.startseite .wechsel-zeile__text h3        { animation-range: entry 8%  entry 76%; }
    body.startseite .wechsel-zeile__text p         { animation-range: entry 16% entry 88%; }
    body.startseite .wechsel-zeile__text .text-link{ animation-range: entry 24% entry 100%; }

    /* --- Die Seite, aus der die Spalten kommen --------------------- */
    /* Erst ab zwei Spalten. Die Verschiebung sitzt auf der <figure> und
       nicht noch einmal auf dem <picture>, damit sich die beiden
       Transformationen nicht ueberschreiben. */
    @media (min-width: 901px) {
      @keyframes zz-von-rechts {
        from { transform: translate3d(30px, 0, 0); }
        to   { transform: translate3d(0, 0, 0); }
      }
      @keyframes zz-von-links {
        from { transform: translate3d(-30px, 0, 0); }
        to   { transform: translate3d(0, 0, 0); }
      }
      body.startseite .wechsel-zeile__bild,
      body.startseite .wechsel-zeile__text {
        animation: zz-von-links linear both;
        animation-timeline: view(block);
        animation-range: entry 0% entry 100%;
      }
      body.startseite .wechsel-zeile:nth-child(odd) .wechsel-zeile__bild,
      body.startseite .wechsel-zeile:nth-child(even) .wechsel-zeile__text {
        animation-name: zz-von-rechts;
      }
    }

    /* Die Tiefe bewegt den ganzen Mockup-Container: Ein Versatz des
       randbuendigen Bildes innerhalb der Schnittkante wuerde oben oder
       unten eine Luecke oeffnen. Bereich und Verlauf bleiben unveraendert;
       `translate` addiert sich zur seitlichen `transform`-Bewegung. */
    @keyframes zz-tiefe {
      from { translate: 0 2%; }
      to   { translate: 0 -2%; }
    }
    body.startseite .wechsel-zeile__bild {
      animation: zz-tiefe linear both;
      animation-timeline: view(block);
      animation-range: cover 0% cover 100%;
    }
    @media (min-width: 901px) {
      body.startseite .wechsel-zeile__bild {
        animation: zz-von-links linear both, zz-tiefe linear both;
        animation-timeline: view(block), view(block);
        animation-range: entry 0% entry 100%, cover 0% cover 100%;
      }
      body.startseite .wechsel-zeile:nth-child(odd) .wechsel-zeile__bild {
        animation-name: zz-von-rechts, zz-tiefe;
      }
    }
  }
}

/* ------------------------------------------------------------------
   DIESELBE BEWEGUNG FUER BROWSER OHNE `animation-timeline`
   ------------------------------------------------------------------

   Arpad am 20.09.2026: keine Bewegung. Sein Browser ist DuckDuckGo
   fuer Mac, also das WebKit seines Systems -- und das kann
   scrollgesteuerte CSS-Animationen nicht. Firefox ebenso wenig.

   Die Weiche steht im Kopf der Seite und stellt sicher, dass immer
   genau EINE der beiden Fassungen laeuft: Nur wenn
   `CSS.supports('animation-timeline','view()')` falsch ist, bekommt
   <html> die Klasse `zz-bewegt`, und nur darauf hoeren die Regeln
   hier. Wo der Browser es selbst kann, bleibt alles wie oben.

   ES IST DIESELBE BEWEGUNG, nur mit anderem Antrieb: `transition`
   statt `animation`, ausgeloest von einer Klasse, die js/zickzack.js
   setzt, sobald die Zeile ins Bild kommt.

   UND DIESELBE REGEL: NUR DAS BILD BLENDET AUF. Der Text bewegt sich,
   bleibt aber immer lesbar -- heute waren zwei Ueberschriften
   verschwunden, weil ihre Deckung an einer Animation hing. Das
   passiert hier nicht noch einmal.

   Die Sicherungen gegen ein haengendes Skript stehen in
   js/zickzack.js und im Kopf der Seite (Frist von 2,5 Sekunden). */
@media (prefers-reduced-motion: no-preference) {
  html.zz-bewegt body.startseite .wechsel-zeile__bild .mockup-reveal {
    opacity: 0;
    transform: translate3d(0, 34px, 0) scale(.955);
    transition: opacity .7s ease, transform .75s cubic-bezier(.2, .7, .2, 1);
  }
  html.zz-bewegt body.startseite .wechsel-zeile__label,
  html.zz-bewegt body.startseite .wechsel-zeile__text h3,
  html.zz-bewegt body.startseite .wechsel-zeile__text p,
  html.zz-bewegt body.startseite .wechsel-zeile__text .text-link {
    transform: translate3d(0, 22px, 0);
    transition: transform .7s cubic-bezier(.2, .7, .2, 1);
  }
  /* Die Staffelung: oben steckte sie im Scrollbereich, hier in der
     Verzoegerung -- hier gibt es wieder Zeit. */
  html.zz-bewegt body.startseite .wechsel-zeile__text h3        { transition-delay: .07s; }
  html.zz-bewegt body.startseite .wechsel-zeile__text p         { transition-delay: .14s; }
  html.zz-bewegt body.startseite .wechsel-zeile__text .text-link{ transition-delay: .21s; }

  @media (min-width: 901px) {
    html.zz-bewegt body.startseite .wechsel-zeile__bild,
    html.zz-bewegt body.startseite .wechsel-zeile__text {
      transform: translate3d(-30px, 0, 0);
      transition: transform .8s cubic-bezier(.2, .7, .2, 1);
    }
    html.zz-bewegt body.startseite .wechsel-zeile:nth-child(odd) .wechsel-zeile__bild,
    html.zz-bewegt body.startseite .wechsel-zeile:nth-child(even) .wechsel-zeile__text {
      transform: translate3d(30px, 0, 0);
    }
  }

  /* Angekommen. Ab hier steht alles genau so, wie es ohne jede
     Bewegung staende -- das ist die Zusage aus dem Kopf des
     Abschnitts, und sie gilt fuer diese Fassung genauso. */
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__bild .mockup-reveal {
    opacity: 1;
    transform: none;
  }
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__bild,
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__text,
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__label,
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__text h3,
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__text p,
  html.zz-bewegt body.startseite .wechsel-zeile.ist-da .wechsel-zeile__text .text-link {
    transform: none;
  }
}

/* Papier kennt kein Scrollen. */
@media print {
  body.startseite .wechsel-zeile *,
  body.startseite .wechsel-zeile { animation: none !important; }
}

/* ------------------------------------------------------- Zahlenband */
body.startseite .zahlenband {
  padding: clamp(40px, 5vw, 64px) 0;   /* enger seit 23.09.2026 (Startseite kuerzen) */
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}
body.startseite .zahlenband__raster {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 48px);
}
body.startseite .zahlenband__zahl {
  color: var(--text-stat);
  margin: 0 0 10px;
  font-size: clamp(40px, 4.4vw, 64px);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -.04em;
  /* Ziffern gleicher Breite: Beim Hochzaehlen springt die Zeile sonst
     bei jedem Stellenwechsel. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
body.startseite .zahlenband__einheit { font-size: .52em; font-weight: 850; }
body.startseite .zahlenband__beschriftung {
  margin: 0;
  max-width: 28ch;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.45;
}
body.startseite .zahlenband__stern {
  margin: clamp(28px, 3vw, 40px) 0 0;
  max-width: 88ch;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

@media (max-width: 900px) {
  body.startseite .zahlenband__raster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 420px) {
  body.startseite .zahlenband__raster { grid-template-columns: 1fr; }
}

/* ============================================================
   KLAPPKARTEN „PRODUCT IN ACTION" (Auftrag 4.13, 19.09.2026)
   ============================================================

   Drei Karten nebeneinander. Jede geht fuer sich auf und zu; es darf auch
   keine offen sein.

   DER KERN IN EINEM SATZ: `display: contents` an `.tab-feld` UND an der
   Szenen-Figur loest die beiden Huellen zwischen Karte und Inhalt auf,
   damit `.szene__buehne` (das Bild) und `.szene__text` (die Unterschrift)
   direkte Zellen des Kartenrasters werden. Nur deshalb kann die
   Unterschrift links unter der Ueberschrift stehen, waehrend das Bild
   rechts daneben liegt -- obwohl beide in derselben, unveraenderlichen
   Figur liegen muessen (tests/test_szenen.py vergleicht sie Zeichen fuer
   Zeichen).

   ZWEI FALLEN, DIE MEHRFACH ZUGESCHLAGEN HABEN:
     * `display: contents` SCHLAEGT `[hidden]`. Ohne die Zeile
       `.tab-feld[hidden] { display: none }` stehen alle drei Felder
       gleichzeitig offen.
     * bauteile.css setzt `.tab-list` auf `flex-direction: column`. Wer
       hier nur `display: flex` schreibt, bekommt die Karten untereinander.
       Die Richtung MUSS mitstehen.

   Alles haengt an `body.startseite` und an der eigenen Klasse
   `.product-tabs--klapp`: bauteile.css ist eingefroren und wird von
   tests/test_bauteile.py gegen das Konzept gehalten. */
body.startseite .product-tabs--klapp { display: block; margin-top: 44px; }

body.startseite .product-tabs--klapp .tab-list {
  display: flex;
  flex-direction: row;   /* MUSS stehen — siehe Kopfkommentar */
  align-items: stretch;
  gap: 12px;
}

/* Rahmen, Grund und Rundung liegen an der KARTE, nicht am Knopf. */
body.startseite .tab-karte {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  min-height: 300px;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 18px;
  background: rgba(255, 255, 255, .03);
  cursor: pointer;
  transition: flex-basis .34s ease, flex-grow .34s ease,
              border-color .2s ease, background-color .2s ease;
}
body.startseite .tab-karte:hover { border-color: rgba(255, 255, 255, .26); }

/* „+" / „−" an der Kartenecke, nicht am Knopf: Der ist im offenen
   Zustand nur noch die linke Spalte. */
body.startseite .tab-karte::after {
  content: "+";
  position: absolute;
  top: 20px;
  right: 20px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid rgba(255, 255, 255, .18);
  border-radius: 8px;
  color: rgba(255, 255, 255, .62);
  font-size: 15px;
  line-height: 1;
}
body.startseite .tab-karte.ist-offen::after {
  content: "−";
  border-color: rgba(89, 230, 184, .42);
  color: #7ce9c7;
}

/* Den Knopf von den Reiter-Eigenschaften befreien, Ziffer in den Fluss. */
body.startseite .tab-karte .tab-btn {
  display: block;
  width: 100%;
  min-height: 0;
  padding: 24px 26px;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  text-align: left;
}
body.startseite .tab-karte .tab-btn:focus-visible {
  outline: 2px solid #58ddaf;
  outline-offset: -3px;
  border-radius: 18px;
}
body.startseite .tab-karte .tab-num {
  position: static;
  display: block;
  margin-bottom: 16px;
  color: rgba(255, 255, 255, .38);
  font-size: 32px;
  font-weight: 800;
  letter-spacing: -.02em;
}
body.startseite .tab-karte.ist-offen .tab-num { color: #58ddaf; }
body.startseite .tab-karte .tab-btn b {
  margin-bottom: 10px;
  color: var(--white);
  font-size: 21px;
  letter-spacing: -.01em;
}
body.startseite .tab-karte .tab-btn > span:last-of-type {
  color: rgba(255, 255, 255, .58);
  font-size: 14px;
  line-height: 1.5;
}

/* Die Kachel: dunkelgruener Grund, dahinter ein weichgezeichnetes Fenster. */
body.startseite .tab-karte .tab-kachel {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  margin: 0 0 22px;
  aspect-ratio: 1 / .78;
  border: 1px solid rgba(255, 255, 255, .06);
  border-radius: 14px;
  background: radial-gradient(118% 94% at 50% 62%, #14402f 0%, #0d2b21 46%, #0a1e19 100%);
}
body.startseite .tab-karte .tab-kachel::before {
  content: "";
  position: absolute;
  inset: 24% 20% 19%;
  border-radius: 10px;
  background: linear-gradient(150deg, rgba(122, 226, 183, .34), rgba(24, 88, 68, .5) 58%, rgba(10, 32, 26, .2));
  filter: blur(15px);
}
body.startseite .tab-karte .tab-kachel svg {
  position: relative;
  width: 44%;
  max-width: 76px;
  height: auto;
  color: rgba(255, 255, 255, .92);
}
body.startseite .tab-karte.ist-offen .tab-kachel { display: none; }

/* Das Feld aufloesen — sein Inhalt soll in das Raster der Karte fallen. */
body.startseite .tab-karte .tab-feld { display: contents; }
body.startseite .tab-karte .tab-feld[hidden] { display: none; }

/* OHNE JAVASCRIPT STEHEN ALLE DREI KARTEN OFFEN.
   ==============================================

   Befund vom 19.09.2026, beim No-JS-Durchgang der Abnahme: `hidden` an
   den Feldern zwei und drei steht IM MARKUP -- es ist der Anfangszustand,
   den js/home.js sonst selbst setzen muesste, und
   test_ohne_javascript_steht_der_erste_reiter_offen haelt ihn fest. Ohne
   Skript fehlt dann aber auch der Weg zum Aufklappen: Zwei von drei
   Bildstrecken waeren unerreichbar, und Abschnitt 5 des Auftrags verlangt
   ausdruecklich Bild eins JEDER Strecke.

   `@media (scripting: none)` loest genau das, und zwar so, wie es
   boxen.css seit dem 12.09.2026 fuer das Kleingedruckte tut: keine
   Bedienung, keine Verbergung. Das Attribut bleibt am Element stehen --
   der Test liest die Eigenschaft, nicht die Sichtbarkeit, und bleibt
   gruen --, aber der Inhalt steht da. Dasselbe im Ausdruck: Papier hat
   keinen Knopf. */
@media (scripting: none) {
  body.startseite .tab-karte .tab-feld[hidden] { display: contents; }
  body.startseite .tab-karte .tab-btn { cursor: default; }
}
@media print {
  body.startseite .tab-karte .tab-feld[hidden] { display: contents; }
}

/* Die offene Karte: links Text, rechts Bild ueber alle Zeilen. */
body.startseite .tab-karte.ist-offen {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: minmax(220px, 330px) minmax(0, 1fr);
  grid-template-rows: auto auto auto 1fr;
  column-gap: 30px;
  padding: 26px;
}
body.startseite .tab-karte.ist-offen > .tab-btn { grid-column: 1; grid-row: 1; padding: 0; }
body.startseite .tab-karte.ist-offen .szene { display: contents; }
body.startseite .tab-karte.ist-offen .szene__nutzen {
  grid-column: 1;
  grid-row: 2;
  margin: 12px 0 14px;
  color: rgba(255, 255, 255, .58);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.55;
}
body.startseite .tab-karte.ist-offen .szene__text {
  grid-column: 1;
  grid-row: 3;
  min-height: 0;
  padding: 0;
  color: rgba(255, 255, 255, .5);
  font-size: 14px;
  line-height: 1.5;
}
body.startseite .tab-karte.ist-offen .szene__buehne {
  grid-column: 2;
  grid-row: 1 / -1;
  align-self: center;
  border-radius: 12px;
}

/* DER TITEL STEHT WAAGERECHT (20.09.2026). Hier stand er senkrecht und
   von unten nach oben -- `vertical-rl` plus `rotate(180deg)`, damals als
   die bessere der beiden Drehrichtungen gewaehlt. Arpad: "ich will nichts
   was von unten nach oben gelesen werden muss." Das ist keine
   Geschmacksfrage: Gedrehter Text zwingt zum Kopfdrehen, und wer ihn
   vergroessert oder vorlesen laesst, bekommt ihn ohnehin waagerecht.

   DER STREIFEN WIRD DAFUER BREITER: 88-116 px trugen nur eine Zeile
   senkrecht. Waagerecht braucht "Follow through" zwei Zeilen und dafuer
   Platz -- 132-168 px. Was die drei Streifen mehr nehmen, fehlt der
   offenen Karte; gemessen bleibt ihr bei 1440 px genug fuer Text und
   Buehne nebeneinander. */
body.startseite .tab-karte.ist-streifen { flex: 0 0 clamp(132px, 11.6vw, 168px); }
body.startseite .tab-karte.ist-streifen .tab-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  padding: 22px 8px;
  text-align: center;
}
body.startseite .tab-karte.ist-streifen .tab-num { order: 1; margin-bottom: 0; }
body.startseite .tab-karte.ist-streifen .tab-btn b {
  order: 2;
  margin: auto 0;
  /* 18px statt 21: Zwei Zeilen in 132 px brauchen etwas weniger
     Schrift, sonst trennt "through" mitten im Wort. */
  font-size: 18px;
  line-height: 1.25;
}
body.startseite .tab-karte.ist-streifen .tab-btn > span:last-of-type { display: none; }
body.startseite .tab-karte.ist-streifen .tab-kachel {
  order: 3;
  width: 46px;
  margin: 0;
  aspect-ratio: 1;
  border-radius: 12px;
}
body.startseite .tab-karte.ist-streifen .tab-kachel svg { width: 56%; }
body.startseite .tab-karte.ist-streifen::after { content: none; }

@media (max-width: 1000px) {
  body.startseite .product-tabs--klapp .tab-list { flex-wrap: wrap; }
  body.startseite .tab-karte,
  body.startseite .tab-karte.ist-offen,
  body.startseite .tab-karte.ist-streifen { flex: 0 0 100%; min-height: 0; }

  body.startseite .tab-karte.ist-offen {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto auto;
  }
  body.startseite .tab-karte.ist-offen > .tab-btn,
  body.startseite .tab-karte.ist-offen .szene__nutzen,
  body.startseite .tab-karte.ist-offen .szene__text,
  body.startseite .tab-karte.ist-offen .szene__buehne { grid-column: 1; }
  body.startseite .tab-karte.ist-offen .szene__buehne { grid-row: 4; margin-top: 18px; }

  body.startseite .tab-karte.ist-streifen .tab-btn {
    display: block;
    height: auto;
    padding: 24px 26px;
    text-align: left;
  }
  body.startseite .tab-karte .tab-kachel { display: none; }
  body.startseite .tab-karte.ist-streifen .tab-num { margin-bottom: 16px; }
  body.startseite .tab-karte.ist-streifen .tab-btn b {
    margin: 0 0 10px;
    writing-mode: horizontal-tb;
    transform: none;
  }
  body.startseite .tab-karte.ist-streifen .tab-btn > span:last-of-type { display: block; }
  body.startseite .tab-karte.ist-streifen::after { top: 20px; right: 20px; bottom: auto; transform: none; }
}

/* 21.09.2026: one visual system, with all original feature copy retained. */
body.startseite .hero { background: var(--gradient-hero); }
/* BREITER ALS DER REST DER SEITE (21.09.2026). Arpad: Text und
   Ueberschrift links weiter nach links, die Punkte rechts weiter nach
   rechts, "sodass beide ein bisschen mehr am Bildschirmrand liegen".

   NICHT AM RASTER GEDREHT, SONDERN AM KASTEN DARUM. Die Spalten
   stehen 9fr / 11fr und sollen so stehen bleiben -- wer sie
   auseinanderzieht, verschiebt nur die Fuge in der Mitte. Beide
   Saeulen nach aussen bringt allein der .container, und der deckelt
   bei --container-max (1240 px). Auf einem 1920er Schirm bleiben
   dadurch 340 px je Seite leer, waehrend der Hero als einziger
   Abschnitt der Seite zwei volle Textspalten traegt.

   NUR HIER, NUR DER HERO: Die 1240 px sind das Lesemass der Seite und
   fuer Fliesstext richtig. Der Hero ist kein Fliesstext, sondern zwei
   Spalten nebeneinander -- er darf breiter, der Rest nicht.

   DIE FORMEL WIRD NIE SCHMALER ALS HEUTE, und das ist ihr ganzer
   Zweck: `max(--container-max, 100% - 200px)` haelt die 1240 px als
   Boden, sodass mittlere Fenster unveraendert bleiben; erst wenn 200
   px Rand je Seite mehr als 1240 px uebrig lassen -- also ab rund
   1640 px Fensterbreite -- waechst der Kasten mit. `min(..., 1520px)`
   ist die Decke, damit die H1 auf sehr breiten Schirmen nicht quer
   durchs Bild laeuft.

     1280 px  ->  1240 (wie bisher)
     1600 px  ->  1400 (100 px Rand)
     1920 px  ->  1520 (200 px Rand)

   `max-width: none` muss dazu: thalassa.css setzt `.container` auf
   `max-width: var(--container-max)`, und ohne das Aufheben bliebe die
   Breite oben bei 1240 px haengen, egal was `width` sagt. */
/* ERST AB 1280 px (22.09.2026). Die Formel stand ohne Medienabfrage, und
   `max(--container-max, …)` hat eben das getan, was oben steht: Sie wird
   NIE schmaler als 1240 px -- auch nicht auf dem Telefon. Arpads
   Schirmbild vom selben Abend, 412 px: der Hero-Kasten 1240 px breit, links
   ohne Rand, die Ueberschrift als „entscheidende Me…" und der Absatz als
   „…exakte Z…" am rechten Rand abgeschnitten; `overflow` des Heros
   schluckte den Rest, deshalb lief die Seite nicht quer und kein Test
   schlug an. Gemessen dasselbe bei 360, 390 und bis 1279 px.

   Unter 1280 px gilt wieder der gewoehnliche `.container` (Innenrand,
   hoechstens --container-max). Ab 1280 px ist alles wie zuvor -- dort
   ergibt die Formel ohnehin mindestens 1240 px, genau wie die Tabelle
   oben. */
@media (min-width: 1280px) {
  body.startseite .hero > .container {
    width: min(max(var(--container-max), calc(100% - 200px)), 1520px);
    max-width: none;
  }
}
body.startseite .hero__raster {
  grid-template-columns: minmax(0, 9fr) minmax(0, 11fr);
  gap: clamp(32px, 4vw, 64px);
  padding-top: 48px;
}
body.startseite .hero h1 {
  font-size: clamp(42px, 5.2vw, 72px);
  line-height: 1.04;
  text-wrap: balance;
}
body.startseite .hero-sub { color: var(--text-on-dark-muted); }
body.startseite .hero-copy .hero-eyebrow {
  font-size: 12px;
  line-height: 1.5;
  color: var(--brand-light);
}
body.startseite .hero-neben { padding-top: 20px; }
/* ENGER GESETZT (21.09.2026, dritter Durchgang). Arpad: "schiebe
   Schriften auf der Hero Page ein bisschen zusammen." Gemeint ist der
   Weissraum zwischen den vier Punkten, nicht die Schriftgroesse -- die
   Groessen bleiben, wo sie am 20.09. gemessen wurden (14px Satz, 16px
   Titel), sonst faellt der zweite Durchgang wieder in sich zusammen.

   24px -> 18px zwischen den Punkten und 1.5 -> 1.45 im Satz: Die vier
   Bloecke lesen sich damit als eine Gruppe statt als vier Inseln. Die
   Spalte wird dabei kuerzer als die H1-Spalte links -- das darf sie,
   `align-content: space-between` faellt hier ohnehin weg, weil die
   spaetere Regel `gap` fest setzt. */
body.startseite .hero-punkte { max-width: none; gap: 18px; }
body.startseite .hero-punkte li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 0;
  border: 0;
  color: var(--text-on-dark-muted);
  font-size: 14px;
  line-height: 1.45;
}
body.startseite .hero-punkte li > div { min-width: 0; }
body.startseite .hero-punkte__icon {
  width: 24px;
  height: 24px;
  margin-top: 1px;
  flex: 0 0 24px;
  color: var(--brand-light);
}
/* 6px -> 3px: Titel und Satz gehoeren zusammen. Der Abstand zwischen
   beiden muss kleiner bleiben als der Abstand zum naechsten Punkt (18px),
   sonst bindet das Auge den Satz an den falschen Titel. */
body.startseite .hero-punkte b {
  margin-bottom: 3px;
  color: var(--brand-light);
  line-height: 1.3;
  letter-spacing: 0;
}
body.startseite .leiste {
  background: var(--surface-hero);
  color: var(--text-on-dark-muted);
}

/* DIE FEINE LINIE UNTER DER ZEILE (21.09.2026). Arpad: "make a very
   fine seamless line under the 'free trial - students from 19.99€ one
   time.'"

   1 px und Weiss bei .18: Leiste und Hero tragen denselben Grund, die
   Linie ist also keine Kante zwischen zwei Flaechen, sondern die
   einzige Markierung, dass hier eine Zeile aufhoert. Sie darf deshalb
   kaum zu sehen sein -- ein voller Strich zerschnitte den Seitenkopf,
   den das Band darueber gerade zusammengefuegt hat.

   OHNE ENDEN: Der Verlauf laeuft an beiden Seiten auf Null aus, wie
   die Maske des Laufbands weiter unten. Ein Strich mit harten Enden
   sieht bei voller Fensterbreite aus, als waere er abgeschnitten;
   ausgeblendet hat er keine Enden, die abgeschnitten wirken koennten. */
body.startseite .leiste::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent,
    rgba(255, 255, 255, .18) 12%,
    rgba(255, 255, 255, .18) 88%,
    transparent);
  pointer-events: none;
}
/* Ohne Strich (23.09.2026), dafuer mit Chevron: Der ganze Satz steht
   fett, also traegt Gewicht hier nichts, und Mint gegen Weiss liegt unter
   3 : 1 -- der Chevron ist das zweite Signal, das WCAG 1.4.1 verlangt. */
body.startseite .leiste a {
  display: inline;
  margin: 0;
  color: var(--brand-light);
}
body.startseite .leiste a::after { content: "\00a0\203A"; }
body.startseite .leiste a:is(:hover, :focus-visible) { color: var(--white, #fff); }

/* Layout und Reveal bleiben fest. Nur die absolute Vorschau waechst:
   kein Sprung der Textspalte, kein neuer Scrollbereich fuer den Reveal.
   Das durchgaengige `contain` vermeidet einen abrupten Fit-Wechsel;
   die Anfangsskalierung erzeugt den Ausschnitt und faehrt auf 1 zurueck. */
body.startseite {
  --mockup-aspect-ratio: 4 / 3;
  --mockup-stage-ratio: 1.3333333333;
  --mockup-grow: 0px;
  --mockup-full-position: 50%;
  /* KEIN VERSATZ NACH AUSSEN MEHR (22.09.2026). Hier stand
     `max(0px, calc((100vw - var(--container-max)) / 2 - 32px))`: Jedes Bild
     rueckte bis 32 px an den Bildschirmrand, bei 1920 px also 308 px aus dem
     Satzspiegel, mit 388 px Luft zwischen Bild und Text. Wunsch: "nicht mehr
     ganz am Bildschirmrand, sondern weiter in der Mitte". Mit null stehen die
     Bilder buendig im Container; die Hover-Vorschau waechst weiter in den
     Spaltenabstand (`--mockup-grow` rechnet mit derselben Variable). */
  --mockup-outset: 0px;
}
body.startseite .wechsel-zeile__bild,
body.startseite .wechsel-zeile__bild:has(img[src*="/overlay/"]) {
  --mockup-source-ratio: 1.5833333333;
  --mockup-cover-scale: max(calc(var(--mockup-stage-ratio) / var(--mockup-source-ratio)), calc(var(--mockup-source-ratio) / var(--mockup-stage-ratio)));
  --mockup-expanded-height: max(100%, min(82svh, calc(100% * 1.4)));
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: var(--mockup-aspect-ratio);
  padding: 0;
  overflow: visible;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
body.startseite .wechsel-zeile__bild:has(img[src*="/overlay/"]) {
  --mockup-source-ratio: .6305555556;
}
body.startseite .wechsel-zeile__bild .mockup-reveal {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
body.startseite .wechsel-zeile__bild .mockup-viewport {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: var(--device-radius);
}
body.startseite .wechsel-zeile__bild picture {
  position: absolute;
  inset: 0;
  display: block;
  height: 100%;
  width: 100%;
}
body.startseite .wechsel-zeile__bild img,
body.startseite .wechsel-zeile__bild img[src*="/overlay/"] {
  display: block;
  width: 100%;
  height: 100%;
  max-height: none;
  object-fit: contain;
  object-position: center top;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: none;
  transform-origin: center top;
}
@media (min-width: 901px) {
  body.startseite {
    --mockup-grow: min(96px, calc(clamp(36px, 5vw, 80px) - 16px + var(--mockup-outset)));
  }
  body.startseite .wechsel-zeile__bild {
    left: calc(-1 * var(--mockup-outset));
    --mockup-full-position: 0%;
  }
  body.startseite .wechsel-zeile:nth-child(odd) .wechsel-zeile__bild {
    left: var(--mockup-outset);
    --mockup-full-position: 100%;
  }
  /* Die aeussere Kante steht fest: Die Vorschau nutzt den freien Abstand
     zur Textspalte, statt ueber den Bildschirmrand hinauszuwachsen. */
  body.startseite .wechsel-zeile:nth-child(odd) .mockup-viewport {
    left: auto;
    right: 0;
  }
}
/* Die vergroesserte Vorschau braucht die freie Bildspalte. Im gestapelten
   Layout bleibt das ganze Bild ohne Hover sichtbar und ueberdeckt keinen Text. */
@media (min-width: 901px) and (hover: hover) and (prefers-reduced-motion: no-preference) {
  body.startseite .wechsel-zeile__bild:hover { z-index: 2; }
  body.startseite .wechsel-zeile__bild .mockup-viewport {
    box-shadow: var(--device-shadow);
    transition: width 550ms cubic-bezier(.22, 1, .36, 1), height 550ms cubic-bezier(.22, 1, .36, 1), top 550ms cubic-bezier(.22, 1, .36, 1), box-shadow 550ms cubic-bezier(.22, 1, .36, 1);
  }
  body.startseite .wechsel-zeile__bild img {
    transform: scale(var(--mockup-cover-scale));
    transition: transform 550ms cubic-bezier(.22, 1, .36, 1), object-position 550ms cubic-bezier(.22, 1, .36, 1);
    will-change: transform;
  }
  body.startseite .wechsel-zeile__bild:hover .mockup-viewport {
    width: calc(100% + var(--mockup-grow));
    height: var(--mockup-expanded-height);
    top: calc((100% - var(--mockup-expanded-height)) / 2);
    box-shadow: none;
  }
  body.startseite .wechsel-zeile__bild:hover img {
    transform: scale(1);
    object-position: var(--mockup-full-position) top;
  }
}
@media (prefers-reduced-motion: reduce) {
  body.startseite .wechsel-zeile__bild img {
    transform: none;
    transition: none;
    will-change: auto;
  }
  /* Nur Deckkraft. Ohne View-Timeline bleibt der bestehende Fallback
     ohne Bewegung sofort sichtbar. */
  @supports (animation-timeline: view()) {
    @keyframes zz-bild-fade {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    body.startseite .wechsel-zeile__bild .mockup-reveal {
      animation: zz-bild-fade linear both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 100%;
    }
  }
}
body.startseite .hero-film__hintergrund-rahmen,
body.startseite .hero-film .hero__buehne {
  border-radius: var(--device-radius);
  box-shadow: var(--device-shadow);
}
/* Use the existing clean capture of the same answer, before its busy page
   backdrop was composited. The original interface copy is unchanged. */
body.startseite .wechsel-zeile__bild--discretion img { opacity: .88; }

/* Full teasers: no line clamping or expandable extra link in these cards. */
body.startseite .moment-card .box__text {
  display: block;
  overflow: visible;
  -webkit-line-clamp: unset;
  color: var(--text-muted);
  line-height: 1.65;
}
body.startseite .moment-card.box--ink .box__text { color: var(--text-on-dark-muted); }
body.startseite .moment-card .text-link {
  display: inline-flex;
  width: fit-content;
  min-height: 44px;
  padding: 8px 0;
  color: var(--brand-dark);
  font-weight: 700;
}
body.startseite .moment-card .text-link::after { content: "\203A"; font-size: 1.25em; line-height: 1; }
body.startseite .moment-card.box--ink .text-link { color: var(--brand-light); }
body.startseite .moment-card .text-link:hover { color: var(--text-link-hover, #17483c); }
body.startseite .zahlenband__zahl { color: var(--text-stat); }

@media (max-width: 1100px) {
  body.startseite .hero__raster { grid-template-columns: 1fr; }
  body.startseite .hero-copy { max-width: 760px; }
  body.startseite .hero-punkte { grid-template-columns: 1fr; }
  body.startseite .hero-neben { padding-top: 0; }
}
@media (max-width: 600px) {
  body.startseite .hero-punkte { grid-template-columns: 1fr; }
  body.startseite .hero-punkte li {
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr);
    gap: 6px 10px;
  }
  body.startseite .hero-punkte li > div { display: contents; }
  body.startseite .hero-punkte b { align-self: center; margin: 0; }
  body.startseite .hero-punkte__beschreibung { grid-column: 1 / -1; }
  body.startseite .zahlenband__raster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body.startseite .zahlenband__zahl { font-size: 44px; }
  body.startseite {
    --mockup-aspect-ratio: 16 / 10;
    --mockup-stage-ratio: 1.6;
  }
}
@media (max-width: 420px) {
  body.startseite .hero-punkte li { font-size: 13px; }
}
@media (max-width: 360px) {
  body.startseite .hero-punkte li { font-size: 12px; }
}

/* =====================================================================
   UMBAU 23.09.2026: DREI MOMENTE, KUERZERE STARTSEITE
   =====================================================================

   Arpad: "radikaler Umbau", die Startseite war 15.240 px lang (16,9
   Bildschirme am Laptop). Der groesste Posten war der Zickzack mit
   3.914 px; an seiner Stelle stehen jetzt drei Momente nebeneinander
   (Variante A) mit den Fotos der Website als menschlichem Element.

   DIE ALTEN WECHSELZEILEN-REGELN WEITER OBEN SIND OHNE MARKUP. Sie
   stehen noch da, weil sie mit den Regeln des Zahlenbands und der
   Hero-Komposition verflochten sind und ein Abriss in einem Zug mehr
   Risiko als Nutzen hat. Sie greifen nicht: Es gibt kein .wechsel mehr. */

/* Hero: die vier Punkte als EINE Gruppe, mittig zur H1-Spalte. Bis heute
   verteilte `align-content: space-between` sie ueber die ganze Hoehe der
   linken Spalte -- 165 px zwischen zwei Punkten, vier Inseln statt einer
   Liste. Der Abstand zwischen den Punkten (18 px) bleibt. */
body.startseite .hero-punkte { align-content: center; }

/* .momente traegt das Grundmass von .section (112 / 78 px), keine Ausnahme. */
body.startseite .momente__titel {
  max-width: 820px;
  margin: 0 0 clamp(32px, 4vw, 48px);
  font-size: clamp(30px, 3.4vw, 44px);
  line-height: 1.08;
}
body.startseite .momente__raster {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 40px);
  margin: 0;
  padding: 0;
  list-style: none;
}
body.startseite .moment { display: flex; flex-direction: column; min-width: 0; }
body.startseite .moment__foto {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  margin: 0 0 20px;
  border-radius: 20px;
}
body.startseite .moment__label {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 800;
  line-height: 1.4;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--emerald-dark);
}
body.startseite .moment h3 {
  margin: 0 0 10px;
  font-size: clamp(21px, 1.9vw, 25px);
  line-height: 1.2;
}
body.startseite .moment p:not(.moment__label) {
  margin: 0 0 8px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text-muted);
}
body.startseite .moment .link-weiter { margin-top: auto; }

body.startseite .momente__zusagen {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px clamp(24px, 3vw, 40px);
  margin: clamp(40px, 5vw, 64px) 0 0;
  padding: 28px 0 0;
  border-top: 1px solid var(--border-subtle);
  list-style: none;
}
body.startseite .momente__zusagen li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  min-width: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-muted);
}
body.startseite .momente__zusagen svg {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  margin-top: 1px;
  color: var(--emerald-dark);
}
body.startseite .momente__zusagen b {
  display: block;
  margin-bottom: 2px;
  font-size: 16px;
  line-height: 1.35;
  color: var(--ink);
}
body.startseite .momente__zusagen .link-weiter { min-height: 36px; font-size: 14px; }
@media (max-width: 900px) {
  body.startseite .momente__raster,
  body.startseite .momente__zusagen { grid-template-columns: 1fr; }
  body.startseite .moment__foto { aspect-ratio: 16 / 9; }
}

/* Uebersetzung als eine Zeile (23.09.2026): mittig, ruhig, mit Chevron. */
body.startseite .uebersetzung-zeile { padding: 8px 0 24px; }
body.startseite .uebersetzung-zeile__text {
  max-width: 760px;
  margin: 0 auto;
  font-size: 15px;
  line-height: 1.6;
  text-align: center;
  color: var(--text-muted);
}
body.startseite .uebersetzung-zeile__text .link-weiter { min-height: 32px; margin-left: 4px; }

/* EINMALIG KAUFEN ALS AKKORDEON (23.09.2026). Der Kopf ist eine Zeile mit
   Plus/Minus wie in den FAQ; offen zeigt er dieselben Karten wie vorher. */
body.startseite .einmal-klapp { border-top: 1px solid var(--border-subtle); border-bottom: 1px solid var(--border-subtle); }
body.startseite .einmal-klapp__kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
  padding: 22px 44px 22px 0;
  position: relative;
  list-style: none;
  cursor: pointer;
}
body.startseite .einmal-klapp__kopf::-webkit-details-marker { display: none; }
body.startseite .einmal-klapp__kopf .eyebrow { margin: 0; }
body.startseite .einmal-klapp__titel { margin: 0; font-size: clamp(20px, 2vw, 26px); line-height: 1.25; }
body.startseite .einmal-klapp__kopf::after {
  content: "+";
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 26px;
  font-weight: 500;
  line-height: 1;
  color: var(--emerald-dark);
}
body.startseite .einmal-klapp[open] > .einmal-klapp__kopf::after { content: "\2212"; }
body.startseite .einmal-klapp[open] > .price-grid { margin: 8px 0 32px; }
body.startseite #groupOnce { padding-top: 24px; padding-bottom: 40px; }

/* WEITERE FRAGEN (23.09.2026): eine zugeklappte Zeile unter den sechs.
   Sie liest sich als Verweis (Gruen, Chevron), nicht als siebte Frage. */
body.startseite .faq-spalte { min-width: 0; }
body.startseite .faq-mehr > summary {
  display: inline-flex;
  align-items: center;
  gap: .35em;
  min-height: 44px;
  margin-top: 16px;
  list-style: none;
  cursor: pointer;
  color: var(--emerald-dark);
  font-weight: 700;
}
body.startseite .faq-mehr > summary::-webkit-details-marker { display: none; }
/* Die allgemeine Regel fuer aufklappbare Zeilen zeichnet einen Winkel aus
   zwei Raendern (9 x 9 px, 45 Grad gedreht). Hier steht stattdessen der
   Pfeil der .link-weiter-Verweise -- ohne das Zuruecksetzen standen beide
   uebereinander (gemessen 23.09.2026). */
body.startseite .faq-mehr > summary::after {
  content: "\203A"; width: auto; height: auto; margin: 0; border: 0;
  transform: none; font-size: 1.25em; line-height: 1;
  transition: transform var(--dur-fast, .15s);
}
body.startseite .faq-mehr[open] > summary::after { transform: rotate(90deg); }
body.startseite .faq-mehr > .faq-list { margin-top: 8px; }
