/* ============================================================================
   Marius May Software- & Webentwicklung — Projekt-Gestaltungsschicht
   Richtung „Die Kante" (siehe .factory/entwuerfe.md)

   Formprinzip: Das Logo ist ein Schnitt — ein Feld, von einer Diagonale in zwei
   Hälften geteilt (links tief, rechts leuchtend), mit eingeschriebenem </>.
   Der Winkel ist aus dem Signet gemessen: 33,3° zur Waagerechten.

   Er tritt bewusst an GENAU ZWEI Stellen exakt auf (Hero-Keil, Abschluss-Keil);
   alle übrigen Bandkanten tragen einen flachen Familien-Schnitt. Ein echter
   33°-Schnitt über die volle Seitenbreite bräuchte über 900 px Höhenversatz —
   deshalb der bewusste Unterschied statt einer falschen Behauptung.

   Wird als LETZTES Stylesheet geladen und gewinnt damit in der Kaskade.
   ========================================================================== */

:root {
  /* --- Projekteigene Farbtoken (die einzige Stelle mit Hex-Werten) ---------
     --accent (#0454fc) und --accent-2 (#0b1b3a) kommen aus site.json über
     partials/head.php und werden hier NICHT neu definiert. */
  --marine-tief:   #060f22;  /* tiefste Fläche: Abschluss-Band */
  --studiograu:    #f2f4f7;  /* ruhige Zwischenfläche, aus dem Porträt-Hintergrund */
  --werkstattgrau: #5b6675;  /* Fließtext-Sekundär auf Hell */
  --papier:        #ffffff;

  /* Derselbe Markenton, für Schrift auf Marineblau aufgehellt. Das reine
     Signalblau erreicht auf #0b1b3a nur 2,99:1 und reißt damit selbst die
     3:1-Schwelle für Großschrift. 75 % Akzent auf Weiß ergibt 4,62:1 und
     besteht AA in jeder Schriftgröße — gleicher Farbton, kein zweiter Akzent. */
  --akzent-auf-dunkel: color-mix(in srgb, var(--accent) 75%, #fff);

  /* --- Die Kante ---------------------------------------------------------- */
  --kante-winkel: 33.3deg;   /* exakt aus dem Signet gemessen */
  --kante-band:   3.2vw;     /* flacher Familien-Schnitt an Bandkanten */

  /* Höhe der Kopfzeile. Kein geschätzter Wert: .header-inner trägt in base.css
     `min-height: 4.5rem`, dazu die 1px-Hairline der Unterkante — zusammen exakt
     die 73 px, die der Kopf im Browser misst. Der Hero rechnet damit seine
     Bildschirmhöhe aus; wird der Kopf in base.css je umgebaut, gehört diese
     Zeile mit angepasst. */
  --kopf-h: calc(4.5rem + 1px);

  /* --- Typo-Korrekturen zum Preset ---------------------------------------
     „minimalist" setzt --display-weight auf 400; Big Shoulders Display liegt
     nur im Schnitt 700 vor — ohne diese Zeile rendert der Browser einen
     synthetischen Fake-Bold. */
  --display-weight: 700;
  --display-tracking: 0.004em;

  /* Fließtext etwas ruhiger als die Preset-Vorgabe (Hanken Grotesk trägt das) */
  --leading-normal: 1.62;
}

/* ---------------------------------------------------------------------------
   Große Schirme: ab 1840 px wächst die Wurzel-Schriftgröße linear mit der
   Fensterbreite, bis 2560 px auf das 1,25-Fache (dann gedeckelt). Das ganze
   Token-System ist rem-basiert — Container (76rem), Abstände, Schriftgrade —,
   deshalb skaliert EINE Regel die komplette Komposition wie eine Vektorgrafik:
   das geprüfte 1440er-Layout bleibt exakt erhalten, nur größer. Ohne sie friert
   der Inhalt bei 1216 px ein, während der vw-basierte Keil weiterwächst, und
   die Seite zerfällt auf breiten Schirmen in Text-Inseln vor leerer Fläche.
   Die Gerade: f(1840px) = 16px, f(2560px) = 20px. 1px-Hairlines bleiben
   bewusst 1px, der Browser-Zoom der Nutzer funktioniert unverändert.
   (In der Media-Query gilt 1rem = 16px, unabhängig von dieser Regel.)
   --------------------------------------------------------------------------- */
@media (min-width: 115rem) {
  html { font-size: clamp(1rem, 0.3611rem + 0.5556vw, 1.25rem); }
}

/* ---------------------------------------------------------------------------
   Deutsche Komposita: base.css setzt auf Überschriften overflow-wrap:break-word.
   Auf Display-Graden bricht das mitten im Wort („Webentwick|lung") — ein
   sichtbarer Satzfehler. Auf Überschriften deshalb konsequent normaler Umbruch.
   --------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
}

/* Display-Haltung: kondensierte Versalien tragen die Struktur.

   Der Zeilenabstand ist an den Umlauten bemessen, nicht an der Versalhöhe:
   Big Shoulders Display setzt ein „Ü" 0,94 em über die Grundlinie, ein „D"
   nur 0,80 em. Bei den früheren 0,9 hingen die Umlautpunkte einer zweiten
   Zeile deshalb 0,04 em in die Buchstaben der Zeile darüber („Drei Felder. /
   Eines FÜHRT."). 0,96 ist der engste Wert, der die Punkte frei stehen lässt.
   Wer hier wieder unter 0,94 geht, holt die Kollision zurück. */
h1, h2, h3 { text-transform: uppercase; line-height: 0.96; }
h4 { text-transform: none; font-family: var(--font-body); font-weight: 700; letter-spacing: 0; }

body { color: var(--accent-2); }
.muted, .lead { color: var(--werkstattgrau); }

/* Mono-Labels — nur dort, wo sie etwas Wahres sagen: Sequenzen, URLs, Eyebrows. */
.mono-label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
}
.mono-label--hell { color: color-mix(in srgb, var(--papier) 72%, transparent); }
/* Versalien tragen ein kurzes Label, keinen ganzen Satz: Wortbilder entstehen
   über Ober- und Unterlängen, und die nimmt Großschrift weg. Ab etwa dreißig
   Zeichen bleibt die Mono-Form, die Versalien fallen weg. */
.mono-label--lang {
  text-transform: none;
  letter-spacing: 0.04em;
}

/* Die eigene Eyebrow-Form ersetzt den Strich-Default aus base.css. */
.eyebrow { font-family: var(--font-mono); letter-spacing: 0.16em; color: var(--accent); }
.eyebrow::before { display: none; }

/* Flache Buttons — das Preset gibt Radius 0 vor, die Schatten müssen mit. */
.btn { box-shadow: none; font-family: var(--font-body); letter-spacing: 0.01em; }
.btn:hover { box-shadow: none; }
/* base.css setzt die Schriftfarbe über die interne Variable --_fg, die nur am
   Element selbst lebt. Hier steht sie noch einmal direkt: --accent-ink kommt aus
   der site.json (gewinnt weiterhin), --papier ist der Rückfallwert. Ohne das
   erbt der Knopf auf hellem Grund die dunkle Fließtextfarbe, sobald --_fg
   nicht aufgelöst wird — und im Hover-Blau ist das nicht mehr lesbar.
   Es gilt für die gefüllten Knöpfe; --ghost und --soft stehen auf hellem Grund
   und bekommen ihre dunkle Schrift direkt danach zurück (u. a. „Nur
   erforderliche“ im Cookie-Banner). */
.btn { color: var(--accent-ink, var(--papier)); }
.btn--ghost { color: var(--fg); }
.btn--soft  { color: var(--accent-700); }
/* base.css setzt im Hover pauschal `background: var(--accent-600)` — das schlägt
   bei den hellen Varianten die Flächenfarbe aus `--_bg` und stellt dunkle
   Schrift auf sattes Signalblau (2,6:1). Betrifft „Nur erforderliche“ im
   Cookie-Banner. Die hellen Varianten behalten hier ihre helle Fläche. */
.btn--ghost:hover { background: var(--accent-soft); color: var(--fg); }
.btn--soft:hover  { background: var(--accent-soft); color: var(--accent-700); }

