/* ==========================================================================
   controlpunkt.com, Designsystem v4
   Stand 2026-07-14. Spezifikation: docs/DESIGN.md.

   v2 ("Messzeichnung") ist gestrichen. Passkreuze, Gradnetz, Kennungen,
   Register, Randnotizen, Blattkopf und Maßstabsleiste sind entfernt: sie
   waren Kostüm, kein Träger. Was bleibt, kommt aus dem Geschäft:
   der dunkle Grund, das EINE helle Blatt (das Dokument für den Großkunden)
   und der Druckvektor (die Kernaussage als Bild).

   Kanonische Marken-Werte (die einzigen drei Hex-Anker, alles andere ist
   daraus in OKLCH abgeleitet, keine zweite Palette):
     Punkt-Violett  #9842F3
     Canvas         #1E162C   (entschieden Tommy 2026-07-17; #0E1726 ist
                               nur noch historischer Papierwert)
     Amber          #F59E0B   (genau einmal: der Druckvektor des Risikoteams)

   Schrift: Archivo (die Seite), Azeret Mono (NUR Zahlen, Preise, Rufnummer),
   Poppins (nur das Wortzeichen). Alle selbst gehostet, kein CDN.

   Das System gilt auf ALLEN Seiten: eine Spalte (.wrap), eine Sektion
   (.section), ein Kopf (.hero). Kein Sonderraster für die Startseite.
   ========================================================================== */

/* --- 1. Schriften -------------------------------------------------------- */

/* Poppins, ausschliesslich für das Wortzeichen (bestehende Identität). */
@font-face {
  font-family: "Poppins"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/assets/fonts/poppins-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+20AC;
}

