/* =========================================================================
   PAQ8 – Plattformpräsentation
   Art Direction: Emons-Stilreferenz (entsättigt, sparsamer Akzent) auf dem
   warmen Savannengrund der Renders, mit den PAQ8-Kernfarben aus dem Small
   Brand Manual: Teal für Struktur, Orange ausschließlich für Handlung.
   Keine externen Requests. Keine Webfonts. Keine Tracker.
   ========================================================================= */

/* ---------- Schrift: ausschließlich Roboto, lokal ----------------------- */
/*
   Eine Datei: Roboto Variable, Achsen wght 100–900 und wdth 75–100.
   Damit kommen alle Gewichte UND die schmalen Schnitte aus derselben Quelle –
   die technischen Labels laufen über font-stretch, nicht über eine zweite
   Schrift. Keine externen Requests, kein Google-Fonts-CDN.
   Lizenz: SIL Open Font License 1.1, siehe assets/fonts/OFL.txt
*/

@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("../fonts/Roboto-Variable.ttf") format("truetype-variations"),
       url("../fonts/Roboto-Variable.ttf") format("truetype");
}

/* ---------- Tokens ------------------------------------------------------ */

:root {
  color-scheme: light;

  /* Flächen: weißer Grund, darauf zwei kühle Abstufungen. Der Grund war
     lange warmes Papier; weiß lässt Teal und Orange kräftiger stehen und
     nimmt der Seite den Prospektton. --paper-3 ist PAQ8 Light aus dem
     Brand Manual und trägt die erhöhten Flächen, --paper-2 die wenigen
     gefüllten Zeilen. */
  --paper:      #FFFFFF;
  --paper-2:    #ECEEF1;
  --paper-3:    #F4F6F8;   /* PAQ8 Light */
  --dark:       #1E232B;   /* PAQ8 Dark */
  --dark-2:     #22323A;   /* PAQ8 Slate */

  /* Schrift */
  --ink:        #1E232B;   /* PAQ8 Dark · 15,8:1 auf Weiß */
  --ink-2:      #4A555C;   /* kühl Richtung Slate · ≥6,6:1 */
  --ink-3:      #566169;   /* ≥5,5:1 auf allen drei hellen Flächen */
  --ink-inv:    #F4F6F8;   /* PAQ8 Light */
  --ink-inv-2:  #B8C2CA;   /* PAQ8 Bluegrey · 8,7:1 auf Dark */

  /* Linien */
  --line:       #DCE0E4;
  --line-soft:  #EDEFF2;
  --line-inv:   #33414A;

  /*
     PAQ8-Farbgewichtung laut Brand Manual: viel Ruhefläche, dunkle Typo,
     Teal für Marke und Struktur, Orange ausschließlich als CTA oder
     Highlight. Die Kontraste diktieren, wo welcher Ton liegen darf:

       Teal   auf Weiß 6,3:1 ✓   auf Dunkel 2,5:1 ✗
       Orange auf Weiß 2,9:1 ✗   als Fläche mit dunkler Typo 5,5:1 ✓
       Amber  auf Dunkel 7,6:1 ✓

     Deshalb: Teal trägt die Struktur auf hellem Grund, Orange ist die
     Handlungsfarbe als Fläche, Amber vertritt den Akzent im dunklen Band.
  */
  --accent:     #0F6B6D;   /* PAQ8 Teal · Marke und Struktur */
  --accent-inv: #FF9C42;   /* PAQ8 Amber · Akzent im dunklen Band */
  --cta:        #FF6A2C;   /* PAQ8 Orange · nur Handlung */
  --cta-hv:     #FF9C42;   /* PAQ8 Amber als Hover: heller statt dunkler,
                              sonst faellt der Kontrast zur dunklen Typo
                              von 5,5:1 auf 4,4:1 */
  --bluegrey:   #B8C2CA;

  /* Typo – ausschließlich Roboto. --mono ist kein zweiter Font, sondern
     dieselbe Schrift auf der schmalen Breitenachse (siehe .is-label). */
  --sans: "Roboto", sans-serif;
  --mono: "Roboto", sans-serif;

  /* Maß */
  --gut:   clamp(20px, 5vw, 64px);
  --stack: clamp(56px, 7vw, 112px);
  --radius: 3px;

  /* Bewegung */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur:  520ms;
}

/* ---------- Reset ------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.55;
  font-feature-settings: "kern" 1, "liga" 1;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }

/* Muss nach den Layout-Regeln greifen: display:grid auf einer Klasse
   überstimmt sonst das hidden-Attribut. */
[hidden] { display: none !important; }

::selection { background: var(--accent); color: var(--ink-inv); }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* ---------- Typo-Skala -------------------------------------------------- */

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.021em;
  line-height: 1.06;
  text-wrap: balance;
}

.t-display {
  font-size: clamp(38px, 7.4vw, 104px);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 0.95;
}

.t-h2 {
  font-size: clamp(28px, 4.2vw, 54px);
  letter-spacing: -0.028em;
  line-height: 1.04;
}

.t-h3 {
  font-size: clamp(20px, 2.2vw, 27px);
  letter-spacing: -0.018em;
  line-height: 1.16;
}

.t-lead {
  font-size: clamp(18px, 1.65vw, 22px);
  line-height: 1.48;
  color: var(--ink-2);
  max-width: 62ch;
  text-wrap: pretty;
}

p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }


.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.muted { color: var(--ink-2); }

/* Technische Labels und Zahlen: gleiche Schrift, schmale Breitenachse.
   Ersetzt den früheren Mono-Stack – bleibt damit in der Roboto-Familie. */
.lang button,
.svc__steps .n,
.svc__principle,
.matrix tbody th,
.matrix .r-principle th,
.matrix .r-principle td,
.gcard__k,
.ref__tag,
.reach__k,
.field__label,
.result__row--head,
.result__row .v,
.hero__note,
.mono {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
}

/* ---------- Layout ------------------------------------------------------ */

.wrap {
  width: min(1320px, 100%);
  margin-inline: auto;
  padding-inline: var(--gut);
}

section { position: relative; scroll-margin-top: 72px; }

.band {
  padding-block: var(--stack);
  border-top: 1px solid var(--line);
}
.band--dark {
  background: var(--dark);
  color: var(--ink-inv);
  border-top-color: var(--dark);
}
.band--dark .t-lead,
.band--dark .muted { color: var(--ink-inv-2); }

.head { max-width: 72ch; margin-bottom: clamp(30px, 3.4vw, 52px); }

/* ---------- Topbar ------------------------------------------------------ */

.topbar {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px var(--gut);
  /* Kein backdrop-filter: ueber dem bewegten Film muesste der Browser die
     Flaeche in jedem Frame neu weichzeichnen. */
  background: color-mix(in srgb, var(--paper) 95%, transparent);
  border-bottom: 1px solid transparent;
  transition: border-color 220ms var(--ease), background 220ms var(--ease);
}
.topbar[data-stuck="true"] { border-bottom-color: var(--line); }

/* ---------- Kopfzeile: zwei Marken ---------------------------------------

   Links das Angebot, rechts daneben der, fuer den es ist. Die Logos kommen
   aus dem Markenhandbuch und aus der Ausschreibung - als PNG, weil von
   keinem von beiden eine Vektorfassung vorliegt. Beide sind 84 px hoch
   hinterlegt und laufen im Kopf auf etwa ein Drittel davon; das reicht
   auch auf einem Schirm mit doppelter Punktdichte.
   -------------------------------------------------------------------- */

.brands {
  display: flex;
  align-items: center;
  gap: 13px;
  min-width: 0;
}
.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  flex: none;
}
.brand__logo {
  display: block;
  height: 25px;
  width: auto;
}
/* Die Optik entscheidet, nicht die Zahl: das HFR-Zeichen ragt ueber die
   Versalhoehe hinaus, bei gleicher Pixelhoehe wirkt die Wortmarke kleiner. */
.brand__client {
  display: block;
  height: 26px;
  width: auto;
  flex: none;
}
.brands__for {
  font-stretch: 86%;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  flex: none;
}
@media (max-width: 720px) {
  .brands { gap: 9px; }
  .brand__logo { height: 21px; }
  .brand__client { height: 23px; }
  .brands__for { display: none; }
}
/* Nicht ausblenden: das Logo des Kunden faellt nicht als Erstes weg,
   nur weil der Schirm schmal ist. Beide werden kleiner, dann passt es. */
@media (max-width: 480px) {
  .brands { gap: 8px; }
  .brand__logo { height: 18px; }
  .brand__client { height: 19px; }
}
/* Auf 320 px schnitt der Sprachumschalter das Kundenlogo um 31 px an.
   Gleiches Prinzip wie oben: beide Marken noch etwas kleiner, und der
   Umschalter gibt ein paar Pixel Polster ab - statt eine Marke zu opfern. */
@media (max-width: 370px) {
  .brands { gap: 7px; }
  .brand__logo { height: 15px; }
  .brand__client { height: 16px; }
  .lang button { padding: 6px 8px; font-size: 10px; letter-spacing: 0.06em; }
  .topbar { padding-inline: 14px; }
}

.topbar__right { display: flex; align-items: center; gap: 10px; }

/* Sprachumschalter */
.lang {
  display: flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px;
  background: var(--paper-3);
}
.lang button {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  padding: 6px 11px;
  border-radius: 999px;
  color: var(--ink-2);
  transition: background 180ms var(--ease), color 180ms var(--ease);
}
.lang button:hover { color: var(--ink); }
.lang button[aria-pressed="true"] {
  background: var(--ink);
  color: var(--paper);
}

/* ---------- Buttons ----------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 22px;
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--paper);
  text-decoration: none;
  font-weight: 500;
  font-size: 15.5px;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: transform 180ms var(--ease), background 180ms var(--ease),
              border-color 180ms var(--ease), color 180ms var(--ease);
}
.btn:hover { transform: translateY(-1px); background: var(--dark-2); }
.btn:active { transform: translateY(0); }

.btn--ghost {
  background: transparent;
  color: var(--ink);
}
.btn--ghost:hover { background: rgba(0,0,0,.05); }

/* Handlungsfarbe. Orange traegt dunkle Typo mit 5,5:1; Weiss darauf
   waere 2,9:1 und faellt durch. */
.btn--accent {
  background: var(--cta);
  border-color: var(--cta);
  color: var(--ink);
  font-weight: 600;
}
.btn--accent:hover { background: var(--cta-hv); border-color: var(--cta-hv); }

.band--dark .btn--ghost {
  color: var(--ink-inv);
  border-color: var(--line-inv);
}
.band--dark .btn--ghost:hover { background: rgba(255,255,255,.07); }