/* ============================================================================
   GRUNDRASTER — Innenabstände.

   Waagerecht die Lesespur, senkrecht der Seitenrhythmus. Beides steht bewusst
   als ausgeschriebene Längsschreibweise (padding-top/-bottom/-left/-right) in
   zwei Stufen da, nicht als `padding-block` mit `clamp()`: die Werte sind so
   auch ohne Layout-Berechnung ablesbar — für Wartung wie für statische Prüfung.
   ========================================================================== */
.container { padding-left: 1.1rem; padding-right: 1.1rem; }
.section { padding-top: 6rem; padding-bottom: 6rem; }
.section--tight { padding-top: 4rem; padding-bottom: 4rem; }
/* base.css schiebt den Fuß mit `margin-top: var(--space-2xl)` vom Inhalt weg.
   Ein Außenabstand zeigt aber die Seitenfläche, nicht die Fußfläche — unter
   jedem dunkel geschlossenen Band (Abschluss-Keil, Person-Feld) stand deshalb
   ein weißer Streifen zwischen Sektionskante und Fuß. Jede Sektion bringt ihren
   Fußabstand selbst mit (6/8 rem, s. oben), der Fuß setzt direkt an. */
.site-footer { margin-top: 0; }
/* Der Fußbereich sitzt unter einer Linie — die braucht Luft über sich.
   Die geerbte Farbe (--fg-subtle) erreicht auf der Fußfläche nur 4,29:1 und
   verfehlt AA knapp; --werkstattgrau ist derselbe kühle Grauton und kommt auf
   5,4:1. */
.footer-bottom { padding-top: 1.75rem; padding-bottom: 1.75rem; color: var(--werkstattgrau); }
/* Betreiber-Zugang zum Statistik-Backend (s. partials/footer.php). Erbt Farbe
   und Größe der Copyright-Zeile, trägt keinen Unterstrich — dadurch liest er
   sich wie Fließtext und tritt optisch nicht hervor. Erst Hover/Fokus macht ihn
   als Link kenntlich. Das Padding hält die Klickfläche auf 24px (WCAG 2.5.8). */
.footer-intern {
  color: inherit; text-decoration: none; margin-left: 0.6rem;
  display: inline-flex; align-items: center; min-height: 24px; padding-inline: 0.2rem;
}
.footer-intern:hover, .footer-intern:focus-visible { color: var(--accent-600); text-decoration: underline; }
/* Die Spaltenköpfe im Fuß sind Überschriften zweiter Ordnung (sie gliedern den
   Fußbereich, nicht einen Abschnitt darüber) — base.css formt nur h3/h4. */
.footer-col h2 {
  font-size: var(--step--1); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--fg-muted); margin: 0 0 var(--space-xs); font-weight: 600;
  line-height: 1.2;
}

@media (min-width: 50rem) {
  .container { padding-left: 2rem; padding-right: 2rem; }
  .section { padding-top: 8rem; padding-bottom: 8rem; }
  .section--tight { padding-top: 5rem; padding-bottom: 5rem; }
}

/* Text-Pfeil-Link: ersetzt die Zwei-Button-Reihe, die das Briefing verbietet. */
.pfeil-link {
  display: inline-flex; align-items: baseline; gap: 0.6rem;
  font-family: var(--font-body); font-weight: 700;
  font-size: var(--step-1); letter-spacing: 0.01em;
  color: var(--accent); text-decoration: none;
  border-bottom: 2px solid currentColor; padding-bottom: 0.15em;
}
.pfeil-link__pfeil { font-family: var(--font-mono); }
.pfeil-link--hell { color: var(--papier); }
@media (prefers-reduced-motion: no-preference) {
  .pfeil-link .pfeil-link__pfeil { transition: transform var(--dur-base) var(--ease-out); }
  .pfeil-link:hover .pfeil-link__pfeil { transform: translateX(4px); }
}

/* ============================================================================
   Kopfzeile — das Logo gehört hierher, nicht in den Hero.
   ========================================================================== */
.site-header { background: var(--papier); border-bottom: 1px solid var(--border); }
.brand__logo { height: clamp(1.9rem, 3.4vw, 2.5rem); width: auto; display: block; }
.nav__link { font-weight: 700; letter-spacing: 0.02em; }

/* Kundenlogin nutzt jetzt echtes .btn--ghost aus base.css (sekundärer
   Button, nur Rahmen statt Füllung) und braucht deshalb kein eigenes
   Farb-CSS mehr. Auf Mobil steckt er als Nav-Link-Zwilling im Burger-Menü
   (.nav__link--kundenlogin, header.php) statt neben dem Menü-Knopf zu
   schweben — exakt das Muster von .nav__link--kontakt. Zwilling versteckt
   sich ab 821px wieder, weil dort der echte .btn--ghost sichtbar ist. */
@media (min-width: 821px) {
  .nav .nav__link--kundenlogin { display: none; }
}

/* ============================================================================
   HERO — „Der Schnitt". Marine-Feld, aus dem unten rechts der Signalblau-Keil
   im exakten Logo-Winkel aufsteigt. Headline aus der Mitte gerückt.
   ========================================================================== */
.hero-kante {
  position: relative;
  overflow: hidden;
  background: var(--accent-2);
  color: var(--papier);
  padding-top: 4.5rem;
  padding-bottom: 3.5rem;
  isolation: isolate;
  /* Der Hero füllt den Schirm bis zur Unterkante — das Laufband darunter setzt
     erst nach dem ersten Scrollen ein. Reicht der Platz nicht (flaches Fenster),
     wächst er über das Maß hinaus, statt den Satz zu stauchen: min-height, nicht
     height. Die erste Zeile ist der Rückfall für Browser ohne svh. */
  min-height: calc(100vh - var(--kopf-h));
  min-height: calc(100svh - var(--kopf-h));
  /* Bleibt Fläche übrig, verteilt sie sich über und unter dem Satz, statt ihn
     nach oben zu drücken. Das einzige Kind im Fluss ist __inner; Keil und </>
     liegen absolut und bleiben davon unberührt. */
  display: grid;
  align-content: center;
}
/* Die Höhe des Heros kommt aus der Luft, nicht aus dem Inhalt: Headline und
   Satz brauchen zusammen gut 550 px, das Polster kam auf weitere 256 px — auf
   einem üblichen Laptop stand die Kante damit unter der Fensterkante und der
   Hero endete nirgends sichtbar. Das Polster hängt deshalb an der FENSTERHÖHE
   statt an einer festen Zahl: auf flachen Schirmen rückt es zusammen, auf hohen
   bleibt es großzügig. Die Grenzen halten beides in Maßen — der Hero wird nie
   gedrängt und nie wieder höher als zuvor. svh statt vh, damit die ein- und
   ausfahrende Adressleiste auf dem Handy nicht an der Fläche zieht. */
@media (min-width: 50rem) {
  .hero-kante { padding-top: 7rem; padding-bottom: 5.5rem; }          /* Rückfall ohne svh */
  .hero-kante { padding-top: clamp(3.5rem, 8svh, 7rem); padding-bottom: clamp(2.75rem, 6.5svh, 5.5rem); }
}

/* Der Keil: ein gedrehtes Rechteck. Eine Drehung hält den Winkel EXAKT — anders
   als clip-path in Prozent, dessen Winkel sich mit dem Seitenverhältnis ändert. */
