*,*::before,*::after{box-sizing:border-box}
/* Der Seitengrund liegt auf html UND auf body, und das ist kein Versehen.
   Steht er nur auf body, reicht der Browser ihn an die Leinwand durch und das Wurzelelement
   selbst bleibt durchsichtig. Im normalen Betrieb sieht man davon nichts. Beim Seitenwechsel
   schon: der Schnappschuss der View Transition wird vom Wurzelelement genommen, hat dann ein
   Loch, und darunter steht die Leinwand des Browsers. Bei einem System im Dunkelmodus ist die
   schwarz — der Übergang blitzt schwarz auf.
   color-scheme:light gehört dazu. Ohne die Angabe hält der Browser die Seite im Dunkelmodus für
   dunkel und stellt Leinwand, Rollbalken, Auswahllisten und Dateiknöpfe entsprechend dunkel dar.
   Diese Seite ist creme, immer. */
html{-webkit-text-size-adjust:100%;background:var(--page-bg);color-scheme:light}

/* ---- Oberhalb von 1920 × 1080 wächst die ganze Seite mit ----
   Die Seite ist auf 1240 px Inhaltsbreite gebaut. Auf einem 4K-Schirm stünde derselbe Block in der
   Mitte von 3840 px und die Schrift wäre halb so groß wie auf einem HD-Schirm, ringsum Creme.
   zoom vergrößert Layout und Schrift gemeinsam, ohne dass eine Zeile anders umbricht: ein 3840er
   16:9 sieht damit aus wie ein 1920er, nur größer.

   max(1, …) statt einer Media Query. Die Formel begrenzt sich selbst, unterhalb von 1920 kommt 1
   heraus. Damit bleibt es bei dem einen Breakpoint des Systems weiter unten, und ein nicht
   maximiertes Fenster auf einem großen Schirm wird nicht verkleinert.

   min() über beide Achsen, nicht nur die Breite. Ein 3440 × 1440 Ultrawide käme über die Breite auf
   Faktor 1,79 und hätte danach 804 px Höhe übrig; die Seite wäre riesig und das Fenster zu flach
   dafür. Über die Höhe sind es 1,33, und der Ultrawide bekommt breitere Ränder statt einer
   erdrückenden Seite. Bei echtem 16:9 sind beide Werte gleich, dort ändert min() nichts.

   --schirm ist derselbe Faktor als Zahl, und JEDE vw- oder vh-Größe im System wird durch ihn
   geteilt. Das ist kein Schmuck: vw und vh schrumpfen unter zoom nicht mit, 100vh bleibt der ganze
   Schirm und wird zusätzlich vergrößert. Ungeteilt stünde --section-gap auf HD bei 86,4 px (8vh
   von 1080, unter seinem Deckel) und auf 4K bei 112 × 2 = 224 statt 172,8 — dreißig Prozent zu viel
   Luft zwischen den Abschnitten. Geteilt ergibt 8vh / 2 von 2160 wieder 86,4.
   Wer eine vw- oder vh-Größe ergänzt, teilt sie durch --schirm. Ausgenommen ist der Handy-Block am
   Ende dieser Datei: dort ist der Faktor immer 1.

   Kein Kreisverkehr, obwohl --schirm auf html steht und html das zoom trägt: die vw und vh darin
   lesen den unveränderten Schirm, nicht den gezoomten.

   Ein Browser ohne zoom lässt die Zeile fallen und zeigt die Seite wie vor dieser Änderung: klein
   in der Mitte des großen Schirms. --schirm rechnet trotzdem, deshalb stehen dort zwei Abstände
   enger als früher — --section-gap 86 statt 112 px, --section-head 43 statt 48. Mehr passiert
   nicht, alle übrigen vw- und vh-Größen liegen bei 1920 längst auf ihrem clamp-Deckel. */