.btn .arrow { transition: transform 200ms var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

/* ---------- Die Bildmarke als Hintergrund -------------------------------

   Vier Kopien derselben Marke, jede mit eigener Groesse, Bahn und Dauer.
   Bewegt wird ausschliesslich transform und nichts sonst: das laeuft im
   Compositor und kostet den Rasterer nichts. Die erste Fassung animierte
   stroke-dashoffset an einer grossen SVG-Figur und riss dabei einzelne
   Frames auf 22 ms auf.

   Darueber liegt ein schwarzer Schleier. Er ist links dichter als rechts,
   damit die Schrift ihre Flaeche behaelt und die Marke trotzdem zu sehen
   bleibt.
   ---------------------------------------------------------------------- */

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  mask-image: linear-gradient(to bottom,
    transparent 0%, #000 8%, #000 78%, transparent 99%);
}
.mark {
  position: absolute;
  height: auto;
  will-change: transform;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

/* Die grosse liegt rechts und laeuft ueber den Rand hinaus - ein
   Ausschnitt von etwas Grossem wirkt, eine kleine vollstaendige Marke in
   der Mitte sieht nach Aufkleber aus. */
.mark--1 {
  width: min(1180px, 92vw);
  right: -16%;
  top: 50%;
  opacity: .2;
  animation-name: markA;
  animation-duration: 28s;
}
.mark--2 {
  width: min(760px, 62vw);
  left: -14%;
  top: 8%;
  opacity: .13;
  animation-name: markB;
  animation-duration: 37s;
}
.mark--3 {
  width: min(460px, 40vw);
  right: 22%;
  bottom: -10%;
  opacity: .17;
  animation-name: markC;
  animation-duration: 23s;
}
.mark--4 {
  width: min(300px, 26vw);
  left: 32%;
  top: 14%;
  opacity: .1;
  animation-name: markD;
  animation-duration: 44s;
}

@keyframes markA {
  from { transform: translate3d(0, -50%, 0) rotate(-3deg) scale(1); }
  to   { transform: translate3d(-4%, -54%, 0) rotate(2.5deg) scale(1.08); }
}
@keyframes markB {
  from { transform: translate3d(0, 0, 0) rotate(4deg) scale(1.05); }
  to   { transform: translate3d(7%, 9%, 0) rotate(-3deg) scale(.94); }
}
@keyframes markC {
  from { transform: translate3d(0, 0, 0) rotate(-8deg) scale(.96); }
  to   { transform: translate3d(-9%, -12%, 0) rotate(6deg) scale(1.12); }
}
@keyframes markD {
  from { transform: translate3d(0, 0, 0) rotate(10deg) scale(1); }
  to   { transform: translate3d(14%, 18%, 0) rotate(-12deg) scale(1.2); }
}

/* .bgmarks ist der Haken fuer das Anhalten: jeder Markenhintergrund
   traegt sie, site.js beobachtet sie alle. */
.bgmarks { /* Verhalten, keine Darstellung */ }

/* Ausserhalb des Blickfelds steht alles still: der Film weiter unten
   braucht sein Frame-Budget fuer sich. */
[data-run="false"] .mark { animation-play-state: paused; }

/* ---------- Die Kreisbahnen ---------------------------------------------

   Dieselbe Figur wie die Bildmarke, neun Mal ineinander. Sie liegen still;
   bewegt wird nur der Kasten, in dem sie stecken - eine Transformation auf
   einem <div> laeuft im Compositor, dieselbe Transformation auf einer
   SVG-Gruppe zwingt die ganze Zeichnung in jedem Frame neu durch den
   Rasterer. Die erste Fassung riss damit Frames auf 22 ms auf.

   Zwei Laeufer bewegen sich wirklich am Pfad entlang (stroke-dashoffset).
   Sie sitzen bewusst auf den beiden innersten, also kuerzesten Bahnen und
   in einer eigenen Zeichnung - nur deren Flaeche wird neu gezeichnet.
   -------------------------------------------------------------------- */

.rings {
  position: absolute;
  top: 50%;
  right: -16%;
  width: min(1420px, 104vw);
  aspect-ratio: 2 / 1;
  transform: translateY(-50%);
  will-change: transform;
  animation: ringsDrift 34s ease-in-out infinite alternate;
}
.rings svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
/* Die bewegte Zeichnung liegt ueber den stillen Ringen und ist die
   einzige, die neu gezeichnet werden muss. */
.rings__live { z-index: 1; }

.ring {
  fill: none;
  transform: scale(var(--s));
  transform-origin: 500px 250px;
  /* Die Strichstaerke rechnet die Skalierung wieder heraus, sonst waere
     der innerste Ring ein Haarstrich und der aeussere ein Balken. */
  stroke: var(--line);
  stroke-width: calc(1.6 / var(--s));
}
/* Statt eines wandernden Strichmusters laufen Punkte am Pfad entlang.
   stroke-dashoffset zwingt den Rasterer, den ganzen Pfad neu zu zeichnen -
   gemessen ein Frame von 23,7 ms je 240. Ein Punkt dirtyt nur seine eigene
   Flaeche. Der Schweif sind drei kleinere Punkte mit Vorlauf. */
.pulse {
  transform: scale(var(--s));
  transform-origin: 500px 250px;
}
.pulse__c {
  fill: var(--accent);
  offset-path: path("M500 250C500 145 425 95 330 95 215 95 140 165 140 250 140 335 215 405 330 405 425 405 500 355 500 250 500 145 575 95 670 95 785 95 860 165 860 250 860 335 785 405 670 405 575 405 500 355 500 250Z");
  offset-rotate: 0deg;
  opacity: calc(1 - var(--i) * 0.22);
  animation: pulseRun var(--dur) linear infinite;
  animation-delay: calc(var(--i) * var(--dur) * -0.0035);
}
.pulse--warm .pulse__c { fill: var(--cta); }

@keyframes pulseRun { to { offset-distance: 100%; } }

.hero__bg[data-run="false"] .pulse__c { animation-play-state: paused; }

@keyframes ringsDrift {
  from { transform: translateY(-50%) rotate(0deg) scale(1); }
  to   { transform: translateY(-53%) rotate(-4deg) scale(1.07); }
}

.hero__bg[data-run="false"] .rings { animation-play-state: paused; }

/* Die untere Zeile steht auf Papier, sonst laeuft die Figur unter dem
   Text durch und beides wird unleserlich. */
.hero__case { background: var(--paper); }

@media (max-width: 860px) {
  .rings { right: -30%; width: 140vw; }
}

.hero__veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(100deg,
    var(--paper) 0%,
    var(--paper) 22%,
    color-mix(in srgb, var(--paper) 74%, transparent) 40%,
    color-mix(in srgb, var(--paper) 28%, transparent) 62%,
    color-mix(in srgb, var(--paper) 6%, transparent) 82%,
    transparent 100%);
}


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

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

   Der Hero laeuft auf einer Uhr, nicht am Scroll: er steht beim Laden
   schon im Bild, eine Scrollauslösung waere vorbei, bevor jemand hinsieht.
   Die Reihenfolge ist die Aussage - erst der Satz, dann das Versprechen,
   dann die Flaeche, die in drei zerfaellt, zuletzt der Fall.

   Alle Verzoegerungen an einer Stelle, damit sich die Abfolge lesen laesst:

     0 ms   Eine Plattform fuer operative Prozesse
     160    PLANEN.            (dann alle 110 ms das naechste Wort)
     760    die beiden Schaltflaechen
     900    die Flaeche waechst aus der Mitte auf
    1420    sie faellt in drei
    1520    die drei Namen, versetzt
    1980    der Fall in Boke
   ---------------------------------------------------------------------- */

.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: min(92svh, 940px);
  overflow: hidden;
}

/* Der Hintergrund hat einen eigenen Kasten, der genau dort endet, wo die
   Flaeche beginnt. Vorher lief er ueber die ganze Sektion und wurde vom
   Streifen hart abgeschnitten - die Figur brach mitten im Bogen ab und das
   sah aus wie ein Fehler. Die Maske loest sie stattdessen nach oben und
   unten auf, damit auch die Kaesten-Kante nicht zu sehen ist. */
.hero__stage {
  position: relative;
  flex: 1;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  padding-top: clamp(48px, 7vw, 96px);
}

.hero__inner {
  position: relative;
  z-index: 2;
  width: min(1320px, 100%);
  margin-inline: auto;
  padding-inline: var(--gut);
  margin-bottom: clamp(40px, 6vw, 76px);
  flex: none;
}

/* Der Satz ueber dem Supersign. Er nennt die Sache beim Namen, bevor die
   vier Verben sie in Versalien behaupten. */
.hero__intro {
  margin: 0 0 clamp(18px, 2vw, 26px);
  font-size: clamp(17px, 1.6vw, 21px);
  color: var(--ink-2);
  opacity: 0;
  transform: translateY(10px);
  animation: heroIn 700ms var(--ease) 0ms forwards;
}

.supersign {
  display: block;
  font-size: clamp(33px, 4.5vw, 74px);
  line-height: 0.97;
  letter-spacing: -0.038em;
  margin: 0;
}
.supersign span {
  display: block;
  opacity: 0;
  transform: translateY(0.35em);
  animation: signIn 900ms var(--ease) forwards;
}
.supersign span:nth-child(1) { animation-delay: 160ms; }
.supersign span:nth-child(2) { animation-delay: 270ms; }
.supersign span:nth-child(3) { animation-delay: 380ms; }
.supersign span:nth-child(4) { animation-delay: 490ms; }
.supersign span:last-child { color: var(--accent); }

@keyframes signIn { to { opacity: 1; transform: translateY(0); } }
@keyframes heroIn { to { opacity: 1; transform: none; } }

.hero__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
  margin-top: 34px;
  opacity: 0;
  transform: translateY(10px);
  animation: heroIn 700ms var(--ease) 760ms forwards;
}

.hero__note {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink-2);
  text-transform: uppercase;
}

/* ---------- Die Flaeche, die in drei zerfaellt -------------------------

   Frueher machten das ein 1px-Grid-Abstand und ein durchscheinender
   Hintergrund. Das laesst sich nicht animieren: eine Linie, die von 0 auf
   1 px waechst, ist keine Bewegung. Also liegen die beiden Trennlinien
   jetzt als eigene Elemente darueber und wachsen aus der Mitte auf.
   ---------------------------------------------------------------------- */

.surface {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  background: var(--paper-3);
}
/* Ober- und Unterkante wachsen aus der Mitte nach aussen. */
.surface::before,
.surface::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  animation: lineX 720ms var(--ease) 900ms forwards;
}
.surface::before { top: 0; }
.surface::after { bottom: 0; }

.surface__split {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--at);
  width: 1px;
  background: var(--line);
  transform: scaleY(0);
  animation: lineY 560ms var(--ease) 1420ms forwards;
}

@keyframes lineX { to { transform: scaleX(1); } }
@keyframes lineY { to { transform: scaleY(1); } }

.surface__cell {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 22px var(--gut) 24px;
  opacity: 0;
  transform: translateY(8px);
  animation: heroIn 640ms var(--ease) forwards;
}
.surface__cell:nth-child(1) { animation-delay: 1520ms; }
.surface__cell:nth-child(2) { animation-delay: 1620ms; }
.surface__cell:nth-child(3) { animation-delay: 1720ms; }

/* Die Randzellen ziehen ihren Text auf das Seitenmass, damit die Flaeche
   randlos laufen kann und der Inhalt trotzdem in der Spalte steht. */
.surface__cell:nth-child(1) { padding-left: max(var(--gut), calc((100vw - 1320px) / 2 + var(--gut))); }
.surface__cell:nth-child(3) { padding-right: max(var(--gut), calc((100vw - 1320px) / 2 + var(--gut))); }

.surface__name {
  font-size: clamp(15px, 1.5vw, 18px);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.surface__name em {
  font-style: normal;
  font-weight: 400;
  color: var(--accent);
}
.surface__promise {
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ink-3);
}

/* ---------- Der Fall unter der Flaeche ---------------------------------
   Der Hero verspricht eine Plattform; diese Zeile sagt, wo sie zuerst
   antritt. Ohne sie bliebe der Hero eine Behauptung ueber Software. */

.hero__case {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 22px;
  width: min(1320px, 100%);
  margin-inline: auto;
  padding: clamp(20px, 2.4vw, 30px) var(--gut) 0;
  opacity: 0;
  transform: translateY(10px);
  animation: heroIn 700ms var(--ease) 1980ms forwards;
}
.hero__case p {
  margin: 0;
  max-width: 68ch;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-2);
}
.hero__jump {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
  flex: none;
}
.hero__jump:hover { color: var(--ink); }
.hero__jump-arrow { transition: transform 200ms var(--ease); }
.hero__jump:hover .hero__jump-arrow { transform: translateY(2px); }

@media (max-width: 760px) {
  /* Der Hero ist auf dem Schirm eine Buehne: der Text steht unten, darueber
     laeuft die Animation. Auf einem Telefon wird aus der Buehne eine
     Leerstelle - ueber dem Text standen 353 px Hintergrund, und der Leser
     scrollt an der Aussage vorbei, bevor sie ihn erreicht. Also kuerzer:
     der Text rueckt nach oben, die drei Services kommen mit und stehen
     zusammen mit der Aussage im ersten Bild. */
  .hero { min-height: min(70svh, 620px); }
  .hero__stage { padding-top: clamp(30px, 6vw, 60px); }
  .hero__inner { margin-bottom: clamp(26px, 4vw, 40px); }

  /* Die drei Services bleiben nebeneinander. Sie sind ein Dreiklang - die
     Flaeche faellt oben sichtbar in genau diese drei Teile. Untereinander
     liest sich das als Liste, und die Teilung verliert ihren Sinn.
     Also enger gesetzt: weniger Polster, kleinere Schrift, Trennlinien
     statt Fugen. */
  .surface { grid-template-columns: repeat(3, 1fr); }
  .surface__split { display: none; }
  .surface__cell { padding: 18px 10px 20px; gap: 3px; }
  .surface__cell:nth-child(1) { padding-left: 14px; }
  .surface__cell:nth-child(3) { padding-right: 14px; }
  .surface__cell + .surface__cell { border-left: 1px solid var(--line); }
  .surface__name { font-size: 13px; }
  .surface__promise { font-size: 11.5px; line-height: 1.32; }
}


/* ---------- Die Reise --------------------------------------------------- */

.journey { position: relative; }
.journey__intro { padding-block: var(--stack) clamp(20px, 2.4vw, 36px); }
.journey__tail { padding-block: clamp(48px, 6vw, 80px) var(--stack); }

/* Angeankert wie der Film: der Bereich bleibt stehen, waehrend der Strahl
   laeuft. Vorher lief die Fuellung am Scrollstand mit und war erst fertig,
   wenn der Abschnitt schon halb aus dem Bild war. */
.brk-track { position: relative; height: 150svh; }
/* Nur so hoch wie der Inhalt. Auf volle Bildhoehe zentriert blieb darunter
   eine halbe Seite leer; so faehrt stattdessen die Einladung von unten
   ins Bild, waehrend der Strahl noch laeuft. */