.hero-kante__keil { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
.hero-kante__keil::before {
  content: "";
  position: absolute;
  left: 56%; top: 100%;
  width: 220%; height: 220%;
  background: var(--accent);
  transform-origin: 0 0;
  transform: rotate(calc(var(--kante-winkel) * -1));
}

/* Auch die beiden Zwischenräume (Zeile, Headline, Fuß) folgen der Fensterhöhe —
   sie waren mit 2 × 56 px der zweitgrößte Posten der Hero-Höhe. */
.hero-kante__inner { position: relative; display: grid; gap: clamp(1.75rem, 5vw, 3rem); }
@media (min-width: 50rem) {
  .hero-kante__inner { gap: clamp(1.5rem, 4.5svh, 3rem); }
}

.hero-kante h1 {
  font-size: clamp(3.3rem, 11.5vw, 8.6rem);
  line-height: 0.84;
  margin: 0;
  max-width: 15ch;
}
/* Drei Zeilen dieses Grades sind allein 347 px hoch — auf einem flachen Fenster
   (720 px) bleibt danach für Polster und Satz nichts mehr übrig. Der Grad kennt
   deshalb neben der Breite auch die Fensterhöhe und gibt NUR dort nach, wo sonst
   nichts mehr passt: ab etwa 920 px Fensterhöhe liegt 15svh über der Obergrenze
   von 8.6rem, die Headline steht dann Pixel für Pixel wie zuvor. */
@supports (height: 1svh) {
  .hero-kante h1 { font-size: clamp(3.3rem, min(11.5vw, 15svh), 8.6rem); }
}
/* Die dritte Zeile trägt die Pointe — sie bekommt die Markenfarbe als Aussage,
   nicht als Dekoration: „einer" ist der ganze Unterschied dieses Anbieters. */
.hero-kante h1 .pointe { color: var(--akzent-auf-dunkel); }

.hero-kante__fuss { display: grid; gap: var(--space-md); max-width: 38rem; }
.hero-kante__lead {
  font-size: var(--step-1);
  color: color-mix(in srgb, var(--papier) 82%, transparent);
  margin: 0;
}
.hero-kante__fuss .pfeil-link { justify-self: start; }

/* Das zweite Logo-Motiv: das </> zeichnet sich selbst, unten rechts im Keil —
   genau dort, wo es im Signet sitzt. Rein dekorativ. */
.hero-kante__code {
  position: absolute;
  right: clamp(1rem, 4vw, 4rem);
  bottom: clamp(1rem, 4vw, 3rem);
  width: clamp(5rem, 14vw, 12rem);
  height: auto;
  color: var(--papier);
  opacity: 0.92;
  z-index: 1;
  pointer-events: none;
}
.hero-kante__code path {
  fill: none; stroke: currentColor; stroke-width: 6;
  stroke-linecap: square; stroke-linejoin: miter;
}

@media (max-width: 860px) {
  /* Auf schmalen Schirmen würde der Keil unter die Textspalte laufen — er rückt
     nach links und die Headline wird kleiner gesetzt. */
  .hero-kante__keil::before { left: 38%; }
  .hero-kante h1 { font-size: clamp(3rem, 14vw, 5rem); }
}

/* ============================================================================
   LAUFBAND — die Signatur. Signalblaues Vollbreit-Band direkt unter dem Hero,
   Trennzeichen ist das </> aus dem Logo statt eines Aufzählungspunkts.
   ========================================================================== */
/* Das Band läuft randlos über die volle Breite; die Laufspur selbst bekommt
   seitlich denselben Rand wie die Lesespur, damit die Wörter am Bildschirmrand
   nicht anstoßen — die weiche Maske blendet dort ohnehin aus. */
.section.laufband {
  background: var(--accent);
  color: var(--accent-ink);
  padding-top: 1rem;
  padding-bottom: 1rem;
  padding-left: 1.1rem;
  padding-right: 1.1rem;
}
@media (min-width: 50rem) { .section.laufband { padding-top: 1.4rem; padding-bottom: 1.4rem; } }
.laufband .marquee__item {
  color: var(--accent-ink);
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(1.1rem, 2.4vw, 1.7rem);
  letter-spacing: 0.03em;
}
/* Die Randmaske aus premium.css frisst bei 8 % das erste und letzte Wort an.
   Schmaler gefasst bleibt die weiche Kante, ohne Text abzuschneiden. */
.laufband .marquee {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
}
.laufband .marquee__item--dot::after {
  content: "</>";
  font-family: var(--font-mono);
  font-size: 0.72em;
  letter-spacing: 0;
  color: color-mix(in srgb, var(--accent-ink) 62%, transparent);
}

/* ============================================================================
   TREPPE — die drei Leistungen. Keine Karten-Reihe: jede Zeile rückt weiter
   ein und wird kleiner. Die linken Textkanten bilden zusammen die Diagonale,
   die Größenstaffelung bildet die Positionierung ab (Webentwicklung führt).
   ========================================================================== */
.treppe { background: var(--papier); }
.treppe__liste { list-style: none; margin: var(--space-xl) 0 0; padding: 0; display: grid; }
.treppe__feld { border-top: 2px solid var(--accent-2); }
.treppe__feld a {
  display: grid; gap: var(--space-sm);
  padding-top: 1.8rem; padding-bottom: 1.8rem;
  color: inherit; text-decoration: none;
}
@media (min-width: 50rem) { .treppe__feld a { padding-top: 2.8rem; padding-bottom: 2.8rem; } }
.treppe__feld h3 { margin: 0; }
.treppe__feld p { margin: 0; color: var(--werkstattgrau); max-width: 46ch; }
.treppe__feld .pfeil-link { justify-self: start; font-size: var(--step-0); }

/* Die Staffelung: Einzug + Grad. Drei Werte, sonst nichts. */
.treppe__feld--1 { margin-left: 0; }
.treppe__feld--1 h3 { font-size: clamp(2.4rem, 6.4vw, 5.2rem); }
.treppe__feld--2 { margin-left: 11%; }
.treppe__feld--2 h3 { font-size: clamp(1.9rem, 4.4vw, 3.5rem); }
.treppe__feld--3 { margin-left: 22%; }
.treppe__feld--3 h3 { font-size: clamp(1.6rem, 3.2vw, 2.5rem); }

@media (prefers-reduced-motion: no-preference) {
  .treppe__feld a { transition: transform var(--dur-base) var(--ease-out); }
  .treppe__feld a:hover { transform: translateX(6px); }
}
@media (max-width: 760px) {
  /* Mobil trägt der Einzug nicht mehr — die Größenstaffelung allein macht die
     Hierarchie, sonst bleibt für den Text keine Spalte übrig. */
  .treppe__feld--2, .treppe__feld--3 { margin-left: 0; }
  .treppe__feld--2 h3 { font-size: clamp(1.8rem, 8vw, 2.6rem); }
  .treppe__feld--3 h3 { font-size: clamp(1.6rem, 7vw, 2.2rem); }
}

/* ============================================================================
   REFERENZ — ein echter Screenshot, kein Mockup. Dezenter Rahmen mit der
   echten URL in Mono; der Rahmen behauptet kein Gerät, er zeigt die Herkunft.
   ========================================================================== */
.referenz { background: var(--studiograu); }
.referenz__projekt {
  display: grid; grid-template-columns: 1.35fr 1fr;
  gap: clamp(var(--space-lg), 5vw, var(--space-2xl));
  align-items: center;
  margin-top: var(--space-xl);
}
.referenz__rahmen { margin: 0; border: 1px solid var(--border-strong); background: var(--papier); }
.referenz__leiste {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-mono); font-size: var(--step--1);
  color: var(--werkstattgrau);
}
.referenz__leiste::before {
  content: ""; width: 0.5rem; height: 0.5rem; flex: none;
  background: var(--accent);
}
.referenz__rahmen img { display: block; width: 100%; height: auto; }
.referenz__text h3 { font-size: clamp(1.8rem, 3.4vw, 2.8rem); margin: 0 0 var(--space-sm); }
.referenz__punkte { list-style: none; margin: var(--space-md) 0 0; padding: 0; display: grid; gap: var(--space-2xs); }
.referenz__punkte li {
  padding-left: 1.6rem; position: relative;
  color: var(--werkstattgrau); font-size: var(--step--1);
}
.referenz__punkte li::before {
  content: "\203A"; position: absolute; left: 0.2rem; top: -0.05em;
  font-family: var(--font-mono); color: var(--accent); font-weight: 700;
}
/* Ab dem zweiten Projekt kehrt sich die Zeile um: zwei gleich gebaute Reihen
   untereinander lesen sich als Liste, nicht als zwei eigenständige Arbeiten.
   nth-of-type zählt nur die <article> — der Überschriftenblock ist ein <div>. */
.referenz__projekt:nth-of-type(even) { grid-template-columns: 1fr 1.35fr; }
.referenz__projekt:nth-of-type(even) .referenz__rahmen { order: 2; }
.referenz__projekt + .referenz__projekt { margin-top: clamp(var(--space-2xl), 7vw, var(--space-3xl)); }
@media (max-width: 860px) {
  .referenz__projekt,
  .referenz__projekt:nth-of-type(even) { grid-template-columns: 1fr; }
  /* Einspaltig steht das Bild wieder überall oben — sonst rutscht es beim
     zweiten Projekt unter den Text und die Reihenfolge wirkt zufällig. */
  .referenz__projekt:nth-of-type(even) .referenz__rahmen { order: 0; }
}

