/* ============================================================
   Pactos Website — geteilte Komponenten (Header, Footer, Fixes)
   Quelle der Wahrheit ab Phase 2. Reihenfolge = Kaskadenreihenfolge:
   Header-Styles -> Footer-Styles -> Basis-Layout -> Härtung.
   Einbau in Seiten via tools/apply-partials.mjs (Ende <body>).
   ============================================================ */

/* ---- 1. Header (aus partials/header.html, TEIL B) ---- */
/* Transparenter Header, verschmilzt mit dem grünen Banner */
.nav-outer{position:fixed;top:0;left:0;right:0;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-bottom:1px solid transparent;padding-top:0;transition:background .3s ease,border-color .3s ease,backdrop-filter .3s ease}
.nav-outer.scrolled{background:var(--grad-shell-scroll);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom-color:rgba(255,255,255,.12)}
.nav-outer .nav{background:transparent;border:0;border-radius:0;box-shadow:none;padding:40px 0}
.nav-outer .btn-ghost{background:transparent;border-color:rgba(255,255,255,.3);color:#fff}
.nav-outer .btn-ghost:hover{background:rgba(255,255,255,.12)}
.nav-outer .nav-cta .btn{white-space:nowrap}
.nav-outer .nav-cta a.btn-primary{background:#52EFBA;color:#000}
.nav-outer .nav-cta a.btn-primary:hover{background:#7CF4CB;color:#000}

/* DE/EN Umschalter (Klick tauscht DE<->EN, kein Rahmen) */
.nav-outer .lang-toggle{display:inline-flex;align-items:center;gap:7px;background:transparent;border:0;color:#fff;font-family:inherit;cursor:pointer;padding:8px 4px;transition:color .16s ease}
.nav-outer .lang-toggle:hover{color:#52EFBA}
/* Flagge im Sprachumschalter, rund (Patrick, 20.08.2026). 16px Durchmesser =
   die Groesse des Globus-Symbols, das hier vorher stand, damit die Zeile ihre
   Hoehe behaelt. `border-radius:50%` ist die im DESIGN.md ausdrueckliche
   Kreis-Ausnahme von der Token-Pflicht (--r-full gilt nur fuer Avatare).
   Die Flaggen sind breiter als hoch; `preserveAspectRatio="…slice"` im SVG
   laesst sie das runde Feld fuellen und beschneidet die Seiten.
   Der Innenring ersetzt einen Rahmen: er trennt die weissen Flaechen der
   britischen Flagge vom dunklen Header, ohne die Flagge zu verkleinern. */
/* Weltkugel statt Flagge (Antonio, 25.08.2026). Ein Icon fuer alle Sprachen,
   deshalb entfallen die vier .flagge-Regeln und mit ihnen die Rolle von
   `.ist-en` hier — die Klasse setzt src/js/header.js weiterhin, sie steuert
   jetzt aber nichts mehr im CSS. Kein Kreis-Rahmen: die Kugel ist eine
   Strichzeichnung in currentColor und nimmt die Farbe der Navigation mit. */
.nav-outer .lang-globus{flex:none;display:inline-flex;width:16px;height:16px}
.nav-outer .lang-globus svg{width:100%;height:100%;display:block}
/* Nav-Trigger: weiß -> Mint beim Hover (Years) */
.nav-outer .nav-links{display:flex;align-items:center;gap:4px}
.nav-outer .nav-item{position:relative;display:flex;align-items:center}
/* Mint-Flaeche beim Ueberfahren (Patrick, 04.09.2026) — uebernommen von
   pactos.ai. Dort gemessen: .navbar6_link:hover und
   .navbar-dropdown9_dropdown-link:hover setzen beide #C5FAE8 mit Text #0A4E47,
   Radius 8px. Beide Werte sind bei uns schon Token (--tech-soft, --green-800),
   der Radius kommt aus unserer Skala (--r-sm, 10px).
   ⚠ NICHT fuer .mega-head: die Kaesten in "Loesungen" und das Kundenpanel unter
   "Referenzen" behalten ihren eigenen Hover (Rahmen + --tech-tint). */
.nav-outer .nav-trigger{display:inline-flex;align-items:center;color:#fff;text-decoration:none;border-radius:var(--r-sm,10px);cursor:pointer;transition:color .16s ease,background-color .16s ease}
.nav-outer .nav-trigger .chev{width:14px;height:14px;color:#fff;transition:transform .2s ease,color .16s ease}
.nav-outer .nav-item:hover .nav-trigger,.nav-outer .nav-trigger:hover,.nav-outer .nav-trigger:focus-visible{background:var(--tech-soft);color:var(--green-800)}
.nav-outer .nav-item:hover .nav-trigger .chev,.nav-outer .nav-trigger:hover .chev{color:var(--green-800)}
.nav-outer .nav-item:hover .nav-trigger .chev{transform:rotate(180deg)}
/* Mega-Panels */
/* ⚠ --mega-luft IST GEMESSEN, NICHT GESCHAETZT. Antonio (25.08.2026): „diese Box
   poppt auf und ist ein bisschen groesser, dass sie oben bei dem Rand so
   reingeht. Wir muessten die ein bisschen mehr reingehen oder die muesste direkt
   buendig sein" — vorher standen hier 16px, und damit begann das Panel 4px
   OBERHALB der Header-Unterkante, lag also unter der Leiste.
   Die Rechnung, bei 1440px gemessen und in beiden Header-Zustaenden gleich:
     .nav-outer endet bei 81px (80px Leiste aus `.nav{height:80px}` + 1px Rand)
     .nav-item endet bei 61,5px (mittig in der 80er Leiste, 43px hoch)
     -> 19,5px sind buendig, alles darunter ueberlappt
   28px = buendig plus 8px sichtbare Luft. Das ist die Loesung, die Antonio bei
   Takto beschrieben hat („die sind nicht in deren Box, wir haben ein bisschen
   Abstand, die dann drunter gehen").
   ⚠ Die Zahl haengt an der Hoehe der Leiste UND an der Hoehe von .nav-item. Wer
   eine von beiden aendert, muss hier neu messen: Abstand von .mega-inner
   Oberkante zu .nav-outer Unterkante, Soll ist +8, nicht negativ.
   Nebeneffekt und gewollt: das Polster ist die Hover-Bruecke zwischen Ausloeser
   und Panel. Groesser heisst, der Zeiger verliert das Menue nicht im Spalt. */
.nav-outer{--mega-luft:28px}
.nav-outer .mega{position:absolute;top:100%;left:0;padding-top:var(--mega-luft);opacity:0;visibility:hidden;transform:translateY(8px);transition:opacity .2s ease,transform .2s ease;z-index:var(--z-mega,90);pointer-events:none}
/* ⚠ `.ra` GILT NUR NOCH IM SCHMALEN FENSTERBAND (Patrick, 31.08.2026: „mach
   das da mal auch bitte linksbündig oder geht das da wegen der Border nicht").
   Es geht, und es liegt nicht an einem Rahmen, sondern am rechten Fensterrand.
   Gemessen, wo ein linksbuendiges Unternehmen-Panel (536 px) enden wuerde:
     1300 px Fenster → 1282 px, also 18 px vor dem Rand und im 24-px-Bundsteg
     1440 px → 1288 px (152 px Luft) · 1920 px → 1309 px (611 px Luft)
   Ueber 1360 px ist es also unkritisch; nur im Band 1281 bis 1360 px bleibt es
   rechtsgebunden, sonst klebt es am Rand. */
.nav-outer .mega.ra{left:0;right:auto}
@media (min-width:1281px) and (max-width:1360px){.nav-outer .mega.ra{left:auto;right:0}}
@media (hover:hover){.nav-outer .nav-item:hover .mega{opacity:1;visibility:visible;transform:none;pointer-events:auto}}
.nav-outer .nav-item:focus-within .mega{opacity:1;visibility:visible;transform:none;pointer-events:auto}
/* DECKEND (Patrick, 31.07.2026) — vorher rgba(255,255,255,.94) + blur(16px).
   Die 6 % Durchlaessigkeit waren KEIN Lesbarkeitsfehler: schlechtester Fall war
   --muted ueber der dunkelsten Stelle des Shell-Verlaufs mit 4,95:1, also ueber
   der AA-Schwelle 4,5. Der Grund ist rein visuell und faellt nur auf Fotoseiten
   auf: auf branche-pflege lief die senkrechte Tuerkante durch das Panel weiter
   und die linke Haelfte nahm einen Gruenstich von Pflanze und Fenster an. Das
   Panel las sich als Folie auf dem Bild statt als eigene Ebene.
   Auf hellen Seiten ist der Unterschied 0,08 Kontraststufen, also unsichtbar.

   backdrop-filter ist mitentfernt, weil er hinter einer deckenden Flaeche nichts
   mehr filtert — KEIN Performance-Argument: das geschlossene Panel ist
   opacity:0 + visibility:hidden und wird ohnehin nicht gezeichnet.
   ⚠ Die Header-LEISTE bleibt transluzent (.nav-outer.scrolled, --grad-shell-scroll
   mit blur(10px)) — das ist eine andere Flaeche und bewusst so. */
.nav-outer .mega-inner{background:var(--surface);border:1px solid var(--line);border-radius:18px;padding:24px;box-shadow:0 30px 60px -28px rgba(0,0,0,.7);display:grid;gap:28px}
/* grid-auto-rows:1fr macht beide Reihen gleich hoch. Ohne das steht Reihe zwei
   auf den 132px aus der Mindesthoehe, waehrend Reihe eins 137px misst — der
   zweizeilige Titel von "Vendor Intelligence" ueber einer dreizeiligen
   Beschreibung gibt den Ausschlag. */
.nav-outer .mega-4 .mega-inner{grid-template-columns:repeat(4,minmax(178px,1fr));grid-auto-rows:1fr;width:920px}
.nav-outer .mega-3 .mega-inner{grid-template-columns:repeat(3,minmax(190px,1fr));width:700px}
.nav-outer .mega-1 .mega-inner{grid-template-columns:1fr;width:250px;gap:0;padding:12px}
/* Kundenband-Panel: EINE Spalte, breiter als mega-3, damit fuenf Logos je Reihe
   passen. ⚠ Diese Zeile MUSS oberhalb des Mobil-Blocks stehen: der Reset dort
   hat dieselbe Spezifitaet und verliert gegen jede spaetere Regel. */
.nav-outer .mega-kunden .mega-inner{grid-template-columns:1fr;width:640px;gap:14px}
.nav-outer .mega-col{display:flex;flex-direction:column}
.nav-outer .mega-title{color:var(--ink);font-weight:600;text-decoration:none;transition:color .16s ease}
.nav-outer .mega-title:hover{color:var(--green-700)}
.nav-outer .mega-desc{color:var(--muted);margin:5px 0 14px;line-height:1.45}
.nav-outer .mega-label{color:var(--muted);letter-spacing:.12em;text-transform:uppercase;margin-bottom:14px}
/* Der Innenabstand von 10px kam mit der Mint-Flaeche dazu, das negative
   Aussenmass haelt den Text an derselben Stelle wie vorher. */
.nav-outer .mega-link{color:var(--ink-soft);text-decoration:none;padding:6px 10px;margin-inline:-10px;border-radius:var(--r-sm,10px);transition:color .16s ease,background-color .16s ease}
.nav-outer .mega-link:hover{background:var(--tech-soft);color:var(--green-800)}
/* Produktlinie eingerahmt (abgehoben von den Unterpunkten) */
.nav-outer .mega-4 .mega-col{gap:2px}
.nav-outer .mega-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;min-height:124px;border:1px solid var(--line);background:var(--surface-2);border-radius:12px;padding:14px 15px;margin-bottom:14px;text-decoration:none;transition:border-color .16s ease,background .16s ease}
.nav-outer .mega-head .mega-htxt{display:block}
.nav-outer .mega-arrow{flex:none;color:var(--ink);line-height:0;margin-top:1px;transition:color .16s ease,transform .16s ease}
.nav-outer .mega-head:hover .mega-arrow{color:var(--green-700)}
.nav-outer .mega-head:hover{border-color:var(--green-700);background:var(--tech-tint)}
.nav-outer .mega-head .mega-title{display:block;color:var(--ink);font-weight:600;transition:color .16s ease}
.nav-outer .mega-head:hover .mega-title{color:var(--green-700)}
.nav-outer .mega-head .mega-desc{display:block;color:var(--muted);margin:4px 0 0;line-height:1.4}

.nav-outer .mega-1 .mega-link{padding:9px 10px;margin-inline:0;border-radius:var(--r-sm,10px)}
.nav-outer .mega-1 .mega-link:hover{background:var(--tech-soft);color:var(--green-800)}
/* Abgesetzter Menuepunkt (Antonio, 25.08.2026): "Fuer Personaldienstleister"
   ist keine Rolle wie Einkauf oder HR, sondern die andere Marktseite. Ein
   Strich darueber trennt, ohne eine vierte Spalte oder eine zweite
   Beschriftung zu brauchen. Farbe aus --line, damit es zu den Rahmen im
   Panel passt und nicht als Element auffaellt. */
/* ⚠ ECHTE TRENNLINIE, NICHT DIE OBERKANTE DER HOVER-FLAECHE (09.09.2026).
   Vorher stand hier `margin-top:10px;padding-top:12px;border-top:1px solid
   var(--line)` am Link selbst. Der Rand lag damit INNERHALB der Hover-Flaeche:
   beim Ueberfahren bekommt `.mega-link` eine mintgruene, abgerundete Kachel
   (Zeile 118), und die Linie war deren Oberkante — sie las sich als Rahmen der
   Box und nicht als Trenner zwischen den Eintraegen. Patrick, 09.09.2026:
   „in der Nav ist bei Fuer Personaldienstleister als Trennlinie einfach die
   obere Linie der Box genommen, wir wollen aber eine echte Trennlinie."
   Jetzt liegt sie als Pseudoelement IM ABSTAND ueber dem Link, also ausserhalb
   der Hover-Flaeche — Hovern veraendert sie nicht mehr.
   ⚠ `left/right:10px` heben das `margin-inline:-10px` des Links auf (Zeile
   117). Ohne das waere die Linie 20 px breiter als der Text der Spalte, also
   genau so breit wie die Hover-Kachel — der Eindruck, den wir loswerden
   wollten. Im Mobil-Panel wird das wieder auf 0 gesetzt, dort ist
   `margin-inline` 0 (siehe §15).
   Der Abstand bleibt derselbe wie vorher: 10 + 12 px = 22 px, Linie in der
   Mitte. Antonios Vorgabe vom 25.08.2026 („oben ein bisschen abtrennen")
   ist damit unveraendert erfuellt. */
.nav-outer .mega-link.mega-abgesetzt{position:relative;margin-top:22px}
.nav-outer .mega-link.mega-abgesetzt::before{content:"";position:absolute;
  left:10px;right:10px;top:-11px;height:1px;background:var(--line)}
/* ENTFERNT 31.07.2026: eine Query @media (max-width:1120px), die .mega-4/.mega-3 auf zwei
   Spalten und 560px verkleinerte. Sie regelte den Bereich zwischen 1025 und 1120px, in dem
   das 920px breite „Lösungen"-Panel rechts herausragte. Seit dem Burger-Umbruch (§15)
   übernimmt unterhalb von 1281px die Mobil-Fassung: schwebende Mega-Panels gibt es dort
   nicht mehr, sie sind Akkordeons in der Panel-Spalte. Die Query war damit toter Code —
   ihr gesamter Geltungsbereich lag unter dem neuen Breakpoint. */

/* ---- 2. Footer (gescoped, pf-präfixiert) ---- */
/* Pactos Footer v2 (pf-präfixiert, kollisionsfrei) */

  footer.pactos-footer{
    --bg: #08302B;            /* green-900 der Website */
    --bg-deep: #08302B;
    --text: #ffffff;
    --text-dim: rgba(255,255,255,0.64);
    --text-faint: rgba(255,255,255,0.5);
    --mint: #52EFBA;          /* tech-Akzent der Website */
    --line: rgba(255,255,255,0.12);
  }
  .pactos-footer *{ margin: 0; padding: 0; box-sizing: border-box; }
  
  .pactos-footer .page-hint{
    max-width: 1280px; margin: 40px auto 24px; padding: 0 40px;
    color: #5a6b64; font-size: 13px; letter-spacing: 0.04em;
  }
  footer.pactos-footer{
    background: linear-gradient(180deg, var(--bg) 0%, var(--bg-deep) 100%);
  }
  .pactos-footer .pf-footer-inner{
    max-width: 1280px;
    margin: 0 auto;
    padding: 88px 40px 0;
  }

  /* ============ Top grid: left brand block | gap | link columns ============ */
  .pactos-footer .pf-footer-grid{
    display: grid;
    grid-template-columns: minmax(300px, 380px) 1fr;
    column-gap: 140px; /* großer Abstand wie bei fonio */
  }

  /* ---------- Left: brand ---------- */
  .pactos-footer .pf-brand .pf-logo{
    font-size: 28px; font-weight: 700; letter-spacing: -0.02em; color: #fff;
  }
  .pactos-footer .pf-brand .pf-logo span{ color: var(--mint); }
  .pactos-footer .pf-brand .pf-claim{
    margin-top: 18px; font-size: clamp(26px, 3.2vw, 38px); font-weight: 600;
    letter-spacing: -0.03em; line-height: 1.12; color: #fff;
    max-width: 14ch;
  }
  .pactos-footer .pf-brand .pf-desc{
    margin-top: 10px; font-size: 14px; line-height: 1.65; color: var(--text-dim);
  }
  .pactos-footer .pf-brand .pf-contact{ margin-top: 28px; font-size: 14px; line-height: 1.9; }
  .pactos-footer .pf-brand .pf-contact a{ color: var(--text-dim); text-decoration: none; }
  .pactos-footer .pf-brand .pf-contact a:hover{ color: var(--mint); }
  .pactos-footer .pf-brand .pf-contact .pf-addr{ display: block; }

  .pactos-footer .pf-cta-row{ margin-top: 18px; display: flex; align-items: center; gap: 12px; }
  .pactos-footer .pf-call-btn{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 11px 20px; border-radius: 999px;
    background: var(--mint); color: #08302B !important;
    font-weight: 600; font-size: 14.5px; text-decoration: none;
    transition: background 0.18s ease, transform 0.14s ease;
  }
  .pactos-footer .pf-call-btn:hover{ background: #7CF4CB; color: #08302B !important; }
  .pactos-footer .pf-call-btn:active{ transform: scale(0.98); }
  .pactos-footer .pf-call-btn svg{ width: 15px; height: 15px; }

  .pactos-footer .pf-li-btn{
    width: 42px; height: 42px; border-radius: 999px; flex: none;
    border: 1px solid rgba(255,255,255,0.2);
    display: flex; align-items: center; justify-content: center;
    color: #fff; transition: border-color 0.18s, color 0.18s, background 0.18s;
  }
  .pactos-footer .pf-li-btn:hover{ border-color: var(--mint); color: var(--mint); background: rgba(82,239,186,0.08); }
  .pactos-footer .pf-li-btn svg{ width: 19px; height: 19px; }

  /* ---------- Certifications: zentrierte eigene Sektion ---------- */
  /* KEINE Linie mehr hier (Antonio, 25.08.2026). Sie sass ueber den
     Zertifizierungen und las sich wie ein Abschluss, obwohl danach noch
     Mitgliedschaften und Rechtszeile kommen. Der Trenner ist nach unten
     gewandert, siehe .pf-bottom. Der Footer hat weiterhin genau EINEN. */
  /* ⚠ 24px oben, vorher 40. Antonio im Website-Review: „Ein bisschen weniger
     Abstand unten, oder? Weil zwischen den KI-Logos und Zertifizierung."
     Gemessen wird der Abstand zwischen der untersten KI-Kachel und dem Wort
     „Zertifizierungen"; die Zahlen stehen in KOMPATIBILITAET.md. */
  .pactos-footer .pf-certs-section{
    margin-top: 0; padding: 24px 0 8px;
    text-align: center;
  }
  .pactos-footer .pf-section-label{
    font-size: 11px; letter-spacing: 0.18em; color: var(--text-faint);
    text-transform: uppercase; margin-bottom: 28px;
  }
  .pactos-footer .pf-certs{
    display: flex; justify-content: center; gap: 72px; flex-wrap: wrap;
  }
  .pactos-footer .pf-cert{ display: flex; align-items: center; gap: 16px; text-align: left; }
  /* Die Karte ist seit 10.09.2026 ein <a> (Ziel: security). Farbe und Schrift
     erbt sie wie vorher; der Hover hebt Titel und Siegel leicht an, mehr nicht —
     es soll wie eine Karte aussehen, die man anklicken KANN, nicht wie ein Knopf. */
  .pactos-footer a.pf-cert{ color: inherit; text-decoration: none; }
  .pactos-footer a.pf-cert:hover .pf-cert-title{ color: var(--mint); }
  .pactos-footer a.pf-cert:hover .pf-holder{ background: rgba(255,255,255,1); }
  .pactos-footer .pf-cert .pf-holder{
    width: 56px; height: 56px; border-radius: 50%; flex: none;
    background: rgba(255,255,255,0.92);
    display: flex; align-items: center; justify-content: center;
  }
  .pactos-footer .pf-cert .pf-holder img{ width: 42px; height: 42px; object-fit: contain; }
  .pactos-footer .pf-cert .pf-cert-title{ font-size: 14px; font-weight: 600; color: var(--text); }
  .pactos-footer .pf-cert .pf-cert-sub{ font-size: 12.5px; color: var(--text-faint); margin-top: 2px; }

  /* Mitgliedschaften: seit 31.07.2026 echte Verbandslogos statt nachgebauter
     Wortmarken (DESIGN.md §4 verlangt echte Assets). Untere Polsterung von 8 auf
     40px, weil die Trennlinie der Bottom-Bar entfallen ist — ohne den Abstand
     klebte die Rechtszeile an den Logos. gap 14 -> 40: der alte Wert war fuer
     Text mit Punkt-Trennern gedacht. Schrift bleibt gesetzt, sie traegt den
     alt-Text falls ein Bild nicht laedt. */
  .pactos-footer .pf-memberships{ padding: 36px 0 40px; text-align: center; }

  /* ⚠ DIESE 16 REGELN WAREN AM 26.08.2026 VERSEHENTLICH GELOESCHT. Beim
     Herausnehmen der Bewertungs-Zeile reichte mein Ausschnitt bis zur
     Bottom-Bar und nahm die Sitemap-Spalten, den Marken-Block und die
     KI-Kacheln mit. Wiederhergestellt aus dem Tag stand-vor-meeting-liste.
     Wer hier wieder etwas herausnimmt: den Bereich vorher eingrenzen, nicht
     bis zum naechsten Abschnittskommentar schneiden. */
  .pactos-footer .pf-memberships .pf-logos{
    display: flex; justify-content: center; align-items: center; gap: 40px;
    flex-wrap: wrap; row-gap: 22px;
    font-size: 13px; font-weight: 600; color: var(--text-dim);
  }
  /* Weiss bei ~.7 Deckkraft — DESIGN.md §4 „Logo-Wall … Auf dunkel: weiss, ~.7".
     Die Assets sind bereits weiss (siehe assets/verbaende/), hier steht deshalb
     KEIN Filter: drei der vier Quelldateien hatten einen deckend weissen Grund,
     ein invert() haette daraus ein schwarzes Rechteck gemacht.
     Hoehe steht je Logo im Markup, weil die Wortmarken unterschiedlich viel
     Anteil an der Bildhoehe haben (OePDL 3 Zeilen, CNA mit Unterzeile). */
  .pactos-footer .pf-memberships .pf-logos img{ opacity: .7; width: auto; display: block }
  /* Logos sind Links (10.09.2026): a als Block ohne Zeilenhoehe, damit kein
     Inline-Spalt unter dem Bild entsteht; Hover nimmt die Daempfung weg. */
  .pactos-footer .pf-memberships .pf-logos a{ display: block; line-height: 0; }
  .pactos-footer .pf-memberships .pf-logos a:hover img{ opacity: 1; }

  /* ---------- Right: link columns (Themen zuerst) ---------- */
  .pactos-footer .pf-link-cols{
    display: grid;
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
    column-gap: 48px;
    align-content: start;
  }
  /* ⚠ War `h4`, ist jetzt `h2` mit Klasse. Grund: die Spaltenkoepfe folgten im
     Dokument auf ein h2 des Hauptinhalts und erzeugten damit auf JEDER Seite
     den Ebenensprung h2→h4 (34 Seiten gemessen, 24.08.2026). Die Klasse haelt
     die Gestaltung unabhaengig von der Ebene. */
  .pactos-footer .pf-col .pf-coltitel{
    font-size: 16px; font-weight: 600; letter-spacing: -0.01em;
    color: #ffffff;
    margin-bottom: 16px;
  }
  .pactos-footer .pf-col ul{ list-style: none; }
  /* ⚠ ZEILENHOEHE AM li, NICHT NUR AM a. Das a ist inline; seine line-height
     bestimmt die Zeilenbox nicht allein, das li erbte 1.6 vom body. Bei
     zweizeiligen Eintraegen („Vendor Intelligence") sah der Umbruch damit wie
     zwei getrennte Links aus (Karo, 10.09.2026). 1.25 innerhalb eines Eintrags,
     die 12 px Abstand zwischen den Eintraegen bleiben — so liest man die
     Gruppe. */
  .pactos-footer .pf-col li{ margin-bottom: 12px; line-height: 1.25; }
  .pactos-footer .pf-col a{
    color: var(--text-dim); text-decoration: none; font-size: 14px; line-height: 1.25;
  }
  .pactos-footer .pf-col a:hover{ color: var(--mint); }

  /* ---------- "Frag eine KI" links in der Marken-Spalte, unter "Jetzt anrufen" ---------- */
  .pactos-footer .pf-brand .pf-claim{ font-size: clamp(19px, 2vw, 24px); margin-top: 14px; }
  .pactos-footer .pf-footer-grid{ margin-bottom: 12px; }
  .pactos-footer .pf-ai-section{
    margin-top: 26px; padding: 0;
    border-top: none;
    text-align: left;
  }
  .pactos-footer .pf-ai-section .pf-ai-label{
    font-size: 14px; color: var(--text-dim); margin-bottom: 16px;
  }
  .pactos-footer .pf-ai-section .pf-ai-tiles{
    display: flex; justify-content: flex-start; gap: 12px;
  }
  .pactos-footer .pf-ai-section .pf-ai-tile{
    width: 46px; height: 46px; border-radius: 12px;
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
    transition: background 0.15s, transform 0.15s;
  }
  .pactos-footer .pf-ai-section .pf-ai-tile:hover{
    background: rgba(127,240,192,0.12); transform: translateY(-2px);
  }
  .pactos-footer .pf-ai-section .pf-ai-tile svg{ width: 26px; height: 26px; }

  /* ---------- Bottom bar ---------- */
  /* HIER SITZT JETZT DER EINE TRENNER (Antonio, 25.08.2026), vorher stand er
     ueber den Zertifizierungen.
     ⚠ Am 31.07. war er genau hier schon einmal weg, weil er 8px unter der
     Mitgliedschafts-Zeile sass und wie deren Unterstreichung las. Der Grund ist
     entfallen: .pf-memberships hat inzwischen 40px Innenabstand nach unten, der
     Strich haengt also nicht mehr an den Logos. Wer ihn wieder herausnimmt,
     sollte den Abstand mitpruefen.
     Der Footer hat weiterhin genau EINEN Trenner — DESIGN.md §4 nennt jetzt
     diese Stelle statt der Zertifizierungs-Linie. */
  .pactos-footer .pf-bottom{
    border-top: 1px solid var(--line);
    padding: 22px 0 30px;
    display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;
    font-size: 13px; color: var(--text-faint);
  }
  .pactos-footer .pf-bottom .pf-legal{ display: flex; gap: 24px; }
  .pactos-footer .pf-bottom .pf-legal a{ color: var(--text-faint); text-decoration: none; }
  .pactos-footer .pf-bottom .pf-legal a:hover{ color: var(--mint); }

  @media (max-width: 1024px) {
    .pactos-footer .pf-footer-grid{ grid-template-columns: 1fr; row-gap: 64px; column-gap: 0; }
    .pactos-footer .pf-link-cols{ grid-template-columns: 1fr 1fr; row-gap: 40px; }
  }
  @media (max-width: 560px) {
    .pactos-footer .pf-link-cols{ grid-template-columns: 1fr; }
  }
  /* Zertifizierungen mobil linksbuendig untereinander statt zentriert-umbrechend
     (zentriert wurde beim Umbruch jede Cert einzeln mittig -> Badges versetzt).
     Mitgliedschaften ebenso linksbuendig (Logos-Reihe links statt zentriert). */
  @media (max-width: 640px) {
    .pactos-footer .pf-certs-section{ text-align: left; }
    .pactos-footer .pf-certs{ flex-direction: column; align-items: flex-start; gap: 22px; }
    .pactos-footer .pf-memberships{ text-align: left; }
    .pactos-footer .pf-memberships .pf-logos{ justify-content: flex-start; }
  }

footer.pactos-footer{display:block;padding:0;margin:0;width:auto;max-width:none}
.pactos-footer .pf-footer-inner{display:block}
.pactos-footer .pf-brand{display:block;position:static}
.pactos-footer .pf-logo{display:block;position:static;width:auto;height:auto}

/* ---- 3. Basis-Layout für den Header ---- */
/* VOLLE BREITE (Entscheidung Patrick 27.07.2026): Logo am linken Bildschirmrand,
   CTA-Gruppe am rechten. Vorher lag der Header in einer zentrierten 1200er-Spalte,
   das Logo begann bei 1440px Fenster erst bei x=144.

   `margin-left:auto` auf .nav-cta statt `justify-content:space-between`: mit
   space-between würde der gewonnene Platz ZWISCHEN alle drei Blöcke verteilt und das
   Menü in die Mitte driften. So bleibt es am Logo, und nur die CTA-Gruppe geht nach
   rechts. (Genau das tat die Altlast `.nav-cta{margin-left:auto}` auf 17 Seiten — sie
   steht jetzt zentral, statt verstreut.)

   Der Randabstand fällt unter 1280px zurück auf 24px: 32px kosten 16px Platz, und
   darunter ist die Kopfzeile ohnehin knapp (siehe §3a in DESIGN.md, offener Punkt).

   ⚠ .nav-outer .wrap ist (0,2,0) und schlägt weiter jedes seitenlokale
   .wrap{max-width:1400px} (0,1,0) — 16 Seiten haben eine eigene, breitere
   Inhaltsspalte. Wird diese Regel je entschärft, reißen die den Header auf.

   DECKEL 1920px (Chef-Anmerkung via Patrick, 31.07.2026): Die Randausrichtung oben
   bleibt, sie lief nur unbegrenzt weiter. Die Lücke zwischen Menüende und CTA ist
   exakt `verfügbare Breite − 1191px` — bei 1440px sind das 249px, bei einem
   3440er-Ultrawide waren es 2249px. Dort stand das Logo zusätzlich 988px links
   neben der Inhaltsspalte, der Kopf hatte keinen Bezug mehr zur Seite.

   Warum 1920 und nicht 1856 o.ä.: Bei genau 1920px ist der Deckel wirkungslos
   (Rand 0, Logo bei x=32) — bis dahin ist die Darstellung bitgleich zur Fassung
   vom 27.07. Darüber friert sie ein, ein Ultrawide sieht im Kopf aus wie ein
   1920er-Monitor (Lücke 729px). Die Entscheidung vom 27.07. wird also nicht
   zurückgenommen, sondern nur nach oben begrenzt.

   `margin:0 auto` statt `margin:0` — sonst klebt der gedeckelte Header links. */
.nav-outer .wrap{max-width:1920px;margin:0 auto;padding:0 32px}
/* Rand 24px: ursprünglich, um der Desktop-Nav Platz zu schaffen. Seit dem
   Burger-Umbruch (§15) greift hier die Mobil-Leiste — der Wert bleibt für sie. */
@media (max-width:1280px){.nav-outer .wrap{padding:0 24px}}
.nav-outer .nav{display:flex;align-items:center;justify-content:flex-start;gap:16px}
.nav-outer .nav-cta{display:flex;align-items:center;gap:10px;margin-left:auto}
.nav-outer .brand a{display:block}
.nav-outer .btn{display:inline-flex;align-items:center;gap:6px;padding:10px 18px;border-radius:999px;font-weight:600;text-decoration:none;border:1px solid transparent}

/* ---- 4. Härtung: identische Schrift & Maße überall ---- */
/* Header/Footer-Härtung: identische Schrift & Maße auf allen Seiten */
.nav-outer{position:fixed;top:0;left:0;right:0;z-index:var(--z-header,100);font-family:"Geist","Geist Fallback",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.5;letter-spacing:-.005em;-webkit-font-smoothing:antialiased}
.nav-outer a,.nav-outer button{font-family:inherit}
.nav-outer *,.nav-outer *::before,.nav-outer *::after{box-sizing:border-box}
.nav-outer .nav{height:80px;min-height:80px;padding:0;align-items:center}
.nav-outer .nav-links{display:flex;align-items:center;gap:4px;margin:0;padding:0}
.nav-outer .nav-item{padding:0;margin:0;gap:0;display:flex;align-items:center}
.nav-outer .brand{padding:0;margin:0;flex:0 0 auto} /* Brand darf im space-between-Flex nie schrumpfen */
.nav-outer .brand img{height:28px;width:auto;max-width:none} /* neutralisiert img{max-width:100%}-Reset aus base.css — Logo überall exakt 28px (§3a) */
/* SCHRIFTGRÖSSEN DES HEADERS — einzige Stelle.
   Bis 27.07.2026 standen dieselben Werte doppelt: oben in rem (.98rem/.92rem/1rem/…)
   und hier in px. Der px-Satz gewann (später, gleiche Spezifität), der rem-Satz war
   toter Code — wer dort drehte, sah nichts passieren. Die rem-Angaben sind entfernt;
   Größen stehen ausschließlich hier.

   Feste px sind hier Absicht: Navigationslabels skalieren nicht mit der Fensterbreite
   (Überschriften tun das, Menüpunkte nicht — sonst wirkt der Header wie eine Tablet-App).

   ⚠ Nicht vollständig zentral: 20 Seiten tragen noch eine Altlast `.nav-links a`
   {font-size:15px;letter-spacing:-.01em} aus der Zeit vor dem zentralen Header. Sie
   verliert gegen jede Regel hier (0,2,0 gegen 0,1,1), greift aber auf Elementen, die
   hier NICHT benannt sind — messbar bei .mega-head: dort erben Titel und Beschreibung
   -0.15px Laufweite statt -0.08px. Wird eine Zeile hier gelöscht, übernimmt dort
   sofort die Altlast.

   Skala: ganze Zahlen 12/13/14/15/16 — vorher standen hier 15,5/14,5/11,5 aus der
   Härtung. Halbe Pixel fallen auf normalen Bildschirmen nicht auf ein Gerätepixel
   (weicheres Schriftbild) und lassen sich aus keiner Skala ableiten. Gemessene
   Referenzen bei 1440px: Personio 16px, Stripe 14px, Linear 13px — 15px liegt drin.
   16px geht bei unseren sechs Menüpunkten nicht auf (CTA ragt dann 58px über).

   Der Trigger-Innenabstand ist 11px statt 14px: erst damit passt die Kopfzeile in
   die 1200er-Spalte. Vorher ragte der CTA-Block 43px darüber hinaus, war also nicht
   auf Kante mit dem Inhaltsraster darunter — bei 1024px fiel er ganz aus dem Bild. */
.nav-outer .nav-trigger{font-size:15px;font-weight:500;letter-spacing:-.005em;padding:10px 11px;gap:6px;margin:0}
.nav-outer .lang-toggle{font-size:14px;font-weight:500;letter-spacing:-.005em}
.nav-outer .btn{font-size:14px}   /* deckt auch Header-Buttons außerhalb von .nav-cta ab */
.nav-outer .nav-cta .btn{font-size:14px;font-weight:600;letter-spacing:-.005em;padding:10px 18px;line-height:1.4;margin:0}
.nav-outer .mega-title{font-size:16px}
.nav-outer .mega-desc{font-size:13px}
.nav-outer .mega-link{font-size:14px;letter-spacing:-.005em}
.nav-outer .mega-label{font-family:"Geist Mono",ui-monospace,monospace;font-size:12px}
footer.pactos-footer{font-family:"Geist","Geist Fallback",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;letter-spacing:normal}
footer.pactos-footer a,footer.pactos-footer button{font-family:inherit}

/* ---- 5. Header-Varianten (DESIGN.md §3a, Entscheidung 21.07.2026) ----
   A = Hintergrund hinter dem Header NICHT weiß (grün/farbig/Foto): transparent.
   B = weißer/heller Hintergrund: solides Pactos-Grün.
   Zuordnung als Klasse auf <body>; beim Scrollen sehen beide gleich aus. */
body.header-a{padding-top:0}
body.header-a .ihero,body.header-a header.hero,body.header-a .hero{padding-top:102px}
/* Fusspolster der Ressourcen-Heroes (29.08.2026).
   Patrick: „die heros auf den resource seiten sind ein bisschen zu kurz, die
   buttons ragen in den inhalt rein".

   ⚠ ZUERST FALSCH GEMESSEN, und der Fehler haette drei Seiten unnoetig hoeher
   gemacht: gemessen wurde der Kasten des letzten KINDES im .wrap, und auf
   blog-uebersicht, faq und glossar-uebersicht ist das eine Huelle (.hero-body)
   mit eigenem Innenpolster — ihr Kasten endet auf der Herokante, ihr Inhalt
   nicht. Richtig ist die unterste sichtbare Kante: Blaetter und Bedienelemente,
   keine Huellen. Damit sieht es bei 1440 px so aus:
     0 px    akademie · community · roi-rechner · presse   ← Knopf auf der Naht
     10 px   kernmodule
     40-107  startseite-dark 40 · faq 56 · glossar-uebersicht 56
             blog-uebersicht 82 · referenzen 107
   Nur die vier mit 0 px haben das Problem, und dort ist es jedes Mal ein Knopf —
   genau das, was Patrick beschreibt. Eingeschaltet ist der Regler auf den drei
   Ressourcen-Seiten davon; presse traegt denselben Fehler, ist aber keine
   Ressourcen-Seite und wartet auf ein Ja.

   ⚠ STANDARD 0, DIE SEITE SCHALTET EIN. Andersherum haette diese Regel
   (0,2,2) die drei Seiten ueberschrieben, die schon ein eigenes Fusspolster
   fuehren: referenzen 80 px, startseite-dark 40, kernmodule 10 — ihre
   Seitenregeln liegen bei (0,1,1) und stehen ausserdem VOR components.css,
   verlieren also zweifach. Ein sinnvoller Standard waere hier ein stiller
   Eingriff in drei Seiten, um die es nicht ging.
   Drei Werte an roi-rechner gemessen und angesehen: 40 px zu knapp, 72 zu luftig,
   56 traegt — der Abstand ueber den Knoepfen ist 40 px, unten darf es etwas mehr
   sein, weil dort ein Abschnitt endet. 56 ist ausserdem der Wert, den faq und
   glossar-uebersicht von sich aus schon fuehren; die drei Seiten reihen sich
   damit ein, statt eine vierte Zahl einzufuehren. Sie setzen ihn als
   clamp(36px,4vw,56px), damit er auf schmalen Fenstern nicht klotzt. */
body.header-a header.hero{padding-bottom:var(--hero-polster,0)}
body.header-b{padding-top:82px}
body.header-b .nav-outer{background:var(--grad-shell);-webkit-backdrop-filter:none;backdrop-filter:none;border-bottom:1px solid rgba(255,255,255,.08)}
body.header-b .nav-outer.scrolled{background:var(--grad-shell-scroll);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom-color:rgba(255,255,255,.12)}

/* ---- 6. Trust-Badges in Graustufen (DESIGN.md §4) ---- */
.pactos-footer .pf-cert img{filter:grayscale(1)}

/* ---- 7. Buttons eckig (DESIGN.md §3b, Referenz buttons.html) ----
   Form zentral für ALLE Buttons; Farben behalten die bestehenden Klassen
   (btn-primary/btn-white/btn-ghost), neue §3b-Klassen zusätzlich verfügbar. */
.btn{border-radius:12px}
.btn:hover{box-shadow:0 12px 30px -10px rgba(0,0,0,.45)}
.btn svg{width:18px;height:18px;flex:none;stroke-width:1.4} /* Pfeil: dünne Strichstärke (DESIGN.md §3b) */
.btn-tech{background:#52EFBA;color:#000}
.btn-tech:hover{box-shadow:0 12px 30px -10px rgba(0,0,0,.5),inset 0 0 0 999px rgba(0,0,0,.07)}
.btn-dark{background:#0A4E47;color:#fff}
.btn-dark:hover{box-shadow:0 12px 30px -10px rgba(0,0,0,.55),inset 0 0 0 999px rgba(0,0,0,.14)}
.btn-ghost-grey{background:transparent;border:1.5px solid #666666;color:#000}
.btn-ghost-grey:hover{border-color:#0A4E47;color:#0A4E47;background:rgba(10,78,71,.06);box-shadow:0 12px 30px -10px rgba(0,0,0,.22)}
.btn-block{width:100%}
.pactos-footer .pf-call-btn,.pactos-footer .pf-li-btn{border-radius:12px}
.nav-outer .nav-cta .btn,.nav-outer .nav-cta a.btn-primary{border-radius:12px}

/* ---- 8. Footer-Fläche (DESIGN.md §4): Verlauf, kompakte KI-Kacheln ---- */
footer.pactos-footer{background:var(--grad-shell);position:relative;color:rgba(255,255,255,.72)}
/* MINT-SCHIMMER AUF PROBE ENTFERNT (Patrick, 27.07.2026).
   Hier lag ein ::after mit einem Mint-Radial oben rechts, das den Footer dort auf
   #146557 aufhellte — deutlich heller als das Grün des Verlaufs (#0A4E47). Der Header
   hatte nie ein Gegenstück, Kopf und Fuß sahen dadurch unterschiedlich aus.
   Exakter voriger Wert, falls er zurückkommt:
     footer.pactos-footer::after{content:"";position:absolute;inset:0;
       background:radial-gradient(55% 60% at 88% 6%, rgba(82,239,186,.14), transparent 60%);
       pointer-events:none}
   Beim Zurücknehmen bitte `var(--glow-mint)` benutzen statt neu zu tippen — das Token
   existiert (tokens.css) und wurde bislang von NIEMANDEM verwendet, während der Footer
   seinen eigenen, leicht anderen Radial hart notiert hatte. Achtung: die Geometrie des
   Tokens weicht ab (130% 120% at 84% 12% statt 55% 60% at 88% 6%), ein Zurücknehmen über
   das Token ist also nicht pixelgleich zum alten Zustand. */
footer.pactos-footer > *{position:relative;z-index:1}   /* bleibt: hebt den Inhalt über eine etwaige ::after-Auflage */

/* FLIESSENDE KURVEN IM FOOTER (Probe, Patrick 28.07.2026)
   Nachbau der React-Vorlage „Background Paths" (framer-motion) ohne Abhängigkeit.
   Markup baut src/js/footer-paths.js, die Bewegung steht hier. Muster ist dasselbe,
   das kernmodule.html schon benutzt: stroke-dasharray + stroke-dashoffset.

   Regler: --pf-paths-intensity — 0 schaltet die Ebene aus, ohne Code zu entfernen
   (wie --pbg-intensity beim Hintergrund). Gütekriterium der Probe: dezenter bleiben
   als der am 27.07. entfernte Schimmer, dessen hellster Punkt #146557 war.

   Zwei Fallen, die hier gelöst sind:
   (1) overflow:hidden fehlte am Footer — ohne das ragen die Kurven heraus.
   (2) `footer.pactos-footer > *{z-index:1}` (0,1,1) würde die Ebene ÜBER den Inhalt
       heben; `.pactos-footer .pf-paths` ist (0,2,0) und schlägt das mit z-index:0. */
/* Startwert .26 ist GEMESSEN, nicht geschätzt: bei .55 lag der hellste zusammengesetzte
   Punkt bei #1b7462 — heller als der entfernte Schimmer (#146557) — und der Kontrast der
   Footer-Schrift rgba(255,255,255,.72) fiel im schlimmsten Fall von 9,6:1 auf 5,6:1.
   Rechnung: über #0A4E47 braucht der Grünkanal 78+161a; für #146557 (G=101) wäre a=.143.
   Mit .26 liegt die stärkste Linie bei a≈.11, also darunter. */
footer.pactos-footer{overflow:hidden;--pf-paths-intensity:.26}
.pactos-footer .pf-paths{position:absolute;inset:0;z-index:0;pointer-events:none}
.pactos-footer .pf-paths svg{display:block;width:100%;height:100%}
.pactos-footer .pf-paths path{
  fill:none;stroke:var(--tech);stroke-linecap:round;
  vector-effect:non-scaling-stroke;                    /* preserveAspectRatio:none verzerrt sonst die Strichbreite */
  stroke-opacity:calc(var(--o) * var(--pf-paths-intensity));
  stroke-dasharray:.35 .65;                            /* pathLength=1, also Anteile statt Pixel */
  animation:pf-paths-flow 26s linear infinite;
  animation-delay:calc(var(--i) * -1.1s);              /* negativ: läuft schon, kein Anlauf-Wellenmuster */
}
@keyframes pf-paths-flow{to{stroke-dashoffset:-1}}
@media (prefers-reduced-motion:reduce){.pactos-footer .pf-paths path{animation:none}}

.pactos-footer .pf-ai-section{padding:24px 0 28px}
.pactos-footer .pf-ai-label{font-size:13px}
.pactos-footer .pf-ai-section .pf-ai-tile{width:40px;height:40px;border-radius:10px}
.pactos-footer .pf-ai-section .pf-ai-tile svg{width:22px;height:22px}

/* ---- 9. Hintergrund-Ebenen-System (Entscheidung Patrick, 22.07.2026) ----
   Ebene 1 · Grundfarbe: --page-bg — EIN zentraler Schalter für die Fläche
             aller Seiten (Test: Weiß; Alternative: #F4F4F4 Pactos Gray).
   Ebene 2 · Hervorhebung (punktuell, lean): dunkelgrüne Verläufe
             (linear-gradient 162deg, green-800 -> green-900) und Grün-Grau
             (.sec.tint / --surface-2) — bleiben in den Sektionen definiert.
   Heroes:   ausgenommen (eigene Flächen inkl. Fotos).
   Bewusst dunkle Seiten (faq.html, .sg auf green-900) definieren ihre
   Fläche selbst und hängen NICHT an diesem Schalter. */
:root{--page-bg:#ffffff}
body{background:var(--page-bg)}

/* ---- Hintergrund-Grundsatz (Patrick, 22.07.2026) ----------------------
   „transparent = Block zeigt Animation · Farbe = solides Element."
   Ebene 1  Paper: body = --page-bg (weiß), die Leinwand.
   Ebene 1b Animation: .pbg-layer fix dahinter (z-index:-1), sichtbar überall
            wo darüberliegende Flächen transparent sind.
   Rollen-Split über Tokens (kollisionssicher; Dunkelgrün nutzt --green-*):
     --surface-2  = Sektionsbänder      -> TRANSPARENT (Animation scheint durch)
     --paper      = Seiten-/Hero-Basis  -> TRANSPARENT (body bleibt via --page-bg weiß)
     --surface    = Inhalts-Elemente    -> WEISS solide (Karten, Inputs, Mockup, Video)
   Dunkelgrün (--green-*, Verläufe) + Foto-Heroes = bewusste Hervorhebung, unberührt.
   components.css lädt nach dem Seiten-CSS -> dieser :root-Override gewinnt global. */
:root{ --surface-2:transparent; --paper:transparent; --surface:#ffffff; }
/* Guard: Formularfelder sind Inhalts-Elemente -> immer solide (manche Seiten
   setzen input-bg auf --paper, das jetzt transparent ist). */
input:not([type=checkbox]):not([type=radio]),select,textarea{background:var(--surface)}
/* Band-Klassen, die auf Gen-C fälschlich var(--surface)=weiß statt des Band-Tokens
   nutzen -> auf die Band-Rolle (transparent) heben, damit die Animation durchscheint.
   Per grep über alle 44 Seiten verifiziert: diese drei Klassen sind AUSNAHMSLOS
   var(--surface)/var(--surface-2), NIE dunkelgrün/Verlauf -> keine Hervorhebung
   kann brechen. .band/.roiband/.gov-strip bewusst NICHT (können dunkelgrün sein). */
.sec.tint, .sec.white, .kpis { background: transparent; }

/* ---- Eyebrow zentral vereinheitlichen (DESIGN.md §2, Referenz: über-uns) ----
   NUR die Klasse .eyebrow (konsistent = der Sektions-Kicker). Nur STRUKTUR
   (Geist Mono, ~.74rem, fw500, .14em, uppercase, Linie davor, Pill-Reste undo);
   FARBE bleibt Sache der Seite (grün auf hell / mint auf dunkel), sonst bräche
   Mint-auf-dunkel. Die Kicker-Klassen .kicker/.kick/.vis-kick sind bewusst NICHT
   erfasst — sie sind überladen (mal Hero-Kicker, mal Karten-Label, mal Trust-
   Label) und werden, falls nötig, pro Seite gezielt behandelt. */
.eyebrow {
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: none;      /* undo Pill-Badge (Produktseiten) */
  padding: 0;
  border: 0;
  border-radius: 0;
}
.eyebrow::before {
  content: "";
  width: 26px; height: 1px;
  background: currentColor;
  opacity: .6;
  flex: none;
  /* ⚠ HIER STAND `margin-top: calc(0.5lh - 0.5px)` mit `align-items:flex-start`
     (Strich an der ERSTEN Zeile). Das war fuer einzeilige Eyebrows identisch
     zu `align-items:center`, bei einem Umbruch aber falsch: der Strich hing
     oben an Zeile 1 statt neben dem Block — auf compliance sah
     „Ist-Zustand bei Personaldienstleistern" dadurch schief aus (Karoline,
     10.09.2026: „der Mono Strich … ist nicht zentriert").
     Gemessen: von 60 Eyebrows auf neun Seiten brechen bei 375px genau drei um,
     und alle drei stehen in einem zentrierten Kopf — dort ist die Mitte des
     ganzen Blocks die richtige Hoehe. Deshalb jetzt `align-items:center` oben
     und hier kein Versatz mehr. */
}

/* ---- Überschriften kanonisch (DESIGN.md §2: Geist 550, Tracking 0) ----
   H1 wurde bereits per Strippen der Seiten-Regeln aktiviert. H2/H3/H4 tragen
   auf fast allen Seiten noch negatives Kerning (-.02/-.03em) + weight 600 aus
   spezifischen Seiten-Selektoren (.sec-head h2 …). Da diese pro Seite variieren,
   wird hier zentral normalisiert — bewusst mit !important, weil ein generischer
   h2/h3-Selektor die spezifischeren Seiten-Regeln sonst nicht schlägt.
   Betrifft nur letter-spacing + font-weight (Größe/Farbe bleiben seitenseitig). */
h2, h3, h4 { letter-spacing: 0 !important; font-weight: var(--fw-head, 550) !important; }

/* ---- Echte Action-Buttons von Pill (999px) auf eckig 12px (DESIGN.md §3b) ----
   NUR diese spezifischen Klassen zentral. Tags/Badges/Chips sind seit der
   23.07.-Regel ebenfalls eckig (--r-sm 10px), Buttons/Filter/Inputs eckig
   (--r-md 12px) — diese Umstellung erfolgte bewusst seitenweise (Bestand am
   24.07. Seite fuer Seite migriert), NICHT zentral, weil die Klassennamen je
   Seiten-Generation Unterschiedliches bedeuten. Rund bleiben nur Avatare,
   Slider-Pfeile, Dots, Deko-Kreise und Icon-Ringe. */
.expand, .copybtn, .submit, .replay, .res-more button { border-radius: var(--r-md); }

/* ---- 5. Zustände & Fokus (DESIGN.md §4b — global, additiv) ----
   Nur Randfälle, die bisher fehlten. Ersetzt KEINE bestehende Hover-Logik. */
/* Tastatur-Fokus (Barrierefreiheit): grün auf hell, Mint auf dunkel.
   :focus-visible greift nur bei Tastatur-Bedienung, stört Maus-Nutzer nicht. */
:focus-visible { outline: 2px solid var(--green-600); outline-offset: 2px; border-radius: inherit; }
.header-a :focus-visible, .pactos-footer :focus-visible, .on-dark :focus-visible { outline-color: var(--tech); }
/* Disabled: nicht klickbar, sichtbar gedämpft */
[disabled], .is-disabled { opacity: .6; cursor: not-allowed; }
/* Aktiv/Pressed: minimal reagieren (nur transform, kein Layout — Detektor-konform) */
.btn:active { transform: translateY(1px); }
/* Text-Links im Fließtext: Unterstrich bei Hover UND Fokus (nicht Nav-/CTA-Links) */
.prose a:hover, .prose a:focus-visible, .rich-text a:hover, .rich-text a:focus-visible { text-decoration: underline; }

/* ---- 10. Bild-Standard (DESIGN.md §4 „Bild-Standard" + „CTA-Abschluss-Band") ----
   Jedes Bild zeigt auf jedem Bildschirm denselben Ausschnitt: fester
   Seitenverhältnis-Rahmen bzw. an die Breite gekoppelte Höhe + cover +
   Fokuspunkt. NIE feste Pixel-Höhe bei full-bleed cover. */
/* Inline-Bilder / Karten-Cover: <div class="img-frame"><img …></div>
   Seitenverhältnis per --ratio überschreibbar (Default 16:9),
   Fokuspunkt per --focus (Default center). */
.img-frame { aspect-ratio: var(--ratio, 16/9); overflow: hidden; border-radius: var(--r-lg, 18px); }
.img-frame > img { width: 100%; height: 100%; object-fit: cover; object-position: var(--focus, center); display: block; }
/* CTA-Foto-Band: <section class="cta-photo" style="--foto:url('/assets/xy.jpg');--foto-y:40%">
   Höhe an Breite gekoppelt -> konstanter Bildausschnitt UND konstante
   Textposition. Pfad root-relativ (/assets/…) — url() löst relativ zu
   dieser Datei (src/styles/) auf, `assets/…` würde fehlschlagen. */
.cta-photo {
  min-height: max(520px, 40vw);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; color: #fff;
  /* Langform statt Shorthand: die Seite setzt background-image INLINE
     (Overlay + url seitenrelativ) — url() in einer var() würde relativ zu
     DIESER Datei aufgelöst (src/styles/…, Chrome-Verhalten) und 404en.
     var(--foto,none) bleibt als Alternativ-Weg (dann root-relativ + HTTP). */
  background-color: var(--green-900, #08302B); /* Fallback-Fläche, falls Bild fehlt */
  background-image: linear-gradient(rgba(8,48,43,.5), rgba(8,48,43,.74)), var(--foto, none);
  background-position: center var(--foto-y, 50%);
  background-size: cover;
  background-repeat: no-repeat;
}

/* CTA-Abschluss-Band, Verlaufs-Fassung — Schwester von .cta-photo oben.
   ENTSCHEIDUNG Patrick 29.07.2026 nach Durchsicht von mockup-final-cta.html:
   Variante B (Verlauf statt Vollton), aber REGELKONFORM.

   Der Mockup hatte linear-gradient(162deg, --green-800, #08302B) — 162 Grad und
   hell -> dunkel. DESIGN.md §1 verlangt seit 27.07. (Antonio) 135 Grad, beginnend
   mit der DUNKLEREN Farbe. Die regelkonforme Fassung ist genau `--grad-dark`, also
   der Token, den DESIGN.md §4 fuers CTA-Band ohnehin vorschreibt und den vorher
   KEINE der 44 Seiten per var() referenziert hat.

   Ersetzt 83 seiteneigene Regeln auf 21 Seiten. Vorher gemessen: 23 Baender in
   15 verschiedenen Zustaenden, darunter zwei verschiedene Marken-Gruens
   (#0E7A5F = Token und #0E7C60 = abgedriftet) und sechs Hintergrund-Rezepte.

   Aufbau: <section class="sec"><div class="wrap"><div class="cta-box"> … </div></div></section>
   Das .wrap der SEITE bleibt bewusst stehen — dadurch haelt die Box die
   Inhaltsbreite ihrer Seite. Ein eigenes max-width hier wuerde die Box auf den
   14 Seiten mit .wrap{max-width:1400px} schmaler machen als den Inhalt darueber. */
.cta-box{
  position:relative; overflow:hidden; text-align:center; color:#fff;
  background:var(--grad-dark);
  border-radius:var(--r-xl);
  padding:76px 32px;
  box-shadow:var(--shadow-cta);
}
.cta-box::after{               /* Mint-Schimmer oben rechts (Variante B des Mockups) */
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(60% 120% at 85% 0, rgba(82,239,186,.26), transparent 58%);
}
.cta-box > *{position:relative}      /* Inhalt ueber den Schimmer */
.cta-box .eyebrow{color:var(--tech); justify-content:center}
.cta-box h2{font-weight:600; font-size:clamp(1.8rem,3.6vw,2.7rem); letter-spacing:-.03em;
  margin:0 0 12px; color:#fff; text-wrap:balance}
.cta-box h2 em{font-style:normal; color:var(--tech)}   /* aus karriere: mintfarbene Hervorhebung */
/* .9 statt der .8 aus dem Mockup — GEMESSEN, nicht geschmackssache:
   Am hellsten Punkt der Box (helles Verlaufsende #0A4E47 plus Mint-Schimmer .26 = #1D7865)
   ergibt .8 nur 4,05:1 und liegt damit unter der AA-Schwelle 4,5:1 fuer normalen Text.
   Mit .9 sind es 4,68:1. Der Schimmer bleibt bei .26, also das gewaehlte Aussehen.
   Zum Vergleich: der ALTE Zustand (Vollton #0E7A5F, p bei .85) lag bei 4,3:1 — das Problem
   ist also aelter als diese Komponente, wird hier aber mit erledigt.
   Die Ueberschrift ist reines Weiss und liegt bei 5,35:1. */
.cta-box p{color:rgba(255,255,255,.9); font-size:1.06rem; margin:0 auto 28px; max-width:52ch}
.cta-box .cta-row{display:flex; gap:12px; justify-content:center; flex-wrap:wrap}
/* ⚠ EIN LANGES KNOPFWORT SPRENGTE DIE BOX. `.btn` ist `white-space:nowrap`
   (base.css:43) und als Flex-Element so breit wie sein Inhalt: gemessen auf
   compliance.html war „Als Personaldienstleister anfragen" 315px breit, in der
   Box blieben bei 390px Fenster 298px — der Knopf lief 17px unter das
   `overflow:hidden` der Box und war rechts abgeschnitten. `flex-wrap` half
   nicht, es umbricht die REIHE, nicht den Knopf.
   Unter 520px darf die Beschriftung deshalb umbrechen und der Knopf nicht
   breiter werden als die Box. Kein anderer CTA-Knopf im Baum ist lang genug,
   dass sich dadurch etwas aendert — geprueft, es sind 16 Sektionen.
   ⚠ Gilt fuer JEDEN `.btn` in der Box, nicht nur fuer `.cta-row .btn`:
   `abschluss`, `kein-konto` und die Initiativbewerbungs-Box auf `karriere`
   setzen den Knopf ohne `.cta-row`-Wrapper direkt in die `.cta-box`. Dort war
   „Initiativbewerbung senden" mit `white-space:nowrap` 276px breit, der
   Innenraum bei 375px Fenster nur 251px — der Knopf lief 25px rechts ueber und
   wurde von `text-align:center` linksbuendig gedrueckt (nicht zentrierbar,
   weil breiter als der Container). Darum hier ohne `.cta-row` im Selektor. */
/* ⚠ HIER STAND `white-space:nowrap` (bis 10.09.2026). Das half dem kurzen
   „Initiativbewerbung senden", scheiterte aber an langen Labels: auf pax-ai ist
   „Datensicherheit und KI-Governance" einzeilig 304px breit, der Innenraum bei
   375px Fenster nur 251px — der Ghost-Knopf lief 53px ueber die Karte hinaus
   und stand versetzt unter dem Hauptknopf (Karoline: „Auch hier passen die
   Buttons noch nicht").
   Statt am Umbruch zu drehen jetzt dieselbe Geste wie bei den Hero-Chips:
   untereinander, volle Breite, dadurch alle gleich lang und nichts kann
   ueberlaufen. Gemessen bei 375px: beide Knoepfe 251px statt 232 und 304. */
@media (max-width:640px){
  .cta-box .cta-row{flex-direction:column; align-items:stretch}
  .cta-box .btn{display:flex; width:100%; justify-content:center;
    white-space:normal; text-align:center; padding-inline:16px}
  /* Nur ohne `.cta-row`-Wrapper — dort macht dessen `gap:12px` den Abstand.
     Knopf direkt in der Box haben `abschluss`, `kein-konto`, die
     Initiativbewerbungs-Box auf karriere und der Abschluss auf pax-ai. */
  .cta-box > .btn + .btn{margin-top:10px}
}
/* Mobil: 76px Innenabstand sind auf kleinen Schirmen zu viel. Ersetzt die
   `.final{padding:32px 22px}`-Regeln, die drei Seiten dafuer einzeln hatten. */
@media (max-width:640px){.cta-box{padding:40px 22px; border-radius:var(--r-lg)}}

/* ---- 11. Geometrie zentral (DESIGN.md §2a, Entscheidung Patrick 27.07.2026) ----
   „Rundung, Schatten und Randstaerke kommen zentral; die Seite setzt nur Groesse
   und Layout." Diese Datei laedt als LETZTE (pactos:shared am Body-Ende) und
   gewinnt daher gegen die Seiten-<style>-Bloecke bei gleicher Spezifitaet.
   ⚠ Verbund-Selektoren der Seiten (.cov .tag = 0,0,2,0) schlagen diese
   Ein-Klassen-Regeln trotzdem — solche Stellen werden in den Seiten entkernt.
   Bewusst NICHT hier: Flaechen-/Textfarben (bleiben Sache der Seite), sowie
   border-radius:50% fuer Kreis-Deko/Avatare und 1–4px an Haarlinien/Chart-Balken.
   Klassen mit mehrdeutiger Bedeutung (.cat, .ic, .tab, .box) sind absichtlich
   ausgespart — dort heisst derselbe Name auf verschiedenen Seiten Verschiedenes. */

/* Karte (§4 Basis-Karte) und ihre Varianten — Radius 18px, Ruheschatten, Hover.
   Namens-Wellen 1–5 (27.07.2026): die alten Namen .mcard/.rcard/.evcard/.ts-card/
   .cs-card/.ecard/.dlcard/.pmcard/.medcard/.ttile/.job/.case existieren nicht mehr.
   ⚠ Diese Liste MUSS mitwachsen, wenn eine Karten-Variante umbenannt wird: in
   Welle 3 wurden Seiten-Radien geloescht, wo diese Regel greift — faellt der Name
   hier heraus, verlieren genau diese Karten ihren Radius (am 27.07. real passiert). */
.card, .card-post, .card-case, .card-feature, .card-resource, .card-event,
.card-portrait, .card-press, .card-clipping, .card-job, .sidecard, .mock-card {
  border-radius: var(--r-lg, 18px); box-shadow: var(--shadow-s);
  transition: box-shadow .2s var(--ease), transform .2s var(--ease);
}
/* Flip-Cards: NUR Radius, kein Schatten — so zeigt es styleguide.html (.flip-face
   mit var(--r-lg), .flip selbst hat gar keinen Radius, nur perspective). */
.flip-face { border-radius: var(--r-lg, 18px); }
@media (hover: hover) {
  .card:hover, .card-post:hover, .card-case:hover, .card-feature:hover,
  .card-resource:hover, .card-event:hover, .card-portrait:hover, .card-press:hover,
  .card-clipping:hover, .card-job:hover, .sidecard:hover, .mock-card:hover {
    box-shadow: var(--shadow-m); transform: translateY(-2px);
  }
}

/* Grosse Boxen (§2a --r-xl): Metrik-Karte, Download-Panel, Hinweisbox, Feature-Box.
   Flip-Cards stehen bewusst NICHT hier: styleguide.html zeigt sie mit 18px, und eine
   Flip-Card ist eine Karte (§2a) — der Styleguide ist die Referenz (27.07.2026). */
.card-metric, .card-download, .notice, .featured {
  border-radius: var(--r-xl, 24px);
}

/* Tags · Badges · Chips — eckig 10px (§4, Entscheidung 23.07.2026: NICHT rund) */
.tag, .badge, .chip { border-radius: var(--r-sm, 10px); }

/* Icon-/Diagramm-Kacheln (§4 „Icon-Kachel … --r-sm") */
.icon-tile, .dia-tile { border-radius: var(--r-sm, 10px); }

/* Inputs (§2a: Buttons und Inputs 12px) — Checkbox/Radio behalten ihre Form */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
textarea, select { border-radius: var(--r-md, 12px); }

/* ---- 12. Schrift + Zustände je Komponente (Antonio-Feedback, 27.07.2026) ----
   Diese vier Regeln standen bisher NUR im lokalen CSS von styleguide.html — die
   44 Seiten hatten sie nicht. Damit sahen Tabellenkopf, Datum und Avatar im
   Schaufenster anders aus als in der echten Seite. */

/* Tags · Badges · Chips: Geist Mono (§4). Bewusst OHNE text-transform — die
   Seiten-Badges sind Satztexte („Alles im gruenen Bereich"), Versalien wuerden
   sie zerreissen. Antonio fragte nach der Schrift, nicht nach Grossschreibung. */
.tag, .badge, .chip { font-family: var(--mono); }

/* Datum und Karten-Meta: Geist Mono (Antonio: „Welche Schriftart ist das Datum?") */
.card-meta, .card-date { font-family: var(--mono); }

/* Tabellenkopf: Mono + Mint-Tint-Flaeche + gedaempft (§4 „Kopfzeile in Mint-Tint,
   Mono, uppercase"). uppercase bleibt aus, weil die Seiten-Tabellen lange deutsche
   Kopfzeilen haben („Pruefschritt (manuell, je Zeitarbeitskraft/Jahr)"). */
.tbl thead th, table.tbl th {
  font-family: var(--mono); letter-spacing: .06em;
  color: var(--muted); background: var(--tech-tint);
}

/* Avatar: Kreis mit sichtbarer Flaeche (Antonio: „Kreis um AZ?" — im Artifact war
   nur der Text zu sehen, weil dort die Tokens nicht laden). BEWUSST OHNE Rahmen:
   Seiten mit eigenem Verlauf-Avatar (.card-case .who .av) gewinnen per Spezifitaet
   nur die Flaeche — ein zentraler Rahmen wuerde dort ungefragt einen Ring
   dazumalen, ohne die Erkennbarkeit zu verbessern. Die Tint-Flaeche genuegt. */
.av {
  border-radius: var(--r-full, 999px); background: var(--tech-tint);
  display: grid; place-items: center; color: var(--green-700); font-weight: 600;
}

/* btn-dark: expliziter Farbwechsel beim Hover (Antonio: „beim Drueberhovern waere
   noch ne leichte Farbaenderung cool"). Die uebrigen Varianten behalten die
   Inset-Abdunklung aus §7 — Entscheidung vom 24.07. */
.btn-dark:hover { background: var(--green-900); }


/* Nur fuer Screenreader sichtbar. Kam ueber Karos Ueber-uns-Seite ins Projekt und
   gehoert zentral, weil es eine allgemeine Hilfsklasse ist. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---- 13. Zitat: Anfuehrungszeichen (DESIGN.md §4, Entscheidung Patrick 30.07.2026) ----
   Die Zeichen nehmen die Farbe des Zitattexts an: weiss auf dunkel, dunkel auf hell.
   `inherit` statt zweier Regeln — die Zeichen sind literale Zeichen in einem <span>
   INNERHALB des Textelements (blockquote / p.qtext / .quote-pull), das die richtige
   Farbe schon traegt. Damit stimmen auch kuenftige Varianten automatisch.

   VORHER: --tech (Mint) unabhaengig vom Untergrund, in 22 seitenlokalen Deklarationen
   auf 18 Seiten. Auf drei hellen Stellen war das unsichtbar (ueber-uns Gruenderzitat,
   Styleguide Zitat hell + Typo-Demo) und widersprach DESIGN.md §1: „Tech-Gruen NIE als
   Textfarbe auf Weiss (Kontrast ~1.3, unlesbar)". Vier Seiten waren still auf
   --green-600 ausgewichen. Das Zitat war die einzige Komponente in DESIGN.md ohne
   Hell/Dunkel-Split — dieser Abschnitt loest den Widerspruch auf, statt ihn zu verschieben.

   ⚠ NIE auf blankes `.q` erweitern: `.quick .q` ist ein Chip mit Rahmen und Polsterung
   (branche-logistik, branche-pflege, prozess-rechnungspruefung, workforce) und hat mit
   Anfuehrungszeichen nichts zu tun. Die Selektoren bleiben auf Zitat-Kontexte gescopet. */
blockquote .mark, blockquote .q,
.quote p .mark,
.quote-pull .mark, .quote-pull .qbig,
.quote-text .mark,
.qtext .qbig,
.trustband p.q .mark,
.founders .tm .q,
.ty-qmark { color: inherit }

/* ---- 14. Hero: Nav-Schutzband (Patrick, 31.07.2026) ----------------------
   Header-Variante A legt die transparente Nav mit WEISSER Schrift und weissem
   Logo ueber den Hero. Das setzt voraus, dass die Bildoberkante dort dunkel
   genug ist. Ein Foto allein genuegt dafuer NICHT.

   Anlass: branche-pflege hat einen WAAGERECHTEN Scrim (.34 links -> .88
   rechts), damit die Textspalte rechts traegt. Damit lag der schwaechste
   Punkt der Flaeche genau unter dem wichtigsten Element.

   ⚠ MASSGEBEND IST DER MINT-ANTEIL DES LOGOS, nicht das Weiss. Das Lockup
   ist #fff PLUS #52EFBA, und Mint ist der schwache Teil. Ein erster Anlauf
   mit .36/190px brachte Weiss auf 3,64:1 und sah damit bestanden aus — Mint
   lag aber bei 2,50:1 und das Logo blieb sichtbar schlecht. Gemessen bei
   1440px (schlechtester Fall: das Logo sitzt bei fixen 32px, der waagerechte
   Scrim waechst mit X/W und ist dort am schwaechsten):

     Logo weiss   2,35:1 ohne Band  ->  8,19:1 mit .80/360
     Logo MINT    1,72:1 ohne Band  ->  5,62:1 mit .80/360
     Nav-Woerter  3,74:1            -> 10,70:1
     Login/CTA   10-12:1            -> unveraendert

   Referenz, wie weit das vom Normalfall weg ist: auf dem soliden Header
   (--grad-shell) hat Weiss 17,04:1 und Mint 11,70:1.

   WARUM EIN LANGER AUSLAUF (360px) und keine Leiste: mit voller Deckung ueber
   die Nav-Hoehe und kurzem Abfall entsteht eine sichtbare Kante — es liest
   als Balken im Bild, nicht als Teil davon. Erst ein Auslauf ueber ~360px
   wirkt wie eine Vignette. Die Personen im Vordergrund kostet das messbar
   nichts: Zone y 320-420 liegt bei Y=135,0 gegen 136,7 ohne jedes Band.

   branche-logistik hatte das Problem nie: dort ist der Scrim SENKRECHT mit
   .66 oben. Dieses Band stellt denselben Schutz her, ohne den waagerechten
   Verlauf aufzugeben.

   VERWORFEN, mit Messwert: eine dritte Header-Variante mit dunkler Schrift,
   die beim Scrollen zurueckschaltet. Rechts ist der Scrim .88 — dunkle
   Schrift haette dort 1,62:1 statt der 10,05:1, die Weiss liefert. Es haette
   die linke Haelfte reparieren und die rechte zerstoeren; dazu ein zweites
   Logo im DOM auf allen 44 Seiten und ein JS-Tausch beim Scrollen.

   REGLER --hero-navschutz, Standard 0 = aus (wie --pf-paths-intensity und
   --pbg-intensity: abschaltbar ohne Code zu entfernen). Bei 0 ist der
   Verlauf rgba(8,48,43,0), also vollstaendig transparent — die anderen 43
   Seiten sehen davon nichts.

   z-index 1: auf branche-pflege ist der Stapel bg 0 · scrim 1 · vg 2 ·
   wrap 3, das Band liegt damit ueber dem Foto und unter Personen und Text.
   Bei Heroes mit dem Foto als Hintergrund von .ihero selbst (.wrap z-index 2)
   sitzt es ebenso ueber dem Foto und unter dem Inhalt. Eine Regel, beide
   Bauformen. ⚠ Vordergrund-Inhalt oberhalb 190px wuerde es NICHT abdecken.

   360px stehen fest und sind kein zweiter Regler: die Strecke muss lang
   genug sein, dass auch die staerkste sinnvolle Deckung (~.8) keine Kante
   zeigt. Ein zweiter Knopf wuerde nur einladen, sie zu kurz zu stellen.
   .ihero::before war repoweit frei, nur ::after ist belegt (Mint-Glow). */
.ihero::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:linear-gradient(180deg,
    rgba(8,48,43,var(--hero-navschutz,0)) 0, transparent 360px);
}

/* ---- 15. Header unter 1281px: Burger + Panel (31.07.2026) -----------------
   ANLASS: Der Header hatte gar keine Breiten-Logik. Die Navigation braucht fest
   1143px; bei 390px endete die CTA-Gruppe folglich bei x=1167, also 777px
   ausserhalb des Bildschirms. Weil base.css `overflow-x:clip` setzt, entstand
   nicht einmal eine Scrollleiste — „Login" und „Gespraech vereinbaren" waren auf
   dem Handy schlicht unerreichbar.

   BREAKPOINT 1280px. Die Desktop-Nav passt rechnerisch bis 1191px (1143 + 2x24
   Rand), aber zwischen 1200 und 1280 bleiben nur 9 bis 89px Luecke zwischen
   Menue und CTA — technisch passend, optisch gequetscht. 1280 ist ausserdem der
   bereits bestehende Rand-Breakpoint, es kommt also keine neue Zahl dazu.

   KEIN ZWEITES MENUE IM DOM. Die Mega-Panels tragen den vollstaendigen Inhalt
   bereits. Hier werden sie per CSS zu Akkordeons: `position:static`, eine
   Spalte, transparenter Grund. Eine Zweitfassung waere doppelte Pflege und
   liefe bei der ersten Menueaenderung auseinander.

   UMSORTIERUNG OHNE DOM-UMBAU: `.nav` bekommt flex-wrap, die Bloecke bekommen
   `order`. Zeile 1 = Logo + Burger, darunter Menue und CTA-Gruppe als volle
   Zeilen. So wandert die CTA-Gruppe ins Panel, ohne sie zu duplizieren. Bei
   390px reichte es sonst nicht: Logo 110 + CTA ~180 + Burger 44 + Rand 48 =
   382 von 390px, ohne jeden Zwischenraum.

   AUSFALLSICHER: Versteckt wird nur unter `html.js`, gesetzt als erste Zeile in
   src/js/header.js. Faellt das Skript aus, bleibt das Menue sichtbar statt
   unerreichbar — sonst haetten wir den heutigen Fehler nur leiser gemacht. */

/* Burger existiert im Markup aller 44 Seiten, ist oberhalb des Breakpoints aber
   unsichtbar und nicht fokussierbar. */
.nav-outer .nav-burger{display:none}

@media (max-width:1280px){

  /* --- Leiste (Zeile 1): Logo links, Burger rechts --- */
  .nav-outer .nav{flex-wrap:wrap;height:auto;min-height:0;gap:0}
  .nav-outer .brand{order:1;height:80px;display:flex;align-items:center}
  .nav-outer .nav-burger{
    order:2;display:inline-flex;align-items:center;justify-content:center;
    margin-left:auto;width:44px;height:44px;   /* 44px = Mindest-Tippflaeche */
    background:transparent;border:0;padding:0;cursor:pointer;color:#fff}
  .nav-outer .nav-burger-icon{
    position:relative;display:block;width:22px;height:2px;
    background:#fff;border-radius:2px;transition:background .15s ease}
  .nav-outer .nav-burger-icon::before,
  .nav-outer .nav-burger-icon::after{
    content:"";position:absolute;left:0;width:22px;height:2px;
    background:#fff;border-radius:2px;transition:transform .2s ease}
  .nav-outer .nav-burger-icon::before{top:-7px}
  .nav-outer .nav-burger-icon::after{top:7px}
  .nav-outer.nav-offen .nav-burger-icon{background:transparent}
  .nav-outer.nav-offen .nav-burger-icon::before{transform:translateY(7px) rotate(45deg)}
  .nav-outer.nav-offen .nav-burger-icon::after{transform:translateY(-7px) rotate(-45deg)}

  /* --- Panel (Zeile 2 und 3) --- */
  .nav-outer .nav-links{order:3;flex-basis:100%;flex-direction:column;align-items:stretch;
    gap:0;padding:4px 0 0}
  .nav-outer .nav-cta{order:4;flex-basis:100%;flex-direction:column;align-items:stretch;
    gap:12px;margin-left:0;padding:20px 0 28px}

  /* Zugeklappt — nur wenn das Skript lief (siehe Kopf). (0,3,1) schlaegt die
     Grundregeln .nav-outer .nav-links (0,2,0) aus Abschnitt 4. */
  html.js .nav-outer .nav-links,
  html.js .nav-outer .nav-cta{display:none}
  html.js .nav-outer.nav-offen .nav-links,
  html.js .nav-outer.nav-offen .nav-cta{display:flex}

  /* Geoeffnet: Variante A ist oben transparent — ohne eigenen Grund staende das
     Menue unlesbar ueber dem Hero. (0,3,1) schlaegt .nav-outer.scrolled (0,2,0). */
  html.js .nav-outer.nav-offen{
    background:var(--grad-shell);-webkit-backdrop-filter:none;backdrop-filter:none;
    border-bottom-color:transparent;max-height:100dvh;overflow-y:auto}

  /* --- Menuezeilen --- */
  .nav-outer .nav-item{display:block;width:100%}
  .nav-outer .nav-trigger{
    display:flex;width:100%;justify-content:space-between;align-items:center;
    padding:15px 0;font-size:17px;border-radius:0;
    border-bottom:1px solid rgba(255,255,255,.12)}
  .nav-outer .nav-trigger .chev{width:18px;height:18px}
  /* Hover-Rotation abschalten: auf Beruehrung bleibt :hover haengen und der
     Pfeil zeigte dann nach oben, obwohl nichts offen ist. */
  .nav-outer .nav-item:hover .nav-trigger .chev{transform:none}
  .nav-outer .nav-item.offen > .nav-trigger .chev{transform:rotate(180deg)}

  /* --- Mega wird Akkordeon ---
     `display:none` neutralisiert zugleich die :hover- und :focus-within-Regeln
     aus Abschnitt 1: die setzen nur opacity/visibility, display schlaegt beide. */
  .nav-outer .mega{position:static;width:100%;padding-top:0;display:none;
    opacity:1;visibility:visible;transform:none;pointer-events:auto}
  .nav-outer .mega.ra{left:auto;right:auto}
  .nav-outer .nav-item.offen > .mega{display:block}
  /* Gleiche Spezifitaet (0,3,0) wie die Breitenregeln in Abschnitt 1, aber
     spaeter in der Datei — deshalb gewinnen sie. Nicht nach oben verschieben. */
  .nav-outer .mega-4 .mega-inner,
  .nav-outer .mega-3 .mega-inner,
  .nav-outer .mega-kunden .mega-inner,
  .nav-outer .mega-1 .mega-inner{
    width:auto;grid-template-columns:1fr;grid-auto-rows:auto;gap:0;padding:6px 0 16px;
    background:transparent;border:0;border-radius:0;box-shadow:none}
  .nav-outer .mega-col{gap:0}
  /* ⚠ Kundenband aus. Der Burger-Grund ist dunkel, die Logos sind dunkelgruen;
     weisse Fassungen gibt es nicht. Titel, Beschreibung und die vier
     Erfolgsgeschichten bleiben, das Panel verliert nur die Dekoration.
     ⚠ JEDE ZEILE HIER IST MIT `.mega-kunden` QUALIFIZIERT. Die Grundregeln
     stehen weiter unten im Blatt (bei den .hat-bild-Regeln, wo sie hingehoeren);
     eine Media Query erhoeht die Spezifitaet nicht, also muss sie es tun. */
  .nav-outer .mega-kunden .kunden-band{display:none}
  .nav-outer .mega-kunden .mega-head.ist-kunden{padding:0;background:transparent;border:0;min-height:0}
  .nav-outer .mega-kunden .mega-head.ist-kunden::before{display:none}
  .nav-outer .mega-kunden .kunden-unter{padding:0}
  .nav-outer .mega-4 .mega-col{gap:0}

  /* Anwendungsfaelle mobil als zweistufiges Akkordeon: die Sektionen
     (Prozesse/Rollen/Industrien/Vertragsformen) stehen zusammengeklappt
     untereinander; Tippen auf das Label klappt die Seiten darunter auf. Nur
     Spalten MIT Label greifen (nur die Anwendungsfaelle haben welche). Das
     Umschalten der .offen-Klasse macht header.js. */
  /* Trenner nur ZWISCHEN den Sektionen — nicht ueber der ersten, sonst steht dort
     ein zweiter Strich direkt unter dem border-bottom des „Anwendungsfaelle"-Triggers. */
  .nav-outer .mega-4 .mega-col:has(> .mega-label):not(:first-child){border-top:1px solid rgba(255,255,255,.10)}
  .nav-outer .mega-4 .mega-col:has(> .mega-label) > .mega-label{
    display:flex;align-items:center;justify-content:space-between;
    cursor:pointer;margin:0;padding:15px 2px;font-size:15px;color:rgba(255,255,255,.82)}
  .nav-outer .mega-4 .mega-col:has(> .mega-label) > .mega-label::after{
    content:"";width:9px;height:9px;margin-left:12px;flex:none;
    border-right:2px solid currentColor;border-bottom:2px solid currentColor;
    transform:translateY(-2px) rotate(45deg);transition:transform .2s var(--ease-out)}
  .nav-outer .mega-4 .mega-col.offen:has(> .mega-label) > .mega-label{color:var(--tech)}
  .nav-outer .mega-4 .mega-col.offen:has(> .mega-label) > .mega-label::after{transform:translateY(2px) rotate(-135deg)}
  .nav-outer .mega-4 .mega-col:has(> .mega-label) .mega-link{display:none}
  .nav-outer .mega-4 .mega-col.offen .mega-link{display:block}
  .nav-outer .mega-4 .mega-col.offen .mega-link:last-child{padding-bottom:10px}
  /* „Fuer Personaldienstleister" (.mega-abgesetzt) trug den hellen --line-Rand vom
     Desktop; auf dem dunklen Panel wurde daraus eine helle, wegen border-radius
     abgerundete Linie. Auf die dezente Panel-Trennfarbe setzen, ohne Rundung. */
  .nav-outer .mega-4 .mega-col .mega-link.mega-abgesetzt{
    border-top-color:rgba(255,255,255,.12);border-radius:0;margin-top:6px;padding-top:14px}

  /* Farben: die Panel-Typografie ist fuer den weissen Grund gebaut (--ink,
     --muted). Auf dem dunkelgruenen Panel waere sie unsichtbar. */
  .nav-outer .mega-title,
  .nav-outer .mega-head .mega-title{color:#fff}
  /* margin-inline zurueck auf 0: der Versatz gehoert zur Mint-Flaeche auf dem
     Desktop, hier gibt es keine, und die Zeilen wuerden nur nach links rutschen. */
  .nav-outer .mega-link{color:rgba(255,255,255,.82);padding:11px 0;margin-inline:0;font-size:15px}
  /* Trennlinie im Panel: dunkler Grund, also die Panel-Haarlinie statt
     --line (die waere hier unsichtbar), und ohne den 10px-Versatz, weil
     `margin-inline` hier 0 ist. */
  .nav-outer .mega-link.mega-abgesetzt::before{left:0;right:0;background:rgba(255,255,255,.18)}
  .nav-outer .mega-desc{color:rgba(255,255,255,.60);margin:3px 0 10px}
  .nav-outer .mega-label{color:rgba(255,255,255,.60);margin:14px 0 4px}
  .nav-outer .mega-arrow,
  .nav-outer .mega-head:hover .mega-arrow{color:#fff}
  .nav-outer .mega-link:hover,
  .nav-outer .mega-title:hover,
  .nav-outer .mega-head:hover .mega-title{color:var(--tech)}
  .nav-outer .mega-head{
    min-height:0;padding:12px 14px;margin:6px 0 8px;
    border-color:rgba(255,255,255,.18);background:rgba(255,255,255,.06)}
  .nav-outer .mega-head:hover{
    border-color:rgba(255,255,255,.35);background:rgba(255,255,255,.10)}
  .nav-outer .mega-1 .mega-link:hover{color:var(--tech)}
  /* Die Mint-Flaeche ist fuer den weissen Grund gebaut. Im Mobil-Panel
     (dunkelgruen) bliebe sie eine helle Kachel unter hellem Text. */
  .nav-outer .mega-link:hover,
  .nav-outer .mega-1 .mega-link:hover,
  .nav-outer .nav-item:hover .nav-trigger,
  .nav-outer .nav-trigger:hover{background:none}
  .nav-outer .nav-item:hover .nav-trigger,
  .nav-outer .nav-trigger:hover{color:var(--tech)}
  .nav-outer .nav-item:hover .nav-trigger .chev,
  .nav-outer .nav-trigger:hover .chev{color:var(--tech)}

  /* --- CTA-Gruppe im Panel ---
     Nur der primaere Button geht ueber die volle Breite. „Login" bleibt ein
     Textlink wie auf dem Desktop und richtet sich an den Menuezeilen aus.
     Grund: .btn-ghost bekommt im Header nirgends einen sichtbaren Rahmen —
     `.nav-outer .btn{border:1px solid transparent}` in Abschnitt 3 steht
     spaeter als `.nav-outer .btn-ghost{border-color:rgba(255,255,255,.3)}` in
     Abschnitt 1 und gewinnt bei gleicher Spezifitaet (0,2,0). Auf dem Desktop
     liest sich das als gewollter Textlink neben dem Mint-Button; volle Breite
     plus Zentrierung liess ihn dagegen als rahmenlosen Block schweben. */
  .nav-outer .lang-toggle{align-self:flex-start;padding:10px 0}
  .nav-outer .nav-cta .btn-ghost{
    align-self:flex-start;width:auto;padding:10px 0;
    justify-content:flex-start;font-size:15px}
  .nav-outer .nav-cta .btn-primary{
    width:100%;justify-content:center;padding:14px 18px;font-size:15px}
}

/* Seite darf hinter dem offenen Panel nicht mitscrollen. */
html.nav-offen{overflow:hidden}

@media (prefers-reduced-motion:reduce){
  .nav-outer .nav-burger-icon,
  .nav-outer .nav-burger-icon::before,
  .nav-outer .nav-burger-icon::after{transition:none}
}

/* ---- 16. Modul-Sektionen und Sprungleiste (02.08.2026) --------------------
   ANLASS: Die fuenf Workforce-Unterseiten trugen je 186-244 Woerter, davon nur
   rund 140 Substanz — der Rest war viermal dasselbe Geruest. Sie liegen jetzt
   als Abschnitte auf workforce.html, die Menuepunkte springen auf Anker.
   Begruendung und die Bedingung fuer eine Rueckabwicklung: DESIGN.md §3a.

   WARUM DER NAMENSRAUM `.modul` NOETIG IST. Die Modulseiten und workforce.html
   benutzen dieselben Klassennamen mit ANDEREN Werten — gemessen kollidieren
   .kpi, .kpi-row, .kpi .v, .kpi .l, .band und .band p. Beispiel: .kpi ist auf
   workforce 36px und dreizeilig, im Modul-Template 44px und zweispaltig. Ohne
   Namensraum haetten sich die uebernommenen Abschnitte still umformatiert.
   `.modul .kpi` ist (0,2,0) und schlaegt das seiteneigene `.kpi` (0,1,0).

   NICHT hierher kopiert wurde, was workforce bereits WERTGLEICH definiert:
   .sec, .sec.tint, .sec-head, .sec-head h2, .eyebrow, .cards-3, .pain,
   .pain p. Nachgemessen, nicht vermutet. Nur .feat* und .kpi-src fehlten dort
   ganz, der Rest steht als Korrektur unten. */

/* Fehlten auf workforce vollstaendig */
.modul .feat-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:18px;max-width:1080px;margin:0 auto}
.modul .feat{display:flex;gap:18px;border:1px solid var(--line);border-radius:var(--r-lg);padding:24px;background:var(--surface)}
.modul .feat .ic{width:44px;height:44px;border-radius:var(--r-md);background:var(--brand-tint);color:var(--brand);display:grid;place-items:center;flex:0 0 auto}
.modul .feat .ic svg{width:22px;height:22px}
.modul .feat p{font-size:14.5px;line-height:1.55;color:var(--muted-readable);margin:0}
.modul .kpi-src{text-align:center;color:var(--muted);font-size:13px;margin:20px 0 0}

/* Karten-Ueberschriften sind beim Zusammenlegen von h3 auf h4 gerutscht:
   Seite h1 > Modul h2 > Problem/Features h3 > Karte h4. Die Optik bleibt. */
.modul .pain h4{font-size:18px;font-weight:600;letter-spacing:-.015em;margin:0 0 8px}
.modul .feat h4{font-size:16.5px;font-weight:600;letter-spacing:-.01em;margin:2px 0 6px}

/* Abweichend definiert — hier gewinnt die Modul-Fassung */
.modul .kpi-row{grid-template-columns:repeat(2,minmax(220px,320px));grid-template-rows:none;justify-content:center;gap:20px}
.modul .kpi{padding:30px}
.modul .kpi .v{font-size:44px}
.modul .kpi .l{font-size:15px;margin-top:10px}
.modul .band{background:var(--brand-tint);border:1px solid var(--brand-tint-2);border-radius:var(--r-lg);padding:44px 40px;text-align:center;max-width:900px;margin:0 auto}
.modul .band p{font-size:clamp(18px,2vw,23px);font-weight:500;letter-spacing:-.015em;line-height:1.4;color:var(--ink);margin:0;text-wrap:balance}

/* Jedes zweite Modul getoent, damit die lange Kette lesbar bleibt. nth-of-type
   zaehlt nur <section>, die Sprungleiste ist ein <nav> und stoert nicht. */
.modul:nth-of-type(2n){background:var(--surface-2)}

@media (max-width:900px){
  .modul .feat-grid,.modul .kpi-row{grid-template-columns:1fr}
}

/* --- Sprungleiste ---
   Klebt unter dem 80px-Header. Sie sitzt IN .modul-gruppe, damit sie genau so
   lange stehen bleibt, wie Module sichtbar sind — und damit sie auch da ist,
   wenn man aus dem Hauptmenue mitten in die Seite springt. */
.modul-gruppe{position:relative}
.sprungleiste{position:sticky;top:80px;z-index:var(--z-sticky);
  background:var(--surface);border-block:1px solid var(--line)}
.sprungleiste .wrap{display:flex;gap:4px;overflow-x:auto;scrollbar-width:none}
.sprungleiste .wrap::-webkit-scrollbar{display:none}
.sprungleiste a{flex:none;padding:15px 14px;font-size:14.5px;font-weight:600;
  color:var(--ink-soft);text-decoration:none;white-space:nowrap;
  border-bottom:2px solid transparent;transition:color .16s ease,border-color .16s ease}
.sprungleiste a:hover{color:var(--green-700)}
.sprungleiste a.is-active{color:var(--green-700);border-bottom-color:var(--green-700)}

/* ⚠ Ohne das landet jeder Anker UNTER Header und Sprungleiste: 80px Header
   plus 52px Leiste, plus etwas Luft. Bisher stand scroll-margin-top nur
   seitenlokal auf fuenf Artikelseiten, dort uneinheitlich 80 gegen 84px. */
.modul{scroll-margin-top:140px}

@media (max-width:1280px){
  /* Unter dem Burger-Breakpoint ist der Header weiterhin 80px hoch. */
  .sprungleiste{top:80px}
  .sprungleiste a{padding:13px 12px;font-size:14px}
  .modul{scroll-margin-top:132px}
}

/* ---- 17. Karussell: Bahn, Pfeile, Punkte (07.08.2026) ---------------------
   NAMING.md fuehrt `.sld-*` unter „Absichtlich unveraendert" mit dem Vermerk
   „existieren nur im Styleguide … Das ist 'Komponente fehlt', nicht 'Name falsch'".
   Diese Luecke schliesst der Abschnitt. Ausloeser: drei Seiten trugen inzwischen
   drei eigene Fassungen derselben Bedienelemente —

     ueber-uns   .sld-arrow 50px · .sld-dot          (Transform-Bahn, generisch)
     referenzen  .vbtn      44px · ohne Punkte       (Scroll-Snap-Schiene)
     karriere    .tarrow    44px · .tdot             (Buehne, tauscht Inhalt an Ort)

   Die drei MECHANIKEN bleiben verschieden und sollen es bleiben — eine Bahn ist
   keine Schiene ist keine Buehne. Zentralisiert wird nur, was dreimal gleich war:
   runder Icon-Knopf, 9px-Punkt, Leiste darunter.

   ⚠ Pfeilgroesse ueber --sld-pfeil, damit ueber-uns seine 50px behaelt, ohne
   einen eigenen Regelblock zu brauchen. Basis ist 44px (zwei von drei Seiten). */
.sld{max-width:none}
.sld-view{overflow:hidden}
.sld-track{display:flex;transition:transform .5s cubic-bezier(.22,1,.36,1)}
.sld-slide{flex:0 0 100%;min-width:0}
.sld-multi .sld-track{gap:16px}
.sld-multi .sld-slide{flex:0 0 calc((100% - 48px)/4)}
@media (max-width:860px){.sld-multi .sld-slide{flex:0 0 calc((100% - 16px)/2)}}

.sld-bar{display:flex;align-items:center;justify-content:space-between;margin-top:30px}
.sld-dots{display:flex;gap:10px;align-items:center}
.sld-dot{width:9px;height:9px;padding:0;border:none;border-radius:50%;background:var(--line);
  cursor:pointer;transition:transform .3s cubic-bezier(.22,1,.36,1),background .2s ease}
.sld-dot[aria-current="true"]{background:var(--tech);transform:scale(1.3)}
.sld-nav{display:flex;gap:12px}
.sld-arrow{width:var(--sld-pfeil,44px);height:var(--sld-pfeil,44px);border-radius:50%;
  border:1px solid var(--line);background:transparent;color:var(--ink);
  display:grid;place-items:center;cursor:pointer;
  transition:transform .25s cubic-bezier(.22,1,.36,1),border-color .2s ease,color .2s ease,background .2s ease}
.sld-arrow svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.4}
.sld-arrow:active{transform:scale(.93)}
.sld-arrow:disabled{opacity:.3;cursor:not-allowed}
@media (hover:hover){.sld-arrow:hover{border-color:var(--green-600);color:var(--green-700)}}
@media (prefers-reduced-motion:reduce){.sld-track{transition:none}}

/* Dunkler Untergrund (karriere: Buehne mit Foto). Der kraeftigere Strich ist
   kein Zufall, sondern noetig: 1,4px Weiss auf einem Foto verschwindet. */
.sld-dunkel .sld-dot{background:rgba(255,255,255,.28)}
/* ⚠ Muss NACH der Zeile darueber stehen: beide Selektoren haben Spezifitaet (0,2,0),
   also entscheidet die Reihenfolge. Fehlt sie, faerbt die Dunkelfassung auch den
   AKTIVEN Punkt weiss und der Zustand verschwindet — gemessen, nicht vermutet. */
.sld-dunkel .sld-dot[aria-current="true"]{background:var(--tech)}
.sld-dunkel .sld-arrow{border-color:rgba(255,255,255,.35);color:#fff}
.sld-dunkel .sld-arrow svg{width:18px;height:18px;stroke-width:2}
@media (hover:hover){
  .sld-dunkel .sld-arrow:hover{border-color:var(--tech);background:rgba(82,239,186,.1);color:#fff}
}

/* ---- 18. Case-Study-Karte (24.08.2026) ------------------------------------
   ANLASS: `sections.mjs compat` meldete fuer die Sektion `case-study` **4 %**
   Strukturaehnlichkeit bei zwei Vorkommen. Der Befund war aber nicht „zwei
   Designs", sondern ein FERTIGES BAUTEIL gegen einen PLATZHALTER:
     · roi-rechner.html trug 56 Zeilen Markup und einen eigenen <style>-Block im
       Rumpf — Foto, Kennzahlenstreifen, dunkles Zitatpanel, Portrait, Knopf.
     · prozess-rechnungspruefung.html trug 18 Zeilen mit `.card-case` und
       ausschliesslich [TODO]-Inhalten. Gemeinsam hatten die beiden nur `.wrap`.

   Deshalb steht das Bauteil jetzt HIER und nicht in einer Seite. Es erfuellt
   damit auch die Bedingung, unter der Zentralisierung ueberhaupt richtig ist:
   es wird von ZWEI Seiten benutzt. Ein Einzelstueck gehoert weiter in seine
   Seite (so wie `.schau-*` auf compliance.html).

   ⚠ DIE REGELN LAGEN IN EINEM <style> IM RUMPF, hier liegen sie im Kopf-Ladepfad.
   Das ist eine Kaskadenverschiebung: ein Rumpf-<style> gewinnt gegen diese Datei
   bei gleicher Spezifitaet. Geprueft: `.cstudy` und alle `.cs-*` kommen im
   ganzen Baum nur in diesen zwei Seiten vor, es gibt also nichts, was sie
   ueberschreiben koennte.
   ⚠ Die Namen bleiben, wie Karo sie gesetzt hat. Ein Umbenennen waere eine
   zweite Aenderung an derselben Stelle und wuerde ihren naechsten Push
   unnoetig kollidieren lassen. */
  .cstudy{padding:68px 0 8px}
  .cs-card{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:stretch}
  /* ⚠ NICHT var(--surface-2), obwohl tokens.css dort genau #EDF1EF fuehrt:
     components.css:476 setzt `--surface-2:transparent` und laedt SPAETER, die
     Flaeche waere also durchsichtig. --line-soft ist #EBEFEC, gegen #EDF1EF ein
     Unterschied von 2/2/3 pro Kanal und damit nicht sichtbar; ausserdem liegt
     das Foto darueber, die Flaeche scheint nur beim Laden durch. */
  .cs-media{display:flex;flex-direction:column;border-radius:22px;overflow:hidden;background:var(--line-soft);min-height:470px}
  .cs-photo{flex:1;min-height:0;position:relative}
/* Leerzustand: solange kein Foto da ist, steht dort ein [TODO]. Ohne eigene
   Regel klebte der Text oben links an der Kante und war angeschnitten
   (gemessen auf prozess-rechnungspruefung.html). */
.cs-platz{position:absolute;inset:0;display:grid;place-items:center;padding:24px;text-align:center;font-family:var(--mono);font-size:11px;line-height:1.5;color:var(--muted)}
  .cs-photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
  .cs-stats{background:var(--tech);padding:26px 30px;display:flex;flex-direction:row;align-items:center;gap:26px}
  .cs-stat{display:flex;flex-direction:column;gap:7px;flex:1}
  .cs-div{width:1px;align-self:stretch;min-height:48px;background:rgba(10,78,71,.28);flex:none}
  .cs-num{font-size:clamp(1.9rem,3vw,2.5rem);font-weight:700;letter-spacing:-.03em;line-height:1;color:var(--green-900);white-space:nowrap}
  .cs-lbl{font-size:.92rem;line-height:1.35;font-weight:500;color:var(--green-800)}
  .cs-panel{background:var(--grad-night);color:#fff;border-radius:22px;padding:clamp(30px,3.2vw,46px);display:flex;flex-direction:column}
  .cs-brand{font-family:var(--mono);font-weight:700;letter-spacing:.14em;font-size:.85rem;color:#fff;opacity:.9;margin-bottom:24px}
  /* ⚠ #EAF3EE ist kein Token und keines passt: der Ton ist ein sehr helles Mint,
     die Palette hat dafuer nur --tech-tint (#E7F8F0, gruener) oder --surface
     (reines Weiss). Auf dem dunklen Panel liefert rgba(255,255,255,.94) ueber
     --grad-night gerechnet #F0F1F0 — gegen #EAF3EE eine Differenz, die auf
     diesem Grund nicht auffaellt, und der Ton bleibt weich statt reinweiss.
     Die Unterzeile daneben arbeitet mit rgba(233,243,238,.68) im selben Sinn. */
  .cs-quote{margin:0;font-size:clamp(1.18rem,1.7vw,1.55rem);line-height:1.42;font-weight:500;letter-spacing:-.01em;color:rgba(255,255,255,.94);text-wrap:pretty}
  .cs-by{display:flex;align-items:center;gap:14px;margin-top:28px}
  .cs-av{width:50px;height:50px;border-radius:50%;object-fit:cover;flex:none}
  .cs-by b{display:block;font-size:1rem;font-weight:600}
  .cs-by span{display:block;font-size:.86rem;color:rgba(233,243,238,.68)}
  .cs-panel .btn{margin-top:28px;align-self:flex-start}
  @media(max-width:820px){.cs-card{grid-template-columns:1fr}.cs-media{min-height:0}.cs-photo{min-height:240px}}
/* ---- 19. Eckring: Kreis, der aus der oberen rechten Ecke schaut (25.08.2026) ----
   Kommt vom ROI-Rechner (.bcard::after) und war dort seitenlokal. Patrick:
   „Finde das als visuelles Element eigentlich echt cool um solche Kaesten nicht
   langweilig zu machen." Damit ist es ein BAUTEIL und gehoert hierher, nicht
   noch dreimal in ein Seiten-<style>.

   Bedienung: Klasse `eckring` an die Karte. Die Karte bekommt dadurch
   `position:relative` und `overflow:hidden` — beides ist noetig, sonst haengt
   der Kreis frei in der Sektion statt angeschnitten in der Ecke.

   ⚠ WER `::after` DER KARTE SCHON BENUTZT, KANN DAS HIER NICHT NEHMEN. Es gibt
   nur ein ::after je Element. Betroffen waeren z. B. Karten mit einem Schleier
   ueber einem Bild (.bt-karte auf workforce.html). Vor dem Anhaengen pruefen.

   ⚠ NICHT AN JEDE KARTE. Der Kreis lebt davon, dass die obere rechte Ecke leer
   ist und dass er selten vorkommt. Auf einer Karte mit Bild, Zahl oder Plakette
   in derselben Ecke wird er zum Fleck.

   Stellschrauben je Einsatzort:
     --ring-groesse  Durchmesser (Vorgabe 150px)
     --ring-farbe    Linie
     --ring-hof      weicher Ring darum
   `ist-warm` dreht ihn auf Bernstein — fuer Karten, deren eigenes Symbol schon
   bernsteinfarben ist (die Problem-Karten der Produktseiten). Ein Mint-Kreis
   auf einer Problemkarte behauptet das Gegenteil ihres Inhalts. */
.eckring { position: relative; overflow: hidden; }

/* ⚠ `.cta-box::before` HAENGT MIT DRIN (09.09.2026, Patrick: „die eckringe
   gerne fuer die ctas die kein bild cta sind sondern einer mit dunkelgruenem
   hintergrund"). Damit tragen ALLE dunkelgruenen Abschluss-Baender den Ring,
   ohne dass die Klasse an ueber 50 Stellen ins Markup muss — und neue CTAs
   bekommen ihn automatisch.
   ⚠ ::before UND NICHT ::after. `.cta-box::after` ist belegt: dort sitzt der
   Mint-Schimmer oben rechts (§10, Zeile 725). Haengt man .cta-box an
   `.eckring::after`, gewinnt die spaetere Regel und der Schimmer ist weg.
   Geometrie und Farben stehen deshalb hier EINMAL fuer beide Selektoren;
   der Versatz -.3067 unten gilt unveraendert.
   ⚠ Der BILD-CTA (`.cta.cta-photo`, Zeile 685) bleibt aussen vor. Er hat ein
   Foto in derselben Ecke, und genau davor warnt der Kopf dieses Abschnitts:
   auf einer Flaeche mit Bild wird der Ring zum Fleck. */
.eckring::after,
.cta-box::before {
  content: ""; position: absolute; pointer-events: none; z-index: 0;
  width: var(--ring-groesse, 150px); height: var(--ring-groesse, 150px);
  /* -.3067 statt runder -.31: das ist genau der Versatz der Vorlage
     (-46 von 150 px). Mit -.31 lag der Ring eine halbe Pixelbreite daneben,
     im Bildvergleich mit der alten Fassung als Kantenunterschied messbar. */
  top: calc(var(--ring-groesse, 150px) * -.3067);
  right: calc(var(--ring-groesse, 150px) * -.3067);
  border-radius: 50%;
  border: 1px solid var(--ring-farbe, color-mix(in srgb, var(--tech) 50%, transparent));
  box-shadow: 0 0 0 13px var(--ring-hof, color-mix(in srgb, var(--tech) 7%, transparent));
}
/* Inhalt ueber den Kreis heben. Ohne das liegt er bei Karten ohne eigene
   Stapelordnung ueber dem Text — beim ROI-Rechner traegt jedes Kind dafuer
   einzeln `position:relative`, das muss eine zentrale Fassung selbst loesen. */
.eckring > * { position: relative; z-index: 1; }

/* Ringgroesse fuer das CTA-Band. 150px sind fuer eine Karte gerechnet; das
   Band ist mit ~1150x300px ein Vielfaches davon, dort liest ein 150er Ring
   als Punkt in der Ecke. 260px halten das Verhaeltnis Ring zu Flaeche
   ungefaehr dort, wo es auf den Karten sitzt.
   `.cta-box > *` traegt bereits `position:relative` (Zeile 729), der Inhalt
   liegt also schon ueber dem Ring — eine z-index-Zeile braucht es hier nicht. */
.cta-box { --ring-groesse: 260px; }
.eckring.ist-warm {
  --ring-farbe: color-mix(in srgb, var(--amber-ink) 34%, transparent);
  --ring-hof: color-mix(in srgb, var(--amber-ink) 7%, transparent);
}
/* ⚠ NUR AUF PAX-AI-KARTEN. Violett ist laut DESIGN.md §4 fuer Pax AI
   reserviert; die Variante existiert, damit dort Ring und Symbol dieselbe
   Farbe sprechen, nicht als weiterer Akzent zum Streuen. */
.eckring.ist-ki {
  --ring-farbe: color-mix(in srgb, var(--ai) 40%, transparent);
  --ring-hof: color-mix(in srgb, var(--ai) 7%, transparent);
}
/* Fuer flachere Karten: 150px nimmt auf einer 230px hohen Karte fast die halbe
   Hoehe ein. Gemessen an den Prinzip-Karten auf pax-ai.html. */
.eckring.ist-klein { --ring-groesse: 118px; }

/* ---- 20. Fortschritts-Haken in der Alltag-Liste der Branchenseiten (25.08.2026) ----
   Uebernommen von der `so-funktionierts`-Sektion auf tender.html
   (`.howto-steps li .ck`): Kreis in Markengruen, weisses Haeckchen, Zustand
   ueber die Deckkraft. Vorher war es ein 8px-Punkt ohne Symbol.

   ⚠ Auf tender steht dort `background: var(--brand)`. Das Token ist
   SEITENEIGEN und existiert weder in tokens.css noch auf den Branchenseiten —
   blind kopiert ergibt weiss auf weiss, also ein unsichtbarer Haken. Gemessen
   im Bild gefunden, nicht im Code. Hier `--green-600`, wie die vorige
   Punktregel es schon nutzte.

   ⚠ ROT UND KREUZ, nicht gruen und Haken (Patrick, 25.08.2026). Die Liste
   nennt PROBLEME — „Freigabe fehlt", „Fristen laufen ab". Ein gruener Haken
   behauptet dort das Gegenteil von dem, was dasteht: er las sich wie
   „erledigt", wo „hier klemmt es" gemeint ist. Das Kreuz sagt dasselbe wie
   der Text.
   Gemessen: weisses Kreuz auf `--red` 4,85:1, Kreis auf weissem Grund
   ebenfalls 4,85:1 (Ziel 3,0 fuer grafische Elemente). Zwei Alternativen
   verworfen: `--amber-ink` (5,41:1, harmoniert mit dem Kartenicon, liest sich
   aber braeunlich statt eindeutig) und ein roter Ring ohne Flaeche (leichter,
   aber der Fortschritt lebt von der Deckkraft und braucht die Flaeche).

   ZENTRAL und nicht je Seite, weil die Regel auf sechs Branchenseiten
   wortgleich gilt (Fingerabdruck vor der Aenderung auf allen fuenf
   Bestandsseiten identisch). Inline haette sie auf jeder davon einen
   Regel-2-Fehler erzeugt; so schrumpft das Seiten-CSS stattdessen.

   Kein Skript: die angepinnte Buehne setzt schon `--p`, und `--nah` faellt
   daraus ab. Eine Zahl, zwei Verwendungen. Auf tender schaltet dagegen ein
   Skript `active`/`done` — dort gibt es kein `--p`.

   Groesse 20px statt 26px wie auf tender: die Liste steht auf den
   Branchenseiten waagerecht bei 14,5px Schrift, nicht senkrecht bei 17px. */
.hs-punkt { width: 20px; height: 20px; border-radius: 50%; background: var(--red);
  color: var(--surface); display: grid; place-items: center; flex: none; }
.hs-punkt svg { width: 12px; height: 12px; display: block; }

/* Ausserhalb des Pins (mobil, unter 1000px, reduzierte Bewegung) stehen alle
   Haken voll da: die Liste ist dort eine Inhaltsuebersicht, kein Fortschritt.
   Im Pin traegt die Deckkraft den Fortschritt — .35 ist der noch sichtbare
   Ruhezustand, 1 der erreichte. */
.halt.an .halt-schritt .hs-punkt { opacity: calc(.35 + var(--nah) * .65); }

/* ---- 21. Bewertungs-Zeile (26.08.2026) ----
   Erst im Footer gebaut, auf Patricks Ansage am 26.08. auf die Startseite
   gewandert. Deshalb OHNE `.pactos-footer` davor: die Bauform ist eine
   Komponente, kein Footer-Detail, und die naechste Seite, die sie braucht,
   soll nur die drei Klassen setzen muessen.
   ⚠ Helle Chips, Marken in Originalfarbe. Capterras Mark sind vier
   verschieden gefaerbte Dreiecke; weiss eingefaerbt verschmelzen sie zu einem
   Klumpen. Der helle Chip ist zugleich die sichere Variante gegenueber den
   Markenrichtlinien der Anbieter — anders als bei den Verbandslogos im Footer,
   die wir einfaerben.
   ⚠ Die ANZAHL der Bewertungen steht im Markup neben dem Wert und ist keine
   Zierde: am 26.08.2026 hatte jede der vier Plattformen genau eine Bewertung.
   § 5b Abs. 3 UWG verlangt beim Werben mit Bewertungen Auskunft darueber, wie
   sie zustande kommen. */
.bew-reihe{display:flex;flex-wrap:wrap;align-items:stretch;justify-content:center;gap:14px}
.bew-chip{display:flex;align-items:center;gap:12px;padding:10px 16px;border-radius:var(--r-sm);
  background:var(--surface);border:1px solid var(--line);text-decoration:none;
  transition:transform .16s ease,box-shadow .16s ease}
.bew-chip img{width:auto;display:block;flex:none}
.bew-wert{display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:600;
  color:var(--ink);white-space:nowrap}
/* Die Anzahl steht kleiner daneben, nicht darunter: sie gehoert zur Aussage und
   darf nicht wie eine Fussnote wirken, die man weglassen kann. */
.bew-n{font-weight:400;font-size:12px;color:var(--muted)}
/* Sternfarbe aus dem Token-Satz (Leitregel 1). Grau waere falsch — ein grauer
   Stern liest sich als nicht vergeben. */
.bew-stern{width:14px;height:14px;color:var(--amber-ink);flex:none}
@media (hover:hover){.bew-chip:hover{transform:translateY(-2px);box-shadow:var(--shadow-s)}}
@media (max-width:640px){.bew-reihe{gap:10px}.bew-chip{padding:8px 12px;gap:9px}}

/* ---- 22. Prozess-Seiten: Ablauf-Bahn, Modul-Schau, Auszug-Band (26.08.2026) ----
   ANLASS, zwei Stimmen. Antonio im Transkript des Website-Meetings (Z. 325):
   „ich wuerde dieses einzelne Modul erklaeren lassen … nicht per se die Module,
   sondern einfach nur die Funktionen der Module halt zeigen, und dann kann man
   sagen, das ist nur ein Auszug von dem gesamten System"; und (Z. 361) „es waere
   halt wahrscheinlich cool, wenn man einen Bildschirm noch haette oder so einen
   Auszug aus dem Portal". Patrick am 26.08.: „benutz nicht immer nur Boxen …
   beim aktuellen Problem ohne System versuch das visuell darzustellen. Und mach
   nicht immer nur Box nach Box nach Box."

   Vorher trugen die sieben Seiten dreimal dasselbe Kartenraster hintereinander
   (`.flips` 3 Karten, `.sol` 4 Karten, `.sol` 3 Karten) und im Hero einen
   [TODO]-Platzhalter statt einer Produktansicht. Drei Bauteile ersetzen das,
   jedes in einer anderen Layout-Familie:

     .ablauf  — annotierte Bahn: der Ablauf von heute als Diagramm. Die Bahn ist
                GESTRICHELT, weil genau das die Aussage ist: der Prozess laeuft
                heute nicht durch. Jede Station traegt das Medium, in dem der
                Schritt heute passiert (Mail, Excel, Telefon) — das Medium IST
                das Problem, deshalb steht es als Marke auf der Bahn.
     .schau   — Produktansicht neben einer Funktionsliste mit Haarlinien.
                Kein Raster: die Sektion soll sich von allem anderen unterscheiden.
     .auszug  — helles Mint-Band mit Textlinks auf die uebrigen Module.
                ⚠ BEWUSST HELL. Direkt darunter steht `.cta-box` auf --grad-dark;
                zwei dunkle Baender hintereinander waeren eine Wiederholung.

   ⚠ HIER UND NICHT IM <style>-BLOCK DER SEITEN (Leitregel 2): alle sieben
   prozess-*.html benutzen dieselben Klassen. Sieben Kopien waeren sieben
   Stellen, an denen eine Aenderung vergessen wird.
   ⚠ NUR KANONISCHE TOKENS (Leitregel 1). Die Prozess-Seiten definieren lokal
   Aliase (--brand, --brand-tint, --ink-panel); die gelten auf den uebrigen 141
   Seiten nicht, eine Regel hier darf sich nicht darauf stuetzen. */

/* --- Ablauf heute: eine Bahn, die nicht durchgeht --- */
.ablauf{position:relative;display:grid;grid-template-columns:repeat(4,1fr);
  gap:34px 26px;--ab-grund:var(--paper)}
.sec.tint .ablauf{--ab-grund:var(--surface-2)}
.ab-schritt,.ab-ende{position:relative;padding-top:54px}
/* ⚠ DIE BAHN ZEICHNET JEDE STATION SELBST, von der eigenen Marke bis zur
   naechsten. Erster Versuch war eine durchgehende Linie auf .ablauf::before mit
   left/right:17px — die endete aber 17px vor dem CONTAINER-Rand und lief damit
   sichtbar ueber die letzte Marke hinaus, weil die letzte Spalte breiter als
   34px ist. Von Markenmitte zu Markenmitte sind es Spaltenbreite + Luecke:
   links 17px (halbe Marke), rechts -43px (26px Luecke + 17px in die naechste
   Spalte hinein). Die Marken sind deckend, die Nahtstellen liegen darunter.
   .ab-ende zeichnet nichts: dort hoert die Bahn auf, das ist die Aussage. */
.ab-schritt::before{content:"";position:absolute;top:16px;left:17px;right:-43px;height:2px;
  background:repeating-linear-gradient(90deg,var(--green-600) 0 7px,transparent 7px 15px);
  opacity:.45}
/* Der Ring in Seitenhintergrundfarbe stanzt die Bahn um die Marke frei — dadurch
   liest sich die Marke als Station AUF der Linie, nicht als Kreis daneben. */
.ab-marke{position:absolute;top:0;left:0;z-index:1;width:34px;height:34px;
  border-radius:var(--r-full);display:grid;place-items:center;
  background:var(--tech-tint);color:var(--green-700);box-shadow:0 0 0 5px var(--ab-grund)}
.ab-marke svg{width:17px;height:17px}
.ab-medium{display:block;font-family:var(--mono);font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;font-weight:500;color:var(--green-700);margin:0 0 9px}
.ab-schritt h3{font-size:18px;font-weight:600;letter-spacing:-.015em;line-height:1.3;
  margin:0 0 8px;color:var(--ink)}
/* ⚠ STUFEN UND ERGEBNIS TEILEN DIE SCHRIFT. Das Ergebnis hatte 15,5 px statt
   15, Gewicht 500 statt 400 und Zeilenhoehe 1,5 statt 1,6 — eine halbe Pixel
   und ein halbes Gewicht Unterschied liest sich nicht als Betonung, sondern
   als Bruch (Patrick am 10.09.2026: „am Ende beim Ergebnis andere Fonts als
   bei den Stufen davor, das sieht nicht gut aus"). Ausgezeichnet wird das
   Ende dort, wo der Kommentar unten es sagt: die Marke im Vollton — und im
   Text allein ueber die Farbe. */
.ab-schritt p,.ab-ende p{font-size:15px;line-height:1.6;margin:0}
.ab-schritt p{color:var(--muted-readable)}
/* Das Ende der Bahn: kein weiterer Schritt, sondern das Ergebnis. Deshalb
   Vollton statt Tint und ein Text ohne Ueberschrift. */
.ab-ende .ab-marke{background:var(--green-700);color:var(--tech-tint)}
.ab-ende p{color:var(--ink)}
@media (max-width:1000px){
  .ablauf{grid-template-columns:1fr 1fr;gap:30px 26px}
  /* Zweispaltig endet jede Zeile rechts im Nichts: das Teilstueck der zweiten
     Spalte zeigte auf eine Marke, die eine Zeile tiefer steht. Also keine Bahn,
     die Marken tragen die Reihenfolge. */
  .ab-schritt::before{display:none}
}
/* Einspaltig wird aus der waagerechten Bahn eine senkrechte — dieselbe Aussage,
   und die Reihenfolge bleibt lesbar. */
@media (max-width:640px){
  .ablauf{grid-template-columns:1fr;gap:0}
  .ab-schritt,.ab-ende{padding:0 0 28px 50px}
  .ab-schritt::before{display:block;left:16px;top:38px;bottom:0;right:auto;width:2px;height:auto;
    background:repeating-linear-gradient(180deg,var(--green-600) 0 7px,transparent 7px 15px)}
  .ab-ende{padding-bottom:0}
  .ab-marke{box-shadow:none}
}

/* --- HubSpot-Formular im dunklen Anfrageband (.dl-band) --- */
/* ⚠ DAS FORMULAR BRINGT SEINE EIGENE SCHRIFTFARBE MIT, UND SIE IST DUNKEL.
   HubSpot rendert in einem fremden <iframe>; Feldbeschriftungen und
   Einwilligungstext kommen mit #33443F aus den Formular-Einstellungen und
   lassen sich von hier aus nicht umfaerben. Das Band ist aber
   --grad-night (#041310 → #0A4E47). Gemessen am Pilot ergab das einen
   Kontrast von 1,08:1 am hellen und 1,84:1 am dunklen Ende — WCAG AA
   verlangt 4,5:1. Die Beschriftungen waren praktisch unsichtbar, nur die
   hellen Eingabefelder standen noch im Bild.
   Das ehemalige Prototyp-Formular hatte dafuer eigene Regeln
   (.dl-band .field label{color:rgba(255,255,255,.85)}); die greifen im
   iframe nicht mehr.
   Loesung ohne HubSpot-Abhaengigkeit: eine helle Karte unter das Formular,
   wie sie .fr-panel auf security.html schon traegt. Damit steht ueberall
   dasselbe Formular auf demselben Grund — und genau das war der Wunsch.
   #33443F auf --surface misst 10,3:1.
   ⚠ NICHT die Formularfarben in HubSpot auf Weiss drehen: dieselbe Form
   steht auf demo.html und security.html auf hellem Grund. */
/* ⚠ content-box, UND DAS IST KEINE STILFRAGE. HubSpot schreibt die gemessene
   Formularhoehe als INLINE-HEIGHT auf genau dieses div (z. B. height:956px),
   und das iframe darin laeuft auf height:100%. Mit dem global gesetzten
   border-box zieht jedes Polster diese Hoehe von innen ab: 2 × 28px Polster
   ergaben ein 900px hohes iframe in einem 956px hohen Kasten — die unteren
   56px des Formulars waren abgeschnitten, und darin lag der Absendeknopf.
   Im Bild faellt das nicht auf, weil die Karte sauber weiss endet. Mit
   content-box legt sich das Polster aussen um HubSpots Hoehe. */
.dl-band .hs-form-frame{background:var(--surface);border-radius:var(--r-lg);
  padding:clamp(18px,2.2vw,28px);box-sizing:content-box}

/* --- Die Bahn baut sich auf, waehrend man sie liest (src/js/ablauf.js) --- */
/* Patrick, 27.08.2026: "wie bei den Implementierungen auf den Produktseiten,
   je weiter man scrollt dann auftauchen."

   Uebernommen ist von .impl2 (workforce.html) die MECHANIK — eine Station
   erscheint, wenn der Bildlauf ihre Marke erreicht. Ausdruecklich NICHT die
   Optik, denn die beiden Bauteile sagen das Gegenteil voneinander:
     · KEINE mitlaufende Volllinie. Die Bahn ist gestrichelt, WEIL der Prozess
       heute nicht durchlaeuft (Begruendung oben). Eine Fuellung, die sauber
       durchzieht, widerspraeche dem Abschnitt, in dem sie steht.
     · KEINE Zielmarke am Ende. .ab-ende ist das Ergebnis, kein Go-Live.
     · Bernstein bleibt Bernstein: Gruen ist auf diesen Seiten die Loesung.
     · Kein Pin. .impl2 haelt die Seite sechs Bildschirme fest und darf das,
       sie ist der Schluss einer langen Seite. Der Ablauf ist der Aufschlag;
       ihn festzuhalten hiesse, die laengste Verweildauer der Seite dem
       Abschnitt zu geben, der sagt, dass heute nichts funktioniert.

   ⚠ ALLES HAENGT AN .an, UND DIE KLASSE SETZT DAS SKRIPT. Ohne JS und bei
   prefers-reduced-motion wird sie nie gesetzt; dann steht der Ablauf
   vollstaendig da wie bisher. Hier wird nichts versteckt, was CSS nicht aus
   eigener Kraft wieder sichtbar machen kann. */
.ablauf.an .ab-schritt,.ablauf.an .ab-ende{opacity:0;transform:translateY(20px);
  transition:opacity .6s var(--ease-out),transform .6s var(--ease-out)}
.ablauf.an .ab-schritt.da,.ablauf.an .ab-ende.da{opacity:1;transform:none}
/* Die Marke setzt sich einen Wimpernschlag nach dem Text auf die Bahn. */
.ablauf.an .ab-marke{opacity:0;transform:scale(.5);
  transition:opacity .34s var(--ease-out) .08s,transform .46s var(--ease) .08s}
.ablauf.an .da .ab-marke{opacity:1;transform:none}
/* ⚠ scaleX, nicht width und nicht clip-path: DESIGN.md §5 laesst fuer Bewegung
   nur transform und opacity zu. Das kostet etwas — waehrend des Laufs steht das
   Streifenmuster enger als im Ruhezustand. Es liest sich als Linie, die
   gezeichnet wird, und liegt am Ende exakt im Raster der uebrigen Teilstuecke. */
.ablauf.an .ab-schritt::before{transform:scaleX(0);transform-origin:left center;
  transition:transform .66s var(--ease-out) .16s}
.ablauf.an .ab-schritt.da::before{transform:scaleX(1)}
@media (max-width:640px){
  /* Einspaltig laeuft die Bahn senkrecht, also waechst sie auch senkrecht. */
  .ablauf.an .ab-schritt::before{transform:scaleY(0);transform-origin:center top}
  .ablauf.an .ab-schritt.da::before{transform:scaleY(1)}
}
/* Zweiter Riegel: das Skript setzt .an hier gar nicht erst — falls die Klasse
   doch einmal steht, darf sie nichts verbergen. */
@media (prefers-reduced-motion:reduce){
  .ablauf.an .ab-schritt,.ablauf.an .ab-ende,.ablauf.an .ab-marke{
    opacity:1;transform:none;transition:none}
  .ablauf.an .ab-schritt::before{transform:none}
}

/* Produktansicht im Hero der Prozess-Seiten. Sie ersetzt den [TODO]-Platzhalter
   `.hvis-img .ph` auf den drei Seiten, fuer die eine zweite, sachlich passende
   Modulansicht existiert (Rechnungspruefung, Datenverwaltung, Compliance). Die
   uebrigen vier behalten den Platzhalter: DESIGN.md §4c sieht im Hero ein
   art-directed KI-Visual vor, und dieselbe Ansicht zweimal auf einer Seite waere
   schlechter als ein markiertes Loch.
   ⚠ DER RAHMEN MUSS SICH DEM BILD ANPASSEN, NICHT UMGEKEHRT. `.hvis` steht
   ohne Bild auf 4/3.3 (1,21) — das war fuer den quadratischen Platzhalter
   richtig. Die Modulansicht ist 880/560 (1,571). Zwei Fassungen davor waren
   beide falsch: ohne `object-fit` blieb unter dem Bild ein leerer Streifen im
   Rahmen, mit `cover` schnitt der Rahmen die Modulkarte links und rechts an und
   die Kopfzeile war nicht mehr lesbar.
   Deshalb: der Rahmen bekommt das Verhaeltnis des Bildes, sobald eines darin
   liegt. `.hvis-img` sitzt mit inset 4%/5% darin, innen bleibt also
   Breite*0,90 / Hoehe*0,92 — fuer 1,571 innen braucht .hvis aussen
   1,571*0,92/0,90 = 1,606. Damit schneidet cover praktisch nichts ab. */
.hvis:has(.hvis-img img){aspect-ratio:1.606}
.hvis-img img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 50%;display:block}

/* --- Modul-Schau: eine Ansicht, daneben ihre Funktionen ---
   Links wechselt die Ansicht durch, rechts ist der zugehoerige Eintrag weiss
   markiert (Patrick, 26.08.2026). Eine Ansicht JE EINTRAG, gerendert von
   tools/modulbilder/rahmen.mjs aus den `.mod-frame` der Mocks — die tragen dort
   dieselben Namen wie die Eintraege hier. Ohne Skript steht Ebene A auf dem
   ersten Eintrag und der ist markiert: sichtbar, nicht leer. */
.schau{display:grid;grid-template-columns:1.1fr .9fr;gap:46px;align-items:center}
.schau-bild{margin:0}
/* ⚠ ZWEI EBENEN IM WECHSEL, NICHT VIER GESTAPELTE. Vier <img> im Baum wuerden
   alle geladen, sobald die Sektion in Sichtweite kommt — gemessen 80 bis 178 kB
   je Bild. `display:none` waere der naheliegende Ausweg und ist der falsche: es
   verhindert das Laden ueberhaupt. Also laedt das Skript nur, was gebraucht
   wird, und blendet zwischen zwei Ebenen um. Dieselbe Loesung wie `.mb-buehne`
   auf den Rollenseiten. */
.schau-buehne{position:relative;aspect-ratio:880/560;border-radius:var(--r-lg);overflow:hidden;
  border:1px solid var(--line);box-shadow:var(--shadow-l);background:var(--green-900)}
.schau-ebene{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  opacity:0;transition:opacity .45s var(--ease-out)}
.schau-ebene.an{opacity:1}
.schau-bild figcaption{margin-top:14px;font-size:13px;line-height:1.5;color:var(--muted)}
/* Funktionen als Liste mit Haarlinien statt als Kartenraster. */
.schau-liste{list-style:none;margin:0;padding:0}
.schau-liste li+li{border-top:1px solid var(--line)}
/* Der Eintrag ist ein <button>: er schaltet die Ansicht, also gehoert ihm die
   Tastaturbedienung. `font:inherit` und `text-align:left`, sonst erbt er das
   Aussehen eines Systemknopfs. */
.schau-eintrag{position:relative;display:grid;grid-template-columns:auto 1fr;gap:0 15px;
  width:100%;text-align:left;padding:15px 16px 19px;border:0;background:transparent;
  font:inherit;color:inherit;cursor:pointer;border-radius:var(--r-sm);
  transition:background .2s var(--ease-out)}
.schau-eintrag .nr{font-family:var(--mono);font-size:11.5px;font-weight:500;letter-spacing:.06em;
  color:var(--muted);padding-top:4px;transition:color .2s var(--ease-out)}
.schau-eintrag b{display:block;font-size:16.5px;font-weight:600;letter-spacing:-.015em;
  color:var(--ink);margin-bottom:3px}
.schau-eintrag .wort{display:block;font-size:14.5px;line-height:1.55;color:var(--muted-readable)}
.schau-eintrag .marke{display:inline-block;margin-left:8px;font-family:var(--mono);font-size:10px;
  letter-spacing:.08em;text-transform:uppercase;font-weight:500;color:var(--amber-ink);
  background:var(--amber-bg);border-radius:var(--r-sm);padding:2px 6px;vertical-align:2px}
/* Markiert: weiss auf der getoenten Sektionsflaeche.
   ⚠ HOVER BEKOMMT BEWUSST KEINE EIGENE FLAECHE. Erste Fassung gab ihm dieselbe
   weisse — und dann waren zwei Eintraege gleichzeitig weiss: der gehoverte und
   der noch aktive, solange der Bildwechsel lief. Zwei Markierungen sind keine.
   Ein Hover schaltet hier ohnehin um, die weisse Flaeche kommt also eine
   Zehntelsekunde spaeter von selbst; `cursor:pointer` traegt die Anfassbarkeit
   bis dahin. Nur der Name wird gruen, das ist Rueckmeldung ohne zweite Flaeche. */
.schau-eintrag[aria-current="true"]{background:var(--surface);box-shadow:var(--shadow-s)}
.schau-eintrag[aria-current="true"] .nr{color:var(--green-600)}
@media (hover:hover){.schau-eintrag:hover b{color:var(--green-600)}}
/* Der Takt zeigt, dass von selbst weitergeschaltet wird. Kein Breiten-, sondern
   ein Transform-Wechsel (DESIGN.md §5), und die Dauer kommt aus --dauer, das
   das Skript aus data-dauer setzt: eine Zahl, zwei Verwendungen. */
.schau-takt{position:absolute;left:16px;right:16px;bottom:9px;height:2px;border-radius:2px;
  background:var(--line);overflow:hidden;opacity:0;transition:opacity .2s var(--ease-out)}
.schau-eintrag[aria-current="true"] .schau-takt{opacity:1}
.schau-takt::before{content:"";display:block;height:100%;background:var(--green-600);
  transform:scaleX(var(--takt,0));transform-origin:left;
  transition:transform var(--dauer,4200ms) linear}
@media (prefers-reduced-motion:reduce){
  .schau-takt{display:none}
  .schau-ebene{transition:none}
}
/* Gespiegelt: Bild rechts, Liste links. Gebraucht auf prozess-compliance.html,
   wo ZWEI Modul-Schauen uebereinander stehen (Compliance im VMS und
   CompliancePro als eigenes Produkt, KERNMODULE.md). Ungespiegelt saehe die
   zweite wie eine Wiederholung der ersten aus. */
.schau-gedreht .schau-bild{order:2}
.schau-gedreht .schau-liste{order:1}
/* Auf ungetoentem Grund traegt die weisse Markierung allein zu wenig: --paper
   und --surface liegen nur wenig auseinander. Deshalb dort zusaetzlich eine
   Kante. GEMESSEN, nicht geschaetzt: siehe Kommentar im Commit. */
.sec:not(.tint) .schau-eintrag[aria-current="true"]{border:1px solid var(--line)}
@media (max-width:900px){
  .schau{grid-template-columns:1fr;gap:32px}
  .schau-bild{order:-1}
  .schau-gedreht .schau-bild{order:-1}
  .schau-gedreht .schau-liste{order:0}
}

/* --- Auszug-Band: was noch im System steckt --- */
.auszug{border-radius:var(--r-xl);background:var(--tech-tint);border:1px solid var(--line);
  padding:40px 44px;display:grid;grid-template-columns:1fr auto;gap:36px 48px;align-items:center}
.auszug h2{font-size:clamp(22px,2.4vw,29px);font-weight:600;letter-spacing:-.025em;
  line-height:1.15;margin:0 0 10px;color:var(--ink);text-wrap:balance}
.auszug p{font-size:16px;line-height:1.55;color:var(--muted-readable);margin:0 0 22px;
  max-width:46ch}
/* Textlinks, keine Kacheln: die Liste soll als Verweis lesen, nicht als
   zweites Angebot neben dem Modul darueber. */
.auszug-liste{list-style:none;margin:0;padding:0;display:grid;gap:2px;min-width:252px}
.auszug-liste a{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:11px 0;font-size:15px;font-weight:500;color:var(--ink);text-decoration:none;
  border-bottom:1px solid var(--line)}
.auszug-liste li:last-child a{border-bottom:0}
.auszug-liste a svg{width:15px;height:15px;flex:none;color:var(--green-600);
  transition:transform .16s var(--ease-out)}
@media (hover:hover){.auszug-liste a:hover{color:var(--green-600)}
  .auszug-liste a:hover svg{transform:translate(2px,-2px)}}
@media (max-width:860px){
  .auszug{grid-template-columns:1fr;padding:32px 26px;gap:26px}
  /* Grid-Kinder duerfen unter ihre min-content-Breite schrumpfen — sonst blaeht der
     nowrap-Knopf „… live ansehen" (316px) die 1fr-Spalte auf und Text/Knopf/Liste
     ragen ~74px ueber den 243px schmalen Kartenrand hinaus. */
  .auszug > *{min-width:0}
  .auszug .btn{white-space:normal;text-align:center}
  .auszug-liste{min-width:0}
}

/* ---- 20. Mega-Menue: Bilder und Unterpunkt-Gruppen (26.08.2026) ------------
   Patrick: „fuer die Unternehmen-, Ressourcen- und Anwendungsfaelle-Nav analog
   zu beam.ai, tacto usw. immer ein Bild rechts oder links daneben" und „in der
   Loesungen-Nav jeweils ein Hintergrundbild in den Produktkarten".
   Antonio im Meeting vom 25.08.: die Unterpunkte muessen zeigen, dass sie zum
   Kasten darueber gehoeren.

   ⚠ DIE BILDER LADEN ERST BEIM ERSTEN OEFFNEN. Das geschlossene Panel ist
   `opacity:0; visibility:hidden`, NICHT `display:none` — ein <img src> darin
   wuerde auf JEDER der 148 Seiten sofort geladen, und `loading="lazy"` greift
   nicht, weil das Panel im Viewport haengt. Die Quelle steht in
   `data-navbild`, src/js/header.js setzt sie beim ersten Oeffnen. Ohne JS
   bleibt das Menue vollstaendig, nur ohne Bild. */

/* -- Hintergrundbild in der Produktkarte (Loesungen) -- */
.nav-outer .mega-head.hat-bild{position:relative;overflow:hidden;isolation:isolate}
.nav-outer .mega-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:right top;z-index:0}
/* ⚠ NUR HELLE BILDER. Der Schleier laesst rechts bewusst viel Bild durch; mit
   einem dunklen Motiv faellt die Beschreibung dort unter AA (mit dem
   Nebelmotiv gemessen: 1,84:1). Produktansichten sind hell, deshalb gehen sie.
   Wer ein dunkles Motiv einhaengen will, muss den Schleier mitziehen. */
.nav-outer .mega-head.hat-bild::before{content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(100deg,rgba(255,255,255,.97) 0 40%,rgba(255,255,255,.80) 66%,rgba(255,255,255,.52));
  pointer-events:none}
.nav-outer .mega-head.hat-bild > *:not(.mega-bg){position:relative;z-index:2}
.nav-outer .mega-head.hat-bild:hover::before{
  background:linear-gradient(100deg,rgba(231,248,240,.97) 0 40%,rgba(231,248,240,.80) 66%,rgba(231,248,240,.52))}
/* -- Kundenband im Referenzen-Panel (Patrick, 31.08.2026) --
   Vorbild ist beam.ai: der Menuepunkt "Our Customers" klappt ein Band der
   Kundenlogos auf einem geblurrten Foto auf. Nachgebaut mit den Bauteilen, die
   hier schon stehen: `.hat-bild` liefert Bild plus Schleier, `data-navbild`
   liefert das Nachladen.
   ⚠ HELLER SCHLEIER, GRUENE LOGOS. Die dunkle Fassung (weisse Typografie auf
   dunklem Schleier, wie bei den vier Produktkarten darunter) haette ZEHN weisse
   Logodateien gebraucht. Die gruenen Mono-Fassungen liegen schon im Repo, und
   das Panelinnere ist ohnehin weiss.
   ⚠ ALLE ELF BILDER SIND LAZY. Ein Bild plus zehn Logos in einem Panel, das auf
   jeder Seite haengt, waeren elf Anfragen je Seitenaufruf. Die Quellen stehen in
   `data-navbild`, src/js/header.js setzt sie beim ersten Oeffnen — dieselbe
   Regel wie bei den Produktkarten. Ohne JS bleibt das Panel vollstaendig, nur
   ohne Bilder.
   ⚠ DAS BILD IST HOCHSKALIERT. `blur()` zieht die Kanten transparent; ohne
   `scale` liegt ein heller Rand um das Motiv. */
.nav-outer .mega-head.ist-kunden{display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:start;gap:12px 14px;min-height:0;padding:16px 18px 18px}
.nav-outer .ist-kunden .mega-bg{object-position:center 60%;
  filter:blur(14px) saturate(.9);transform:scale(1.14)}
/* ⚠ DER SCHLEIER IST OBEN DICHT UND UNTEN DUENN, UND ZWAR GEMESSEN.
   Zonenweise gegen das geblurrte Foto geprueft, Text und Logos ausgeblendet:
     · gleichmaessig .78 auf .90  →  Beschreibung an der dunkelsten Stelle 3,03:1
       (AA verlangt 4,5) und Logos 4,62:1
     · jetzt .95 oben auf .80 unten  →  Beschreibung 5,8:1, Logos 4,3:1
   Das Foto soll also HINTER DEN LOGOS durchkommen, nicht hinter dem Text.
   Wer den Schleier oben aufhellt, macht die Beschreibung unlesbar; wer ihn
   unten schliesst, kann das Bild gleich weglassen.
   ⚠ `.mega-head.ist-kunden::before`, NICHT `.ist-kunden::before`. Die
   Grundregel `.nav-outer .mega-head.hat-bild::before` hat drei einfache
   Selektoren; mit zwei verliert man gegen sie, und zwar lautlos: der Schleier
   blieb der waagerechte aus der Produktkarte (.97 links auf .52 rechts), und
   jede Aenderung am eigenen Verlauf blieb ohne Wirkung. Gemessen daran, dass
   drei verschiedene Verlaeufe exakt dieselben Zahlen ergaben. */
.nav-outer .mega-head.ist-kunden::before{background:linear-gradient(180deg,rgba(255,255,255,.99) 0 32%,rgba(255,255,255,.70) 56%,rgba(255,255,255,.70))}
.nav-outer .mega-head.ist-kunden:hover::before{background:linear-gradient(180deg,rgba(231,248,240,.99) 0 32%,rgba(231,248,240,.70) 56%,rgba(231,248,240,.70))}
.nav-outer .ist-kunden .mega-desc{max-width:44ch}
/* ⚠ EINE DURCHLAUFENDE REIHE (Patrick, 31.08.2026): „eher einfach eine
   durchlaufende Reihe der Logos auf dem Hintergrund". Vorher ein 5x2-Raster.
   ⚠ ZWEI EXAKT GLEICHE HAELFTEN, `gap:0`, Abstand als `margin-inline-end`.
   `translateX(-50%)` setzt gleiche Haelften voraus; mit `gap` bleibt die letzte
   Kachel jeder Haelfte ohne Abstand, und die Reihe springt je Runde. Genau
   dieser Fehler steckte in den zwei Baendern auf startseite.html (32 px) und
   referenzen.html (7 px). */
.nav-outer .kunden-band{grid-column:1/-1;display:block;overflow:hidden;
  margin-top:8px;padding-top:14px;border-top:1px solid rgba(11,91,82,.14);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent)}
.nav-outer .kb-lauf{display:flex;align-items:center;gap:0;width:max-content;
  animation:kb-lauf 34s linear infinite}
@keyframes kb-lauf{to{transform:translateX(-50%)}}
/* ⚠ Bei reduzierter Bewegung laeuft nichts: die erste Haelfte bricht um und
   steht, die zweite (aria-hidden) entfaellt. Ein Band, das nur die Haelfte
   zeigt, waere kein Rueckfall, sondern ein Fehler. */
@media (prefers-reduced-motion:reduce){
  .nav-outer .kb-lauf{animation:none;flex-wrap:wrap;width:100%;
    justify-content:center;gap:14px 0}
  .nav-outer .kb-logo[aria-hidden="true"]{display:none}
  .nav-outer .kb-logo{margin-inline-end:26px}
}
.nav-outer .kb-logo{max-height:21px;width:auto;height:auto;flex:none;display:block;
  object-fit:contain;margin-inline-end:38px;filter:var(--logo-mono)}
/* ⚠ NUR FUER MARKEN, DIE IHR GRUEN ALS DATEI TRAGEN — das ist knuth-mono.png
   und sonst nichts. GEMESSEN malt die Datei rgb(12,80,77), der Filter wuerde
   rgb(11,79,75) daraus machen: ein Punkt Unterschied, also unnoetig.
   ⚠ buerger-mono.svg stand hier faelschlich mit drin und blieb dadurch
   rgb(0,0,0) — schwarz zwischen lauter gruenen Logos, im Menue „Referenzen"
   sofort zu sehen (Patrick, 10.09.2026). Die Mono-Fassung ist gerade DESHALB
   entstanden, damit der Filter greifen kann: das Original hat weisse Schrift
   in einer farbigen Platte, die brightness(0) verschluckt (siehe tokens.css
   bei --logo-mono). Sie gehoert also gefiltert, nicht ausgenommen. Auf allen
   anderen Seiten trug Buerger ohnehin nie eine Sonderklasse.
   Wer hier eine Marke eintraegt: vorher die Datei messen. */
.nav-outer .kb-logo.ist-eigen{filter:none}

/* -- Nebelmotiv in den vier Produktkarten (Patrick, 26.08.2026) --
   Die vier Produktseiten tragen seit dem 26.08.2026 den bewegten Nebel im Hero
   (src/styles/nebel.css); die Karten im Menue zeigen dasselbe Motiv in derselben
   Produktfarbe. EIN Bild fuer alle vier, die Farbe macht ein Filter — siehe die
   Regeln in nebel.css.
   ⚠ Das ist die UMKEHRUNG der hellen Fassung darueber, und zwar genau so, wie
   deren Hinweis es verlangt: „Wer ein dunkles Motiv einhaengen will, muss den
   Schleier mitziehen." Also dunkler Schleier UND weisse Typografie. Mit dem
   hellen Schleier war die Beschreibung auf dem Nebel bei 1,84:1 gemessen; mit
   diesem sind es 8,9:1 (Titel 15,1:1).
   ⚠ ES IST EIN STANDBILD, keine Animation. Vier Karten mal zwei bewegte Ebenen
   liefen auf JEDER der 148 Seiten mit, auch bei geschlossenem Menue — das Panel
   ist nur opacity:0, nicht display:none. Der Nutzen im 132 px hohen Kasten
   waere kaum zu sehen, die Kosten hat jede Seite. */
.nav-outer .mega-head.nebel-karte{background:var(--grad-ink);
  border-color:color-mix(in srgb, var(--surface) 16%, transparent)}
.nav-outer .mega-head.nebel-karte:hover{background:var(--grad-ink);
  border-color:color-mix(in srgb, var(--tech) 55%, transparent)}
/* ⚠ DIE STOPPS LIEGEN WEIT RECHTS (0 bis 54 %), nicht bei 38 % wie in der
   hellen Fassung. Der Text steht in der linken Kartenhaelfte; mit den 38 % der
   Vorlage kam die Beschreibung am hellsten Bildpunkt auf 4,27:1 (VMS) und
   4,44:1 (Tender), also unter die Schwelle 4,5. Gemessen danach: 5,6 und 5,9.
   Die Alternative waere gewesen, den Schleier insgesamt zu verstaerken — das
   haette vom Motiv nichts uebrig gelassen. */
.nav-outer .mega-head.nebel-karte::before{
  background:linear-gradient(100deg,
    color-mix(in srgb, var(--ink) 95%, transparent) 0 54%,
    color-mix(in srgb, var(--ink) 74%, transparent) 76%,
    color-mix(in srgb, var(--ink) 42%, transparent))}
.nav-outer .mega-head.nebel-karte:hover::before{
  background:linear-gradient(100deg,
    color-mix(in srgb, var(--ink) 91%, transparent) 0 54%,
    color-mix(in srgb, var(--ink) 68%, transparent) 76%,
    color-mix(in srgb, var(--ink) 36%, transparent))}
.nav-outer .mega-head.nebel-karte .mega-title{color:var(--surface)}
.nav-outer .mega-head.nebel-karte:hover .mega-title{color:var(--tech)}
.nav-outer .mega-head.nebel-karte .mega-desc{color:color-mix(in srgb, var(--surface) 74%, transparent)}
.nav-outer .mega-head.nebel-karte .mega-arrow,
.nav-outer .mega-head.nebel-karte:hover .mega-arrow{color:var(--surface)}
/* Produktfarbe des Motivs. Die Drehwinkel sind gerechnet, nicht probiert: der
   Nebel liegt bei Farbton 159 Grad, --orange #FE5E00 bei 22, --ai #6025E1 bei
   259, daraus -137 und +100. VMS braucht keine Regel, dort ist das Bild schon
   richtig. Dieselben Werte wie in nebel.css — sie stehen HIER, weil das Menue auf
   allen 148 Seiten liegt und nebel.css nur auf den vier Produktseiten. */
/* ⚠ DIESELBEN FILTER WIE DIE HEROES (Abschnitt 25), seit die Karten am
   28.08.2026 auf das Platinenbild umgestellt sind (src/js/nebel.js). Vorher
   standen hier andere Werte, weil ein anderes Grundbild darunter lag; jetzt
   ist es dasselbe Bild, also gehoeren dieselben Werte hin. Gemessener Farbton
   der Kachel in Klammern. */
.nav-outer [data-nebel-produkt] .mega-bg{
  filter:saturate(1.65) contrast(1.45)}                                    /* vms */
/* ⚠ ALLE VIER PRODUKTE TRAGEN IHR EIGENES BILD und damit ihre eigene Farbe
   (assets/hero/hero-kreise-*.webp bzw. hero-workforce.webp, dieselben Dateien
   wie im Hero der Seite). Der Filter ist überall aus; er drehte den Ton EINES
   Nebelbildes in vier Richtungen und würde die gebackene Farbe verdrehen.
   Workforce Intelligence (pax-ai) trägt seit 07.09.2026 hero-workforce.webp
   (Kreise, schon grün) statt der Platine — daher hier ebenfalls filter:none. */
.nav-outer [data-nebel-produkt="vms"] .mega-bg,
.nav-outer [data-nebel-produkt="compliance"] .mega-bg,
.nav-outer [data-nebel-produkt="tender"] .mega-bg,
.nav-outer [data-nebel-produkt="pax-ai"] .mega-bg{filter:none}

/* Gleiche Hoehe fuer alle vier Produktkaesten, sonst franst die Reihe aus. */
.nav-outer .mega-4 .mega-head{min-height:132px}

/* Zweite Reihe: zwei breite Kaesten (Patrick, 04.09.2026). Datensicherheit
   unter Vendor und Compliance, Schnittstellen unter Tender und Workforce.
   Sie liegen direkt im Raster statt in einer .mega-col und nehmen je zwei
   Spalten — 2x196,5px plus 28px Abstand = 421px.
   Hoehe wie die Produktkaesten (Patrick, 04.09.2026): die 132px aus der Regel
   darueber gelten mit, hier wird nur der Aussenabstand nach unten genommen.
   Der Inhalt bleibt oben ausgerichtet wie in Reihe eins. */
.nav-outer .mega-4 .mega-breit{grid-column:span 2;margin-bottom:0}
/* Alle vier Produktnamen enden auf "Intelligence". Ohne Begrenzung passt nur
   "Tender Intelligence" in eine Zeile (gemessen: 145px bei 148px Platz), die
   drei anderen brauchen 148, 173 und 183px und brechen um — dann beginnen die
   Beschreibungen auf verschiedenen Hoehen. 12ch zwingt alle vier zum Umbruch
   nach dem ersten Wort; "Intelligence" steht dadurch in allen vier Kaesten auf
   derselben Zeile. Einzeilig ginge nur mit rund 1100px Panelbreite statt 920. */
.nav-outer .mega-4 .mega-col .mega-title{max-width:12ch}
/* Jede Spalte traegt jetzt genau einen Kasten; der Aussenabstand nach unten
   kaeme zum Rasterabstand von 28px hinzu.
   flex:1 laesst den Kasten die Rasterzeile fuellen. Ohne das steht er auf
   seinen 132px, waehrend die Zeile so hoch ist wie ihr hoechster Kasten:
   "Vendor Intelligence" hat seit der Umbenennung einen zweizeiligen Titel ueber
   einer dreizeiligen Beschreibung und misst 137px — die drei anderen haetten
   dann 5px Luft unter sich. */
.nav-outer .mega-4 .mega-col .mega-head{margin-bottom:0;flex:1}

/* -- Unterpunkte gehoeren sichtbar zu ihrem Kasten (Antonio) --
   Eine Senkrechte statt Bullets: sie verbindet die Punkte mit dem Kasten
   darueber, Bullets haetten nur eine zweite Liste erzeugt. */
.nav-outer .mega-unter{display:flex;flex-direction:column;margin-left:14px;padding-left:14px;
  border-left:1px solid var(--line)}
.nav-outer .mega-unter .mega-link{position:relative;padding-left:14px;margin-inline:0}
.nav-outer .mega-unter .mega-link::before{content:"";position:absolute;left:0;top:50%;
  width:7px;height:1px;background:var(--line);transition:background .16s ease,width .16s ease}
.nav-outer .mega-unter .mega-link:hover::before{background:var(--green-700);width:10px}

/* -- Ein Bild neben den Textspalten. Nur Bild: kein Link, kein Text, keine
      Beschriftung. -- */
.nav-outer .mega.hat-seitenbild .mega-inner{align-items:stretch}
.nav-outer .mega-3.hat-seitenbild .mega-inner{grid-template-columns:repeat(3,minmax(170px,1fr)) 260px;width:968px}
/* Anwendungsfälle: 4 Spalten + Seitenbild, links-bündig ab Item-Position ~330px,
   Desktop-Menü erst ab 1281px → Gesamtbreite ~940px, Bild 190px, lange Labels umbrechen. */
.nav-outer .mega-4.hat-seitenbild .mega-inner{grid-template-columns:repeat(4,minmax(150px,1fr)) 190px;width:940px;gap:20px}
.nav-outer .mega-4.hat-seitenbild .mega-link{overflow-wrap:break-word;hyphens:auto}
.nav-outer .mega-1.hat-seitenbild .mega-inner{grid-template-columns:226px 260px;width:auto;gap:16px;padding:16px}
.nav-outer .mega-seitenbild{display:block;border-radius:12px;overflow:hidden;
  background:var(--line-soft);min-height:100%}
.nav-outer .mega-seitenbild img{width:100%;height:100%;object-fit:cover;display:block}

/* Im Burger-Panel bleibt die Liste eine Liste: Bilder sind dort Ballast, die
   Zugehoerigkeit der Unterpunkte bleibt. */
@media (max-width:1280px){
  .nav-outer .mega-bg,
  .nav-outer .mega-head.hat-bild::before,
  .nav-outer .mega-seitenbild{display:none}
  /* Einspaltig im Burger: die Desktop-Regel (940px, 4 Spalten + Bild) hat 0,4,0
     und schlaegt sonst die 1fr-Regel weiter oben. Hier gleiche Spezifitaet, aber
     spaeter -> gewinnt. Damit stehen die Anwendungsfaelle-Sektionen untereinander. */
  .nav-outer .mega-4.hat-seitenbild .mega-inner,
  .nav-outer .mega-1.hat-seitenbild .mega-inner{grid-template-columns:1fr;width:auto;gap:0}
  /* Im Panel ist das Motiv ausgeblendet (Zeile darueber). Dann gibt es auch
     keinen Grund, die vier Produktkarten dunkler zu faerben als die anderen
     zwei — vorher standen sie hier fast schwarz zwischen zwei durchscheinenden
     Kaesten. Zurueck auf die Panel-Fassung. */
  .nav-outer .mega-head.nebel-karte,
  .nav-outer .mega-head.nebel-karte:hover{background:rgba(255,255,255,.06);
    border-color:rgba(255,255,255,.18)}
  .nav-outer .mega-head.nebel-karte:hover{background:rgba(255,255,255,.10);
    border-color:rgba(255,255,255,.35)}
  .nav-outer .mega-4 .mega-head{min-height:0}
  /* Einspaltig: „span 2“ wuerde hier eine implizite zweite Spalte anlegen. */
  .nav-outer .mega-4 .mega-breit{grid-column:auto}
  /* Gestapelt, also nebeneinander nichts auszurichten: natuerlicher Umbruch. */
  .nav-outer .mega-4 .mega-col .mega-title{max-width:none}
  .nav-outer .mega-unter{border-left-color:rgba(255,255,255,.24)}
  .nav-outer .mega-unter .mega-link::before{background:rgba(255,255,255,.32)}
}

/* ---- 23. Musterflächen auf grünem Grund (27.08.2026) -----------------------
   ANLASS: Patrick — „bisher ist das immer nur das Grün". Die dunklen Flächen
   (`--grad-dark`) waren einfarbig; auf einer Produktseite wiederholt sich das
   vier, fünf Mal. Vorlage waren zwei ChatGPT-Bilder (27.08.), nachgebaut als
   Formfiles: `assets/muster/kreise.svg` (Kreisbahnen) und
   `assets/muster/bahnen.svg` (Platinenbahnen). Erzeugt von
   `tools/muster/{kreise,bahnen}.mjs` mit fester Saat — neu laufen lassen
   ergibt bitgleich dieselbe Datei.
   ⚠ WUERFEL RAUS (10.09.2026). Das erste Muster waren isometrische
   Wuerfelkanten (`wuerfel.svg`) — Karo: „In manchen Karten sind so
   Wabenformen. Wir haben eigentlich immer die Kreislogik." Die Kreise sind
   dasselbe Motiv wie die Seitenhintergruende (background.css: Haarlinie mit
   Hof), nur als Flaechenfuellung. Der Wuerfel-Generator liegt unter
   tools/stillgelegt/, die Klasse `.muster-wuerfel` gibt es nicht mehr.

   ⚠ NICHT ALS `mask-image`, SO WAR ES ZUERST GEBAUT. Masken sind
   CORS-pflichtig: über `file://` blockiert Chrome die externe SVG-Datei
   („Access to image … blocked by CORS policy"), die Fläche bleibt einfarbig.
   Genau der Fall, vor dem DESIGN.md beim Foto-CTA warnt — die Seiten müssen per
   Doppelklick UND über Server stimmen. Bilder unterliegen dem nicht, also
   `background-image` und die Stärke über `opacity` statt über den Alphawert
   einer Farbe. Preis dafür: die Strichfarbe (#fff, per Pfad abgestuft) steht in
   der Datei und ist nicht per Token umfärbbar. Für Weiß auf Dunkelgrün in
   Ordnung; wer das Muster je mintfarben will, ändert die zwei Generatoren.
   ⚠ Der `url()` steht DIREKT hier, nicht in einer CSS-Variablen — in einer
   Variablen würde er beim Verbrauch relativ zu components.css aufgelöst und
   liefe ins Leere (DESIGN.md §4, Foto-CTA, verifiziert 24.07.).
   Gemessen 24,5 KB / 7,8 KB Dateigröße, gepackt 4,7 KB / 1,3 KB — die
   Vorlagen-PNGs waren 1,1 MB und 1,0 MB.

   ::before, NICHT ::after. Auf allen vier Flächen der VMS-Seite (.zahlenbox,
   .fu, .cta-box, .ref35-karte) ist ::after schon belegt — überall mit
   `--glow-mint`. ::before war frei und ist zusätzlich die richtige Reihenfolge:
   es liegt UNTER dem Mint-Schimmer, so wie in der Vorlage, und unter dem
   Inhalt, weil die Flächen ihre Kinder ohnehin auf `z-index:1` heben.

   `border-radius: inherit` ist Pflicht — die Kästen sind gerundet und tragen
   nicht alle `overflow: hidden` (.ref35-karte bewusst nicht, s. workforce.html).

   REGLER --muster-deckung. Die Klasse schaltet ein, die Variable bestimmt die
   Stärke; `0` schaltet aus, ohne Markup anzufassen — wie --pbg-intensity,
   --pf-paths-intensity und --hero-navschutz. Voreinstellung .28: gemessen
   bleibt der hellste Punkt in der Textspalte damit bei 9,85:1 gegen Weiß, das
   Vorlagen-PNG lag bei 8,68:1 (Würfel) bzw. 5,84:1 (Bahnen).

   `mask-position: right center` gehört zur Bauart, nicht zur Deko: die Dichte
   der beiden Muster liegt rechts, links läuft sie auf null. Text steht links. */
.muster-kreise::before,
.muster-bahnen::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  border-radius:inherit;
  opacity:var(--muster-deckung,.24);
  background-repeat:no-repeat;
  background-size:auto;              /* NICHT cover — s. Kopf */
  background-position:right center;
  /* Zweite, FLÄCHENRELATIVE Ausblendung. Die SVG-Datei blendet bei 34–62 %
     ihrer eigenen Breite aus — auf einer 1152px schmalen Box sieht man davon
     aber den Ausschnitt 520–1672, die Ausblendung liegt dann schon am linken
     Kastenrand und eine Bahn lief mitten durch die Überschrift. Diese Maske
     rechnet in Prozent DER FLÄCHE und ist damit von der Kastenbreite
     unabhängig. Ein Verlauf als Maske ist erlaubt: nur externe Dateien
     unterliegen CORS, erzeugte Verläufe nicht.
     ⚠ ZWEI STOPPS, NICHT EINER. `transparent 0, #000 66%` ist eine Rampe über
     die ganze linke Hälfte — bei 700px von 1152 sind das noch 92 % Deckung,
     die Bahn lief weiter durch die Überschrift. Die Ausblendung braucht einen
     Anlauf von 22 %, davor ist sie vollständig aus. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,
    transparent calc(var(--muster-rand,52%) - 22%),#000 var(--muster-rand,52%));
          mask-image:linear-gradient(90deg,transparent 0,
    transparent calc(var(--muster-rand,52%) - 22%),#000 var(--muster-rand,52%));
}
/* Zentrierter Inhalt braucht mehr Abstand: bei .cta-box und .zahlenbox steht
   die Überschrift in der Mitte, nicht links. */
.muster-mitte{--muster-rand:66%}

/* UNTER 640px AUS. Nicht aus Vorsicht, sondern weil die Geometrie dort nicht
   mehr aufgeht: das Band ist am Handy 2871px hoch (gemessen, 390px Breite),
   die Grafik 1420px und mittig gesetzt — oben und unten bleiben je ~725px
   leer, und in der Bandmitte blieben am rechten Rand drei, vier Würfelkanten
   stehen. Das liest als Versehen, nicht als Muster. Ab 768px stimmt es wieder
   (dort geprüft: Bahnen sitzen rechts, kreuzen keinen Text), 640px ist der
   bereits vorhandene Breakpoint dazwischen — es kommt keine neue Zahl dazu. */
@media (max-width:640px){
  .muster-kreise,.muster-bahnen{--muster-deckung:0}
}
.muster-kreise::before {background-image:url(../../assets/muster/kreise.svg)}
.muster-bahnen::before {background-image:url(../../assets/muster/bahnen.svg)}
/* Bewegung ist hier keine, also gibt es auch nichts abzuschalten — die Fläche
   bleibt bei `prefers-reduced-motion` unverändert. Absicht, kein Vergessen. */

/* ---------- Kundenlogos im Laufband ----------------------------------------
   Sieben Seiten tragen dasselbe Laufband (index, startseite, die vier
   Startseiten-Varianten, roi-rechner). Die Regeln stehen deshalb hier und nicht
   inline: Regel 2 der Kompatibilitaetswaechter verweist neue Regeln
   ausdruecklich nach components.css, und drei dieser Seiten stehen in der
   Basislinie.
   Die HOEHE steht bewusst inline am Bild. Die Logos haben unterschiedliche
   Bauform — eine gestapelte Marke (unique, Manpower) braucht mehr Hoehe als
   eine reine Wortmarke (VOLVO), sonst wirkt sie winzig. Genauso halten es die
   Verbandslogos auf ueber-uns.html.
   ⚠ gap:0 plus margin-inline-end statt gap: das Laufband animiert auf
   translateX(-50%) und braucht dafuer zwei exakt gleich breite Haelften. Mit
   `gap` fehlt der letzten Kachel jeder Haelfte ihr Abstand — die halbe
   Spurbreite liegt dann um eine halbe Luecke daneben und das Band ruckt bei
   jedem Durchlauf um 32 px. Der :has()-Selektor greift nur dort, wo wirklich
   Bilder laufen; die Logowand auf referenzen.html behaelt ihr gap. */
.logos-track:has(> img){gap:0}
.logos-track > img{flex:none;display:block;width:auto;object-fit:contain;margin-inline-end:64px}
/* Bildlogos in der Logowand auf referenzen.html. Auch hier zentral: die Seite
   traegt bereits eine offene Regel-2-Schuld, jede weitere Inline-Regel
   vergroessert sie. */
.logos-item img{display:block;width:auto;max-width:148px;object-fit:contain}
/* Dieselbe Halbierungs-Rechnung wie oben, nur fuer die Kachelwand: gemessen
   begann die zweite Haelfte 7 px (eine halbe Luecke) neben der halben
   Spurbreite, das Band sprang bei jedem Durchlauf. */
.logos-track:has(> .logos-item){gap:0}
.logos-track > .logos-item{margin-inline-end:14px}
@media (max-width:760px){.logos-track > img{margin-inline-end:38px}}

/* ---------- Kundenlogos einfarbig (.logos-mono) -----------------------------
   Die 15 Anwendungsfall-Seiten (5 Prozess, 4 Rollen, 6 Branchen) trugen bis zum
   27.08.2026 `<span>[TODO: Kundenlogo]</span>` bzw. Firmennamen als Text. Jetzt
   stehen dort echte Logos, und zwar in derselben Farbe wie die Investorenlogos
   auf ueber-uns.html — die Filterkette liegt als --logo-mono in tokens.css, die
   Begruendung und die Alpha-Falle stehen dort.
   Die Klasse sitzt am Band, nicht am Bild: so bleibt entscheidbar, welches Band
   einfarbig laeuft. Sie traegt deshalb auch das stille `.kundenband-reihe` auf
   compliance.html und compliance-neu.html (27.08.2026, Patrick: „Mach das auf
   Compliance auch") sowie roi-rechner.html (29.08.2026, Patrick: „auf der roi
   rechner seite sind die Kundenlogos noch farblich" — die Seite stand bis dahin
   auf der Ausnahmeliste, das war offenbar keine Absicht).
   NICHT einfarbig laufen jetzt nur noch die Startseiten-Familie und die Logowand
   auf referenzen — an der Startseite arbeitet eine zweite Sitzung, deshalb
   bleibt sie hier unangetastet.
   Bei `prefers-reduced-motion` steht das Band still und bricht um; die
   Zeilenluecke muss hier stehen, weil `.logos-track:has(> img){gap:0}` (0,1,1)
   jede Regel im Media-Query bei (0,1,0) schlaegt — Media-Queries erhoehen die
   Spezifitaet nicht. */
.logos-mono img{filter:var(--logo-mono)}

/* Ruhezustand des einfarbigen Bandes: umbrechen statt abschneiden.
   Unter 760px (dort schalten die 10 Rollen- und Branchenseiten die Bewegung ab)
   und bei `prefers-reduced-motion` laeuft nichts mehr. Ohne die drei Regeln
   unten steht das Band dann abgeschnitten am Fensterrand — GEMESSEN auf
   rolle-hr bei 390px: zweieinhalb von zehn Logos sichtbar, der Rest hinter der
   Maske. Drei Sachen muessen dafuer zusammenkommen:
     · width:auto — `max-content` ist immer die Summe EINER Zeile, mit ihm
       greift flex-wrap:wrap nie;
     · gap statt margin-inline-end — sonst schiebt die letzte Kachel jeder Zeile
       die zentrierte Reihe um eine halbe Luecke nach links;
     · die aria-hidden-Haelfte ausblenden — sie ist die Kopie fuer das Laufband;
       im umgebrochenen Zustand stuende jedes Logo sonst zweimal da.
   Bewusst an .logos-mono und nicht an :has(> img): das Laufband der
   Startseiten-Familie soll auf dem Telefon weiterlaufen. */
@media (max-width:760px){
  .logos-track.logos-mono{flex-wrap:wrap;width:auto;justify-content:center;gap:20px 34px}
  .logos-track.logos-mono > img{margin-inline-end:0}
  .logos-track.logos-mono > img[aria-hidden=true]{display:none}
  /* Und die Randmaske aus: sie blendet die aeussersten 12 % aus, damit Logos im
     LAUFEN weich hinein- und hinausgleiten. Steht das Band still, waeren das
     erste und das letzte Logo dauerhaft halb durchsichtig — GEMESSEN bei 1440px
     reichen die 158 px Ueberblendung genau bis in „Vaillant" und
     „Talent Spring" hinein. */
  .logos-marquee:has(.logos-mono){-webkit-mask-image:none;mask-image:none}
}
@media (prefers-reduced-motion:reduce){
  .logos-track.logos-mono{flex-wrap:wrap;width:auto;justify-content:center;gap:20px 34px}
  .logos-track.logos-mono > img{margin-inline-end:0}
  .logos-track.logos-mono > img[aria-hidden=true]{display:none}
  /* Und die Randmaske aus: sie blendet die aeussersten 12 % aus, damit Logos im
     LAUFEN weich hinein- und hinausgleiten. Steht das Band still, waeren das
     erste und das letzte Logo dauerhaft halb durchsichtig — GEMESSEN bei 1440px
     reichen die 158 px Ueberblendung genau bis in „Vaillant" und
     „Talent Spring" hinein. */
  .logos-marquee:has(.logos-mono){-webkit-mask-image:none;mask-image:none}
}

/* ---------- Kundenband (statisch, ohne Laufband) ---------------------------
   Ruhige Reihe Kundenlogos innerhalb einer bestehenden Sektion — auf
   compliance.html unter der Kundenstimme. Zentral, weil compliance.html und
   compliance-neu.html in der Basislinie stehen und jede neue Inline-Regel dort
   Regel 2 ausloest. Die Hoehe steht wie beim Laufband inline am Bild. */
.kundenband{margin-top:clamp(28px,3.4vw,44px);padding-top:clamp(22px,2.6vw,32px);
  border-top:1px solid var(--line-soft)}
.kundenband-cap{text-align:center;color:var(--muted-readable);font-size:14px;margin:0 0 18px}
.kundenband-reihe{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:clamp(22px,3vw,46px)}
.kundenband-reihe img{flex:none;display:block;width:auto;object-fit:contain}

/* ---- 24. Fließende Inhaltsbreite (28.08.2026) ------------------------------
   ANLASS: Patrick — „unser inhalt ist immer so dünn auf großen bildschirmen …
   bezogen auf die breite will ich es genauso wie bei tacto haben". GEMESSEN auf
   tacto.ai: EIN Container mit max-width 1920px und einem Polster von rund
   4,25 % der Containerbreite.
     1440px Fenster   Polster 60,95px  →  Inhalt 1318px   92 %
     1920px Fenster   Polster 81,52px  →  Inhalt 1757px   92 %
     2560px Fenster   Container bei 1920 gedeckelt  →  1757px   69 %
     3440px Fenster                                     1757px   51 %
   Effektiv `min(91.5vw, 1757px)` — genau das steht unten. Kopf und Inhalt
   liegen bei Tacto im SELBEN Container (gemessen beide 1757px), deshalb zieht
   die Regel die Kopfzeile mit.

   UNSER STAND DAVOR bei 2560px: Inhalt 1200px (47 %) bzw. 1400px (55 %),
   Kopfzeile 1920px, Logo 328px LINKS neben der Inhaltsspalte.

   ⚠ WARUM EINE KLASSE UND NICHT DER TOKEN --wrap. Weil der Token nicht
   durchkommt: 14 Seiten deklarieren `.wrap{max-width:1400px}` in einem
   <style>-Block NACH base.css und schlagen damit `.wrap{max-width:var(--wrap)}`
   bei gleicher Spezifität (0,1,0). Erst `body.breite-fliessend .wrap` (0,2,1)
   gewinnt gegen beide. (Auf 4 der 18 Seiten mit 1400px stand die Regel VOR
   base.css und war toter Code — gerendert lagen dort 1200px an.)

   ⚠ ANTONIOS 1920er-DECKEL IST NICHT AUFGEHOBEN, sondern erfüllt. Sein Zweck
   war, dass der Kopf den Bezug zur Inhaltsspalte nicht verliert (§13 dieser
   Datei); hier bekommt er dieselbe Breite wie der Inhalt. Aus 328px Versatz
   wird 0. Die Regel braucht (0,3,1), weil `.nav-outer .wrap` (0,2,0) ist.

   ⚠ WAS DIESE REGEL NICHT LÖST: der Container wird breit, der Inhalt DARIN
   bleibt schmal. Gemessen bei 2560px sind die inneren Deckel .sec-head 780px,
   .lead 721px, h2 656px. Bei 15px Schrift laufen die Zeilen dort schon auf
   ~104 Zeichen; sie einfach zu weiten macht sie unlesbar. Tactos 1283px-
   Textspalte funktioniert, weil die Schrift mitwächst: 16px bei 1440 auf 22px
   ab 1920. Das ist die zweite Hälfte ihrer Mechanik und eine eigene
   Entscheidung. */
/* ⚠ EINZELWERTE, KEINE KURZSCHREIBWEISE. Hier stand `padding:0 32px`, und das
   war ein stiller Eingriff in 30 Abschnitte auf 18 Seiten: die Kurzform setzt
   auch oben und unten auf 0 und loescht damit jedes senkrechte Polster, das
   ein .wrap selbst mitbringt. Gemessen reichte das von 56px (.news) bis 130px
   (.cta auf ueber-uns). Sichtbar wurde es auf presse.html, wo die Hero-Knoepfe
   dadurch mit 0px Luft exakt auf der Naht zum hellen Abschnitt standen —
   .hero .wrap fuehrt dort 72px 24px 60px, und beides war weg.
   Spezifitaet ist bei beiden 0,2,0; components.css laedt nach dem Seiten-CSS
   und gewinnt deshalb. Diese Regel ist fuer Breite und seitliche Rinne
   zustaendig, nicht fuer die Hoehe — also nur die zwei Achsen setzen, die
   sie meint. */
body.breite-fliessend .wrap{max-width:min(91.5vw,1757px);margin:0 auto;
  padding-left:32px;padding-right:32px}
body.breite-fliessend .nav-outer .wrap{max-width:min(91.5vw,1757px);padding:0 32px}
@media (max-width:1280px){
  /* ⚠ Auch hier Einzelwerte, gleicher Grund wie oben: die Kurzform hat das
     senkrechte Polster der Heroes bis 1280px geloescht. Auf presse.html
     standen die Knoepfe dadurch bei 390px weiterhin auf der Naht, obwohl die
     Regel darueber schon korrigiert war. Der Nav-Balken braucht seine 0 oben
     und unten weiterhin — die holt er sich aus seiner eigenen Regel
     (body.breite-fliessend .nav-outer .wrap, 0,3,0), nicht von hier. */
  body.breite-fliessend .wrap,
  body.breite-fliessend .nav-outer .wrap{padding-left:24px;padding-right:24px}
}

/* ---- 25. Platinen-Hintergrund der Produktseiten (28.08.2026) ---------------
   Löst den Nebel auf den Produktseiten ab. Grund ist ein STANDBILD
   (assets/hero/hero-platine.webp), die Bewegung kommt aus Impulsen, die über
   die GEMESSENEN Leiterbahnen des Bildes laufen. Markup baut src/js/nebel.js,
   die Geometrie steht dort als Zahlenfeld; Nachweis in kontrolle-bahnen.html,
   die vollständige Herleitung in demo-hero-platine.html.

   WEG DAHIN, weil jeder Schritt eine Messung war und die ersten drei falsch:
     1 Lichtstreifen (color-dodge) über dem Standbild → „die Elemente bewegen
       sich nicht"
     2 Bild in Frequenzebenen zerlegt und die Ebenen bewegt → gemessen 2,13 von
       255 Bild-zu-Bild-Unterschied, Helligkeit +21 %, Kantenenergie −16 %:
       heller, weicher, praktisch unbewegt
     3 Impulse auf 6 Bahnen, davon einige neben der Bahn (bis 4 px Versatz) und
       zwei im Dunkeln schwebend
     4 21 nachgezogene Bahnen, Versatz im Median ≤ 1 px, 28 Impulse,
       21 blinkende Kontakte, 7 Bauteil-Glimmer
     5 HIER: Kontakte wieder entfernt, Tempo auf 0,3 und Sättigung auf 1,65 —
       einheitlich für alle vier Produkte (Patrick, 28.08.2026)

   ⚠ KONTRAST UND SÄTTIGUNG SIND DER HEBEL GEGEN DEN DUNST, nicht die Farbe.
   Gemessen, Anteil der Fläche im Dunstband (Luminanz 12–45):
     Nebel-Hero (workforce, alt)   80,9 %   Streuung 26,6   Akzent S0,42
     Platine ohne Anhebung         28,2 %   Streuung 35,8   Akzent S0,51
     Platine mit contrast/saturate  9,4 %   Streuung 36,4   Akzent S0,96
   Beides als Regler: --pl-kontrast (1.45) und --pl-satt (1.65 — Patricks Wert
   fuer alle vier Produkte, 28.08.2026).

   ⚠ DIE TÖNUNG IST PFLICHT, KEINE DEKO. Ohne sie ist die linke Hälfte reines
   Schwarz — gemessen Helligkeit 2,8 gegen 16 bis 17 bei den Nebel-Heroes, bei
   77,5 % völlig schwarzen Pixeln. Der Text stand in einem Loch. Das Bild ist
   deckend, ein Verlauf DARUNTER kommt nie durch; die Tönung liegt deshalb
   darüber und wird vom Produktfilter mitgedreht.

   ⚠ --hero-navschutz GEHÖRT HIER AUF 0. Auf dem Nebelbild schützt das Band die
   Navigation, auf der Platine hellt es nur reines Schwarz auf und ist eine
   Nebelquelle: 22,2 % Dunstanteil mit, 9,5 % ohne. Und die Nav wird dabei
   besser, nicht schlechter — Menüwörter gemessen 18,58:1 → 21,00:1, weil
   unter ihnen die Platine schwarz ist. */
.pl-hero{background:#000; --hero-navschutz:0}
.pl-grund,.pl-tint,.pl-bewegung,.pl-schutz{position:absolute;inset:0;pointer-events:none}
.pl-grund{z-index:0;background:url(../../assets/hero/hero-platine.webp) right center/cover no-repeat}
/* Tönung: weicher Schein links, damit die Textspalte kein Loch ist. */
/* ⚠ 0,3 IST GEMESSEN, NICHT GESCHAETZT — es ist der Kompromiss zwischen zwei
   Rueckmeldungen, die gegeneinander stehen („linke Seite zu dunkel" und „zu
   neblig"). Linke Bildhaelfte / Dunstanteil des ganzen Heros auf
   workforce.html bei 1440px:
     0     H  0,1   99,9 % schwarz    Dunst  9,5 %   ← das Loch
     0,2   H  3,8   99,8 % schwarz    Dunst  9,7 %   ← wirkt noch nicht
     0,3   H  5,6   93,9 % schwarz    Dunst 12,4 %   ← gewaehlt
     0,4   H  7,4   80,0 % schwarz    Dunst 18,8 %
     0,62  H 11,5   56,1 % schwarz    Dunst 29,7 %
   Nebel-Hero zum Vergleich: H 16 und 80,9 % Dunst. */
.pl-tint{z-index:0;mix-blend-mode:screen;
  background:radial-gradient(115% 95% at 6% 52%,
    rgba(10,78,71,var(--pl-tint,.3)) 0,
    rgba(8,48,43,calc(var(--pl-tint,.3) * .5)) 44%, transparent 74%)}
.pl-bewegung{z-index:1}
.pl-impulse{position:absolute;inset:0;width:100%;height:100%;display:block;
  mix-blend-mode:screen;
  /* Flächenrelativer Rand. GEMESSEN ohne ihn: ein Impuls kreuzte die
     Überschrift, schlechtester Moment 1,67:1 gegen Weiß. Mit Rand 10,20:1.
     Verlauf statt Datei — nur externe Dateien unterliegen CORS. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,
    transparent calc(var(--pl-rand,62%) - 16%),#000 var(--pl-rand,62%));
          mask-image:linear-gradient(90deg,transparent 0,
    transparent calc(var(--pl-rand,62%) - 16%),#000 var(--pl-rand,62%))}
.pl-impulse .spur{stroke:rgba(82,239,186,var(--pl-spur,.10));stroke-width:1.2}
.pl-impulse .imp{stroke:#CFFFF0;stroke-width:2.8;stroke-linecap:round;
  stroke-dasharray:38 4000;
  filter:drop-shadow(0 0 4px rgba(82,239,186,.95));
  animation-name:pl-lauf;animation-timing-function:linear;
  animation-iteration-count:infinite}
@keyframes pl-lauf{from{stroke-dashoffset:38px} to{stroke-dashoffset:calc(-1px * var(--len))}}
.pl-teile{position:absolute;inset:0;pointer-events:none;mix-blend-mode:screen}
.pl-teile i{position:absolute;left:var(--tx);top:var(--ty);
  width:calc(var(--tr) * 2);aspect-ratio:1;transform:translate(-50%,-50%);border-radius:50%;
  background:radial-gradient(circle,rgba(82,239,186,.34),rgba(82,239,186,.09) 45%,transparent 72%);
  animation-name:pl-teil;animation-timing-function:ease-in-out;
  animation-iteration-count:infinite;animation-direction:alternate}
@keyframes pl-teil{from{opacity:.12;transform:translate(-50%,-50%) scale(.8)}
                   to  {opacity:1;  transform:translate(-50%,-50%) scale(1.18)}}
/* ⚠ z-index 2, NICHT 3 — und das war ein echter Fehler, keine Feinheit.
   Mit 3 lag dieser Verlauf UEBER dem .wrap (z-index 2 in den Seitenstilen) und
   damit ueber der Schrift, die er schuetzen soll. Patrick am 29.08.2026: „schau
   dir bitte noch an warum die schrift links so ausgegraut ist, bzw so dunkel".
   Gemessen als tatsaechlich gerasterter Bildpunkt, nicht als Sollfarbe:
     Marke      soll #52EFBA          war rgb(61,178,139)    K  7,51:1
     Untertitel soll #FFF bei 88 %    war rgb(170,170,170)   K  8,51:1
     pax-ai, schlechtester Fall       war rgb(53,154,120)    K  5,83:1
   Mit dem Verlauf unter dem Text trifft die Marke ihren Tokenwert exakt und
   der Kontrast steigt auf 12,9 bis 13,5:1. Der Verlauf tut weiter genau das,
   wofuer er da ist: er dunkelt das BILD hinter dem Text ab.
   Die Stapelfolge lautet damit Grund 0 · Toenung 0 · Bewegung 1 · Schutz 2 ·
   Inhalt 3. Die 3 fuer den Inhalt setzt die Regel darunter zentral — die vier
   Seitenstile fuehren alle .ihero .wrap mit z-index 2, gleiche Spezifitaet,
   und components.css wird spaeter geladen. */
.pl-schutz{z-index:2;
  background:linear-gradient(100deg,
    rgba(0,0,0,var(--pl-schutz,.5)) 0,
    rgba(0,0,0,calc(var(--pl-schutz,.5) * .45)) 40%, transparent 64%)}
.pl-hero .wrap{z-index:3}

/* Produktfarben. Die Filter laufen über Grund, Tönung, Bewegung UND Glimmer —
   eine grüne Bahn unter violettem Grund wäre sofort zu sehen. Gemessener
   Farbton im rechten Bildteil in Klammern; Tender trifft Brand-Orange
   #FE5E00 (22°), Pax AI das AI-Violett #6025E1 (259°). */
/* -- Kreisbogen-Heros je Produkt (Patrick, 01.09.2026) --
   Drei fertige Bilder aus dem Ordner „Pactos Hero-Bilder": gleiches Motiv
   (konzentrische Kreisbögen mit Glow), die Marken-Farbe ist JE DATEI gebacken.
   Sie ersetzen den Platinen-Grund auf VMS, Compliance und Tender. Pax AI bleibt
   auf der Platine — so liefert es die README des Ordners ausdrücklich.
   ⚠ KEIN FILTER MEHR AUF DIESEN DREI. Die `hue-rotate`-Kette darunter färbte
   EIN Bild in vier Tönen; jetzt bringt jede Datei ihren Ton mit, und ein
   Filter darüber würde ihn ein zweites Mal verdrehen.
   ⚠ DIE IMPULSE SIND HIER AUS. `src/js/nebel.js` zeichnet sie auf den
   GEMESSENEN Leiterbahnen der Platine (assets/hero/hero-platine-bahnen.json).
   Über Kreisbögen liefen Lichtpunkte auf unsichtbaren Linien. Wer sie
   zurückholen will, braucht Bahnen zum neuen Motiv — nicht nur die Klasse. */
.pl-hero[data-nebel-produkt="vms"] .pl-grund{
  background-image:url(../../assets/hero/hero-kreise-vms.webp)}
.pl-hero[data-nebel-produkt="compliance"] .pl-grund{
  background-image:url(../../assets/hero/hero-kreise-compliance.webp)}
.pl-hero[data-nebel-produkt="tender"] .pl-grund{
  background-image:url(../../assets/hero/hero-kreise-tender.webp)}

.pl-hero .pl-grund,.pl-hero .pl-tint,.pl-hero .pl-bewegung{
  filter:saturate(var(--pl-satt,1.65)) contrast(var(--pl-kontrast,1.45))
         brightness(var(--pl-kraft,1))}                                    /* vms 152° S0,96 */
.pl-hero[data-nebel-produkt="compliance"] .pl-grund,
.pl-hero[data-nebel-produkt="compliance"] .pl-tint,
.pl-hero[data-nebel-produkt="compliance"] .pl-bewegung{
  /* brightness(.85) vor dem Regler: Compliance war im Haus das dunklere Grün
     (nebel.css). Ohne das ist es von VMS nicht zu unterscheiden. */
  filter:hue-rotate(-8deg) saturate(var(--pl-satt,1.65)) contrast(var(--pl-kontrast,1.45))
         brightness(.85) brightness(var(--pl-kraft,1))}                    /* 143° S0,96 */
.pl-hero[data-nebel-produkt="tender"] .pl-grund,
.pl-hero[data-nebel-produkt="tender"] .pl-tint,
.pl-hero[data-nebel-produkt="tender"] .pl-bewegung{
  filter:hue-rotate(-123deg) saturate(var(--pl-satt,1.65)) contrast(var(--pl-kontrast,1.45))
         brightness(var(--pl-kraft,1))}                                    /* 22° S0,90 */
.pl-hero[data-nebel-produkt="pax-ai"] .pl-grund,
.pl-hero[data-nebel-produkt="pax-ai"] .pl-tint,
.pl-hero[data-nebel-produkt="pax-ai"] .pl-bewegung{
  filter:hue-rotate(112deg) saturate(var(--pl-satt,1.65)) contrast(var(--pl-kontrast,1.45))
         brightness(var(--pl-kraft,1))}                                    /* 259° S0,69 */

/* ⚠ DIESER BLOCK MUSS HINTER DEN VIER FILTERREGELN STEHEN. Er hat dieselbe
   Spezifitaet wie sie; davor stehend verlor er lautlos, und Tender kam mit
   hue-rotate(-123deg) auf einem ORANGEN Bild heraus — gemessen violett,
   rgb(78,48,153) hinter der Textspalte. */
.pl-hero[data-nebel-produkt="vms"] .pl-grund,
.pl-hero[data-nebel-produkt="vms"] .pl-tint,
.pl-hero[data-nebel-produkt="compliance"] .pl-grund,
.pl-hero[data-nebel-produkt="compliance"] .pl-tint,
.pl-hero[data-nebel-produkt="tender"] .pl-grund,
.pl-hero[data-nebel-produkt="tender"] .pl-tint{filter:none}
.pl-hero[data-nebel-produkt="vms"] .pl-bewegung,
.pl-hero[data-nebel-produkt="compliance"] .pl-bewegung,
.pl-hero[data-nebel-produkt="tender"] .pl-bewegung{display:none}
/* ⚠ Der linke Schein bleibt, sonst ist die Textspalte ein Loch (0,3 ist dort
   gemessen). Auf Tender wird er orange: ein grüner Schein neben orangen Bögen
   ist ein Farbfehler, kein Akzent. */
.pl-hero[data-nebel-produkt="tender"] .pl-tint{
  background:radial-gradient(115% 95% at 6% 52%,
    rgba(254,94,0,calc(var(--pl-tint,.3) * .55)) 0,
    rgba(154,57,0,calc(var(--pl-tint,.3) * .28)) 44%, transparent 74%)}

@media (prefers-reduced-motion:reduce){
  .pl-impulse .imp,.pl-teile i{animation:none !important}
  .pl-impulse .imp{stroke-dasharray:none;opacity:.34}
  .pl-teile i{opacity:.5;transform:translate(-50%,-50%)}
}

/* ---- 26. Hero in drei Stufen: Standbild, Einflug, Inhalt (29.08.2026) -------
   Patricks Bild: „Man ruft die Seite auf und es ist einfach der Titel mit dem
   Hintergrundbild. Dann wenn man scrollt fliegt von unten die Animation ins
   Bild ein der rest bleibt stehen. Dann scrollt man weiter und dann kommt der
   Inhalt."

   Drei Stufen, EIN Regler: --pl-auf laeuft von 0 bis 1 und wird von
   src/js/nebel.js aus der Scrollstrecke gesetzt.
     Stufe 1  --pl-auf 0   Titel + Standbild. Nichts bewegt sich.
     Stufe 2  0 → 1        Impulse und Dashboard fliegen von unten ein, der
                           Hero selbst steht (position:sticky).
     Stufe 3  --pl-auf 1   Der Pin loest, der Inhalt schiebt den Hero hoch.

   WARUM EIN WRAPPER (.pl-bahn) UND NICHT DER HERO SELBST: ein sticky-Element
   klebt nur innerhalb seines Elternelements. Der Hero soll seine Hoehe von
   100svh behalten UND kleben — also traegt die Bahn die Scrollstrecke
   (100svh + --pl-pin) und der Hero klebt darin. Alle Regeln aus Abschnitt 25
   bleiben dadurch unberuehrt.

   ⚠ DIE ZUSATZHOEHE HAENGT AN html.js — der Klasse, die partials/header.html
   noch vor dem Nav-Markup setzt. Ohne Skript gibt es keinen Fortschritt, und
   dann darf es auch keine leere Scrollstrecke geben: --pl-auf bleibt auf 1,
   die Bahn behaelt ihre natuerliche Hoehe, die Seite ist die alte.

   ⚠ DER EINFLUG DER IMPULSE IST EINE MASKE, KEINE VERSCHIEBUNG. Die 21 Bahnen
   liegen pixelgenau auf den Leiterbahnen des Standbildes (Abschnitt 25, Median
   ≤ 1 px). Sie um 18vh zu verschieben haette sie waehrend des Fluges NEBEN den
   Leiterbahnen laufen lassen — genau das „messy" aus der zweiten Fassung. Die
   Maske gibt die Flaeche von unten nach oben frei, die Bahnen bleiben liegen.

   ⚠ MOBIL UND BEI prefers-reduced-motion GIBT ES KEINEN PIN. Die Entscheidung
   faellt in nebel.js (Grenze 900 px, dieselbe wie der Einspalter-Umbruch des
   Heros in workforce.html), NICHT hier: --pl-auf wird dort als Inline-Stil
   gesetzt, und ein Inline-Stil schlaegt jede Medienabfrage in dieser Datei. */
.pl-bahn{position:relative}
.pl-pin{--pl-auf:1;--pl-rest:calc(1 - var(--pl-auf))}
html.js .pl-pin{--pl-auf:0}
html.js .pl-bahn.hat-pin{min-height:calc(100svh + var(--pl-pin,88vh))}
html.js .pl-bahn.hat-pin .pl-pin{position:sticky;top:0}

/* Impulse, Spuren und Bauteil-Glimmer werden von unten freigelegt.
   ⚠ Der untere Anschlag ist NEGATIV (-14 %), damit bei --pl-auf 0 wirklich
   nichts stehen bleibt: mit 0 als erstem Halt waere der unterste Bildpunkt
   deckend und darueber laege ein 14 % hohes Verlaufsband — gemessen als
   sichtbarer Mintstreifen am unteren Rand. Oben laeuft das Fenster auf 118 %,
   damit die weiche Kante am Ende ganz aus dem Bild ist. */
.pl-pin .pl-bewegung{
  --pl-kante:calc(var(--pl-auf) * 132% - 14%);
  -webkit-mask-image:linear-gradient(0deg,#000 0,#000 var(--pl-kante),
    transparent calc(var(--pl-kante) + 14%));
          mask-image:linear-gradient(0deg,#000 0,#000 var(--pl-kante),
    transparent calc(var(--pl-kante) + 14%))}

/* Das Dashboard wird nicht aufgedeckt, es fliegt: es ist ein Objekt AUF dem
   Bild, kein Teil des Bildes. Abgeschnitten wird es vom overflow:hidden des
   Heros.
   ⚠ 52 % + 52svh, kein fester Prozentwert: die Buehne steht mittig, ihre
   Unterkante liegt also bei (Hero + Buehne) / 2. Der Weg nach unten muss
   deshalb die halbe Buehnenhoehe UND die halbe Herohoehe enthalten — mit einem
   festen Prozentwert haengt bei flachen Fenstern ein Streifen im Bild und bei
   hohen fliegt sie unnoetig weit. Die 2 % sind Luft fuer den Schatten. */
.pl-pin .zb-buehne{transform:translateY(calc((52% + 52svh) * var(--pl-rest)))}

/* Stufe 1 ist WIRKLICH still. Ohne das laeuft die Runde des Dashboards
   unsichtbar mit, und der Einflug faengt mitten in einer Karte an.
   Namentlich aufgezaehlt statt einem Stern hinter .pl-ruht — der Hero traegt
   auch Elemente, deren Bewegung nichts mit dieser Buehne zu tun hat.
   ⚠ html.js DAVOR. Die Klasse pl-ruht steht im Markup, damit der erste
   Rahmen schon ruhig ist (nebel.js laeuft mit defer). Ohne Skript nimmt sie
   aber nie wieder jemand weg — dann stand das Dashboard fuer immer still,
   gemessen als ruht:true bei abgeschaltetem JavaScript. Die Pause gilt
   deshalb nur dort, wo es auch ein Skript gibt, das sie wieder aufhebt. */
html.js .pl-ruht .pl-impulse .imp,
html.js .pl-ruht .pl-teile i,
html.js .pl-ruht .zb-karte,
html.js .pl-ruht .zb-karte::after,
html.js .pl-ruht .zb-skelett,
html.js .pl-ruht .zb-inhalt{animation-play-state:paused}

/* ---- 27. Diagramme im Produktfenster des Heros (28.08.2026) ----------------
   Zwei Bausteine für die Kästchen der Hero-Animation: ein Flächendiagramm und
   ein Ring. Sie stammen aus dem Vorbild der alten Website (Lottie, dort als
   Dashboardkarten „Time To Fill" und ein Ring mit Legende) und stehen jetzt in
   der letzten Phase, den Auswertungen.
   ⚠ Zentral und nicht inline: die Startseite hatte vor dem 28.08. keinen
   Regel-2-Fehler, und inline waren es gemessen +684 Zeichen.
   ⚠ Kurz lag daraus eine gedimmte GRUNDSCHICHT hinter der ganzen Szene. Die ist
   wieder weg — sie war als Erklärung gedacht, gewollt waren größere Kästchen. */
.fl-kurve { flex: 1; min-height: 4.5em; width: 100%; display: block; }
.fl-kurve .fl-flaeche { fill: var(--tech-tint); }
.fl-kurve .fl-linie { fill: none; stroke: var(--tech); stroke-width: 2; }
.fl-ringfeld { display: flex; align-items: center; gap: 1.1em; }
.fl-ringfeld svg { width: 6.5em; flex: none; transform: rotate(-90deg); }
.fl-ringfeld circle { fill: none; stroke-width: 7; }
/* Drei Segmente auf einem Umfang von 100: 58 / 26 / 16. */
.fl-ringfeld .fl-r1 { stroke: var(--green-800); stroke-dasharray: 58 42; }
.fl-ringfeld .fl-r2 { stroke: var(--tech); stroke-dasharray: 26 74; stroke-dashoffset: -58; }
.fl-ringfeld .fl-r3 { stroke: var(--tech-soft); stroke-dasharray: 16 84; stroke-dashoffset: -84; }
/* ⚠ FARBE UND GRAD AUSDRUECKLICH. Der Hero setzt weisse Schrift, und die erbt
   bis in den Screen: gemessen stand die Legende in rgb(255,255,255) auf weissem
   Grund, also unsichtbar — und in 25,5 px, dem vollen Grad der Szene. */
.fl-ringliste { display: flex; flex-direction: column; gap: .5em; min-width: 0;
  font-size: .78em; color: var(--ink-soft); }
.fl-ringliste span { display: flex; align-items: center; gap: .5em; white-space: nowrap; }
.fl-ringliste i { width: .62em; height: .62em; border-radius: 50%; flex: none; }
.fl-ringliste span:nth-child(1) i { background: var(--green-800); }
.fl-ringliste span:nth-child(2) i { background: var(--tech); }
.fl-ringliste span:nth-child(3) i { background: var(--tech-soft); }

/* ---- 27. Produktkreis der Startseite (31.08.2026) --------------------------
   Ersetzt das erste der zwei Bento-Raster: die Startseite fuehrte .prod-raster
   fuer die Produkte UND .bran fuer die Branchen, zweimal dieselbe Bauform auf
   einer Seite (Patrick, 31.08.2026).

   Vorbild ist der Merge-Ring aus schnittstellen.html — Nabe in der Mitte,
   Speichen nach aussen, ein Fenster in der Mitte. Uebernommen ist die Geometrie,
   neu sind die Drehung, der Nebel und die vier Produktfarben.

   Erarbeitet und gemessen in proben/demo-produktkreis.html; dort stehen auch
   die Regler und die vier verworfenen Fassungen. Diese Datei traegt nur, was
   sich bewaehrt hat.
   ============================================================================ */
/* ---- Der Kreis
   GEOMETRIE wie beim Schnittstellen-Orb: jeder Arm beginnt im Mittelpunkt
   (left/top 50 %, transform-origin 0 0) und ist um `--w` gedreht; die Plakette
   hängt am Armende und dreht sich um `calc(var(--w) * -1)` zurück, damit die
   Schrift waagerecht steht. Keine Koordinate wird von Hand gerechnet.

   ⚠ DREI VERSCHACHTELTE ELEMENTE FÜR DREI DREHUNGEN, und das ist kein
   Aufräumbedarf: eine `animation` auf `transform` ERSETZT die statische
   `transform` desselben Elements. Wer Kreisen und Zurückdrehen auf ein Element
   legt, verliert eine der beiden. Deshalb trägt jede Ebene genau eine Aufgabe:
     .pk-lauf    dreht den ganzen Ring          (Animation)
     .pk-arm     Winkel der Speiche             (statisch)
     .pk-spitze  sitzt auf der Armspitze        (statisch)
     .pk-halter  dreht gegen den Ring zurück    (Animation)
     .pk-knopf   dreht den Armwinkel zurück     (statisch)
   Ring und Gegendrehung laufen beide `linear`, `infinite` und gleich lang und
   starten zusammen — damit bleiben sie verkoppelt und die Schrift steht. Wer
   eine der beiden Dauern ändert, muss die andere mitziehen. */
/* ⚠ overflow-x:clip GEGEN DEN NEBEL. Der Nebel traegt inset:-16 %, ist beim
   700-px-Kreis also 924 px breit. Wo der Inhaltsbereich schmaler ist, schob er
   die Seite waagerecht heraus: gemessen 12 px bei 900 px Fenster. Clip statt
   hidden, damit senkrecht nichts abgeschnitten wird (hidden wuerde beide Achsen
   zu Scrollbereichen machen). Beschnitten wird nur, WO es sonst ueberliefe —
   bei 1440 px ist der Bereich 1254 px breit, da bleibt der Hof unangetastet.
   Der Nebel ist Zierde und pointer-events:none; ein paar Pixel weniger Hof sind
   kein Verlust, eine waagerecht scrollende Startseite schon. */
.pk-feld { display: grid; place-items: center; overflow-x: clip; }

/* ---- Der Nebel ----------------------------------------------------------
   Patrick: „haette es so gewollt dass der ganze kreis einfach dann so einen
   Hintergrundnebel in der Farbe des Produkts hat wenn man drueber hovert".
   Liegt als erstes Kind ganz unten im Stapel, reicht ueber den Kreis hinaus
   und faerbt sich ueber --pk-akzent mit — eine Ebene, vier Farben.
   ⚠ NUR opacity WIRD ANIMIERT (DESIGN.md §5). Kein blur(): ein weicher
   Radialverlauf liest sich als Nebel und kostet keinen Filterdurchgang, den
   der Browser bei jedem Bild neu rechnen muesste.
   ⚠ Im Ruhezustand unsichtbar. Der Nebel ist die Antwort auf das Annaehern,
   nicht Dauerzustand — sonst ist die Sektion permanent gruen getoent und die
   Farbe sagt nichts mehr aus. */
.pk-nebel { position: absolute; inset: -16%; z-index: 0; border-radius: 50%;
  pointer-events: none; opacity: 0;
  background: radial-gradient(circle at 50% 50%,
    color-mix(in srgb, var(--pk-akzent) calc(32% * var(--pk-nebel)), transparent) 0,
    color-mix(in srgb, var(--pk-akzent) calc(17% * var(--pk-nebel)), transparent) 38%,
    color-mix(in srgb, var(--pk-akzent) calc(6% * var(--pk-nebel)), transparent) 60%,
    transparent 76%);
  transition: opacity .38s var(--ease-out); }
.pk-kreis:has(.pk-knopf:hover) .pk-nebel,
.pk-kreis.ist-offen .pk-nebel { opacity: 1 }
.pk-kreis { position: relative; width: 100%; max-width: 700px; aspect-ratio: 1;
  container-type: inline-size;
  /* Grundfarbe der Grafik: Markengrün. Auf Weiß gemessen 9,57:1 als Linie. */
  --pk-akzent: var(--green-800);
  --pk-auf: #fff;                 /* Schrift auf einer Fläche in --pk-akzent */
  --pk-dauer: 48s;
  --pk-nebel: .5; }       /* Nebelstaerke. 0,5 ist Patricks Wahl vom 31.08.2026 */

/* Zwei ruhige Ringe als Feld. Zierde, deshalb aria-hidden im Markup.
   Sie nehmen die Produktfarbe mit an — „die Grafik nimmt die Farbe an" heißt
   nicht nur die Plakette. */
.pk-hof { position: absolute; inset: 9%; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--pk-akzent) 22%, transparent);
  /* opacity: die Ringe fahren beim Landen mit ein (Abschnitt 30). */
  transition: border-color .32s var(--ease-out), opacity .45s var(--ease-out); }
.pk-hof::before { content: ""; position: absolute; inset: 19%; border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--pk-akzent) 16%, transparent); }

.pk-nabe { position: absolute; left: 50%; top: 50%; z-index: 2;
  transform: translate(-50%, -50%); width: 27%; aspect-ratio: 1; border-radius: 50%;
  /* ⚠ GEFUELLTE SCHEIBE, NICHT WEISS MIT RAND. Erste Fassung war eine weisse
     Scheibe mit der dunkelgruenen Marke darauf — auf hellem Grund verschwand
     sie fast in der Seite. Patrick zweimal: „fehlt ja noch das Pactos Logo"
     und dann „das Logo fehlt immer noch wie es auf der Schnittstellen Seite
     drin ist". Gegenuebergestellt war die Groesse gar nicht der Unterschied
     (dort 11,3 % des Kreises, hier 11,0 %), sondern die Behandlung: dort eine
     gefuellte Scheibe in --grad-fresh mit weissem Logo, also ein Abzeichen.
     Genau das steht jetzt hier. */
  background: var(--grad-fresh);
  border: 1px solid color-mix(in srgb, var(--tech) 30%, transparent);
  box-shadow: 0 0 0 12px color-mix(in srgb, var(--pk-akzent) 7%, transparent), var(--shadow-m);
  display: grid; place-content: center; justify-items: center; gap: 6px;
  /* ⚠ `opacity 0s` GEHOERT ZUM LOGOFLUG (Abschnitt 30): beim Landen geht die
     Nabe OHNE Uebergang auf 1, danach blendet der Flugkreis darueber weg. Zwei
     halbdurchsichtige gruene Scheiben liessen in der Mitte der Blende den Grund
     durch. Steht hier und nicht dort, damit box-shadow nicht doppelt gepflegt
     werden muss — eine kurze zweite Liste haette ihn geloescht. */
  transition: box-shadow .32s var(--ease-out), opacity 0s; }
/* ⚠ DIE NABE BLEIBT PACTOS-GRUEN, sie nimmt die Produktfarbe NICHT an — und das
   ist eine Korrektur an meiner ersten Fassung. Zwei Gruende:
     · Es ist die Marke. Ein Logo, das je Produkt die Farbe wechselt, ist keine
       Marke mehr. Auf der Schnittstellen-Seite ist die Nabe aus demselben Grund
       immer gruen.
     · Gemessen: die weisse Wortmarke „Pactos" auf Orange ist 3,08:1 und faellt
       durch. Auf einer mitfaerbenden Nabe braeuchte Tender eine Sonderregel.
   Die Farbe tragen Nebel, Ringe, Speichen, Plakette und Film — das ist reichlich.
   Nur der weiche Ring um die Nabe (box-shadow) faerbt mit, damit sie nicht wie
   ausgeschnitten in der farbigen Flaeche sitzt. */
/* ⚠ WIEDER EIN <img>, KEINE MASKE. Meine erste Fassung war eine CSS-Maske mit
   der Begruendung, ein Bild koenne die Produktfarbe nicht annehmen. Das stimmt,
   ist hier aber gegenstandslos, seit die Nabe konstant gruen ist — und die
   Maske hatte einen Preis: pactos-mark-white.svg hat ZWEI Toene (weiss und
   Mint im unteren Blatt), eine Maske nutzt nur den Alphakanal und haette beide
   zu einer Flaeche verschmolzen. */
.pk-nabe img { width: 11cqw; height: auto; display: block; }
.pk-nabe b { font-size: clamp(11px, 3cqw, 16px); font-weight: 500;
  letter-spacing: -.01em; color: var(--surface); }

.pk-lauf { position: absolute; inset: 0; animation: pk-dreh var(--pk-dauer) linear infinite; }
@keyframes pk-dreh { to { transform: rotate(360deg) } }

/* ⚠ 38 %, NICHT 34 %. Mit 34 % sitzen die Plaketten auf Radius 190 px — und
   „Pactos Compliance" ist 172 px breit, ragt also von der Mitte ihrer Position
   noch 86 px nach innen und landete damit im Fenster (gemessen: zwei von vier
   Plaketten verdeckt). Zwei Dinge zusammen loesen das: die Plaketten heissen
   jetzt nur noch VMS, Compliance, Tender und Pax AI — die Nabe sagt „Pactos",
   viermal wiederholt war es ohnehin redundant — und der Arm ist laenger. */
.pk-arm { position: absolute; left: 50%; top: 50%; width: 38%; height: 0;
  transform: rotate(var(--w)); transform-origin: 0 0; }
/* Im Uhrzeigersinn, beginnend oben. Reihenfolge ist die Produkthierarchie:
   das VMS trägt den Prozess, Compliance und Tender docken an, Pax AI arbeitet
   in allen mit. */
.pk-arm[data-produkt="vms"]        { --w: -90deg }
.pk-arm[data-produkt="compliance"] { --w: 0deg }
.pk-arm[data-produkt="tender"]     { --w: 90deg }
.pk-arm[data-produkt="pax-ai"]     { --w: 180deg }

.pk-bahn { position: absolute; left: 26%; right: 12%; top: -1px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--pk-akzent) 10%, transparent),
    color-mix(in srgb, var(--pk-akzent) 40%, transparent));
  transition: background .32s var(--ease-out); }

.pk-spitze { position: absolute; right: 0; top: 0; transform: translate(50%, -50%); }
/* ⚠ inline-block IST PFLICHT, NICHT KOSMETIK. .pk-halter ist ein <span>, also
   ein nicht-ersetztes Inline-Element — und darauf wirkt „transform" gar nicht,
   also auch keine Animation, die transform animiert. Ohne diese Zeile lief die
   Gegendrehung still ins Leere und die Plaketten kippten mit dem Ring mit:
   gemessen nach 3 s alle vier um 22° mitgedreht, die Schrift stand schräg.
   Der Nachbar .pk-spitze funktioniert nur deshalb, weil „position:absolute" ein
   Element ohnehin zum Block macht. */
.pk-halter { display: inline-block; animation: pk-gegen var(--pk-dauer) linear infinite; }
@keyframes pk-gegen { to { transform: rotate(-360deg) } }

.pk-knopf { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  transform: rotate(calc(var(--w) * -1));
  padding: 9px 15px; border-radius: var(--r-full); text-decoration: none;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font-size: clamp(11px, 2.8cqw, 14px); font-weight: 500; line-height: 1.2;
  box-shadow: var(--shadow-s); cursor: pointer;
  transition: background .22s var(--ease-out), border-color .22s var(--ease-out),
              color .22s var(--ease-out); }
.pk-knopf::before { content: ""; flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--pk-eigen); }
/* Jede Plakette trägt IHRE Farbe im Punkt, auch wenn der Kreis gerade grün ist —
   sonst sieht man erst beim Hovern, dass die Produkte verschiedene Farben haben. */
.pk-arm[data-produkt="vms"]        .pk-knopf { --pk-eigen: var(--green-800) }
.pk-arm[data-produkt="compliance"] .pk-knopf { --pk-eigen: var(--green-600) }
.pk-arm[data-produkt="tender"]     .pk-knopf { --pk-eigen: var(--orange) }
.pk-arm[data-produkt="pax-ai"]     .pk-knopf { --pk-eigen: var(--ai) }

/* Die aktive Plakette füllt sich in ihrer Farbe.
   ⚠ DIE SCHRIFTFARBE IST NICHT FÜR ALLE VIER DIESELBE, und das ist gemessen,
   nicht Geschmack. Kontrast auf der gefüllten Plakette:
                     weisse Schrift   dunkle Schrift   gewählt
     green-800 VMS         9,57:1           1,87:1     weiss
     green-600 Compl.      5,29:1           3,38:1     weiss
     orange    Tender      3,08:1           5,80:1     DUNKEL
     ai        Pax AI      7,37:1           2,42:1     weiss
   Weiss auf Orange fällt mit 3,08:1 durch. Deshalb liefert jedes Produkt neben
   --pk-akzent auch --pk-auf. */
.pk-arm.ist-aktiv .pk-knopf { background: var(--pk-akzent); border-color: var(--pk-akzent);
  color: var(--pk-auf); box-shadow: var(--shadow-m); }
.pk-arm.ist-aktiv .pk-knopf::before { background: var(--pk-auf) }
.pk-kreis.ist-offen .pk-arm:not(.ist-aktiv) { opacity: .45 }
.pk-arm { transition: opacity .25s var(--ease-out) }

/* ---- Produktfarben. Zwei Selektoren, eine Regel, ein Variablensatz.
   `:has(...:hover)` färbt ohne Skript, `[data-aktiv]` setzt das Skript für
   Tastatur und Touch. Beide schreiben denselben Wert, sie können also nicht
   auseinanderlaufen. */
.pk-kreis:has(.pk-arm[data-produkt="vms"] .pk-knopf:hover),
.pk-kreis[data-aktiv="vms"]        { --pk-akzent: var(--green-800); --pk-auf: #fff }
.pk-kreis:has(.pk-arm[data-produkt="compliance"] .pk-knopf:hover),
.pk-kreis[data-aktiv="compliance"] { --pk-akzent: var(--green-600); --pk-auf: #fff }
.pk-kreis:has(.pk-arm[data-produkt="tender"] .pk-knopf:hover),
.pk-kreis[data-aktiv="tender"]     { --pk-akzent: var(--orange);    --pk-auf: var(--ink) }
.pk-kreis:has(.pk-arm[data-produkt="pax-ai"] .pk-knopf:hover),
.pk-kreis[data-aktiv="pax-ai"]     { --pk-akzent: var(--ai);        --pk-auf: #fff }

/* ⚠ ANHALTEN BEIM ANNÄHERN, nicht erst beim Treffen. Ein Ziel, das sich bewegt,
   ist mit der Maus schwer zu fassen und mit eingeschränkter Motorik kaum. Der
   Kreis hält an, sobald der Zeiger irgendwo im Feld ist — dann steht das Ziel
   still, bevor man es erreicht. `focus-within` macht dasselbe für die Tastatur. */
.pk-kreis:hover .pk-lauf, .pk-kreis:hover .pk-halter,
.pk-kreis:focus-within .pk-lauf, .pk-kreis:focus-within .pk-halter,
.pk-kreis.ist-offen .pk-lauf, .pk-kreis.ist-offen .pk-halter { animation-play-state: paused }

/* ---------------------------------------------------------------- Das Fenster
   Liegt mittig über der Nabe wie beim Orb, Höhe nach Inhalt. */
/* ⚠ 24 % RAND, NICHT 6 %. Erste Fassung war so breit wie beim Schnittstellen-Orb
   (6 %) — dort trägt das Fenster aber nur Text, hier zusätzlich den Film. Bei
   560 px Kreis wurde es 490 px breit und deckte den Ring: gemessen war die
   Compliance-Plakette rechts angeschnitten und die VMS-Plakette oben halb
   verdeckt. Es sah aus wie eine Karte, die vor einem Kreis liegt, nicht wie ein
   Fenster, das sich in ihm öffnet.
   Mit 24 % sind es 291 px. Die Plaketten sitzen auf Radius 190 px, das Fenster
   reicht waagerecht bis 145 px und senkrecht bis rund 100 px — beides bleibt
   frei, der Ring bleibt lesbar. */
.pk-fenster { position: absolute; left: 24%; right: 24%; top: 50%; z-index: 3;
  transform: translateY(-50%);
  background: var(--surface); color: var(--ink); text-align: left;
  border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-overlay);
  padding: clamp(13px, 3.2cqw, 18px); display: grid; gap: 9px; }
.pk-fenster[hidden] { display: none }
/* ⚠ DER TITEL TRÄGT NICHT DIE PRODUKTFARBE, und das ist gemessen. Erste Fassung
   war „color: var(--pk-akzent)", weil es naheliegt. Auf Weiß:
     VMS 9,57:1 ✓ · Compliance 5,29:1 ✓ · Pax AI 7,37:1 ✓ · Tender 3,08:1 ✗
   Orange trägt als Linie und Fläche (3:1 reicht dort), als Schrift nicht. Ein
   dunkleres Orange gäbe es nur als neuen Hex-Wert, und das verbietet Leitregel 1.
   Eine Sonderregel nur für Tender wäre willkürlich — also tragen alle vier
   Titel --ink, und die Farbe steckt da, wo Patrick sie haben wollte: in der
   Grafik. Ring, Logo, Plakette und Film färben sich, der Text bleibt lesbar. */
.pk-fenster h3 { font-size: clamp(15px, 3.6cqw, 20px); line-height: 1.15; letter-spacing: -.02em;
  margin: 0; color: var(--ink); }
.pk-fenster p { font-size: clamp(12.5px, 2.9cqw, 15px); line-height: 1.55; margin: 0;
  color: var(--muted-readable); text-wrap: pretty; }
/* Aus demselben Grund die Sitefarbe für Links (base.css setzt sie ohnehin auf
   --green-600, 5,29:1) statt der Produktfarbe. */
.pk-mehr { display: inline-flex; align-items: center; gap: 7px; font-size: clamp(12px, 2.7cqw, 14px);
  font-weight: 600; color: var(--green-600); text-decoration: none; }
.pk-mehr svg { width: 15px; height: 15px }

/* ------------------------------------------------------- Das Bild im Fenster
   Patrick, 01.09.2026: „kannst du da eher die Hero-Bilder der jeweiligen
   Produkte einfügen?" — vorher lief hier ein „Film" aus drei Balken je Produkt
   (vier Varianten: kette, faecher, lesen). Dieselben Bilder wie im Hero der
   Produktseite, in der Menuekarte und auf der Preisseite: ein Motiv je Produkt,
   an vier Stellen dasselbe.
   ⚠ KEINE ZEILE JAVASCRIPT DAFUER. `src/js/produktkreis.js` setzt beim Oeffnen
   ohnehin `data-aktiv` auf den Kreis; die vier Regeln unten haengen daran. Der
   alte Film brauchte dagegen ein Attribut am Element und einen Reflow-Trick,
   damit die Animation von vorn lief — beides ist entfallen.
   ⚠ PAX AI HAT KEIN EIGENES MOTIV. Sein Hero und seine Menuekarte tragen die
   Platine, also traegt sein Fenster sie auch. Kommt ein eigenes Bild, hier und
   an den drei anderen Stellen eintragen.
   ⚠ Der Film kommt per `git revert` zurueck; die Herleitung steht unveraendert
   in proben/demo-produktkreis.html. */
.pk-schau { position: relative; aspect-ratio: 16 / 9; border-radius: var(--r-md);
  background: var(--green-900);
  border: 1px solid color-mix(in srgb, var(--pk-akzent) 18%, transparent);
  overflow: hidden;
  transition: border-color .32s var(--ease-out); }
/* ⚠ DAS BILD LIEGT IM ::before, NICHT AM ELEMENT. Pax AI braucht einen Filter
   (siehe unten); am Element hätte er den Rahmen mitgedreht, und der trägt die
   Produktfarbe aus --pk-akzent. */
.pk-schau::before { content: ""; position: absolute; inset: 0;
  background: center/cover no-repeat; }
.pk-kreis[data-aktiv="vms"] .pk-schau::before{
  background-image:url(../../assets/hero/hero-kreise-vms.webp)}
.pk-kreis[data-aktiv="compliance"] .pk-schau::before{
  background-image:url(../../assets/hero/hero-kreise-compliance.webp)}
.pk-kreis[data-aktiv="tender"] .pk-schau::before{
  background-image:url(../../assets/hero/hero-kreise-tender.webp)}
/* ⚠ PAX AI: PLATINE IN VIOLETT, NICHT IM ROHTON. Es hat kein eigenes Motiv, und
   die Platine liegt im Repo in Teal. Hero und Menükarte drehen sie seit dem
   28.08. mit derselben Kette auf Violett (components.css Abschnitt 25 und der
   Nav-Block); ohne sie stand hier ein grünes Bild unter einem violetten Punkt.
   Dieselben Werte, damit es an allen drei Stellen dieselbe Farbe ist. */
.pk-kreis[data-aktiv="pax-ai"] .pk-schau::before{
  background-image:url(../../assets/hero/hero-platine.webp);
  filter:hue-rotate(112deg) saturate(1.65) contrast(1.45)}

@media (prefers-reduced-motion: reduce) {
  /* Der Kreis steht, das Fenster funktioniert weiter. Das Bild im Fenster ist
     ein Standbild, dort gibt es nichts abzuschalten. */
  .pk-lauf, .pk-halter { animation: none }
}

@container (max-width: 380px) {
  /* Im schmalen Kreis wird das Fenster zu klein für Bild UND Text. Der Text
     gewinnt: er trägt die Aussage. */
  .pk-schau { display: none }
}
@media (max-width: 680px) {
  /* ⚠ UNTER 680px KEIN KREIS. Vier Plaketten auf einem 300-px-Ring stapeln sich
     übereinander, und ein rotierendes Ziel auf dem Telefon ist unbedienbar.
     Dann eine schlichte Liste — dieselben Inhalte, dieselben Farben. */
  .pk-kreis { max-width: none; aspect-ratio: auto; }
  /* ⚠ DER NEBEL MUSS HIER MIT WEG. Er traegt inset:-16 %, und auf dem
     Einspalter ist der Kreis kein Quadrat mehr: gemessen bei 390 px stand er
     408 px breit und schob die Seite um 9 px waagerecht heraus. Sichtbar ist er
     dort ohnehin nie — es gibt kein Hovern. */
  .pk-hof, .pk-nabe, .pk-nebel { display: none }
  .pk-lauf { position: static; animation: none }
  /* ⚠ `height: auto` GEHOERT DAZU. Die Speiche ist im Ring eine Linie ohne
     Hoehe (`.pk-arm{height:0}` weiter oben); ohne die Ruecknahme bleiben die
     vier Listeneintraege 0px hoch und liegen im 10-px-Abstand des
     margin-bottom uebereinander statt untereinander. */
  .pk-arm { position: static; width: auto; height: auto; transform: none; display: block; margin-bottom: 10px }
  .pk-bahn { display: none }
  .pk-spitze { position: static; transform: none }
  .pk-halter { animation: none }
  .pk-knopf { transform: none; width: 100%; justify-content: flex-start }
  .pk-fenster { position: static; transform: none; margin-top: 14px }
}


/* ---- 28. Branchen als Kartenstapel auf der Startseite (02.09.2026) ---------
   ⚠ HIER STATT IM SEITEN-<style>, UND ZWAR AUS EINEM GEMESSENEN GRUND. Der Block
   stand zuerst inline und damit dreifach: index.html, startseite.html (Alias) und
   startseite-merge-neu.html. Regel 2 hat das gemeldet — index.html lag 2 555
   Zeichen ueber der Basislinie in tools/compat-baseline.json (43 839). Ein
   Bauteil, das auf drei Seiten steht, gehoert zentral; das ist genau der Fall,
   fuer den Regel 2 da ist.
   ⚠ Die Kaskade dreht sich dadurch: components.css laedt NACH dem Seiten-<style>.
   Fuer diesen Block ist das ungefaehrlich, weil `.brs.an .bran-k` spezifischer ist
   als das `.bran-k` des Bento-Rasters, das inline bleibt. Wer hier Regeln ergaenzt,
   die mit dem Raster gleich spezifisch sind, muss das nachrechnen. */
/* ---------- Branchen als Stapel (Vorlage: sherpahq.ai „The Platform") ------
   Patrick 01.09.2026: „siehst du auf der sherpa seite die sektion the
   platform? Will die formattierung bzw das layout übernehmen … statt den
   wechselnden weißen Karten sind da immer die Branchenbilder aber auch so
   übereinander gelegt."

   GEMESSEN AN DER VORLAGE, nicht geschaetzt (Playwright auf sherpahq.ai,
   1440x900): die Huelle ist 1944 px hoch bei 900 px Ansicht, also rund 29 vh
   Scrollstrecke je Karte. Die Karten liegen deckungsgleich uebereinander in
   einem Feld von 460 x 620 px. Ruhelage je Tiefe:
     Tiefe 0  translateY 0    scale 1     rotate 0      z 4   Deckung 1
     Tiefe 1  translateY 18px scale .95   rotate +2,5°  z 3   Deckung 1
     Tiefe 2  translateY 36px scale .90   rotate -2,5°  z 2   Deckung 1
     Tiefe 3  translateY 54px scale .85   rotate +2,5°  z 1   Deckung 0
   Die abgehende Karte: rotate(-10°), Deckung 0, z 50 — sie liegt beim Abgang
   also OBEN. Genau diese Zahlen stehen unten.

   ⚠ EINE ZAHL, DER REST RECHNET CSS. Das Skript setzt `--a` (welche Karte
   vorn ist) auf die Huelle und die Klasse `.vorn`. Jede Karte kennt nur ihren
   eigenen Platz `--k`; ihre Tiefe `--d` rechnet CSS daraus aus.

   ⚠ DER KIPPWINKEL HAENGT AN DER KARTE, NICHT AN DER TIEFE. Sherpa wechselt
   das Vorzeichen je Tiefe; das braeuchte hier `mod()`. Mit festem Vorzeichen
   je Karte (`--kipp`, abwechselnd 1/-1) wechseln sich die sichtbaren Karten
   genauso ab, weil ihre Plaetze aufeinanderfolgen — nur behaelt jede Karte
   ihre eigene Neigung, statt sie bei jedem Schritt zu tauschen. */
.brs.an { height: calc(var(--halte, 6) * 29vh + 100vh); }
.brs.an .brs-view { position: sticky; top: 80px; height: calc(100vh - 80px);
  display: flex; align-items: center; }
.brs-raster { display: grid; gap: clamp(28px, 4vw, 64px); align-items: center; }
/* ⚠ 1100px UND ZENTRIERT, wie in der Vorlage. Ohne die Deckelung sass die
   Karte am linken Seitenrand und die Textspalte war 830px breit — die
   Ueberschrift lief dann quer ueber den halben Bildschirm, waehrend rechts
   ein Drittel leer blieb. Sherpa setzt `max-w-[1100px]` mit 64px Fuge. */
.brs.an .brs-raster { max-width: 1100px; margin-inline: auto;
  grid-template-columns: minmax(0, 460px) minmax(0, 1fr); }
/* Ohne `.an` steht der Text ueber dem Raster, wie bei jeder anderen Sektion. */
.brs-text .eyebrow { display: block; }
.brs-text h2 { margin: 10px 0 0; }
.brs-lead { margin: 14px 0 0; max-width: 46ch; font-size: 16px; line-height: 1.7;
  color: var(--muted-readable); text-wrap: pretty; }
.brs-marken { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
.brs-marken a { font-size: 13.5px; line-height: 1; text-decoration: none;
  color: var(--muted-readable); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-full); padding: .58em .9em;
  transition: color .3s var(--ease), border-color .3s var(--ease),
    background .3s var(--ease); }
@media (hover: hover) { .brs-marken a:hover { color: var(--ink); border-color: var(--ink); } }
.brs-marken a.jetzt { color: var(--green-800); background: var(--tech-tint);
  border-color: var(--tech-soft); font-weight: 600; }
/* Ohne Stapel stehen die sechs Kacheln selbst da — dann sind die Marken eine
   Dopplung und entfallen.
   ⚠ DESHALB BRAUCHT DIESER BLOCK KEINE REDUCED-MOTION-FASSUNG. Bei reduzierter
   Bewegung setzt das Skript `.an` gar nicht erst: dann gibt es weder Stapel
   noch Marken, und es gibt nichts abzuschalten. Eine Regel dafuer stand hier
   kurz und war tote Fracht — sie hat Regel 2 um 146 Zeichen gerissen.
   `.bran-k.ist-breit` braucht im Stapel ebenfalls nichts: `.bran` ist dort
   `display: block`, `grid-column` wirkt gar nicht. */
.brs:not(.an) .brs-marken { display: none; }

/* Das Stapelfeld. Ohne `.an` bleibt `.bran` das Raster von oben. */
.brs.an .bran { position: relative; display: block;
  height: clamp(420px, 62vh, 600px); }
.brs.an .bran-k { position: absolute; inset: 0; min-height: 0;
  --d: calc(var(--k) - var(--a, 0));
  --w: clamp(0, var(--d), 3);
  --g: clamp(0, calc(0 - var(--d)), 1);
  z-index: calc(50 * var(--g) + 10 - var(--w));
  transform: translateY(calc(var(--w) * 18px))
    scale(calc(1 - var(--w) * .05))
    rotate(calc(var(--kipp, 1) * var(--w) * 2.5deg + var(--g) * -10deg));
  opacity: calc((1 - var(--g)) * (1 - clamp(0, calc(var(--d) - 2), 1)));
  transition: transform .6s var(--ease), opacity .6s var(--ease);
  /* ⚠ KANTE UND SCHATTEN, sonst ist der Stapel nicht als Stapel zu erkennen.
     Sherpas Karten sind weiss mit 2px Rand; unsere sind Fotos mit dunklem
     Schleier, und die herausschauenden Raender liefen ohne Kante als dunkler
     Fleck ineinander. Der helle Ring zeichnet jedes Blatt, der Schatten hebt
     das vordere ab. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .32),
    0 26px 50px -28px rgba(2, 12, 10, .75);
  pointer-events: none; }
/* Klickbar ist nur die vordere Karte — die anderen liegen darunter. Alle
   sechs Verweise bleiben trotzdem erreichbar: sie stehen rechts als Marken. */
.brs.an .bran-k.vorn { pointer-events: auto; }
.brs.an .bran-k h3 { font-size: clamp(1.35rem, 1.9vw, 1.8rem); }

/* ---- 29. Innereien der Startseiten-Animation (02.09.2026) ------------------
   Patrick hat je Phase gesagt, was in den Kaestchen fehlt: die Vorlage soll ihre
   Felder zeigen, die Pflichtnachweise Kacheln statt Chips, „wird vorbefuellt"
   soll das Vorbefuellen SEHEN lassen, die Lieferantengruppen ihre Reihenfolge,
   die Genehmigungsstufen wer schon zugestimmt hat, die Verteilung ihre
   Prioritaeten, die Kandidatenkarten mehr Inhalt, die Pipeline einen Ablauf, und
   beim Einsatz Duplikat/Blacklist als scannende Quadrate, die Personalakte mit
   Upload-Kreis und der AUE-Vertrag zwei Signaturen.

   ⚠ HIER STATT IM SEITEN-<style>. Der Block waere sonst dreifach im Baum
   (index, startseite als Alias, startseite-merge-neu) und index.html liegt
   bereits 365 Zeichen ueber der Regel-2-Basislinie. Dieselbe Entscheidung wie
   bei Abschnitt 28.
   ⚠ DIE KASKADE DREHT SICH: components.css laedt NACH dem Seiten-<style>. Fuer
   diesen Block ist das erwuenscht — die Reduced-Motion-Fassung am Ende muss die
   Regeln aus der Seite ueberschreiben koennen.
   ⚠ EINE ZAHL BLEIBT DIE REGEL: `--v` staffelt die Elemente, jede Verzoegerung
   steht als `calc(Xs * var(--tempo))`. Wer den Takt aendert, aendert `--tempo`
   im Seitenstil, nicht diese Zahlen.
   ⚠ ANIMIERT WIRD NUR transform UND opacity (DESIGN.md §5). */

/* --- Feldzeilen der Jobvorlage: Label links, Wert rechts ------------------- */
.fl-felder { display: flex; flex-direction: column; gap: .18em; width: 100%; }
.fl-feld { display: flex; align-items: baseline; gap: .6em; padding: .3em 0;
  border-bottom: 1px solid var(--line-soft); opacity: 0; }
.fl-feld:last-child { border-bottom: 0; }
.fl-feld em { font-style: normal; font-size: .74em; color: var(--muted-readable);
  flex: none; min-width: 7.6em; }
.fl-feld b { font-size: .78em; font-weight: 600; color: var(--ink); margin-left: auto;
  text-align: right; }
.fl-karte.jetzt .fl-feld { animation: fl-ein .34s var(--ease) both;
  animation-delay: calc((.6s + var(--v, 0) * .12s) * var(--tempo)); }

/* --- Nachweis-Kacheln: Symbol oben, Wort darunter ------------------------- */
.fl-nwreihe { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .4em; width: 100%; }
.fl-nw { display: flex; flex-direction: column; align-items: center; gap: .42em;
  padding: .6em .3em; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); text-align: center; opacity: 0; }
.fl-nw i { display: grid; place-items: center; width: 2.1em; height: 2.1em;
  border-radius: var(--r-sm); background: var(--tech-tint); color: var(--green-700); }
.fl-nw i svg { width: 1.15em; height: 1.15em; }
.fl-nw em { font-style: normal; font-size: .66em; line-height: 1.25;
  color: var(--ink-soft); }
.fl-karte.jetzt .fl-nw { animation: fl-pop .38s var(--ease) both;
  animation-delay: calc((1s + var(--v, 0) * .14s) * var(--tempo)); }

/* --- „Wird vorbefuellt": die Zeile laeuft sichtbar voll, dann der Haken ---- */
.fl-fuellliste { display: flex; flex-direction: column; gap: .34em; width: 100%; }
.fl-fuell { display: flex; align-items: center; gap: .55em; opacity: 0; }
.fl-fuell em { font-style: normal; font-size: .72em; color: var(--muted-readable);
  flex: none; min-width: 6.8em; }
.fl-fuell i { position: relative; flex: 1; height: .5em; border-radius: var(--r-full);
  background: var(--line-soft); overflow: hidden; }
.fl-fuell i::after { content: ""; position: absolute; inset: 0;
  background: var(--tech-soft); transform: scaleX(0); transform-origin: left; }
.fl-fuell b { display: grid; place-items: center; width: 1.05em; height: 1.05em;
  flex: none; border-radius: 50%; background: var(--green-600); color: var(--surface);
  opacity: 0; transform: scale(.5); }
.fl-fuell b svg { width: .72em; height: .72em; }
.fl-karte.jetzt .fl-fuell { animation: fl-ein .3s var(--ease) both;
  animation-delay: calc((1.4s + var(--v, 0) * .22s) * var(--tempo)); }
.fl-karte.jetzt .fl-fuell i::after { animation: fl-fuellen .5s var(--ease) both;
  animation-delay: calc((1.5s + var(--v, 0) * .22s) * var(--tempo)); }
.fl-karte.jetzt .fl-fuell b { animation: fl-pop .3s var(--ease) both;
  animation-delay: calc((1.95s + var(--v, 0) * .22s) * var(--tempo)); }
@keyframes fl-fuellen { from { transform: scaleX(0) } to { transform: scaleX(1) } }

/* --- Reihenfolge A vor B vor C: Kreis mit Buchstabe, Pfeil dazwischen ------ */
.fl-stufen { display: flex; align-items: stretch; gap: .5em; width: 100%; }
.fl-stufe { position: relative; flex: 1; display: flex; flex-direction: column;
  align-items: center; gap: .3em; padding: .5em .2em;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  opacity: 0; }
.fl-stufe + .fl-stufe::before { content: ""; position: absolute; left: -.5em; top: 50%;
  width: .5em; height: 1.5px; background: var(--line); }
.fl-stufe b { display: grid; place-items: center; width: 1.75em; height: 1.75em;
  border-radius: 50%; font-size: .84em; font-weight: 600;
  background: var(--line-soft); color: var(--muted-readable); }
.fl-stufe em { font-style: normal; font-size: .64em; color: var(--muted-readable); }
.fl-stufe.ist-jetzt b { background: var(--green-600); color: var(--surface); }
.fl-stufe.ist-jetzt em { color: var(--green-700); font-weight: 600; }
.fl-stufe.ist-jetzt { border-color: var(--tech-soft); background: var(--tech-tint); }
.fl-karte.jetzt .fl-stufe { animation: fl-pop .36s var(--ease) both;
  animation-delay: calc((1s + var(--v, 0) * .18s) * var(--tempo)); }

/* --- Genehmigungsstufen: wer hat zugestimmt, wer ist dran ------------------ */
.fl-gliste { display: flex; flex-direction: column; gap: .3em; width: 100%; }
.fl-gz { display: flex; align-items: center; gap: .55em; padding: .38em .5em;
  border: 1px solid var(--line-soft); border-radius: var(--r-sm); opacity: 0; }
.fl-gz i { display: grid; place-items: center; width: 1.2em; height: 1.2em; flex: none;
  border-radius: 50%; border: 1.5px solid var(--line); color: transparent; }
.fl-gz i svg { width: .8em; height: .8em; }
.fl-gz em { font-style: normal; font-size: .76em; font-weight: 600; color: var(--ink); }
.fl-gz small { margin-left: auto; font-size: .66em; color: var(--muted-readable); }
.fl-gz.ist-ok { border-color: var(--tech-soft); background: var(--tech-tint); }
.fl-gz.ist-ok i { background: var(--green-600); border-color: var(--green-600);
  color: var(--surface); }
.fl-gz.ist-ok small { color: var(--green-700); }
.fl-gz.ist-dran i { border-color: var(--green-600); box-shadow: 0 0 0 .18em var(--tech-tint); }
.fl-karte.jetzt .fl-gz { animation: fl-ein .32s var(--ease) both;
  animation-delay: calc((.9s + var(--v, 0) * .25s) * var(--tempo)); }

/* --- Faecher: aus der Freigabe laufen drei Zweige zu den Gruppen ---------- */
.fl-faecher { display: grid; grid-template-columns: repeat(3, 1fr); place-items: center;
  height: 1.1em; width: 100%; }
.fl-fzweig { width: 1.5px; height: 100%; background: var(--tech); transform: scaleY(0);
  transform-origin: top; border-radius: 2px; }
.fl-karte.jetzt .fl-fzweig { animation: fl-zweig .34s var(--ease) both;
  animation-delay: calc((1.6s + var(--v, 0) * .12s) * var(--tempo)); }
/* ⚠ DIE CHIPS DARUNTER BRAUCHEN DASSELBE RASTER, sonst zeigen die Zweige ins
   Leere: `.fl-zeile` ist inhaltsbreit, der Faecher ein Drittelraster — gerendert
   standen die Zweige bei 1000/1135/1272px, die Chips bei 980/1080/1183px. */
.fl-faecher + .fl-zeile { display: grid; grid-template-columns: repeat(3, 1fr);
  gap: .3em; }
.fl-faecher + .fl-zeile .fl-chip { justify-self: center; }
@keyframes fl-zweig { from { transform: scaleY(0) } to { transform: scaleY(1) } }

/* --- Leiter der Prioritaeten: jede Stufe rueckt ein ----------------------- */
.fl-leiter { display: flex; flex-direction: column; gap: .3em; width: 100%; }
.fl-sprosse { display: flex; align-items: center; gap: .55em; opacity: 0;
  margin-left: calc(var(--tief, 0) * .9em); padding: .4em .55em;
  border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: var(--surface); }
.fl-sprosse b { display: grid; place-items: center; width: 1.45em; height: 1.45em;
  flex: none; border-radius: var(--r-sm); font-size: .72em; font-weight: 600;
  background: var(--line-soft); color: var(--muted-readable); }
.fl-sprosse em { font-style: normal; font-size: .76em; font-weight: 600; color: var(--ink); }
.fl-sprosse small { margin-left: auto; font-size: .64em; color: var(--muted-readable); }
.fl-sprosse.ist-jetzt { border-color: var(--tech-soft); background: var(--tech-tint); }
.fl-sprosse.ist-jetzt b { background: var(--green-600); color: var(--surface); }
.fl-sprosse.ist-jetzt small { color: var(--green-700); }
.fl-karte.jetzt .fl-sprosse { animation: fl-ein .32s var(--ease) both;
  animation-delay: calc((.9s + var(--v, 0) * .2s) * var(--tempo)); }

/* --- Mini-Chips auf den Kandidatenkarten --------------------------------- */
.fl-minis { display: flex; flex-wrap: wrap; gap: .28em; }
.fl-mini { font-size: .6em; line-height: 1; padding: .34em .55em;
  border-radius: var(--r-full); background: var(--line-soft); color: var(--ink-soft);
  opacity: 0; }
.fl-karte.jetzt .fl-mini { animation: fl-pop .3s var(--ease) both;
  animation-delay: calc((.8s + var(--v, 0) * .1s) * var(--tempo)); }
.fl-box.ist-gewaehlt .fl-mini { background: var(--surface); color: var(--green-700); }

/* --- Pipeline als Ablauf: vier Kaestchen nebeneinander ------------------- */
.fl-pipe { display: flex; align-items: stretch; gap: .45em; width: 100%; }
.fl-pstufe { position: relative; flex: 1; display: flex; flex-direction: column;
  align-items: center; gap: .35em; padding: .45em .2em;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  opacity: 0; }
.fl-pstufe + .fl-pstufe::before { content: ""; position: absolute; left: -.45em; top: 50%;
  width: .45em; height: 1.5px; background: var(--line); }
.fl-pstufe b { font-size: .6em; font-weight: 600; color: var(--muted-readable);
  line-height: 1.2; text-align: center; }
.fl-pstufe i { display: grid; place-items: center; width: 1.35em; height: 1.35em;
  border-radius: var(--r-sm); background: var(--line-soft); color: transparent; }
.fl-pstufe i svg { width: .85em; height: .85em; }
.fl-pstufe.ist-jetzt { border-color: var(--tech-soft); background: var(--tech-tint); }
.fl-pstufe.ist-jetzt b { color: var(--green-700); }
.fl-pstufe.ist-jetzt i { background: var(--green-600); color: var(--surface); }
.fl-karte.jetzt .fl-pstufe { animation: fl-pop .34s var(--ease) both;
  animation-delay: calc((1.4s + var(--v, 0) * .18s) * var(--tempo)); }

/* --- Automatische Pruefung: zwei Quadrate, die gescannt werden ----------- */
.fl-pruef { display: grid; grid-template-columns: 1fr 1fr; gap: .5em; width: 100%; }
.fl-pkachel { position: relative; aspect-ratio: 1; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
  overflow: hidden; opacity: 0; }
.fl-pkachel em { font-style: normal; font-size: .74em; font-weight: 600;
  color: var(--ink-soft); }
/* Der Scanbalken laeuft von oben nach unten durch die Kachel. */
.fl-pkachel .fl-scanline { position: absolute; left: 0; right: 0; top: 0; height: 34%;
  background: linear-gradient(180deg, transparent, var(--tech-tint) 55%, transparent);
  transform: translateY(-120%); }
.fl-pkachel .fl-haken { position: absolute; right: .4em; bottom: .4em;
  display: grid; place-items: center; width: 1.3em; height: 1.3em; border-radius: 50%;
  background: var(--green-600); color: var(--surface); opacity: 0; transform: scale(.5); }
.fl-pkachel .fl-haken svg { width: .85em; height: .85em; }
.fl-karte.jetzt .fl-pkachel { animation: fl-pop .36s var(--ease) both;
  animation-delay: calc((.9s + var(--v, 0) * .16s) * var(--tempo)); }
.fl-karte.jetzt .fl-pkachel .fl-scanline { animation: fl-scannen .9s var(--ease) both;
  animation-delay: calc((1.2s + var(--v, 0) * .5s) * var(--tempo)); }
.fl-karte.jetzt .fl-pkachel .fl-haken { animation: fl-pop .32s var(--ease) both;
  animation-delay: calc((2.1s + var(--v, 0) * .5s) * var(--tempo)); }
@keyframes fl-scannen { from { transform: translateY(-120%) } to { transform: translateY(320%) } }

/* --- Personalakte: erst Upload-Kreis, dann liegt der Nachweis da --------- */
.fl-akte { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .4em; width: 100%; }
.fl-akachel { position: relative; display: flex; flex-direction: column;
  align-items: center; gap: .4em; padding: .55em .25em;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  text-align: center; opacity: 0; }
.fl-akachel i { display: grid; place-items: center; width: 2em; height: 2em;
  border-radius: 50%; }
.fl-akachel .fl-lade { border: 1.5px dashed var(--line); color: var(--muted-readable); }
.fl-akachel .fl-fertig { position: absolute; top: .55em; left: 50%;
  transform: translateX(-50%) scale(.6); opacity: 0;
  background: var(--tech-tint); color: var(--green-700); }
.fl-akachel i svg { width: 1.1em; height: 1.1em; }
.fl-akachel em { font-style: normal; font-size: .62em; line-height: 1.25;
  color: var(--ink-soft); }
.fl-karte.jetzt .fl-akachel { animation: fl-ein .34s var(--ease) both;
  animation-delay: calc((.9s + var(--v, 0) * .2s) * var(--tempo)); }
.fl-karte.jetzt .fl-akachel .fl-lade { animation: fl-weg .3s var(--ease) both;
  animation-delay: calc((1.85s + var(--v, 0) * .3s) * var(--tempo)); }
.fl-karte.jetzt .fl-akachel .fl-fertig { animation: fl-da .34s var(--ease) both;
  animation-delay: calc((1.9s + var(--v, 0) * .3s) * var(--tempo)); }
@keyframes fl-weg { to { opacity: 0; transform: scale(.7) } }
@keyframes fl-da { from { opacity: 0; transform: translateX(-50%) scale(.6) }
                     to { opacity: 1; transform: translateX(-50%) scale(1) } }

/* --- AUE-Vertrag: zwei Signaturen, beide Seiten ------------------------- */
.fl-sig { display: grid; grid-template-columns: 1fr 1fr; gap: .6em; width: 100%; }
.fl-sigfeld { position: relative; display: flex; flex-direction: column; gap: .3em;
  padding-top: .9em; opacity: 0; }
.fl-sigfeld .fl-strich { display: block; height: 1.5px; border-radius: 2px;
  background: var(--ink-soft); transform: scaleX(0); transform-origin: left; }
.fl-sigfeld .fl-sigok { position: absolute; right: 0; top: 0; display: grid;
  place-items: center; width: 1.15em; height: 1.15em; border-radius: 50%;
  background: var(--green-600); color: var(--surface); opacity: 0; transform: scale(.5); }
.fl-sigfeld .fl-sigok svg { width: .78em; height: .78em; }
.fl-sigfeld em { font-style: normal; font-size: .64em; color: var(--muted-readable); }
.fl-karte.jetzt .fl-sigfeld { animation: fl-ein .3s var(--ease) both;
  animation-delay: calc((1.1s + var(--v, 0) * .3s) * var(--tempo)); }
.fl-karte.jetzt .fl-sigfeld .fl-strich { animation: fl-fuellen .55s var(--ease) both;
  animation-delay: calc((1.3s + var(--v, 0) * .5s) * var(--tempo)); }
.fl-karte.jetzt .fl-sigfeld .fl-sigok { animation: fl-pop .3s var(--ease) both;
  animation-delay: calc((1.9s + var(--v, 0) * .5s) * var(--tempo)); }

/* --- Reduzierte Bewegung: Endzustand, kein Ablauf -----------------------
   ⚠ JEDER ANIMIERTE SELEKTOR MUSS HIER STEHEN. Die Lehre vom 28.08.2026: eine
   spezifischere Regel im Seitenstil laeuft sonst weiter, gemessen waren es
   damals 84 laufende Animationen in der Phase Auswahl. */
@media (prefers-reduced-motion: reduce) {
  .fl-karte.jetzt .fl-feld, .fl-karte.jetzt .fl-nw, .fl-karte.jetzt .fl-fuell,
  .fl-karte.jetzt .fl-fuell i::after, .fl-karte.jetzt .fl-fuell b,
  .fl-karte.jetzt .fl-stufe, .fl-karte.jetzt .fl-gz, .fl-karte.jetzt .fl-fzweig,
  .fl-karte.jetzt .fl-sprosse, .fl-karte.jetzt .fl-mini, .fl-karte.jetzt .fl-pstufe,
  .fl-karte.jetzt .fl-pkachel, .fl-karte.jetzt .fl-pkachel .fl-scanline,
  .fl-karte.jetzt .fl-pkachel .fl-haken, .fl-karte.jetzt .fl-akachel,
  .fl-karte.jetzt .fl-akachel .fl-lade, .fl-karte.jetzt .fl-akachel .fl-fertig,
  .fl-karte.jetzt .fl-sigfeld, .fl-karte.jetzt .fl-sigfeld .fl-strich,
  .fl-karte.jetzt .fl-sigfeld .fl-sigok { animation: none; }
  .fl-feld, .fl-nw, .fl-fuell, .fl-stufe, .fl-gz, .fl-sprosse, .fl-mini,
  .fl-pstufe, .fl-pkachel, .fl-akachel, .fl-sigfeld { opacity: 1; }
  .fl-fuell i::after, .fl-fzweig, .fl-sigfeld .fl-strich { transform: none; }
  .fl-fuell b, .fl-pkachel .fl-haken, .fl-sigfeld .fl-sigok { opacity: 1; transform: none; }
  .fl-akachel .fl-lade { opacity: 0; }
  .fl-akachel .fl-fertig { opacity: 1; transform: translateX(-50%) scale(1); }
  .fl-pkachel .fl-scanline { opacity: 0; }
}

/* --- Schmale Fenster: die Kaestchen sind hoehengedeckelt, also muss der Inhalt
   enger werden. GEMESSEN bei 390px vor dieser Stelle: Phase 0 lief 29px, Phase 2
   6 und 11px, Phase 3 12px ueber den Rahmen. Nur Abstaende und Grade, keine
   Struktur — die Rezepte bleiben dieselben. */
@media (max-width: 620px) {
  .fl-felder { gap: .1em; }
  .fl-feld { padding: .2em 0; }
  .fl-feld em { min-width: 5.2em; font-size: .7em; }
  .fl-feld b { font-size: .72em; }
  .fl-nw { padding: .42em .18em; gap: .3em; }
  .fl-nw i { width: 1.7em; height: 1.7em; }
  .fl-nw em { font-size: .6em; }
  .fl-fuellliste { gap: .24em; }
  .fl-fuell em { min-width: 5.2em; font-size: .68em; }
  .fl-gliste { gap: .22em; }
  .fl-gz { padding: .28em .42em; gap: .45em; }
  .fl-gz em { font-size: .72em; }
  .fl-gz small { font-size: .62em; }
  .fl-faecher { height: .8em; }
  .fl-leiter { gap: .22em; }
  .fl-sprosse { padding: .3em .45em; gap: .45em; }
  .fl-sprosse em { font-size: .72em; }
  .fl-stufe { padding: .4em .15em; gap: .24em; }
  .fl-pipe { gap: .3em; }
  .fl-pstufe { padding: .38em .15em; }
  /* ⚠ Zweiter Durchgang, wieder gemessen: es blieben 18px (Phase 0) und je 7px
     (Phasen 2 und 3). Auf dem Telefon faellt deshalb die vierte Feldzeile weg —
     drei Felder tragen die Aussage genauso, und Zeilen weiter zu quetschen macht
     sie unleserlich. Faecher und Leiter geben den Rest ab. */
  /* ⚠ EIN GRAD STATT ZEHN ABSTAENDE. Nach zwei Runden Quetschen blieben 10px
     (Phase 0) und je 6px (Phasen 2, 3). Der Grundgrad der Szene nimmt alles
     proportional mit; das ist ehrlicher als weitere Zeilen zu verstecken.
     Die Regel im Seitenstil setzt hier 1em, components.css laedt danach. */
  .fl-szene { font-size: .88em; }
  .fl-feld:nth-of-type(4) { display: none; }
  .fl-faecher { height: .58em; }
  .fl-sprosse { padding: .26em .4em; }
  .fl-sprosse small, .fl-stufe em { font-size: .6em; }
}

/* ---- 30. Logoflug der Startseite (03.09.2026) ------------------------------
   Das Logo faellt am Ende der Hero-Animation in einen gruenen Kreis zusammen,
   fliegt durch die Seite und geht in der Kernsystem-Sektion als Produktkreis
   auf; danach bleibt es als Knopf unten links stehen. Patrick, 03.09.2026,
   nach dem Vorbild talentium.io.

   Erarbeitet und Etappe fuer Etappe gemessen in
   proben/startseite-logoflug.html; dort steht auch, was verworfen wurde und
   welche zwei Messfallen es gekostet hat. Diese Datei traegt nur, was sich
   bewaehrt hat. Das Verhalten steht im Seitenblock von index.html, weil es
   nur diese eine Sektion auf zwei Seiten betrifft.

   ⚠ ALLE ZUSTANDSKLASSEN SETZT DAS SKRIPT. Ohne Skript, bei reduzierter
   Bewegung, unter 1001 px Breite und unter 680 px Hoehe traegt nichts eine
   davon: der Hero ist 300vh, die Sektion steht wie immer, der Produktkreis
   ist offen und dreht, der Flugkreis ist display:none. Der Effekt verstaerkt
   einen sichtbaren Grundzustand, er stellt ihn nicht her (DESIGN.md §5).
   ============================================================================ */
/* ---- Der Hero ist um das Einklappen laenger ---------------------------
   300vh (Auftritt) + 80vh (Einklappen) = 380vh. Der Wert selbst steht im
   Seitenkopf von index.html bei den anderen .hz-Regeln; hier stehen nur die
   zwei Rueckfaelle, weil sie ueberschreiben muessen und components.css nach
   dem Seitenkopf laedt. Die Reihenfolge der beiden ist Absicht: bei
   reduzierter Bewegung UND flachem Fenster muss `auto` gewinnen. */
/* ⚠ Unter 680 px Fensterhoehe faellt das Einklappen weg, und zwar KOMPLETT:
   die Huelle ist wieder 300vh, damit rechnen beide Skripte takt = 1 und die
   Choreografie endet wie auf index.html. Dieselbe Schwelle gilt fuer Flug und
   Halt (im Skript). Sonst klappte das Fenster in einen Kreis zusammen, den
   dann niemand abholt. */
/* ⚠ AUF `body:has([data-pkhalt])` EINGESCHRAENKT, und das ist kein Zierrat:
   startseite-merge-neu.html traegt denselben `.hz`-Hero mit 240vh Huelle. Eine
   nackte `.hz.an`-Regel hier haette ihn auf flachen Fenstern stumm auf 300vh
   gezogen. Die Bedingung sagt genau das Richtige aus — die Regel gilt nur, wo
   es einen Landeplatz fuer den Kreis gibt. */
@media (max-height: 679px) {
  body:has([data-pkhalt]) .hz.an { height: 300vh; }
}
@media (prefers-reduced-motion: reduce) {
  body:has([data-pkhalt]) .hz.an { height: auto; }
}

/* ---- Der Halt am Kreis -----------------------------------------------
   Patrick: "wenn dann das ganze in dem kreis endet muss der bildschirm da
   kurz stehen bleiben bevor man dann weiterscrollt weil so wie es aktuell
   ist sieht man garnicht den ganzen Kreis."
   ZWEI Ursachen, beide hier behoben:
   (1) Es hielt nicht an. Jetzt klebt die Ansicht 80svh lang.
   (2) Der Kreis PASST bei 900 px Fensterhoehe gar nicht: 700 px Kreis, 118 px
       Kopf, 40 px Fuge und 102 px Kopfleiste sind 960 px. Im Halt wird er
       deshalb nur so gross, wie hineingeht. Das kostet keine Sonderregeln:
       der ganze Produktkreis rechnet in Containerabfragen (cqw), also gehen
       Plaketten, Schrift, Speichen, Nabe und Nebel von selbst mit.
   ⚠ Das Kopfpolster liegt auf der ANSICHT, nicht auf der Sektion: sonst
   schiebt es den Inhalt nach unten und die Mitte sitzt zu tief. So wird im
   Feld UNTER der Kopfleiste zentriert, wie beim Hero. */
.pk-halt.an { height: calc(100svh + 80svh); }
.pk-halt.an .pk-halt-view { position: sticky; top: 0; height: 100svh;
  box-sizing: border-box; padding: 102px 0 24px; overflow: clip;
  display: grid; align-content: center; }
.pk-halt.an .pk-halt-view > .sec { padding-top: 0; padding-bottom: 0; }
.pk-halt.an .pk-kreis { max-width: min(700px, calc(100svh - 320px)); }

/* ---- Der Flugkreis ----------------------------------------------------
   Sieht aus wie .pk-nabe, weil er dieselbe Nabe IST — nur voruebergehend
   freigestellt und im Bildschirm unterwegs. Deshalb Zeile fuer Zeile die
   Werte aus components.css Abschnitt 27; nur die drei cqw-Zahlen sind
   umgerechnet, weil der Containerbezug hier der Kreis selbst ist und nicht
   das Feld: die Nabe ist 27 % des Feldes, also 11cqw → 11/27 = 40,74cqw und
   3cqw → 3/27 = 11,11cqw. Am Landepunkt sind beide dadurch deckungsgleich.

   ⚠ NUR transform UND opacity WERDEN GESCHRIEBEN (DESIGN.md §5). Die Groesse
   kommt aus scale(), nicht aus `width`: eine Breite je Bild waere ein
   Layoutdurchgang je Bild. transform-origin: 0 0 macht die Kette
   translate(Ziel) scale(k) translate(-50%,-50%) eindeutig — der Kreis sitzt
   mit seiner MITTE auf dem Ziel, in jeder Groesse.
   ⚠ z-index 70: ueber dem Inhalt, unter Kopf (100) und Megamenue (90).
   ⚠ Ohne Skript steht hier nichts: opacity 0 im Grundzustand. */
.lf-kreis { position: fixed; left: 0; top: 0; z-index: 70; transform-origin: 0 0;
  width: 189px; aspect-ratio: 1; border-radius: 50%;
  container-type: inline-size; pointer-events: none; opacity: 0;
  background: var(--grad-fresh);
  border: 1px solid color-mix(in srgb, var(--tech) 30%, transparent);
  /* ⚠ KEIN 12-px-HOF MEHR. Patrick 04.09.2026: „da sind irgendwie zwei Kreise
     hintereinander." Genau das war es: der Hof (Gruen 7 %, 12 px Streuung) ist
     auf dem hellen Hero-Foto unsichtbar, aber der Flugkreis landet inzwischen
     mitten in der Visualisierung — und dort, auf fast weissem Grund, liest er
     sich als zweiter, grauer Kreis hinter der Scheibe. Im Bild bei
     doppelter Auflösung nachgesehen. Die Nabe des Produktkreises (Abschnitt 27)
     behaelt ihren Hof: sie steht weiter auf dem dunklen Band. */
  box-shadow: var(--shadow-m);
  display: grid; place-content: center; justify-items: center; gap: 6px; }
/* ⚠ DIE INNENMASSE KOMMEN GEMESSEN AUS DER ECHTEN NABE (--lf-mark und
   --lf-schrift setzt das Skript). Die cqw-Werte sind nur der Rueckfall.
   Warum nicht einfach cqw: die Nabe fragt den KREIS (700 px, ohne Rand), der
   Flugkreis fragt sich selbst — und sein eigener 1-px-Rand macht den
   Containerkasten 187 statt 189 px breit. Gemessen war das Zeichen dadurch
   76,17 statt 77,00 px und der Schriftzug sass 0,62 px hoeher; am
   Landepunkt sind das 1,6 Geraetepixel Versatz auf lauter harten Kanten,
   und der harte Wechsel wird sichtbar. Gemessen mit PSNR, siehe LIESMICH. */
.lf-kreis img { width: var(--lf-mark, 40.74cqw); height: auto; display: block; }
.lf-kreis b { font-size: var(--lf-schrift, clamp(11px, 11.11cqw, 16px)); font-weight: 500;
  letter-spacing: -.01em; color: var(--surface);
  transition: opacity .25s var(--ease-out); }
/* ⚠ In der Ecke traegt nur das Zeichen. Die Groesse kommt aus scale(), der
   Schriftzug wird also mitverkleinert: bei 81 px Durchmesser stehen von den
   16 px Schrift 6,9 px auf dem Schirm, und das ist ein Fleck, kein Wort.
   Er geht deshalb weg, sobald der Kreis klein wird — die Klasse setzt das
   Skript an der Groesse, nicht am Scrollstand.
   ⚠ NUR opacity, kein display: der Schriftzug bleibt im Raster stehen. Sonst
   ruecke das Zeichen in die Mitte, und am Landepunkt sass es 5 px anders als
   in der echten Nabe — genau die Verschiebung, die den harten Wechsel
   auffliegen liesse. */
.lf-kreis.ist-klein b { opacity: 0; }

/* ---- Der Produktkreis, solange der Flugkreis noch unterwegs ist -------
   ⚠ DIE KLASSEN SETZT DAS SKRIPT. Ohne Skript, bei reduzierter Bewegung und
   unter 1001 px traegt der Kreis keine davon und die Sektion steht wie heute
   da — offen, drehend, vollstaendig. Der Effekt verstaerkt einen sichtbaren
   Grundzustand, er stellt ihn nicht erst her (DESIGN.md §5).
     .fliegt        zu, still, Nabe unsichtbar (der Flugkreis ist sie)
     .ist-gelandet  auf: Ring faehrt aus, Namen kommen, Drehung beginnt */
.pk-kreis.fliegt .pk-nabe { opacity: 0; }
/* ⚠ DIE NABE IST SCHON DA, BEVOR DER FLUGKREIS GEHT. Beide sind ab dem
   Andocken deckungsgleich (gemessen: Zeichen 77,00 px, Schriftzug an
   derselben Stelle) — aber der Flugkreis ist eine verschobene Ebene und
   rastert einen halben Pixel anders als die im Fluss liegende Nabe. Ein
   harter Wechsel liess das als Nachschaerfen aufblitzen (PSNR 29 dB).
   Also: die Nabe geht ohne Uebergang auf 1, DANN blendet der Flugkreis
   darueber weg. Nie komplementaer ueberblenden — zwei halbdurchsichtige
   gruene Scheiben lassen in der Mitte der Blende den Grund durch, das ist
   dieselbe Delle wie beim Aufgehen des Fensters. */
.pk-kreis.fliegt.nabe-da .pk-nabe { opacity: 1; }
.pk-kreis.fliegt .pk-hof { opacity: 0; }
/* ⚠ visibility, NICHT NUR opacity. Eine Plakette mit opacity 0 ist weiter
   anklickbar und weiter im Tabulatorlauf: man haette vier unsichtbare
   Produktlinks im Fokus, bevor der Kreis aufgeht. visibility nimmt sie
   heraus und schaltet beim Landen ohne Uebergang zurueck, waehrend
   Deckkraft und Groesse einfahren. */
.pk-kreis.fliegt .pk-oeffnen { transform: scale(.52); opacity: 0;
  visibility: hidden; pointer-events: none; }
.pk-kreis.fliegt .pk-arm { opacity: 0; }
/* ⚠ Ring UND Gegendrehung zusammen anhalten und zusammen loslassen, sonst
   laufen sie auseinander und die Schrift steht schraeg (Abschnitt 27). Beide
   stehen bei 0 s, starten also synchron. */
.pk-kreis.fliegt .pk-lauf, .pk-kreis.fliegt .pk-halter { animation-play-state: paused; }

/* Die neue Zwischenebene traegt das Aufgehen. Sie muss eine EIGENE sein:
   .pk-lauf dreht (Animation) und .pk-arm haelt den Winkel (statisch) — wer
   das Aufgehen auf eines der beiden legt, loescht dessen transform. */
.pk-oeffnen { position: absolute; inset: 0;
  transition: transform .85s var(--ease-out), opacity .5s var(--ease-out); }
/* ⚠ NUR IM FLUG LAENGER. Abschnitt 27 laesst die Plaketten in 0,25 s
   abblenden, wenn eine andere aktiv ist — das bleibt so. Das Ausfahren beim
   Landen braucht mehr Zeit, sonst sind die vier Namen da, bevor man sie
   nacheinander wahrnimmt. Deshalb nur die Dauer, und nur in diesen zwei
   Zustaenden. */
.pk-kreis.fliegt .pk-arm,
.pk-kreis.ist-gelandet .pk-arm { transition-duration: .45s; }
/* Die Namen kommen nacheinander, in der Produkthierarchie des Abschnitts 27.
   Nur beim Aufgehen verzoegert; beim Zugehen gehen alle vier zusammen. */
.pk-kreis.ist-gelandet .pk-arm[data-produkt="vms"]        { transition-delay: .12s }
.pk-kreis.ist-gelandet .pk-arm[data-produkt="compliance"] { transition-delay: .22s }
.pk-kreis.ist-gelandet .pk-arm[data-produkt="tender"]     { transition-delay: .32s }
.pk-kreis.ist-gelandet .pk-arm[data-produkt="pax-ai"]     { transition-delay: .42s }

/* ⚠ DIE ZWISCHENEBENE MUSS AUF DEM TELEFON WIEDER IN DEN FLUSS.
   Abschnitt „unter 680px kein Kreis" (weiter oben) stellt .pk-lauf, .pk-arm
   und .pk-spitze schon auf `static` und macht aus dem Ring eine Liste. Die
   Ebene .pk-oeffnen kam spaeter dazu (Flug-/Landeanimation) und steht mit
   `position:absolute; inset:0` HIER, also NACH jenem Block — sie gewinnt
   deshalb und faltet die Liste wieder zusammen: gemessen bei 375px lagen die
   vier Plaketten „Schichtplanung/Zeiterfassung/Kurzfristeinsaetze/Abrechnung"
   in 10-px-Schritten uebereinander, .pk-lauf war 0px hoch (Karoline,
   10.09.2026: „Jetzt steht es ganz komisch").
   Darum die Rueckstellung hier unten und nicht oben im Block — Quellreihenfolge
   entscheidet, nicht Absicht. Danach gemessen: vier Plaketten, je 295px breit,
   untereinander mit 20px Abstand. */
@media (max-width: 680px) {
  .pk-oeffnen { position: static; inset: auto; display: flex; flex-direction: column;
    align-items: stretch; transform: none; transition: none; }
  /* Der Flugzustand darf die Liste nicht verstecken: ohne Kreis gibt es kein
     Landen, `.fliegt` bliebe sonst auf visibility:hidden stehen. */
  .pk-kreis.fliegt .pk-oeffnen { transform: none; opacity: 1;
    visibility: visible; pointer-events: auto; }
  .pk-kreis.fliegt .pk-arm { opacity: 1; }
}

/* ---- Geparkt ist der Kreis ein Knopf --------------------------------
   Patrick: "wenn man auf den Kreis klickt waere es geil wenn man dann auf
   die demo ausmachen Seite geleitet wird."
   ⚠ NUR IM STAND, NICHT IM FLUG. Ein Ziel, das sich bewegt, ist mit der Maus
   schwer zu fassen — und waehrend des Einklappens liegt der Kreis genau
   ueber dem Aktionsknopf des Rundgangs, wo er Klicks schlucken wuerde.
   `pointer-events` und der Tabulatorlauf gehen deshalb erst an, wenn er
   steht; `aria-hidden` nimmt das Skript in demselben Augenblick weg. */
.lf-kreis { text-decoration: none; }

/* ⚠ DAS ZEICHEN IM FLUGKREIS TAUCHT LANGSAM AUF. Patrick 05.09.2026: „das
   Logo taucht langsam auf und dreht sich auch im Uhrzeigersinn, bis es dann
   rechts in der richtigen Position zum Stehen kommt." Die Drehung macht das
   Skript (ein Winkel fuer Rad und Flugkreis, 720 Grad bis zum Parkplatz);
   hier steht nur, dass das Zeichen dabei kommt. Ohne `--markop` — also am
   Parkplatz, auf der Reise und im Formwandel — steht es ganz da. */
.lf-kreis img { opacity: var(--markop, 1); }
.lf-kreis.ist-geparkt { pointer-events: auto; cursor: pointer; }
@media (hover: hover) {
  .lf-kreis.ist-geparkt { transition: box-shadow .22s var(--ease-out); }
  .lf-kreis.ist-geparkt:hover {
    box-shadow: 0 0 0 18px color-mix(in srgb, var(--green-800) 12%, transparent), var(--shadow-l); }
}

@media (prefers-reduced-motion: reduce) { .lf-kreis { display: none } }
@media (max-width: 1000px), (max-height: 679px) { .lf-kreis { display: none } }

/* ============================================================
   31. Glas — eine Flaeche, durch die das Bild dahinter durchkommt
   ============================================================
   Patrick 04.09.2026: „die Box darauf braucht einen noch durchsichtigeren
   Eindruck, vlt kann man da allgemein eine klasse anlegen dafür." Also
   zentral, nicht je Sektion.

   ⚠ DIE ZAHLEN SIND GEMESSEN, NICHT GESCHAETZT. Gemessen wird auf dem
   dunkelsten Punkt der Flaeche (Schrift ausgeblendet, P02) ueber den drei
   Ist-Zustand-Fotos, weil das der schlechteste Fall fuer dunkle Schrift ist:
       Weiss 74 %  → Titel 9,6 · Text (--ink-soft) 5,5 · Eyebrow (green-800) 5,1
       Weiss 62 %  → Titel 6,7 · Text (--ink-soft) 3,9 · Eyebrow (green-800) 3,6
   62 % ist also die durchsichtigere Flaeche, aber `--ink-soft` und
   `--green-800` fallen darauf durch. WER `.glas` UEBER EIN FOTO LEGT, NIMMT
   DESHALB `--ink` fuer den Fliesstext und `--green-900` fuer kleine Labels
   (gemessen 6,6 und 5,4 : 1). Der Tausch geht in diese Richtung, weil die
   Durchsichtigkeit die Vorgabe war und die Schriftfarbe frei ist.
   Wer den Wert weiter senkt, muss neu messen — 4,5 : 1 gilt fuer Fliesstext
   und, weil der Eyebrow nur .74rem gross ist, auch fuer ihn.

   ⚠ NUR FLAECHE UND TIEFE, KEIN LAYOUT. Kein Polster, keine Breite, keine
   Schriftgroesse — das gehoert der Stelle, an der die Box steht. Sonst wird
   `.glas` zur zweiten Kartenklasse.

   ⚠ NUR AUF EINEM BILD ODER EINEM VERLAUF EINSETZEN. Auf einer weissen
   Flaeche ist durchscheinendes Weiss unsichtbar; dort gehoert `.card` hin. */
.glas {
  background: rgba(255, 255, 255, .62);
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: var(--r-lg);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  backdrop-filter: blur(20px) saturate(1.1);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .7) inset,
              0 26px 60px -34px rgba(4, 19, 16, .55);
}

/* Fuer dunkle Graende: dieselbe Bauform, nur andersherum. Die Schrift ist
   dort weiss, also ist die Flaeche die dunkle Seite. Noch nirgends im
   Einsatz — sie steht hier, damit die zweite Glassorte nicht wieder in
   einer Seite erfunden wird. */
.glas-dunkel {
  background: rgba(4, 20, 17, .58);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: var(--r-lg);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  backdrop-filter: blur(20px) saturate(1.1);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .10) inset,
              0 26px 60px -34px rgba(4, 19, 16, .8);
}

/* ============================================================================
   Hero-Aktionen mobil: untereinander und alle gleich lang (volle Breite).
   Gilt fuer die Sprungchips (.chip-links: rolle-*, akademie, community) UND die
   CTA-Zeile (.ihero-cta: prozess-*, vertragsform-*, branche-*, rolle-*, ...),
   auch bei nur einem Ghost-Chip. display:flex, weil manche Seiten es nur inline
   setzen; align-items:stretch macht die Chips gleich lang wie den CTA daneben.
   Bewusst am Dateiende als eigener Block. */
@media (max-width: 640px) {
  .ihero-cta,
  .chip-links { display: flex; flex-direction: column; align-items: stretch; }
  /* Loesungsseiten (.pl-hero: workforce/compliance/tender/pax-ai): Hero-CTA-Zeile
     genauso stapeln, damit der Ghost-Knopf so lang wird wie „Gespraech vereinbaren".
     Hoehere Spezifitaet (.ihero.pl-hero …), weil der Seiten-stilKopf `.ihero .cta-row`
     (0,2,0) inline nach components.css setzt. */
  .ihero.pl-hero .cta-row,
  .ihero.pl-hero .hero-cta { display: flex; flex-direction: column; align-items: stretch; }
  /* Startseiten-Hero (.hz) mobil komplett zentriert: `.hz-links` war display:block,
     dadurch stand der große „Pactos"-Schriftzug linksbuendig, obwohl der Rest mittig
     war. Als zentrierte Flex-Spalte sitzen Logo, Untertitel, Knoepfe und „Scrollen"
     mittig. Die zwei Knoepfe zusaetzlich gleich lang (volle Breite, gestapelt). */
  .hz-links { display: flex; flex-direction: column; align-items: center; }
  .hz-marke .cta-row { flex-direction: column; align-items: stretch; width: 100%; }
}

/* Startseite „Von der Jobvorlage bis zur Rechnung" mobil ganz weg.
   ⚠ ERST NUR `.va-fenster` AUSGEBLENDET — das war zu wenig. Die Ueberschrift
   steht NICHT neben der Abbildung, sondern IN ihr (section > .wrap >
   .hz-buehne > figure.va > .va-zeile > h2). Uebrig blieb deshalb der Titel,
   ein einzelnes Icon-Blaeschen und 150px Leere (gemessen: Sektion 274px hoch,
   Inhalt 122px). Karoline dazu am 10.09.2026 mit Screenshot: „das hier im
   Mobil löschen".
   Die ganze Sektion ausblenden statt nur die Figur, weil sonst eine Sektion
   mit Polster und ohne Inhalt stehen bliebe. `:has(figure.va)` trifft auf der
   Startseite genau eine Sektion (gemessen auf / und startseite.html: je 1,
   auf anderen Seiten 0) — kein zweites Vorkommen im Bestand. */
@media (max-width: 700px){ section:has(figure.va){ display: none; } }

/* Vendor-Intelligence-Module (workforce) — Mobil (<1000px, einspaltig):
   Screenshot IMMER vor der Beschreibung (auch bei gedrehten Modulen). Das
   Einfrieren auf den ersten (gruenen) Screenshot und das Unterdruecken des
   lila KI-Bilds macht der Film-/Klick-Guard in workforce.json; die :has-Regeln
   hier neutralisieren das Lila zusaetzlich, falls doch ein ist-ki-Frame aktiv
   wuerde. Hoehere Spezifitaet (.sec …) schlaegt die Inline-/Baustein-Regeln. */
/* Modul-Grid mobil: die Seite lief 38px breiter als das Fenster.
   Ursache ist die min-width:auto-Falle — `grid-template-columns:1fr` ist
   minmax(auto,1fr) und kann nicht unter die Mindestbreite des Inhalts
   schrumpfen. Der Knopf „Compliance Intelligence ansehen" steht auf
   white-space:nowrap und war 335px breit, die Spalte hatte 227px zur
   Verfuegung. Ergebnis: das Grid blaeht sich auf, das ganze Dokument wird
   breiter als der Bildschirm und laesst sich seitlich schieben — dadurch
   sieht JEDE zentrierte Sektion (z.B. die Zahlenbox) verschoben aus.
   Gemessen bei 375px: document.scrollWidth 413 -> 375, bei 320px 345 -> 320.
   Zwei Regeln: min-width:0 nimmt der Spalte den Mindestbreiten-Boden,
   white-space:normal laesst den langen Knopftext umbrechen. */
@media (max-width: 900px){
  .mod-grid > *{ min-width: 0; }
  .mod-copy .btn{ white-space: normal; text-align: center; }
}

/* Footer-Rechtslinks mobil: fuenf Links in einer nowrap-Flexzeile waren 532px
   breit in einem 295px-Footer und wurden rechts abgeschnitten (der Footer hat
   overflow:hidden, deshalb fiel es nur als fehlender Text auf). */
@media (max-width: 640px){
  .pf-legal{ flex-wrap: wrap; row-gap: 10px; }
}

@media (max-width: 999px){
  /* Screenshot IMMER ueber der Beschreibung — auch bei den Zusatzmodulen und
     bei Pax AI. Vorher galt das nur fuer `.gedreht`; drei Faelle fielen durch:
       #schichtplanung/#zeitnachweise setzen im Seiten-stilKopf eigene
       `order`-Werte mit id-Spezifitaet (1-1-0), die jede Klassenregel schlagen;
       #pactos-ai hat die Beschreibung im DOM zuerst stehen, dort reicht order:0
       nicht, es braucht -1.
     Deshalb `!important` und nicht nur hoehere Spezifitaet: der stilKopf steht
     als inline <style> NACH components.css, mit id-Selektoren kommt man ohne
     nicht durch. Gemessen bei 375px: .mod-visual liegt jetzt in allen elf
     Modulen ueber .mod-copy. */
  .mod-grid .mod-visual{ order: -1 !important; }
  .mod-grid .mod-copy{ order: 0 !important; }
}

/* Modulketten mobil: kuerzerer Halt vor dem grossen Wort.
   Der gepinnte Bereich (.mod-pin) ist die Scroll-Strecke, ueber die das grosse
   Wort steht — auf dem Desktop 112vh. Auf dem Telefon ist das eine leere
   Bildschirmlaenge zu viel: workforce hat dafuer laengst `84vh` plus
   `.mod-reveal{margin-top:-10vh}` im Seiten-stilKopf, pax-ai hatte es nie.
   Gemessen bei 390px auf pax-ai („Total Workforce Solutions"): Luft ueber dem
   Wort 457px, Abstand Wort→erstes Modul 500px; auf workforce 373 / 359.
   Danach 339 / 324 — etwas knapper, weil das Wort dort drei Zeilen hat.
   ⚠ `.sec …` (0,3,0 bzw. 0,4,0) ist noetig, weil pax-ai die Werte als
   `.mod-track.an .mod-pin` im inline <style> NACH components.css setzt.
   Fuer workforce sind es dieselben Zahlen wie bisher, dort aendert sich nichts. */
@media (max-width: 900px){
  .sec .mod-pin,
  .sec .mod-track.an .mod-pin{ height: 84vh; }
  .sec .mod-reveal,
  .sec .mod-track.an .mod-reveal{ padding-top: 56px; padding-bottom: 20px; }
  /* ⚠ DAS NEGATIVE MASS GILT NUR FUER DAS ERSTE MODUL. Es zieht das Modul unter
     den Wort-Halt, damit es beim Scrollen ueber „Total Workforce Solutions"
     bzw. „Kernmodule" laeuft — genau der Effekt, den Karoline meint.
     Auf pax-ai liegt jedes Modul in einem EIGENEN .mod-track (auf workforce
     stecken Wort und erstes Modul in einem). Eine Regel auf alle .mod-reveal
     hat dort deshalb JEDES Modul 10vh nach oben gezogen: die Karten klebten
     aneinander, und das nachfolgende .mod-reveal (z-index 2) lag ueber den
     Reitern des vorigen — „Ein Einsatzdatensatz" war nicht mehr anklickbar
     (gemessen: elementsFromPoint lieferte auf dem Reiter das fremde
     .mod-reveal als oberstes Element). */
  .sec .mod-track > .mod-pin + .mod-reveal,
  .sec .mod-track:has(> .mod-pin):not(:has(> .mod-reveal)) + .mod-track > .mod-reveal:first-child{ margin-top: -10vh; }
  .sec .mod-track:not(:has(> .mod-pin)) + .mod-track > .mod-reveal:first-child,
  .sec .mod-track.an .mod-reveal + .mod-reveal{ margin-top: 0; }
}

/* Schnittstellen: die Systemtabelle wird auf dem Telefon zu Bloecken
   (`.sys-tbl, tbody, tr, td { display: block }` im Seiten-CSS). Die
   Tabellen-UEBERSCHRIFT stand nicht in dieser Aufzaehlung und behielt
   `display: table-caption` — in einem Elternteil, das kein Tabellenkasten mehr
   ist, schrumpft sie auf ihre Mindestbreite. Gemessen bei 390px: 77px statt
   309px, der Satz lief mit einem Wort je Zeile 14 Zeilen tief. */
.sys-tbl caption{ display: block; }

/* Hero-Knoepfe auf schnittstellen (.ihero ohne .pl-hero) mobil gleich lang.
   Der Block am Dateiende deckt `.ihero-cta`, `.chip-links` und
   `.ihero.pl-hero .cta-row` ab — diese Seite nutzt `.cta-row` in einem
   schlichten `.ihero`. Gemessen bei 390px: 251px und 237px, jetzt beide gleich. */
@media (max-width: 640px){
  .ihero .cta-row{ display: flex; flex-direction: column; align-items: stretch; }
}

/* Datensicherheit (security.html) — Hero mobil.
   1) Der Mono-Kicker „Datensicherheit" lag UNTER der Navigation. Die Leiste ist
      fixiert und bei 375px 81px hoch, der Hero hat aber nur
      `padding: clamp(48px, 6vw, 92px)` — auf dem Telefon greift das Minimum von
      48px. Gemessen: Kicker begann bei y=56, die Leiste endete bei y=81, also
      25px dahinter. Auf dem Desktop reichen die 92px, deshalb nur hier.
      Jetzt 120px: 81px Leiste + 39px Luft (nachgemessen 47px bis zur
      Oberkante des Kickers, weil er selbst noch Zeilenluft hat).
   2) Die zwei Hero-Knoepfe gleich lang, wie ueberall sonst auf dem Telefon.
      `.shero-tat` ist eine `flex-wrap:wrap`-Zeile — untereinander waren sie
      dadurch verschieden breit (233px und 184px), jetzt beide 295px.
   ⚠ `header.shero` (0,1,1) bzw. `.shero .shero-tat` (0,2,0), weil das
   Seiten-CSS als inline <style> nach components.css steht. */
@media (max-width: 640px){
  header.shero{ padding-top: 120px; }
  .shero .shero-tat{ flex-direction: column; align-items: stretch; }
  .shero .shero-tat .btn{ width: 100%; justify-content: center; }
}

/* Zwei Problem-Buehnen hintereinander (compliance: „Ist-Zustand bei Endkunden"
   und „… bei Personaldienstleistern") brauchen mobil Luft dazwischen. Auf dem
   Desktop sind es gepinnte Scroll-Buehnen, da stossen sie absichtlich
   aneinander; mobil steht der zweite Kopf sonst direkt unter der letzten Karte
   der ersten Buehne (gemessen: 0px Abstand). */
@media (max-width: 900px){
  .probleme + .probleme{ margin-top: 64px; }
}

/* Kundenkarten (.ref35, Baustein kundenreferenzen) mobil alle gleich hoch
   (Karoline, 10.09.2026). Vorher trug die aktive Karte die Hoehe
   (position:relative), die drei anderen lagen absolut darueber — beim
   Weiterschalten sprang der Kasten. Gemessen bei 375px auf workforce:
   785 / 827 / 656 / 863px, also bis zu 207px Versatz; danach 863px in allen
   vier Stellungen. Jetzt liegen alle Karten im selben Rasterfeld, der Kasten
   ist so hoch wie die laengste Karte.
   ⚠ HIER UND NICHT IN bausteine/kundenreferenzen.css: workforce.json traegt
   eine eigene Kopie dieser Regeln im stilKopf, das Baustein-Stylesheet wird
   dort gar nicht eingebunden (gemessen: `.ref35-taf .ref35-karte` kam in
   dist/index.html an, in dist/workforce.html nicht). `.ref35-taf .ref35-karte`
   (0,2,0) schlaegt beide Kopien von `.ref35-karte{position:absolute}`.
   `pointer-events` bleibt unberuehrt: der Baustein setzt es schon auf none und
   nur `.an` auf auto, die verdeckten Karten fangen also keine Klicks. */
@media (max-width: 900px){
  .ref35-taf{ display: grid; }
  .ref35-taf .ref35-karte{ position: relative; grid-area: 1 / 1; inset: auto; }
}

/* Implementierungs-Zeitstrahl mobil: die Schiene (.flow-track) und der
   Abschlusspunkt (.flow-end) sind dort schon ausgeblendet — die Knoten
   (.fi-node) blieben stehen und schwebten als gruene Punkte ueber den
   Phasen-Chips, ohne Linie, an die sie gehoeren (Karoline, 10.09.2026).
   `.flow-item .fi-node` (0,2,0) schlaegt das seiteneigene `.fi-node`, das als
   inline <style> nach components.css steht. Gilt fuer workforce und
   compliance, die beide den Baustein implementierungs-timeline nutzen. */
@media (max-width: 900px){
  .flow-item .fi-node{ display: none; }
}

/* Lila „+KI-Funktion"-Flaeche unterdruecken, solange noch das LIVE-Mockup
   laeuft. ⚠ ERST AB 561px: darunter zeigt mock-kette.css statt des Mockups das
   Screenshot-Bild, und das liegt im ::after. Die Regel galt vorher bis 0px und
   hat damit auf dem Telefon das Bild von Pax AI mit ausgeblendet — die Kachel
   war leer tuerkis (Karoline, 10.09.2026: „Wieso ist bei Pactos AI kein
   Bild?"). Gemessen: getComputedStyle(v,'::after').display war 'none'. */
@media (min-width: 561px) and (max-width: 999px){
  .sec .mod-visual:has(.mod-frame.is-on.ist-ki){ background: none; }
  .sec .mod-visual:has(.mod-frame.is-on.ist-ki) .ki-flagge{ display: none; }
  .sec .mod-visual:has(.mod-frame.is-on.ist-ki)::after{ display: none; }
}