.brk-sticky {
  position: sticky;
  top: 88px;
  display: flex;
  align-items: flex-start;
}
.brk { width: 100%; }

@media (max-width: 900px) {
  /* Auf kurzen Schirmen passt der Block nicht in eine Bildhoehe - dann
     lieber mitlaufen lassen als abschneiden. */
  .brk-track { height: auto; }
  .brk-sticky { position: static; height: auto; padding-top: 0; }
}

/* ---------- Die vier Brueche als Zeitstrahl ------------------------------

   Ueberschrift und Einleitung stehen mittig ueber der ganzen Breite, die
   vier Stationen darunter nebeneinander. Die Fuellung des Strahls folgt
   dem Scrollstand: was man gerade liest, ist auch schon passiert. Das ist
   dieselbe Bewegungsrichtung wie die Kette selbst.
   ---------------------------------------------------------------------- */

.brk__h {
  margin: 0 auto clamp(26px, 3vw, 40px);
  max-width: 22ch;
  text-align: center;
  font-size: clamp(30px, 4.6vw, 72px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.032em;
}

.brk__h em { font-style: normal; color: var(--accent); }

.brk__lead {
  margin: 0 auto;
  max-width: 78ch;
  text-align: center;
  font-size: clamp(17px, 1.55vw, 21px);
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
}

.tl {
  position: relative;
  margin-top: clamp(52px, 6.5vw, 96px);
}

/* Der Strahl liegt auf Hoehe der Punkte und laeuft bis an den rechten
   Rand: die Kette hoert hier nicht auf, sie wird nur nicht mehr gezeigt. */
.tl__rail {
  position: absolute;
  left: 21px;
  right: 0;
  top: 20px;
  height: 2px;
  background: var(--line);
  overflow: hidden;
}
.tl__fill {
  display: block;
  height: 100%;
  /* Teal, nicht Orange: Orange heisst auf dieser Seite "das kann man
     bedienen" - die Punkte hier kann man nicht. Und Orange auf Papier
     kaeme als Text auf 2,4:1. */
  background: var(--accent);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  will-change: transform;
}

.tl__stops {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(18px, 2.6vw, 40px);
}
.tl__stop {
  position: relative;
  display: grid;
  gap: 6px;
  padding-top: 62px;
  padding-right: clamp(10px, 1.6vw, 26px);
}

/* Das Zeichen sitzt selbst auf dem Strahl. Eine Ziffer haette nur
   gezaehlt; das Zeichen sagt, worum es geht, bevor man liest. */
.tl__dot {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 2px solid var(--line);
  background: var(--paper);
  /* Der Strahl soll am Kreis abbrechen, nicht dahinter durchlaufen. Der
     Ring aus Papier haelt ihn auf Abstand - eine deckende Flaeche allein
     laesst ihn optisch am Rand weiterlaufen. */
  box-shadow: 0 0 0 7px var(--paper);
  color: var(--ink-3);
  display: grid;
  place-items: center;
  transition: border-color 260ms var(--ease), background 260ms var(--ease),
              color 260ms var(--ease), transform 260ms var(--ease);
}
.tl__dot svg { width: 21px; height: 21px; display: block; }
.tl__stop[data-on="true"] .tl__dot {
  border-color: var(--accent);
  background: var(--accent);
  color: #fff;
}

.tl__t {
  font-size: clamp(16px, 1.5vw, 19px);
  font-weight: 600;
  letter-spacing: -0.016em;
  line-height: 1.2;
  color: var(--ink);
}
.tl__d {
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--ink-2);
}

/* Die Station bleibt lesbar, bevor der Strahl sie erreicht - sie tritt
   nur naeher heran. Ein Text, der erst bei Kontakt erscheint, waere auf
   kurzen Schirmen nie zu sehen. */
.js .tl__stop { opacity: .5; transform: translateY(6px); transition: opacity 420ms var(--ease), transform 420ms var(--ease); }
.js .tl__stop[data-on="true"] { opacity: 1; transform: none; }

@media (max-width: 900px) {
  .tl__stops { grid-template-columns: repeat(2, 1fr); gap: 34px 24px; }
  .tl__rail { display: none; }
  .tl__stop { padding-top: 56px; }
}
/* Untereinander braucht der Zeitstrahl eine senkrechte Achse. Ohne sie
   sind die vier Brueche nur eine Liste mit Zeichen davor - und genau das
   Verbindende, das der Abschnitt behauptet, fehlt. Dieselbe Fuellung,
   dieselbe Farbe, nur um 90 Grad gedreht: --p setzt site.js unveraendert. */
@media (max-width: 620px) {
  .tl__stops { grid-template-columns: 1fr; gap: 0; }
  .tl__rail {
    display: block;
    left: 20px;
    right: auto;
    top: 21px;
    bottom: 34px;
    width: 2px;
    height: auto;
  }
  .tl__fill {
    width: 100%;
    transform: scaleY(var(--p, 0));
    transform-origin: center top;
  }
  .tl__stop {
    padding: 0 0 34px 62px;
    min-height: 42px;
  }
  .tl__stop:last-child { padding-bottom: 0; }
  .brk__h { max-width: none; }
}


/* ---------- Die Einladung -----------------------------------------------
   Sie steht zwischen Text und Bild und sagt, dass das Bild darunter
   bedienbar ist. Ohne sie haelt man die Masken fuer Dekoration und
   scrollt daran vorbei. */

.tryout {
  display: flex;
  align-items: center;
  gap: clamp(24px, 4vw, 56px);
  margin-top: clamp(16px, 2vw, 32px);
  padding: clamp(26px, 3vw, 38px) clamp(26px, 3vw, 40px);
  background: var(--paper-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--cta);
  border-radius: var(--radius);
}
.tryout__text { min-width: 0; }

/* Schlanke Ausfuehrung fuer den zweiten Hinweis am Bericht: gleiche Familie,
   weniger Gewicht - der erste soll der lautere bleiben. */
.tryout--slim {
  gap: clamp(18px, 2.4vw, 34px);
  padding: clamp(18px, 2vw, 24px) clamp(20px, 2.4vw, 28px);
  margin-top: clamp(20px, 2.4vw, 34px);
}
.tryout--slim .tryout__t { font-size: clamp(17px, 1.5vw, 20px); }
.tryout--slim .tryout__d { margin-top: 4px; font-size: 15px; }
/* Kein Bildpunkt, sondern ein Zeiger auf einer Flaeche: ruhiger Ring in der
   Linienfarbe, Zeichen in Teal wie die uebrigen Sinnbilder der Seite. Der
   orange Rand links bleibt - Orange ist auf dieser Seite die Handlungsfarbe,
   das Pluszeichen dagegen gehoert allein den Punkten im Bild. */
.tryout__icon {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 2px solid var(--line);
  background: var(--paper);
  color: var(--accent);
  display: grid;
  place-items: center;
}
.tryout__icon svg { width: 21px; height: 21px; display: block; }

/* Derselbe Punkt wie im Bild darunter. Er sagt ohne Worte, wonach man
   sucht - der Satz allein erklaert es, das Zeichen zeigt es. */
.tryout__mark {
  position: relative;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--cta);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .2);
  display: grid;
  place-items: center;
}
.tryout__mark::before,
.tryout__mark::after {
  content: "";
  position: absolute;
  background: var(--ink);
  border-radius: 1px;
}
.tryout__mark::before { width: 14px; height: 2px; }
.tryout__mark::after  { width: 2px; height: 14px; }
.tryout__mark i {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 2px solid var(--cta);
  opacity: 0;
  animation: hsPulse 2.8s var(--ease) infinite;
}
.tryout__t {
  margin: 0 0 10px;
  font-size: clamp(20px, 2.1vw, 27px);
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.1;
}
.tryout__d {
  margin: 0;
  max-width: 76ch;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--ink-2);
}

/* Drei Winkel, die nacheinander aufleuchten und nach unten zeigen. */
.tryout__go {
  flex: none;
  display: grid;
  gap: 3px;
  margin-left: auto;
}
.tryout__chev {
  display: block;
  width: 26px;
  height: 26px;
  border-right: 2px solid var(--cta);
  border-bottom: 2px solid var(--cta);
  transform: rotate(45deg);
  opacity: .18;
  animation: chev 1900ms var(--ease) infinite;
}
.tryout__chev:nth-child(2) { animation-delay: 190ms; }
.tryout__chev:nth-child(3) { animation-delay: 380ms; }

@keyframes chev {
  0%, 60%, 100% { opacity: .18; }
  30%           { opacity: 1; }
}

@media (max-width: 900px) {
  .brk__grid { grid-template-columns: 1fr; }
  .tryout { flex-direction: column; align-items: flex-start; gap: 22px; margin-top: clamp(40px, 8vw, 64px); }
  /* Nebeneinander lesen sich drei Winkel als Zickzack, nicht als "weiter
     unten". Einer reicht: er zeigt nach unten und spart Hoehe. */
  .tryout__go { margin-left: 0; }
  .tryout__chev:nth-child(n + 2) { display: none; }
}


/* ---------- Der Film: drei Bilder, ein Raum ------------------------------

   Mine, Landschaft und Hafen liegen uebereinander in EINEM klebenden Rahmen
   und werden am Scroll ineinander geblendet. Kein Nacheinander von Bloecken.

   Kein scroll-snap: Einrasten und direkt danach festhalten liest sich als
   Haengenbleiben; die Haltestrecke traegt den Abschnitt allein.
   ---------------------------------------------------------------------- */

.film { position: relative; height: 260svh; }
.film__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  padding-top: 56px;
}
.film__inner { width: 100%; }

.film__head {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 3;
  display: grid;
  align-content: start;
  padding: clamp(20px, 3vw, 44px) clamp(22px, 3.2vw, 52px);
  pointer-events: none;
}
/* Der Verlauf beginnt bei 100 % Deckung. Bei 88 % blieb am Rahmenrand eine
   Stufe gegen die Seitenflaeche stehen - das war die sichtbare Kante. */
.film__scrim {
  position: absolute;
  inset: 0 0 auto;
  height: 46%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to bottom,
    var(--paper) 0%,
    color-mix(in srgb, var(--paper) 92%, transparent) 12%,
    color-mix(in srgb, var(--paper) 72%, transparent) 38%,
    color-mix(in srgb, var(--paper) 26%, transparent) 70%,
    transparent 100%);
}

.cue {
  grid-area: 1 / 1;
  max-width: 54ch;
  opacity: var(--o, 0);
  transform: translateY(var(--cue-off, 0px));
  will-change: opacity, transform;
}
.cue__t {
  font-size: clamp(23px, 2.6vw, 34px);
  font-weight: 600;
  letter-spacing: -0.026em;
  line-height: 1.1;
  margin-bottom: 10px;
}
.cue__d { font-size: clamp(15px, 1.35vw, 18px); line-height: 1.45; color: var(--ink); max-width: 46ch; }

/* Der Rahmen ist 16:9 und beschneidet nichts. Sein Hintergrund muss
   derselbe sein wie der der Seite - mit --paper-2 zeichnete er sich als
   Tonstufe ab. 100% und nicht 100vw: vw zaehlt die Scrollleiste mit. */
.film__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  width: min(100%, calc((100svh - 72px) * 16 / 9));
  margin-inline: auto;
  overflow: hidden;
  background: var(--paper);
}
/* Die untere Kante aufloesen. */
.film__frame::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 16%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to top,
    var(--paper) 0%,
    color-mix(in srgb, var(--paper) 55%, transparent) 34%,
    transparent 100%);
}

.layer { position: absolute; inset: 0; z-index: 1; opacity: var(--o, 0); will-change: opacity; }
.layer__media { width: 100%; height: 100%; object-fit: contain; }
.layer__img {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transform-origin: 50% 50%;
  transform: translate(-50%, -50%)
             translate(var(--tx, 0%), var(--ty, 0%))
             scale(var(--ts, 2.4));
  will-change: transform;
}
/* Drei bewusste Entscheidungen, die zusammen 6 ms pro Frame gespart haben:
   die Ebene liegt in Viertelaufloesung vor und wird vierfach vergroessert,
   die Unschaerfe ist fest und wird nicht animiert, und ihre Transformation
   ist eingefroren - eine maskierte, weichgezeichnete Ebene wird bei jeder
   Transformaenderung neu gerastert. */
.layer__img--blur {
  width: 25%;
  height: 25%;
  transform: translate(-50%, -50%) scale(4);
  filter: blur(6px);
  opacity: var(--bo, 0);
  mask-image: radial-gradient(ellipse 58% 58% at 50% 50%,
    rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, .7) 70%, rgba(0, 0, 0, 1) 100%);
  will-change: opacity;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Bedienpunkte im Bild ---------------------------------------- */