/* ============================================================================
   PERSON — der „ein Ansprechpartner"-Moment. Marine-Vollbreitband, Porträt
   vollhoch und randlos rechts. Das Hochformat wird respektiert, nicht
   ins Querformat gequetscht; kein Filter auf dem Gesicht.
   ========================================================================== */
.person {
  background: var(--accent-2);
  color: var(--papier);
  display: grid;
  grid-template-columns: 1fr minmax(18rem, 38%);
  align-items: stretch;
  clip-path: polygon(0 var(--kante-band), 100% 0, 100% 100%, 0 100%);
  /* Der Schnitt nimmt oben ein Dreieck aus der Fläche — sichtbar wird dort, was
     DAHINTER liegt, und das war die weiße Seitenfläche: ein heller Splitter
     zwischen Referenzband und Marine. Die Sektion rückt deshalb um die Kanten-
     höhe unter das Band darüber (das seinerseits um denselben Betrag weiter
     reicht, s. `.section:has(+ .person)`). Im Dreieck steht damit die Farbe der
     Sektion darüber — die Schräge liest als Kante zwischen zwei Feldern. */
  margin-top: calc(var(--kante-band) * -1);
}
/* Gilt für die Sektion unmittelbar davor, unabhängig davon, welche es ist: die
   Referenz kann in der site.json fehlen, dann steht die Treppe darüber. Der
   Zuschlag hält den Abstand zum Inhalt genau so groß wie vor dem Hochrücken. */
.section:has(+ .person) { padding-bottom: calc(6rem + var(--kante-band)); }
@media (min-width: 50rem) {
  .section:has(+ .person) { padding-bottom: calc(8rem + var(--kante-band)); }
}
.person__text {
  display: grid; align-content: center; gap: var(--space-md);
  padding: 4rem 1.6rem;
  margin-left: auto;
  max-width: 46rem; width: 100%;
}
@media (min-width: 50rem) { .person__text { padding: 7rem 5rem; } }
.person__text h2 { font-size: clamp(2.2rem, 5.2vw, 4.4rem); margin: 0; }
.person__text p { margin: 0; color: color-mix(in srgb, var(--papier) 80%, transparent); max-width: 42ch; }
.person__text .pfeil-link { justify-self: start; }
.person__bild { position: relative; min-height: clamp(22rem, 46vw, 40rem); margin: 0; }
.person__bild picture, .person__bild img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 12%;
}

/* ---------------------------------------------------------------------------
   Kennzeichnung des KI-bearbeiteten Porträts (Art. 50 Abs. 4 und 5 KI-VO).

   Sie steht in der unteren Ecke des Bildes selbst, nicht als Bildunterschrift
   darunter: der Hinweis gehört zum Bild und muss mit ihm mitwandern, egal in
   welchem Layout es steht — auf der Startseite füllt das Porträt seine Zelle
   randlos, da gibt es kein „darunter".

   Wie weit sich der Hinweis zurücknehmen darf, ist keine Geschmacksfrage. Er
   muss „klar und erkennbar" und barrierefrei sein (Art. 50 Abs. 5); dezent ist
   deshalb alles, was Fläche spart, und nichts, was Lesbarkeit kostet.

   Im Ruhezustand steht deshalb nur „AI" da — das ist kein Kürzel, das wir uns
   ausgedacht haben, sondern die Form, die der Code of Practice der Kommission
   als standardisiertes Sichtlabel vorsieht. Der Code sieht die Lokalisierung je
   Sprache vor (deutsch wäre „KI"); der Betreiber hat sich bewusst für die
   englische Grundform entschieden. Beim Überfahren wächst das Label nach links
   zur vollen Angabe „AI-BEARBEITET" aus. Dass die Kurzform englisch ist, trägt
   die Kennzeichnung nicht allein: die ausgeschriebene Angabe, der vorgelesene
   Satz („mit künstlicher Intelligenz bearbeitet"), der Bildnachweis im
   Impressum und die XMP-Daten in der Bilddatei stehen daneben. (`:focus-within` steht mit im Selektor, greift
   heute aber nie — im Bild liegt nichts Fokussierbares. Das Label dafür
   fokussierbar zu machen, hieße einen Tabstop ohne Funktion einzubauen; wer
   mit der Tastatur oder einem Vorleser unterwegs ist, bekommt die Angabe
   ohnehin vollständig, siehe unten.)

   Drei Dinge daran sind Absicht und dürfen nicht „vereinfacht" werden:

   - Das Label ist IMMER sichtbar, die Expansion ist Zugabe. Eine Kennzeichnung,
     die erst bei Hover erscheint, gäbe es auf Touch-Geräten gar nicht und wäre
     bei erster Exposition nicht da — genau das verlangt Art. 50 Abs. 5 aber.
   - Der Vorleser bekommt immer den ganzen Satz. Die beiden sichtbaren Teile
     („KI" und „-bearbeitet") tragen `aria-hidden`, weil ein aufklappendes
     Wortfragment vorgelesen keinen Sinn ergibt; daneben steht der vollständige
     Satz in `.visually-hidden`. Die zusammengeklappte Hälfte bleibt trotzdem
     bei `max-width: 0` statt `display: none` — sonst müsste der Browser sie
     beim Aufklappen neu einfügen und der Übergang würde springen.
   - NICHT gespart wird am Kontrast. Der Bildgrund unter der Ecke schwankt
     gemessen zwischen Helligkeit 0 und 255 (helle Wand, dunkles Hemd), ein
     Hinweis ohne Sockel wäre also je nach Bild mal lesbar und mal nicht. Der
     Sockel deckt deshalb genug, um ALLEIN zu tragen: Weiß auf rgba(11,22,41,.72)
     hält über jedem denkbaren Untergrund über 4.5:1 (WCAG AA), im schlechtesten
     Fall — reinweißer Grund — 5,2:1. Die Kommission warnt im Code of Practice
     ausdrücklich vor „schwachen Labels auf Bildern"; klein darf es sein,
     blass nicht.

   Ein durchsichtigerer Sockel mit `backdrop-filter: brightness()` sah leichter
   aus und war schon gebaut; er ist wieder heraus. Der Filter fällt in mehr
   Lagen aus, als es scheint (Druck, Screenshot-Werkzeuge, abgeschaltete
   Effekte), und dann läge Weiß auf einem 0,5-Sockel: über hellem Grund 2,7:1.
   Eine Kennzeichnung, die je nach Rendering verschwindet, ist keine. Der Blur
   bleibt als reine Zutat — er trägt keinen Kontrast.
   --------------------------------------------------------------------------- */
.ki-hinweis {
  position: absolute; right: 0.6rem; bottom: 0.6rem; z-index: 1;
  display: flex; align-items: baseline;
  font-family: var(--font-mono);
  font-size: 0.6875rem; line-height: 1;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: #fff;
  background: rgba(11, 22, 41, 0.72);
  padding: 0.25rem 0.4rem; border-radius: 2px;
  backdrop-filter: blur(3px);
}
/* Der ausklappbare Teil. `max-width` statt `width`, damit der Endwert nicht
   geraten werden muss — der Inhalt bestimmt die Breite, der Wert deckelt sie
   nur. Er liegt bewusst weit über dem Bedarf (gemessen 78 px ≈ 12 ch): mit
   einem knappen Deckel schnitte eine andere Schriftgröße oder ein
   Fallback-Font den letzten Buchstaben ab. */
.ki-hinweis__lang {
  display: inline-block; overflow: hidden; white-space: nowrap;
  max-width: 0; opacity: 0;
  transition: max-width 0.32s ease, opacity 0.2s ease 0.06s;
}
.person__bild:hover .ki-hinweis__lang,
.person__bild:focus-within .ki-hinweis__lang,
.personkopf__bild:hover .ki-hinweis__lang,
.personkopf__bild:focus-within .ki-hinweis__lang {
  max-width: 16ch; opacity: 1;
}
/* Ohne Zeigegerät (Touch) gibt es kein Hover. Dort steht die Langfassung
   dauerhaft: lieber ein etwas breiteres Label als eine Angabe, an die niemand
   herankommt. */