/* Archivo, variabel (wght 100..900), OFL, Omnibus Type. Die Seitenschrift. */
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("/assets/fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("/assets/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

/* Azeret Mono, variabel (wght 400..600), OFL, Displaay.
   NUR Zahlen, Preise, Dauer-Angaben, Rufnummer. Nie Fließtext,
   nie Pseudo-Kennungen, nie Formularlabel. */
@font-face {
  font-family: "Azeret Mono"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("/assets/fonts/azeret-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+20AC, U+2122;
}
@font-face {
  font-family: "Azeret Mono"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("/assets/fonts/azeret-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

/* --- 2. Tokens ----------------------------------------------------------- */
/* FARBSTRATEGIE, committed (Tommy, 14.07.).
   Vorher: dunkles Marineblau plus ein leuchtender Akzent. Das ist wörtlich
   Anti-Referenz 1 aus PRODUCT.md (der MSSP-Reflex): die Schlösser waren weg,
   die Farbwelt war dieselbe. Auf die Kategorie Security-Beratung rät ein
   Fremder diese Palette im ersten Versuch.

   Jetzt: Punkt-Violett trägt als FLÄCHE. Drei Oberflächen, drei
   Bedeutungen, sonst nichts. Jede ist eine Klasse, die dieselben Tokens neu
   belegt. Es gibt keine zweite Palette, nur drei Belegungen einer Palette.

     1. DAS FELD (.brandfield)  Getränktes Violett. Hier spricht controlpunkt:
                               Kopfzeile, Kopf, Abgrenzung, Vertrauen, Kontakt,
                               Fußzeile. Weiße Typo, keine Icons.
     2. DER GRUND (:root)      Violettschwarz, KEIN Marineblau. Hier wird
                               gezeichnet und belegt: das Netz, die Fälle.
     3. DAS BLATT (.invert)    Papierweiß. Das Dokument, das der Kunde
                               jemandem vorlegt, der Macht über ihn hat.
                               Unverändert. Es ist die einzige Fläche mit
                               dieser Bedeutung.

   Alle Neutralen kippen auf die Marken-Hue (301). Kein reines Schwarz, kein
   reines Weiß. Kontraste unten sind gerechnet (sRGB, WCAG 2.x), nicht
   geschätzt. */
/* DIE ZEICHENFLÄCHE (.pressure). Der Druckvektor ist eine Zeichnung: seine
   Marken sind violett, und Violett auf Violett trägt keine Information. Er
   steht auf /fahrplan im Kopf, also auf dem FELD, und dort wäre die Platte,
   auf die der Amber-Pfeil auftrifft, unsichtbar (1.9:1). Also stellt er sich
   den Grund selbst wieder her. Dieselben Werte wie :root, an EINER Stelle
   deklariert: eine Selektorliste, keine zweite Palette. */
:root, .pressure {
  color-scheme: dark;

  /* Kanon. Die drei Hex-Anker der Marke, alles andere ist daraus abgeleitet. */
  --cp-violet:  #9842F3;   /* oklch(0.585 0.247 301) */
  --cp-amber:   #F59E0B;
  --cp-canvas:  #0E1726;   /* NUR historischer Papierwert, wird nirgends neu
                              verwendet. Markengrund ist #1E162C (--cp-ground),
                              entschieden Tommy 2026-07-17, gilt auch LinkedIn. */
  --cp-hue: 301;

  /* Violett-Rampe, OKLCH, eine Hue */
  --cp-violet-text:  oklch(0.82 0.130 var(--cp-hue));          /* Links, Marken auf Grund, 9.4:1 */
  --cp-violet-lift:  oklch(0.72 0.190 var(--cp-hue));          /* Preise, Ziffern auf Grund, 6.4:1 */
  --cp-violet-deep:  oklch(0.45 0.215 var(--cp-hue));          /* Violett auf dem hellen Blatt */
  --cp-violet-line:  oklch(0.585 0.247 var(--cp-hue) / 0.42);  /* gezogene Linien, Rahmen */
  --cp-violet-wash:  oklch(0.585 0.247 var(--cp-hue) / 0.10);  /* Flächen-Tints */

  /* Amber, ausschließlich der Druckvektor auf /fahrplan. Genau einmal. */
  --cp-amber-text: oklch(0.80 0.155 70);

  /* DER GRUND. Violettschwarz (#1E162C), nicht Marineblau. */
  --cp-ground:   oklch(0.222 0.042 var(--cp-hue));
  --cp-ground-2: oklch(0.278 0.046 var(--cp-hue));   /* gehobene Fläche: Karten, Panele */
  --cp-ink:      oklch(0.960 0.010 295);             /* Überschriften, 15.5:1 */
  --cp-ink-2:    oklch(0.855 0.022 292);             /* Fließtext, 11.1:1 */
  --cp-muted:    oklch(0.705 0.034 288);             /* Sekundärtext, 6.6:1 */

  /* Zwei Linienstärken mit klarer Zuständigkeit:
     --cp-rule-strong trägt JEDE sichtbare Begrenzung eines Bedienelements
     (Knopfrahmen, Feldunterkante). 3.9:1 auf dem Grund, WCAG 1.4.11 erfüllt.
     --cp-rule und --cp-rule-2 sind Haarlinien zur Gliederung und dürfen nie
     die einzige Begrenzung eines Bedienelements sein. */
  --cp-rule-strong: oklch(0.575 0.055 var(--cp-hue));  /* 3.9:1 */
  --cp-rule:        oklch(0.440 0.048 var(--cp-hue));
  --cp-rule-2:      oklch(0.335 0.045 var(--cp-hue));
  --cp-focus:       var(--cp-violet-text);
  --cp-danger:      oklch(0.72 0.16 25);

  /* Knopf-Vertrag: jede Oberfläche legt fest, wie ihr Hauptknopf aussieht.
     Auf dem Grund ist er Punkt-Violett mit Weiß (4.76:1). */
  --cp-btn-bg:      var(--cp-violet);
  --cp-btn-fg:      #fff;
  --cp-btn-bg-over: oklch(0.52 0.235 var(--cp-hue));

  /* Schrift */
  --cp-font:      "Archivo", "Helvetica Neue", Arial, sans-serif;
  --cp-font-mono: "Azeret Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --cp-font-mark: "Poppins", var(--cp-font);   /* nur Wortzeichen */

  /* Maße */
  --cp-max:    1180px;
  --gutter:    clamp(20px, 4vw, 48px);
  --measure:   62ch;

  /* Abstände, 8er-Modul */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px; --s-10: 128px;

  --cp-radius: 0px;   /* Keine abgerundeten Ecken. */

  /* Die Farbe des hellen Blattes, als Token. Die Übergabe-Marke im Netz IST
     ein kleines Stück dieses Blattes und muss es zitieren, nicht kopieren:
     der Wert stand dort hartkodiert und wäre beim nächsten Anfassen
     auseinandergelaufen. */
  --cp-paper: oklch(0.972 0.005 292);

  /* Das Liniennetz. Kein neues Farb-Token, nur Maße. DESIGN.md 9. */
  --net-track: 3px;     /* Linienstärke */
  --net-dot: 11px;      /* Station */
  --net-hub: 22px;      /* Der Knotenpunkt. Doppelter Stationsdurchmesser, offener
                           Ring statt voller Punkt: der Umsteigebahnhof ist keine
                           Station wie die anderen, er ist die, an der sich der
                           Weg entscheidet. Dritte und letzte Marke im System. */

  /* Aliasse für den Bestand (faelle, vertrauen, kontakt, Rechtstexte, /en/*).
     Sie erben damit dasselbe System, ohne dass ihr Markup sofort umgebaut
     werden muss. Keine zweite Palette, nur andere Namen für dieselben Tokens. */
  --cp-sheet:        var(--cp-ground-2);
  --cp-hairline:     var(--cp-rule);
  --cp-violet-ink:   var(--cp-violet-text);
  --cp-font-display: var(--cp-font);
  --cp-font-body:    var(--cp-font);
  --cp-max-wide:     var(--cp-max);
  --cp-measure:      var(--measure);
  --frame-max:       var(--cp-max);

  /* Der Kontrollpunkt. Fester Vermessungspunkt, das Signaturmotiv des
     Aufnahme-Auftritts. Ein Mass, zwei Bauteile (cp-fix, cp-fix--survey),
     keine neue Palette: beide zitieren --cp-violet und --cp-violet-deep. */
  --fix-survey: clamp(96px, 12vw, 132px);
}

/* DAS FELD. Getränktes Punkt-Violett, die tragende Fläche der Marke.
   Referenz: zuehlke.com, das getränkte Markenfeld. Eine gesättigte Farbe
   wird zum Markenraum, die Typo wird weiß, es gibt keine Icons und keinen
   zweiten Akzent. Weiß auf dem Feld: 8.2:1.
   Auf dem Feld ist Violett KEIN Akzent mehr, es ist der Grund. Der Akzent ist
   das Weiße. Deshalb werden Links, Preise und der Hauptknopf hier hell,
   nicht violett: Violett auf Violett trägt keine Information. */
.brandfield {
  --cp-ground:   oklch(0.440 0.170 var(--cp-hue));   /* #6431A0 */
  --cp-ground-2: oklch(0.375 0.165 var(--cp-hue));   /* vertiefte Fläche im Feld */
  --cp-ink:      oklch(0.990 0.006 var(--cp-hue));   /* 8.2:1 */
  --cp-ink-2:    oklch(0.945 0.022 var(--cp-hue));   /* 7.2:1 */
  --cp-muted:    oklch(0.855 0.050 var(--cp-hue));   /* 5.4:1 */
  --cp-rule-strong: oklch(0.720 0.095 var(--cp-hue)); /* 3.3:1, WCAG 1.4.11 */
  --cp-rule:     oklch(0.640 0.115 var(--cp-hue));
  --cp-rule-2:   oklch(0.560 0.140 var(--cp-hue));
  --cp-violet-text: oklch(0.990 0.006 var(--cp-hue));
  --cp-violet-lift: oklch(0.990 0.006 var(--cp-hue));
  --cp-violet-line: oklch(0.990 0.006 var(--cp-hue) / 0.45);
  --cp-violet-wash: oklch(0.990 0.006 var(--cp-hue) / 0.10);
  --cp-focus:    oklch(0.990 0.006 var(--cp-hue));
  --cp-btn-bg:      oklch(0.990 0.006 var(--cp-hue));
  --cp-btn-fg:      oklch(0.300 0.150 var(--cp-hue));   /* 13.4:1 auf dem Knopf */
  --cp-btn-bg-over: oklch(0.900 0.055 var(--cp-hue));
  background: var(--cp-ground);
  color: var(--cp-ink-2);
  color-scheme: dark;
}

/* Das helle Blatt: das Dokument, das der Kunde seinem Großkunden vorlegt.
   Der Grund dafür wird auf der Seite NICHT erklärt. */
.invert {
  --cp-ground:   oklch(0.972 0.005 292);
  --cp-ground-2: oklch(1 0 0);
  --cp-ink:      oklch(0.225 0.030 272);
  --cp-ink-2:    oklch(0.330 0.028 274);
  --cp-muted:    oklch(0.505 0.028 282);
  --cp-rule-strong: oklch(0.62 0.030 290);
  --cp-rule:     oklch(0.80 0.020 290);
  --cp-rule-2:   oklch(0.885 0.015 292);
  --cp-violet-text: var(--cp-violet-deep);
  --cp-violet-lift: var(--cp-violet-deep);
  --cp-focus:    var(--cp-violet-deep);
  --cp-btn-bg:      var(--cp-violet-deep);
  --cp-btn-fg:      #fff;
  --cp-btn-bg-over: oklch(0.36 0.190 var(--cp-hue));
  background: var(--cp-ground);
  color: var(--cp-ink-2);
  color-scheme: light;
}

/* --- 3. Basis ------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: auto; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
/* Landet die Seite direkt auf einem Anker (/faelle#saas), springt sie sofort
   dorthin statt sekundenlang ueber die halbe Seite zu fahren: die Fahrt
   liess Leser auf leeren dunklen Zwischenflaechen zurueck (R11, vier von
   sieben Personas, "fast den Tab geschlossen"). */
html:has(:target) { scroll-behavior: auto; }

body {
  margin: 0;
  background-color: var(--cp-ground);
  color: var(--cp-ink-2);
  font-family: var(--cp-font);
  font-size: 1.0625rem;
  font-weight: 400;
  line-height: 1.7;           /* helle Schrift auf dunklem Grund, +0.05 */
  -webkit-font-smoothing: antialiased;
}
/* KEIN overflow-x: hidden. Es stand hier und hat den Kopfzeilen-Überlauf
   auf dem Telefon lautlos verschluckt: bei 360px waren 20 von 44 Pixeln des
   Menüknopfs unerreichbar, und man konnte nicht einmal hinscrollen. Eine
   Sicherung, die den Fehler versteckt, statt ihn zu melden, ist schlimmer als
   keine. Überlauf wird an der Ursache repariert und bleibt sichtbar, wenn er
   wiederkommt. */

/* Sprungziele landen nicht bündig an der Oberkante. Zwölf Stationsanker
   zeigen hierher. */
[id] { scroll-margin-top: var(--s-7); }

h1, h2, h3, h4 { color: var(--cp-ink); margin: 0; text-wrap: balance; font-weight: 700; }
/* Typoskala. Vorher brach sie unten zusammen: h3 (19.2px) war nur 13 Prozent
   größer als der Fließtext (17px), das registriert niemand als Hierarchie.
   Jetzt: 48 / 32 / 23 / 17. Jeder Schritt mindestens 35 Prozent. */
h1 { font-size: clamp(1.95rem, 1.15rem + 2.4vw, 2.7rem); line-height: 1.08; letter-spacing: -0.03em; }
h2 { font-size: clamp(1.5rem, 1.15rem + 1.35vw, 2rem); line-height: 1.16; letter-spacing: -0.025em; }
h3 { font-size: clamp(1.3rem, 1.15rem + 0.5vw, 1.45rem); line-height: 1.3; letter-spacing: -0.015em; font-weight: 600; }
p  { margin: 0 0 var(--s-4); max-width: var(--measure); }
strong { color: var(--cp-ink); font-weight: 600; }

a { color: var(--cp-violet-text); text-underline-offset: 0.2em; text-decoration-thickness: 1px; transition: color 120ms ease; }
a:hover { text-decoration-thickness: 2px; }

/* Telefonnummer hinter einem Klick (2026-08-27): kein tel:-Link im Quelltext,
   Harvester ernten den Footer nicht mehr. Der Button traegt sich wie ein Link. */
.tel-reveal {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; color: var(--cp-violet-text);
  text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px;
}
.tel-reveal:hover { text-decoration-thickness: 2px; }

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

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

/* Die Utilities (mt-*, measure-*, subhead, ...) stehen als Abschnitt 19 am
   DATEIENDE, damit sie wie die frueheren Inline-Styles jede Komponenten-
   Regel gleicher Spezifitaet schlagen. Hier stand der alte mt-Block. */
.skip-link {
  position: absolute; left: var(--s-5); top: -80px; z-index: 90;
  background: var(--cp-violet); color: #fff; font-weight: 600;
  padding: var(--s-3) var(--s-5); text-decoration: none;
}
.skip-link:focus { top: var(--s-5); }

/* Zahlen. Mono ist die Instrumentenschrift: was gemessen oder bezahlt wird,
   steht in Mono. Sonst nichts. */
.num, .price, .amount, .fact b, .pricecard .amount, .contact__tel {
  font-family: var(--cp-font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* --- 4. Layout: eine Spalte, eine Sektion, ein Kopf ---------------------- */
/* Gilt auf jeder Seite. Es gibt kein zweites Raster. */
.wrap {
  width: min(var(--cp-max), 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section {
  padding-block: clamp(56px, 7vw, 104px);
  border-top: 1px solid var(--cp-rule-2);
}
.section--plain { border-top: 0; }
/* Typ B (DESIGN.md, Abschnitt "Angebotskarte und Flow"): kurze, inhaltlich
   fortlaufende Blöcke rücken zusammen, statt mit dem vollen Großabschnitts-
   Abstand (231px) auseinanderzustehen. Nur --s-6 (32px). Der erste Block eines
   Laufs behält den oberen Abstand zum Großabschnitt davor, der letzte den
   unteren zum nächsten. :has ist bereits im Einsatz (siehe .sitefoot). */
.section--flow + .section--flow { border-top: 0; padding-top: var(--s-6); }
.section--flow:has(+ .section--flow) { padding-bottom: var(--s-6); }
.hero { padding-block: clamp(48px, 7vw, 96px) clamp(40px, 5vw, 72px); }

.lead {
  font-size: clamp(1.1rem, 1rem + 0.5vw, 1.3rem);
  line-height: 1.55; color: var(--cp-ink-2); max-width: 54ch;
}
/* Kleinlabel. 0.8125rem = 13px ist die harte Untergrenze der Seite
   (DESIGN.md 9, die Anti-Söldner-Klausel). Sie galt bisher nur im Netz und
   wurde überall sonst gerissen, zuletzt vom Produktnamen selbst. Sie gilt
   jetzt für JEDES Label auf jeder Fläche. */
.eyebrow {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--cp-muted);
  margin: 0 0 var(--s-4); max-width: none;
}

/* Der Kontrollpunkt: fester Vermessungspunkt als Signaturmotiv. Zwei
   Bauteile, keine neue Farbe: beide zitieren nur --cp-violet und
   --cp-violet-deep, die bereits im Kanon stehen.
   cp-fix: die kleine Marke, immer neben einem echten Textlabel (Eyebrow).
   cp-fix--survey: das grosse Vermessungszeichen fuer die Aufnahme- und
   Faelle-Hero, Ring + Kernpunkt + Sichtlinien zu Knoten. Beide sind rein
   dekorativ (aria-hidden, focusable="false") und ersetzen nie ein Label. */
.cp-fix { flex: 0 0 auto; }
.cp-fix .fix-ring { fill: none; stroke: var(--cp-violet); stroke-width: 2; }
.cp-fix .fix-core { fill: var(--cp-violet); stroke: none; }
.cp-fix--onpaper .fix-ring, .sheet .cp-fix .fix-ring, .invert .cp-fix .fix-ring { stroke: var(--cp-violet-deep); }
.cp-fix--onpaper .fix-core, .sheet .cp-fix .fix-core, .invert .cp-fix .fix-core { fill: var(--cp-violet-deep); }
.cp-fix--survey { width: var(--fix-survey); height: auto; aspect-ratio: 132 / 104; flex: 0 0 auto; }
.cp-fix--survey .fix-ring  { fill: none; stroke: var(--cp-violet); stroke-width: 3; }
.cp-fix--survey .fix-core  { fill: var(--cp-violet); }
.cp-fix--survey .fix-sight { stroke: var(--cp-violet-line); stroke-width: 1.5; }
.cp-fix--survey .fix-node  { fill: none; stroke: var(--cp-violet-line); stroke-width: 1.5; }
.cp-fix--survey .fix-node--measured { fill: var(--cp-violet); stroke: none; }
@media (max-width: 480px) { .cp-fix--survey .fix-sight, .cp-fix--survey .fix-node { display: none; } }

/* Hero-Raster mit dem Vermessungszeichen links neben dem Anspruch, nur auf
   /aufnahme (/assessment) und /faelle (/cases). Unter 720px faellt es auf
   eine Spalte zurueck; das Zeichen steht im Markup vor .hero__claim, also
   stapelt es sich dort automatisch darueber, ohne eigene Regel. */
.hero--survey { display: grid; gap: var(--s-5); }
@media (min-width: 720px) {
  .hero--survey { grid-template-columns: auto minmax(0, 1fr); align-items: center; }
}
/* Finale Abnahme 2026-08-27: ab 1000px war die rechte Haelfte des Hero-Bands
   leer und das Vermessungszeichen hing klein links (Tommy: Leerflaechen).
   Jetzt traegt das Zeichen die rechte Haelfte: es ist die eine Grafik, die
   das Produkt bedeutet (der eingemessene Referenzpunkt, PRODUCT.md), keine
   Dekoration. Links bleibt der Claim in Lesebreite. */
@media (min-width: 1000px) {
  .hero--survey { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s-8); }
  .hero--survey .cp-fix--survey { order: 2; width: clamp(260px, 28vw, 400px); justify-self: end; }
}

/* --- 5. Kopfzeile, zweizeilig ---------------------------------------------
   B4e ist bindend: Rufnummer und E-Mail stehen im Kopf JEDER Seite, nicht
   erst ab 1220px. Zeile 1 trägt Wortzeichen und Erreichbarkeit, Zeile 2
   die Navigation. DESIGN.md Abschnitt 8. */
.masthead { padding-block: 0; border-bottom: 0; }

/* Zeile 1 ist ein Raster, kein Flexbalken mit space-between.
   Der alte Balken hat drei nicht schrumpfbare Kinder nebeneinander gestellt
   (Wortzeichen, Rufnummer mit white-space: nowrap, Menüknopf) und ist
   deshalb unter 400px aus der Seite gelaufen. Der Menüknopf, also die
   EINZIGE Navigation auf dem Telefon, lag bei 320px komplett außerhalb.
   Jetzt tragen Wortzeichen und Menüknopf die Zeile; die Rufnummer ist ein
   drittes Rasterkind, das unter 560px in eine eigene volle Zeile fällt,
   statt zu drängeln. Sie verschwindet nie (B4e, DESIGN.md 8), sie wird
   größer. */
.masthead__row1 {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--s-4);
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--cp-rule-2);
}
.logo { display: inline-flex; align-items: baseline; gap: 3px; text-decoration: none; min-width: 0; }
.logo span {
  font-family: var(--cp-font-mark); font-weight: 600; font-size: 1.3rem;
  letter-spacing: -0.02em; color: var(--cp-ink); white-space: nowrap;
}
/* Der Punkt ist das Signaturzeichen. Auf dem Grund ist er violett, auf dem
   Feld wäre Violett auf Violett unsichtbar: dort ist er die Papierfarbe.
   Der Punkt ist immer die Farbe, die die Fläche NICHT ist. */
.logo i { width: 7px; height: 7px; border-radius: 50%; background: var(--cp-violet); display: block; }
.brandfield .logo i { background: var(--cp-ink); }

.masthead__direct {
  grid-column: 2; justify-self: end; min-width: 0;
  display: flex; align-items: center; gap: var(--s-5);
}
.masthead__direct .tel {
  font-family: var(--cp-font-mono); font-size: 0.85rem; font-weight: 500;
  color: var(--cp-violet-text); text-decoration: none;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.masthead__direct .tel:hover { text-decoration: underline; text-underline-offset: 0.25em; }
.masthead__direct .mail { font-size: 0.85rem; color: var(--cp-ink-2); text-decoration: none; white-space: nowrap; }
.masthead__direct .mail:hover { color: var(--cp-ink); text-decoration: underline; text-underline-offset: 0.25em; }
.masthead__direct .lang { font-size: 0.8125rem; color: var(--cp-muted); letter-spacing: 0.06em; text-decoration: none; }
.masthead__direct .lang:hover { color: var(--cp-ink); }

/* Unter 1040px ziehen Mail und Sprachumschalter ins Menüpanel. */
@media (max-width: 1039px) {
  .masthead__direct .mail, .masthead__direct .lang { display: none; }
}
/* Unter 560px bekommt die Rufnummer eine eigene Zeile unter dem Wortzeichen.
   Damit ist der Überlauf baulich unmöglich, nicht nur unwahrscheinlich:
   in Zeile 1 stehen dann nur noch zwei Kinder. */
@media (max-width: 559px) {
  .masthead__row1 { grid-template-columns: minmax(0, 1fr) auto; row-gap: var(--s-3); }
  .masthead__direct {
    grid-column: 1 / -1; grid-row: 2; justify-self: start;
    padding-top: var(--s-3); border-top: 1px solid var(--cp-rule-2);
    width: 100%;
  }
  .masthead__direct .tel { font-size: 0.95rem; }
}

/* .nav sitzt bereits in <header class="wrap masthead">, das Mass und
   Gutter liefert. Kein zweites width/padding-inline hier, sonst rücken
   die Links gegenüber Zeile 1 nach innen und die Haarlinie bricht ab. */
.nav {
  display: flex; gap: var(--s-5); align-items: center;
  padding-block: var(--s-2); border-bottom: 1px solid var(--cp-rule-2);
}
.nav a {
  font-size: 0.95rem; font-weight: 500; color: var(--cp-ink-2); text-decoration: none;
  padding-block: var(--s-2); border-bottom: 1px solid transparent;
  transition: color 120ms ease, border-bottom-color 120ms ease;
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--cp-ink); border-bottom-color: var(--cp-violet); }
@media (max-width: 1039px) { .nav { display: none; } }

/* Mobile Navigation: details/summary, funktioniert ohne JavaScript. */
.nav-mobile { display: none; }
@media (max-width: 1039px) {
  .nav-mobile { display: block; position: relative; }
  .nav-mobile summary {
    list-style: none; cursor: pointer; width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--cp-rule);
  }
  .nav-mobile summary::-webkit-details-marker { display: none; }
  .nav-mobile summary::marker { content: ""; }
  .nav-mobile__icon, .nav-mobile__icon::before, .nav-mobile__icon::after {
    width: 18px; height: 1.5px; background: var(--cp-ink); display: block;
  }
  .nav-mobile__icon { position: relative; }
  .nav-mobile__icon::before, .nav-mobile__icon::after { content: ""; position: absolute; left: 0; }
  .nav-mobile__icon::before { top: -6px; }
  .nav-mobile__icon::after  { top: 6px; }
  .nav-mobile__panel {
    position: absolute; right: 0; top: calc(100% + var(--s-3)); z-index: 80;
    background: var(--cp-ground-2); border: 1px solid var(--cp-rule);
    padding: var(--s-5); min-width: 262px;
    display: flex; flex-direction: column; gap: var(--s-4);
    box-shadow: 0 14px 40px oklch(0.1 0.05 var(--cp-hue) / 0.5);
  }
  .nav-mobile__panel a { font-size: 1rem; font-weight: 500; color: var(--cp-ink); text-decoration: none; }
  .nav-mobile__panel a:hover { color: var(--cp-violet-text); }
  .nav-mobile__panel .tel, .nav-mobile__panel .mail {
    padding-top: var(--s-3); border-top: 1px solid var(--cp-rule-2);
    color: var(--cp-violet-text);
  }
  .nav-mobile__panel .tel {
    font-family: var(--cp-font-mono); font-variant-numeric: tabular-nums;
  }
  .nav-mobile__panel .mail { border-top: 0; padding-top: 0; }
  .nav-mobile__panel .lang { font-size: 0.85rem; color: var(--cp-muted); }
}

/* --- 6. Der zweispaltige Kopf und der Druckvektor -------------------------
   v4: .hero--home heißt .hero--split, weil er nicht mehr startseiten-eigen
   ist. Er steht jetzt auf /fahrplan, neben dem Druckvektor (DESIGN.md 7).
   Die Startseite bekommt einen einspaltigen Kopf plus das Liniennetz. */
.hero--split {
  display: grid; gap: clamp(40px, 5vw, 64px);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 1040px) {
  .hero--split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(48px, 5vw, 80px); }
}

/* Der Kopf der Startseite. Er ließ ab 1040px rund 45 Prozent der ersten
   Bildschirmbreite rechts leer stehen und schob das Netz komplett unter den
   Falz: bei 1440x900 begann die H2 bei 892px, die erste Stationszeile 209px
   UNTER der Kante. Das Netz hat .doors genau deshalb ersetzt, damit drei
   Türen gleichwertig sichtbar sind (PRODUCT.md, Grundsatz 5).
   Jetzt zwei Spalten: links die These und die Handlung (Knopf, Rufnummer),
   rechts die Erklärung und der Preis. Die Copy aus B1 bleibt vollständig
   und wörtlich, sie steht nur nebeneinander statt untereinander. Das ist
   der halbe Kopf in der Höhe, und das Netz rutscht über den Falz. */
.hero--home {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-6);
  align-items: start;
  padding-block: clamp(24px, 2.4vw, 32px) clamp(24px, 2vw, 28px);
}
@media (min-width: 1040px) {
  .hero--home {
    grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
    column-gap: clamp(40px, 4vw, 64px);
  }
}
/* Der Lead trägt im zweispaltigen Kopf die Erklärung, nicht die Stimme.
   Bei 1.3rem und 46ch war er 226px hoch und hat allein das Netz unter den
   Falz geschoben. Er bleibt wörtlich (B1), er wird nur ruhiger gesetzt. */
.hero--home .lead {
  margin-bottom: 0; max-width: 52ch;
  font-size: clamp(1.05rem, 0.98rem + 0.32vw, 1.15rem); line-height: 1.5;
}
.hero--home .actions { margin-top: var(--s-4); }

.hero__claim h1 { max-width: 20ch; }
/* Die Startseiten-H1 (SALES-STORY.md, Main Message) ist ein einzelner langer
   Fragesatz mit drei Adressaten, wörtlich aus dem Käufertest, nicht kürzbar.
   20ch würde ihn auf sieben bis acht Zeilen zwingen. Breiter setzen und die
   Schrift etwas zurücknehmen, damit er in drei bis vier Zeilen bricht, statt
   die Seite zu dominieren. Bricht bewusst über mehrere Zeilen (Bauauftrag). */
.hero--home .hero__claim h1 {
  max-width: 32ch;
  font-size: clamp(1.7rem, 1.05rem + 2.4vw, 2.5rem);
}
/* Zwei Sätze, zwei Rollen: die Lage des Käufers, dann die Entlastung.
   Die Entlastung trägt die volle Tinte. */
.hero__claim h1 .setup {
  display: block; color: var(--cp-muted); font-weight: 600;
  font-size: 0.62em; line-height: 1.25; letter-spacing: -0.02em;
  margin-bottom: var(--s-3);
}
.hero__claim h1 .relief { display: block; color: var(--cp-ink); }
.hero__claim .lead { margin-top: var(--s-6); }

/* Die Angebotszeile: Name, Dauer, Preis. Die einzige Stelle im Kopf mit Mono. */
.hero__offer {
  margin-top: var(--s-6); padding-top: var(--s-5);
  border-top: 1px solid var(--cp-rule);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-3) var(--s-4);
  max-width: none;
}
.hero__offer b { color: var(--cp-ink); font-weight: 600; }
/* KEIN Trenner als Haarlinie mehr. Er war als border-left gebaut, und sobald
   die Zeile umbrach (im schmalen Kopf ab Werk, auf dem Telefon immer), führte
   dieser Rahmen die neue Zeile an: dann stand dort genau der 2px-Seitenstreifen,
   der auf dieser Seite verboten ist, nur diesmal aus Versehen erzeugt.
   Ein Umbruch darf keine Dekoration erfinden können. Die drei Angaben stehen
   jetzt untereinander, getrennt durch Raum. */