.hotspots {
  position: absolute;
  inset: 0;
  z-index: 4;
  opacity: var(--o, 0);
  pointer-events: none;
  /* Keine Transition: film() setzt den Wert ohnehin in jedem Frame, eine
     zusaetzliche Ueberblendung wuerde nur hinterherhinken. */
}
.hotspots[data-active="true"] { pointer-events: none; }
.hotspots[data-active="true"] .hotspot,
.hotspots[data-active="true"] .hsheet { pointer-events: auto; }

.hotspot {
  position: absolute;
  z-index: 1;
  left: var(--x, 50%);
  top: var(--y, 50%);
  width: 34px;
  height: 34px;
  transform: translate(-50%, -50%);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--cta);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: opacity 160ms var(--ease), transform 180ms var(--ease), background 180ms var(--ease);
}
/* Netz fuer den Fall, dass ein Punkt doch unter einer Maske laege. */
.hotspot[data-covered="true"] { opacity: 0; pointer-events: none; }
.hotspot:hover { transform: translate(-50%, -50%) scale(1.12); }
.hotspot[data-covered="true"]:hover { transform: translate(-50%, -50%); }
.hotspot:active { transform: translate(-50%, -50%) scale(1.02); }

.hotspot__plus,
.hotspot__plus::before { content: ""; position: absolute; background: var(--ink); border-radius: 1px; }
.hotspot__plus { width: 14px; height: 2px; transition: transform 220ms var(--ease); }
.hotspot__plus::before { width: 2px; height: 14px; left: 6px; top: -6px; }
.hotspot[aria-expanded="true"] .hotspot__plus { transform: rotate(45deg); }

.hotspot__ring {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 2px solid var(--cta);
  opacity: 0;
  animation: hsPulse 2.8s var(--ease) infinite;
}
.hotspot[aria-expanded="true"] .hotspot__ring { animation: none; opacity: 0; }

@keyframes hsPulse {
  0%   { transform: scale(.72); opacity: .7; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* ---------- Die Masken --------------------------------------------------
   Ueber den Punkten: die DOM-Reihenfolge allein wuerde den zweiten Punkt
   vor die erste Maske stellen. Der Wechsel ist eine Ueberblendung, kein
   Schnitt - die abgehende Maske faehrt auf opacity 0 und wird erst danach
   aus dem Baum genommen. */

.hsheet {
  position: absolute;
  z-index: 2;
  /* Startwerte; die genaue Lage rechnet site.js, damit die Maske im
     Rahmen bleibt. */
  left: 0;
  top: 0;
  width: 300px;
  max-width: calc(100% - 24px);
  max-height: calc(100% - 24px);
  overflow-y: auto;
  /* Seitwaerts wird nie gescrollt. Kommt doch einmal etwas zu breit
     herein, soll es abgeschnitten werden statt eine Leiste zu ziehen. */
  overflow-x: clip;
  background: var(--paper-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .08), 0 18px 44px rgba(0, 0, 0, .18);
  padding: 18px;
  opacity: 0;
  transform: translateY(8px) scale(.985);
  transform-origin: 50% 0;
  pointer-events: none;
  transition: opacity 240ms var(--ease), transform 240ms var(--ease);
  will-change: opacity, transform;
}
.hsheet[data-open="true"] { opacity: 1; transform: none; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .hsheet { transition: none; } }

.hsheet__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}
.hsheet__kicker {
  display: block;
  font-stretch: 86%;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 4px;
}
.hsheet__title { font-size: 18px; font-weight: 600; letter-spacing: -0.02em; }
.hsheet__x {
  flex: none;
  width: 30px;
  height: 30px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink-2);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.hsheet__x:hover { background: rgba(0, 0, 0, .05); color: var(--ink); }

.hsfield { margin-bottom: 14px; }
.hsfield__label {
  display: block;
  font-stretch: 86%;
  font-size: 10.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 9px;
}

/* Das Plus ist deutlich groesser als das Minus: Hochzaehlen ist die Geste,
   die im Feld hundertfach gemacht wird, Korrigieren die Ausnahme. */
.counter { display: flex; align-items: center; gap: 12px; }
.counter__btn {
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  display: grid;
  place-items: center;
  line-height: 1;
  transition: background 150ms var(--ease), transform 120ms var(--ease);
  flex: none;
}
.counter__btn:active { transform: translateY(1px); }
.counter__btn--minus { width: 38px; height: 38px; font-size: 19px; }
.counter__btn--minus:hover { background: rgba(0, 0, 0, .06); }
.counter__btn--plus {
  width: 62px;
  height: 62px;
  font-size: 30px;
  font-weight: 500;
  background: var(--cta);
  border-color: var(--cta);
}
.counter__btn--plus:hover { background: var(--cta-hv); border-color: var(--cta-hv); }
.counter__btn[disabled] { opacity: .35; cursor: not-allowed; transform: none; }
.counter__value {
  font-size: 34px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  min-width: 2ch;
  text-align: center;
}

.hsflag {
  display: inline-block;
  margin-top: 12px;
  font-size: 13px;
  line-height: 1.3;
  padding: 5px 9px;
  border-radius: 2px;
  border: 1px solid transparent;
}
.hsflag[data-state="ok"]  { color: var(--accent); border-color: var(--line); }
.hsflag[data-state="out"] { color: var(--ink); background: var(--accent-inv); }
.hsflag[data-state="err"] { color: var(--ink); background: var(--cta); font-weight: 600; }

.stepper { display: flex; align-items: center; gap: 10px; }
.stepper__btn {
  width: 34px;
  height: 34px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  color: var(--ink);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.stepper__btn:hover { border-color: var(--ink-3); }
.stepper__btn[disabled] { opacity: .35; cursor: not-allowed; }
.stepper__value {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 18px;
  font-weight: 500;
  min-width: 4.5ch;
  text-align: center;
}

.calc {
  margin: 12px 0 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--ink-3);
}
.calc b {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  color: var(--ink);
}

/* Automatisch vergebene Nummer. Kein Eingabefeld - das ist der Punkt. */
.autono {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
}
.autono b {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 19px;
  letter-spacing: 0.06em;
}
.autono span { font-size: 12.5px; color: var(--ink-3); }

/* Gegenueberstellung zweier Zahlen. Keine Tabelle mit Rahmen - die Werte
   sollen sich lesen lassen wie eine Abrechnungszeile. */
.ledger {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0;
}
.ledger dt {
  padding: 9px 0;
  font-size: 12.5px;
  color: var(--ink-3);
  border-top: 1px solid var(--line-soft);
}
.ledger dd {
  margin: 0;
  padding: 9px 0;
  text-align: right;
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  color: var(--ink);
  border-top: 1px solid var(--line-soft);
}
.ledger dt:first-of-type,
.ledger dt:first-of-type + dd { border-top: 0; padding-top: 0; }
/* Die letzte Zeile ist die Differenz - sie traegt die Aussage. */
.ledger dt:last-of-type,
.ledger dd:last-of-type {
  border-top-width: 2px;
  border-top-color: var(--line);
  color: var(--ink);
}

/* Angebotsschalter im Panel. Kein Formular, ein Hinweis mit Haken. */
.sign {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  font-size: 13.5px;
  color: var(--ink);
}
.sign input {
  width: 17px;
  height: 17px;
  flex: none;
  accent-color: var(--accent);
  cursor: pointer;
}
.sign:hover { color: var(--accent); }

/* Unterschriftenfeld. Die Linie ist die Schreiblinie, darauf laeuft die
   Unterschrift auf. */
.sigpad {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 150ms var(--ease);
}
.sigpad:hover { border-color: var(--ink-3); }
.sigpad[aria-pressed="true"] { cursor: default; border-color: var(--accent); }
.sigpad::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 16px;
  height: 1px;
  background: var(--line);
}
/* --len misst site.js mit getTotalLength(); ohne das waere die Laenge
   geraten und der Strich liefe zu frueh oder zu spaet aus. */
.sigpad__ink {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 260 / 64;
  stroke: var(--ink);
  stroke-width: 2.2;
  stroke-dasharray: var(--len, 900);
  stroke-dashoffset: var(--len, 900);
}
.sigpad[aria-pressed="true"] .sigpad__ink {
  animation: sigWrite 1500ms cubic-bezier(.45, .05, .3, 1) forwards;
}
@keyframes sigWrite { to { stroke-dashoffset: 0; } }

.sigpad__hint {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 13px;
  color: var(--ink-3);
  transition: opacity 200ms var(--ease);
}
.sigpad[aria-pressed="true"] .sigpad__hint { opacity: 0; }