@media (hover: none) {
  .ki-hinweis__lang { max-width: 16ch; opacity: 1; transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .ki-hinweis__lang { transition: none; }
}
/* Im Ausdruck bleibt die Kennzeichnung stehen und wird deckend gesetzt: Browser
   lassen Hintergrundfarben beim Drucken standardmäßig weg, weißer Text auf
   weißem Papier wäre die perfekte Tarnung. */
@media print {
  .ki-hinweis { background: #0b1629; color: #fff; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* Auf Papier gibt es kein Überfahren — dort steht die Angabe ausgeschrieben. */
  .ki-hinweis__lang { max-width: 16ch; opacity: 1; transition: none; }
}
@media (max-width: 860px) {
  /* Schmaler Schirm: der Schnitt darf steiler stehen, sonst verschwindet er.
     Über die Variable statt über ein zweites clip-path — so kennen Schnitt,
     Hochrücken und der Zuschlag der Sektion darüber weiterhin denselben Wert. */
  :root { --kante-band: 5vw; }
  .person { grid-template-columns: 1fr; }
  .person__bild { min-height: 24rem; order: -1; }
  .person__text { margin-left: 0; }
}

/* ============================================================================
   ABSCHLUSS — der zweite exakte Keil, gespiegelt: er steigt von links oben
   herein und schließt den Bogen zum Hero.
   ========================================================================== */
.abschluss {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--marine-tief);
  color: var(--papier);
  padding-top: 4.5rem;
  padding-bottom: 4.5rem;
}
@media (min-width: 50rem) { .abschluss { padding-top: 8rem; padding-bottom: 8rem; } }
.abschluss__keil { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
.abschluss__keil::before {
  content: "";
  position: absolute;
  right: 62%; bottom: 100%;
  width: 220%; height: 220%;
  background: var(--accent);
  transform-origin: 100% 100%;
  transform: rotate(calc(var(--kante-winkel) * -1));
}
.abschluss__inner { display: grid; gap: var(--space-md); justify-items: end; text-align: right; }
.abschluss__block { display: grid; gap: var(--space-md); justify-items: inherit; }
.abschluss h2 { font-size: clamp(2.4rem, 6.5vw, 5.4rem); margin: var(--space-xs) 0 0; max-width: 16ch; }
.abschluss p { margin: 0; max-width: 44ch; color: color-mix(in srgb, var(--papier) 80%, transparent); }

/* --- Varianten: nicht jede Seite endet mit demselben Bild -------------------
   Ohne Variante (Startseite) steigt der Keil von links oben herein und ist der
   Gegenschnitt zum Hero — das gehört genau dorthin. */

/* „kehr": der Keil steigt von rechts unten auf wie im Hero, der Satz steht
   links. Gegenrichtung zur Startseite. */
.abschluss--kehr .abschluss__keil::before {
  right: auto; bottom: auto;
  left: 58%; top: 100%;
  transform-origin: 0 0;
}
.abschluss--kehr .abschluss__inner { justify-items: start; text-align: left; }

/* „saum": kein Dreieck im Feld, sondern ein flacher Saum an der Unterkante im
   Familien-Schnitt. Headline und Satz stehen nebeneinander statt untereinander. */
.abschluss--saum .abschluss__keil::before {
  right: auto; bottom: 0; left: 0; top: auto;
  width: 100%; height: 26%;
  transform: none;
  clip-path: polygon(0 100%, 100% 0, 100% 100%);
}
/* Der Satz muss über dem Saum bleiben — sonst schneidet die Diagonale durch die
   Unterstreichung des Kontakt-Links. */
.abschluss--saum { padding-bottom: 6.5rem; }
@media (min-width: 50rem) { .abschluss--saum { padding-bottom: 10rem; } }
.abschluss--saum .abschluss__inner {
  justify-items: start; text-align: left;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(var(--space-lg), 5vw, var(--space-2xl));
  align-items: end;
}
.abschluss--saum .abschluss__block { align-content: end; }
.abschluss--saum h2 { font-size: clamp(2.2rem, 5.4vw, 4.4rem); max-width: 14ch; }
@media (max-width: 860px) {
  .abschluss--kehr .abschluss__keil::before { left: 40%; }
  .abschluss--saum .abschluss__inner { grid-template-columns: 1fr; }
}
.abschluss__mail {
  font-family: var(--font-display); text-transform: none;
  font-size: clamp(1.4rem, 3.6vw, 2.6rem);
  color: var(--papier); text-decoration: none;
  border-bottom: 2px solid var(--accent); padding-bottom: 0.1em;
  letter-spacing: 0.01em;
}
.abschluss__mail:hover { color: var(--accent); }
@media (max-width: 860px) {
  .abschluss__keil::before { right: 76%; }
  .abschluss__inner { justify-items: start; text-align: left; }
}

/* ============================================================================
   UNTERSEITEN — jede Seite bekommt eine eigene Komposition, kein wiederholtes
   „Kopfzeile plus Liste".
   ========================================================================== */

/* --- Seitenkopf (Leistungen): links gesetzt, mit Kurzindex der Felder ------ */
.seitenkopf { background: var(--papier); padding-top: 3.5rem; padding-bottom: 2.25rem; }
@media (min-width: 50rem) { .seitenkopf { padding-top: 6rem; padding-bottom: 3.5rem; } }
.seitenkopf__grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: clamp(var(--space-lg), 5vw, var(--space-2xl)); align-items: end; }
.seitenkopf h1 { font-size: clamp(2.6rem, 7vw, 6rem); margin: var(--space-sm) 0 0; }
.seitenkopf .lead { margin: var(--space-md) 0 0; max-width: 44ch; }
/* Das Verzeichnis der Felder: die Headline kündigt eine Rangfolge an („Drei
   Felder. Eines führt."), also muss die erste Zeile sie einlösen — kräftigere
   Oberlinie im Akzent, dunkler Titel, größerer Grad. Die beiden anderen sind
   sichtbar nachgeordnet. Mehr Auszeichnung braucht es nicht: die Nummern tragen
   die Ordnung, kein zweiter Erklärsatz. */
.seitenkopf__index { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-sm); }
.seitenkopf__feld { border-top: 1px solid var(--border); padding-top: var(--space-xs); }
/* Das Raster sitzt auf der Zeile, NICHT auf dem <li>: läge es dort, stünde der
   Link als einziges Kind in der ersten (auto-breiten) Spalte und die Sprungmarke
   klebte am Titel statt an der Außenkante. */
.seitenkopf__feld > a,
.seitenkopf__zeile { display: grid; grid-template-columns: auto 1fr auto; align-items: baseline; gap: var(--space-xs); }
.seitenkopf__feld > a { text-decoration: none; color: inherit; padding-bottom: 0.15rem; }
.seitenkopf__nr {
  font-family: var(--font-mono); font-size: var(--step--1);
  letter-spacing: 0.12em; color: var(--accent);
}
.seitenkopf__name { font-weight: 600; color: var(--werkstattgrau); line-height: 1.25; }
.seitenkopf__marke { font-family: var(--font-mono); color: var(--werkstattgrau); }

.seitenkopf__feld--fuehrt { border-top: 2px solid var(--accent); }
.seitenkopf__feld--fuehrt .seitenkopf__name { color: var(--accent-2); font-size: var(--step-1); }

.seitenkopf__feld > a:hover .seitenkopf__name,
.seitenkopf__feld > a:hover .seitenkopf__marke { color: var(--accent); }
@media (prefers-reduced-motion: no-preference) {
  .seitenkopf__name, .seitenkopf__marke { transition: color var(--dur-fast) var(--ease), transform var(--dur-base) var(--ease-out); }
  .seitenkopf__feld > a:hover .seitenkopf__marke { transform: translateY(3px); }
}

@media (max-width: 860px) {
  .seitenkopf__grid { grid-template-columns: 1fr; }
  /* Einspaltig steht das Verzeichnis unter dem Satz — dort braucht die erste
     Zeile Abstand, sonst klebt sie am Lead. */
  .seitenkopf__index { margin-top: var(--space-md); }
}

/* ----------------------------------------------------------------------------
   LEISTUNGSFELDER — drei Felder, drei Formen. Die Seitenheadline kündigt eine
   Rangfolge an („Drei Felder. Eines führt."), also muss die Fläche sie einlösen:
   Feld 1 bekommt Grad und Raum, die beiden anderen sind sichtbar nachgeordnet
   und tragen je eine eigene Bildsprache (Oberfläche / Ablaufdiagramm) statt
   derselben Aufzählung in anderer Farbe.
   -------------------------------------------------------------------------- */