.hero__offer {
  display: grid; row-gap: var(--s-1); justify-items: start;
}
.hero__offer span { padding-left: 0; border-left: 0; }
.hero__offer .price { color: var(--cp-violet-lift); font-size: 1.05rem; }

/* Die rechte Spalte des Startseiten-Kopfs. Sie stand als .hero__pitch leer:
   151px Inhalt in einer 449px hohen Zeile, darunter tote Fläche ohne Kante,
   die drei Käufer als Ladefehler lasen. Jetzt trägt sie die drei Fakten, die
   dieselben Käufer als Kaufgrund nannten: das Angebot als Klickziel und die
   beiden Fragen samt ihrer Einschränkung. Startseiten-lokal: .hero__offer
   bleibt für die sieben anderen Seiten unangetastet, dieses Bauteil hängt an
   .hero__facts. */
.hero__facts {
  display: grid; row-gap: var(--s-2);
  align-content: start;
}
.hero__fact {
  border-top: 1px solid var(--cp-rule);
  padding-top: var(--s-3);
  display: grid; row-gap: var(--s-2);
}
.hero__fact__q {
  margin: 0; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--cp-muted); max-width: none;
}
.hero__fact__a {
  margin: 0; font-size: 1rem; line-height: 1.4; font-weight: 600;
  color: var(--cp-ink); max-width: 46ch;
}
.hero__fact__limit {
  margin: 0; font-size: 0.9rem; line-height: 1.5; color: var(--cp-muted);
  max-width: 50ch;
}
/* Plate 1: das Angebot ist das einzige Klickziel im Kopf rechts. Ein <a> mit
   Flächen-Hover, sonst nichts. Plate 2 und 3 sind Prosa mit Inline-Link, kein
   Block-Hover, kein Rahmen, kein Flächen-Tint. */
a.hero__fact--offer {
  text-decoration: none; color: inherit;
  transition: border-color 120ms ease;
}
.hero__fact--offer b {
  color: var(--cp-ink); font-weight: 600;
  text-decoration: underline; text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  transition: color 120ms ease;
}
.hero__fact--offer span { max-width: none; }
.hero__fact--offer .price {
  color: var(--cp-violet-lift); font-size: 1.05rem;
  font-family: var(--cp-font-mono); font-variant-numeric: tabular-nums;
}
a.hero__fact--offer:hover { border-top-color: var(--cp-rule-strong); }
a.hero__fact--offer:hover b { color: var(--cp-ink); }
a.hero__fact--offer:active { transform: translateY(1px); }

/* Angebotskarte im Hero der Unterseiten (Typ A, DESIGN.md). Zitiert die Token
   der .pricecard, steht aber im Kopf auf dem Feld. Sie wird NIE auf Claim-Höhe
   gestreckt: die Höhe kommt aus echtem Inhalt. Vertikal zentriert (align-self:
   center, Tommy 2026-07-24), damit die Rest-Leere sich oben und unten teilt. NICHT
   interaktiv: kein <a>, kein <button>, kein Flächen-Hover. Der eine Primärknopf
   bleibt links im Claim. Seitenlokal: nur auf isms-luecken, zweitmeinung, pe,
   detection und ihren EN-Spiegeln. */
.hero__offercard {
  border: 1px solid var(--cp-violet-line);
  background: var(--cp-ground-2);
  padding: var(--s-6);
  align-self: center;
}
.hero__offercard__name {
  margin: 0; max-width: none;
  color: var(--cp-ink); font-size: 1.05rem; font-weight: 600;
}
.hero__offercard__price {
  margin: var(--s-2) 0 0; max-width: none;
  font-family: var(--cp-font-mono); font-variant-numeric: tabular-nums;
  color: var(--cp-violet-lift); font-size: 1.15rem;
}
.hero__offercard dl {
  margin: var(--s-5) 0 0; display: grid; grid-template-columns: auto 1fr;
  gap: var(--s-5); border-top: 1px solid var(--cp-rule-2); padding-top: var(--s-5);
}
.hero__offercard dt {
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--cp-muted); align-self: center;
}
.hero__offercard dd { margin: 0; color: var(--cp-ink); font-weight: 600; font-size: 0.95rem; }