.sigclear {
  margin-top: 8px;
  border: 0;
  background: transparent;
  padding: 2px 0;
  font-size: 12.5px;
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.sigclear:hover { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .sigpad[aria-pressed="true"] .sigpad__ink { animation: none; stroke-dashoffset: 0; }
}

.linked { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.linked b { font-stretch: 86%; font-size: 15px; letter-spacing: 0.08em; }
.linked span { font-size: 12.5px; color: var(--ink-3); }

/* Drei Kennzeichen nebeneinander statt untereinander: das spart 94 px
   Hoehe und haelt die Maske unter der Beschriftung. min-width: 0, weil
   ein Grid-Kind von sich aus nicht unter seinen Inhalt schrumpft. */
.plates { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.plate {
  font-stretch: 86%;
  font-size: 12.5px;
  letter-spacing: 0.03em;
  text-align: center;
  padding: 9px 2px;
  min-width: 0;
  white-space: nowrap;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 150ms var(--ease), background 150ms var(--ease);
}
.plate:hover { border-color: var(--ink-3); }
.plate[aria-checked="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

.seg--w button { font-size: 13px; padding: 9px 6px; }
.seg--w button[aria-checked="true"] { background: var(--ink); color: var(--paper); }

.hsnote { margin-top: 9px; font-size: 13px; line-height: 1.4; color: var(--ink-2); }
.hsheet__foot {
  margin: 0;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-3);
}

@media (max-width: 860px) {
  .film { height: 200svh; }
  .film__head { min-height: 152px; }
}

/* ---------- Die drei Services ------------------------------------------- */

.platform {
  display: grid;
  gap: 2px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 860px) { .platform { grid-template-columns: 1fr; } }

.svc {
  background: var(--paper-3);
  padding: clamp(26px, 3vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 100%;
  position: relative;
  transition: background 260ms var(--ease);
}
.svc:hover { background: var(--paper-3); }
.svc__name {
  font-size: clamp(25px, 2.6vw, 34px);
  font-weight: 700;
  letter-spacing: -0.032em;
  line-height: 1;
}
.svc__name em { font-style: normal; color: var(--ink-3); font-weight: 400; }
.svc__promise {
  font-size: 17.5px;
  font-weight: 500;
  letter-spacing: -0.014em;
  color: var(--ink);
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line-soft);
}
.svc__steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; flex: 1; }
.svc__steps li { display: grid; grid-template-columns: 26px 1fr; gap: 12px; }
.svc__steps .n {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  padding-top: 4px;
  letter-spacing: 0.06em;
}
.svc__steps b {
  display: block;
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 2px;
}
.svc__steps span.d { font-size: 15px; color: var(--ink-2); line-height: 1.42; }
.svc__principle {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
}

/* ---------- Wer wir sind ------------------------------------------------

   Zwei Fragen, zwei Antworten, nebeneinander. Die Stelle steht zwischen
   dem Preis und den Referenzen: wer bis hierher gelesen hat, weiss was es
   kann und was es kostet - jetzt will er wissen, mit wem er es zu tun hat.
   ---------------------------------------------------------------------- */

/* Keine Kaesten: eine Haarlinie zwischen den Spalten reicht. Ein Rahmen
   um jeden Absatz macht aus einer Aussage ein Formular. */
.trust {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(32px, 5vw, 80px);
  margin-top: clamp(32px, 4vw, 52px);
}
.trust__col {
  padding: 0;
  display: flex;
  flex-direction: column;
}
.trust__col + .trust__col {
  border-left: 1px solid var(--line);
  padding-left: clamp(32px, 5vw, 80px);
}
.trust__q {
  margin: 0 0 16px;
  font-size: clamp(20px, 2.1vw, 27px);
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.1;
}
.trust__a {
  margin: 0;
  font-size: clamp(15.5px, 1.35vw, 17.5px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 54ch;
}
/* Der Satz am Fuss der Spalte. Beide Spalten enden damit auf
   derselben Linie. */
.trust__claim {
  margin: auto 0 0;
  padding-top: 22px;
  font-size: clamp(16px, 1.5vw, 19px);
  font-weight: 600;
  letter-spacing: -0.016em;
  line-height: 1.3;
  color: var(--accent);
}

@media (max-width: 860px) {
  .trust { grid-template-columns: 1fr; gap: 34px; }
  .trust__col + .trust__col {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-left: 0;
    padding-top: 34px;
  }
  .trust__claim { padding-top: 18px; }
}

/* ---------- Die Überleitung ---------------------------------------------
   Nach vier Abschnitten Zahlen braucht die Seite einen Atemzug, bevor der
   Kontakt kommt. Viel Luft, wenig Text, mittig - das ist der Bruch im
   Rhythmus, den der Satz meint.
   ---------------------------------------------------------------------- */

/* Nicht in ch: die Einheit rechnet gegen die Schriftgroesse dieses
   Kastens (16 px), nicht gegen die der Ueberschrift darin - daraus wurden
   190 px und zwei Woerter je Zeile. Das Textmass steht an der
   Ueberschrift selbst, dort stimmt die Bezugsgroesse. */
.turn {
  max-width: min(100%, 1020px);
  margin-inline: auto;
  text-align: center;
}
.turn__h {
  max-width: 17ch;
  margin: 0 auto clamp(18px, 2vw, 28px);
  font-size: clamp(30px, 5vw, 74px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.032em;
}
.turn__h em { font-style: normal; color: var(--accent); }
.turn__d {
  margin: 0 auto;
  max-width: 46ch;
  font-size: clamp(16px, 1.45vw, 19px);
  line-height: 1.55;
  color: var(--ink-2);
}

/* ---------- Matrix (dunkle Sektion) ------------------------------------- */

.matrix {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 16px;
}
.matrix th, .matrix td {
  text-align: left;
  vertical-align: top;
  padding: 18px 20px 18px 0;
  border-bottom: 1px solid var(--line-inv);
}
.matrix thead th {
  font-size: clamp(18px, 2vw, 25px);
  font-weight: 700;
  letter-spacing: -0.028em;
  padding-bottom: 14px;
}
.matrix thead th:first-child { width: 20%; }
.matrix tbody th {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-inv-2);
  font-weight: 400;
  white-space: nowrap;
}
.matrix .r-promise td {
  font-size: 17px;
  font-weight: 500;
  color: var(--ink-inv);
  letter-spacing: -0.012em;
}
.matrix .r-principle th,
.matrix .r-principle td {
  border-bottom: 0;
  padding-bottom: 0;
  color: var(--accent-inv);
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.06em;
}
/* Eigener Name – .step gehört der Prozesskette und würde hier die
   Reveal-Startwerte (opacity 0) erben. */
.matrix td.m-step { color: var(--ink-inv); }

@media (max-width: 800px) {
  .matrix, .matrix thead, .matrix tbody, .matrix tr, .matrix th, .matrix td {
    display: block;
    width: auto;
  }
  .matrix thead { display: none; }
  .matrix tbody tr { margin-bottom: 34px; }
  .matrix tbody th { padding-bottom: 8px; border-bottom: 0; }
  .matrix td { padding: 6px 0; border-bottom: 0; }
  .matrix td::before {
    content: attr(data-col) " · ";
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-inv-2);
  }
}

.matrix-note {
  margin-top: 34px;
  padding-top: 24px;
  border-top: 1px solid var(--line-inv);
  font-size: 15px;
  color: var(--ink-inv-2);
  max-width: 60ch;
}

/* ---------- Prozesskette ------------------------------------------------ */

.chain {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0;
  margin-top: 8px;
}
@media (max-width: 1000px) { .chain { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .chain { grid-template-columns: 1fr; } }

.chain .step {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 26px 22px 26px 0;
  border-top: 2px solid var(--ink);
  margin-right: 18px;
}
.js .chain .step {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
}
.js .chain .step.in { opacity: 1; transform: none; }
.chain .step:nth-child(1) { transition-delay: 0ms; }
.chain .step:nth-child(2) { transition-delay: 90ms; }
.chain .step:nth-child(3) { transition-delay: 180ms; }
.chain .step:nth-child(4) { transition-delay: 270ms; }
.chain .step:nth-child(5) { transition-delay: 360ms; }

.chain .step__n {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.15em;
  color: var(--ink-3);
  display: block;
  margin-bottom: 14px;
}
.chain .step__t {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin-bottom: 10px;
}
.chain .step__d { font-size: 15px; color: var(--ink-2); line-height: 1.45; }

.chain .step__layer {
  margin-top: auto;     /* unten bündig über alle fünf Karten */
  align-self: flex-start;
  display: inline-block;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: var(--paper-2);
  border: 1px solid var(--line);
  padding: 5px 9px;
  border-radius: 2px;
}

/* Laufender Trip-Punkt auf der Kette */
.chain .step__rail {
  position: absolute;
  top: -2px; left: 0; right: 18px;
  height: 2px;
  overflow: hidden;
}
.chain .step__rail i {
  position: absolute;
  top: 0; left: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
}
.chain .step.in .step__rail i {
  animation: railFill 700ms var(--ease) forwards;
}
.chain .step:nth-child(1).in .step__rail i { animation-delay: 120ms; }
.chain .step:nth-child(2).in .step__rail i { animation-delay: 380ms; }
.chain .step:nth-child(3).in .step__rail i { animation-delay: 640ms; }
.chain .step:nth-child(4).in .step__rail i { animation-delay: 900ms; }
.chain .step:nth-child(5).in .step__rail i { animation-delay: 1160ms; }

@keyframes railFill { to { width: 100%; } }

/* ---------- Ausleitungen / BI ------------------------------------------- */

.outs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 2px;
  background: var(--line-inv);
  border: 1px solid var(--line-inv);
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 40px;
}
.out {
  background: var(--dark-2);
  padding: 28px 26px;
}
.out h4 {
  font-size: 18px;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}
.out p { font-size: 15px; color: var(--ink-inv-2); line-height: 1.45; }

/* ---------- Nutzen-Raster ----------------------------------------------- */

/* ---------- Warum wir ---------------------------------------------------

   Angeankert wie der Zeitstrahl. Der Abschnitt bleibt stehen, die sechs
   Punkte werden nacheinander scharf - alle sechs sind dabei sichtbar, es
   wird nichts versteckt. Ein Karussell, das Inhalt wegnimmt, liest sich
   auf kurzen Schirmen als Fehler.

   Keine Karten, keine Kicker. Sechs Saetze, eine Ziffer, eine Linie.
   ---------------------------------------------------------------------- */

.stack-track { position: relative; height: 210svh; }
.stack-sticky {
  position: sticky;
  top: 92px;
  display: flex;
  flex-direction: column;
}

.stack__h {
  margin: 0 0 clamp(28px, 3.4vw, 52px);
  font-size: clamp(28px, 4.2vw, 62px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.03em;
  max-width: 18ch;
}
.stack__h em { font-style: normal; color: var(--accent); }

.stack {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

.st {
  display: grid;
  grid-template-columns: 40px minmax(0, 0.88fr) minmax(0, 1.25fr);
  gap: clamp(14px, 2vw, 32px);
  align-items: start;
  padding: clamp(16px, 1.9vw, 26px) 0;
  border-bottom: 1px solid var(--line);
  /* Vor dem Erreichen zurueckgenommen, nicht weg: man sieht, wie viel
     noch kommt. */
  opacity: .34;
  transition: opacity 420ms var(--ease);
}
.st[data-on="true"] { opacity: 1; }

/* Das Zeichen sagt, worum es geht, bevor man liest. Eine Ziffer haette
   nur gezaehlt. */
.st__i {
  display: block;
  color: var(--ink-3);
  transition: color 420ms var(--ease);
}
.st__i svg { display: block; width: 26px; height: 26px; }
.st[data-on="true"] .st__i { color: var(--accent); }

.st__t {
  margin: 0;
  font-size: clamp(17px, 1.8vw, 23px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.st__d {
  margin: 0;
  font-size: clamp(14.5px, 1.25vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
}

@media (max-width: 860px) {
  /* Auf kurzen Schirmen passt der Block nicht in eine Bildhoehe - dann
     lieber mitlaufen lassen als abschneiden. */
  .stack-track { height: auto; }
  .stack-sticky { position: static; }
  .st {
    grid-template-columns: 34px 1fr;
    gap: 8px 14px;
    opacity: 1;
  }
  .st__d { grid-column: 2; }
}

/* ---------- Referenzen -------------------------------------------------- */

/* Beide Ueberschriften tragen den Wortaufzug. Groesse und Abstand stehen
   hier, nicht in .rise - die Klasse ist nur der Haken. */
.trust__h,
.ref__h {
  margin: 0 0 clamp(20px, 2.2vw, 30px);
  font-size: clamp(28px, 4.2vw, 62px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.03em;
  max-width: 20ch;
}
.trust__h em,
.ref__h em { font-style: normal; color: var(--accent); }

/* Der Dreiklang: drei Woerter ueber die ganze Breite, durch Haarlinien
   getrennt. In einer Spalte neben dem Fliesstext gingen sie unter. */
.triad {
  list-style: none;
  margin: clamp(40px, 5vw, 72px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 2px solid var(--ink);
}
.triad li {
  padding: clamp(22px, 2.6vw, 34px) 0 0;
  font-size: clamp(26px, 4vw, 56px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ink);
}
.triad li + li {
  border-left: 1px solid var(--line);
  padding-left: clamp(18px, 2.4vw, 36px);
}
.triad li:last-child { color: var(--accent); }

.js [data-reveal].triad li { opacity: 0; transform: translateY(14px); }
.js [data-reveal].triad.in li {
  opacity: 1;
  transform: none;
  transition: opacity 620ms var(--ease), transform 620ms var(--ease);
}
.triad li:nth-child(1) { transition-delay: 60ms; }
.triad li:nth-child(2) { transition-delay: 200ms; }
.triad li:nth-child(3) { transition-delay: 340ms; }

@media (max-width: 720px) {
  .triad { grid-template-columns: 1fr; border-top-width: 2px; }
  .triad li + li { border-left: 0; border-top: 1px solid var(--line); padding-left: 0; }
}

/* Der Schnitt zwischen den beiden Haelften des Abschnitts. Eine Linie
   statt eines neuen Bandes - es ist dieselbe Aussage. */
.cut {
  border: 0;
  border-top: 1px solid var(--line);
  margin: clamp(56px, 7vw, 110px) 0 clamp(48px, 6vw, 88px);
}

/* ---------- Die Referenzen ----------------------------------------------

   Ohne Karten. Die Ueberschrift bleibt links stehen, waehrend die Faelle
   rechts durchlaufen - das traegt den Abschnitt, ohne ihn in Kaesten zu
   zerlegen. Getrennt wird durch Linien und Abstand, nicht durch Rahmen.
   ---------------------------------------------------------------------- */

.refs {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(32px, 5vw, 88px);
  align-items: start;
}

.refs__lead {
  position: sticky;
  top: 108px;
}
.refs__sub {
  margin: 0;
  max-width: 34ch;
  font-size: clamp(15.5px, 1.35vw, 17.5px);
  line-height: 1.55;
  color: var(--ink-2);
}

.refs__list { display: grid; }

.ref {
  padding: clamp(34px, 4vw, 56px) 0;
  border-top: 2px solid var(--ink);
}
.ref:first-child { padding-top: 0; border-top: 0; }

.ref__top {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: clamp(22px, 2.4vw, 32px);
}
/* Das Kundenlogo traegt den Fall, deshalb gross. align-self, weil die
   Flex-Zeile es sonst dehnt und die Marke verzerrt. */
.ref__logo {
  display: block;
  height: clamp(32px, 3.4vw, 46px);
  width: auto;
  max-width: 54%;
  align-self: center;
}
/* Teal, nicht Grau: die Marke steht hier neben einem fremden Logo und soll
   als unsere gelesen werden. Der Ring nimmt denselben Ton verduennt auf -
   voll ausgezeichnet wuerde er lauter als die Fallueberschrift darunter. */
.ref__tag {
  flex: none;
  font-stretch: 86%;
  font-size: 10.5px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 36%, transparent);
  padding: 6px 11px;
  border-radius: 999px;
}

.ref__t {
  margin: 0 0 14px;
  font-size: clamp(22px, 2.4vw, 32px);
  font-weight: 700;
  letter-spacing: -0.024em;
  line-height: 1.12;
}
.ref__d {
  margin: 0;
  max-width: 56ch;
  font-size: clamp(15.5px, 1.4vw, 18px);
  line-height: 1.5;
  color: var(--ink-2);
}

.reach { margin-top: clamp(26px, 2.8vw, 38px); }
.reach__k {
  display: block;
  font-stretch: 86%;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 18px;
}

.logorow {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(26px, 3.4vw, 48px);
}
/* Graustufen: fuenf fremde Markenfarben nebeneinander zerreissen die
   Seite, und hier geht es um Reichweite, nicht um die Marken selbst.
   Beim Darueberfahren kommt die Originalfarbe zurueck. */
.logorow img {
  display: block;
  height: var(--h, 30px);
  width: auto;
  max-width: 160px;
  object-fit: contain;
  filter: grayscale(1);
  opacity: .72;
  transition: filter 260ms var(--ease), opacity 260ms var(--ease);
}
.logorow img:hover { filter: none; opacity: 1; }

.js [data-reveal] .logorow img { opacity: 0; transform: translateY(6px); }
.js [data-reveal].in .logorow img {
  opacity: .72;
  transform: none;
  transition: opacity 520ms var(--ease), transform 520ms var(--ease), filter 260ms var(--ease);
}
.logorow li:nth-child(1) img { transition-delay: 220ms; }
.logorow li:nth-child(2) img { transition-delay: 320ms; }
.logorow li:nth-child(3) img { transition-delay: 420ms; }

@media (max-width: 900px) {
  .refs { grid-template-columns: 1fr; gap: 40px; }
  .refs__lead { position: static; }
  .refs__sub { max-width: none; }
}

/* ---------- Preisrechner ------------------------------------------------ */

.pricing {
  display: grid;
  grid-template-columns: minmax(280px, 380px) 1fr;
  gap: clamp(24px, 3vw, 48px);
  align-items: start;
}
@media (max-width: 940px) { .pricing { grid-template-columns: 1fr; } }

.panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper-3);
  padding: clamp(24px, 2.6vw, 32px);
}

.field { margin-bottom: 26px; }
.field:last-child { margin-bottom: 0; }

.field__label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 12px;
}
.field__label output {
  font-size: 19px;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-weight: 500;
  text-transform: none;
}

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 26px;
  background: transparent;
  cursor: pointer;
  margin: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 3px;
  background: var(--line);
  border-radius: 2px;
}
input[type="range"]::-moz-range-track {
  height: 3px;
  background: var(--line);
  border-radius: 2px;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 19px; height: 19px;
  margin-top: -8px;
  border-radius: 50%;
  background: var(--ink);
  border: 3px solid var(--paper-3);
  box-shadow: 0 0 0 1px var(--ink);
}
input[type="range"]::-moz-range-thumb {
  width: 19px; height: 19px;
  border-radius: 50%;
  background: var(--ink);
  border: 3px solid var(--paper-3);
  box-shadow: 0 0 0 1px var(--ink);
}

.seg {
  display: flex;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.seg button {
  flex: 1;
  appearance: none;
  border: 0;
  border-right: 1px solid var(--line);
  background: transparent;
  padding: 11px 10px;
  cursor: pointer;
  font-size: 14px;
  color: var(--ink-2);
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
.seg button:last-child { border-right: 0; }
.seg button:hover { background: rgba(0,0,0,.04); }
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

.check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 15px;
  color: var(--ink-2);
  cursor: pointer;
  line-height: 1.4;
}
.check input { margin: 3px 0 0; width: 16px; height: 16px; accent-color: var(--ink); flex: none; }

/* Ergebnis */
.result {
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  overflow: hidden;
}
.result__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding: 17px clamp(20px, 2.4vw, 30px);
  border-bottom: 1px solid var(--line);
  font-size: 15.5px;
}
.result__row .k { color: var(--ink-2); }
.result__row .k small {
  display: block;
  font-size: 12.5px;
  color: var(--ink-3);
  margin-top: 2px;
}
.result__row .v {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  white-space: nowrap;
}
.result__row--total {
  background: var(--ink);
  color: var(--paper);
  border-bottom: 0;
  padding-block: 24px;
}
.result__row--total .k { color: var(--ink-inv-2); font-size: 15px; }
/* Liegt auf der dunklen Summenflaeche: helle Sekundaerfarbe, nicht die
   fuer Papier gedachte. */
.result__row--total .k small { color: var(--bluegrey); opacity: .75; }
.result__row--total .v { font-size: clamp(26px, 3.2vw, 38px); font-weight: 600; letter-spacing: -0.03em; }
.result__row--head {
  background: var(--paper-2);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-block: 12px;
}

.assumption {
  margin-top: 20px;
  font-size: 13.5px;
  color: var(--ink-3);
  line-height: 1.5;
  max-width: 68ch;
}

/* ---------- Der Abschluss ----------------------------------------------

   Das dunkle Kontaktband ist entfallen. Die Seite endet dort, wo der Ton
   umschlaegt: erst der Satz, dann drei Schritte, dann die Handlung. Die
   Figur aus dem Hero steht dahinter - die Seite schliesst den Kreis.
   ---------------------------------------------------------------------- */

#kontakt { position: relative; overflow: hidden; }

.end__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* Nach oben und unten aufloesen, sonst reisst die Figur an der
     Bandkante ab. */
  mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
}
.mark--e1 {
  width: min(1080px, 84vw);
  right: -18%;
  top: 50%;
  opacity: .14;
  animation-name: markA;
  animation-duration: 34s;
}
.mark--e2 {
  width: min(560px, 48vw);
  left: -12%;
  bottom: -14%;
  opacity: .09;
  animation-name: markC;
  animation-duration: 43s;
}

.end { position: relative; z-index: 1; }

/* Drei Schritte, mittig unter dem Satz. Die Linie oben in Teal, damit sie
   als Zusage gelesen wird und nicht als Tabelle. */
.end__steps {
  list-style: none;
  margin: clamp(40px, 5vw, 72px) auto 0;
  padding: 0;
  max-width: min(100%, 1020px);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 44px);
  text-align: left;
}
.cstep {
  padding-top: 16px;
  border-top: 2px solid var(--accent);
}
.cstep__t {
  display: block;
  margin-bottom: 7px;
  font-size: clamp(16px, 1.5vw, 19px);
  font-weight: 700;
  letter-spacing: -0.016em;
  line-height: 1.25;
  color: var(--ink);
}
.cstep__d {
  display: block;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
}

/* Grosse Ausfuehrung, seit dem Entfernen der Abschlussknoepfe nur noch in
   der Tuer im Einsatz. */
.btn--xl {
  padding: 17px 28px;
  font-size: 16px;
}

@media (max-width: 860px) {
  .end__steps { grid-template-columns: 1fr; gap: 22px; }
}

/* ---------- Footer ------------------------------------------------------ */

.foot {
  border-top: 1px solid var(--line);
  padding-block: 40px 56px;
  font-size: 14px;
  color: var(--ink-3);
}
.foot__row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 32px;
  justify-content: space-between;
  align-items: center;
}
/* Umgebrochen sieht "space-between" aus wie zwei linksbuendige Zeilen, die
   sich verlaufen haben. Untereinander gehoert beides in die Mitte. */
@media (max-width: 560px) {
  .foot__row { justify-content: center; text-align: center; gap: 10px; }
}
/* Der Datenschutzhinweis steht unter der Zeile, nicht darin: er ist eine
   Angabe, kein Navigationspunkt, und soll die beiden Links nicht verdraengen. */
.foot__note {
  margin: 18px 0 0;
  max-width: 76ch;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-3);
}
@media (max-width: 560px) {
  .foot__note { text-align: center; margin-top: 14px; }
}