.lfeld { padding-top: 3.5rem; padding-bottom: 3.5rem; }
@media (min-width: 50rem) { .lfeld { padding-top: 5.5rem; padding-bottom: 5.5rem; } }
.lfeld__teaser { font-size: var(--step-1); margin: 0 0 var(--space-md); color: var(--werkstattgrau); }
.lfeld__text { margin: 0; color: var(--werkstattgrau); }
.lfeld__spalte h2 { font-size: clamp(1.9rem, 3.8vw, 3rem); margin: 0 0 var(--space-md); }
.lfeld__spalte--halb { max-width: 46rem; }

/* --- Feld 1 „führend": größte Fläche, größter Grad, Umfang als Verzeichnis -- */
.lfeld--eins { background: var(--papier); }
@media (min-width: 50rem) { .lfeld--eins { padding-top: 6.5rem; padding-bottom: 7rem; } }
.lfeld--eins h2 { font-size: clamp(2.6rem, 8vw, 7rem); margin: 0; max-width: 14ch; }
/* Der Satz steht zweispaltig unter der Headline — der Teaser führt, der
   Fließtext liegt daneben statt darunter. Das gibt es nur bei diesem Feld. */
.lfeld__satz {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(var(--space-md), 4vw, var(--space-2xl));
  margin-top: clamp(var(--space-lg), 4vw, var(--space-2xl));
  align-items: start;
}
.lfeld__satz .lfeld__teaser { font-size: var(--step-2); color: var(--accent-2); margin: 0; max-width: 22ch; }
.lfeld__satz .lfeld__text { max-width: 52ch; }
/* Verzeichnis statt Chevron-Liste: drei Spalten, Oberlinie, kein Aufzählungszeichen. */
.lfeld__verzeichnis {
  list-style: none; padding: 0;
  margin: clamp(var(--space-xl), 6vw, var(--space-2xl)) 0 0;
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg) clamp(var(--space-md), 3vw, var(--space-xl));
}
.lfeld__verzeichnis li {
  border-top: 2px solid var(--accent-2);
  padding-top: var(--space-xs);
  font-size: var(--step-0);
}
@media (max-width: 860px) {
  .lfeld__satz { grid-template-columns: 1fr; }
  .lfeld__verzeichnis { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) { .lfeld__verzeichnis { grid-template-columns: 1fr; } }

/* --- Feld 2 „Oberfläche": der Umfang IST die Navigation einer Anwendung ---- */
.lfeld--zwei { background: var(--accent-2); color: var(--papier); overflow: hidden; }
.lfeld--zwei .lfeld__teaser,
.lfeld--zwei .lfeld__text { color: color-mix(in srgb, var(--papier) 82%, transparent); }
.lfeld__grid {
  display: grid; grid-template-columns: minmax(16rem, 33%) 1fr;
  gap: clamp(var(--space-lg), 5vw, var(--space-2xl));
  align-items: center;
}
/* Der Rahmen läuft nach rechts aus dem Satzspiegel und wird von der Sektion
   angeschnitten: eine Anwendung ist größer als ihr Ausschnitt. */
.mockup__rahmen {
  background: var(--marine-tief);
  border: 1px solid color-mix(in srgb, var(--papier) 20%, transparent);
}
@media (min-width: 50rem) { .mockup__rahmen { width: calc(100% + 14vw); } }
.mockup__leiste {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid color-mix(in srgb, var(--papier) 16%, transparent);
  font-family: var(--font-mono); font-size: var(--step--1);
  color: color-mix(in srgb, var(--papier) 72%, transparent);
}
.mockup__marke { width: 0.55rem; height: 0.55rem; flex: none; background: var(--accent); }
.mockup__flaeche { display: grid; grid-template-columns: minmax(11rem, 42%) 1fr; }
.mockup__nav {
  list-style: none; margin: 0; padding: 0.5rem 0;
  border-right: 1px solid color-mix(in srgb, var(--papier) 16%, transparent);
}
.mockup__nav li {
  padding: 0.62rem 1rem 0.62rem 1.6rem;
  font-size: var(--step--1); line-height: 1.35;
  color: color-mix(in srgb, var(--papier) 86%, transparent);
  position: relative;
}
.mockup__nav li::before {
  content: ""; position: absolute; left: 0.75rem; top: 1.05em;
  width: 0.3rem; height: 0.3rem; background: var(--akzent-auf-dunkel);
}
/* Die erste Zeile ist als aktiver Eintrag markiert — das macht aus der Liste
   eine Oberfläche. Reine Fläche, kein zweiter Akzentton. */
.mockup__nav li:first-child {
  background: color-mix(in srgb, var(--papier) 7%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
  color: var(--papier);
}
/* Der Inhaltsbereich ist bewusst ohne Zahlen: eine erfundene Auswertung wäre
   eine Falschangabe. Er zeigt nur die Gattung — dekorativ, aria-hidden. */
.mockup__inhalt { padding: 1rem; display: grid; gap: 1rem; align-content: start; }
.mockup__kacheln { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; }
.mockup__kacheln span {
  height: 2.6rem;
  border: 1px solid color-mix(in srgb, var(--papier) 14%, transparent);
  background: color-mix(in srgb, var(--papier) 4%, transparent);
}
.mockup__chart { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0.45rem; align-items: end; height: 5rem; }
.mockup__chart i { background: color-mix(in srgb, var(--akzent-auf-dunkel) 55%, transparent); display: block; }
.mockup__chart i:nth-child(1) { height: 42%; }
.mockup__chart i:nth-child(2) { height: 66%; }
.mockup__chart i:nth-child(3) { height: 34%; }
.mockup__chart i:nth-child(4) { height: 82%; }
.mockup__chart i:nth-child(5) { height: 58%; }
.mockup__chart i:nth-child(6) { height: 100%; background: var(--accent); }
.mockup__chart i:nth-child(7) { height: 71%; }
.mockup__zeilen { display: grid; gap: 0.5rem; }
.mockup__zeilen span { height: 0.42rem; background: color-mix(in srgb, var(--papier) 13%, transparent); }
.mockup__zeilen span:nth-child(2) { width: 82%; }
.mockup__zeilen span:nth-child(3) { width: 64%; }
.mockup__zeilen span:nth-child(4) { width: 88%; }
@media (max-width: 860px) {
  .lfeld__grid { grid-template-columns: 1fr; }
  .mockup__flaeche { grid-template-columns: 1fr; }
  .mockup__nav { border-right: 0; border-bottom: 1px solid color-mix(in srgb, var(--papier) 16%, transparent); }
}

/* --- Feld 3 „Strang": Ablaufdiagramm mit Rücklauf --------------------------
   Die sechs Punkte sind KEINE Reihenfolge, deshalb keine Nummern und keine
   Pfeile zwischen den Knoten. Was der Strang behauptet, ist der Kreislauf:
   der Rücklauf führt zurück an den Anfang. */
.lfeld--drei { background: var(--studiograu); }
.strang { margin-top: clamp(var(--space-xl), 5vw, var(--space-2xl)); }
.strang__stationen {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(6, 1fr);
  column-gap: clamp(var(--space-sm), 2vw, var(--space-lg));
  border-top: 2px solid color-mix(in srgb, var(--accent-2) 30%, transparent);
}
.strang__stationen li {
  position: relative;
  padding-top: 1.7rem;
  font-size: var(--step--1); line-height: 1.4;
  color: var(--accent-2);
}
.strang__stationen li::before {
  content: ""; position: absolute; left: 0; top: -0.42rem;
  width: 0.85rem; height: 0.85rem; background: var(--accent);
}
/* Der Rücklauf: ein Bogen unter der Reihe, der links mit einer Spitze nach
   oben zurück auf den ersten Knoten zeigt. */
.strang__ruecklauf {
  height: 1.5rem; margin-top: var(--space-md); position: relative;
  border: 2px solid color-mix(in srgb, var(--accent-2) 30%, transparent);
  border-top: 0;
}
.strang__ruecklauf::before {
  content: ""; position: absolute; left: -0.42rem; top: -0.1rem;
  border-left: 0.45rem solid transparent;
  border-right: 0.45rem solid transparent;
  border-bottom: 0.58rem solid var(--accent);
}
@media (max-width: 900px) {
  .strang__stationen { grid-template-columns: repeat(3, 1fr); row-gap: var(--space-lg); }
}
@media (max-width: 560px) {
  /* Senkrecht trägt der Strang weiter als ein zerbrochenes Raster: die Linie
     wandert nach links, der Bogen entfällt (waagerecht ergäbe er hier nichts). */
  .strang__stationen {
    grid-template-columns: 1fr; row-gap: 0;
    border-top: 0; border-left: 2px solid color-mix(in srgb, var(--accent-2) 30%, transparent);
  }
  .strang__stationen li { padding: 0.9rem 0 0.9rem 1.6rem; font-size: var(--step-0); }
  .strang__stationen li::before { left: -0.42rem; top: 1.1rem; }
  .strang__ruecklauf { display: none; }
}

/* --- Technik: eine Zeile, keine Logo-Wand ---------------------------------- */
.technik { background: var(--papier); padding-top: 2.75rem; padding-bottom: 2.75rem; border-top: 2px solid var(--accent-2); }
@media (min-width: 50rem) { .technik { padding-top: 4rem; padding-bottom: 4rem; } }
.technik__liste { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-md); margin: var(--space-sm) 0 var(--space-md); padding: 0; list-style: none; }
.technik__liste li { font-family: var(--font-mono); font-size: var(--step-1); color: var(--accent-2); }
.technik__hinweis { margin: 0; max-width: 52ch; color: var(--werkstattgrau); }

/* --- Personkopf (Über mich): Porträt in voller Größe, Text als Lesespur ---- */
/* Unten behält die Sektion einen Innenabstand wie jede andere — nur das Porträt
   wird bewusst daraus herausgezogen (negativer Außenabstand gleicher Größe) und
   steht damit exakt auf der Sektionskante, statt zu schweben. */
.personkopf { background: var(--studiograu); padding-top: 3.5rem; padding-bottom: 1.5rem; }
@media (min-width: 50rem) { .personkopf { padding-top: 5rem; } }
.personkopf__grid { position: relative; z-index: 0; display: grid; grid-template-columns: 1fr 1fr; gap: clamp(var(--space-lg), 5vw, var(--space-2xl)); align-items: end; }
.personkopf h1 { font-size: clamp(2.6rem, 7vw, 5.6rem); margin: var(--space-sm) 0 var(--space-md); }
.personkopf__text p { margin: 0 0 var(--space-md); max-width: 46ch; color: var(--werkstattgrau); font-size: var(--step-1); }
.personkopf__text p:last-child { margin-bottom: clamp(2rem, 5vw, 3.5rem); }
/* Das Porträt sitzt bündig auf der Sektionskante (align-items:end) — es steht
   damit auf der Grundlinie, statt zu schweben. Ein zusätzlicher Farbsockel lag
   vollständig hinter dem Bild und war unsichtbar; er ist ersatzlos gestrichen. */
.personkopf__bild { margin: 0 0 -1.5rem; position: relative; }
.personkopf__bild img { display: block; width: 100%; height: auto; }
@media (max-width: 860px) {
  .personkopf__grid { grid-template-columns: 1fr; }
  .personkopf__bild { max-width: 26rem; }
}

/* --- Haltung: drei Aussagen einer Person, kein Zeilenraster ----------------
   Ausgerechnet auf der Seite über den Menschen darf nicht dieselbe
   Trennlinien-Liste stehen wie bei den Leistungen. Die Sätze stehen deshalb
   groß gesetzt in der Fläche, das Stichwort signiert sie darunter. Den Rhythmus
   macht der wechselnde Versatz — links, nach rechts gerückt, eingerückt —,
   nicht eine Linie über die volle Breite. */
.haltung { background: var(--papier); }
.haltung__saetze {
  list-style: none; padding: 0;
  margin: clamp(var(--space-xl), 6vw, var(--space-2xl)) 0 0;
  display: grid; gap: clamp(var(--space-xl), 6vw, 5.5rem);
}
.haltung__aussage {
  margin: 0;
  font-size: clamp(1.35rem, 2.5vw, 2rem);
  line-height: 1.32;
  color: var(--accent-2);
  letter-spacing: -0.005em;
}
.haltung__marke {
  display: flex; align-items: center; gap: 0.9rem;
  margin: var(--space-md) 0 0;
  font-family: var(--font-mono); font-size: var(--step--1);
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent);
}
.haltung__strich { display: block; width: 2.4rem; height: 3px; background: var(--accent); flex: none; }
/* Der Versatz: drei Werte, sonst nichts. Die erste Aussage trägt die
   Kernaussage der Marke und steht deshalb am größten.
   Die Zeilenbreite steht bewusst in rem, nicht in ch: `ch` würde sich auf die
   geerbte Fließtextgröße des <li> beziehen, nicht auf den Display-Grad des
   Satzes darin — die Spalte fiele damit viel zu schmal aus. */