/* Rechte Kopf-Spalte, wenn dort mehr als ein Element steht: Karte plus Grenz-
   Panel auf /detection, Karte plus die zwei Qualifier-Absätze auf /pe. Ein
   Stapel, damit die Elemente EINE Rasterzelle teilen und nicht als getrennte
   Grid-Kinder in eigene Spalten brechen. */
.hero__stack {
  display: grid; gap: var(--s-5); align-content: start; align-self: center;
}
.hero__stack > .hero__qualifier { margin: 0; max-width: none; }

/* Der Druckvektor. Drei Bahnen, zwei Vektoren, eine Aussage:
   der amberfarbene Druck endet auf der controlpunkt-Bahn. */
.pressure {
  margin: 0;
  display: grid;
  column-gap: var(--s-5);
  border: 1px solid var(--cp-rule);
  padding: var(--s-5) var(--s-5) var(--s-6);
  background: var(--cp-ground);
  color: var(--cp-ink-2);
}

.pressure__lane {
  grid-column: 1 / -1;
  border: 1px solid var(--cp-rule);
  padding: var(--s-4) var(--s-5);
}
.pressure__who {
  margin: 0; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--cp-muted); max-width: none;
}
.pressure__say {
  margin: var(--s-2) 0 0; font-size: 1rem; line-height: 1.45;
  color: var(--cp-ink); font-weight: 600; max-width: none;
}
.pressure__add {
  margin: var(--s-2) 0 0; font-size: 0.9rem; line-height: 1.5;
  color: var(--cp-muted); max-width: none;
}

/* Bahn 1: das Risikoteam. Der einzige Amber-Ort der Seite. */
.pressure__lane--them { border-color: var(--cp-amber); }
.pressure__lane--them .pressure__who { color: var(--cp-amber-text); }

/* Bahn 2: controlpunkt. Hier endet der Druck. Die obere Kante ist die Platte,
   auf die der Amber-Pfeil auftrifft: 3px, massiv, violett. */
.pressure__lane--us {
  border: 1px solid var(--cp-violet-line);
  border-top: 3px solid var(--cp-violet);
  background: var(--cp-violet-wash);
}
.pressure__lane--us .pressure__who { color: var(--cp-violet-text); }
.pressure__brand {
  font-family: var(--cp-font-mark); font-weight: 600; letter-spacing: -0.02em;
  text-transform: none; font-size: 0.95rem; color: var(--cp-ink);
}

/* Bahn 3: das Unternehmen des Kunden. Kein Amber. Das ist die Aussage. */
.pressure__lane--you { border-color: var(--cp-rule); }

/* Die Vektorspalte zwischen den Bahnen. */
/* Die Vektorzeile spannt beide Spalten und wiederholt das Spaltenmaß der
   Tafel. Kein subgrid: das Maß steht an einer Stelle, in --pressure-rail. */
.pressure { --pressure-rail: 40px; }
@media (min-width: 600px) { .pressure { --pressure-rail: 56px; } }
.pressure { grid-template-columns: var(--pressure-rail) minmax(0, 1fr); }
.pressure__gap {
  display: grid; grid-column: 1 / -1;
  grid-template-columns: var(--pressure-rail) minmax(0, 1fr);
  column-gap: var(--s-5);
  align-items: stretch;
  min-height: 84px;
}
.pressure__vectors { position: relative; display: flex; justify-content: center; gap: 14px; }
.pressure__note {
  align-self: center; margin: var(--s-4) 0; padding: 0;
  font-size: 0.88rem; line-height: 1.5; color: var(--cp-ink-2); max-width: 34ch;
}
.pressure__note b {
  display: block; position: relative; padding-left: var(--s-4);
  color: var(--cp-ink); font-weight: 600;
}
.pressure__note b + b { margin-top: var(--s-3); }
/* Der Punkt vor der Zeile hat die Farbe des Vektors, zu dem sie gehört. */
.pressure__note b::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 7px; height: 7px; border-radius: 50%;
}
.pressure__note .amb { color: var(--cp-amber-text); }
.pressure__note .amb::before { background: var(--cp-amber); }
.pressure__note .vio { color: var(--cp-violet-text); }
.pressure__note .vio::before { background: var(--cp-violet); }

/* Die Vektoren selbst: eine Linie, eine Spitze.
   Der Amber-Pfeil zeigt nach unten und endet exakt an der Platte.
   Der violette zeigt nach oben, zurück zum Risikoteam: das sind die
   Gespräche, die wir führen.
   Der dritte zeigt nach unten, zu Ihnen: das ist das Dokument. */
.vec { position: relative; width: 2px; }
.vec::after {
  content: ""; position: absolute; left: 50%; width: 0; height: 0;
  transform: translateX(-50%);
  border-left: 5px solid transparent; border-right: 5px solid transparent;
}
.vec--pressure { background: var(--cp-amber); }
.vec--pressure::after { bottom: -1px; border-top: 8px solid var(--cp-amber); }
.vec--back { background: var(--cp-violet); }
.vec--back::after { top: -1px; border-bottom: 8px solid var(--cp-violet); }
.vec--deliver { background: var(--cp-violet); }
.vec--deliver::after { bottom: -1px; border-top: 8px solid var(--cp-violet); }

.pressure__caption {
  grid-column: 1 / -1; margin: var(--s-6) 0 0; padding-top: var(--s-4);
  border-top: 1px solid var(--cp-rule-2);
  font-size: 0.88rem; line-height: 1.5; color: var(--cp-muted); max-width: none;
}
.pressure__caption b { color: var(--cp-ink-2); font-weight: 600; }

/* --- 7. Das Liniennetz ----------------------------------------------------
   v4.1: ersetzt .doors. Der Linienkopf IST die Tür (Name, Auslöser, Preis,
   Link auf die Seite). Gebaut in HTML/CSS, nicht als SVG: die Bedeutung liegt
   in der Struktur (figure > je Linie ein <ol> mit <a>-Stationen), die
   Geometrie ist aria-hidden und rein dekorativ. DESIGN.md 3, 4, 5, 9, 10.
   Keine Legende: Form, Füllung und Empfängertext tragen die Bedeutung
   dreifach redundant.

   REPARATUR (Review 14.07.), drei Fehler, die das Bild gegen seine eigene
   Aussage arbeiten ließen:

   a) DIE LINIEN ENDETEN NICHT DORT, WO SIE ENDEN. Das Gleis lief mit
      left:0/right:0 über die letzte Station hinaus, bei Linie 3 waren 49
      Prozent der gezeichneten Strecke Nichts. Ein Fahrplan ohne Ende ist
      genau das, was der CTO fürchtet: das offene Programm ohne Deckel.
      DAS ENDE IST DAS VERKAUFSARGUMENT. Jetzt zeichnet JEDE Station ihr
      eigenes Gleisstück bis zur nächsten Marke, und die letzte Station
      zeichnet keines. Das Gleis kann baulich nicht mehr überstehen.
   b) DER STAMM lief unter den letzten Abzweig. Jetzt zeichnet jede Linie
      außer der letzten ihr Stammstück bis zum nächsten Abzweig. Der Stamm
      endet am letzten Abzweig, weil er aus ihnen besteht.
   c) DIE ENDPUNKT-MARKE WAR UNSICHTBAR: ein violetter Balken auf einem
      violetten Punkt. Der Endbalken ist jetzt höher als der Punkt UND
      heller als die Schiene (--cp-violet-text, 9.4:1 auf dem Grund gegen
      3.7:1 der Schiene). Form und Helligkeit, nicht Violett auf Violett. */
/* Der Abschnitt, in dem das Netz steht. Er ist der GRUND, nicht das Feld:
   auf dem Feld wären die violetten Marken Violett auf Violett, und die
   Übergabe-Marke (papierweiß gefüllt) hätte keinen Unterschied mehr zur
   Schiene. Das Netz braucht die dunkle Zeichenfläche, deshalb bekommt es
   sie. */
.net-section { padding-block: clamp(24px, 2.4vw, 32px) clamp(56px, 7vw, 104px); }
.net { margin: var(--s-5) 0 0; }

/* Der Satz unter dem Netz. Er nennt den Beleg, ohne einen Kunden zu nennen, und
   führt auf die Fälle. Er erklärt nicht die Zeichnung, er nennt ihre Herkunft. */
.net__note {
  margin: var(--s-7) 0 0; padding-top: var(--s-5);
  border-top: 1px solid var(--cp-rule-2); max-width: 62ch; color: var(--cp-ink-2);
}
.net__note a { color: var(--cp-violet-text); }

/* Schlanke Verzweigung (2026-07-16): loest das dichte Liniennetz auf der
   Startseite ab. Aufnahme als Knoten, fuenf Wege als je eine Zeile
   (Name + Preis), Detail liegt auf den Einzelseiten. Die alten .net__*-Regeln
   sind ungenutzt. */
.net-map { margin: var(--s-6) 0 0; max-width: 46rem; }
.net-map__hub {
  display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap;
  text-decoration: none; color: var(--cp-ink);
  position: relative; padding-left: 30px; min-height: 34px;
}
.net-map__hub::before {
  content: ""; position: absolute; left: 0; top: calc(50% - 9px);
  width: 18px; height: 18px; border-radius: 50%;
  border: var(--net-track) solid var(--cp-violet); background: transparent;
}
.net-map__branches {
  list-style: none; margin: var(--s-1) 0 0; padding: 0;
  margin-left: 8px; border-left: var(--net-track) solid var(--cp-violet-line);
}
.net-map__branch {
  display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap;
  text-decoration: none; color: var(--cp-ink);
  position: relative; padding: var(--s-4) 2px var(--s-4) 22px;
}
.net-map__branch::before {
  content: ""; position: absolute; left: -7px; top: calc(50% - 5.5px);
  width: var(--net-dot); height: var(--net-dot); border-radius: 50%;
  background: var(--cp-violet);
}
.net-map__name { flex: 1 1 auto; font-weight: 600; font-size: 1.05rem; transition: color 120ms ease; }
.net-map__price {
  flex: 0 0 auto; font-family: var(--cp-font-mono); font-size: 0.95rem;
  color: var(--cp-violet-text); white-space: nowrap;
}
.net-map__note { display: block; font-size: 0.82rem; font-weight: 400; color: var(--cp-muted); margin-top: 2px; }
/* Dauer vor Preis (Runde 15, Variante B): die Dauer steht als Note unter dem
   Namen, der Betrag bleibt rechts. Kein Betrag entfaellt. */
.net-map__hub .net-map__name { font-size: 1.2rem; }
.net-map__branch:hover .net-map__name,
.net-map__hub:hover .net-map__name { color: var(--cp-violet-text); }
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .net-map__branch::before { transition: transform 120ms ease; }
  .net-map__branch:hover::before { transform: scale(1.3); }
}
.net-map a:focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 3px; }
@media (max-width: 520px) {
  .net-map__price { flex-basis: 100%; }
}


@media (max-width: 1039px) {
  .net { margin-top: var(--s-5); }
}

/* --- 8. Das helle Blatt: Angebot und Preiskarte -------------------------- */
.offer { display: grid; grid-template-columns: 1fr; gap: var(--s-7); margin-top: var(--s-6); }
@media (min-width: 900px) { .offer { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); } }
/* Angebot ohne zweite Karte: eine Spalte, sonst steht auf Desktop die halbe
   Breite leer neben der Liste. */
.offer--single { grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
@media (min-width: 900px) { .offer--single { grid-template-columns: minmax(0, 1fr); } }
.offer__list { list-style: none; margin: 0; padding: 0; }
.offer__list li {
  position: relative; padding-left: var(--s-6); margin-bottom: var(--s-5); max-width: 48ch;
}
.offer__list li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 9px; height: 9px; border-radius: 50%; background: var(--cp-violet);
}
.pricecard {
  border: 1px solid var(--cp-violet-line);
  padding: var(--s-6); align-self: start; background: var(--cp-ground-2);
}
.pricecard .amount {
  font-size: clamp(1.5rem, 1rem + 1.5vw, 2rem); line-height: 1.15;
  letter-spacing: -0.03em; color: var(--cp-ink); margin: 0; max-width: none;
}
.pricecard dl {
  margin: var(--s-5) 0 0; display: grid; grid-template-columns: auto 1fr;
  gap: var(--s-3) var(--s-5); border-top: 1px solid var(--cp-rule-2); padding-top: var(--s-5);
}
.pricecard dt {
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--cp-muted); align-self: center;
}
.pricecard dd { margin: 0; color: var(--cp-ink); font-weight: 600; font-size: 0.95rem; }
.pricecard .fineprint {
  margin: var(--s-5) 0 0; font-size: 0.9rem; color: var(--cp-muted); max-width: none;
}