.foot a { color: var(--ink-2); text-decoration: none; border-bottom: 1px solid var(--line); }
.foot a:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* ---------- Reveal ------------------------------------------------------ */

/* Nur wenn JavaScript läuft, darf etwas unsichtbar starten. Ohne JS –
   blockiertes Skript, Fehler, alter Browser – steht die ganze Seite da. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
}
.js [data-reveal].in { opacity: 1; transform: none; }


/* ---------- Der Tagesabschluss als Anwendung ----------------------------

   Das Fenster ist die Fortsetzung der Kette: was am Hafen geprueft wurde,
   laeuft hier zusammen. Es rechnet und es sperrt - die Freigabe bleibt
   verriegelt, solange ein Datensatz in Klaerung steht. Genau das ist die
   Aussage, die eine Abbildung nicht transportiert.

   Keine Fensterdekoration mit bunten Punkten. Die Flaeche traegt sich
   ueber Linie und Rhythmus, wie der Rest der Seite.
   ---------------------------------------------------------------------- */

.app {
  background: var(--paper-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 18px 48px rgba(30, 35, 43, .10);
  overflow: hidden;
}

.app__bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 22px;
  border-bottom: 1px solid var(--line-soft);
  background: #fff;
}
.app__mark {
  width: 10px;
  height: 10px;
  flex: none;
  background: var(--accent);
}
.app__name {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.app__scope {
  font-stretch: 86%;
  font-size: 12.5px;
  color: var(--ink-3);
}
/* Der Zustand steht rechts und ist der einzige Ort, an dem sich das
   Fenster selbst beschreibt. */
.app__state {
  margin-left: auto;
  font-stretch: 86%;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 6px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink-2);
}
.app__state[data-state="done"] {
  border-color: transparent;
  background: var(--accent);
  color: #fff;
}

/* Auf schmalen Schirmen bricht die Kopfzeile des Fensters in zwei Zeilen:
   Name oben, Ort und Zustand darunter. In einer Zeile zerfaellt das Datum in
   drei Zeilen und der Zustand wird mitten im Wort getrennt. */
@media (max-width: 560px) {
  .app__bar { flex-wrap: wrap; gap: 8px 10px; padding: 14px 16px; }
  .app__name { flex: 1 1 auto; }
  .app__scope { order: 3; flex: 0 1 auto; }
  .app__state { order: 4; margin-left: auto; white-space: nowrap; }
}

.app__tabs {
  display: flex;
  gap: 2px;
  padding: 0 22px;
  border-bottom: 1px solid var(--line-soft);
  background: #fff;
}
.app__tab {
  appearance: none;
  border: 0;
  background: none;
  padding: 13px 4px;
  margin-right: 26px;
  font: inherit;
  font-size: 14px;
  color: var(--ink-3);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 150ms var(--ease), border-color 150ms var(--ease);
}
.app__tab:hover { color: var(--ink); }
.app__tab[aria-selected="true"] {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

.app__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
}
.app__main { padding: 26px 26px 30px; min-width: 0; }
.app__view:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }

/* ---------- Kennzahlen ---------- */

.kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
}
.kpi {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 16px 18px;
  background: #fff;
}
.kpi__k {
  font-stretch: 86%;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.kpi__v {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.kpi__n { font-size: 12.5px; color: var(--ink-3); }

/* ---------- Balken ----------
   Kein Diagramm-Paket fuer dreizehn Werte. Die Hoehe steckt in --h,
   die Zahl steht darueber - damit muss niemand am Balken messen. */

.chart { margin: 26px 0 0; }
.chart__t {
  font-stretch: 86%;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 14px;
}
.bars {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 6px;
  align-items: end;
  height: 132px;
}
.bar {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-end;
  height: 100%;
  gap: 5px;
}
.bar__n {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  text-align: center;
  color: var(--ink-3);
}
.bar__v {
  display: block;
  height: calc(var(--h) * 100%);
  min-height: 3px;
  background: var(--accent);
  border-radius: 2px 2px 0 0;
  transform-origin: bottom;
}
.js [data-reveal] .bar__v { transform: scaleY(0); }
.js [data-reveal].in .bar__v {
  transform: scaleY(1);
  transition: transform 520ms var(--ease);
}
.bar:nth-child(1)  .bar__v { transition-delay: 0ms; }
.bar:nth-child(2)  .bar__v { transition-delay: 35ms; }
.bar:nth-child(3)  .bar__v { transition-delay: 70ms; }
.bar:nth-child(4)  .bar__v { transition-delay: 105ms; }
.bar:nth-child(5)  .bar__v { transition-delay: 140ms; }
.bar:nth-child(6)  .bar__v { transition-delay: 175ms; }
.bar:nth-child(7)  .bar__v { transition-delay: 210ms; }
.bar:nth-child(8)  .bar__v { transition-delay: 245ms; }
.bar:nth-child(9)  .bar__v { transition-delay: 280ms; }
.bar:nth-child(10) .bar__v { transition-delay: 315ms; }
.bar:nth-child(11) .bar__v { transition-delay: 350ms; }
.bar:nth-child(12) .bar__v { transition-delay: 385ms; }
.bar:nth-child(13) .bar__v { transition-delay: 420ms; }
.bar__x {
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  text-align: center;
  color: var(--ink-3);
  padding-top: 7px;
  border-top: 1px solid var(--line-soft);
}
.chart__d {
  margin: 14px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 62ch;
}

/* ---------- Datentabellen ---------- */

.dtable {
  width: 100%;
  margin-top: 28px;
  border-collapse: collapse;
  font-size: 13.5px;
}
.dtable caption {
  text-align: left;
  font-stretch: 86%;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-bottom: 10px;
}
.dtable th,
.dtable td {
  text-align: right;
  padding: 10px 0 10px 14px;
  border-bottom: 1px solid var(--line-soft);
  font-variant-numeric: tabular-nums;
  font-stretch: 86%;
  color: var(--ink);
}
.dtable thead th {
  font-weight: 400;
  font-size: 11.5px;
  color: var(--ink-3);
  border-bottom-color: var(--line);
  white-space: nowrap;
}
.dtable th:first-child,
.dtable td:first-child,
.dtable thead th:first-child { text-align: left; padding-left: 0; }
.dtable tbody th { font-weight: 500; }
.dtable__sub {
  font-stretch: 100%;
  font-weight: 400;
  font-size: 12px;
  color: var(--ink-3);
  margin-left: 7px;
}
.dtable tfoot th,
.dtable tfoot td {
  border-bottom: 0;
  border-top: 2px solid var(--ink);
  font-weight: 500;
}
.dtable--trips td:last-child,
.dtable--trips th:last-child { text-align: right; }

/* Die offene Zeile ist die Aussage der Sicht: sie haelt alles an. */
.dtable--trips tr[data-open="true"] th,
.dtable--trips tr[data-open="true"] td { background: rgba(255, 106, 44, .07); }
.dtable--trips tr.is-flash th,
.dtable--trips tr.is-flash td { animation: rowflash 1200ms var(--ease); }
@keyframes rowflash {
  0%, 60% { background: rgba(255, 156, 66, .38); }
  100%    { background: rgba(255, 106, 44, .07); }
}

.dtable__act {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  white-space: nowrap;
}

.tag {
  display: inline-block;
  font-stretch: 86%;
  font-size: 11.5px;
  letter-spacing: 0.04em;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-2);
}
.tag[data-state="ok"]  { color: var(--accent); border-color: rgba(15, 107, 109, .35); }
.tag[data-state="out"] { color: var(--ink); background: var(--accent-inv); border-color: transparent; }
.tag[data-state="err"] { color: var(--ink); background: var(--cta); border-color: transparent; font-weight: 600; }

/* Textbutton. Kein Link - es fuehrt nirgendwo hin, es tut etwas. */
.lnk {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 12.5px;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.lnk:hover { color: var(--ink); }

.app__act {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--line-soft);
}
.app__act .btn[disabled] { opacity: .4; cursor: not-allowed; transform: none; }
.app__note {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 44ch;
}

/* ---------- mind ----------
   Eigene Spalte, dunkel abgesetzt: das ist eine andere Art von Aussage
   als eine gemessene Zahl, und das soll man sehen.

   Der Aufbau ist die Aussage: erst was das System bis heute gesehen hat,
   dann was ihm daran aufgefallen ist, dann was es daraus ableitet. Ohne
   den ersten Block wirkt der dritte wie geraten. */

.mind {
  padding: 26px 24px 24px;
  background: var(--dark);
  color: var(--ink-inv);
  display: flex;
  flex-direction: column;
}
.mind__name {
  margin: 0 0 20px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-inv);
}
.mind__name em { font-style: normal; font-weight: 400; color: var(--accent-inv); }