.haltung__satz { max-width: 36rem; }
.haltung__satz:nth-child(1) { max-width: 46rem; }
.haltung__satz:nth-child(1) .haltung__aussage { font-size: clamp(1.5rem, 3.2vw, 2.6rem); }
.haltung__satz:nth-child(2) { justify-self: end; }
.haltung__satz:nth-child(3) { margin-left: 12%; }
@media (max-width: 700px) {
  .haltung__satz { max-width: none; }
  .haltung__satz:nth-child(3) { margin-left: 0; }
}

/* --- Ablauf: echte Sequenz, deshalb echte Nummern (01–04) ----------------- */
.sequenz { background: var(--accent-2); color: var(--papier); }
.sequenz .eyebrow, .sequenz .mono-label { color: var(--papier); }
.sequenz h2 { margin: var(--space-xs) 0 var(--space-sm); }
.sequenz .lead { color: color-mix(in srgb, var(--papier) 78%, transparent); }
.sequenz__liste { list-style: none; margin: var(--space-xl) 0 0; padding: 0; display: grid; gap: 0; counter-reset: schritt; }
.sequenz__liste li {
  display: grid; grid-template-columns: auto minmax(10rem, 22%) 1fr;
  gap: clamp(var(--space-sm), 3vw, var(--space-lg));
  align-items: baseline;
  border-top: 1px solid color-mix(in srgb, var(--papier) 26%, transparent);
  padding-top: 1.6rem; padding-bottom: 1.6rem;
}
@media (min-width: 50rem) { .sequenz__liste li { padding-top: 2.4rem; padding-bottom: 2.4rem; } }
.sequenz__liste li::before {
  counter-increment: schritt;
  content: counter(schritt, decimal-leading-zero);
  font-family: var(--font-mono); font-size: var(--step-1);
  color: var(--akzent-auf-dunkel); font-weight: 700;
}
.sequenz__liste h3{ font-size: clamp(1.4rem, 2.6vw, 2rem); margin: 0; }
.sequenz__liste p { margin: 0; color: color-mix(in srgb, var(--papier) 78%, transparent); max-width: 58ch; }
@media (max-width: 760px) {
  .sequenz__liste li { grid-template-columns: auto 1fr; }
  .sequenz__liste p { grid-column: 2; }
}

/* --- Kontakt: Aussage links, Formular rechts ------------------------------ */
.kontaktblock { background: var(--papier); padding-top: 3.5rem; padding-bottom: 3.5rem; }
@media (min-width: 50rem) { .kontaktblock { padding-top: 6rem; padding-bottom: 6rem; } }
.kontaktblock__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(var(--space-lg), 5vw, var(--space-2xl)); align-items: start; }
.kontaktblock h1 { font-size: clamp(2.4rem, 6vw, 5rem); margin: var(--space-sm) 0 var(--space-md); }
.kontaktblock__lead { font-size: var(--step-1); color: var(--werkstattgrau); margin: 0 0 var(--space-lg); max-width: 40ch; }
.kontaktdaten { display: grid; gap: var(--space-sm); margin: 0; }
.kontaktdaten > div { display: grid; gap: 0.25rem; border-top: 1px solid var(--border); padding-top: var(--space-xs); }
.kontaktdaten dt { font-family: var(--font-mono); font-size: var(--step--1); letter-spacing: 0.12em; text-transform: uppercase; color: var(--werkstattgrau); }
.kontaktdaten dd { margin: 0; font-size: var(--step-1); }
.kontaktdaten a { color: var(--accent-2); text-decoration: none; border-bottom: 2px solid var(--accent); }
.kontaktdaten a:hover { color: var(--accent); }
/* Fehlende Pflichtangaben sind sichtbar als Lücke markiert, nicht erfunden. */
.platzhalter {
  display: inline-block;
  font-family: var(--font-mono); font-size: var(--step--1);
  color: var(--werkstattgrau);
  background: var(--studiograu);
  border: 1px dashed var(--border-strong);
  padding: 0.15em 0.5em;
}
/* Der Link zur Datenschutzerklärung muss im Fließtext des Labels als Link
   erkennbar sein — Farbe allein reicht dafür nicht. */