/* --- 9. Ablauf, Argument, Arithmetik, Verzichte -------------------------- */
.steps { list-style: none; margin: var(--s-6) 0 0; padding: 0; counter-reset: step; }
.steps li {
  position: relative; counter-increment: step;
  padding: var(--s-4) 0 var(--s-4) var(--s-8);
  border-top: 1px solid var(--cp-rule-2);
  max-width: 56ch;
}
.steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; left: 0; top: var(--s-4);
  font-family: var(--cp-font-mono); font-size: 0.8125rem; font-weight: 500;
  color: var(--cp-violet-text); letter-spacing: 0.06em;
}
.steps strong { color: var(--cp-ink); }

/* DAS ARGUMENT. Vorher ein 2px-Seitenstreifen links. Der Streifen ist im
   Skill ein absolutes Verbot und gilt dort als das verlässlichste Signal,
   dass ein Modell dieses CSS geschrieben hat. Er kam auf dieser Seite
   fünfmal vor.
   Ersatz ist kein zweiter Streifen, sondern eine FLÄCHE: das Argument steht
   auf dem Markenfeld. Es ist der Satz, mit dem sich controlpunkt von einer
   Compliance-Plattform unterscheidet, also spricht hier die Marke, und die
   Marke hat jetzt eine Fläche. Klasse im Markup: class="argument brandfield".
   Die Tokens kommen aus .brandfield, hier steht kein einziger Farbwert. */
.argument {
  padding: var(--s-6) clamp(20px, 3vw, 32px);
  margin-top: var(--s-6);
}
.argument p {
  font-size: clamp(1.12rem, 1rem + 0.55vw, 1.4rem); line-height: 1.5;
  color: var(--cp-ink); max-width: var(--measure); font-weight: 500; letter-spacing: -0.012em;
}
.argument p:last-child { margin-bottom: 0; }
/* Das Gründer-Zitat ist ein echtes <blockquote>: der Browser-Default-Rand
   wird durch den bestehenden .argument-Takt ersetzt, keine neue Zahl. */
blockquote.argument { margin: var(--s-6) 0 0; }
blockquote.argument cite {
  display: block; margin-top: var(--s-3); font-style: normal;
  font-size: 0.88rem; color: var(--cp-muted);
}

/* Tür 3: die Arithmetik. Subjekt ist das System, nie der Mensch. */
.arith {
  list-style: none; margin: 0 0 var(--s-6); padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr);
  border-top: 1px solid var(--cp-rule);
}
@media (min-width: 700px) { .arith { grid-template-columns: repeat(4, 1fr); } }
.arith li { padding: var(--s-5) var(--s-4) var(--s-5) 0; border-right: 1px solid var(--cp-rule-2); }
.arith li:last-child { border-right: 0; }
.arith b {
  display: block; font-family: var(--cp-font-mono); font-weight: 500;
  font-size: clamp(1.4rem, 1rem + 1.3vw, 2.1rem); line-height: 1;
  letter-spacing: -0.03em; color: var(--cp-ink); font-variant-numeric: tabular-nums;
}
.arith span { display: block; margin-top: var(--s-2); font-size: 0.88rem; color: var(--cp-muted); }

/* Die drei Verzichte. Kein Seitenstreifen (siehe .argument): die Haarlinien
   gliedern bereits, ein zweiter Akzent daneben ist Dekoration. Was trägt,
   ist das Gewicht der Schrift und der Raum. */
.verzichte { margin-top: var(--s-6); border-top: 1px solid var(--cp-rule); max-width: 52ch; }
.verzicht {
  margin: 0; padding: var(--s-5) 0;
  border-bottom: 1px solid var(--cp-rule-2);
  font-size: 1.06rem; font-weight: 600; color: var(--cp-ink); max-width: 52ch;
}

/* --- 10. Fälle ---------------------------------------------------------- */
.cases { display: grid; grid-template-columns: 1fr; margin-top: var(--s-6); }
@media (min-width: 900px) { .cases { grid-template-columns: 1fr 1fr; } }
/* Ein einzelner .case in diesem Grid ließ ab 900px eine leere halbe Box
   stehen (SW10). Ein Fall bekommt eine Spalte, keine erfundene zweite. */
.cases--single { grid-template-columns: 1fr; max-width: 46rem; }
.case { border: 1px solid var(--cp-rule-2); padding: var(--s-6); }
@media (min-width: 900px) { .case + .case { border-left: 0; } }
@media (max-width: 899px) { .case + .case { border-top: 0; } }
.case .eyebrow { color: var(--cp-violet-text); }
.case p { max-width: none; }
.marks { list-style: none; margin: var(--s-5) 0 0; padding: var(--s-5) 0 0; border-top: 1px solid var(--cp-rule-2); }
.marks li { position: relative; padding-left: var(--s-6); margin-bottom: var(--s-4); }
.marks li:last-child { margin-bottom: 0; }
.marks li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 9px; height: 9px; border-radius: 50%; background: var(--cp-violet);
}

/* --- 11. Vertrauen und Listen -------------------------------------------- */
/* --- 10a. Die Auslöser ("Was bringt Sie gerade her?") ---------------------
   Waren einmal drei Türen, und drei Türen haben den Großteil der echten
   Kunden ausgeschlossen. Jetzt sind es neun Lagen. Sieben-Käufer-Review:
   "Die Auslöser-Liste ist eine Sackgasse. Acht Anlässe, keiner ist ein
   Link." Jede Lage verlinkt jetzt auf den Weg, der zu ihr passt, ohne dass
   der Leser vorher wissen muss, welcher Weg seiner ist. */
.triggers {
  list-style: none; margin: var(--s-6) 0 0; padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 760px) {
  .triggers { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-8); }
}
.triggers li { border-top: 1px solid var(--cp-rule-2); padding: 0; max-width: 44ch; }
/* Klickbarkeit sichtbar machen (Persona-Runde 7, Gruender: "Der direkteste Weg
   von meinem Problem zu eurer Antwort ist unsichtbar gemacht"). Die Kacheln
   waren Links in gedaempftem Fliesstext ohne Unterstrich; erst beim Hover
   aenderte sich etwas. Bewusst KEINE klassische Unterstreichung auf dem ganzen
   Mehrzeiler: sieben unterstrichene Absaetze untereinander erschlagen die
   Sektion, und die ruhige Flaeche ist das Muster der Seite. Stattdessen ein
   violetter Fuehrungsstrich links, der bei Hover und Fokus voll deckt, und die
   volle Tinte auf dem Text. */
/* Nur der Ganz-Eintrag-Link (einziges Element im li) bekommt die Kachel mit
   violetter Kante. Stehen in einem Eintrag MEHRERE Links im Fliesstext
   ("Fractional CISO oder Beteiligungen"), bleiben sie normale Textlinks,
   sonst zerfaellt der Satz in gestapelte Kaesten. */
.triggers li > a:only-child {
  display: block; padding: var(--s-4) 0 var(--s-4) var(--s-4); color: var(--cp-ink);
  text-decoration: none;
  border-left: 2px solid var(--cp-violet);
  transition: border-left-color 120ms ease, color 120ms ease, background-color 120ms ease;
}
.triggers li > a:only-child:hover, .triggers li > a:only-child:focus-visible {
  color: var(--cp-violet-text);
  border-left-color: var(--cp-violet-text);
  background-color: color-mix(in oklch, var(--cp-violet) 7%, transparent);
}
/* Der gemischte Eintrag traegt den Kachel-Innenabstand selbst, damit seine
   Textkante mit den Kachel-Eintraegen fluchtet. */
.triggers li:not(:has(> a:only-child)) { padding: var(--s-4) 0 var(--s-4) var(--s-4); }

/* --- 10a.1 Die Wege als Panels (Zweitmeinung: /pe, /fahrplan) -------------
   Jedes Panel ist ein einziger <a>, ein echtes Klickziel statt einer nur per
   Hover erreichbaren Karte. Rahmen und Abstand wie .case, dieselbe Breite
   wie .triggers (760px). Hover/Fokus hebt nur die Kopfzeile hervor, im
   selben Muster wie .net__hublink:hover .net__hubname: die Fläche selbst
   bleibt ruhig, nur der Text unterstreicht. Die Geometrie-Divs sind
   aria-hidden, ihre Bahnen/Balken nutzen die bestehenden .pressure__lane-
   Klassen unverändert, kein neuer Farbwert. */
.routes { display: grid; grid-template-columns: 1fr; gap: var(--s-6); margin-top: var(--s-6); }
@media (min-width: 760px) {
  .routes { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-8); }
}
.route {
  display: block; border: 1px solid var(--cp-rule-2); padding: var(--s-6);
  color: var(--cp-ink-2); text-decoration: none;
}
.route__label {
  display: inline-block; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--cp-violet-text);
}
.route:hover .route__label, .route:focus-visible .route__label {
  text-decoration: underline; text-underline-offset: 0.25em;
}
.route__figure { margin: var(--s-5) 0; display: grid; gap: var(--s-3); }
.route .route__then { margin: 0; color: var(--cp-ink-2); max-width: none; }
/* Die controlpunkt-Bahn im Hand-in-Hand-Panel: gleiche Höhe wie die anderen
   beiden, nur die Rahmenfarbe zeigt "auf Augenhöhe, aber unser Platz". */
.pressure__lane--controlpunkt { border-color: var(--cp-violet-line); }

/* --- 10b. Die Wege (die Fälle als Weg, nicht als Kachel) ------------------
   Jeder Fall wird in derselben Reihenfolge erzählt: derselbe Anfang, ein
   anderes Ende. Der Ring vor "Aufnahme" ist derselbe Ring wie der Knotenpunkt
   im Netz, und er beweist das erste Muster, ohne dass ein Satz es behauptet.
   Kein Kundenname, keine Zahl, die nicht im Beleg-Register steht. */
.ways { margin-top: var(--s-6); }
.way {
  display: grid; grid-template-columns: minmax(0, 1fr); row-gap: var(--s-3);
  padding: var(--s-6) 0; border-top: 1px solid var(--cp-rule);
}
@media (min-width: 860px) {
  .way {
    grid-template-columns: minmax(0, 0.44fr) minmax(0, 1fr);
    column-gap: var(--s-8); align-items: start;
  }
}
.way__who {
  margin: 0; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.11em;
  line-height: 1.25; text-transform: uppercase; color: var(--cp-violet-text);
  max-width: none;
}
/* Die Schiene (2026-08-27, Tommy). Vorher trug JEDE Zeile einen eigenen Ring
   plus das Wort "Aufnahme.", fuenf Mal untereinander. Das Muster "derselbe
   Anfang" wurde damit fuenf Mal behauptet, statt einmal gezeigt, und die linke
   Spalte trug auf 44% Breite genau ein informatives Wort. Jetzt: EIN Knoten
   oben, eine Linie an allen Faellen entlang, und die linke Spalte sagt, was
   sich unterscheidet, naemlich der Weg, in den der Fall lief. Dieselbe
   Geometrie wie .net-map, damit es als dasselbe Bild gelesen wird. */
