@font-face{font-family:Geist;src:url(/assets/fonts/geist-sans.woff2) format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Geist Mono";src:url(/assets/fonts/geist-mono.woff2) format("woff2");font-weight:100 900;font-display:swap}

:root{
  --white:#ffffff; --paper:#f5f8fc;
  --ink:#0d1826; --ink-soft:#41566b; --muted:#6b7d8f; --line:#e4eaf1;
  --navy:#020914;
  --cyan:#19bff4; --cyan-ink:#0784b0; --cyan-soft:#e8f7fe;
  --bezel:#0b1422; --chrome:#101c2e; --chrome2:#0c1626;
  --page:clamp(22px,5vw,80px);
  --wrap:1180px;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body.web{margin:0;background:var(--white);color:var(--ink);
  font-family:Geist,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
img{max-width:100%;display:block}
h1,h2,h3{margin:0}
.skip{position:absolute;left:-999px;top:auto}
.skip:focus{left:16px;top:16px;z-index:99;padding:10px 16px;background:var(--navy);color:#fff;border-radius:8px}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

/* ---- Bausteine ---- */
.eyebrow{margin:0 0 14px;font-size:.8rem;font-weight:680;letter-spacing:.14em;text-transform:uppercase;color:var(--cyan-ink)}
.eyebrow--light{color:#6fd3f5}
.web-btn{display:inline-flex;align-items:center;justify-content:center;height:52px;padding:0 26px;border-radius:11px;
  background:var(--cyan);color:#00202e;font-weight:700;font-size:1rem;text-decoration:none;border:0;cursor:pointer;
  transition:transform .15s ease,background-color .15s ease,box-shadow .18s ease}
.web-btn:hover{transform:translateY(-1px);background:#43ccfb;box-shadow:0 12px 28px rgba(25,191,244,.32)}
.web-btn--lg{height:58px;padding:0 34px;font-size:1.06rem}
.web-link{display:inline-flex;align-items:center;gap:8px;color:var(--cyan-ink);font-weight:640;text-decoration:none}
.web-link::after{content:"→";transition:transform .2s ease}
.web-link:hover::after{transform:translateX(4px)}
.web-link--light{color:#8fdcf7}

/* ---- Fokus: sichtbar, einheitlich, nur bei Tastaturbedienung ----
   Ein sauberer Fokusring ist kein Detail fuer Spezialfaelle — er ist das,
   woran man eine sorgfaeltig gebaute Seite erkennt. */
:where(a,button,summary,[tabindex]):focus-visible{outline:2.5px solid var(--cyan-ink);outline-offset:3px;border-radius:5px}
.web-btn:focus-visible{outline-offset:4px}
.faq__item summary:focus-visible{outline-offset:-2px}

/* ---- Kopfleiste ------------------------------------------------------------
   Das Markup und die Mechanik liefern site-nav.css / site-nav.js — dieselbe
   Datei wie auf Startseite und /software, damit die Leiste ueberall gleich
   liegt und gleich heisst. Hier stehen nur die Farben.

   Die geteilte Datei setzt jede Farbe ueber eine Variable mit DUNKLEM
   Rueckfallwert. Diese Seite ist hell, also werden die Variablen hier
   umgesetzt — und nur hier, unter body.web. Die geteilte Datei anzufassen
   wuerde den hellen Kopf auch auf die dunklen Seiten ziehen. */
body.web{
  --nav-bg:rgba(255,255,255,.92);
  --nav-linie:var(--line);
  /* Logo voll schwarz, wie im alten Kopf dieser Seite (dort stand
     `filter:brightness(0)`). Ohne Filter kaeme das SVG in seinen Eigenfarben,
     der Rueckfallwert der geteilten Datei dreht es auf Weiss — beides ist auf
     dieser hellen Leiste falsch. */
  --nav-logo:brightness(0);
  --nav-ruhe:var(--ink-soft);
  --nav-hell:var(--ink);
  --nav-akzent:var(--cyan);
  --nav-akzent-hell:#43ccfb;
  --nav-akzent-text:#00202e;
  /* Auf Weiss reicht ein leiser Schein; der dunkle Rueckfallwert (.7) wirkt
     hier wie ein Leuchtstift. */
  --nav-glow:rgba(25,191,244,.42);
  /* Abschnitts-Schiene rechts: benutzt die Mechanik der Punkt-Schiene aus
     site-nav.css, sieht hier aber anders aus (unterteiltes Rechteck, weiter
     unten in dieser Datei). Diese Werte versorgen beide Fassungen. */
  --rail-ruhe:rgba(65,86,107,.32);
  --rail-hell:var(--ink);
  --rail-akzent:var(--cyan);
  --rail-glow:rgba(25,191,244,.55);
  --rail-chip:rgba(255,255,255,.96);
  --pill-linie:var(--line);
}
/* DAUERHAFT SICHTBAR statt transparent-bis-gescrollt.
   Die geteilte Datei laesst die Leiste ueber dem Hero transparent starten — das
   passt zu den dunklen Seiten, wo sie auf einem Bild liegt. Diese Seite ist hell
   und der Hero ist eine helle Szene: dort verschwindet eine transparente Leiste
   und der Kopf wirkt unfertig. So sah der alte Kopf dieser Seite aus, und so
   bleibt er. Der Schatten kommt dazu, weil eine weisse Leiste auf weissem Grund
   sonst nur an der Haarlinie haengt.
   box-shadow steht nicht in der transition der geteilten Datei, deshalb hier
   mitgegeben — sonst schnappt er beim Scrollen. */
body.web .topnav{
  background:rgba(255,255,255,.88);
  -webkit-backdrop-filter:blur(12px) saturate(1.1);backdrop-filter:blur(12px) saturate(1.1);
  border-bottom-color:var(--line);
  box-shadow:0 6px 24px -18px rgba(13,24,38,.5);
  transition:background-color .28s ease,border-color .28s ease,box-shadow .28s ease}
/* Gescrollt nur ETWAS praesenter — kein zweiter Zustand, nur mehr Tiefe. */
body.web .topnav.is-scrolled{background:rgba(255,255,255,.94);
  box-shadow:0 10px 30px -20px rgba(13,24,38,.62)}
/* Mobil faehrt die Leiste beim Runterscrollen nach oben aus dem Bild; die
   Klasse setzt hero.js. 64px sind auf einem Handy im Hero der Unterschied
   zwischen „Chip-Reihe im Bild" und „Chip-Reihe darunter" — und sie kommen
   hier her, statt das Geraet zu kuerzen (das war der vorherige Weg und hat
   das Handy auf kleinen Schirmen um 8 bis 15px gestaucht).
   Die drei Punkte bleiben stehen: der Griff ist position:fixed und haengt
   nicht an der Leiste.
   NUR mobil — auf dem Desktop ist die Leiste die Navigation der Seite und das
   Platzproblem gibt es dort nicht. */
@media(max-width:768px){
  body.web .topnav{transition:background-color .28s ease,border-color .28s ease,
    box-shadow .28s ease,transform .3s cubic-bezier(.4,0,.2,1)}
  body.web .topnav.is-weg{transform:translateY(-100%)}
}
@media(prefers-reduced-motion:reduce){
  body.web .topnav,body.web .topnav.is-weg{transition:none}
}

/* ------------------------------------------------- Abschnitts-Schiene ---
   Rechts am Rand: EIN Rechteck, quer unterteilt in ein Feld je Abschnitt.
   Markup, Mechanik und JS sind die der Punkt-Schiene aus site-nav.css --
   derselbe [data-snav]-Block, dieselbe Datei, keine zweite Zustaendigkeit
   fuer dieselbe Sache. Geaendert ist ausschliesslich die Optik, und zwar aus
   einem Grund: diese Seite spricht scharfe Kanten und Haarlinien (die
   Branchen-Karten, der Strich darunter). Runde Punkte wie auf /software sind
   hier Fremdsprache -- der Zusammenhang bleibt in der Position, der Mechanik
   und der Beschriftung, die Form darf die der Seite sein.

   Zwei Entscheidungen bewusst gegen die erste Skizze („ganz am Rand"):
   - NICHT buendig an der Kante und NICHT ueber die ganze Hoehe. Ein
     unterteilter Balken direkt am Fensterrand liest sich als Scrollleiste,
     und dann versuchen Leute zu ziehen. 38px breit (eine Scrollleiste ist
     ~12) und rund 200px hoch statt voller Hoehe nehmen die Verwechslung raus.
   - Jedes Feld traegt seine Haarlinie SELBST und ueberlappt den Nachbarn um
     1px, statt dass ein Rahmen um alles liegt. Dadurch entsteht das Rechteck
     beim Hereinfahren Feld fuer Feld, und im Hero steht nie ein leerer
     Rahmen herum. Mit Rahmen haette es einen :has()-Umweg gebraucht.

   Ausgeblendet wird sie nicht hier: site-nav.css nimmt .dotrail unter 768px
   und unter 520px Fensterhoehe schon raus. Auf dem Handy stehen die
   Abschnitte im Menue -- das JS laeuft weiter und versorgt es. */
/* Breite und Abstand sind GEMESSEN, nicht geschaetzt: der rechte Slider-Pfeil
   der Auftritte haengt per .arrow--r{right:-14px} absichtlich ueber die Kante
   seines Rahmens und ragt damit in denselben Seitenrand. Mit 38px Feldbreite
   und clamp(10px,1.5vw,22px) Abstand ueberlappten die beiden bei 1280/1366/
   1440px um 7/4/2px -- nie die Mitte des 44px-Knopfes, aber sein aeusserer
   Rand, und beim Vorbeiscrollen frisst das einen Klick. Der Pfeil war zuerst
   da, also weicht die Schiene: 34px breit, 10px Abstand. Nachgemessen bleiben
   damit bei 1280..1920px 8..22px Luft, auch wenn der Pfeil beim Hover auf
   scale(1.16) waechst (+3,5px je Seite). 34px sind immer noch mehr als das
   Doppelte einer Scrollleiste — die Verwechslung kommt dadurch nicht zurueck. */
body.web .dotrail--felder{
  right:10px;
  align-items:stretch;
  gap:0}

/* DIE KANTE IST EIN INSET-SCHATTEN, KEIN border — und das ist Voraussetzung
   fuer den Farbwechsel weiter unten, nicht Geschmack. Die Deckebene muss das
   Feld inklusive seiner Kante ueberdecken. Mit einem echten border liegt sie
   entweder darin (dann bleibt aussen eine helle Haarlinie stehen) oder sie
   ragt mit inset:-1px darueber hinaus — dann ueberlappen sich benachbarte
   Deckebenen um 3px und an jeder Naht stehen zwei Linien mit einem Pixel
   Abstand. Als Innenschatten liegt die Kante INNERHALB des Kastens, die
   Deckebene sitzt buendig auf inset:0 und beides passt genau aufeinander. */
body.web .dotrail--felder a{
  width:34px;height:40px;justify-content:center;
  background:var(--white);border:0;box-shadow:inset 0 0 0 1px var(--line);
  transition:opacity .32s ease,transform .44s cubic-bezier(.22,.7,.3,1),
             background-color .2s ease,box-shadow .2s ease}
/* Zwei Haarlinien zwischen zwei Feldern waeren eine doppelte Linie. */
body.web .dotrail--felder a + a{margin-top:-1px}
body.web .dotrail--felder a:hover{background:var(--paper);box-shadow:inset 0 0 0 1px rgba(65,86,107,.3)}
/* Das aktive Feld liegt VOR seinen Nachbarn: sonst schneidet die Haarlinie des
   naechsten Feldes seine Marke an der Unterkante an.
   Es behaelt seine HAARLINIE. Erster Versuch war ein Navy-Rahmen — angesehen
   liest man dann oben und unten zwei fette Querbalken, und aus dem einen
   unterteilten Rechteck wird eine Zelle, die aus dem Verbund herausspringt.
   Markiert wird stattdessen mit der Marke links und einer Spur Cyan im
   Hintergrund; die Ziffer geht ohnehin auf volles --ink. */
body.web .dotrail--felder a[aria-current="true"]{
  position:relative;z-index:1;background:var(--cyan-soft);box-shadow:inset 0 0 0 1px var(--line)}

/* ::after ist hier nicht der Punkt, sondern die Marke an der LINKEN Kante des
   Feldes: sie zeigt in die Seite hinein, nicht aus ihr heraus. Die Masse der
   Punkt-Fassung (7x7, rund, margin, scale-transform) muessen alle zurueck. */
/* Die Marke sass auf der AUSSENKANTE des frueheren border, also bei -1px. Seit
   die Kante ein Innenschatten ist, liegt dieselbe Stelle bei 0. */
body.web .dotrail--felder a::after{
  position:absolute;z-index:2;left:0;top:0;bottom:0;
  width:2px;height:auto;margin:0;border-radius:0;
  background:var(--rail-akzent);box-shadow:none;
  transform:scaleY(0);transform-origin:50% 50%;
  transition:transform .28s cubic-bezier(.22,.7,.3,1),opacity .28s ease}
body.web .dotrail--felder a[aria-current="true"]::after{transform:scaleY(1)}

/* ---- Fortschritt: EINE durchgezogene Linie ueber die ganze Schiene -------
   Ein Zwischenstand hat die Marke am aktiven Feld zum Fortschrittsbalken
   gemacht — die faengt dann aber in jedem Abschnitt wieder bei null an und
   liest sich als fuenf kleine Balken statt als ein Weg durch die Seite.
   Jetzt eine Linie ueber die volle Hoehe der Schiene, gefuellt von oben nach
   dem Stand der GANZEN Seite.
   SIE STEHT AUF DER ANDEREN SEITE. Die Abschnittsmarke sitzt links am Feld;
   beide an derselben Kante waeren zwei Linien uebereinander. Rechts ist
   ausserdem die richtige Seite: dort liegt der Fensterrand, und ein
   Fortschritt gehoert an den Rand, nicht in die Sache hinein.
   Zwei Elemente, weil die Bahn ueber die volle Hoehe steht und die Fuellung
   nur bis --seite. Beide ohne Transition — der Stand soll exakt mitgehen und
   nicht nachlaufen. */
body.web .dotrail--felder::before,
body.web .dotrail--felder::after{content:"";position:absolute;right:-5px;top:0;width:2px;
  z-index:2;pointer-events:none;
  /* NEBEN der Schiene, nicht auf ihr, und darueber. Auf right:0 lag die Linie
     genau auf der rechten Kante der Felder — die sind deckend, und das aktive
     traegt z-index:1, also war sie ausgerechnet an der interessanten Stelle
     verdeckt. Jetzt sitzt sie in der Luecke zwischen Schiene und Fensterrand
     (die Schiene steht auf right:10px, die Linie belegt davon 3 bis 5px) und
     liegt mit z-index:2 ueber allem, was in der Schiene passiert. */
  /* MUSS mit der Schiene kommen, nicht vorher. Die Felder stehen beim Laden auf
     opacity:0 und blenden sich einzeln ein, sobald ihr Abschnitt dran ist — eine
     Linie, die sofort da ist, haengt bis dahin allein am Fensterrand und sieht
     nach Fehler aus. :has() fragt, ob ueberhaupt schon ein Feld eingeblendet
     wurde; die Klasse dafuer setzt site-nav.js ohnehin. */
  opacity:0;transition:opacity .32s ease}
body.web .dotrail--felder:has(a.is-da)::before,
body.web .dotrail--felder:has(a.is-da)::after{opacity:1}
body.web .dotrail--felder::before{bottom:0;background:rgba(25,191,244,.16)}
body.web .dotrail--felder::after{height:calc(var(--seite,0) * 100%);background:var(--rail-akzent)}

/* site-nav.css versteckt <b> — die Punkt-Fassung braucht keine Nummer. Hier
   traegt jedes Feld seine, sonst stehen dort fuenf leere Kaestchen. Farbe
   NICHT --rail-ruhe: das ist ein Punktgrau (rund 1,6:1 auf Weiss) und als
   Ziffer unlesbar. --ink-soft liegt bei etwa 7:1. */
/* GROESSE UND GEWICHT MUESSEN HIER UND AN DER DECKEBENE GLEICH SEIN. Die Zahl
   wird an der Naht aus zwei Haelften zusammengesetzt — unten die gezeichnete,
   oben diese. Weichen sie ab, sitzt die Naht in zwei verschieden grossen
   Ziffern und es sieht aus wie ein Darstellungsfehler.
   Von .62rem/600 auf .72rem/700 hochgesetzt: auf Dunkel war die Zahl trotz
   Weiss nicht zu entziffern, und das lag nicht am Kontrast (15,5:1), sondern
   an 9,9px feiner Mono. Helle Striche auf dunklem Grund brauchen mehr Flaeche,
   nicht mehr Kontrast. Das Feld ist 34px breit, zwei Ziffern auf 11,5px
   brauchen rund 14px — Platz ist reichlich. */
body.web .dotrail--felder a b{
  display:block;position:static;right:auto;opacity:1;pointer-events:none;
  font:700 .72rem/1 "Geist Mono","Geist",ui-monospace,monospace;
  letter-spacing:.02em;color:var(--ink-soft);
  /* --mx ist die Anziehung zum Zeiger, die site-nav.js je Bild schreibt. In
     der Punkt-Fassung bewegt sie den Punkt; hier darf sich der Rahmen nicht
     verziehen — also geht nur die Ziffer ein Stueck mit, gedaempft auf ein
     Drittel. Das Rechteck bleibt starr, lebendig ist der Inhalt. */
  transform:translateX(calc(var(--mx,0px) * .34));
  transition:color .2s ease,transform .18s cubic-bezier(.22,.7,.3,1)}
body.web .dotrail--felder a:hover b,
body.web .dotrail--felder a[aria-current="true"] b{color:var(--ink)}

/* Die Beschriftung faehrt links aus dem Feld. Zwei Aenderungen gegenueber der
   Punkt-Fassung:
   - right:20px ist dort auf einen 7px-Punkt gerechnet; am 34px-Feld laege der
     Chip zur Haelfte darauf.
   - Das Aussehen. Diese Seite hat schon eine Tooltip-Sprache: .arrow__tip an
     den Slider-Pfeilen der Auftritte — dunkles Navy, helle Schrift, 7px
     Radius. Die geteilte Datei macht daraus eine weisse Pille mit 999px. Zwei
     verschiedene Tooltips auf derselben Seite waere einer zu viel, also folgt
     die Schiene dem, was hier schon steht. */
body.web .dotrail--felder a span{
  right:calc(100% + 9px);
  height:auto;padding:5px 10px;border-radius:7px;
  font-size:.76rem;font-weight:600;letter-spacing:0;
  color:#eaf3fb;background:var(--navy);
  box-shadow:0 6px 18px rgba(2,9,20,.4)}

/* Die Welle der Punkt-Fassung schiebt jeden Punkt waagerecht heraus. In einem
   starren Rechteck waere genau das ein Defekt. Also laeuft statt der Bewegung
   ein Licht durch die Marken, von oben nach unten — derselbe Gedanke („ein
   Ruck laeuft durch"), in der Form, die diese Schiene erlaubt. Das aktive
   Feld bleibt aussen vor: seine Marke soll nicht kurz verschwinden. */
@keyframes feldWelle{
  0%,100%{transform:scaleY(0);opacity:0}
  32%    {transform:scaleY(1);opacity:1}
  66%    {transform:scaleY(1);opacity:.4}
}
body.web .dotrail--felder.is-welle a.is-da::after{animation:none}
body.web .dotrail--felder.is-welle a.is-da:not([aria-current="true"])::after{
  animation:feldWelle .8s cubic-bezier(.25,.6,.3,1) calc(var(--i,0) * 85ms)}

/* Sprungreserve. site-nav.js schaltet mit der Schiene html.snav-an, und
   site-nav.css setzt darueber scroll-margin-top: nav-hoehe + 16px. Die 16px
   rechnen mit Sektionen ohne eigenes Polster -- diese hier haben 100px
   (Desktop) bzw. 52px (mobil) oben. Zusammen standen nach einem Sprung 116px
   bzw. 68px Leere ueber der Ueberschrift.
   Richtig ist genau die Leistenhoehe: dann beginnt die Sektion unmittelbar
   unter der Leiste und ihr eigenes Polster macht den Abstand, so wie ohne
   Leiste auch. Ohne diese Zeile war es umgekehrt falsch -- ohne Schiene gab es
   gar keine Reserve, und gemessen verschwanden auf 390px 12 von 17px der
   Eyebrow-Zeile hinter der Leiste. Nur fuer diese Seite: /software hat andere
   Polster und behaelt den geteilten Wert. */
/* NUR DESKTOP, und die Grenze ist gemessen statt gesetzt. site-nav.css nimmt
   .dotrail erst unter 768px raus -- das passt zu /software, nicht zu dieser
   Seite: hier steht im Rand schon der rechte Slider-Pfeil der Auftritte. Von
   769 bis 1279px reicht der Rand fuer beide nicht. Gemessen (Luft zwischen
   Pfeil und Schiene / zwischen Schiene und Case-Karte):
        769px  -20px / -6px      1024px  -7px /  7px
        900px  -13px /  1px      1100px  -3px / 11px
       1000px   -8px /  6px      1180px   1px / 15px
       1280px    6px / 20px  <-- erste Breite, bei der beides frei liegt
   Bei 769px lag die Schiene also auf der Karte. Ab 1280px hat der Pfeil auch
   im Hover (scale 1.16, +3,5px je Seite) noch Luft. Darunter uebernimmt das
   Menue die Abschnitte -- genau wie auf dem Handy.
   Das JS laeuft in jedem Fall weiter: html.snav-an und damit die Sprungreserve
   unten haengen an der Schiene im Markup, nicht an ihrer Sichtbarkeit. */
/* ---- Farbwechsel PIXELGENAU an der Sektionskante ------------------------
   Die Schiene haengt fest am Fensterrand und belegt dort 44px (10px Abstand
   plus 34px Breite). Mit weissem Grund stanzte sie ein helles Loch in den
   dunklen Takt und in den Abschluss — es wirkte, als waere die Sektion rechts
   abgeschnitten. (Nachgemessen ist sie das nicht: .takt ist auf 1920px genau
   1920px breit. Es war die Schiene.)

   Eine erste Fassung hat die ganze Schiene umgeschaltet, sobald eine dunkle
   Sektion ihr Band erreichte. Jetzt wechselt sie an der KANTE: liegt die Naht
   zwischen hell und dunkel mitten in einem Feld, ist der obere Teil des Feldes
   hell gestaltet und der untere dunkel — auf den Pixel.

   WIE: jedes Feld traegt eine zweite, rein zeichnerische Ebene (::before) in
   der dunklen Fassung, buendig darueber, und die wird beschnitten. Sichtbar ist
   von ihr genau der Teil, der ueber Dunkel liegt; darueber und darunter ist sie
   weggeschnitten. clip-path ist dabei nicht animiert — der Sinn der Sache ist,
   dass sie exakt mitgeht und nicht nachlaeuft.
   Sie zeichnet die Ziffer NEU (content:attr(data-nr)), weil auch die Zahl an der
   Naht umschlagen muss; ein Pseudoelement kann den echten <b> nicht umfaerben.
   Deshalb steht die Nummer im Markup zweimal — einmal als Text fuer Vorlese-
   programme und Auswahl, einmal als Attribut fuer die Deckebene.
   Die Werte --dk-o (Schnitt von oben) und --dk-u (von unten) setzt hero.js.
   Ohne JS bleibt --dk-o auf 100%: dann ist die Deckebene komplett weg und die
   Schiene sieht aus wie immer.
   Die Deckebene liegt UNTER dem Tooltip und unter der Cyan-Marke: beide sind
   spaeter im Baum (span) bzw. spaeter als Pseudoelement (::after) und malen
   damit darueber. Genau so soll es sein. */
body.web .dotrail--felder a::before{
  content:attr(data-nr);
  /* z-index IST NOETIG, und der Grund ist unauffaellig: die echte Ziffer traegt
     ein transform (die Zeiger-Anziehung, --mx). Transformierte Elemente malen
     in DERSELBEN Ebene wie positionierte, und darin nach Baumreihenfolge — das
     <b> steht nach dem ::before, also lag die dunkle Ziffer ueber der weissen.
     Am Pixel gemessen: der hellste Punkt in der Ziffer war (136,145,155) statt
     Weiss, weil vom weissen Glyph nur der Kantensaum durchkam. Mit z-index
     liegt die Deckebene wieder oben. */
  position:absolute;inset:0;z-index:1;box-sizing:border-box;
  display:grid;place-items:center;
  /* NAVY ZUERST, dann derselbe helle Schleier darueber. Die Deckebene liegt auf
     dem WEISSEN Feld — ein blosses rgba(255,255,255,.055) waere dort Weiss auf
     Weiss und damit unsichtbar. Erst deckt sie das Feld mit der Sektionsfarbe
     zu, dann kommt der Schleier, der die Kachel vom Grund abhebt. So steht die
     Rechnung im Code statt eines von Hand ausgemischten Hexwerts: aendert sich
     --navy, geht die Kachel automatisch mit. */
  background:linear-gradient(rgba(255,255,255,.10),rgba(255,255,255,.10)),var(--navy);
  /* Echter Rahmen statt Innenschatten: der Hintergrund laeuft unter ihm durch,
     also mischt sich sein Alpha mit dem Navy darunter und nicht mit dem hellen
     Feld. Mit border-box deckt er genau die Stelle, an der das Feld selbst
     seine Kante zeichnet. */
  border:1px solid rgba(255,255,255,.28);
  /* WEISS. Die helle Seite stellt die Ziffer in --ink-soft auf Weiss, also
     auf 7,6:1 — dieselbe Zahl umgekehrt ergibt eine Ziffer, die duenner WIRKT
     als sie ist: helle Striche auf dunklem Grund werden vom Auge schmaler
     gelesen, und bei 9,9px Mono kippt das ins Unleserliche. Zwei
     Zwischenstaende belegen es: #8fa6bd lag bei 6,4:1 und war nicht zu
     entziffern, #d6e3f0 bei 12,3:1 und ging gerade so. Weiss auf der Fuellung
     sind 15,5:1, und mehr geht nicht — hier ist kein Spielraum zu holen, also
     nimmt man das Ende der Skala. */
  color:#fff;
  font:700 .72rem/1 "Geist Mono","Geist",ui-monospace,monospace;
  letter-spacing:.02em;
  pointer-events:none;
  clip-path:inset(var(--dk-o,100%) 0 var(--dk-u,0px) 0);
  transition:background-color .2s ease,border-color .2s ease,color .2s ease}
body.web .dotrail--felder a:hover::before{
  background:linear-gradient(rgba(255,255,255,.16),rgba(255,255,255,.16)),var(--navy);
  border-color:rgba(255,255,255,.42);color:#fff}
body.web .dotrail--felder a[aria-current="true"]::before{
  background:linear-gradient(rgba(25,191,244,.24),rgba(25,191,244,.24)),var(--navy);
  border-color:rgba(255,255,255,.28);color:#fff}
/* Die Zeiger-Anziehung schiebt die ECHTE Ziffer waagerecht (--mx aus
   site-nav.js), die gezeichnete auf der Deckebene aber nicht — sie kann sich
   nicht getrennt von ihrem Kasten bewegen. In einem GETEILTEN Feld liefen die
   beiden Haelften derselben Ziffer damit um bis zu 4px auseinander. In genau
   diesem Fall steht die Ziffer still; hero.js setzt die Klasse. Ausserhalb der
   Naht bleibt die Anziehung wie sie war. */
body.web .dotrail--felder a.is-geteilt b{transform:none}
/* Der Tooltip ist selbst navy und steht neben der Schiene, also immer ueber
   derselben Flaeche wie das Feld, aus dem er kommt. Eine Kante bekommt er
   pauschal — auf Hell stoert sie nicht, auf Navy traegt sie die Form. */
body.web .dotrail--felder a span{border:1px solid rgba(255,255,255,.15)}

@media(max-width:1279px){
  body.web .dotrail--felder{display:none}
}

html.snav-an body.web [id]{scroll-margin-top:var(--nav-hoehe,80px)}

@media(prefers-reduced-motion:reduce){
  body.web .dotrail--felder a,body.web .dotrail--felder a::after,
  body.web .dotrail--felder a b{transition:none}
  body.web .dotrail--felder.is-welle a.is-da:not([aria-current="true"])::after{
    animation:none}
}

/* ======================================================================
   HERO — Monitor-Raum (Live-Vorschau, Deviceswitch, Feierabend-Egg)
   portiert aus raum-prototype.html · self-contained, unter .stage gescoped
   ====================================================================== */
/* min-height ZWEIMAL: svh gibt es erst ab Safari 15.4 / iOS 15.4. Aeltere
   Browser verwerfen die zweite Zeile und behalten 100vh, neuere nehmen svh
   (die kleine Ansicht mit ausgefahrener Adressleiste — die stabile). Ohne
   den Rueckfall haette die Stage dort gar keine Mindesthoehe. */
.stage{position:relative;min-height:100vh;min-height:100svh;overflow:hidden;
  display:grid;grid-template-columns:.68fr 1.32fr;gap:clamp(20px,2.4vw,36px);align-items:end;
  /* Oben die Leistenhoehe mitrechnen: .topnav ist FIXED und belegt keinen
     Platz im Fluss (die alte .web-head war sticky und tat es). Ohne das laege
     der Hero unter der Leiste. --nav-hoehe kommt aus site-nav.css und ist dort
     unter 768px selbst schon kleiner. */
  padding:calc(var(--nav-hoehe,80px) + clamp(14px,2vw,26px)) clamp(22px,5vw,80px) clamp(48px,6vw,80px);
  background:
    radial-gradient(1000px 540px at 78% 12%,rgba(140,175,210,.10),transparent 60%),
    linear-gradient(180deg,#fdfdfe 0%,#f7f9fc 55%,#eef2f7 100%)}
.stage__text{align-self:center}
.rig{align-self:end;margin-bottom:clamp(14px,2.5vh,32px)}
/* Full-bleed-Szene: cozy Grossraumbuero in Tiefenebenen */
.szene{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.layer{position:absolute;left:0;right:0;bottom:0;will-change:transform}
.layer svg{display:block;width:100%;height:auto}
.layer--wand{top:-24px;bottom:clamp(100px,14vh,160px)}
.layer--wand svg{width:100%;height:100%}
.pendant{position:absolute;top:-24px;width:92px;transform:translateX(-50%);z-index:0;pointer-events:none}
.pendant svg{display:block;width:100%;height:auto}
/* ===== Feierabend-Easter-Egg: Tasse klicken -> Nacht + Lampe an -> Sonnenaufgang ===== */
.prop--mug{cursor:pointer;pointer-events:auto}
.night-veil{position:absolute;inset:0;z-index:0;pointer-events:none;opacity:0;transition:opacity 2.4s ease;
  background:radial-gradient(1100px 640px at 58% 4%, rgba(30,140,200,.16), transparent 62%),
             linear-gradient(180deg,#060e1c 0%,#0a1526 52%,#0b1832 100%)}
.stage.is-night .night-veil{opacity:1}
.stage.is-sunrise .night-veil{transition:opacity 3.2s ease}
/* Sonnenaufgang: das warme Licht STEIGT (background-position wandert hoch), am Fenster verankert */
.sun{position:absolute;inset:0;z-index:0;pointer-events:none;opacity:0;
  background:radial-gradient(1080px 820px at 54% 16%, rgba(255,196,118,.66), rgba(255,168,92,.22) 43%, transparent 65%);
  background-size:100% 175%;background-position:50% 92%;background-repeat:no-repeat;
  transition:opacity 2.6s ease,background-position 4.2s cubic-bezier(.32,.12,.22,1)}
.stage.is-sunrise .sun{opacity:1;background-position:50% 0%}
.eyebrow,.stage__text h1,.h1promise,.lead,.trustmarks li,.dsw__hint{transition:color 1.6s ease}
.stage.is-night .eyebrow,.stage.is-night .stage__text h1,.stage.is-night .h1promise,.stage.is-night .lead,.stage.is-night .trustmarks li,.stage.is-night .dsw__hint{transition-delay:.9s}
.stage.is-night .eyebrow{color:#63d2f8}
.stage.is-night .stage__text h1{color:#eff6fd}
.stage.is-night .h1promise{color:#96acc1}
.stage.is-night .lead,.stage.is-night .trustmarks li{color:#b0c4d8}
.stage.is-night .dsw__hint{color:#8298ae}
.szene__nebel,.layer--wand,.szene__boden,.szene__licht{transition:opacity 1.9s ease}
.stage.is-night .szene__nebel{opacity:0}
.stage.is-night .layer--wand{opacity:.42}
.stage.is-night .szene__boden{opacity:.22}
.stage.is-night .szene__licht{opacity:0}
/* Fenster: draussen wird es dunkel */
.layer--wand rect[fill]{transition:fill 2.2s ease,fill-opacity 2.2s ease}
.stage.is-night .layer--wand rect[fill]{fill:#0b1c31;fill-opacity:.85}
/* Moebel gehorchen dem Licht: Tische/Umschalter dimmen mit */
.deviceswitch{transition:filter 2s ease}
.stage.is-night .desk{filter:brightness(.5) saturate(.7)}
.stage.is-night .deviceswitch{filter:brightness(.62)}
/* ---- Der BILDSCHIRM ist nachts die Lichtquelle ----
   Einspaltig gibt es keine Pendelleuchte mehr (sie ist ein Zweispalten-Element).
   Was einen abends anleuchtet, ist ohnehin der Monitor — erzaehlerisch passender
   fuer eine Web-Agentur als eine Lampe. Der Screen glueht und wirft Licht nach
   unten auf die Tischplatte. */
.stage.is-night .monitor{box-shadow:14px 42px 90px -24px rgba(2,9,20,.8),
  0 0 74px -6px rgba(31,155,208,.42),0 0 0 1px rgba(70,170,220,.20)}
.monitor::after{content:"";position:absolute;left:50%;top:100%;width:190%;height:clamp(90px,16vw,170px);
  transform:translateX(-50%);pointer-events:none;opacity:0;
  background:radial-gradient(58% 100% at 50% 0%,rgba(126,208,246,.34),rgba(126,208,246,.12) 46%,transparent 74%);
  transition:opacity 1.3s ease}
.stage.is-night .monitor::after{opacity:1;transition-delay:.45s}
@media(prefers-reduced-motion:reduce){.monitor::after{transition:none}}
/* Lampe schnappt AN (kurz nach der Daemmerung), statt traege zu faden */
.pendant svg{transition:stroke .45s ease}
.pendant svg path{transition:fill .45s ease}
.pendant{transition:filter .6s ease}
.stage.is-night .pendant svg{stroke:var(--cyan);transition-delay:1.05s}
.stage.is-night .pendant svg path{fill:rgba(25,191,244,.5);transition-delay:1.05s}
.stage.is-night .pendant{filter:drop-shadow(0 3px 15px rgba(25,191,244,.55));transition-delay:1.05s}
/* Einschalt-Flackern: Glow-Schicht zuckt 2x, dann steht sie */
.pendant__glow{position:absolute;left:50%;top:126px;width:132px;height:66px;transform:translateX(-50%);border-radius:50%;pointer-events:none;
  opacity:0;background:radial-gradient(closest-side,rgba(25,191,244,.55),rgba(25,191,244,.16) 62%,transparent);filter:blur(11px);transition:opacity .7s ease}
.stage.is-night .pendant__glow{animation:lampFlick 1.05s linear .82s both}
@keyframes lampFlick{0%,50%{opacity:0}56%{opacity:.75}63%{opacity:.12}72%{opacity:.9}79%{opacity:.38}88%,100%{opacity:1}}
/* Lichtkegel waechst nach unten, sobald die Lampe an ist */
.pendant::after{content:"";position:absolute;left:50%;top:168px;transform:translateX(-50%) scaleY(.5);transform-origin:top center;width:380px;height:400px;pointer-events:none;
  opacity:0;transition:opacity .9s ease,transform 1.2s cubic-bezier(.3,.7,.25,1);
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 380 400' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='v' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%2319bff4' stop-opacity='.34'/%3E%3Cstop offset='.5' stop-color='%2319bff4' stop-opacity='.11'/%3E%3Cstop offset='1' stop-color='%2319bff4' stop-opacity='0'/%3E%3C/linearGradient%3E%3Cfilter id='f' x='-30%25' y='-15%25' width='160%25' height='130%25'%3E%3CfeGaussianBlur stdDeviation='10'/%3E%3C/filter%3E%3C/defs%3E%3Cpolygon points='146,4 234,4 380,396 0,396' fill='url(%23v)' filter='url(%23f)'/%3E%3Cpolygon points='168,4 212,4 306,396 74,396' fill='url(%23v)' filter='url(%23f)' opacity='.6'/%3E%3C/svg%3E") center/100% 100% no-repeat}
.stage.is-night .pendant::after{opacity:1;transform:translateX(-50%) scaleY(1);transition-delay:1.15s}
.layer--buero{bottom:clamp(74px,10.5vh,124px);transform:scale(.9);transform-origin:bottom center}
.szene__boden{position:absolute;left:0;right:0;bottom:0;height:clamp(110px,15vh,170px);
  background:linear-gradient(180deg,#e9eef5,#dde4ed);border-top:1px solid #dbe3ed}
.szene__licht{position:absolute;left:27%;bottom:clamp(110px,15vh,170px);width:300px;height:46%;
  transform:skewX(-13deg);transform-origin:bottom left;
  background:linear-gradient(180deg,rgba(175,205,235,0),rgba(175,205,235,.22));filter:blur(2px)}
/* Licht-Nebel unter der Textspalte: traegt die Lesbarkeit ueber der Szene */
.szene__nebel{position:absolute;left:-6%;top:6%;width:52%;height:82%;
  background:radial-gradient(ellipse at 38% 46%,rgba(252,253,255,.94) 0%,rgba(252,253,255,.6) 46%,transparent 72%)}
.stage__text,.rig{position:relative;z-index:1}
/* Szene ist statisch — Ruhe. Nur Miniscreens dezent gedimmt. */
.miniscreen{opacity:.82}
.stage__text{max-width:470px}
.stage__text h1{margin:0 0 18px;font-size:clamp(2.1rem,3.6vw,3.2rem);line-height:1.05;letter-spacing:-.035em;font-weight:720}
.h1promise{display:block;font-size:.5em;font-weight:600;color:var(--ink-soft);letter-spacing:-.01em;line-height:1.15;margin-top:.42em}
/* ---- Ansicht-Umschalter: kleine Desk-Illustration (Monitor=Desktop, Handy davor=Mobil) ---- */
.deviceswitch{position:absolute;z-index:4;right:calc(100% + clamp(8px,1.6vw,30px));bottom:31px;
  display:flex;flex-direction:column;align-items:center;gap:2px}
.dsw__stage{position:relative;width:186px;height:140px}
.dsw__desk{position:absolute;left:0;bottom:0;width:100%}
.dsw__dev{position:absolute;padding:0;border:0;background:none;cursor:pointer;line-height:0;opacity:.7;transform-origin:center bottom;
  transition:opacity .18s ease,transform .18s ease,filter .2s ease;-webkit-tap-highlight-color:transparent}
.dsw__dev svg{display:block;width:100%;height:auto;overflow:visible}
.dsw__dev--desk{left:22px;bottom:53px;width:112px}
.dsw__dev--phone{left:124px;bottom:52px;width:42px}
.dsw__frame{stroke:#8397ab;stroke-width:2.4;fill:none;stroke-linejoin:round;stroke-linecap:round}
.dsw__screen{fill:rgba(25,191,244,.12)}
.dsw__dev:hover{opacity:1;transform:scale(1.02);filter:drop-shadow(0 0 7px rgba(25,191,244,.4))}
.dsw__dev:hover .dsw__frame{stroke:var(--ink)}
.dsw__dev.is-active{opacity:1}
.dsw__dev.is-active .dsw__frame{stroke:var(--cyan-ink)}
.dsw__dev.is-active .dsw__screen{fill:var(--cyan)}
/* Einmaliger Cyan-Lichtstreifen am Rahmen beim ersten Erscheinen (kein Dauer-Puls) */
.dsw__beam{fill:none;stroke:var(--cyan);stroke-width:2.8;stroke-linejoin:round;stroke-linecap:round;opacity:0;stroke-dasharray:15 85;stroke-dashoffset:15}
.deviceswitch.dsw-lit-desk .dsw__dev--desk .dsw__beam{animation:frameBeam 1.35s ease-in-out 1}
.deviceswitch.dsw-lit-phone .dsw__dev--phone .dsw__beam{animation:frameBeam 1.2s ease-in-out 1}
@keyframes frameBeam{0%{opacity:0;stroke-dashoffset:15}12%{opacity:.95}86%{opacity:.9}100%{opacity:0;stroke-dashoffset:-85}}
.dsw__hint{font-size:.78rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:-4px}
.dsw__txt{display:none}     /* Beschriftung nur mobil, wo die Tasten Text brauchen */
.hl{position:relative;white-space:nowrap}
.hl::after{content:"";position:absolute;left:-.05em;right:-.13em;bottom:.03em;height:.34em;background:var(--cyan);opacity:.34;z-index:-1;
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 40' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='0'/%3E%3Cstop offset='0.007' stop-color='%23fff' stop-opacity='0.65'/%3E%3Cstop offset='0.018' stop-color='%23fff' stop-opacity='1'/%3E%3Cstop offset='0.24' stop-color='%23fff' stop-opacity='0.94'/%3E%3Cstop offset='0.42' stop-color='%23fff' stop-opacity='1'/%3E%3Cstop offset='0.58' stop-color='%23fff' stop-opacity='0.93'/%3E%3Cstop offset='0.74' stop-color='%23fff' stop-opacity='1'/%3E%3Cstop offset='0.88' stop-color='%23fff' stop-opacity='0.97'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='1'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M3 13C6 9.5 12 7.8 20 7.5 33 7 44 5.8 55 5.2 70 4.4 82 3.4 95 3 112 2.5 126 4 140 4.4 156 4.8 170 3 185 2.6 202 2.2 216 3.6 230 4 244 4.4 256 2.9 268 2.6 280 3.4 290 5.4 297.4 8.2C299.4 11.6 298.4 16.4 299.5 20.8C299.9 24.4 298.6 28.6 296.8 31.6C288 34.6 276 36.4 264 37 242 38 218 36.3 194 37.1 170 37.9 148 36.2 124 37 100 37.8 78 36.3 56 35.7 42 35.2 30 33.2 20 32 12 31 6 29.5 3 27Z'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 40' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='0'/%3E%3Cstop offset='0.007' stop-color='%23fff' stop-opacity='0.65'/%3E%3Cstop offset='0.018' stop-color='%23fff' stop-opacity='1'/%3E%3Cstop offset='0.24' stop-color='%23fff' stop-opacity='0.94'/%3E%3Cstop offset='0.42' stop-color='%23fff' stop-opacity='1'/%3E%3Cstop offset='0.58' stop-color='%23fff' stop-opacity='0.93'/%3E%3Cstop offset='0.74' stop-color='%23fff' stop-opacity='1'/%3E%3Cstop offset='0.88' stop-color='%23fff' stop-opacity='0.97'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='1'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M3 13C6 9.5 12 7.8 20 7.5 33 7 44 5.8 55 5.2 70 4.4 82 3.4 95 3 112 2.5 126 4 140 4.4 156 4.8 170 3 185 2.6 202 2.2 216 3.6 230 4 244 4.4 256 2.9 268 2.6 280 3.4 290 5.4 297.4 8.2C299.4 11.6 298.4 16.4 299.5 20.8C299.9 24.4 298.6 28.6 296.8 31.6C288 34.6 276 36.4 264 37 242 38 218 36.3 194 37.1 170 37.9 148 36.2 124 37 100 37.8 78 36.3 56 35.7 42 35.2 30 33.2 20 32 12 31 6 29.5 3 27Z'/%3E%3C/svg%3E");
  -webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  transition:opacity 1.1s ease,filter 1.1s ease}
/* Marker faengt das Lampenlicht: glueht, sobald die Leuchte an ist */
.stage.is-night .hl::after{opacity:.88;transition-delay:1.15s;
  filter:drop-shadow(0 0 9px rgba(25,191,244,.65)) drop-shadow(0 0 24px rgba(25,191,244,.38))}
.lead{margin:0 0 24px;max-width:40ch;font-size:clamp(1.05rem,1.35vw,1.22rem);line-height:1.55;color:var(--ink-soft)}
/* margin-top ist PFLICHT, seit die Trust-Zusagen VOR dem Button stehen: die
   Liste hat nur oben Abstand (margin:22px 0 0), vorher lag sie hinter dem
   Button und das ging auf. Ohne das klebt der Button am letzten Bullet. */
.cta-row{display:flex;align-items:center;gap:22px;flex-wrap:wrap;margin-top:28px}
/* ---- Der Haken ist GEZEICHNET, nicht bebildert -------------------------
   Vorher stand hier ein gefuellter Kreis mit weissem Haken darin. Das ist die
   Standardform, die jede zusammengeklickte Seite benutzt — und genau deshalb
   liest sie sich wie von der Stange, egal wie gut sie sitzt.
   Diese Seite markiert sonst mit 2px-Haarlinien (Kartenoberkanten, Taktlinie,
   Schienenmarke) und mit einem gekippten Quadrat (Referenzpunkte). Ein Haken in
   derselben Strichstaerke gehoert in diese Reihe, ein Abzeichen nicht: der
   Kreis war das einzige Element auf der Seite, das seine Bedeutung in eine
   gefuellte Flaeche gepackt hat.
   STUMPFE ENDEN, SPITZE ECKE (kein stroke-linecap/linejoin) — runde Enden sind
   der zweite Teil des Von-der-Stange-Eindrucks. Die Strichstaerke 2,3 liegt
   zwischen den 2px der Kartenkanten und den 2,4px des FAQ-Winkels.
   Als MASKE statt als Hintergrundbild: damit steht die Farbe in CSS und nicht
   in einer Datei-URL, der Nachtmodus kann sie mitziehen, und dieselbe Form
   dient beiden Listen in zwei Groessen. */
.trustmarks,.zusage__punkte{
  --haken:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 8.4 6.3 12.7 14 3.6' fill='none' stroke='%23000' stroke-width='2.3'/%3E%3C/svg%3E")}
.trustmarks{display:flex;flex-direction:column;gap:9px;margin:22px 0 0;padding:0;list-style:none}
.trustmarks li{position:relative;padding-left:22px;
  font-size:.9rem;font-weight:560;color:var(--ink-soft);white-space:nowrap;
  transition:color 1.6s ease}
.trustmarks li::before{content:"";position:absolute;left:0;top:.14em;
  width:14px;height:14px;background:var(--cyan);
  -webkit-mask:var(--haken) 0 0/14px 14px no-repeat;
          mask:var(--haken) 0 0/14px 14px no-repeat}

/* ================= Rig (Monitor + Desk) ================= */
.rig{position:relative;justify-self:end;width:min(100%,50vw,1060px)}
.monitor{position:relative;z-index:2;width:100%;margin:0 auto;border-radius:14px;background:var(--bezel);padding:9px 9px 0;
  box-shadow:14px 42px 70px -28px rgba(13,24,38,.32),0 0 0 1px rgba(13,24,38,.08),inset 0 1px 0 rgba(255,255,255,.06)}
.monitor__chin{display:flex;align-items:center;justify-content:center;height:26px}
.led{width:5px;height:5px;border-radius:50%;background:#22374f;transition:background .8s ease,box-shadow .8s ease}
.is-on .led{background:var(--cyan);box-shadow:0 0 8px rgba(25,191,244,.9)}
.monitor__hals{width:30px;height:52px;margin:0 auto;background:linear-gradient(180deg,#1a2a3d,#0e1a2a);border-radius:0 0 6px 6px}
.monitor__base{width:180px;height:11px;margin:-2px auto 0;border-radius:7px;background:linear-gradient(180deg,#22354b,#101f31);
  box-shadow:0 12px 18px -8px rgba(13,24,38,.30)}
/* ---- Vordergrund: Holztisch + Props ---- */
.desk{position:relative;z-index:1;margin-top:-7px}
.desk__top{position:relative;height:17px;border-radius:9px;background:linear-gradient(180deg,#eef2f8,#dfe6ef);
  box-shadow:0 1px 0 #d0dbe7,0 18px 28px -14px rgba(13,24,38,.20)}
.desk__legs{display:flex;justify-content:space-between;padding:0 11%}
.desk__legs i{width:12px;height:66px;border-radius:0 0 5px 5px;background:linear-gradient(180deg,#cfd9e4,#bfccda)}
.desk__teppich{position:absolute;left:-9%;right:-9%;bottom:-10px;height:26px;border-radius:50%;
  background:radial-gradient(ellipse at center,#e6ebf2 0%,#dde4ed 62%,transparent 74%)}
.prop{position:absolute;z-index:3;bottom:100%;pointer-events:none}
/* Tasse: eigenes Rig-Kind auf z3 (ueber dem Monitor, z2) — sonst verschwindet der Dampf dahinter */
.prop--mug{right:9%;bottom:80px;width:60px;pointer-events:auto;cursor:pointer;
  transition:transform .18s ease,opacity .4s ease,filter 2s ease}
.prop--mug:hover{transform:translateY(-2px) scale(1.05)}
.stage.is-night .prop--mug{filter:brightness(.6) saturate(.75)}
.is-phone .prop--mug,.rig.is-morphing .prop--mug{opacity:0;pointer-events:none}
.prop--notiz{right:14%;width:92px;margin-bottom:-5px}
.prop--sukku{right:4%;width:46px;margin-bottom:-2px}
/* Dampf: steigt nur waehrend des Feierabend-Moments aus der Tasse (Klick) */
.dampf{opacity:0}
.stage.is-brewing .dampf{animation:dampfZug 2.4s ease-in-out infinite}
.stage.is-brewing .dampf--b{animation-duration:2.9s;animation-delay:.7s}
@keyframes dampfZug{0%{opacity:0;transform:translateY(5px)}30%{opacity:.85}70%{opacity:.3}100%{opacity:0;transform:translateY(-8px)}}

/* ---- Einmaliger Anstoss der Tasse (nur mobil) --------------------------
   Warum ueberhaupt: auf dem Handy gibt es keinen Cursor und kein Hover, die
   Tasse ist 44px gross und sitzt am Rand — es existiert schlicht kein Hinweis,
   dass sie etwas kann. Also meldet sie sich einmal selbst.
   EINMAL, nicht in Schleife: eine wiederkehrende Bewegung im Blickfeld liest
   sich als Werbebanner. Zwei kurze Hopser statt eines langen — ein einzelner
   Ruck sieht aus wie ein Ruckler, zwei lesen sich als Absicht (dasselbe
   Muster wie ein Kopfnicken).
   Der Schein ist Cyan, weil die Tasse selbst schon einen Cyan-Streifen traegt
   und Cyan auf dieser Seite „hier ist etwas" bedeutet.
   transform-origin unten: die Tasse kippt aus ihrem Stand, nicht aus der Mitte,
   sonst schwebt sie. */
/* Gilt auf JEDER Breite. Der Wink war zuerst nur mobil, weil dort Cursor und
   Hover fehlen — auf dem Desktop fuehrt er trotzdem zum selben Ziel: die Tasse
   ist auch dort nur eine Tasse, bis sie sich einmal meldet.
   transform-origin unten, damit sie aus ihrem Stand kippt und nicht schwebt.
   Waehrend der Nacht nie: dort hat die Szene ohnehin die Aufmerksamkeit, und
   die Nachtregel setzt einen eigenen filter, mit dem die Animation streiten
   wuerde. */
.prop--mug{transform-origin:50% 88%}
.prop--mug.is-wink{animation:tasseWink 1.55s cubic-bezier(.3,.72,.35,1) both}
.stage.is-night .prop--mug.is-wink{animation:none}

@keyframes tasseWink{
  0%   {transform:translateY(0) rotate(0deg);   filter:drop-shadow(0 0 0 rgba(25,191,244,0))}
  12%  {transform:translateY(-7px) rotate(-5deg);filter:drop-shadow(0 3px 10px rgba(25,191,244,.55))}
  27%  {transform:translateY(0) rotate(0deg)}
  40%  {transform:translateY(-4px) rotate(3.5deg);filter:drop-shadow(0 3px 12px rgba(25,191,244,.42))}
  55%  {transform:translateY(0) rotate(0deg)}
  100% {transform:translateY(0) rotate(0deg);   filter:drop-shadow(0 0 0 rgba(25,191,244,0))}
}

/* ================= Browser im Screen ================= */
.browser{border-radius:10px;overflow:hidden;background:var(--chrome);
  opacity:0;filter:brightness(.35) saturate(.6);transition:opacity .9s ease,filter 1.1s ease}
.is-on .browser{opacity:1;filter:none}
.tabsbar{display:flex;align-items:flex-end;gap:5px;height:38px;padding:7px 10px 0;background:var(--chrome2)}
.btab{display:inline-flex;align-items:center;gap:8px;max-width:198px;height:31px;padding:0 13px;border:0;cursor:pointer;
  border-radius:8px 8px 0 0;background:transparent;color:#8ea1b5;font:560 .8rem/1 Geist,sans-serif;letter-spacing:.005em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .15s,color .15s;-webkit-tap-highlight-color:transparent}
.btab:hover{background:#16243a66;color:#c4d2e0}
.btab[aria-selected="true"]{background:var(--chrome);color:#eaf2fa}
.btab i{width:7px;height:7px;border-radius:50%;flex:0 0 auto;background:var(--tabdot,#6b7d8f)}
.btab--neu i{display:none}
.btab--neu::before{content:"+";font-size:1rem;font-weight:600;color:var(--cyan);margin-right:2px}

/* Laufendes Projekt: das Tab-Puenktchen pulst, statt still zu stehen — ein
   zweites Signal neben dem Schild in der Vorschau, damit der Tab auch auffaellt,
   waehrend ein anderer offen ist. */
/* Der Punkt selbst bleibt stehen — bewegt wird nur ein weicher Ring um ihn
   herum. Vorher liefen Deckkraft UND Skalierung: einen 7px-Punkt zu skalieren
   heisst, ihn ueber wenige Pixel zu rastern, und jeder Zwischenschritt rundet
   sichtbar anders — das flackert, statt zu atmen. Ein Ring aus box-shadow hat
   keine harte Kante, die rastern koennte, und laeuft deshalb glatt. Dazu
   langsamer (3.6s statt 2.4s) und mit flacherer Kurve. */
.btab--wip i{animation:wipAtem 3.6s cubic-bezier(.37,0,.63,1) infinite}
@keyframes wipAtem{
  0%,100%{box-shadow:0 0 0 0 rgba(29,154,219,.5);opacity:1}
  55%    {box-shadow:0 0 0 4px rgba(29,154,219,0);opacity:.78}
}

/* Schild UNTER dem Geraet, nicht darueber: eine Bildunterschrift verdeckt nichts
   und braucht keinen pointer-events-Trick. Erscheint nur, wenn der betreffende
   Tab offen ist (.rig.is-wip), und nur auf Desktop — dort zeigt das Mockup die
   Desktop-Ansicht, also genau das, was hier noch fehlt. Auf Mobil sieht der
   Besucher ohnehin die fertige Ansicht, da waere der Hinweis irrefuehrend. */
.wipnote{position:absolute;left:0;display:none;margin:13px 0 0;align-items:center;gap:8px;
  padding:6px 12px 6px 10px;border-radius:999px;background:#ffffffcc;border:1px solid #d7e0ea;
  color:#42586e;font:600 .78rem/1.3 Geist,sans-serif;letter-spacing:.01em;white-space:nowrap;
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.wipnote span{color:#8ba0b5;font-weight:400}
.wipnote i{width:6px;height:6px;border-radius:50%;flex:0 0 auto;background:#1D9ADB;
  animation:wipAtem 3.6s cubic-bezier(.37,0,.63,1) infinite}

@media (min-width:1001px){
  .rig.is-wip .wipnote{display:flex}
}

.chip--wip::before{content:"";display:inline-block;width:6px;height:6px;margin-right:6px;
  border-radius:50%;background:#1D9ADB;vertical-align:middle;
  animation:wipAtem 3.6s cubic-bezier(.37,0,.63,1) infinite}

@media (prefers-reduced-motion:reduce){
  .btab--wip i,.wipnote i,.chip--wip::before{animation:none}
}
.urlbar{display:flex;align-items:center;gap:10px;height:38px;padding:0 12px;background:var(--chrome)}
.urlfield{display:flex;align-items:center;gap:8px;flex:1;height:26px;min-width:0;padding:0 12px;border-radius:13px;background:#0a1322;
  color:#9fb2c6;font:400 .76rem/1 "Geist Mono",monospace;overflow:hidden;white-space:nowrap}
.urlfield svg{width:11px;height:11px;flex:0 0 auto;color:#5d7590}
.urllive{flex:0 0 auto;color:var(--cyan);font:600 .76rem/1 Geist,sans-serif;text-decoration:none;opacity:.85}
.urllive:hover{opacity:1}

/* View + Pages */
.view{position:relative;aspect-ratio:16/9;background:#0a1322;overflow:hidden;touch-action:pan-y}
.track{display:flex;height:100%;transition:transform .55s cubic-bezier(.3,.86,.28,1)}
.page{position:relative;flex:0 0 100%;height:100%}
.page__frame{position:absolute;top:0;left:0;border:0;display:block;background:#fff;transform-origin:top left;width:100%;height:100%}
.page__scroll{height:100%;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none}
.page__scroll::-webkit-scrollbar{width:0;height:0;display:none}
.page__scroll img{width:100%;height:auto}
.page__fade{position:absolute;left:0;right:0;bottom:0;height:70px;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(10,19,34,.82));display:flex;align-items:flex-end;justify-content:center;padding-bottom:12px;
  opacity:0;transition:opacity .3s}
.is-live .page.is-active .page__fade{opacity:1}
.page__fade a{color:#bfe9fb;font:600 .8rem/1 Geist,sans-serif;text-decoration:none;pointer-events:auto}
.page__fade a:hover{color:#fff}

/* Hint-Overlay (Klick aktiviert Scroll) */
.scrollcue{position:absolute;top:12px;bottom:12px;right:7px;width:4px;border-radius:3px;background:rgba(255,255,255,.1);z-index:3;opacity:0;transition:opacity .45s ease .35s;pointer-events:none}
.is-on .scrollcue{opacity:1}
.scrollcue__thumb{position:absolute;left:0;right:0;top:0;height:26%;border-radius:3px;background:rgba(127,208,242,.55);transition:top .12s linear,height .12s linear}
.hintcover{position:absolute;inset:0;z-index:4;display:flex;align-items:flex-end;justify-content:center;
  padding-bottom:22px;border:0;background:linear-gradient(180deg,transparent 55%,rgba(10,19,34,.42));cursor:pointer;
  opacity:1;transition:opacity .3s;-webkit-tap-highlight-color:transparent}
.hintcover span{display:inline-flex;align-items:center;gap:9px;height:38px;padding:0 18px;border-radius:19px;
  background:rgba(10,19,34,.86);color:#eaf2fa;font:600 .85rem/1 Geist,sans-serif;
  box-shadow:0 6px 22px rgba(2,9,20,.4),inset 0 0 0 1px rgba(25,191,244,.35)}
.hintcover span::before{content:"";width:7px;height:11px;border-radius:4px;border:1.5px solid var(--cyan);border-bottom-width:4px}
.is-neu .hintcover,.rig.is-interactive .hintcover{opacity:0;pointer-events:none}
/* Maus-Geraete: kein Klick-Gate — Hover aktiviert direkt (JS), Overlay entfaellt */
@media(hover:hover){.hintcover{display:none}}

/* =====================================================================
   AUSKLAPPEN (nur mobil) — das Handy startet eingerollt: sichtbar sind
   Tableiste, Adressleiste und der Griff. Ein Tipp fahrt den Bildschirm
   nach unten aus, der Viewport geht mit.
   WOZU: das Geraet ist ausgefahren rund 500px hoch. Eingerollt kostet es
   85px, und der Besucher sieht trotzdem sofort, WAS drin ist -- in der
   Adressleiste steht die echte Kundendomain, in der Tableiste stehen die
   Kundennamen. Der Beweis ist also da, bevor man tippt.
   Alle Regeln haengen an .rv-on (setzt das Inline-Skript im <head>):
   ohne JavaScript gibt es kein Ausklappen, dann muss das Handy offen sein.
   ===================================================================== */
.unfold{display:none}
@media(max-width:700px){
  .rv-on .rig.is-phone .unfold{display:flex;align-items:center;justify-content:center;gap:8px;
    width:100%;height:46px;padding:8px 0 0;border:0;background:var(--chrome);
    color:#dceaf5;font:620 .87rem/1 Geist,sans-serif;letter-spacing:.005em;
    cursor:pointer;-webkit-tap-highlight-color:transparent;position:relative}
  /* Greiferstrich: sagt „hier" ohne ein weiteres Wort und trennt den Griff
     optisch von der Adressleiste, die dieselbe Farbe hat. */
  .rv-on .rig.is-phone .unfold::before{content:"";position:absolute;top:5px;left:50%;
    transform:translateX(-50%);width:36px;height:3px;border-radius:2px;background:rgba(255,255,255,.16)}
  .rv-on .rig.is-phone .unfold:active{background:#1b2637}
  .rv-on .rig.is-phone .unfold__pfeil{width:17px;height:17px;color:var(--cyan);flex:0 0 auto;
    transition:transform .5s cubic-bezier(.22,.61,.36,1)}
  /* Ausgefahren zeigt der Pfeil nach oben — dieselbe Taste klappt wieder zu. */
  .rv-on .rig.is-phone:not(.is-folded) .unfold__pfeil{transform:rotate(180deg)}

  /* Die Hoehe setzt das JS in Pixeln (0 bzw. Breite * 15.5/9). Ein Wechsel
     zwischen aspect-ratio-Hoehe und fixer Hoehe laesst sich NICHT animieren --
     transition:height braucht auf beiden Seiten einen Pixelwert.

     DAUER UND KURVE STEHEN NUR HIER. Das JS liest --fahrt aus, um die
     Viewport-Fahrt und das Nachladen darauf zu synchronisieren; zwei getrennte
     Werte wuerden auseinanderlaufen.
     Die Kurve ist genau easeOutCubic — das JS rechnet fuer die Viewport-Fahrt
     1-(1-p)^3, also dieselbe Kurve. Sonst sind es zwei Bewegungen statt einer. */
  .rv-on .rig.is-phone{--fahrt:760ms}
  .rv-on .rig.is-phone .view{transition:height var(--fahrt) cubic-bezier(.215,.61,.355,1)}
  .rv-on .rig.is-phone.is-folded .view{aspect-ratio:auto}
  /* Bis die Kundenseite wirklich steht, bleibt der Bildschirm ruhig dunkel und
     blendet dann auf. Ohne das poppt der Inhalt hart herein, sobald das iframe
     fertig ist — auf einem langsamen Geraet mitten in die Bewegung. */
  .rv-on .rig.is-phone .track{transition:opacity .34s ease}
  .rv-on .rig.is-phone.is-leer .track{opacity:0}
  .rv-on .rig.is-phone.is-leer .hintcover{opacity:0;pointer-events:none}
  .rv-on .rig.is-folded .scrollcue{opacity:0}
  /* Eingerollt ist „Live ansehen" verfrueht — man hat die Seite noch nicht gesehen. */
  .rv-on .rig.is-folded .urllive{opacity:0;pointer-events:none}
  .rv-on .rig.is-folded .urlbar{transition:none}

  /* Die Szene faehrt mit auf: eingerollt ist das Geraet 98px hoch, die
     Fensterflaeche aber 420px — sie stand als leerer Rahmen hinter dem Text.
     Und die Tasse sass auf der Geraeteecke, also teilweise auf dem Tippziel.
     Beides kommt zurueck, sobald ausgefahren ist: der Raum oeffnet sich
     zusammen mit dem Handy. Das Easter Egg ist damit erst nach dem Ausfahren
     erreichbar — vorher gibt es ohnehin nichts zu sehen. */
  .rv-on .stage.is-eingerollt .layer--wand{opacity:0}
  .rv-on .stage.is-eingerollt .prop--mug{opacity:0;pointer-events:none}
  .rv-on .stage .layer--wand{transition:opacity .45s ease}
}
@media(prefers-reduced-motion:reduce){
  /* Selektoren MUESSEN so spezifisch sein wie die Regeln oben (.rv-on .rig
     .is-phone .view = vier Klassen). Mit .rig.is-phone .view hat es verloren und
     das Handy fuhr trotz reduce animiert aus — nachgemessen: nach 260ms erst
     381 von 465px. Media Queries erhoehen die Spezifitaet nicht. */
  .rv-on .rig.is-phone .unfold__pfeil,
  .rv-on .rig.is-phone .track,
  .rv-on .rig.is-phone .view{transition:none}
}
/* Touch: Vorschau erst nach Antippen bedienbar. Vorher faengt das iframe den
   vertikalen Wisch ab und der Nutzer kommt auf der Seite nicht weiter. */
@media(hover:none){
  .rig:not(.is-interactive) .page__frame{pointer-events:none}
}

/* "Dein Projekt"-Tab */
.neu{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;height:100%;text-align:center;
  background:linear-gradient(180deg,#f8fbfe,#eef4fa);color:var(--ink);padding:24px}
.neu h3{margin:0;font-size:clamp(1.3rem,2.6vw,1.9rem);letter-spacing:-.02em;font-weight:710}
.caret{display:inline-block;width:2px;height:1em;margin-left:3px;background:var(--cyan-ink);vertical-align:-.12em;animation:blink 1.05s steps(1) infinite}
@keyframes blink{50%{opacity:0}}
.neu p{margin:0;max-width:34ch;color:var(--ink-soft);font-size:.95rem;line-height:1.5}
.neu .web-btn{height:46px;padding:0 22px;font-size:.92rem}
/* ---- Feierabend im dritten Tab: hier entsteht gerade Code ----------------
   Warum hier und nicht ueber der Live-Vorschau: die Vorschau IST das Argument
   der Seite. Dieser Tab ist leer, hier kostet der Effekt nichts.

   AUFBAU: Einladung und Editor liegen UEBEREINANDER in einem Grid-Feld, der
   Knopf darunter. Die Buehne ist immer so hoch wie ihre hoechste Ebene, also
   aendert sich beim Wechsel keine Hoehe -- vorher fiel die Einladung am Ende
   ihrer Blende aus dem Layout und der Knopf sprang um 60px.

   ALLE Transitions stehen in den BASIS-Regeln, nicht in den .is-night-Regeln.
   Sonst gelten sie nur auf dem Hinweg, und der Rueckweg zum Tag schnappt. */
.neu{position:relative;transition:color .9s ease}
/* Die Nacht als eigene Ebene DARUEBER, nur ein- und ausgeblendet. Von einem
   Gradient auf einen anderen animiert der Browser nicht zuverlaessig. Absolut
   positioniert, also kein Flex-Item -- das Layout bleibt unberuehrt. */
.neu::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;
  background:linear-gradient(180deg,#0b1727,#050d19);
  /* HIN und ZURUECK unterschiedlich lang: die Basisregel gilt auf dem Rueckweg
     zum Tag, die .is-night-Regel auf dem Hinweg. Das Aufhellen darf laenger
     dauern — es ist die Aufloesung, nicht der Auftritt. */
  transition:opacity .9s ease}
.stage.is-night .neu::before{opacity:1;transition:opacity .55s ease}
.stage.is-night .neu{color:#dceaf5;transition:color .55s ease}
.neu > *{position:relative;z-index:1}

/* Die Buehne traegt die Monoschrift, damit sich 34ch genau EINMAL aufloest.
   Vorher hatten Dateiname (11,5px) und Code (12,5px) je eigene ch-Breiten,
   waren beide zentriert und standen dadurch 56px versetzt. */
.neu__buehne{display:grid;place-items:center;width:100%;max-width:34ch;
  font:500 clamp(10px,1.05vw,12.5px)/1.7 "Geist Mono",monospace}
.neu__tag,.neu__editor{grid-area:1/1;width:100%}
/* Die Einladung braucht ihre eigene Schrift zurueck (die Buehne ist mono). */
.neu__tag{display:flex;flex-direction:column;align-items:center;gap:13px;
  font:1rem/1.5 Geist,-apple-system,"Segoe UI",Roboto,sans-serif;
  transition:opacity .55s ease .3s}
.stage.is-night .neu__tag{opacity:0;pointer-events:none;transition:opacity .3s ease .08s}

/* visibility statt display: so bleibt die Hoehe des Editors IMMER im Layout
   und die Buehne behaelt ihr Mass. Mit display:none waere die Buehne tags
   niedriger und der Knopf wuerde beim Wechsel doch wieder wandern. */
.neu__editor{position:relative;text-align:left;padding-left:16px;
  visibility:hidden;opacity:0;transform:translateY(7px);
  transition:opacity .55s ease,transform .55s ease,visibility .55s}
.stage.is-night .neu__editor.is-offen{visibility:visible;opacity:1;transform:none;
  transition:opacity .4s ease,transform .45s cubic-bezier(.22,.61,.36,1),visibility .4s}
/* Der Bundsteg als eigene Ebene, damit er sich ZEICHNEN kann. Als border-left
   waere er sofort in ganzer Laenge da -- das Zeichnen ist der Moment, in dem
   die Datei aufgeht. */
.neu__editor::before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;
  background:rgba(25,191,244,.26);transform:scaleY(0);transform-origin:top;
  transition:transform .6s ease}
.stage.is-night .neu__editor.is-offen::before{transform:scaleY(1);
  transition:transform .55s cubic-bezier(.22,.61,.36,1) .18s}
/* Dateiname mit Punkt davor, wie ein ungespeicherter Reiter im Editor. */
.neu__datei{display:flex;align-items:center;gap:7px;margin:0 0 11px;
  font-size:.72rem;font-weight:600;letter-spacing:.1em;color:#6b8299}
.neu__datei::before{content:"";width:6px;height:6px;border-radius:50%;
  background:var(--cyan);flex:0 0 auto}
.neu__code{display:block;margin:0;color:#8fd8f5;white-space:pre;letter-spacing:.01em}

/* Waehrend der Nacht steht in der Adressleiste localhost (s. hero.js) --
   ein Link "Live ansehen" waere daneben ein Widerspruch. */
.stage.is-night .urllive{opacity:0;pointer-events:none}
/* Der Knopf steht unter der Buehne: erst die Regel, dann das Ergebnis.
   0.9s statt der 0.18s von .web-btn -- das ist Hover-Tempo und laesst das
   Leuchten schnappen statt warm werden. */
.neu .web-btn{transition:box-shadow .9s ease,transform .15s ease,background-color .15s ease}
/* DAS ERGEBNIS: sobald der Code fertig getippt ist, setzt das JS is-gluehend.
   WICHTIG: die drei Schattenwerte muessen mit dem Codetext im HTML
   uebereinstimmen -- sonst zeigt die Seite eine Regel, die sie nicht anwendet. */
.stage.is-night .neu.is-gluehend .web-btn{
  box-shadow:0 0  0 1px var(--cyan),
             0 0 22px -4px var(--cyan),
             0 0 64px -10px var(--cyan)}
@media(prefers-reduced-motion:reduce){
  .neu,.neu::before,.neu__tag,.neu__editor,.neu__editor::before,
  .neu .web-btn{transition:none}
  .stage.is-night .neu__editor{transform:none}
  .stage.is-night .neu__editor.is-offen::before{transform:scaleY(1)}
}
/* Leiser Hinweis, dass in dem Tab etwas passiert. Kein Blinken: das zieht
   mehr Aufmerksamkeit als der Effekt wert ist. */
.stage.is-night .btab--neu{color:var(--cyan)}

/* Pfeile + Chips */
.arrow{position:absolute;z-index:6;top:50%;transform:translateY(-50%);width:44px;height:44px;
  border:0;background:none;padding:0;cursor:pointer;display:grid;place-items:center;will-change:transform;
  filter:drop-shadow(0 2px 5px rgba(2,9,20,.55));transition:transform .16s ease,filter .16s ease;-webkit-tap-highlight-color:transparent}
.arrow:hover{transform:translateY(-50%) scale(1.16);filter:drop-shadow(0 3px 8px rgba(2,9,20,.7))}
.arrow svg{width:27px;height:27px}
.arrow svg path{fill:#fff;stroke:#fff;stroke-width:1.4;stroke-linejoin:round}
.arrow--l{left:-14px}.arrow--r{right:-14px}
.arrow__tip{position:absolute;top:50%;transform:translateY(-50%);white-space:nowrap;pointer-events:none;
  background:var(--navy);color:#eaf3fb;font-size:.76rem;font-weight:600;padding:5px 10px;border-radius:7px;
  opacity:0;transition:opacity .16s ease;box-shadow:0 6px 18px rgba(2,9,20,.4)}
.arrow--l .arrow__tip{left:calc(100% + 9px)}
.arrow--r .arrow__tip{right:calc(100% + 9px)}
.arrow:hover .arrow__tip{opacity:1}
.chips{display:none;justify-content:center;gap:8px;margin-top:18px;flex-wrap:wrap}
.chip{height:36px;padding:0 15px;border-radius:18px;border:1px solid var(--line);background:#fff;color:var(--ink-soft);
  font:600 .82rem/1 Geist,sans-serif;cursor:pointer;transition:all .15s;-webkit-tap-highlight-color:transparent}
.chip[aria-selected="true"]{background:var(--ink);border-color:var(--ink);color:#fff}

/* ---- Device-Morph: Monitor <-> Handy ---- */
.monitor{transition:width .6s cubic-bezier(.5,.02,.2,1),height .6s cubic-bezier(.5,.02,.2,1),border-radius .5s ease,padding .45s ease,box-shadow .5s ease}
.browser{display:flex;flex-direction:column}
.rig:not(.is-phone) .view{aspect-ratio:16/9;flex:0 0 auto}
.is-phone .view{flex:1 1 auto;min-height:0}
.page__scroll img{width:100%;height:auto;display:block}
.tabsbar{transition:height .35s ease,opacity .28s ease,padding .35s ease}
.is-phone .tabsbar{height:0;padding-top:0;opacity:0;overflow:hidden;pointer-events:none}
.monitor__hals,.monitor__base{transition:opacity .3s ease,height .4s ease}
.is-phone .monitor__hals{opacity:0}
.is-phone .monitor__base{opacity:0}
.is-phone .urlbar{justify-content:center}
.is-phone .urllive{display:none}
.is-phone .monitor{display:flex;flex-direction:column;border-radius:44px;padding:13px;
  box-shadow:0 46px 84px -32px rgba(13,24,38,.5),0 0 0 1px rgba(13,24,38,.10),inset 0 1px 0 rgba(255,255,255,.06)}
.is-phone .browser{flex:1 1 auto;min-height:0;border-radius:31px}
.monitor__chin{transition:height .35s ease,opacity .3s ease}
.is-phone .monitor__chin{height:0;overflow:hidden;opacity:0}
.desk{transition:opacity .4s ease,filter 2s ease}
.is-phone .desk{opacity:0}
.rig.is-morphing .monitor{display:flex;flex-direction:column}
.rig.is-morphing .browser{flex:1 1 auto;min-height:0}
.rig.is-morphing .view{flex:1 1 auto;min-height:0;aspect-ratio:auto}
.track{transition:transform .55s cubic-bezier(.3,.86,.28,1),opacity .22s ease}
.rig.is-morphing .track{opacity:0}
/* =====================================================================
   EINSPALTIG (ab hier steht das Geraet UNTER dem Text).
   Alles, was von der Spaltenzahl abhaengt, gehoert in DIESEN Breakpoint —
   nicht in den 700er. Ich hatte Lampe und Fenster zuerst nur unter 700px
   umgestellt; zwischen 701 und 1000px war das Layout aber schon einspaltig
   und die Leuchte hing wieder 53px im Text (gemessen). Merke: Szenen-Geometrie
   folgt dem LAYOUT-Breakpoint, Geraete-/Bedien-Regeln dem 700er.
   ===================================================================== */
@media(max-width:1000px){
  .stage{grid-template-columns:1fr;gap:34px;align-items:start;padding-top:64px}
  .stage__text{max-width:640px}
  .rig{width:100%;justify-self:center}
  .szene__licht{display:none}
  .layer--buero{opacity:.55}

  /* Fenster/Wand in den unteren Bereich, hinter das Geraet — sonst laufen die
     Rahmenlinien quer durch Eyebrow und Lead. */
  .layer--wand{top:auto;height:min(50%,420px);bottom:clamp(92px,12vh,140px)}
  .szene__nebel{display:none}   /* war der Lesbarkeits-Nebel der Textspalte; ohne Fenster dahinter ohne Funktion */

  /* PENDELLEUCHTE RAUS (Basti: „nimmt unnoetig Platz weg, eher scheisse").
     Sie ist ein Zweispalten-Element: dort haengt sie ueber der Headline und hat
     einen Sinn. Einspaltig braeuchte sie ~78px reservierte Hoehe ueber dem
     Geraet und brachte optisch nichts. Der Platz geht ans Geraet. */
  .pendant{display:none}

  /* Nacht-Kante weich auslaufen lassen.
     Der Schleier liegt in .stage. Auf dem Desktop ist die Stage 100svh hoch und
     fuellt den Schirm — einspaltig ist der Hero ~1200px bei ~850px Fenster,
     dadurch sah man Dunkelheit und direkt darunter die naechste Sektion in
     vollem Weiss (harte Linie quer durchs Bild). Die Maske laesst Schleier und
     Sonne auf den letzten ~10% auslaufen, der Uebergang wird dadurch ein
     Verlauf statt einer Kante. */
  .night-veil,.sun{
    -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 88%,transparent 100%);
    mask-image:linear-gradient(180deg,#000 0%,#000 88%,transparent 100%)}
}
/* =====================================================================
   HERO MOBIL — eigene Komposition, nicht der geschrumpfte Desktop.
   Kernentscheidungen:
   · Fenster liegt NUR hinter dem Geraet, nie hinter dem Text
   · Lampe haengt ueber dem GERAET (Position via placeLamp), nicht ueber der H1
   · Standard ist die HANDY-Ansicht: die Kundenseite ist bei ~0.67 lesbar,
     der Desktop-Screenshot waere bei 0.26 nur ein Bild
   ===================================================================== */
@media(max-width:700px){
  .stage{gap:26px;padding-top:calc(var(--nav-hoehe,64px) + 20px)}
  .layer--buero{display:none}

  /* ---- Textblock: EIN gap statt vieler Einzelabstaende ----
     Vorher trug jedes Element seine eigene margin und die Abstaende wirkten
     gequetscht und ungleich. Flex + gap regelt den Rhythmus an einer Stelle. */
  .stage__text{display:flex;flex-direction:column;gap:1.5rem}
  .stage__text>*{margin-top:0;margin-bottom:0}
  .stage__text h1{margin:0}
  .trustmarks{margin:0;gap:11px}
  .cta-row{margin:0}

  /* ---- CTA ueber die volle Breite ----
     Auf dem Handy ist ein breiter Button das deutlich bessere Touch-Ziel und
     liest sich als klarer naechster Schritt statt als Randnotiz. */
  .cta-row{display:block}
  .cta-row .web-btn{width:100%;height:56px;font-size:1.04rem}

  /* --- Geraet: Handy-Ansicht (Standard) --- */
  .is-phone .monitor{width:min(288px,76vw);height:auto;display:block;padding:9px;
    border-radius:32px;box-shadow:0 26px 50px -24px rgba(13,24,38,.5),0 0 0 1px rgba(13,24,38,.10)}
  .is-phone .browser{border-radius:24px}
  .is-phone .view{flex:none;aspect-ratio:9/15.5;min-height:0}
  .is-phone .urlbar{height:34px}

  /* --- Geraet: Desktop-Ansicht (per Umschalter) ---
     Feste Landschafts-Proportion statt fixer Hoehe: mit height:min(58vh,436px)
     wurde das Bild bei ~610px Breite fast quadratisch (Verhaeltnis 1.23) und las
     sich nicht mehr als Monitor. 16/10 ist eindeutig Landschaft und spart Hoehe. */
  .rig:not(.is-phone) .monitor{padding:7px 7px 0;border-radius:13px}
  .rig:not(.is-phone) .view{aspect-ratio:16/10;height:auto}

  /* WICHTIG: Handy ist mobil der Standard — die Desktop-Regeln blenden im
     is-phone-Zustand aber Tisch und Tasse aus. Damit waeren sie mobil DAUERHAFT
     weg: kein Tisch unter dem Geraet und das Feierabend-Egg unerreichbar.
     Hier zurueckgeholt; das Handy liegt auf dem Tisch. */
  .is-phone .desk{opacity:1}
  .is-phone .prop--mug{opacity:1;pointer-events:auto}
  /* Hals und Standfuss auf Null: ein Handy hat keinen Monitorfuss. Auf dem
     Desktop behalten sie ihre Hoehe (Reflow-Schutz beim Morph) — mobil gibt es
     keinen Morph, also darf hier kollabiert werden. */
  .is-phone .monitor__hals{height:0}
  .is-phone .monitor__base{height:0;margin-top:0}

  .tabsbar{display:none}
  /* 8 statt 14: nachgemessen war die Reihe nach dem Ausklappen auf 390x664 um
     3px angeschnitten. Zusammen mit den 5px am Monitorpolster sind es 11px —
     danach steht sie mit 8px Luft im Bild. */
  .chips{display:flex;margin-top:8px}
  /* Die Chip-Reihe stand hier zwischenzeitlich 46px HOEHER, also im Band der
     Tischbeine — das war noetig, solange die Kopfleiste 64px belegte und die
     Reihe sonst unter der Bildkante lag.
     Seit die Leiste beim Runterscrollen wegfaehrt, gibt es den Platz, und die
     Reihe steht wieder da, wo sie hingehoert: UNTER der Tisch-Illustration.
     Nebenwirkung, positiv: dadurch ist die Geometrie im eingerollten und im
     ausgefahrenen Zustand wieder gleich — und genau deren Unterschied hatte
     die Tasse 50px ueber der Tischplatte schweben lassen. */

  /* Einzeilig bleiben. Bei 360px Breite (Galaxy S23 und die ganze 360er-Klasse)
     stehen nach dem Seitenrand 316px zur Verfuegung, und mit gap 8 plus 15px
     Innenpolster brauchte die Reihe 326px — sie brach auf zwei Zeilen und riss
     44px zusaetzliche Hoehe. Zwei Zeilen sind hier ohnehin die schlechtere
     Reihe, nicht nur die hoehere. */
  @media(max-width:389px){
    .chips{gap:6px}
    .chip{padding:0 11px;font-size:.78rem}
  }
  .arrow{display:none}
  .prop--notiz,.prop--sukku{display:none}
  .desk__legs i{height:42px}
  /* Tasse an die TISCHPLATTE binden, nicht an die Rig-Unterkante: darunter liegen
     mobil Chips und Umschalter, sonst landet sie auf den Tasten. --mug-bottom
     wird gemessen (platziereTasse), der Fallback greift ohne JS. */
  /* Etwas groesser und ein Stueck weiter auf die Platte: 44px am aeussersten
     Rand sind mit dem Daumen kaum zu treffen und faellt als Motiv nicht auf. */
  .prop--mug{right:7%;width:52px;bottom:var(--mug-bottom,158px)}
  /* Mehr Farbe, aber mit dem, was schon da ist: der Cyan-Streifen geht auf
     volle Deckung und wird eine Spur hoeher, der Rand der Tasse bekommt einen
     Hauch davon ab. Auf 52px ist das der Unterschied zwischen „weisses Ding"
     und „das eine bunte Teil auf dem Tisch". Kein neuer Farbton — der Streifen
     ist im SVG schon #19bff4. */
  .prop--mug .mug__band{opacity:1}
  .prop--mug .mug__leib{stroke:#b9dcea}

  /* --- Geraete-Umschalter mobil: aus der Schreibtisch-Illustration werden zwei
     beschriftete Tasten mit 44px Trefferflaeche. Die 186px breite Deko-Szene
     passt auf 390px nicht und waere mit dem Finger nicht bedienbar. --- */
  /* margin-top 10 statt 16: nachgemessen war der Umschalter auf dem iPhone
     14/15 mit ausgefahrener Adressleiste nach dem Ausklappen um 3px
     angeschnitten — vom obersten Geraeterand bis zu seiner Unterkante brauchte
     es 665px, im Bild waren 662. Drei Pixel sehen nicht nach knapp aus,
     sondern nach schlampig. Die 6px hier holen sie. */
  .deviceswitch{display:flex;position:static;right:auto;bottom:auto;
    flex-direction:row;justify-content:center;gap:8px;margin:10px auto 0;filter:none}
  .dsw__hint{display:none}
  .dsw__stage{position:static;display:flex;gap:8px;width:auto;height:auto}
  .dsw__desk{display:none}
  .dsw__beam{display:none}
  .dsw__dev{position:static;left:auto;bottom:auto;width:auto;opacity:1;
    display:inline-flex;align-items:center;justify-content:center;gap:8px;
    min-height:44px;padding:0 16px;border:1px solid var(--line);border-radius:11px;
    background:var(--white);color:var(--ink-soft);font:640 .88rem/1 Geist,sans-serif;
    transform:none;transition:background .16s ease,border-color .16s ease,color .16s ease}
  .dsw__dev svg{width:15px;height:auto;flex:0 0 auto}
  .dsw__dev .dsw__frame{stroke:currentColor;stroke-width:2.2}
  .dsw__dev .dsw__screen{fill:none}
  .dsw__dev.is-active{background:var(--cyan-soft);border-color:#9adcf6;color:var(--cyan-ink)}
  .dsw__dev.is-active .dsw__screen{fill:rgba(25,191,244,.22)}
  .dsw__dev:hover{transform:none;filter:none}
  .dsw__txt{display:inline}
}
@media(prefers-reduced-motion:reduce){
  .track{transition:none}
  .browser{transition:none;opacity:1;filter:none}
  .caret{animation:none}
  .stage.is-brewing .dampf{animation:none;opacity:0}
  .dsw__beam{animation:none!important;opacity:0}
  .monitor{transform:none}
}

/* ---- Sektions-Kopf ----
   Zwei Varianten bewusst im Wechsel: zentriert = Aussage/Kapitelmarke,
   links = Arbeitsabschnitt. Über 8 Sektionen entsteht so Rhythmus statt Schema. */
.sec-head{max-width:720px;margin:0 auto clamp(40px,5vw,60px);text-align:center}
.sec-head h2{margin:0 0 14px;font-size:clamp(2rem,4vw,3rem);line-height:1.05;letter-spacing:-.03em;font-weight:710;
  text-wrap:balance}                       /* verhindert Schusterjungen in der 2. Zeile */
.sec-sub{margin:0;font-size:clamp(1.05rem,1.4vw,1.18rem);color:var(--ink-soft);line-height:1.5;text-wrap:pretty}
/* Umbruch am SINN, nicht am Platz. Der Doppelpunkt trennt Ankuendigung und
   Einloesung — dort soll die Zeile brechen und nicht dort, wo der Rand
   zufaellig erreicht ist.
   NUR AB 561px. Darunter passt der erste Teil (47 Zeichen) nicht mehr auf
   eine Zeile: auf 390px stehen rund 41 Zeichen zur Verfuegung, der erzwungene
   Bruch machte aus drei Zeilen vier, davon eine mit einem Wort. Ohne die
   Regel bricht der Satz dort normal um — das Leerzeichen hinter dem <br>
   bleibt erhalten, wenn es ausgeblendet ist. */
.br-satz{display:none}
@media(min-width:561px){ .br-satz{display:inline} }
/* Linksbündige Variante: Kopf und Subline sitzen nebeneinander, Blick läuft in den Inhalt */
.sec-head--left{max-width:var(--wrap);margin-left:auto;margin-right:auto;text-align:left;
  display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(18px,4vw,64px);align-items:end}
.sec-head--left h2{margin:0;font-size:clamp(1.95rem,3.5vw,2.7rem)}
.sec-head--left .sec-sub{margin:0;padding-bottom:.35em;font-size:clamp(1.02rem,1.25vw,1.12rem)}
.sec-head--left .eyebrow{grid-column:1/-1;margin-bottom:2px}
@media(max-width:820px){
  .sec-head--left{grid-template-columns:1fr;align-items:start;gap:14px}
  .sec-head--left .sec-sub{padding-bottom:0}
}
/* Titel-Marker: derselbe handgezeichnete Strich wie im Hero — einmal pro Seite,
   als Wiedererkennung. Bewusst NICHT überall, sonst verliert er seine Wirkung. */
.mark{position:relative;z-index:0;white-space:nowrap}   /* z-index:0 = eigener Stacking-Context,
     sonst rutscht das ::after mit z-index:-1 hinter den Sektionshintergrund und ist unsichtbar */
.mark::after{content:"";position:absolute;left:-.04em;right:-.08em;bottom:.05em;height:.3em;z-index:-1;
  background:var(--cyan);opacity:.32;
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 40' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M3 13C6 9.5 12 7.8 20 7.5 33 7 44 5.8 55 5.2 70 4.4 82 3.4 95 3 112 2.5 126 4 140 4.4 156 4.8 170 3 185 2.6 202 2.2 216 3.6 230 4 244 4.4 256 2.9 268 2.6 280 3.4 290 5.4 297.4 8.2C299.4 11.6 298.4 16.4 299.5 20.8C299.9 24.4 298.6 28.6 296.8 31.6C288 34.6 276 36.4 264 37 242 38 218 36.3 194 37.1 170 37.9 148 36.2 124 37 100 37.8 78 36.3 56 35.7 42 35.2 30 33.2 20 32 12 31 6 29.5 3 27Z'/%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 40' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M3 13C6 9.5 12 7.8 20 7.5 33 7 44 5.8 55 5.2 70 4.4 82 3.4 95 3 112 2.5 126 4 140 4.4 156 4.8 170 3 185 2.6 202 2.2 216 3.6 230 4 244 4.4 256 2.9 268 2.6 280 3.4 290 5.4 297.4 8.2C299.4 11.6 298.4 16.4 299.5 20.8C299.9 24.4 298.6 28.6 296.8 31.6C288 34.6 276 36.4 264 37 242 38 218 36.3 194 37.1 170 37.9 148 36.2 124 37 100 37.8 78 36.3 56 35.7 42 35.2 30 33.2 20 32 12 31 6 29.5 3 27Z'/%3E%3C/svg%3E");
  -webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}

/* ---- Der Strich faengt Licht, wenn der Zeiger nahe kommt ---------------
   Uebernommen von /software, damit beide Seiten dieselbe Sprache sprechen.
   --hlg (0 bis 1) ist die Naehe des Zeigers und kommt aus hero.js.

   drop-shadow und NICHT box-shadow: die Form des Strichs entsteht ueber eine
   Maske. Ein box-shadow wuerde den rechteckigen Kasten umranden statt die
   gezeichnete Kontur.

   DREI SCHICHTEN, und der Radius WAECHST mit der Naehe statt nur die
   Deckkraft. Faehrt nur die Deckkraft hoch, steht der Hof sofort in voller
   Groesse da und wird blass ein- und ausgeblendet — das sieht aus wie eine
   geschaltete Lampe. Echtes Licht breitet sich aus: innen ein enger, fast
   weisser Kern, darum Cyan, aussen weiter Dunst.
   Bei --hlg = 0 sind alle Deckkraefte 0, es kostet also nichts, solange
   niemand in der Naehe ist.
   Die Transition ist bewusst KURZ: die eigentliche Weichheit macht die
   Daempfung im JS. Eine lange Transition darueber addiert nur Verzoegerung
   und laesst den Strich verspaetet wirken. */
.hl::after,.mark::after{
  /* DER STRICH SELBST macht den groessten Teil der Wirkung, nicht der Hof.
     Auf einem hellen Grund kann ein Glow nicht durch Aufhellen arbeiten —
     hell auf hell ist nichts. Er muss FARBIGER werden. Deshalb faehrt die
     Deckkraft des Strichs von .32 auf .94 (er geht also von blassem Wisch auf
     volles Cyan), und der Hof ist durchgehend cyan statt innen fast weiss.
     Die erste Fassung war 1:1 von /software uebernommen — das ist eine DUNKLE
     Seite, dort strahlt ein weisser Kern auf Navy. Hier war er unsichtbar.
     Dazu WAECHST der Strich um 22%: eine Groessenaenderung sieht das Auge auf
     jedem Untergrund, unabhaengig von Helligkeit. Ankerpunkt unten, damit er
     nach oben aufgeht und nicht von der Schriftlinie wegrutscht.
     KEINE transition hier: die Weichheit macht die Daempfung in hero.js. Eine
     eigene Transition wuerde ausserdem die 1,1s ueberschreiben, mit denen der
     Strich im Nachtmodus des Heros aufglueht — genau das war der Fall, bevor
     diese Zeile weggefallen ist. */
  opacity:calc(.32 + var(--hlg,0) * .62);
  transform:scaleY(calc(1 + var(--hlg,0) * .22));transform-origin:50% 100%;
  filter:
    drop-shadow(0 0 calc(1px  + var(--hlg,0) * 3px)  rgba(25,191,244,calc(var(--hlg,0) * .95)))
    drop-shadow(0 0 calc(5px  + var(--hlg,0) * 15px) rgba(25,191,244,calc(var(--hlg,0) * .80)))
    drop-shadow(0 0 calc(12px + var(--hlg,0) * 36px) rgba(7,132,176,calc(var(--hlg,0) * .40)))}

/* ---- Scroll-Reveal ----
   Armiert per JS (html.rv-on): ohne JS bleibt alles sichtbar. Bewusst knapp
   dosiert — 10px und 0.6s, das liest sich als Ruhe, nicht als Effekt. */
.rv-on .rv{opacity:0;transform:translateY(10px)}
@media(prefers-reduced-motion:no-preference){
  .rv-on .rv{transition:opacity .6s cubic-bezier(.22,.7,.3,1),transform .6s cubic-bezier(.22,.7,.3,1);
    transition-delay:var(--rvd,0ms)}
}
.rv-on .rv.is-in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.rv-on .rv{opacity:1;transform:none}}

/* ---- Cases ---- */
.cases{padding:clamp(52px,7vw,100px) var(--page);background:var(--paper)}
/* ---- Keine Screenshots mehr, und das ist der Kern der Sektion ----------
   Hier standen zwei Browser-Attrappen mit Screenshots der Kundenseiten —
   dieselben zwei Seiten, die der Hero 2.000px weiter oben LIVE und
   interaktiv zeigt. Gemessen: Hero 702x395px lebendig, hier 624 bzw. 490px
   statisch. Die zweite Fassung war schlicht die schwaechere; ein Screenshot
   kann nichts, was die laufende Vorschau nicht besser kann.
   An ihrer Stelle traegt jetzt die MESSLEISTE die Referenz. Sie klemmte
   vorher in der 490px-Textspalte mit 113px je Wert; ueber die volle
   Rasterbreite sind es rund 290px. Damit wird der Beleg zum Bild — was eine
   Referenz ohnehin tun soll: nicht zeigen, wie es aussieht, sondern was es
   kann.
   Der Kopf uebernimmt das linksbuendige Muster, das die Seite an vier
   weiteren Stellen benutzt (Marke und Titel links, Beschreibung rechts) —
   kein neues Layout, nur ein weiteres Vorkommen.
   assets/cases/reifenservice-web.webp und gws-web.webp liegen weiter auf dem
   Server, werden aber von keiner Seite mehr geladen. */
/* BEIDE REFERENZEN NEBENEINANDER, die Messleiste darunter ueber die volle
   Breite. Das hat zwei Gruende, und der zweite ist der wichtigere:
   - Nebeneinander liest sich als „hier sind unsere Arbeiten“ statt als zwei
     einzelne Auftritte hintereinander.
   - Es gibt bisher nur EINE Messung (Reifenservice). Untereinander stand sie
     bei der ersten Referenz und fehlte sichtbar bei der zweiten. Unter beiden
     gehoert sie zur Sektion statt zu einer Karte.
   DAFUER MUSS SIE IHR PROJEKT NENNEN. Steht sie unbeschriftet unter zwei
   Referenzen, liest sie sich als Messung fuer beide — und die Zahl fuer die
   zweite Seite haben wir nicht. Die Quellzeile sagt deshalb „Google
   Lighthouse · Reifenservice Mechernich · Test vom …“. Sobald die zweite
   Seite gemessen ist, kommt eine zweite Leiste dazu und beide sind
   beschriftet.
   Der Kopf ist in der schmalen Spalte wieder EINSPALTIG: bei rund 560px je
   Referenz haetten Titel und Beschreibung nebeneinander je 270px — zu wenig
   fuer beides. */
.case__paar{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4vw,56px);
  max-width:var(--wrap);margin:0 auto}
.case{margin:0}
.case__kopf{margin-bottom:4px}
/* Die Leiste gehoert jetzt der Sektion, nicht der Referenz. */
.cases .mess{max-width:var(--wrap);margin:clamp(38px,4.6vw,60px) auto 0}

.case__tag{margin:0 0 8px;font-size:.78rem;font-weight:680;letter-spacing:.11em;text-transform:uppercase;color:var(--cyan-ink)}
/* ---- Kundenstimme ------------------------------------------------------
   Eigener Block hinter den zwei Case-Karten, NICHT in einer davon. In der
   Karte stand sie neben Beschreibung, Leistungspunkten und PageSpeed — vier
   Aussagen in einem Kasten, von denen jede die anderen schwaecht, und die
   Rezension war mit Abstand das groesste Element. Allein wirkt sie.
   Aufbau: Portraet links, Wortlaut rechts, Name darunter. Auf dem Handy
   wandert das Portraet nach oben und wird klein — dort zaehlt der Text.
   Wortlaut unveraendert uebernommen; Anfuehrungszeichen als Grafik statt im
   Text, damit beim Kopieren der reine Wortlaut in der Zwischenablage landet. */
.stimme{display:grid;grid-template-columns:clamp(190px,20vw,260px) minmax(0,1fr);
  grid-template-areas:"bild text" "bild wer";
  align-content:start;gap:6px clamp(26px,3.4vw,44px);
  max-width:var(--wrap);margin:clamp(46px,5.5vw,78px) auto 0;
  padding:clamp(28px,3vw,40px);background:var(--paper);border:1px solid var(--line)}
/* Das Bild FUELLT seine Spalte ueber beide Zeilen. Quadratisch gesetzt blieben
   darunter gemessen rund 180px tote Flaeche, weil der Text daneben hoeher ist.
   Die Datei ist 800x1000 und damit von Haus aus hochkant — sie wird nur
   beschnitten, nicht gestreckt. */
.stimme__bild{grid-area:bild;width:100%;height:100%;min-height:100%;
  object-fit:cover;object-position:50% 22%;display:block;border:1px solid var(--line)}
.stimme__text{grid-area:text;margin:0;position:relative}
/* Das Anfuehrungszeichen ist Deko und darf nicht mitkopiert werden. */
.stimme__text::before{content:"";position:absolute;left:0;top:-2px;width:34px;height:2px;background:var(--cyan)}
.stimme__text p{margin:18px 0 0;color:var(--ink-soft);font-size:1.02rem;line-height:1.62}
.stimme__text p:first-of-type{margin-top:22px}
/* Der letzte Satz traegt mehr Gewicht — aber NUR ueber die Farbe, nicht ueber
   die Schriftstaerke. Fett in einem Zitat liest sich als Betonung des
   Sprechers, und die hat er nicht gesetzt: wir haetten den verkaufsrelevanten
   Satz hervorgehoben. Wer das merkt, rechnet das ganze Zitat ab. Grau zu
   Textfarbe reicht fuer die Hierarchie. */
.stimme__pointe{color:var(--ink)!important}

/* Anfuehrungszeichen per CSS, nicht im Text: so landet beim Kopieren der reine
   Wortlaut in der Zwischenablage und nicht unsere Typografie.
   Nur am Anfang und am Ende des ganzen Zitats — die alte Regel, jeden Absatz
   erneut zu oeffnen, wirkt heute fussgaengerisch.
   Deutsch oeffnet unten, Englisch oben; die englische Seite traegt lang="en". */
.stimme__text p:first-of-type::before{content:"„";color:var(--ink)}
.stimme__text p:last-of-type::after{content:"“";color:var(--ink)}
html[lang="en"] .stimme__text p:first-of-type::before{content:"“"}
html[lang="en"] .stimme__text p:last-of-type::after{content:"”"}
.stimme__wer{grid-area:wer;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px;
  margin:20px 0 0;padding-top:16px;border-top:1px solid var(--line)}
.stimme__wer b{font-size:1.05rem;color:var(--ink)}
.stimme__wer span{color:var(--muted);font-size:.92rem}
.stimme__hinweis{font-size:.8rem;opacity:.85}
@media(max-width:760px){
  /* KOPFZEILE: Foto und Name nebeneinander, das Zitat darunter ueber die volle
     Breite. Vorher stand das Portraet klein allein oben und der Name ganz
     unten — das Gesicht trug damit nichts, weil es weit weg von seinem Namen
     stand.
     Warum NICHT das Zitat neben das Bild: gemessen hat der Block auf 390px
     innen 302px. Mit einem 120px-Foto blieben fuer den Text 166px, also rund
     20 Zeichen je Zeile — und „Ansprechpartner" ist allein schon 123px breit.
     Angenehm liest sich Fliesstext bei 45 bis 75 Zeichen. Ein NAME dagegen
     braucht die Breite nicht, der passt dort locker. Also bekommt die schmale
     Spalte den Namen und der Fliesstext seine vollen 39 Zeichen.
     Das Bild darf dadurch von 96 auf bis zu 124px wachsen. */
  .stimme{grid-template-columns:clamp(104px,30vw,124px) minmax(0,1fr);
    grid-template-areas:"bild wer" "text text";
    column-gap:16px;row-gap:0;padding:clamp(22px,5vw,28px)}
  .stimme__bild{width:100%;height:auto;min-height:0;aspect-ratio:1;
    object-position:50% 18%;margin:0}
  /* Neben dem Foto gestapelt statt in einer Zeile, und ohne Trennlinie: die
     gehoert an einen Abschluss, nicht an einen Kopf. */
  .stimme__wer{align-self:center;flex-direction:column;align-items:flex-start;
    gap:3px;margin:0;padding:0;border-top:0}
  .stimme__wer b{font-size:1.08rem;line-height:1.2}
  .stimme__wer span{font-size:.88rem;line-height:1.35}
  .stimme__text{margin-top:20px}
  .stimme__text p{font-size:1rem}
}


.case__body h3{margin:0;font-size:clamp(1.6rem,2.6vw,2.2rem);letter-spacing:-.02em;font-weight:700}
.case__body p{margin:0;color:var(--ink-soft);line-height:1.55;font-size:1.06rem}
/* ---- Messwerte: fremdgemessene Belege statt Eigenlob --------------------
   KEINE Karte, keine Ringe, kein Schatten. Zwischenstand war eine weisse Box
   mit vier Fortschrittsringen. Bei vier fast perfekten Werten tragen Ringe
   keine Information: 100, 96, 100 und 100 sehen als Kreis praktisch gleich
   aus, die Zahl daneben sagt alles. Was blieb, war Unruhe — vier Animationen,
   ein Schatten und eine Karte in einer Karte.
   Jetzt eine Leiste: zwei Haarlinien, vier Zahlen, duenne Trenner. Sie liest
   sich als technischer Nachweis in der Seite und nicht als eingeklebter
   Lighthouse-Screenshot.
   KEINE Flaeche darunter, obwohl „sehr hell, leicht blaeulich“ naheliegt: die
   Sektion liegt selbst auf --paper (#f5f8fc), eine hellblaue Flaeche waere
   darauf unsichtbar. Auf dieser Seite ist die Linienfassung die einzige, die
   ueberhaupt sichtbar ist.
   Die Quelle steht klein DARUNTER, nicht gross darueber: wer gemessen hat,
   ist die Beglaubigung, nicht die Schlagzeile.
   Die Ladezeiten sind RAUS. „1,4 s mobil“ benennt keine Messgroesse — LCP,
   Speed Index und vollstaendige Ladezeit sind drei verschiedene Zahlen. Eine
   Sekundenangabe ohne Bezug ist keine Angabe, sondern eine Behauptung. Sobald
   feststeht, welche gemeint ist, gehoert sie beschriftet zurueck. */
/* container-type, weil die Fensterbreite hier die FALSCHE Bezugsgroesse ist.
   Gemessen ist die Leiste bei 1024px nur 376px breit (dort steht die Referenz
   zweispaltig, die Textspalte ist schmal), bei 768px aber 691px (einspaltig).
   Die Breite laeuft also nicht mit dem Fenster mit, sondern springt — mit einer
   Media Query waere jede Grenze an einer Stelle richtig und an der anderen
   falsch. Die Leiste fragt darum ihre eigene Breite. */
.mess{container-type:inline-size;
  margin:26px 0 22px;padding:16px 0 14px;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.mess__titel{margin:0 0 12px;
  font-size:.72rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cyan-ink)}
.mess__werte{display:grid;grid-template-columns:repeat(4,1fr);
  margin:0;padding:0;list-style:none}
/* Die Trenner sitzen an der linken Kante jedes Feldes ausser dem ersten —
   keine eigenen Elemente, die man beim Umbruch einzeln nachziehen muesste. */
.mess__werte li{padding:0 10px;min-width:0}
.mess__werte li + li{border-left:1px solid var(--line)}
.mess__werte li:first-child{padding-left:0}
.mess__werte li:last-child{padding-right:0}
.mess__werte b{display:block;
  font-size:clamp(1.8rem,2.5vw,2.05rem);line-height:1.05;font-weight:660;
  letter-spacing:-.03em;color:var(--ink);font-variant-numeric:tabular-nums}
.mess__werte span{display:block;margin-top:7px;
  font-size:.8rem;line-height:1.3;font-weight:560;color:var(--muted)}
/* Quelle und Bericht teilen sich eine Zeile: links wer und wann gemessen
   hat, rechts der Weg zum Original. Untereinander lag der Link auf derselben
   Hoehe wie die Abschlusszeile der Sektion und las sich als deren Anfang. */
.mess__fuss{display:flex;flex-wrap:wrap;justify-content:space-between;
  align-items:baseline;gap:8px 24px;margin:14px 0 0}
.mess__quelle{font-size:.76rem;color:var(--muted)}

/* Beide Belege einer Referenz in EINER Zeile: die Seite selbst und der
   Messbericht gehoeren zum selben Projekt. Vorher stand der Bericht in der
   Messbox und „Live ansehen“ darunter — zwei Linkzeilen fuer eine Sache. */
.case__links{display:flex;flex-wrap:wrap;gap:10px 28px;margin:0}
/* Nach aussen fuehrende Links tragen den schraegen Pfeil, seiteninterne den
   waagerechten. Das ist die einzige Ankuendigung, die ein neuer Tab bekommt. */
.web-link--aus::after{content:"\2197"}
.web-link--aus:hover::after{transform:translate(3px,-3px)}

/* Vier Werte nebeneinander brauchen vier Beschriftungen nebeneinander, und
   „Barrierefreiheit“ allein ist auf 12,8px rund 92px breit. Mit 2x10px Polster
   je Feld braucht eine Vierer-Reihe damit rund 450px. Darunter zwei mal zwei.
   Der Trenner sitzt dann nur zwischen den beiden Spalten, nicht vor jedem Feld.
   Nachgemessen liegt die Leiste so auf 1280 und 1440px vierspaltig (479 und
   490px), in der zweispaltigen Referenzansicht zwischen 901 und 1279px
   zweispaltig (337 bis 376px), auf dem Tablet wieder vierspaltig (691px) und
   auf dem Handy zweispaltig (316 bis 346px). */
@container (max-width:449px){
  .mess__werte{grid-template-columns:repeat(2,1fr);row-gap:18px}
  .mess__werte li:nth-child(odd){padding-left:0;border-left:0}
  .mess__werte li:nth-child(even){padding-right:0;border-left:1px solid var(--line)}
}
/* Ohne Container-Queries greift die Abfrage oben nicht und es blieben ueberall
   vier Spalten — auf dem Handy waeren die Beschriftungen dann zweizeilig in
   86px schmalen Feldern. Dann lieber die Fensterbreite als grober Ersatz. */
@supports not (container-type:inline-size){
  @media(max-width:520px){
    .mess__werte{grid-template-columns:repeat(2,1fr);row-gap:18px}
    .mess__werte li:nth-child(odd){padding-left:0;border-left:0}
    .mess__werte li:nth-child(even){padding-right:0;border-left:1px solid var(--line)}
  }
}

.case__points{margin:20px 0 22px;padding:0;list-style:none}
/* MARKE IST EINE HAARLINIE, keine gefuellte Raute. Vorher stand hier ein um
   45 Grad gekipptes Quadrat auf 9px in vollem Cyan — das war nach dem Umbau
   der Haekchen das letzte gefuellte Zeichen auf der Seite und damit das
   schwerste. Diese Seite markiert sonst mit 2px-Linien: die Oberkanten der
   Karten, der Anschlag ueber dem Takt, die Marke am aktiven Schienenfeld.
   Eine Linie sagt hier ausserdem das Richtige. Ein Haken hiesse „zugesagt“
   (den tragen die Zusagen im Hero und beim Preis), ein Punkt hiesse
   „Aufzaehlung“ (den tragen die Ortsnamen). Diese drei Zeilen sind weder das
   eine noch das andere, sondern Merkmale einer gebauten Seite — markiert,
   nicht versprochen.
   top ist GEMESSEN, nicht gerechnet: die Zeilenhoehe steht auf `normal`, also
   haengt sie an der Schrift und nicht an einer Zahl im CSS. Eine unsichtbare
   Messmarke im Textfluss ergab die Mitte der Grossbuchstaben bei 10,5px —
   abzueglich der halben Strichstaerke sind das 0,59em. Mit dem gerechneten
   Wert (0,75em aus Zeilenhoehe 1,5) sass der Strich 2,5px zu tief. */
.case__points li{position:relative;padding-left:22px;margin-bottom:10px;color:var(--ink);font-size:1rem}
.case__points li::before{content:"";position:absolute;left:0;top:.59em;
  width:12px;height:2px;background:var(--cyan)}

/* ---- Ablauf ---- */
.ablauf{padding:clamp(52px,7vw,100px) var(--page);background:var(--paper)}
.steps{position:relative;display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(20px,2.6vw,34px);max-width:var(--wrap);margin:0 auto;padding:0;list-style:none}
.step{position:relative;padding-top:22px;border-top:2px solid var(--line)}
.step::before{content:"";position:absolute;top:-2px;left:0;width:42px;height:2px;background:var(--cyan)}
/* Einzeilig (Desktop): die vier Schritte teilen sich EINE Zeitleiste — graue Spur,
   Cyan-Fortschritt waechst beim Scrollen mit (--p aus JS), Kerben trennen die Stationen.
   So liest es sich als Ablauf mit vier Etappen statt als Ladebalken. */
@media(min-width:901px){
  /* KEIN padding-top auf .steps: die Leiste liegt bei top:0 der Padding-Box, die
     Kerben bei top:0 ihres Schritts — jedes Padding verschiebt beide gegeneinander. */
  .step{border-top:0;padding-top:28px}
  .steps::after{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:var(--line);z-index:0}
  .steps::before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:var(--cyan);z-index:1;
    transform-origin:left center;transform:scaleX(var(--p,0));will-change:transform}
  /* Kerbe in Sektionsfarbe schneidet die Leiste vor jeder Station auf.
     WICHTIG: setzt die 42px-Cyan-Basisregel zurueck — sonst bleibt bei Schritt 1
     ein Stummel ueber der leeren Spur stehen. */
  .step::before{content:"";display:block;position:absolute;top:0;left:calc(-1 * clamp(20px,2.6vw,34px) / 2 - 4px);
    width:8px;height:2px;background:var(--paper);z-index:2}
  .step:first-child::before{content:none}
  .step__no{position:relative;display:inline-block}
}
@media(min-width:901px) and (prefers-reduced-motion:reduce){
  .steps::before{transform:scaleX(1)}
}
.step__no{font-family:"Geist Mono",monospace;font-size:.92rem;font-weight:700;color:var(--cyan-ink)}
.step h3{margin:12px 0 10px;font-size:1.3rem;letter-spacing:-.015em}
.step p{margin:0;color:var(--ink-soft);line-height:1.5;font-size:1rem}

/* ---- Umfang ---- */
.umfang{padding:clamp(52px,7vw,100px) var(--page);background:var(--paper)}
.umfang__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;max-width:var(--wrap);margin:0 auto;
  background:var(--line);border:1px solid var(--line);border-radius:0;overflow:hidden}
.feat{position:relative;background:var(--white);padding:28px 26px;transition:background .2s ease}
.feat:hover{background:#fbfdff}
/* Icons in der Linien-Sprache der Hero-Illustration (gleiche Strichstaerke, gleiche Farbe)
   — schlaegt die Bruecke zurueck in die Raum-Welt, ohne sie zu wiederholen. */
.feat__ico{display:block;width:26px;height:26px;margin:0 0 14px;color:#8397ab;transition:color .2s ease}
.feat:hover .feat__ico{color:var(--cyan-ink)}
.feat__ico svg{display:block;width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.feat h3{margin:0 0 10px;font-size:1.16rem;letter-spacing:-.01em}
.feat p{margin:0;color:var(--ink-soft);line-height:1.5;font-size:.98rem}

/* ---- Pair: EINE Aussage, keine zwei -------------------------------------
   Hier standen zwei Kaesten nebeneinander. Der zweite („Gefunden werden —
   Damit Kunden dich in deiner Region finden.“) ist raus, und zwar aus zwei
   nachpruefbaren Gruenden:
   1. Er hat eine Aussage wiederholt, die 400px vorher schon steht. Im
      Umfang-Raster: „Google-Unternehmensprofil — Gepflegt und optimiert,
      damit Kunden dich in der Region finden.“ Im Kasten: „… ein gepflegtes
      Google-Unternehmensprofil — die Basis, damit Menschen dich finden, wenn
      sie suchen.“ Derselbe Beleg, fast derselbe Satz.
   2. Seine Ueberschrift stand unmittelbar ueber der Regionen-Sektion
      („Aus der Region, fuer die Region.“) — zwei Region-Ueberschriften
      hintereinander, und die untere ist die, die den Abschnitt traegt.
   Was bleibt, ist eine einzelne Aussage, mittig und auf Lesebreite begrenzt.
   Zwei Kaesten waren ein weiteres Raster; einer ist eine Pause zwischen dem
   Umfang und der dunklen Regionen-Sektion — und die tut der Strecke gut. */
.pair{max-width:var(--wrap);margin:0 auto;
  padding:clamp(24px,4vw,44px) var(--page) clamp(52px,7vw,88px)}
/* 760px sind rund 75 Zeichen je Zeile. Ueber die volle Rasterbreite (1180px)
   waeren es rund 115 — doppelt so viel, wie sich angenehm liest. */
.pair__card{max-width:760px;margin:0 auto;
  padding:clamp(28px,3vw,40px);border-radius:0;border:1px solid var(--line);background:var(--white)}
.pair__card h3{margin:8px 0 12px;font-size:clamp(1.3rem,2vw,1.55rem);letter-spacing:-.02em}
.pair__card p{margin:0;color:var(--ink-soft);line-height:1.55}

/* ---- Preis: was den Preis bestimmt + Festpreis-Zusage ---- */
.preis{padding:clamp(52px,7vw,100px) var(--page);background:var(--white)}
.preis__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(18px,2.4vw,26px);max-width:var(--wrap);margin:0 auto}
.treiber{padding:clamp(22px,2.2vw,28px);border:1px solid var(--line);border-radius:0;background:var(--white)}
.treiber h3{margin:0 0 9px;font-size:1.1rem;letter-spacing:-.01em}
.treiber p{margin:0;color:var(--ink-soft);line-height:1.5;font-size:.97rem}
.treiber__frage{display:block;margin-top:10px;color:var(--cyan-ink);font-size:.9rem;font-weight:620}
/* Zusage: der Festpreis als Prozess-Versprechen (keine Zahl, aber verbindlich) */
.zusage{max-width:var(--wrap);margin:clamp(26px,3.2vw,40px) auto 0;padding:clamp(28px,3vw,42px);
  border-radius:0;background:var(--cyan-soft);border:1px solid #cbeefb;
  display:grid;grid-template-columns:1fr 1.15fr;gap:clamp(22px,3vw,44px);align-items:center}
.zusage h3{margin:0 0 10px;font-size:clamp(1.3rem,2.1vw,1.65rem);letter-spacing:-.02em}
.zusage > div > p{margin:0;color:var(--ink-soft);line-height:1.55}
.zusage__punkte{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:13px}
.zusage__punkte li{position:relative;padding-left:26px;color:var(--ink);font-size:1rem;line-height:1.45}
/* Dieselbe Form, eine Nummer groesser — hier steht Fliesstext auf 1rem, nicht
   .9rem. Die Maske kommt aus --haken weiter oben, es gibt sie nur einmal. */
.zusage__punkte li::before{content:"";position:absolute;left:0;top:.16em;
  width:17px;height:17px;background:var(--cyan);
  -webkit-mask:var(--haken) 0 0/17px 17px no-repeat;
          mask:var(--haken) 0 0/17px 17px no-repeat}
/* Ohne Maskenunterstuetzung waere der Haken eine cyane Flaeche. Dann lieber die
   Form, die die Referenzpunkte dieser Seite ohnehin benutzen: ein gekipptes
   Quadrat. Sagt dasselbe und ist auf jeden Fall kein Klotz. */
@supports not ((mask-image:none) or (-webkit-mask-image:none)){
  .trustmarks li::before,.zusage__punkte li::before{
    width:9px;height:9px;border-radius:2px;transform:rotate(45deg);
    -webkit-mask:none;mask:none}
  .trustmarks li::before{top:.42em}
  .zusage__punkte li::before{top:.4em;left:3px}
}
.zusage__punkte strong{font-weight:680}
.preis__laufend{max-width:var(--wrap);margin:clamp(20px,2.4vw,28px) auto 0;text-align:center;color:var(--muted);font-size:.98rem}
.preis__laufend b{color:var(--ink);font-weight:660}

/* =====================================================================
   KARTEN-SPRACHE
   Runde Boxen sind der Standard jedes Baukastens — die Kanten sind deshalb
   ueberall scharf (border-radius:0 steht jeweils an der Quelle der Regel).
   Eine angeschnittene Ecke mit cyaner Schnittkante war hier zwischenzeitlich
   drin und ist bewusst wieder raus: sie hat jede Karte verziert, statt eine
   Struktur zu bauen.
   Der Akzent liegt jetzt an EINER Stelle — die Branchen-Karten sind oben und
   unten offen und stehen auf einer dunklen Kante (s. .branche / .branche::after).
   Alle anderen Flaechen bleiben ruhige scharfe Rahmen. Das ist Hierarchie, keine
   zweite Sprache: eine Sektion traegt den Effekt, der Rest traegt den Inhalt.
   REGEL: Flaechen scharf, Bedienelemente (Buttons, Chips, Geraetetasten) rund —
   die Rundung ist dort Aufforderung zum Antippen.
   ===================================================================== */
.branchen{padding:clamp(52px,7vw,100px) var(--page);background:var(--white)}
/* Zeilenabstand groesser als der Spaltenabstand: die Standfuesse brauchen den
   Platz, sonst stoesst der Fuss der oberen Reihe an die Karte darunter. */
.branchen__grid{display:grid;grid-template-columns:repeat(2,1fr);
  column-gap:clamp(18px,2.4vw,26px);row-gap:clamp(46px,4.4vw,58px);
  max-width:var(--wrap);margin:0 auto}
/* OBEN UND UNTEN OFFEN: kein Kasten mehr, sondern zwei senkrechte Haarlinien als
   Kanal, der unten auf der dunklen Standkante endet (s. .branche::after). */
.branche{position:relative;--karte-pad:clamp(26px,2.6vw,34px);padding:var(--karte-pad);
  /* min-width:0 ist hier PFLICHT, nicht Kosmetik: die Karte ist ein
     Rasterelement und hat damit von Haus aus min-width:auto -- sie weigert
     sich, schmaler zu werden als ihr Inhalt. Mit der nicht umbrechenden
     Chip-Reihe darin hat das die Spalte gemessen auf 811px aufgezogen und
     470px waagerechten Ueberlauf erzeugt. */
  min-width:0;
  border:0 solid var(--line);border-width:0 1px;
  border-radius:0;background:var(--white);
  transition:border-color .18s ease}
/* Hover: die Standkante wird kraeftiger. Der frueher hier stehende Lift-Schatten
   passt nicht mehr — ein Schatten umrundet eine geschlossene Flaeche, und diese
   Karte hat keine Unterkante. Ein Farbwechsel auf zwei Haarlinien waere zu leise. */
.branche:hover::after{height:3px}
/* STANDKANTE — die Karte steht auf einer Linie, statt auf hellem Grund zu
   schweben. Gleicher Ton wie die Tischkante im Hero (--navy), also derselbe
   Tisch und kein zweites Formenvokabular.
   Nichts verbindet Karte und Linie: die offenen Kanten und die offene Luecke
   sind der Effekt. Ein Steg dazwischen wuerde die Form wieder schliessen.
   left/right mit 1px Uebermass, weil absolute Offsets ab der Padding-Box zaehlen
   — sonst waere die Linie 2px schmaler als die Karte. */
.branche::after{content:"";position:absolute;left:-1px;right:-1px;bottom:-20px;height:2px;
  pointer-events:none;background:var(--bra,var(--navy));transition:height .18s ease}
@media(prefers-reduced-motion:reduce){
  .prop--mug.is-wink{animation:none}
  .branche,.branche::after{transition:none}
}
.branche h3{margin:0 0 10px;font-size:clamp(1.2rem,1.9vw,1.45rem);letter-spacing:-.015em}
.branche > p{margin:0 0 18px;color:var(--ink-soft);line-height:1.55;font-size:1rem}
.tags{display:flex;flex-wrap:wrap;gap:7px;margin:0;padding:0;list-style:none}
.tags li{padding:6px 12px;border-radius:8px;background:var(--paper);border:1px solid var(--line);
  color:var(--ink-soft);font-size:.87rem;font-weight:520}

/* ---- Mobil: die Reihe laeuft quer und aus dem Bild ----------------------
   Vorher stapelten sich 5 bis 7 Chips SENKRECHT, weil sie nebeneinander nicht
   passen. Gemessen waren das 195 bis 273px je Karte, mal vier Karten rund
   940px -- fast ein ganzer Bildschirm, nur fuer Wortlisten, und dabei sah es
   aus wie eine Aufzaehlung statt wie ein Angebot.
   Quer sind es 44px je Karte. Und eine Reihe, die rechts aus dem Bild laeuft,
   sagt von selbst „da kommt noch was" -- Bewegung ohne Animation.
   DIE RECHNUNG: die Reihe muss aus ZWEI Polstern heraus, dem der Karte
   (--karte-pad) und dem der Sektion (--page). Negative Marge schiebt den
   Scrollkasten exakt bis zur Bildkante, das gleich grosse padding-right sorgt
   dafuer, dass der letzte Chip am Ende des Scrollwegs nicht an der Kante
   klebt. Weil beide Werte aus denselben Variablen kommen wie die Polster
   selbst, kann die Reihe nie ueber die Kante hinausragen und einen
   waagerechten Ueberlauf erzeugen. */
@media(max-width:700px){
  /* KEINE Scroll-Reihe mehr. Sie war die Antwort auf 5 bis 7 senkrecht
     gestapelte Pillen (gemessen 195 bis 273px je Karte) — aber eine Reihe, die
     an der Bildkante abgeschnitten wird, sieht auf dem Handy nach Fehler aus,
     auch mit Blende. Und Wischen in einer Liste, die man nur LIEST, ist
     Bedienung ohne Nutzen.
     Jetzt sind es keine Pillen mehr, sondern eine Zeile Fliesstext mit
     Trennpunkten. Gerechnet: sechs Begriffe sind rund 90 Zeichen, bei 39
     Zeichen je Zeile also drei Zeilen = etwa 66px. Gestapelt waren es 234px,
     die Scroll-Reihe war 36px. Nichts wird abgeschnitten, nichts muss
     gewischt werden, und die Begriffe bleiben vollstaendig im Text — sie
     tragen ja die Long-Tail-Suchbegriffe. */
  .tags{
    display:block;overflow:visible;margin-right:0;padding-right:0;
    font-size:.92rem;line-height:1.65;color:var(--muted);
    -webkit-mask-image:none;mask-image:none;min-width:0}
  /* Aus Pillen werden Woerter: kein Rahmen, keine Fuellung, kein Kasten.
     Der Trennpunkt steckt im ::after und nicht im Text — so bleibt der
     Wortlaut sauber, wenn jemand die Begriffe kopiert. */
  .tags li,
  .branche[class*="branche--"] .tags li{
    display:inline;padding:0;border:0;background:none;border-radius:0;
    color:inherit;font-size:inherit;font-weight:520}
    /* --line waere hier fast unsichtbar (ein Haarlinien-Grau auf Weiss). Der
     Punkt soll trennen, nicht verschwinden. */
  .tags li:not(:last-child)::after{content:" · ";color:rgba(107,125,143,.55)}
  /* Tastatur: eine scrollbare Flaeche muss erreichbar sein. hero.js setzt
     tabindex nur, wenn wirklich mehr drin steht als hineinpasst. */
  .tags[tabindex]:focus-visible{outline:2.5px solid var(--cyan-ink);outline-offset:4px;border-radius:4px}
}

/* ---- Farbe je Branche -------------------------------------------------
   Vier Akzente, und sie sind NICHT ausgedacht: die ersten beiden sind aus den
   Screenshots der echten Kundenseiten gemessen (Reifenservice-Orange, GWS-Gold
   — dieselben Toene tragen auch die Punkte in der Tableiste des Heros). Fuer
   die zwei Branchen ohne Referenz kommen Petrol und Gruen dazu; Petrol ist
   absichtlich ein Verwandter des Seiten-Cyan, damit die Reihe wie eine Familie
   aussieht und nicht wie vier zufaellige Farben.
   Alle Werte sind auf Kontrast geprueft: Linien und Raender liegen ueber 3:1
   auf Weiss, die Schrift ueber 4.5:1 auf ihrer Fuellung. Die Rohtoene der
   Kundenseiten waeren dafuer zu hell gewesen (das GWS-Gelb #f4e500 kommt auf
   1,2:1) — die Toene hier sind ihre abgedunkelten Geschwister.
   Eingesetzt an genau drei Stellen: Anschlag der Standkante, Referenz-Marke,
   Chip-Raender. Nichts grossflaechig gefuellt — vier Farben, die Flaechen
   belegen, waeren Konfetti. */
.branche--kfz      {--bra:#d8541a;--bra-tief:#a34313;--bra-hell:#fdf1ea;--bra-rand:#f0c3a8}
.branche--sicher   {--bra:#b8860b;--bra-tief:#7a5a06;--bra-hell:#fbf5e4;--bra-rand:#e6d29a}
.branche--handwerk {--bra:#0f7b8a;--bra-tief:#0a5c68;--bra-hell:#e8f6f8;--bra-rand:#a9d5dc}
.branche--praxis   {--bra:#2f7d4f;--bra-tief:#235f3c;--bra-hell:#eaf5ee;--bra-rand:#b3d8c2}

/* Die Standkante traegt die Branchenfarbe auf voller Breite.
   Erste Fassung liess sie navy und faerbte nur die ersten ~84px ein. Auf einer
   580px breiten Karte war das ein Siebtel — angesehen las sich das nicht als
   Akzent, sondern wie eine Linie, die nicht fertig gezeichnet wurde. Wenn
   Farbe hier Bedeutung tragen soll (welche Branche gehoert zu welcher Karte),
   dann muss sie auch zu sehen sein.
   Alle vier Toene sind fuer diese Verwendung geprueft: als grafisches Element
   braucht es 3:1 auf Weiss, das Gold liegt mit 3,25:1 am knappsten, Orange bei
   4,04, Petrol 4,98, Gruen 5,04. Der Rueckfall bleibt navy, falls eine Karte
   mal ohne Branchenklasse steht. */

/* Chips: getoenter Rand und eine Spur Fuellung. Die Schrift bleibt --ink-soft
   — sie in der Akzentfarbe zu setzen haette bei Gold und Orange den Kontrast
   gekostet, und lesbar geht vor bunt. */
/* Nur ab 701px: darunter sind die Begriffe Fliesstext ohne Kasten, und die
   Fuellung haette dort Woerter mit farbigem Hintergrund ergeben. Diese Regel
   steht spaeter in der Datei als die mobile Umstellung und wuerde sie sonst
   ueberstimmen — gleiche Spezifitaet, spaeter gewinnt. */
@media(min-width:701px){
  .branche[class*="branche--"] .tags li{border-color:var(--bra-rand);background:var(--bra-hell)}
}

/* Abstand ab dem STANDFUSS gerechnet, nicht ab der Kartenkante: der Fuss ragt
   19px unter die Karte, gemessen blieben davor nur 19px zur Notiz. */
.branchen__note{max-width:var(--wrap);margin:clamp(48px,5vw,64px) auto 0;text-align:center;color:var(--muted);font-size:.98rem}


/* ======================================================================
   DUNKLER TAKT — die Pause zwischen zwei Textstrecken
   ======================================================================
   Zweck: nach Preis folgen Umfang und Paar, noch einmal ueber 2.000px in
   derselben hellen Form. Ein lauter, randloser Bildschirm dazwischen setzt
   den Blick zurueck. Er traegt bewusst KEINEN Knopf — der Aufruf steht am
   Seitenende, ein zweiter davor wuerde ihn nur verduennen.

   OHNE FOTO, und das ist eine Entscheidung, keine Luecke. Hier stand eine
   Werkstatt-Aufnahme (werkstatt-abend.webp, zweispaltig, damit sie nicht
   hochskaliert wird). Sie sah zu deutlich nach KI aus — auf einer Seite, die
   von Vertrauen und echten Betrieben handelt, ist ein erkennbar erfundenes
   Bild schaedlicher als gar keins. Bis es eine echte Aufnahme gibt, traegt
   der Takt sich selbst: Flaeche, ein Satz, eine Uhrzeit als Grafik.
   Die Datei liegt weiterhin unter /assets/img und wird von den beiden
   Slice-Prototypen benutzt — nicht loeschen, ohne dort nachzusehen. */
.takt{position:relative;overflow:hidden;background:var(--navy);color:#e8f1fa;
  display:grid;align-items:center;isolation:isolate;
  padding:clamp(52px,7vw,104px) var(--page);
  min-height:clamp(260px,30vw,400px)}
/* Die Uhrzeit ist das, was vom Bild uebrig bleibt: gross, sehr leise, und in
   derselben Mono, die auch die Abschnitts-Schiene und das Mobilmenue
   benutzen. Sie steht hinter dem Satz und sagt dasselbe — deshalb
   aria-hidden, fuer Vorleseprogramme waere sie eine Doppelung.
   Kontrast bewusst unter jeder Lesbarkeitsschwelle: sie ist Flaeche, kein
   Text. Wer sie entziffern will, soll es koennen, wer nur liest, soll sie
   nicht bemerken.

   GANZE ZIFFERN, KOMPLETT INNERHALB DER SEKTION. Vorher lag sie mit
   bottom:-.24em und right:-.06em unter der Kante und wurde von
   overflow:hidden unten und rechts amputiert — angesehen las sich das nicht
   als Absicht, sondern als Unfall. Jetzt sitzt sie auf der Unterkante auf
   (bottom:0) und steht seitlich mit einer Winzigkeit Luft im Bild.
   Ein Zwischenstand liess sie unten aus der Sektion herausragen. Das brauchte
   zwei Farben (Weiss auf 5% ist auf der hellen Sektion unsichtbar, die Zahl
   waere unten einfach weg) und mit negativem right auch 15px waagerechten
   Ueberlauf mit sichtbarer Scrollleiste. Verworfen — beides Aufwand fuer eine
   Zahl, die leise sein soll. */
/* Sie steht STILL auf 22:00 und sitzt auf der Unterkante der Sektion.
   Zwei Zwischenstaende sind wieder ausgebaut, und beide Gruende gehoeren
   hierher, damit sie niemand nachbaut:
   - Sie hat einmal durch die Stunden gezaehlt (Start 22, eine Runde, zurueck
     auf 22). Sah gut aus, hat aber nichts gesagt, was die Zahl nicht schon
     sagt, und war eine dauerhafte Bewegung in einem Abschnitt, der von Ruhe
     lebt.
   - Darunter stand eine Statuszeile („Online · 24/7 · 365 Tage“). Die hat
     denselben Gedanken ein zweites Mal ausgesprochen, den der Satz daneben
     ohnehin macht.
   Was bleibt, ist die Zahl als Flaeche: gross, sehr leise, ganze Ziffern,
   aufsitzend auf der Kante. 22:00 ist die Stunde, die der Satz nennt — Zahl
   und Wortlaut sagen dasselbe, und mehr muss dort nicht passieren. */
.takt__uhr{position:absolute;z-index:0;right:-.06em;bottom:-.24em;
  font:700 clamp(6.5rem,20vw,16rem)/.78 "Geist Mono",ui-monospace,monospace;
  letter-spacing:-.045em;color:rgba(255,255,255,.05);
  pointer-events:none;-webkit-user-select:none;user-select:none;white-space:nowrap}

.takt__wort{position:relative;z-index:1;max-width:var(--wrap);margin:0 auto;width:100%}
.takt__zeile{margin:0;position:relative;padding-top:22px;max-width:22ch;
  font-size:clamp(1.45rem,3.1vw,2.5rem);line-height:1.18;letter-spacing:-.02em;font-weight:760}
/* Haarlinie in Cyan ueber dem Satz: dasselbe Zeichen, das auf der hellen
   Seite die Karten markiert — hier ist es der Anschlag des Taktes. */
.takt__zeile::before{content:"";position:absolute;top:0;left:0;width:44px;height:2px;background:var(--cyan)}
/* text-wrap:balance verteilt die Zeilen gleichmaessig, statt die letzte als
   Rest stehen zu lassen — ohne das stand „auch." allein auf einer Zeile.
   Aeltere Browser ignorieren die Zeile und brechen wie bisher, kein Rueckfall
   noetig. */
/* Nur die direkten Kinder werden Bloecke. Der Kindselektor stammt aus einer
   Fassung, in der die Tageszeit in einem eigenen span steckte und sonst mit
   umgebrochen waere; er bleibt, weil er ohnehin genauer ist. */
.takt__zeile > span,.takt__zeile > b{display:block;text-wrap:balance}
/* Der Abschnitt hatte zwischenzeitlich zwei bewegte Sachen: die Tageszeit im
   Satz wechselte mit der Uhr (22 abends um zehn, 6 morgens um sechs, 12 mittags
   um zwoelf), und darunter stand eine Statuszeile mit gruenem Punkt. Beides ist
   wieder raus, und der Grund gehoert hierher, damit es niemand nachbaut:
   Text, der sich aendert waehrend man ihn liest, ist die einzige Bewegung, die
   das Verstehen unterbricht — wer mitten im Satz erwischt wird, liest neu und
   haelt es fuer einen Fehler. Und die Statuszeile hat den Gedanken des Satzes
   ein zweites Mal ausgesprochen, statt ihn zu tragen.
   Der Abschnitt ist jetzt, was er sein soll: eine Flaeche, ein Satz, eine
   Uhrzeit. Nichts davon bewegt sich. */
.takt__zeile span{color:#8fa6bd;font-weight:600}
.takt__zeile b{color:#fff;font-weight:760}

@media(max-width:700px){
  .takt__zeile{max-width:none}
  /* Auf dem Handy ist die Uhrzeit kleiner und noch leiser: die Zeilen laufen
     dort ueber die ganze Breite und wuerden sie sonst kreuzen. Der Anschnitt
     ist eine Spur tiefer als auf dem Desktop, weil die Zahl im Verhaeltnis
     zur Sektionshoehe groesser ist. */
  .takt__uhr{font-size:clamp(5rem,34vw,9rem);bottom:-.28em;right:-.04em;
    color:rgba(255,255,255,.042)}
}

/* ---- Regionen (lokale Signale) ---- */
/* --fuge steht ganz oben, weil ZWEI Sachen exakt dieselbe Zahl brauchen: die
   Fugen des Kartenrasters und die Luecken in der Maske des Abschlussbands.
   Zweimal dasselbe clamp() haette beim naechsten Anfassen um einen Pixel
   auseinandergelaufen — und dann steht das Band unter den Karten schief. */
/* ---- HELL, und das ist eine Ruecknahme mit Begruendung ----------------
   Diese Sektion war am 28.07. kurzzeitig dunkel (navy), um eine gemessene
   Strecke von 3.400px ohne dunklen Anker aufzubrechen. Wieder zurueck, und
   der Grund gehoert hierher, damit es niemand als „gute Idee“ neu vorschlaegt:

   1. DIE DUNKELHEIT WAR NICHT VERDIENT. Der Takt ist dunkel, weil sein
      Inhalt Nacht IST (22:00, „abends um zehn“). Der Abschluss ist dunkel,
      weil er das Ende ist. Diese Sektion ist eine Ortsliste — sie hatte
      keinen inhaltlichen Grund. Ein Farbumschlag ohne Grund ist genau der
      Zug, an dem man ein Template erkennt.
   2. Mit 785px war sie der GROESSTE dunkle Block der Seite. Der eine dunkle
      Moment mit Bedeutung — der Takt mit 412px — stand damit im Schatten
      eines groesseren ohne Bedeutung.
   3. Die Messung dahinter war auf der falschen Achse: gezaehlt wurde nur der
      HINTERGRUND. Tatsaechlich stehen auf dieser Strecke fuenf verschiedene
      Kompositionen (Preis mit getrennten Karten und Cyan-Kasten, Umfang als
      zusammenhaengender Block mit Symbolen, Pair als einzelne mittige
      Aussage, Regionen als Dreierreihe, FAQ als Aufklappliste). Sie variiert
      ueber die FORM, nicht ueber die Flaeche.

   Was dabei verlorengeht, ist echt: auf Navy leuchten die 30 Cyan-Punkte vor
   den Ortsnamen deutlich staerker. Wer das zurueckholen will, macht die
   Ortsnamen auf hellem Grund kraeftiger — nicht den Hintergrund dunkel. */
.regionen{--fuge:clamp(18px,2.4vw,26px);
  padding:clamp(52px,7vw,100px) var(--page);background:var(--paper)}                    /*  8,0:1 */

/* Der Abstand zur Ueberschrift. Er stand frueher nur fuer den einspaltigen
   Fall und wurde ab 901px von einem negativen Rand ueberschrieben, damit die
   Karten in das Bild darueber hineinragen — das Bild ist raus, der negative
   Rand mit ihm. */
.regionen__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--fuge);
  max-width:var(--wrap);margin:clamp(20px,5vw,28px) auto 0}
.region{padding:clamp(24px,2.4vw,32px);border-radius:0;background:var(--white);border:1px solid var(--line)}
.region h3{margin:0 0 8px;font-size:1.2rem;letter-spacing:-.015em}
.region p{margin:0 0 14px;color:var(--ink-soft);line-height:1.5;font-size:.98rem}
.region__orte{margin:0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:6px 10px;font-size:.88rem;color:var(--muted)}
.region__orte li{position:relative;padding-left:13px}
.region__orte li::before{content:"";position:absolute;left:0;top:.45em;width:6px;height:6px;border-radius:50%;background:var(--cyan)}
/* Kante oben auf ALLEN drei Karten. Sie ist damit kein Zustand mehr, sondern
   die Form der Karte — und die Karten stehen als Reihe zusammen, statt dass
   eine herausfaellt.
   Die Standort-Karte war vorher komplett cyan gefuellt. Angesehen las sich das
   als AUSGEWAEHLT, als haette man geklickt. Sie soll aber nur sagen „hier
   sitzen wir“ — das macht jetzt die Marke darueber, nicht die Flaeche. */
.region{position:relative}
.region::before{content:"";position:absolute;left:-1px;right:-1px;top:-1px;
  height:2px;background:var(--cyan)}
.region--sitz{background:var(--white);border-color:var(--line)}
.region__marke{display:block;margin:0 0 10px;
  font-size:.72rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cyan-ink)}

/* Gemessen stand die Zeile auf 15,68px und damit unter der Fliesstextgroesse
   der Karten — als Abschluss einer Sektion zu leise. Jetzt auf Fliesstext-
   niveau und in der normalen Textfarbe statt im Grau. */
.regionen__note{max-width:var(--wrap);margin:clamp(30px,3.4vw,44px) auto 0;
  text-align:center;color:var(--ink-soft);font-size:1.06rem;line-height:1.55}

/* ---- Ab drei Spalten fluchten die Karten ------------------------------
   Hier stand frueher ein randloses Foto (eine Daemmerungsaufnahme), ueber das
   die Karten mit ihrer Oberkante hineinragten, und darunter dasselbe Bild in
   drei Stuecken auf Kartenbreite. Beides ist raus — die Sektion ist eine
   Textsektion, und das Foto hat mit ihr um Aufmerksamkeit konkurriert, statt
   sie zu tragen.
   Was bleibt, ist die Flucht der drei Karten (subgrid, s. unten). Wer hier
   wieder ein Bild einsetzen will: die Datei eifel-daemmerung.webp liegt noch
   unter /assets/img, wird aber von keiner Seite mehr benutzt. */
@media(min-width:901px){
  /* Die Karten teilen sich EIN Zeilenraster, damit Titel, Absatz und Ortsliste
     ueber alle drei auf derselben Linie beginnen. Ohne das haengt jede Zeile
     an der Laenge dessen, was darueber steht: gemessen begann der Titel der
     ersten Karte 25px tiefer als die anderen zwei (sie traegt die Marke
     „Unser Standort"), und bei 901px lagen die drei Ortslisten 24px
     auseinander, weil die Ortsnamen dort unterschiedlich oft umbrechen.
     Drei Karten auf drei Hoehen lesen sich als drei einzelne Kaesten, nicht
     als eine Reihe.

     subgrid statt eigener Rechnung: die Karte uebernimmt die vier Zeilen des
     Elternrasters, statt sich eigene zu bauen. Jede Zeile ist damit so hoch
     wie ihr laengster Inhalt in ALLEN drei Karten. Die Platzierung steht
     ausdrucklich an jedem Kind, weil zwei der drei Karten keine Marke haben —
     ohne das rutschte bei ihnen alles eine Zeile hoch und der Effekt waere
     genau verkehrt.
     Die 1fr auf der Absatzzeile nimmt den Rest der Kartenhoehe auf, damit die
     Ortsliste unten steht und nicht mitten in der Karte haengt.

     Nur ab 901px — darunter steht das Raster einspaltig, dann gibt es keine
     Reihe, auf der etwas fluchten koennte. */
  /* row-gap:0 ist PFLICHT, nicht Kosmetik. gap:var(--fuge) auf dem Raster
     setzt Spalten- UND Zeilenfuge. Solange es eine Zeile gab, war die
     Zeilenfuge wirkungslos; mit vier Zeilen lagen plotzlich 3x26px INNERHALB
     jeder Karte — gemessen ein Loch von 116px zwischen Absatz und Ortsliste.
     Den Abstand machen die Margen der Elemente, so wie vorher. */
  .regionen__grid{grid-template-rows:auto auto 1fr auto;row-gap:0}
  .region{position:relative;z-index:1;box-shadow:0 14px 34px -26px rgba(2,9,20,.34);
    display:grid;grid-template-rows:subgrid;grid-row:span 4}
  .region__marke{grid-row:1}
  .region h3{grid-row:2}
  .region p{grid-row:3}
  .region__orte{grid-row:4}
  /* Ohne subgrid bekommt die Karte eigene Zeilen, dann fluchtet nichts mehr
     ueber die Karten hinweg. Dann wenigstens die Listen auf eine Linie, ueber
     die Kartenunterkante — die Karten sind als Raster-Kinder gleich hoch. */
  @supports not (grid-template-rows:subgrid){
    .region{display:flex;flex-direction:column}
    .region__orte{margin-top:auto}
  }
}

/* ---- FAQ (natives details/summary, kein JS) ---- */
.faq{padding:clamp(52px,7vw,100px) var(--page);background:var(--white)}
.faq__list{max-width:840px;margin:0 auto}
.faq__item{border-bottom:1px solid var(--line)}
.faq__item:first-child{border-top:1px solid var(--line)}
.faq__item summary{display:flex;align-items:center;justify-content:space-between;gap:18px;
  padding:22px 4px;cursor:pointer;list-style:none;font-size:clamp(1.02rem,1.4vw,1.14rem);font-weight:640;
  letter-spacing:-.01em;color:var(--ink);transition:color .15s ease}
.faq__item summary::-webkit-details-marker{display:none}
.faq__item summary:hover{color:var(--cyan-ink)}
.faq__item summary::after{content:"";flex:0 0 auto;width:12px;height:12px;margin-right:4px;
  border-right:2.4px solid var(--cyan-ink);border-bottom:2.4px solid var(--cyan-ink);
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .22s ease}
.faq__item[open] summary::after{transform:rotate(225deg) translate(-2px,-2px)}
.faq__item[open] summary{color:var(--cyan-ink)}
.faq__answer{margin:0;padding:0 4px 24px;max-width:70ch;color:var(--ink-soft);line-height:1.6;font-size:1rem}
.faq__answer a{color:var(--cyan-ink);font-weight:600}
.faq__note{max-width:840px;margin:clamp(26px,3vw,36px) auto 0;text-align:center;color:var(--muted);font-size:.95rem}

/* ---- CTA + Footer ---- */
/* overflow:hidden, damit das randlose Maskenwort saeuberlich an der Sektionskante
   beschnitten wird statt eine Seitenleiste zu erzeugen. */
/* Der Abschluss-Abschnitt liegt jetzt in assets/css/finale.css und wird von
   allen Unterseiten geteilt (websites, shops, software). Bitte dort aendern —
   die Werte hier standen vorher dreimal parallel und liefen auseinander. */

.web-foot{display:flex;flex-wrap:wrap;gap:12px 26px;justify-content:space-between;align-items:center;
  padding:26px var(--page);background:var(--navy);color:#8ea1b5;font-size:.9rem;border-top:1px solid rgba(255,255,255,.07)}
.web-foot a{color:#c4d2e0;text-decoration:none}
.web-foot a:hover{color:#fff}
.web-foot__worlds a{margin:0 2px}

/* ---- Responsive ---- */
@media(max-width:900px){
  .case__paar{grid-template-columns:1fr;gap:clamp(38px,6vw,56px)}
  .steps{grid-template-columns:1fr 1fr;gap:28px}
  .umfang__grid{grid-template-columns:1fr 1fr}
  .branchen__grid{grid-template-columns:1fr}
  .regionen__grid{grid-template-columns:1fr}
  .preis__grid{grid-template-columns:1fr 1fr}
  .zusage{grid-template-columns:1fr;gap:24px}
}
@media(max-width:600px){
  .preis__grid{grid-template-columns:1fr}
}
/* Unter 768px raeumt site-nav.css Welten und Aktionen selbst aus der Leiste;
   uebernommen hat sie dann die gemeinsame Edge-Nav (edge-nav.css).
   EINE Sache muss diese Seite doch richtigstellen: edge-nav.css schiebt den
   Griff nach unten und nach rechts, sobald er sich in die drei Punkte
   verwandelt (52px statt 36px, 10px statt 18px vom Rand). Das ist auf den
   dunklen Seiten richtig — dort faehrt der Kopf beim Scrollen weg und der Griff
   steht danach frei im Bild. Hier BLEIBT die Leiste stehen, es gibt also nichts
   auszuweichen: gemessen sass er als Punkte 20px unter der Leistenmitte.
   Beide Zustaende sitzen jetzt mittig IN der Leiste, an ihre Hoehe gekoppelt
   statt fest verdrahtet. */
@media(max-width:768px){
  html body.web .edge-handle,
  .nav-compact body.web .edge-handle{top:calc(var(--nav-hoehe,64px) / 2);right:18px}
}

@media(max-width:600px){
  .steps{grid-template-columns:1fr}
  /* TREPPE: gestapelt hat jeder Schritt seine eigene Oberkante. Die Cyan-Marken
     wachsen beim Scrollen unterschiedlich weit — der unterste ganz durch, jeder
     darueber ein Stueck weniger. Ergibt eine Treppe von kurz (oben) nach lang
     (unten), also eine sichtbare Zunahme statt vier gleicher Striche.
     Startwert ist die vorhandene 42px-Marke, NICHT 0: ohne JavaScript und im
     Ausgangszustand sieht der Abschnitt genauso aus wie bisher.
     --sp (0..1) kommt aus dem JS. */
  .step{--ziel:100%}
  .step:nth-child(1){--ziel:30%}
  .step:nth-child(2){--ziel:53%}
  .step:nth-child(3){--ziel:76%}
  .step:nth-child(4){--ziel:100%}
  .step::before{width:calc(42px + (var(--ziel) - 42px) * var(--sp,0))}
  .umfang__grid{grid-template-columns:1fr}
  .cta__row{gap:16px}
}