.kontaktblock .field--check label a { color: var(--accent); text-decoration: underline; text-underline-offset: 0.15em; }
/* Was in die Nachricht gehört: nimmt dem Formular die Hürde und spiegelt den
   ersten Schritt des Ablaufs (Gespräch & Briefing). */
.kontakthinweis { margin: var(--space-lg) 0 0; max-width: 42ch; }
.kontakthinweis p { margin: var(--space-2xs) 0 0; color: var(--werkstattgrau); font-size: var(--step--1); }
.kontaktblock .form { border-radius: 0; box-shadow: none; border: 2px solid var(--accent-2); background: var(--papier); }
.kontaktblock .form .btn { justify-self: start; }
@media (max-width: 860px) { .kontaktblock__grid { grid-template-columns: 1fr; } }

/* ============================================================================
   Rechtsseiten + geteilte Bibliothek an die Projekt-Haltung angleichen
   ========================================================================== */
.section--accent { background: var(--studiograu); }

/* ============================================================================
   Selbstzeichnende SVG-Momente (data-sda="draw" + pathLength="1").
   Ruhezustand ist IMMER der sichtbare Endzustand: ohne JS, ohne Support und
   bei prefers-reduced-motion steht die Zeichnung fertig da.
   ========================================================================== */
.kante-draw path { stroke-dasharray: 1; stroke-dashoffset: 0; }
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .kante-draw path {
      animation: kante-zeichnen linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 42%;
    }
  }
  .hero-kante__code path {
    animation: kante-zeichnen 1.5s var(--ease-out) both;
    animation-delay: 0.35s;
  }
}
@keyframes kante-zeichnen { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

/* Sektions-Marke: der „/" aus dem </> als kurzer, selbstzeichnender Strich im
   Logo-Winkel. Feste Maße — gestreckt würde aus der Marken-Diagonale eine
   beliebige Linie. */
.kante-linie {
  display: block; width: 3.4rem; height: 2.25rem;
  margin-top: var(--space-md);
  color: var(--accent); overflow: visible;
}
.kante-linie path { fill: none; stroke: currentColor; stroke-width: 5; stroke-linecap: square; }
.sequenz .kante-linie, .person .kante-linie { color: var(--akzent-auf-dunkel); }

/* ============================================================================
   Zugänglichkeit: sichtbarer Tastaturfokus auf allen eigenen Interaktionen.
   ========================================================================== */
.treppe__feld a:focus-visible,
.pfeil-link:focus-visible,
.abschluss__mail:focus-visible,
.seitenkopf__feld > a:focus-visible,
.kontaktdaten a:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}
.hero-kante .pfeil-link:focus-visible,
.abschluss .pfeil-link:focus-visible,
.person .pfeil-link:focus-visible,
.abschluss__mail:focus-visible {
  outline-color: var(--papier);
}

/* ============================================================================
   Druck: die Farbflächen kosten Toner und tragen auf Papier nichts bei.
   ========================================================================== */
@media print {
  .hero-kante, .person, .abschluss, .lfeld--zwei, .sequenz { background: #fff; }
  /* Die hellen Schriften dieser Bänder müssen MIT umgestellt werden, und zwar
     bis in die Nachfahren: Browser drucken Flächenfarben standardmäßig nicht,
     weißer Text stünde also unsichtbar auf weißem Papier. Die eigenen
     Textfarben der Kinder (.hero-kante__lead, .lfeld__teaser, .sequenz p …)
     sind spezifischer als eine Sammelregel — deshalb hier der Nachdruck. */
  .hero-kante, .hero-kante *,
  .person, .person *,
  .abschluss, .abschluss *,
  .lfeld--zwei, .lfeld--zwei *,
  .sequenz, .sequenz * { color: #000 !important; }
  /* Der Anwendungs-Rahmen bekommt auf Papier eine Kontur statt der Fläche,
     sonst steht die Navigationsspalte ohne jeden Halt da. */
  .mockup__rahmen { background: #fff; border-color: #000; }
  .mockup__inhalt, .hero-kante__keil, .abschluss__keil, .laufband { display: none; }
}

/* ============================================================================
   WERDEGANG — der persönliche Weg als vertikale Etappen (Über mich).
   Spaltenmaße als lokale Variablen, damit die Linie exakt in der Knotenmitte
   sitzt (eine Rechnung, kein doppelt gepflegter Wert). Die Linie zeichnet
   sich scroll-gebunden selbst (data-sda="draw", effects.css) — ohne
   Unterstützung steht sie fertig da. Chips eckig (Die Kante), nur die
   Icon-Knoten rund: der Ring ist als Signet-Form Teil der Marke.
   ========================================================================== */
.werdegang {
  --weg-marke: 7.5rem; --weg-knoten: 2.6rem; --weg-abstand: var(--space-md);
  background: var(--studiograu);
}
.werdegang__spur { position: relative; margin-top: clamp(var(--space-lg), 4vw, var(--space-xl)); }
.werdegang__linie {
  position: absolute; z-index: 0; top: calc(var(--weg-knoten) / 2); bottom: 0;
  inset-inline-start: calc(var(--weg-marke) + var(--weg-abstand) + var(--weg-knoten) / 2 - 1px);
  width: 2px; pointer-events: none;
  /* Die Linie läuft am letzten Knoten nicht hart aus, sondern blendet weg —
     der Weg ist nicht zu Ende. */
  -webkit-mask-image: linear-gradient(#000 78%, transparent);
  mask-image: linear-gradient(#000 78%, transparent);
}
.werdegang__linie svg { width: 2px; height: 100%; overflow: visible; }
.werdegang__linie path { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.werdegang__liste {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(var(--space-md), 3vw, var(--space-lg));
}
.werdegang__etappe {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: var(--weg-marke) var(--weg-knoten) 1fr;
  column-gap: var(--weg-abstand); align-items: start;
}
.werdegang__marke { padding-top: 0.72rem; text-align: end; overflow-wrap: anywhere; }
.werdegang__knoten {
  display: grid; place-items: center;
  width: var(--weg-knoten); height: var(--weg-knoten);
  border-radius: var(--radius-full); border: 1px solid var(--accent-300);
  background: var(--papier); color: var(--accent-600);
}
.werdegang__knoten svg { width: 1.2rem; height: 1.2rem; }
.werdegang__text h3 { font-size: var(--step-1); }
.werdegang__text p { margin: var(--space-2xs) 0 0; max-width: 64ch; }
.werdegang__felder {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs) var(--space-sm);
  margin-top: clamp(var(--space-lg), 4vw, var(--space-xl));
  padding-top: var(--space-md); border-top: 1px solid var(--border);
}
.werdegang__felder-label { display: inline; }
.werdegang__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 0; padding: 0; }
.werdegang__chips li {
  padding: 0.35rem 0.8rem; border: 1px solid var(--border);
  background: var(--papier);
  font-family: var(--font-mono); font-size: var(--step--1);
  letter-spacing: 0.04em; color: var(--werkstattgrau);
}
@media (max-width: 760px) {
  .werdegang { --weg-knoten: 2.2rem; --weg-abstand: var(--space-sm); }
  .werdegang__linie { inset-inline-start: calc(var(--weg-knoten) / 2 - 1px); }
  .werdegang__etappe { grid-template-columns: var(--weg-knoten) 1fr; }
  .werdegang__knoten { grid-column: 1; grid-row: 1; }
  .werdegang__marke { grid-column: 2; grid-row: 1; text-align: start; padding-top: 0.42rem; }
  .werdegang__text { grid-column: 2; grid-row: 2; padding-top: var(--space-2xs); }
}