.ways--rail { position: relative; margin-left: 11px; padding-left: 0; }
.ways--rail .way { border-left: var(--net-track) solid var(--cp-violet-line); }
.ways--rail .way:first-of-type { border-top: 0; }
.ways__hub {
  position: relative; margin: 0 0 var(--s-2); padding-left: 30px;
  margin-left: -11px;
  font-weight: 600; font-size: 1.05rem; color: var(--cp-ink); max-width: none;
}
.ways__hub::before {
  content: ""; position: absolute; left: 0; top: calc(50% - 9px);
  width: 18px; height: 18px; border-radius: 50%; box-sizing: border-box;
  border: var(--net-track) solid var(--cp-violet); background: transparent;
}
/* Der Abzweig je Fall: derselbe gefuellte Punkt wie .net-map__branch. */
.ways--rail .way > div:first-child { position: relative; }
.ways--rail .way > div:first-child::before {
  /* Der Punkt sitzt AUF der Linie: die Linie ist der border-left des .way,
     das div beginnt an dessen Innenkante. Also die halbe Punktbreite plus
     die Linienstaerke nach links, nicht zusaetzlich um das Innenmass. */
  content: ""; position: absolute; left: -7px; top: 0.42em;
  width: var(--net-dot); height: var(--net-dot); border-radius: 50%;
  background: var(--cp-violet);
}
.ways--rail .way > div { padding-left: var(--s-5); }
.way__route { margin: var(--s-2) 0 0; max-width: none; }
.way__route a {
  font-weight: 600; color: var(--cp-ink); text-decoration: none;
  border-bottom: 1px solid var(--cp-violet-line);
}
.way__route a:hover { color: var(--cp-violet-text); }
.way__route a:focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 3px; }
.way__then { margin: 0; color: var(--cp-ink-2); max-width: 58ch; }
.way__then + .way__then { margin-top: var(--s-4); }
.way__then b { color: var(--cp-ink); font-weight: 600; }
/* Steht die Ergebnisliste allein (ein Weg ohne Vorgeschichte), trägt sie keine
   Haarlinie: die Linie trennt die Lage vom Ergebnis, und ohne Lage trennt sie
   nichts. */
.way .marks:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

.grid-2 { display: grid; grid-template-columns: 1fr; gap: var(--s-7); margin-top: var(--s-6); }
@media (min-width: 900px) { .grid-2 { grid-template-columns: 1fr 1fr; } }
.grid-3 { display: grid; grid-template-columns: 1fr; gap: var(--s-7); margin-top: var(--s-6); }
@media (min-width: 900px) { .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.list-dot { list-style: none; margin: 0; padding: 0; }
.list-dot li { position: relative; padding-left: var(--s-6); margin-bottom: var(--s-5); max-width: 46ch; }
.list-dot li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 9px; height: 9px; border-radius: 50%; background: var(--cp-violet);
}
.panel { border: 1px solid var(--cp-rule-2); background: var(--cp-ground-2); padding: var(--s-6); }

/* Der Notausgang (laufender Vorfall -> eigene Cyberversicherung, A7): ein
   eigener, ruhiger Zweig, kein Teil der Hauptargumentation. Gestrichelte
   Kante auf .panel signalisiert "Ausnahmepfad", keine neue Farbe. */
/* Der gestrichelte Vorfall-Kasten lief ueber die volle Breite, der Text nur
   in der linken Haelfte (GF-Fund: "wirkt wie ein Ladefehler"). Auf Textbreite
   gekappt wie .cases--single, damit der Rahmen den Inhalt umschliesst. */
.exit-note { border-style: dashed; border-color: var(--cp-rule-strong); max-width: 46rem; }

/* Der Gründer-Block (Sieben-Käufer-Review, B0f): Name, Porträt, LinkedIn.
   Echtes Foto (800x800, /assets/tomislav-ljubas.jpg) ersetzt die Initialen. */
.founder { display: flex; align-items: center; gap: var(--s-5); margin-bottom: var(--s-6); }
.founder__portrait {
  width: 84px; height: 84px; flex: none; border-radius: 50%;
  background: var(--cp-violet-wash);
  border: 1px solid var(--cp-violet-line);
  object-fit: cover;
}
.founder__id { min-width: 0; }
.founder__name { margin: 0; font-weight: 600; font-size: 1.05rem; color: var(--cp-ink); }
.founder__role { margin: 2px 0 0; font-size: 0.86rem; color: var(--cp-muted); }
.founder__li {
  display: inline-flex; align-items: center; gap: 6px; margin-top: var(--s-2);
  font-family: var(--cp-font-mono); font-size: 0.8125rem; font-weight: 500;
  color: var(--cp-violet-text);
}
.founder__li:hover, .founder__li:focus-visible { color: var(--cp-ink); }

/* --- 12. Erreichbarkeit -------------------------------------------------- */
/* Rufnummer und Adresse sichtbar, groß, auf der Startseite. */
.contact { display: grid; grid-template-columns: 1fr; gap: var(--s-7); margin-top: var(--s-6); }
@media (min-width: 900px) { .contact { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); } }
/* Kein Seitenstreifen (siehe .argument). Der Kontaktblock steht auf dem
   Markenfeld, und die Rufnummer ist groß genug, um ohne Zierrat zu tragen. */
.contact__direct { padding-left: 0; }
/* E-Mail ist jetzt der primaere Kontaktweg (Telefon nur im Footer/Impressum),
   deshalb traegt sie die Groesse, die vorher die Rufnummer hatte. */
.contact__mail {
  display: block; font-size: clamp(1.2rem, 0.9rem + 1.1vw, 1.6rem); line-height: 1.2;
  font-weight: 600; color: var(--cp-violet-text); text-decoration: none; letter-spacing: -0.02em;
}
.contact__mail:hover { text-decoration: underline; text-underline-offset: 0.25em; }
.contact__linkedin {
  display: block; margin-top: var(--s-3); font-size: 1.05rem; font-weight: 600;
  color: var(--cp-ink); text-decoration: none;
}
.contact__linkedin:hover { color: var(--cp-violet-text); text-decoration: underline; text-underline-offset: 0.25em; }
.contact__who { margin: var(--s-5) 0 0; font-size: 0.92rem; color: var(--cp-muted); max-width: 34ch; }

/* --- 13. Knöpfe --------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-family: var(--cp-font); font-weight: 600; font-size: 1rem;
  padding: var(--s-3) var(--s-6); border: 1px solid transparent;
  cursor: pointer; text-decoration: none; min-height: 44px;
  transition: background-color 0.16s ease, border-color 0.16s ease, color 0.16s ease, transform 0.1s ease;
}
.btn:active { transform: translateY(1px); }
/* Der Knopf folgt der Fläche, auf der er steht (Knopf-Vertrag in :root).
   Auf dem Grund: Punkt-Violett mit Weiß. Auf dem Feld wäre das Violett auf
   Violett, dort ist er hell mit tiefviolettem Text (13.4:1). Auf dem hellen
   Blatt ist er tiefviolett mit Weiß. Drei Flächen, ein Knopf, kein
   Sonderfall im Markup. */
.btn--primary { background: var(--cp-btn-bg); color: var(--cp-btn-fg); }
.btn--primary:hover { background: var(--cp-btn-bg-over); }
/* Der Geisterknopf trug --cp-rule und lag damit bei 2.3:1. WCAG 1.4.11
   verlangt 3:1 für die Begrenzung eines Bedienelements, und dieser Knopf ist
   die Rufnummer im Kopf, also der wichtigste Ausgang der Seite für den CTO.
   --cp-rule-strong ist genau dafür da: 3.9:1 auf dem Grund, 3.3:1 auf dem Feld. */
.btn--ghost { background: transparent; color: var(--cp-ink); border-color: var(--cp-rule-strong); }
.btn--ghost:hover { border-color: var(--cp-ink); color: var(--cp-ink); }
.actions { display: flex; gap: var(--s-4); flex-wrap: wrap; margin-top: var(--s-7); align-items: center; }
.actions--tight { margin-top: var(--s-6); }

/* Telefon als tertiärer Text-Link neben dem Primary-Button (SW12): genau ein
   Knopf soll pro Screen dominieren, der Ghost-Button daneben zog optisch
   gleich viel Gewicht. Header und Footer sind davon nicht betroffen, dort
   bleibt die Rufnummer eine eigene Zeile. */
.tel-inline {
  color: var(--cp-ink-2); text-decoration: none; font-size: 0.95rem;
}
.tel-inline:hover, .tel-inline:focus-visible { color: var(--cp-ink); text-decoration: underline; text-underline-offset: 0.25em; }

/* --- 14. Formular -------------------------------------------------------- */
.form { display: grid; gap: var(--s-5); max-width: 38rem; margin-top: var(--s-6); }
.field { display: grid; gap: var(--s-2); }
.field label {
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--cp-muted);
}
/* Die Unterkante ist die EINZIGE sichtbare Begrenzung dieser Felder und lag
   mit --cp-rule bei 2.3:1. WCAG 1.4.11 verlangt 3:1. Jetzt --cp-rule-strong. */
.field input, .field textarea {
  font-family: var(--cp-font); font-size: 1rem; color: var(--cp-ink);
  background: transparent; border: 0; border-bottom: 1px solid var(--cp-rule-strong);
  padding: var(--s-3) 0; transition: border-color 0.16s ease;
  min-height: 44px;
}
.field input:hover, .field textarea:hover { border-bottom-color: var(--cp-ink-2); }
.field input:focus-visible, .field textarea:focus-visible {
  outline: none; border-bottom-color: var(--cp-focus); border-bottom-width: 2px;
  padding-bottom: calc(var(--s-3) - 1px);
}
.field textarea { resize: vertical; min-height: 7rem; }
.field .hint, .form > .hint { font-size: 0.85rem; color: var(--cp-muted); margin: 0; }
.field[data-state="error"] input, .field[data-state="error"] textarea { border-bottom-color: var(--cp-danger); }
.field .error { color: var(--cp-danger); font-size: 0.85rem; font-weight: 500; margin: 0; }
.checkline { display: grid; grid-template-columns: auto 1fr; gap: var(--s-3); align-items: start; }
.checkline label { font-size: 0.95rem; color: var(--cp-ink-2); }
/* 24x24px. WCAG 2.5.8 (Target Size, Minimum) verlangt es, und dieses Kästchen
   ist die Pflichteinwilligung: wer es nicht trifft, kann nicht absenden. */
.checkline input {
  accent-color: var(--cp-violet); width: 24px; height: 24px;
  margin: 0.1em 0 0; flex: 0 0 auto;
}
.checkline input[aria-invalid="true"] { outline: 2px solid var(--cp-danger); outline-offset: 2px; }
.checkline .error { grid-column: 1 / -1; }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form .formnote { margin: 0; padding: var(--s-4); font-size: 0.95rem; max-width: none; }
.form .formnote--ok  { border: 1px solid var(--cp-violet-line); background: var(--cp-violet-wash); color: var(--cp-ink); }
.form .formnote--err { border: 1px solid var(--cp-danger); color: var(--cp-ink); }
.form button[disabled] { opacity: 0.6; cursor: default; }
/* Die Reaktionszusage steht am Formular, nicht im Kleingedruckten.
   Kein Seitenstreifen (siehe .argument), sondern ein Flächen-Tint mit vollem
   Rahmen. */
.form__promise {
  margin: 0; font-size: 0.92rem; color: var(--cp-ink-2); max-width: none;
  padding: var(--s-4); border: 1px solid var(--cp-violet-line);
  background: var(--cp-violet-wash);
}

/* --- 15. Fußzeile ------------------------------------------------------- */
.sitefoot { border-top: 1px solid var(--cp-rule); margin-top: var(--s-8); }
/* Endet die Seite auf einer violetten .brandfield-Section (Startseite: der
   Kontaktblock), entfaellt der dunkle Trenner zum ebenfalls violetten Footer.
   Sonst klafft dort ein 64px-Spalt in body-Farbe (oklch 0.222), also violett,
   dunkel, violett, was wie ein Ladefehler aussieht (Tommy, 2026-07-24). Auf
   allen anderen Seiten steht vor dem Footer eine helle Section, dort bleibt
   der dunkle Trenner bewusst. */
main:has(> section.brandfield:last-child) + .sitefoot { margin-top: 0; }
.sitefoot__grid {
  display: grid; grid-template-columns: 1fr; gap: var(--s-6);
  padding-block: var(--s-7);
}
@media (min-width: 700px) { .sitefoot__grid { grid-template-columns: repeat(3, 1fr); } }
.sitefoot h2 {
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--cp-muted); margin: 0 0 var(--s-3);
}
.sitefoot p, .sitefoot address {
  margin: 0 0 var(--s-2); font-size: 0.92rem; color: var(--cp-ink-2);
  font-style: normal; max-width: none;
}
.sitefoot a { color: var(--cp-ink-2); text-decoration: none; }
.sitefoot a:hover { color: var(--cp-violet-text); text-decoration: underline; text-underline-offset: 0.25em; }
.sitefoot .tel { font-family: var(--cp-font-mono); font-variant-numeric: tabular-nums; }
.sitefoot__links { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-5); }
.sitefoot__foot {
  display: flex; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap;
  padding-block: var(--s-5); border-top: 1px solid var(--cp-rule-2);
  font-size: 0.86rem; color: var(--cp-muted);
}
.sitefoot__foot p { margin: 0; color: var(--cp-muted); }