.mind__block {
  padding-bottom: 18px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--line-inv);
}
.mind__block:last-of-type { border-bottom: 0; padding-bottom: 0; }

.mind__k {
  display: block;
  font-stretch: 86%;
  font-size: 10.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-inv-2);
  margin-bottom: 8px;
}
.mind__v {
  display: block;
  font-stretch: 86%;
  font-variant-numeric: tabular-nums;
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink-inv);
}
.mind__v span { font-weight: 400; }
.mind__n {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink-inv-2);
}

/* Der Balken zeigt eine echte Groesse: 214 von 365 Tagen des ersten
   Jahres. Ein Balken ohne Bezug waere Dekoration. */
.mind__bar {
  height: 3px;
  margin-top: 12px;
  background: var(--line-inv);
  border-radius: 2px;
  overflow: hidden;
}
.mind__bar i {
  display: block;
  height: 100%;
  width: calc(var(--w) * 100%);
  background: var(--accent-inv);
}

.mind__list { list-style: none; margin: 0; padding: 0; }
.hint { padding: 12px 0; border-top: 1px solid var(--line-inv); }
.hint:first-child { border-top: 0; padding-top: 0; }
.hint p {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-inv-2);
}
.hint .lnk {
  margin-top: 8px;
  display: inline-block;
  color: var(--accent-inv);
}
.hint .lnk:hover { color: #fff; }

.mind__block--fc .mind__v { color: var(--accent-inv); }

.mind__foot {
  margin: 20px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--line-inv);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-inv-2);
}

@media (max-width: 1000px) {
  .app__body { grid-template-columns: 1fr; }
  .kpis { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .kpis { grid-template-columns: 1fr; }
  .bars { height: 104px; }
  .bar__n { display: none; }
  /* Lieber zwei Spalten weniger als eine abgeschnittene Tabelle. Slip,
     Gewogen, Abweichung und Status tragen die Aussage allein. */
  .dtable--trips .c-veh,
  .dtable--trips .c-calc { display: none; }
  .app__main { padding: 20px 18px 24px; }
  .mind { padding: 22px 18px; }
}


/* ---------- Ueberschrift ueber dem Tagesabschluss -----------------------

   Die Woerter fahren beim Einscrollen aus einer Blende hoch, versetzt.
   Der Hero nebenan macht dasselbe beim Laden - hier loest das Scrollen
   aus, sonst waere die Bewegung vorbei, bevor jemand hinsieht.
   ---------------------------------------------------------------------- */

.tailhead { margin-bottom: clamp(36px, 4.5vw, 64px); }

/* Die Ueberschrift nimmt die ganze Seitenbreite. Kein Textmass in ch:
   die Einheit rechnet gegen die Schriftgroesse ihres Kastens, nicht
   gegen die der Ueberschrift darin. */
/* .rise ist nur der Haken fuer den Wortaufzug. Groesse und Abstand
   gehoeren an die Stelle, die ihn benutzt - sonst ueberschreibt der Haken
   die Typografie jeder weiteren Ueberschrift, die ihn bekommt. */
.tailhead .rise {
  font-size: clamp(32px, 5.4vw, 86px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.034em;
  margin: 0;
}
.tailhead__sub {
  margin: 22px 0 0;
  max-width: 54ch;
  font-size: clamp(17px, 1.45vw, 21px);
  line-height: 1.55;
  color: var(--ink-2);
  text-wrap: pretty;
}

/* Der Block selbst blendet nicht mit - sonst liefen zwei Bewegungen
   uebereinander und keine waere zu sehen. Die Woerter tragen es allein. */
.js [data-reveal]:has(> .rise) {
  opacity: 1;
  transform: none;
  transition: none;
}

/* Die Blende je Wort, nicht je Zeile: Woerter brechen um, Zeilen nicht.
   Das Polster unten faengt die Unterlaengen auf - ohne das schneidet
   overflow das g in "Tages" ab. */
/* Die Blende ist so hoch wie der Kasten plus Polster. Sie darf die
   Zeilenhoehe nicht uebersteigen, sonst schiebt sie sich in die Zeile
   darueber - gemessen 11 px Ueberlapp bei 72 px Schrift und 0,99 Zeile.
   Roboto ragt 0,06 em unter den Kasten, 0,09 em Polster reichen also. */
.rise .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  /* Ohne das erbt die Blende die Zeilenhoehe der Ueberschrift und wird
     dadurch hoeher als die Zeile selbst - gemessen 85,7 statt 79,2 px,
     also 6,5 px, die sich in die Zeile darueber schoben. */
  line-height: 1;
  padding-bottom: 0.09em;
  margin-bottom: -0.09em;
}
.rise .w > i {
  display: inline-block;
  font-style: normal;
  line-height: 1;
}
.js .rise .w > i {
  transform: translateY(110%);
  transition: transform 760ms var(--ease);
  transition-delay: calc(var(--i) * 42ms);
}
.js [data-reveal].in .rise .w > i { transform: none; }

/* Die Unterzeile kommt nach, wenn die Woerter stehen. */
.js .tailhead__sub {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 620ms var(--ease) 260ms, transform 620ms var(--ease) 260ms;
}
.js [data-reveal].in .tailhead__sub { opacity: 1; transform: none; }

@media (max-width: 860px) { .tailhead { max-width: none; } }

/* ---------- Zugang und Sprachhinweis ------------------------------------

   Die Tuer. Sie ist kein Schloss: der Code steht im Quelltext. Sie haelt
   zufaellige Besucher ab und macht sichtbar, dass die Seite vertraulich
   ist - mehr kann eine statische Seite ohne Server nicht.

   Solange sie zu ist, steht alles dahinter still. Ohne das waere die
   Hero-Animation vorbei, bevor jemand den Code getippt hat.
   ---------------------------------------------------------------------- */

.is-locked { overflow: hidden; }
.is-locked body > *:not(.gate) { visibility: hidden; }

.is-locked *,
.is-locked *::before,
.is-locked *::after { animation-play-state: paused !important; }
.is-locked .gate,
.is-locked .gate *,
.is-locked .gate *::before { animation-play-state: running !important; }

/* Ohne JavaScript bleibt die Tuer weg - sonst staende der Besucher vor
   einer Maske, die nichts annehmen kann. */
.gate { display: none; }
.js .gate {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  overflow: hidden;
  padding: var(--gut);
}
.js:not(.is-locked) .gate { display: none; }

.gate__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  mask-image: linear-gradient(to bottom, transparent 0%, #000 18%, #000 82%, transparent 100%);
}
.mark--g1 {
  width: min(1100px, 92vw);
  right: -20%;
  top: 50%;
  opacity: .17;
  animation-name: markA;
  animation-duration: 30s;
}
.mark--g2 {
  width: min(560px, 52vw);
  left: -14%;
  bottom: -16%;
  opacity: .1;
  animation-name: markC;
  animation-duration: 39s;
}

.gate__inner {
  position: relative;
  z-index: 1;
  width: min(100%, 640px);
}
.gate__brands {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 13px;
  row-gap: 14px;
  margin-bottom: clamp(36px, 5vw, 64px);
}
/* Der Umschalter sitzt am rechten Ende derselben Zeile. Hinter der Tuer
   ist die Kopfzeile unsichtbar, also braucht die Maske einen eigenen. */
.gate__lang { margin-left: auto; }

.gate__h {
  margin: 0 0 12px;
  font-size: clamp(27px, 3.6vw, 44px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.028em;
}
.gate__d {
  margin: 0 0 clamp(26px, 3vw, 38px);
  max-width: 44ch;
  font-size: clamp(15.5px, 1.35vw, 17.5px);
  line-height: 1.5;
  color: var(--ink-2);
}

.gate__label {
  display: block;
  font-stretch: 86%;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 10px;
}
.gate__form { margin: 0; }
.gate__row { display: flex; flex-wrap: wrap; gap: 12px; }

.gate__input {
  flex: 1 1 200px;
  min-width: 0;
  font: inherit;
  font-stretch: 86%;
  font-size: 22px;
  letter-spacing: 0.32em;
  padding: 14px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  color: var(--ink);
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease);
}
.gate__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.gate[data-state="wrong"] .gate__input {
  border-color: var(--cta);
  box-shadow: inset 0 0 0 1px var(--cta);
  animation: gateShake 420ms var(--ease);
}
@keyframes gateShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(2px); }
}