:root{--schirm:max(1, min(100vw / 1920px, 100vh / 1080px))}
html{zoom:var(--schirm)}
body{margin:0;background:var(--page-bg);color:var(--text-primary);font-family:var(--font-body);font-size:var(--fs-body);line-height:var(--lh-body);letter-spacing:var(--ls-body);font-weight:var(--fw-medium);-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{margin:0;font-family:var(--font-display);font-weight:var(--fw-bold);letter-spacing:var(--ls-heading);line-height:var(--lh-heading);text-wrap:balance}
h1{font-size:var(--fs-display-l);letter-spacing:var(--ls-display);line-height:var(--lh-display)}
h2{font-size:var(--fs-display-m);letter-spacing:var(--ls-display);line-height:var(--lh-display)}
h3{font-size:var(--fs-heading)}
h4{font-size:var(--fs-subhead);line-height:var(--lh-subhead)}
p{margin:0;text-wrap:pretty}
em,.ds-italic{font-family:var(--font-accent);font-style:italic;font-weight:400;letter-spacing:-0.01em}
a{color:var(--text-primary);text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1.5px;transition:color var(--dur-fast) var(--ease-snap),text-decoration-color var(--dur-fast) var(--ease-snap)}
a:hover{color:var(--hover-text);text-decoration-color:var(--murk)}
button,input,textarea,select{font:inherit;color:inherit}
:focus-visible{outline:var(--stroke-heavy) solid var(--focus-ring);outline-offset:2px;transition:none}
::selection{background:var(--acid);color:var(--ink)}
.ds-label{font-family:var(--font-body);font-size:var(--fs-label);font-weight:var(--fw-semibold);letter-spacing:var(--ls-label);text-transform:uppercase;line-height:var(--lh-label)}
.ds-num{font-variant-numeric:tabular-nums}
.ds-page{max-width:var(--grid-max);margin:0 auto;padding-inline:var(--page-inset)}
.ds-grid{display:grid;grid-template-columns:repeat(var(--grid-columns),1fr);gap:var(--grid-gutter)}

/* Uneven card rows. The ratio is set inline per section (e.g. 5fr 4fr 3fr) because it varies —
   this class exists so the row can be stacked below the breakpoint. */
.ds-cards{display:grid;gap:var(--grid-gutter);align-items:stretch}

/* Absolutely placed fill layer (hero cards). Returns to normal flow below the breakpoint —
   an absolute element inside a stacked column would overlap the text above it. */
.ds-fill{position:absolute;inset:0}

/* ---- Auftritt beim Eintritt ins Bild ----
   Der versteckte Ausgangszustand hängt an .js-reveal auf <html>, gesetzt vom Skript der Seite.
   Das ist der Kern der Regel: ohne Skript bleibt der Inhalt sichtbar. Eine ausgefallene
   Beobachtung darf niemals eine leere Verkaufsseite ergeben, und genau das ist die übliche
   Art, wie Scroll-Reveal in freier Wildbahn kaputtgeht.

   .is-in setzt der IntersectionObserver, einmal je Element, danach unobserve — beim
   Zurückscrollen passiert nichts mehr. Ein Block, der einmal da war, bleibt da.

   Gestaffelt wird über --i (0,1,2 …). Setzbar über .ds-delay-1/2/3, damit die Seite keine
   eigenen Custom Properties inline schreiben muss.

   Kein will-change: bei zwanzig Blöcken kostet die Dauerbeförderung auf eine eigene Ebene mehr
   Speicher als sie bringt; Deckkraft und Transform laufen ohnehin auf dem Compositor.

   Elemente mit eigenem Inline-Transform (die gekippten Motive) bekommen .ds-reveal NICHT —
   der Inline-Wert schlägt jede Regel hier, das Element würde nur ein- statt aufblenden.
   In dem Fall trägt die Elternschicht den Auftritt. */
.ds-reveal{transition:opacity var(--dur-reveal) var(--ease-out),transform var(--dur-reveal) var(--ease-out);transition-delay:calc(var(--i,0) * var(--reveal-step))}
.js-reveal .ds-reveal{opacity:0;transform:translateY(var(--reveal-shift))}
.js-reveal .ds-reveal.is-in{opacity:1;transform:none}
.ds-delay-1{--i:1}
.ds-delay-2{--i:2}
.ds-delay-3{--i:3}
@media (prefers-reduced-motion:reduce){.js-reveal .ds-reveal{opacity:1;transform:none}}

/* ---- The one breakpoint in the system: 768px. Below it, everything stacks. ----
   The declarations are !important on purpose, not by accident: column spans are authored as
   inline styles (grid-column: span 7), and no selector beats an inline style. Without it the
   12-column grid stays split at 320px. Do not remove and do not add a second breakpoint —
   one hard switch, no in-between layout. */
@media (max-width:767px){
  /* Das 6vh hier steht als einzige Größe im System ungeteilt da, und das ist Absicht: unter 768 px
     Breite ist --schirm immer 1, weil min() dort längst unter der Eins liegt und max(1, …) greift.
     Eine Division änderte nichts und legte nur nahe, sie könnte etwas ändern. */
  :root{--grid-gutter:var(--s-4);--section-gap:clamp(40px,6vh,72px)}
  /* Kartenpolster auf dem Handy. Am Schreibtisch ist eine Karte 380 breit und 48 Polster kosten
     ein Viertel davon; auf 390 px ist sie 358 breit und dieselben 48 kosten ein Drittel — die
     Zeile fällt von rund 46 Zeichen auf unter 30 und der Fließtext bricht auf zwei, drei Wörter.
     Das Polster ist ein Anteil der Karte, kein fester Wert, und die Karte wird schmäler.
     Kein !important nötig: die Komponenten setzen padding:var(--pad-card-md) inline, die Variable
     wird aber erst beim Auflösen gelesen — hier umgesetzt gilt sie auch dort.
     sm bleibt, es liegt mit 24 ohnehin darunter. */
  :root{--pad-card-md:var(--s-6);--pad-card-lg:var(--s-6)}
  .ds-grid>*{grid-column:1 / -1 !important}
  .ds-cards{grid-template-columns:1fr !important}
  /* The fill layer needs more than position:static to come back to flow. It was sized for the
     right half of a hero row — a max-width and an auto margin that pinned it to that edge. Those
     two survive the switch to static and leave the stacked card narrow and hard right, with the
     gap growing as the viewport approaches 768. Released here, not on the page, so the card is
     the full column wherever the layer is used. */
  .ds-fill{position:static !important;inset:auto !important;width:100% !important;max-width:none !important;margin-inline:0 !important}
  /* Die Sprungmarken der Navileiste. Wortmarke und Knopf bleiben und tragen zusammen rund 280 px,
     die vier Marken kämen ungebrochen auf knapp 500 dazu — die Leiste stünde über dem Rand und die
     ganze Seite ließe sich seitwärts schieben. !important, weil display:flex in der Komponente
     inline steht, dieselbe Lage wie beim Raster. */
  .ds-navlinks{display:none !important}
  /* Das „24 H" neben der Wortmarke. Es kostet mit seinem Abstand 53 px, und die Leiste hat sie
     unten nicht: Wortmarke 83, Knopf 162, Rinne 32 macht 277 — bei 320 px Fensterbreite bleiben
     288. Mit Marke wären es 330, die Leiste stünde 42 px über dem Rand und zöge das Layoutfenster
     mit sich, samt fest sitzender Rücklaufleiste. Die Aussage geht nicht verloren, sie steht im
     ersten Absatz darunter noch einmal. */
  .ds-navbadge{display:none !important}
  /* Deutsche Komposita in Displaygrößen. „Unternehmensgegenstand" misst im Impressum 348 px und
     ist ein einziges Wort — bei 320 px Fensterbreite stand es 44 px über dem Rand und schob die
     ganze Seite mit. hyphens trennt nach den Regeln von lang="de-AT" am Fugenpunkt, das ist die
     saubere Trennung; overflow-wrap steht als Auffanglinie dahinter, falls kein Wörterbuch da
     ist. Beides nur unten — oben ist Platz, und Displayschrift will nicht getrennt werden. */
  h1,h2,h3,h4{hyphens:auto;overflow-wrap:break-word}
}