/* --- 16. Bestand: Klassen der übrigen Seiten ---------------------------- */
/* faelle, vertrauen, kontakt, danke, Rechtstexte und /en/* benutzen noch
   .sheet, .trust, .dotline, .footer. Sie laufen jetzt im selben System, mit
   denselben Tokens, damit die Sprache auf ALLEN Seiten gilt, bis web-builder
   sie auf .wrap/.section/.panel hebt. */
.trust { background: var(--cp-ground-2); border-block: 1px solid var(--cp-rule); }
.trust .grid { display: grid; gap: var(--s-7); grid-template-columns: 1fr; }
@media (min-width: 900px) { .trust .grid { grid-template-columns: 1fr 1fr; } }
.trust ul { list-style: none; margin: 0; padding: 0; }
.trust ul li { position: relative; padding-left: var(--s-6); margin-bottom: var(--s-5); max-width: 46ch; }
.trust ul li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 9px; height: 9px; border-radius: 50%; background: var(--cp-violet);
}
.sheet {
  border: 1px solid var(--cp-rule); padding: var(--s-7);
  display: grid; gap: var(--s-7); grid-template-columns: minmax(0, 1fr);
  /* Ungleich hohe Spalten stretchten sonst die kürzere zu einer leeren
     weißen Box (Design-Bug, siehe DESIGN.md/SW6). Oben ausrichten statt
     strecken. */
  align-items: start;
}
@media (min-width: 900px) { .sheet { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); } }
@media (max-width: 899px) { .sheet { padding: var(--s-6); } }
.sheet ul { list-style: none; margin: 0; padding: 0; }
.sheet ul li { position: relative; padding-left: var(--s-6); margin-bottom: var(--s-4); max-width: 46ch; }
.sheet ul li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 9px; height: 9px; border-radius: 50%; background: var(--cp-violet);
}
/* Musterblatt als Tabelle: der Ausschnitt sieht aus wie das gekaufte
   Dokument, nicht wie seine Beschreibung. Die Prioritaet steht als Gewicht,
   nicht als Ampel: kein Rot/Gruen, nur das Violett/Ink-System. */
.sheet__scroll { overflow-x: auto; min-width: 0; }
.sheet__table { width: 100%; border-collapse: collapse; font-size: 0.95rem; line-height: 1.45; }
/* Handy: die Tabelle wird gestapelt, jede Zeile ein Block mit Beschriftung
   je Wert. So ist nichts abgeschnitten und man muss nicht wischen. */
@media (max-width: 560px) {
  .sheet__table thead { display: none; }
  .sheet__table, .sheet__table tbody, .sheet__table tr, .sheet__table td { display: block; width: auto; }
  .sheet__table tr { padding: var(--s-4) 0; border-bottom: 1px solid var(--cp-rule-2); }
  .sheet__table tbody tr:first-child { padding-top: 0; }
  .sheet__table tbody tr:last-child { padding-bottom: 0; border-bottom: 0; }
  .sheet__table td { border: 0; padding: 3px 0; }
  .sheet__table td:first-child { color: var(--cp-ink); font-weight: 600; margin-bottom: var(--s-2); }
  .sheet__table td[data-label]::before {
    content: attr(data-label); display: inline-block; min-width: 8.5em;
    color: var(--cp-muted); text-transform: uppercase; font-size: 0.7rem; letter-spacing: 0.06em;
  }
}
.sheet__table th {
  text-align: left; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--cp-muted); white-space: nowrap;
  padding: 0 var(--s-5) var(--s-3) 0; border-bottom: 1px solid var(--cp-rule);
}
.sheet__table td {
  padding: var(--s-4) var(--s-5) var(--s-4) 0; vertical-align: top;
  color: var(--cp-ink-2); border-bottom: 1px solid var(--cp-rule-2);
}
.sheet__table th:last-child, .sheet__table td:last-child { padding-right: 0; }
.sheet__table td:first-child { color: var(--cp-ink); font-weight: 500; }
.sheet__table tbody tr:last-child td { border-bottom: 0; }
.prio {
  display: inline-block; font-family: var(--cp-font-mono);
  font-size: 0.78rem; line-height: 1.5; padding: 0.05em 0.55em;
  border-radius: 2px; white-space: nowrap;
}
.prio--hoch    { background: var(--cp-violet-deep); color: #fff; }
.prio--mittel  { border: 1px solid var(--cp-violet-line); color: var(--cp-violet-deep); }
.prio--niedrig { border: 1px solid var(--cp-rule); color: var(--cp-muted); }

/* Kostenaufbau als Beleg: zwei Posten addieren sich sichtbar zur Summe,
   die Zertifizierungsstelle steht als Fussnote daneben, nicht im Preis. */
.coststack { margin: var(--s-5) 0 0; max-width: 34rem; border: 1px solid var(--cp-rule); }
.coststack__row {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-5);
  padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--cp-rule-2);
}
.coststack__label { color: var(--cp-ink-2); }
.coststack__note { display: block; font-size: 0.82rem; color: var(--cp-muted); margin-top: 2px; }
.coststack__amt { font-family: var(--cp-font-mono); color: var(--cp-violet-lift); white-space: nowrap; }
.coststack__row--sum { background: var(--cp-violet-wash); border-bottom: 0; }
.coststack__row--sum .coststack__label,
.coststack__row--sum .coststack__amt { color: var(--cp-ink); font-weight: 600; }
.coststack__foot {
  padding: var(--s-4) var(--s-5); border-top: 1px solid var(--cp-rule-2);
  font-size: 0.86rem; line-height: 1.55; color: var(--cp-muted); margin: 0;
}
/* Handy: der lange Betrag (nowrap) sprengt sonst die Zeile, also Label und
   Betrag untereinander statt nebeneinander. */
@media (max-width: 480px) {
  .coststack__row { flex-direction: column; align-items: flex-start; gap: 4px; }
}

/* Positionierung als Bruecke: zwei Pole (Berater, Dienstleister), controlpunkt
   in der Mitte, die beide verbindet. Der eine Satz, der die ganze Abgrenzung
   traegt, als Bild. */
.bridge { margin: var(--s-5) 0 0; display: flex; align-items: stretch; flex-wrap: wrap; max-width: 44rem; }
.bridge__pole, .bridge__mid {
  flex: 1 1 0; min-width: 8.5rem; padding: var(--s-4) var(--s-5);
  border: 1px solid var(--cp-rule-2); text-align: center;
  display: flex; flex-direction: column; gap: 3px; justify-content: center;
}
.bridge__pole b, .bridge__mid b { color: var(--cp-ink); font-weight: 600; }
.bridge__pole span, .bridge__mid span { font-size: 0.85rem; color: var(--cp-muted); }
.bridge__mid { border-color: var(--cp-violet-line); background: var(--cp-violet-wash); }
.bridge__mid b { color: var(--cp-violet-text); }
.bridge__link { align-self: center; flex: 0 0 auto; width: var(--s-5); height: 1px; background: var(--cp-rule-strong); }
@media (max-width: 620px) {
  .bridge { flex-direction: column; }
  .bridge__link { width: 1px; height: var(--s-5); }
}

/* Wort-Hervorhebung als Marker: ein farbiger Balken hinter dem tragenden
   Wort, wie ein Textmarker. Fuehrt das Auge auf die Kernaussage. Sparsam,
   ein Wort je Hero, sonst verliert er das Gewicht. Auf hellen Flaechen ein
   dezentes Violett hinter dunklem Text, auf dem violetten Hero ein
   Bernstein-Balken mit dunkler Schrift, damit das Wort lesbar bleibt. */
.mark {
  background-color: var(--cp-mark, oklch(0.585 0.247 var(--cp-hue) / 0.20));
  padding: 0.02em 0.16em; border-radius: 2px;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.brandfield .mark { background-color: var(--cp-amber); color: var(--cp-violet-deep); }
.dotline { display: flex; flex-wrap: wrap; gap: var(--s-4); list-style: none; margin: 0; padding: 0; font-weight: 600; color: var(--cp-ink); }
.dotline li { display: flex; align-items: center; gap: var(--s-4); }
.dotline li + li::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--cp-violet); }
.punkt::before {
  content: ""; display: inline-block; width: 0.42em; height: 0.42em;
  margin-right: 0.5em; border-radius: 50%; background: var(--cp-violet); vertical-align: middle;
}
.legal-warning {
  border: 1px solid var(--cp-danger); padding: var(--s-5); margin-bottom: var(--s-7);
  max-width: var(--measure); color: var(--cp-ink); font-size: 0.95rem;
}
.legal-warning strong { color: var(--cp-danger); }
.legalpage .placeholder { color: var(--cp-danger); font-weight: 600; }
.legal-note { color: var(--cp-muted); font-size: 0.92rem; margin: 0 0 var(--s-6); }
.legalpage h2 { margin-top: var(--s-8); }
.legalpage ul { padding-left: 1.2em; max-width: var(--measure); }
.legalpage .updated { color: var(--cp-muted); font-size: 0.95rem; }
.footer { border-top: 1px solid var(--cp-rule-2); padding-block: var(--s-7); color: var(--cp-muted); font-size: 0.9rem; }
.footer .row { display: flex; justify-content: space-between; gap: var(--s-5); flex-wrap: wrap; }
.footer a { color: var(--cp-muted); }
.legal {
  margin-top: var(--s-7); padding-top: var(--s-5); border-top: 1px solid var(--cp-rule-2);
  font-size: 0.86rem; line-height: 1.7; color: var(--cp-muted); max-width: none;
}

/* --- 16b. Die zwei Beweis-Plätze -----------------------------------------
   DESIGN.md 12. Komponente und CSS stehen bereit, der Inhalt kommt erst,
   wenn Tommy ihn liefert (12a, 12b). Bis dahin bleiben die Abschnitte, die
   diese Klassen benutzen, als HTML-Kommentar in der Seite. Ein leerer
   Slot steht nicht auf der Seite. */
.casestudy { margin-top: var(--s-6); border: 1px solid var(--cp-rule-2); padding: var(--s-6); }
.casestudy__grid {
  display: grid; grid-template-columns: 1fr; gap: var(--s-5); margin: 0;
}
@media (min-width: 700px) {
  .casestudy__grid { grid-template-columns: repeat(2, 1fr); }
  /* Fuenf Eintraege auf zwei Spalten liessen unten rechts ein Loch
     (IT-Leiter, R10). Der letzte, kurze Eintrag spannt beide Spalten
     und schliesst die Unterkante. */
  .casestudy__grid > div:last-child { grid-column: 1 / -1; }
}
.casestudy__grid dt {
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--cp-muted); margin: 0 0 var(--s-2);
}
.casestudy__grid dd { margin: 0; color: var(--cp-ink-2); max-width: 42ch; }
/* Kein Seitenstreifen (siehe .argument), sondern ein Flächen-Tint mit vollem
   Rahmen. */
.casestudy__quote {
  margin: var(--s-6) 0 0; padding: var(--s-5) var(--s-5) var(--s-5);
  border: 1px solid var(--cp-violet-line); background: var(--cp-violet-wash);
}
.casestudy__quote p {
  font-size: 1.1rem; font-style: normal; line-height: 1.5; color: var(--cp-ink);
  max-width: 46ch; font-weight: 500;
}
.casestudy__quote cite {
  display: block; margin-top: var(--s-3); font-style: normal; font-size: 0.88rem; color: var(--cp-muted);
}

.pubs { list-style: none; margin: var(--s-6) 0 0; padding: 0; }
.pubs__item { padding: var(--s-5) 0; border-top: 1px solid var(--cp-rule-2); }
.pubs__item:first-child { border-top: 0; }
.pubs__title { font-size: 1.05rem; font-weight: 600; color: var(--cp-ink); text-decoration: none; }
.pubs__title:hover { color: var(--cp-violet-text); text-decoration: underline; text-underline-offset: 0.25em; }
.pubs__meta { margin: var(--s-2) 0 0; font-size: 0.86rem; color: var(--cp-muted); max-width: none; }
.pubs__meta .pubs__date { font-family: var(--cp-font-mono); margin-left: var(--s-3); padding-left: var(--s-3); border-left: 1px solid var(--cp-rule); }
.pubs__abstract { margin: var(--s-2) 0 0; font-size: 0.95rem; color: var(--cp-ink-2); max-width: 56ch; }