.gate__msg {
  margin: 12px 0 0;
  min-height: 1.4em;
  font-size: 13.5px;
  color: var(--cta-txt, #B33A0E);
}
.gate__note {
  margin: clamp(30px, 4vw, 48px) 0 0;
  font-size: 12.5px;
  color: var(--ink-3);
}

/* Die Tuer geht auf: sie zieht sich zurueck, die Seite kommt ihr
   entgegen. Zwei Bewegungen, eine Richtung. */
.is-opening .gate {
  animation: gateOut 620ms var(--ease) forwards;
  pointer-events: none;
}
.is-opening body > *:not(.gate) {
  visibility: visible;
  animation: gateIn 620ms var(--ease) forwards;
}
@keyframes gateOut {
  to { opacity: 0; transform: scale(1.05); }
}
@keyframes gateIn {
  from { opacity: 0; transform: scale(.985); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .is-opening .gate { animation: none; opacity: 0; }
  .is-opening body > *:not(.gate) { animation: none; opacity: 1; transform: none; }
}

/* ---------- Sprachhinweis ----------------------------------------------

   Die Seite stellt sich still auf die Browsersprache ein. Der Hinweis
   macht das sichtbar und umkehrbar - sonst wundert sich ein deutscher
   Leser mit englischem System, warum hier Englisch steht.

   Bewusst keine Geo-IP-Abfrage: die braeuchte einen externen Dienst und
   damit eine Datenweitergabe. navigator.language liefert dasselbe,
   lokal und ohne Einwilligung.
   ---------------------------------------------------------------------- */

.geo {
  position: fixed;
  left: var(--gut);
  bottom: var(--gut);
  z-index: 90;
  width: min(100%, 420px);
  display: none;
  padding: 18px 20px;
  background: var(--paper-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .05), 0 16px 40px rgba(30, 35, 43, .14);
}
.geo[data-open="true"] {
  display: block;
  animation: geoIn 420ms var(--ease) both;
}
@keyframes geoIn {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
.geo__t {
  margin: 0 0 4px;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.012em;
}
.geo__d { margin: 0 0 14px; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.geo__row { display: flex; flex-wrap: wrap; gap: 8px; }
.geo__btn {
  appearance: none;
  font: inherit;
  font-size: 13px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 150ms var(--ease), background 150ms var(--ease);
}
.geo__btn:hover { border-color: var(--ink-3); }
.geo__btn--go { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.geo__btn--go:hover { background: var(--dark-2); border-color: var(--dark-2); }

@media (max-width: 560px) {
  .geo { left: 12px; right: 12px; bottom: 12px; width: auto; }
}

/* ---------- Der Film im Hochformat --------------------------------------

   Im 16:9-Rahmen bleibt auf einem Telefon ein Streifen von 211 px in einem
   812 px hohen Bild uebrig. Das Bild wird zur Briefmarke, die Beschriftung
   liegt auf den Bedienpunkten, und die Masken werden unten abgeschnitten.

   Im Hochformat fuellt der Rahmen deshalb den Bildschirm. Das Video steht
   in voller Hoehe und ist dadurch breiter als der Schirm - der Scroll
   faehrt von links nach rechts darueber. Erst danach kommt der Uebergang,
   am Hafen dasselbe noch einmal.

   Die Schwelle ist das Seitenverhaeltnis - ein liegendes Telefon fuellt den
   16:9-Rahmen von selbst und braucht die Fahrt nicht. Die Breitengrenze muss
   trotzdem dazu: ein Schreibtischfenster von 1640 x 1328 hat ein Verhaeltnis
   von 1,235 und lag damit unter 5/4 - es hielt sich fuer ein Telefon und
   bekam das randlose Bild samt Blatt ueber die volle Breite. 1100 px deckt
   Telefone und beide iPad-Groessen im Hochformat ab.
   ------------------------------------------------------------------------ */

@media (max-aspect-ratio: 5 / 4) and (max-width: 1100px) {
  /* Mehr Weg: die Fahrt ueber zwei Videos braucht Strecke, sonst rauscht
     sie in einer Daumenbewegung vorbei. */
  .film { height: 340svh; }
  .film__sticky { padding-top: 0; height: 100svh; }
  .film__inner { height: 100%; }

  .film__frame {
    aspect-ratio: auto;
    width: 100%;
    height: 100%;
  }
  /* Die untere Weichzeichnung loest eine Rahmenkante auf. Im Vollbild gibt
     es keine, also weg damit. */
  .film__frame::after { display: none; }

  /* Volle Hoehe, Breite aus dem Seitenverhaeltnis - dadurch breiter als der
     Schirm. --pan ist der zurueckgelegte Weg, den site.js setzt. */
  .layer__media {
    position: absolute;
    top: 0;
    left: 0;
    width: auto;
    height: 100%;
    max-width: none;
    object-fit: cover;
    transform: translateX(var(--pan, 0px));
  }
  /* Das Uebergangsbild fuellt ebenfalls, sonst haengt mitten in der Fahrt
     ein Briefmarkenbild zwischen zwei Vollbildern. */
  .layer__img { object-fit: cover; }

  /* Die Beschriftung steht unten, nicht oben. Oben kreuzen die
     Bedienpunkte sie: zwei von ihnen sitzen auf 22 und 23 Prozent Hoehe
     und fahren waehrend der Fahrt quer durch den Text. Unten ist das Band
     frei - der tiefste Punkt sitzt auf 63 Prozent. */
  .film__head {
    top: auto;
    bottom: 0;
    align-content: end;
    padding-top: 0;
    padding-bottom: clamp(22px, 4vw, 38px);
  }
  /* Ist eine Maske offen, tritt die Beschriftung zurueck: die Maske steht
     am selben Rand und sagt ohnehin, wo man ist. */
  .film__frame:has(.hotspots[data-open="true"]) .film__head {
    opacity: 0;
    transition: opacity 200ms var(--ease);
  }
  /* Der Verlauf traegt im Hochformat mehr als auf dem Schirm. Dort steht
     die Beschriftung in einem breiten 16:9-Rahmen weit oben; hier liegt sie
     ueber einem bildschirmhohen Ausschnitt, und das Video laeuft - die
     dunkelste Stelle wandert von Bild zu Bild. Mit dem urspruenglichen
     Verlauf kam der Erklaersatz auf 2,95:1 gegen dunkle Stellen, gemessen
     an den echten Bildpunkten.
     Deshalb bleibt die Deckung bis zum Ende des Textes hoch und faellt erst
     darunter ab. Die untere Haelfte des Videos bleibt unberuehrt. */
  .film__scrim {
    inset: auto 0 0;
    height: 46%;
    background: linear-gradient(to top,
      var(--paper) 0%,
      color-mix(in srgb, var(--paper) 95%, transparent) 38%,
      color-mix(in srgb, var(--paper) 82%, transparent) 56%,
      color-mix(in srgb, var(--paper) 34%, transparent) 80%,
      transparent 100%);
  }
  .cue__t { font-size: clamp(22px, 6.4vw, 30px); }
  .cue__d { font-size: 15px; max-width: 30ch; }

  /* Die Punkte markieren Stellen im Bild, also fahren sie mit. --f ist
     Videobreite geteilt durch Rahmenbreite; --x bleibt der Ort im Video. */
  .hotspot {
    left: calc(var(--x, 50%) * var(--f, 1));
    transform: translate(-50%, -50%) translateX(var(--pan, 0px));
  }
  .hotspot:hover { transform: translate(-50%, -50%) translateX(var(--pan, 0px)) scale(1.12); }
  .hotspot[data-covered="true"]:hover { transform: translate(-50%, -50%) translateX(var(--pan, 0px)); }
  .hotspot:active { transform: translate(-50%, -50%) translateX(var(--pan, 0px)) scale(1.02); }

  /* Die Maske wird zum Blatt am unteren Rand. Frei im Bild platziert deckt
     sie auf einem Telefon den ganzen Schirm zu - dann sieht man von der
     Fahrt nichts mehr, und die ist hier die Hauptsache. Unten steht sie
     ausserdem dort, wo der Daumen ist. site.js laesst left/top im
     Hochformat leer, damit diese Regeln greifen. */
  .hsheet {
    /* top aus der Grundregel ausdruecklich aufheben: sind top und bottom
       beide gesetzt, gewinnt top und das Blatt klebt wieder oben. */
    top: auto;
    right: 10px;
    bottom: 10px;
    width: auto;
    max-width: none;
    max-height: 48svh;
    transform: translateY(14px);
    transform-origin: 50% 100%;
  }
  .hsheet[data-open="true"] { transform: none; }
}

/* ---------- Der Film auf flachen Schirmen --------------------------------

   Ein liegendes Telefon ist 375 px hoch. Der 16:9-Rahmen wird dort 539 px
   breit und steht mit weissen Raendern in einem 812 px breiten Fenster,
   waehrend die Beschriftung quer ueber die Bedienpunkte laeuft.

   Also auch hier vollflaechig - aber ohne Fahrt: das Fenster ist breiter
   als 16:9, das Bild fuellt es in der Breite und wird oben und unten leicht
   beschnitten. Es gibt seitlich nichts zu fahren.
   ------------------------------------------------------------------------ */

@media (max-height: 540px) and (min-aspect-ratio: 5 / 4) and (max-width: 1100px) {
  .film__sticky { padding-top: 0; }
  .film__inner { height: 100%; }
  .film__frame {
    aspect-ratio: auto;
    width: 100%;
    height: 100svh;
  }
  .film__frame::after { display: none; }
  .layer__media { object-fit: cover; }
  .layer__img { object-fit: cover; }

  /* Unter der Kopfzeile anfangen: bei 62 px schnitt sie die Ueberschrift
     an, die Leiste endet bei 63. */
  .film__head { padding-top: 78px; padding-inline: clamp(18px, 3vw, 34px); }
  .film__scrim { height: 56%; }
  .cue__t { font-size: 21px; margin-bottom: 6px; }
  .cue__d { font-size: 13.5px; line-height: 1.4; max-width: 38ch; }
}

/* Auf sehr flachen Schirmen - ein liegendes Telefon hat 375 px - bleibt
   unter der Kopfzeile nur eine Handbreit. Der Erklaersatz faellt dort weg:
   sonst stoesst er auf den Bedienpunkt an der Waage, der bei 44 Prozent
   Hoehe sitzt. Die Ueberschrift nennt die Etappe, das Weitere steht in der
   Maske, die man dort oeffnet. */
@media (max-height: 460px) and (min-aspect-ratio: 5 / 4) and (max-width: 1100px) {
  .cue__d { display: none; }

  /* Die Maske darf nicht hoeher sein als der flache Schirm. */
  .hsheet { max-height: calc(100svh - 84px); }
}

/* ---------- Reduced motion ---------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
  }
  [data-reveal], .chain .step { opacity: 1 !important; transform: none !important; }
  .bar__v { transform: none !important; }
  .rise .w > i { transform: none !important; }
  .tailhead__sub { opacity: 1 !important; transform: none !important; }
  .supersign span { opacity: 1; transform: none; }
  .hero__intro, .hero__foot, .surface__cell, .hero__case { opacity: 1; transform: none; }
  .surface::before, .surface::after, .surface__split { transform: none; }
  .mark, .rings, .pulse__c, .tryout__chev, .tryout__mark i { animation: none !important; }
  .tl__stop { opacity: 1 !important; transform: none !important; }
  .logorow img { opacity: .72 !important; transform: none !important; }
  .triad li { opacity: 1 !important; transform: none !important; }
  .st { opacity: 1 !important; }
  .tryout__chev { opacity: .6 !important; }
  .chain .step__rail i { width: 100%; }
  .transit__img { filter: none !important; }
}

/* ---------- Print ------------------------------------------------------- */

@media print {
  .topbar, .hero__media, .cta__actions { display: none !important; }
  body { background: #fff; font-size: 10pt; }
  .band { padding-block: 14mm; break-inside: avoid; }
  .band--dark { background: #fff !important; color: #000 !important; }
  .band--dark .matrix th, .band--dark .matrix td { border-color: #ccc; }
}

/* ---------- Rechtsseiten -------------------------------------------------

   Impressum und Datenschutz liegen als eigene Seiten im Projekt, nicht als
   Verweis nach aussen: ein Angebot soll nicht auf eine Vorschauadresse
   zeigen, und die Datenschutzerklaerung muss beschreiben, was DIESE Seite
   tut - nicht, was der Marketingauftritt tut.

   Bewusst schmal und ruhig. Hier wird gelesen, nicht gescrollt.
   ------------------------------------------------------------------------ */

.legal { padding-block: clamp(40px, 6vw, 80px) clamp(60px, 8vw, 110px); }
.legal__inner { max-width: 74ch; }

.legal__back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: clamp(26px, 4vw, 44px);
  font-stretch: 86%;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 3px;
}
.legal__back:hover { color: var(--ink); border-bottom-color: var(--ink); }

.legal h1 {
  margin: 0 0 10px;
  font-size: clamp(30px, 4.4vw, 52px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.03em;
}
.legal__lead {
  margin: 0 0 clamp(30px, 4vw, 48px);
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.5;
  color: var(--ink-2);
}
.legal h2 {
  margin: clamp(32px, 4vw, 52px) 0 12px;
  font-size: clamp(18px, 1.8vw, 22px);
  font-weight: 600;
  letter-spacing: -0.015em;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.legal h3 {
  margin: 22px 0 8px;
  font-size: 15.5px;
  font-weight: 600;
}
.legal p, .legal li { font-size: 15.5px; line-height: 1.6; color: var(--ink-2); }
.legal p { margin: 0 0 12px; }
.legal ul { margin: 0 0 12px; padding-left: 20px; }
.legal li { margin-bottom: 5px; }
.legal a { color: var(--accent); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent) 36%, transparent); }
.legal a:hover { border-bottom-color: var(--accent); }
.legal strong { color: var(--ink); font-weight: 600; }

/* Die Anschrift steht als Block, nicht als Fliesstext. */
.legal address {
  font-style: normal;
  margin: 0 0 12px;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink);
}

/* Der Kasten hebt hervor, was diese Seite von einem Marketingauftritt
   unterscheidet - er ist die eigentliche Aussage der Erklaerung. */
.legal__box {
  margin: 20px 0 8px;
  padding: clamp(18px, 2vw, 24px);
  background: var(--paper-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}
.legal__box p:last-child { margin-bottom: 0; }

.legal__meta {
  margin-top: clamp(34px, 4vw, 52px);
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-3);
}

.legal__table { width: 100%; border-collapse: collapse; margin: 0 0 14px; }
.legal__table th, .legal__table td {
  text-align: left;
  vertical-align: top;
  padding: 9px 12px 9px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14.5px;
  line-height: 1.5;
}
.legal__table th { font-weight: 600; color: var(--ink); white-space: nowrap; }
.legal__table td { color: var(--ink-2); }