/* --- 16c. Inhalts-Grafiken: vier neue Formen, dasselbe Netz-Vokabular -----
   standards.html, pe.html, fahrplan.html, detection.html. Keine neue Palette:
   jede Marke zitiert --cp-violet, --cp-violet-text, --cp-paper, --net-track,
   --net-dot. Statisch, kein SMIL, kein Rotieren. Geometrie ist aria-hidden,
   die echten Textlabels stehen als sichtbarer Inhalt in der Liste daneben. */

/* Der Ausnahmepfad: eine absteigende Kaskade statt einer flachen Liste.
   standards.html #ausnahme-h. Greift Stufe 1 nicht, kommt Stufe 2, greift die
   nicht, Stufe 3. Die letzte Stufe traegt zusaetzlich den Endbalken: der
   letzte Ausweg ist auch das Linienende. */
.casc { list-style: none; margin: var(--s-6) 0 0; padding: 0; max-width: 52ch; }
.casc__step { position: relative; padding: 0 0 var(--s-6) calc(var(--net-dot) + var(--s-4)); }
.casc__step:last-child { padding-bottom: 0; }
.casc__step:not(:last-child)::before {
  content: ""; position: absolute; z-index: 0;
  left: calc(var(--net-dot) / 2 - var(--net-track) / 2);
  top: calc(0.2em + var(--net-dot) / 2);
  bottom: calc(-1 * var(--s-6) + 0.2em + var(--net-dot) / 2);
  width: var(--net-track); background: var(--cp-violet);
}
.casc__mark { position: absolute; left: 0; top: 0.2em; z-index: 1; display: block; }
.casc__mark--dot { width: var(--net-dot); height: var(--net-dot); border-radius: 50%; background: var(--cp-violet); }
.casc__mark--terminus {
  width: 18px; height: 3px; left: calc(var(--net-dot) / 2 - 9px);
  top: calc(0.2em + var(--net-dot) + 8px); background: var(--cp-violet-text);
}
.casc__gate {
  position: absolute; left: calc(var(--net-dot) + var(--s-4)); top: calc(-1 * var(--s-5) + 0.2em);
  font-family: var(--cp-font-mono); font-size: 0.75rem; font-weight: 500;
  letter-spacing: 0.04em; color: var(--cp-muted);
}
.casc__name { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.35; color: var(--cp-ink); }
.casc__sub { margin: var(--s-1) 0 0; font-size: 0.9rem; line-height: 1.45; color: var(--cp-muted); max-width: 44ch; }

/* Das Phasentor: die vier Stationen der ersten Phase, dann die Uebergabe-
   Marke (Ihre Entscheidung), dann das Mandat mit Endbalken. pe.html
   #phase-h. Waagerecht ab 1040px, senkrecht darunter. Keine Preise: die
   stehen in der Pricecard daneben. */
.gate { list-style: none; margin: var(--s-6) 0 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); position: relative; }
.gate__pt { position: relative; padding-top: 18px; padding-right: var(--s-4); }
.gate__pt:last-child { padding-right: 0; }
.gate__pt:not(.gate__pt--last)::before {
  content: ""; position: absolute; z-index: 0;
  left: calc(var(--net-dot) / 2); right: calc(-1 * var(--net-dot) / 2);
  top: calc(var(--net-dot) / 2 - var(--net-track) / 2);
  height: var(--net-track); background: var(--cp-violet);
}
.gate__mark { position: absolute; left: 0; top: 0; display: block; }
.gate__mark--dot { width: var(--net-dot); height: var(--net-dot); border-radius: 50%; background: var(--cp-violet); }
.gate__mark--handoff {
  width: 16px; height: 20px; top: calc(var(--net-dot) / 2 - 10px);
  background: var(--cp-paper); border: 2px solid var(--cp-violet);
}
.gate__mark--terminus {
  width: 3px; height: 18px; left: var(--net-dot);
  top: calc(var(--net-dot) / 2 - 9px); background: var(--cp-violet-text);
}
.gate__name { display: block; margin-top: var(--s-3); font-size: 0.9375rem; font-weight: 600; line-height: 1.3; color: var(--cp-ink); }
.gate__sub { display: block; margin-top: var(--s-1); font-size: 0.8125rem; font-weight: 500; color: var(--cp-muted); }
@media (max-width: 1039px) {
  .gate { grid-auto-flow: row; grid-template-columns: minmax(0, 1fr); row-gap: var(--s-5); padding-left: calc(var(--net-dot) + var(--s-4)); }
  .gate__pt { padding-top: 0; padding-right: 0; }
  .gate__pt:not(.gate__pt--last)::before {
    left: calc(-1 * (var(--net-dot) + var(--s-4)) + var(--net-dot) / 2 - var(--net-track) / 2);
    right: auto; width: var(--net-track); height: auto;
    top: calc(0.15em + var(--net-dot) / 2);
    bottom: calc(-1 * var(--s-5) - 0.15em - var(--net-dot) / 2);
  }
  .gate__mark { left: calc(-1 * (var(--net-dot) + var(--s-4))); top: 0.15em; }
  .gate__mark--handoff { left: calc(-1 * (var(--net-dot) + var(--s-4)) + var(--net-dot) / 2 - 8px); top: calc(0.15em + var(--net-dot) / 2 - 10px); }
  .gate__mark--terminus {
    width: 18px; height: 3px;
    left: calc(-1 * (var(--net-dot) + var(--s-4)) + var(--net-dot) / 2 - 9px);
    top: calc(0.15em + var(--net-dot) + 6px);
  }
  .gate__name { margin-top: 0; }
}

/* Das Drei-Zonen-Band: controlpunkt, der Betreiber, und bewusst leer. Ersetzt
   zwei nebeneinanderliegende .panel plus einen Absatz. detection.html
   #grenze-h. Naht 1 (controlpunkt -> Betreiber) traegt die Uebergabe-Marke:
   dort wird uebergeben. Naht 2 (Betreiber -> leer) ist nur eine staerkere
   Trennlinie ohne Marke: dort wird nichts uebergeben, es hoert auf. */
.band { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; align-items: stretch; margin: var(--s-6) 0 0; border: 1px solid var(--cp-rule-2); }
.band__field { padding: var(--s-5); min-width: 0; }
.band__name { margin: 0; font-size: 1.05rem; }
.band__sub { margin: var(--s-1) 0 0; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--cp-muted); }
.band__label { margin: 0; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--cp-muted); }
.band__text { margin: var(--s-3) 0 0; font-size: 0.9375rem; color: var(--cp-ink-2); max-width: 40ch; }
.band__seam { position: relative; width: var(--net-track); background: var(--cp-rule-2); }
.band__seam--stop { width: 1px; background: var(--cp-rule-strong); }
.band__mark {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 16px; height: 20px; background: var(--cp-paper); border: 2px solid var(--cp-violet);
}
@media (max-width: 719px) {
  .band { grid-template-columns: 1fr; }
  .band__seam { width: 100%; height: var(--net-track); }
  .band__seam--stop { height: 1px; width: 100%; }
  .band__mark { width: 20px; height: 16px; }
}

/* --- 17. Bewegung -------------------------------------------------------- */
/* Nur mit JavaScript UND nur ohne Reduktionswunsch. Ohne .js-motion ist jeder
   Inhalt im Endzustand sichtbar. Kein SMIL. Keine Zählanimation.
   Der Druckvektor bewegt sich nicht: er ist die Aussage, keine Vorführung. */
@media (prefers-reduced-motion: no-preference) {
  /* Nur Bewegung, keine Opazitaet (Persona-Runde 7). Drei Leser haben beim
     schnellen Scrollen Textbloecke gesehen, die kurz blass oder unlesbar waren,
     einer dachte, die Seite sei kaputt. Der Effekt war ein Ein-Blenden von
     opacity 0; wer schneller scrollt als die 500ms, liest Grau. Die Bewegung
     traegt den Reveal genauso, und Text ist nie unlesbar. */
  .js-motion .reveal { transform: translateY(10px); }
  .js-motion .reveal.is-in {
    transform: none;
    transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1);
    transition-delay: calc(min(var(--i, 0), 3) * 60ms);   /* 60ms, gedeckelt bei 4 Schritten */
  }
}

/* --- 18. Druck ----------------------------------------------------------- */
@media print {
  .nav-mobile, .skip-link { display: none; }
  body { background: #fff; color: #000; }
}

/* --- 19. Utilities (bewusst LETZTER Abschnitt) ---------------------------
   Seit 2026-07-26 traegt das Markup KEIN style="..."-Attribut mehr: alles
   laeuft ueber diese Klassen, deshalb kommt die CSP ohne 'unsafe-inline'
   fuer Styles aus (style-src 'self'). Die Position am Dateiende ist Teil
   des Vertrags: ein Utility ersetzt ein frueheres Inline-Attribut und muss
   deshalb jede Komponenten-Regel gleicher Spezifitaet schlagen. Wer ein
   neues Inline-Style-Attribut einfuehrt, bricht es still; tools/
   csp-hashes.py prueft das mechanisch. */
.m0   { margin: 0; }
.mt-0 { margin-top: 0; }
.mt-3 { margin-top: var(--s-3); }
.mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); }
.mt-6 { margin-top: var(--s-6); }
.mt-7 { margin-top: var(--s-7); }
.mt-8 { margin-top: var(--s-8); }
.mb-4 { margin-bottom: var(--s-4); }
.pt-8 { padding-top: var(--s-8); }
.pb-0 { padding-bottom: 0; }
.bt-0 { border-top: 0; }
.py-6 { padding-top: var(--s-6); padding-bottom: var(--s-6); }
/* Lesebreiten: 58ch ist die Standard-Blockbreite der Sektionen, 52ch die
   engere Variante, 46rem die Breite der Einzelfall-Karten. */
.measure-58 { max-width: 58ch; }
.measure-52 { max-width: 52ch; }
.maxw-46 { max-width: 46rem; }
/* Der hervorgehobene Schlusssatz einer Sektion. */
.standout { max-width: 58ch; font-weight: 600; color: var(--cp-ink); }
/* Kleine Binnen-Ueberschrift in Panels und Blaettern. */
.subhead { margin: 0 0 var(--s-3); font-size: 1.05rem; }
.subhead--roomy { margin-bottom: var(--s-5); }
/* Stagger-Index fuer .reveal (transition-delay = min(--i,3) * 60ms in
   Abschnitt 17). Ohne Klasse gilt --i:0 ueber var(--i, 0). */
.i1 { --i: 1; }
.i2 { --i: 2; }
.i3 { --i: 3; }
.i4 { --i: 4; }

/* --- 20. Finale Abnahme 2026-08-27: Leerflaechen und Handlungsschluss ----- */
/* Vier kurze Verzicht-Zeilen liessen auf der Startseite 65% der Breite leer. */
@media (min-width: 900px) {
  .verzichte--2col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-8); }
  .verzichte--2col .verzicht:nth-child(2) { border-top: 1px solid var(--cp-rule); }
}
/* Die Preiskarte begleitet die Angebotsliste beim Scrollen: der Preis bleibt
   im Blick, waehrend der Leser liest, was er dafuer bekommt. Kein Effekt,
   eine Lesehilfe; unter 900px stapelt das Raster ohnehin. */
@media (min-width: 900px) {
  .offer .pricecard { position: sticky; top: var(--s-7); align-self: start; }
}
/* Der Schlussblock: links der Kontakt, rechts das Geruest fuer die erste
   Mail. Beide beginnen auf derselben Hoehe. */
/* Spalten beginnen oben: fuer Paar-Layouts, in denen eine Seite kuerzer ist
   (Panel neben Liste, Tabelle neben Text). Ohne start streckt das Grid den
   kurzen Block und er wirkt leer. */
.ai-start { align-items: start; }
.contact-close { align-items: start; }
/* Die Mail-Punkte stehen im Schlussblock in EINER Spalte: sie leben schon in
   der rechten Haelfte, die triggers-eigene Zweispaltigkeit ergaebe drei
   schmale Spalten nebeneinander. */
.contact-close .triggers { margin-top: var(--s-3); grid-template-columns: minmax(0, 1fr); }
.contact-close .triggers li { max-width: none; }
