/* ==========================================================================
   Components — Header, Hero, Kennzahlen, Akkordeon, Logos, Arbeiten, Footer
   ========================================================================== */

/* --- Kopfzeile ---------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: var(--rule) solid var(--line);
}
@supports not (backdrop-filter: blur(1px)) { .site-header { background: var(--paper); } }

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  min-height: var(--header-h, 76px);
}

/* Der Wortmarken-SVG ist sehr breit und flach (Seitenverhältnis ~12:1).
   Die Padding-Fläche macht daraus ein ausreichend großes Klickziel. */
.brand {
  display: flex;
  align-items: center;
  text-decoration: none;
  flex: none;
  color: var(--ink);
  padding-block: var(--s-2);
}
/* Keine vw-Breite (Prinzip aus DESIGN-SYSTEM.md 7b): vw schliesst die
   Rollbalkenbreite anders ein als die Container-Prozentrechnung und liess
   das Logo beim Seitenwechsel je nach Rollbalken-Zustand um ein paar Pixel
   springen. */
.brand__logo { width: 208px; height: auto; display: block; }
.brand:hover { text-decoration: none; color: var(--ink-2); }

.nav { margin-left: auto; }
.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(var(--s-2), 1.8vw, var(--s-4));
  list-style: none;
  margin: 0; padding: 0;
}
.nav__list li { margin: 0; }
/* Der Akzentstrich sitzt direkt unter der Schrift. Zwischenstand vom
   27.08.2026 war die Unterkante der Kopfzeile - dort ging er unter und
   wurde auf Wunsch wieder zurueckgeholt. Die Einblendung von links nach
   rechts bleibt. */
/* Versalien, leicht gesperrt und deutlich duenner - Vorbild ist die
   Navigation auf danielhacker.de (27.08.2026). Die Farbe ist im Ruhezustand
   zurueckgenommen und springt beim Ueberfahren auf volles Schwarz; zusammen
   mit dem einlaufenden Akzentstrich gibt das eine klare Rueckmeldung.
   Schriftgrad bewusst kleiner als --step--1: Grossbuchstaben und die
   Sperrung machen die Zeile sonst zu breit fuer sechs Punkte plus Logo. */
.nav__link {
  font-family: var(--font-display);
  /* 0.72rem mit 0.1em Sperrung ist der groesste Satz, der die sechs Punkte
     neben dem 208px-Logo noch traegt. Gemessen am 27.08.2026: mit 0.78rem
     und 0.14em braucht die Leiste 792px, mit diesen Werten 703px. Zum
     Vergleich - der fruehere Satz ohne Versalien brauchte 670px, der Bereich
     knapp ueber dem 860px-Umbruch war also schon vorher eng. */
  font-size: 0.72rem;
  font-weight: 450;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  padding: var(--s-1) 0;
  white-space: nowrap;
  color: var(--ink-2);
  transition: color var(--dur) var(--ease);
}
.nav__link:not(.nav__cta):hover,
.nav__link:not(.nav__cta):focus-visible,
.nav__link:not(.nav__cta)[aria-current="true"] { color: var(--ink); }
.nav__link:not(.nav__cta) {
  position: relative;
  display: inline-block;
}
/* Strich waechst von links nach rechts ein - Vorbild ist der Effekt auf
   danielhacker.de. Animiert wird right (100% -> 0), nicht width oder scaleX:
   scaleX wuerde von der Mitte aus wachsen und width erzwingt bei jedem Bild
   ein neues Layout. */
.nav__link:not(.nav__cta)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0;
  height: 3px;
  background: var(--accent);
  transition: right var(--dur) var(--ease);
}
.nav__link:not(.nav__cta):hover::after,
.nav__link:not(.nav__cta):focus-visible::after,
.nav__link:not(.nav__cta)[aria-current="true"]::after { right: 0; }
.nav__link:hover, .nav__link[aria-current="true"] { text-decoration: none; }

.nav-toggle {
  display: none;
  margin-left: auto;
  width: 48px; height: 48px;
  background: none;
  border: var(--rule) solid var(--line);
  cursor: pointer;
  padding: 0;
  place-items: center;
}
.nav-toggle__bar,
.nav-toggle__bar::before,
.nav-toggle__bar::after {
  display: block; width: 20px; height: 2px;
  background: var(--ink);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.nav-toggle__bar { position: relative; }
.nav-toggle__bar::before,
.nav-toggle__bar::after { content: ""; position: absolute; left: 0; }
.nav-toggle__bar::before { top: -6px; }
.nav-toggle__bar::after  { top: 6px; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar::after  { transform: translateY(-6px) rotate(-45deg); }

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0.95em 1.6em;
  min-height: 48px;
  text-decoration: none;
  border: 2px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.btn:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); text-decoration: none; }
.btn__arrow { transition: transform var(--dur) var(--ease); }
.btn:hover .btn__arrow { transform: translateX(4px); }

.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.section--dark .btn { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.section--dark .btn:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* Textlink mit Pfeil */
.link-arrow {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--step--1);
  letter-spacing: 0.02em;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  border-bottom: 2px solid var(--accent);
  padding-bottom: 2px;
}
.link-arrow:hover { text-decoration: none; border-bottom-color: var(--ink); }
.link-arrow span { transition: transform var(--dur) var(--ease); }
.link-arrow:hover span { transform: translateX(4px); }

/* --- Hero ----------------------------------------------------------------
   Ziel: die ganze Aussage steht im ersten Viewport. Deshalb ist die Headline
   bewusst kleiner als zuvor (vorher bis 7rem — da passte nur noch der Name
   ins Bild), und das Bild sitzt oben statt unten, damit es nicht angeschnitten
   wird.                                                                     */
.hero {
  position: relative;
  border-bottom: var(--rule) solid var(--line);
  overflow: clip;             /* fängt die Parallaxbewegung des Bildes ab */
}
.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 47%);
  gap: clamp(var(--s-4), 4vw, var(--s-6));
  align-items: center;
  padding-block: clamp(var(--s-4), 4vw, var(--s-6));
}
.hero__text { position: relative; z-index: 1; }
.hero__media { position: relative; }

.hero__title {
  /* Bewusst zurückgenommen. Mit der alten Größe stand im ersten Viewport nur
     noch der Name — die eigentliche Aussage fiel heraus. Jetzt trägt die
     Headline in drei bis vier Zeilen, ohne ihre Wucht zu verlieren. */
  font-size: clamp(2rem, 3.5vw, 3.3rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin: 0 0 var(--s-4);
  max-width: 15ch;
  text-wrap: balance;
}
.hero__roles {
  list-style: none;
  margin: 0 0 var(--s-4);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-3);
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 550;
  color: var(--ink-2);
}
/* Marker vor jedem Eintrag, nicht nur zwischen den Einträgen: die Zeile bricht
   je nach Breite um, ein reines Trennzeichen stünde dann am Zeilenanfang. */
.hero__roles li { margin: 0; display: flex; align-items: center; gap: var(--s-2); }
.hero__roles li::before {
  content: "";
  flex: none;
  width: 6px; height: 6px;
  background: var(--accent);
}
/* Das Bild ist absichtlich höher als sein Rahmen. Der Überschuss ist der Weg,
   den es beim Scrollen zurücklegt — dadurch entsteht die Parallaxe, ohne dass
   irgendwo eine Lücke aufreißt. --p wird vom Skript gesetzt (-1 … +1). */
/* Feste, an die Fensterhöhe gekoppelte Bildhöhe. Vorher füllte das Bild die
   ganze Rasterzeile — die wuchs mit der Textspalte mit, und object-fit
   beschnitt das Motiv dann bis zur Unkenntlichkeit. */
.hero__media picture {
  display: block;
  height: clamp(320px, 56svh, 580px);
  overflow: clip;
}
.hero__media img {
  width: 100%;
  height: calc(100% + 2 * var(--parallax-weg, 44px));
  margin-top: calc(-1 * var(--parallax-weg, 44px));
  object-fit: cover;
  display: block;
  transform: translate3d(0, calc(var(--p, 0) * var(--parallax-weg, 44px)), 0);
  will-change: transform;
  /* Sanftes Aufziehen beim Laden — einmal, dann nie wieder.
     scale steht bewusst als eigene Eigenschaft da: transform trägt bereits die
     Parallaxe, und Custom Properties ließen sich in @keyframes gar nicht
     interpolieren. */
  animation: hero-auf var(--dur-slow) var(--ease) both;
}
@keyframes hero-auf {
  from { opacity: 0; scale: 1.05; }
  to   { opacity: 1; scale: 1; }
}

/* Das NA-Signet als Gestaltungselement im Hero, nicht als zweites Logo.
   Es steht im Textfluss über der Headline — absolut positioniert lag es
   vorher mitten auf der Schrift. */
.hero__signet {
  display: block;
  width: 44px;
  color: var(--accent);
  margin-bottom: var(--s-3);
  transform: translate3d(0, calc(var(--p, 0) * -14px), 0);
  pointer-events: none;
}
.hero__signet svg { width: 100%; height: auto; display: block; }

/* "Zurueck"-Link auf Detailseiten (Blogbeitrag, Arbeitsprobe): bewusst nah an
   der Navigation und mit deutlichem Abstand zum Inhalt darunter - sonst
   wirkt er wie Teil des NA-Signet/Datum/Titel-Blocks statt einer eigenen,
   vorgelagerten Wegmarke. Die Sektion bekommt dafuer weniger Kopfabstand als
   sonst (padding-top am section-Tag), dieser Link gleicht das mit eigenem
   Abstand nach unten wieder aus. */
.zurueck { margin: 0 0 var(--s-7); }

/* --- Werdegang (Über mich) ------------------------------------------------
   Vier Karrierestationen mit Jahr - dieselbe Sprache wie die Kennzahlen
   (Strich oben statt Box), damit keine neue Bausteinart entsteht. */
.werdegang {
  list-style: none;
  margin: var(--s-6) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
}
.werdegang__item {
  border-top: 3px solid var(--ink);
  padding: var(--s-3) var(--s-4) 0 0;
}
.werdegang__jahr {
  display: block;
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: var(--s-1);
}
.werdegang__titel { font-size: var(--step--1); color: var(--ink-2); }

/* --- Kenntnisse & Fähigkeiten (Über mich) ---------------------------------
   Schmale Balken statt Kreisdiagramm - passt zu "keine Zierelemente" und
   braucht kein SVG. Prozentwerte stammen unveraendert aus dem Bestand. */
.skill { margin-bottom: var(--s-3); }
.skill__kopf {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-2);
  margin-bottom: var(--s-1);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
}
.skill__wert { color: var(--ink-3); font-weight: 500; }
.skill__spur { height: 5px; background: var(--line); }
.skill__balken { height: 100%; background: var(--accent); }

@media (max-width: 860px) {
  .werdegang { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4) 0; }
  .werdegang__item { padding-right: var(--s-4); }
}
@media (max-width: 560px) {
  .werdegang { grid-template-columns: 1fr; }
  .werdegang__item { padding-right: 0; }
}

/* Zitat im Fliesstext (Marketingweisheiten im Blog) - dieselbe Schreibschrift
   wie das Hero-Zitat, damit beide als eine Familie erkennbar bleiben. Kleiner
   und mit Akzentlinie statt zentriert auf Foto, weil es hier Fliesstext
   begleitet statt eine ganze Sektion zu tragen. */
.quote {
  border-left: 3px solid var(--accent);
  padding-left: var(--s-4);
  margin: var(--s-3) 0;
  max-width: 640px;
}
.quote p {
  font-family: var(--font-script);
  font-size: clamp(1.7rem, 4vw, 2.75rem);
  font-weight: 400;
  line-height: 1.28;
  letter-spacing: 0;
  margin: 0;
  text-wrap: balance;
}
.quote figcaption { font-size: var(--step--1); color: var(--ink-3); margin-top: var(--s-2); }
.quote cite { font-style: normal; font-weight: 600; color: var(--ink); }

/* --- Kennzahlen --------------------------------------------------------- */
.figures { display: grid; gap: 0; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.figure { padding: var(--s-4) var(--s-4) var(--s-4) 0; border-top: 3px solid var(--ink); }
.figure + .figure { padding-left: var(--s-4); }
.figure__value {
  font-family: var(--font-display);
  font-size: var(--step-4);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  display: block;
  margin-bottom: var(--s-1);
}
.figure__label {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 600;
  margin-bottom: var(--s-2);
  display: block;
}
.figure__desc { font-size: var(--step--1); color: var(--ink-2); margin: 0; }
.section--dark .figure { border-top-color: var(--accent); }
.section--dark .figure__desc { color: #b9b9b9; }

/* --- Akkordeon ---------------------------------------------------------- */
.accordion { border-top: var(--rule) solid var(--line); }
.accordion__item { border-bottom: var(--rule) solid var(--line); }
.accordion__item summary {
  cursor: pointer;
  list-style: none;
  padding: var(--s-3) 0;
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}
.accordion__item summary::-webkit-details-marker { display: none; }
.accordion__item summary::after {
  content: "+";
  margin-left: auto;
  font-weight: 400;
  color: var(--ink-3);
  transition: transform var(--dur) var(--ease);
}
.accordion__item[open] summary::after { content: "–"; }
.accordion__item summary:hover { color: var(--ink); }
.accordion__num {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--accent-ink);
  background: var(--accent);
  padding: 0.15em 0.5em;
  flex: none;
}
.accordion__body { padding-bottom: var(--s-4); }
.accordion__body > :last-child { margin-bottom: 0; }

/* --- Kundenlogos -------------------------------------------------------- */
/* Feste Spaltenzahl statt auto-fill: das elastische Raster ließ die letzte
   Reihe anbrechen, und weil die Trennlinien über den Hintergrund entstehen,
   blieb dort ein grauer Block stehen. 4 Spalten teilen beide Stände glatt:
   12 Logos = 3 Reihen, 52 Logos = 13 Reihen. Kein Loch, egal welcher Zustand. */
.clients {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--rule);
  background: var(--line);
  border: var(--rule) solid var(--line);
}
.clients__more { margin-top: var(--s-5); }
.clients__item {
  background: var(--paper);
  display: grid;
  place-items: center;
  padding: var(--s-3);
  aspect-ratio: 5 / 2;   /* flache Zellen, dem Format von Wortmarken angemessen */
  /* Der Listen-Reset (li + li) schöbe jede Zelle außer der ersten um 8px nach
     unten — im Raster sichtbar als eine einzelne verrutschte Kachel. */
  margin: 0;
}
.clients__item img {
  max-height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.7;
  transition: filter var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.clients__item:hover img { filter: grayscale(0); opacity: 1; }

/* --- Arbeiten (Bento-Masonry-Grid mit Hover-Reveal) ---------------------
   Ersetzt seit 26.08.2026 das vorherige 12-Spalten-Editorial-Raster; vom
   Auftraggeber selbst als Entwurf in arbeitsproben/index-v2.html gebaut und
   auf dessen Wunsch zum einzigen Raster gemacht (Startseite + Übersicht). */
.work {
  display: grid;
  grid-auto-flow: dense;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: 300px;
  gap: var(--col-gap, clamp(1rem, 2vw, 2rem));
}
/* Volle Viewportbreite statt auf --container begrenzt (Wunsch des
   Auftraggebers, 26.08.2026) - klassischer Breakout-Trick: das Grid bleibt
   im HTML innerhalb von .container (der Text darüber/darunter bleibt lesbar
   schmal), bricht per Breite/Margin aber bis an den Bildschirmrand aus.
   .work--verwandt ("Weitere Arbeitsproben" am Seitenende) bleibt bewusst
   ausgenommen - dort passt die schmalere Spaltenbreite besser zum Fließtext
   darüber. */
.work:not(.work--verwandt) {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding-inline: var(--gutter, clamp(1.25rem, 4vw, 3.5rem));
  box-sizing: border-box;
}
.work__item { grid-column: span 1; grid-row: span 1; min-width: 0; min-height: 0; display: block; }
.work__item:nth-child(6n + 1) { grid-column: span 2; grid-row: span 2; }
.work__item:nth-child(6n + 2) { grid-column: span 2; grid-row: span 1; }
/* Hochkant-Kachel (1 Spalte breit, 2 Zeilen hoch) - auf Wunsch des
   Auftraggebers ergänzt (26.08.2026), passend zu Bildern, die ohnehin im
   Hochformat zugeschnitten sind. grid-auto-flow:dense (oben) füllt die
   dadurch entstehenden Lücken automatisch mit nachfolgenden Kacheln auf. */
.work__item:nth-child(6n + 4) { grid-column: span 1; grid-row: span 2; }
.work__link {
  display: block; position: relative; width: 100%; height: 100%;
  overflow: hidden; text-decoration: none !important;
  background: var(--paper-2, #1a1a1a);
}
/* .work__figure/.work__tags werden auch AUSSERHALB des Grids verwendet
   (Bildergalerie + Kategorie-Zeile in der Seitenleiste der Detailseiten,
   siehe bildraster() in rebuild_alle_arbeitsproben.py) - deshalb hier nur
   die Basiswerte, die grid-spezifische absolute Positionierung folgt weiter
   unten scoped auf ".work .work__figure". */
.work__figure { margin: 0 0 var(--s-2); overflow: hidden; background: var(--paper-2); }
.work__figure img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
.work__figure--contain img { object-fit: contain; }
.work__figure--natural img { aspect-ratio: auto; object-fit: contain; }
.work__figure--weiss,
.work__figure--weiss picture,
.work__figure--weiss img { background: #fff !important; }

.work .work__figure { margin: 0; position: absolute; inset: 0; overflow: clip; }
.work .work__figure picture { display: block; width: 100%; height: 100%; }
.work .work__figure img {
  width: 100%; height: 100%; aspect-ratio: unset; object-fit: cover; object-position: center top;
  transition: transform 0.6s cubic-bezier(0.2, 0, 0.2, 1); will-change: transform;
}
.work__link:hover .work__figure img,
.work__link:focus-visible .work__figure img { transform: scale(1.05); }

.work__caption {
  position: absolute; inset: auto 0 0 0; padding: var(--s-3);
  background: rgba(17, 17, 17, 0.54);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transform: translateY(101%); opacity: 0;
  transition: transform 0.38s cubic-bezier(0.2, 0, 0.2, 1), opacity 0.28s ease;
  pointer-events: none;
}
.work__link:hover .work__caption,
.work__link:focus-visible .work__caption { transform: translateY(0); opacity: 1; }
.work__caption::before {
  content: ""; display: block; width: 24px; height: 2px;
  background: var(--accent, #a6e22e); margin-bottom: var(--s-2);
  transition: width 0.4s cubic-bezier(0.2, 0, 0.2, 1);
}
.work__link:hover .work__caption::before,
.work__link:focus-visible .work__caption::before { width: 52px; }

/* Kategorie-Zeile — Klartext aus der Portfolio-Taxonomie des Bestands, keine
   erfundene Einordnung. Auch in der Seitenleiste der Detailseiten verwendet
   (dort die Basiswerte), im Grid dagegen die auffälligere Akzentfarbe. */
.work__tags {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 var(--s-1);
}
.work .work__tags {
  display: block; margin: 0 0 4px;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.09em;
  color: var(--accent, #a6e22e); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.work__title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin: 0 0 4px; font-family: var(--font-display);
  font-size: var(--step-0, 1rem); font-weight: 700; line-height: 1.2; color: #fff;
  transition: transform 0.3s var(--ease, ease);
}
.work__link:hover .work__title,
.work__link:focus-visible .work__title { transform: translateX(5px); }
.work__meta {
  display: block; margin: 0; font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.75); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.work__pfeil {
  position: absolute; bottom: var(--s-3); right: var(--s-3);
  display: grid; place-items: center; width: 36px; height: 36px;
  background: var(--accent, #a6e22e); color: #111;
  font-size: 1rem; line-height: 1;
  transition: background 0.35s ease, color 0.35s ease;
  z-index: 10;
}
.work__link:hover .work__pfeil,
.work__link:focus-visible .work__pfeil { background: #fff; color: #111; }

/* Arbeitsproben, deren Bild noch nicht eingepflegt ist: derselbe
   Platzhalter wie beim Porträtfoto (gestrichelter Rahmen, Schraffur,
   Hinweistext) — täuscht kein Bild vor, zeigt aber an, dass eines folgt. */
.work__figure--platzhalter {
  aspect-ratio: 16 / 10;
  border: var(--rule) dashed var(--ink-3);
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 10px, rgba(0, 0, 0, 0.028) 10px 20px);
  display: grid;
  place-items: center;
}
.work .work__figure--platzhalter { aspect-ratio: unset; border: none; background: var(--paper-2, #1e1e1e); }
/* Grosse Platzhalter-Variante fuer Detailseiten ohne aufloesbares Bild —
   breiteres Seitenverhaeltnis, damit die Flaeche wie ein Titelbild wirkt. */
.work__figure--gross { aspect-ratio: 21 / 9; margin: 0; }

@media (max-width: 1280px) { .work { grid-auto-rows: 270px; } }
@media (max-width: 960px) {
  .work { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: 260px; }
  .work__item,
  .work__item:nth-child(6n + 1),
  .work__item:nth-child(6n + 2),
  .work__item:nth-child(6n + 4) { grid-column: span 1; grid-row: span 1; }
  .work__item:first-child { grid-column: span 2; }
}
@media (max-width: 768px) {
  .work { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 260px; gap: var(--s-3); }
  .work__item,
  .work__item:first-child,
  .work__item:nth-child(6n + 1),
  .work__item:nth-child(6n + 2),
  .work__item:nth-child(6n + 4) { grid-column: span 1; grid-row: span 1; }
  .work__caption { transform: translateY(0); opacity: 1; }
  .work__caption::before { width: 52px; }
}
@media (max-width: 480px) {
  .work { grid-template-columns: 1fr; grid-auto-rows: 300px; gap: var(--s-3); }
}

/* Modifier für "Weitere Arbeitsproben" am Ende der Detailseiten: gleich
   große Karten in einer Reihe, keine hervorgehobene große Kachel wie im
   Haupt-Grid - vier gleichwertige Vorschläge statt eines redaktionellen
   Schwerpunkts. */
.work--verwandt { grid-auto-rows: 240px; }
.work--verwandt .work__item,
.work--verwandt .work__item:nth-child(6n + 1),
.work--verwandt .work__item:nth-child(6n + 2),
.work--verwandt .work__item:nth-child(6n + 4) { grid-column: span 1; grid-row: span 1; }

/* --- Teaser-Karten (ohne Boxen: nur Linie + Typo) ----------------------- */
.teasers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; }
.teaser { padding: var(--s-4) var(--s-4) var(--s-4) 0; border-top: 3px solid var(--ink); }
.teaser + .teaser { padding-left: var(--s-4); }
/* Senkrechte Linien links vom ersten und rechts vom letzten Feld
   (Wunsch vom 27.08.2026): Die drei Einstiege wirkten als Gruppe offen und
   liefen nach aussen aus. Die beiden Kanten fassen sie zusammen, ohne einen
   geschlossenen Rahmen zu ziehen - der waere im Editorial-Raster zu schwer. */
.teaser:first-child { border-left: 3px solid var(--ink); padding-left: var(--s-4); }
.teaser:last-child { border-right: 3px solid var(--ink); }
.teaser__title { font-size: var(--step-2); margin-bottom: var(--s-2); }
.teaser p { font-size: var(--step--1); color: var(--ink-2); margin-bottom: var(--s-3); }

/* --- Footer ------------------------------------------------------------- */
.site-footer { background: var(--ink); color: #c9c9c9; padding-block: var(--s-7) var(--s-4); }
.site-footer h2, .site-footer h3 { color: var(--paper); }
.site-footer a { color: var(--paper); text-decoration-color: var(--accent); }
.site-footer__brand { color: var(--paper); }
.site-footer__brand .brand__logo { width: min(240px, 70%); height: auto; margin-bottom: var(--s-3); }
.site-footer__cols { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: var(--col-gap); }
.footer-title {
  font-family: var(--font-display);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: #8f8f8f;
  margin-bottom: var(--s-3);
}
.footer-list { list-style: none; margin: 0; padding: 0; }
.footer-list li + li { margin-top: var(--s-2); }
.site-footer address { font-style: normal; line-height: 1.9; }
.footer-title--spaced { margin-top: var(--s-5); }
/* Profile nebeneinander — es sind vier kurze Wörter, keine zweite Navigation */
.footer-list--inline { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-3); }
.footer-list--inline li + li { margin-top: 0; }

.socket {
  margin-top: var(--s-6);
  padding-top: var(--s-3);
  border-top: var(--rule) solid #2b2b2b;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  align-items: center;
  font-size: var(--step--1);
  color: #8f8f8f;
}
.socket ul { display: flex; gap: var(--s-3); list-style: none; margin: 0 0 0 auto; padding: 0; }
.socket li { margin: 0; }

/* --- Cookie-Einwilligung -------------------------------------------------
   Flaeche statt Karte: Trennlinie oben wie beim Socket/Footer, keine
   Box-Schatten - dieselbe flache Sprache wie der Rest des Systems. */
.consent {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-overlay);
  background: var(--paper);
  border-top: 3px solid var(--ink);
  padding: var(--s-3) 0;
}
.consent[hidden] { display: none; }
.consent__card { display: grid; gap: var(--s-3); }
.consent__text { margin: 0; max-width: 70ch; font-size: var(--step--1); color: var(--ink-2); }
.consent__text a { color: var(--ink); }
.consent__einstellungen {
  display: grid;
  gap: var(--s-2);
  padding-top: var(--s-2);
  border-top: var(--rule) solid var(--line);
}
.consent__einstellungen[hidden] { display: none; }
.consent__zeile { display: flex; align-items: flex-start; gap: var(--s-2); font-size: var(--step--1); }
.consent__zeile input { margin-top: 0.3em; flex: none; }
.consent__aktionen { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.consent .btn { padding: var(--s-2) var(--s-3); font-size: var(--step--1); }

/* --- Porträt-Platzhalter ------------------------------------------------
   Steht bewusst als leere, beschriftete Fläche da und nicht als Fake-Bild:
   der Rahmen zeigt Format und Position, täuscht aber keinen Inhalt vor.
   Ersetzen durch ein <picture> mit demselben Seitenverhältnis.            */
.portrait-slot {
  aspect-ratio: 4 / 5;
  border: var(--rule) dashed var(--ink-3);
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 10px, rgba(0, 0, 0, 0.028) 10px 20px);
  display: grid;
  place-items: center;
}
.portrait-slot__hint {
  font-family: var(--font-display);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-3);
}

/* --- Porträt ------------------------------------------------------------
   Das quadratische Original wird innerhalb der vorgesehenen 4:5-Fläche
   beschnitten, nie verzerrt. Der Fokus bleibt auf Gesicht und Oberkörper. */
.portrait {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--paper-2);
}
.portrait img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 45% 50%;
}

/* --- Blogbeiträge -------------------------------------------------------- */
.posts {
  margin-top: var(--s-7);
  border-top: var(--rule) solid var(--line);
}
.post { border-bottom: var(--rule) solid var(--line); }
.post__link {
  display: grid;
  grid-template-columns: 5.5rem 12rem 1fr auto;
  align-items: baseline;
  gap: var(--s-2) var(--s-4);
  padding: var(--s-4) 0;
  text-decoration: none;
  color: inherit;
}
.post__link:hover { text-decoration: none; }
/* Vorschaubild-Platzhalter: derselbe gestrichelte Rahmen wie beim Porträt und
   bei den Arbeitsproben - die Originaldateien liegen dem Inhaber vor und
   werden im gemeinsamen Durchgang nachgereicht. */
.post__bild {
  grid-row: 1 / 3;
  align-self: start;
  aspect-ratio: 4 / 3;
  margin: 0;
  border: var(--rule) dashed var(--ink-3);
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 10px, rgba(0, 0, 0, 0.028) 10px 20px);
  display: grid;
  place-items: center;
}
.post__bild span {
  font-family: var(--font-display);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-align: center;
  line-height: 1.3;
  padding: 0 4px;
}
/* --- Elemente im Beitragstext ------------------------------------------
   Ergaenzt 29.08.2026, als die Altbeitraege ihr Bildmaterial bekommen haben.
   Das Schluesselbild steht ganz oben im Textbereich, also genau dort, wo es
   im WordPress-Original stand.                                          */
.beitrag__bild {
  margin: 0 0 var(--s-5);
  background: none;              /* .work__figure setzt sonst ein helles Grau
                                    hinter die dunklen Zitatmotive          */
}
.beitrag__bild img { width: 100%; height: auto; }

/* Bildschirmaufnahmen liefen frueher als animiertes GIF (1,2 MB fuer 106
   Frames). Als MP4 sind es 300 KB bei besserer Qualitaet. Selbst gehostet,
   also ohne Einwilligung ladbar - anders als ein YouTube-Embed.          */
.beitrag__video { margin: var(--s-4) 0; }
.beitrag__video video {
  width: 100%;
  height: auto;
  display: block;
  background: var(--paper-2);
}
.beitrag__video figcaption,
.beitrag__bild figcaption {
  font-size: var(--step--1);
  color: var(--ink-3);
  margin-top: var(--s-2);
  max-width: var(--measure);
}

/* Wechselrede (Interview mit dem CEO). Vorher ein einzelner zentrierter
   Absatz, in dem Sprecher und Antwort nur durch Leerzeilen getrennt waren -
   als Definitionsliste ist die Zuordnung auch fuer Screenreader eindeutig. */
.dialog { margin: var(--s-4) 0; max-width: var(--measure); }
.dialog dt {
  font-family: var(--font-display);
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: var(--s-3);
}
.dialog dt:first-child { margin-top: 0; }
.dialog dd { margin: var(--s-1) 0 0; padding-left: var(--s-3);
             border-left: var(--rule) solid var(--accent); }

.quelle { font-size: var(--step--1); color: var(--ink-3); }

.post__date {
  font-family: var(--font-display);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  color: var(--ink-3);
}
.post__title {
  font-size: var(--step-1);
  line-height: 1.25;
  margin: 0;
  text-wrap: balance;
}
.post__link:hover .post__title { text-decoration: underline; text-decoration-color: var(--accent); }
.post__excerpt {
  grid-column: 3;
  font-size: var(--step--1);
  color: var(--ink-2);
  margin: var(--s-1) 0 0;
  max-width: 62ch;
}
.post__more {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  white-space: nowrap;
  color: var(--ink-3);
  transition: color var(--dur) var(--ease);
}
.post__link:hover .post__more { color: var(--ink); }

/* --- Kennzahl beim Hochzählen -------------------------------------------
   Feste Ziffernbreite, damit die Zeile während der Animation nicht springt. */
.figure__num { font-variant-numeric: tabular-nums; }


/* ==========================================================================
   Creative Revision — Bewegung, Marke, Rhythmus
   ========================================================================== */

/* --- Scroll-Reveal -------------------------------------------------------
   Grundzustand ist sichtbar. Erst wenn das Skript läuft, bekommt <html> die
   Klasse js und die Elemente starten verborgen. Ohne JavaScript bleibt also
   alles lesbar, statt dauerhaft unsichtbar zu sein.                        */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
  transition-delay: var(--verzug, 0ms);
}
.js [data-reveal].ist-da { opacity: 1; transform: none; }

/* --- NA-Signet als wiederkehrendes Element ------------------------------- */
.signet { display: block; color: var(--accent); }
.signet svg { width: 100%; height: auto; display: block; }
/* Kapitelmarke am Sektionskopf */
.label__signet {
  width: 15px; height: 15px;
  flex: none;
  color: var(--accent);
  margin-right: var(--s-1);
}
.label__signet svg { width: 100%; height: auto; display: block; }

/* --- Kopfzeile: Zustand beim Scrollen ------------------------------------ */
.site-header { transition: box-shadow var(--dur) var(--ease); }
.site-header[data-gescrollt] {
  box-shadow: 0 1px 0 var(--line), 0 10px 30px -22px rgba(0, 0, 0, 0.5);
}
.site-header[data-gescrollt] .site-header__inner { min-height: 62px; }
.site-header__inner { transition: min-height var(--dur) var(--ease); }

/* Kontakt hebt sich als einziger Punkt vom Rest ab */
.nav__cta {
  border: 2px solid var(--ink);
  padding: 0.5em 1.1em;
  border-bottom-width: 2px;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.nav__cta:hover,
.nav__cta:focus-visible {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
/* Aktive Seite (Kontakt): vollflaechig statt nur der duennen Unterstreichung,
   die .nav__link[aria-current] sonst setzt - auf dem eigenen 2px-Rahmen des
   Buttons sah eine einzelne gruene Kante wie ein Darstellungsfehler aus. */
.nav__cta[aria-current="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* --- Kennzahlen: mehr Grün, mehr Gewicht --------------------------------- */
.figures { position: relative; }
.figure { position: relative; }
.figure__value { font-size: clamp(2.6rem, 5.4vw, 4.6rem); }
.section--dark .figure__value { color: var(--paper); }
/* grüner Strich unter der Zahl, wächst beim Einblenden mit */
.figure__value::after {
  content: "";
  display: block;
  height: 3px;
  width: var(--strich, 0%);
  background: var(--accent);
  margin-top: var(--s-2);
  transition: width 900ms var(--ease) 180ms;
}
.figure.ist-da .figure__value::after { --strich: 68%; }

/* Dezente Rasterstruktur im Hintergrund der dunklen Sektion */
.section--dark.section--raster { position: relative; overflow: clip; }
.section--dark.section--raster::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
  background-size: calc(100% / 6) 100%;
  pointer-events: none;
}
.section--raster > .container { position: relative; }

/* Hinweis zur Entstehung der Arbeiten — inhaltlich wichtig, deshalb
   typografisch aufgewertet statt kleingedruckt. */
.work__hinweis {
  border-left: 3px solid var(--accent);
  padding-left: var(--s-3);
  max-width: 62ch;
  margin-top: var(--s-6);
  font-size: var(--step-0);
  color: var(--ink-2);
}

/* --- Referenzkunden als laufende Logostrecke -----------------------------
   Zwei Reihen, gegenläufig und unterschiedlich schnell. Die Liste ist im
   Markup doppelt vorhanden, damit der Umlauf ohne Sprung schließt.         */
.marquee { overflow: clip; position: relative; }
.marquee + .marquee { margin-top: var(--s-3); }
.marquee__spur {
  display: flex;
  width: max-content;
  gap: var(--s-5);
  align-items: center;
  animation: marquee var(--tempo, 64s) linear infinite;
}
.marquee--rueck .marquee__spur { animation-direction: reverse; }
.marquee:hover .marquee__spur,
.marquee:focus-within .marquee__spur { animation-play-state: paused; }
@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
/* Logos laufen an den Rändern weich aus, statt hart abzuschneiden */
.marquee {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
}
.marquee__item {
  flex: none;
  margin: 0;
  display: grid;
  place-items: center;
  /* 120px Anzeigebreite bei 140px Quellbreite (auf Wunsch des Auftraggebers
     26.08.2026 von 96px vergrößert). Mehr geben die Dateien im Backup nicht
     her — die Originale gehören zu den 353 verlorenen Medien. Nah an der
     Quellbreite bleiben sie noch scharf; bei 140px (Quellgröße) wäre die
     Obergrenze erreicht, darüber hinaus würden sie sichtbar verpixeln. */
  width: 120px;
}
/* Die Quelldateien sind JPG mit weißem Grund. Auf einer grauen Fläche stünde um
   jedes Logo ein sichtbarer weißer Kasten. mix-blend-mode half nicht: opacity
   erzeugt einen eigenen Stapelkontext und isoliert die Mischung. Deshalb läuft
   die Strecke auf Weiß — dort ist schlicht nichts zu kaschieren. */
.marquee-band {
  background: var(--paper);
  border-block: var(--rule) solid var(--line);
  padding-block: var(--s-4);
  margin-top: var(--s-6);
}
/* Die Logostrecke ist das Letzte in der Referenzen-Sektion. Deren graue
   Grundflaeche lief darunter noch als Streifen weiter, bevor der schwarze
   Fuss begann - eine Farbe zu viel auf engem Raum (bemaengelt 27.08.2026).
   Ohne unteren Innenabstand stoesst das weisse Band direkt an den Fuss.
   Die untere Kante des Bands entfaellt dabei, sonst laege eine helle Linie
   auf Schwarz. */
#referenzen { padding-bottom: 0; }
#referenzen .marquee-band { border-bottom: 0; }
.marquee__item img {
  max-width: 100%;
  height: auto;
  filter: grayscale(1);
  opacity: 0.6;
  transition: filter var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.marquee__item:hover img { filter: grayscale(0); opacity: 1; }

/* --- Blogteaser: zurückhaltend, ohne betontes Datum ---------------------- */
.teaser-liste { display: grid; gap: var(--s-3); }
.teaser-post {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  padding-block: var(--s-2);
  border-bottom: var(--rule) solid var(--line);
  text-decoration: none;
  color: inherit;
}
.teaser-post:hover { text-decoration: none; }
.teaser-post__titel {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 550;
  line-height: 1.35;
  margin: 0;
}
.teaser-post:hover .teaser-post__titel {
  text-decoration: underline;
  text-decoration-color: var(--accent);
}
.teaser-post__pfeil { margin-left: auto; color: var(--ink-3); flex: none; }

/* --- Bewegung abschalten, wenn der Besucher das so eingestellt hat ------- */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .hero__media img { animation: none; transform: none; }
  .hero__signet { transform: none; }
  .marquee__spur { animation: none; }
  .figure__value::after { transition: none; --strich: 68%; }
}

/* Footer wird vierspaltig — Blog zieht dort ein */
.site-footer__cols { grid-template-columns: 1.3fr 1fr 0.8fr 1.1fr; }
.teaser-liste--dunkel .teaser-post { border-bottom-color: #2b2b2b; color: var(--paper); }
.teaser-liste--dunkel .teaser-post__pfeil { color: #8f8f8f; }
.teaser-liste--dunkel .teaser-post__titel { font-size: var(--step--1); }

/* ==========================================================================
   Hero nach dem ursprünglichen Entwurf — Bild, Zitat, drei Einstiege
   Überschreibt bewusst die vorherige zweispaltige Fassung; die alten Regeln
   stehen weiter oben und bleiben für die Marken- und Rollenbausteine gültig.
   ========================================================================== */
.hero { border-bottom: 0; overflow: clip; }

.hero__bild {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  min-height: clamp(420px, 68svh, 720px);
  overflow: clip;
  background: var(--ink);
  /* html { scrollbar-gutter: stable } (base.css) reserviert bewusst Platz für
     einen Rollbalken; dadurch bleibt <body> permanent schmäler als das echte
     Fenster. Nur hier, am randabfallenden Hero-Bild, wird das ausgeglichen -
     mit dem von main.js (Abschnitt 1a) gemessenen Wert, NICHT mit vw: vw
     würde auf einem Browser mit klassischem (nicht reserviertem) Rollbalken
     zu breit ausfallen und exakt die waagerechte Scrollleiste zurückbringen,
     die an anderer Stelle bewusst vermieden wird. --rollbalken-reserve ist
     dagegen eine echte Messung und kann die Fensterbreite nie überschreiten;
     .hero { overflow: clip } fängt den Übertrag zusätzlich ab. */
  margin-right: calc(-1 * var(--rollbalken-reserve, 0px));
}
.hero__bild picture { position: absolute; inset: 0; display: block; }
.hero__bild img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Bewegt sich langsamer als die Seite. Der Rahmen ist geclippt, deshalb
     reißt am Rand nichts auf. */
  transform: translate3d(0, calc(var(--p, 0) * 52px), 0) scale(1.12);
  will-change: transform;
  animation: hero-auf var(--dur-slow) var(--ease) both;
}
/* Videohintergrund im Hero (Testfassung vom 27.08.2026) ------------------
   Liegt als eigene Ebene ÜBER dem <picture>, aber unter dem Schleier und dem
   Zitat. Das Bild bleibt damit vollwertig bestehen: Es ist weiterhin das,
   was zuerst gezeichnet wird (und damit der LCP), und es bleibt stehen, wenn
   das Video nicht startet - bei reduzierter Bewegung, ohne JavaScript, bei
   gesperrter Autowiedergabe oder wenn die Datei nicht lädt. Deshalb wird das
   Video auch erst per JavaScript nachgeladen (main.js, Abschnitt 7a) und
   liegt nicht im Markup: 2,4 MB sollen den ersten Seitenaufbau nicht
   ausbremsen.
   Eingeblendet wird es erst, wenn wirklich Bilder laufen - sonst blitzte
   kurz ein schwarzes Rechteck auf, bevor das erste Vollbild da ist. */
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 700ms var(--ease);
  /* dieselbe Parallaxe und derselbe Anschnitt wie beim Bild, damit beim
     Überblenden nichts springt */
  transform: translate3d(0, calc(var(--p, 0) * 52px), 0) scale(1.12);
  will-change: transform, opacity;
}
.hero__video.laeuft { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .hero__video { display: none; }
}

/* Punktraster ueber dem Video (Wunsch vom 27.08.2026) --------------------
   Im Video passiert viel; darueber steht weisse Schrift. Das Raster nimmt
   dem Hintergrund Schaerfe und Detail, ohne ihn zuzudecken - man erkennt
   weiterhin, dass dort etwas passiert und was es grob ist.

   Aufbau bewusst als Umkehrung des Punktfelds weiter unten auf der Seite:
   dort schwarze Punkte auf frei, hier eine schwarze Flaeche mit frei
   gelassenen Punkten. Ein radial-gradient je Rasterzelle, gekachelt ueber
   background-size - kein Bild, keine zusaetzliche Anfrage.

   --hero-raster-deckung steuert, wie stark es deckt. 0.1 entspricht der
   Vorgabe (Schwarz bei 10 %); der Wert laesst sich hier an einer Stelle
   hochziehen, falls der Hintergrund noch ruhiger werden soll. */
.hero__raster {
  position: absolute;
  inset: 0;
  pointer-events: none;
  --hero-raster-deckung: 0.10;
  --hero-raster-weite: 7px;
  background-image: radial-gradient(
    circle at 50% 50%,
    transparent 0 1.6px,
    rgba(17, 17, 17, var(--hero-raster-deckung)) 1.7px);
  background-size: var(--hero-raster-weite) var(--hero-raster-weite);
}

/* Schreibmaschine: blinkender Akzent-Cursor. Eigenes Element statt ::after
   am Elternelement - main.js haengt es direkt hinter den gerade getippten
   Textknoten, damit es auch in Ueberschriften mit nachgestellten <span>
   an der richtigen Stelle sitzt (siehe Kommentar dort). */
.tipp-cursor {
  display: inline-block;
  width: 0.07em;
  height: 0.92em;
  /* Etwa eine Leerzeichenbreite Abstand zum letzten Buchstaben - direkt
     angeklebt wirkte der Strich wie ein Satzzeichen (Wunsch 27.08.2026). */
  margin-left: 0.26em;
  background: var(--accent);
  vertical-align: -0.1em;
  animation: tippBlink 0.8s step-end infinite;
}
@keyframes tippBlink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .tipp-cursor { display: none; } }

/* Schleier nur so dunkel wie nötig — das Motiv soll erkennbar bleiben,
   der Text darauf aber sicher lesbar sein. */
.hero__schleier {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(115% 85% at 50% 52%, rgba(17, 17, 17, 0.52), rgba(17, 17, 17, 0.26) 62%),
    linear-gradient(to bottom, rgba(17, 17, 17, 0.16), rgba(17, 17, 17, 0.34));
}

.hero__zitat {
  position: relative;
  z-index: 1;
  margin: 0 auto;
  padding: var(--s-5) var(--gutter);
  /* Absolut, nicht in ch: ch misst in der geerbten Fließtextschrift, nicht in
     der viel größeren Schreibschrift — daraus wurden 210px und ein Wort je Zeile. */
  max-width: min(92%, 940px);
  text-align: center;
  color: var(--paper);
  transform: translate3d(0, calc(var(--p, 0) * -16px), 0);
}
.hero__zitat .hero__signet {
  width: 48px;
  margin: 0 auto var(--s-4);
}
.hero__zitat blockquote { margin: 0; border: 0; padding: 0; }
.hero__zitat p {
  font-family: var(--font-script);
  font-size: clamp(2.1rem, 5.6vw, 4.4rem);
  line-height: 1.14;
  font-weight: 400;
  letter-spacing: 0;
  margin: 0;
  text-wrap: balance;
  text-shadow: 0 2px 26px rgba(0, 0, 0, 0.4);
}
/* Der Abstand ist bewusst gross: das Zitat soll optisch in der Mitte des
   Hero stehen, die Signatur deutlich darunter (Wunsch vom 27.08.2026).
   Vorher hing beides als ein Block zusammen und wirkte dadurch als Ganzes
   zentriert, das Zitat selbst aber zu hoch. */
.hero__zitat figcaption {
  margin-top: clamp(var(--s-3), 4.5svh, var(--s-5));
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: center;
}
/* Feine Linie über der Signatur — im Bestand stand hier ein 50px breiter
   weißer Trennstrich (av_hr custom_width='50px'). Seit 27.08.2026 sitzt das
   Signet mittig darin: Linienstueck, Signet, Linienstueck. Deshalb liegt die
   Linie jetzt nicht mehr im ::before der figcaption, sondern als zwei
   Haelften links und rechts des Signets. */
.hero__signatur {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: min(300px, 68%);
  margin-bottom: var(--s-2);
}
.hero__signatur::before,
.hero__signatur::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(255, 255, 255, 0.55);
}
/* Kleiner als das frühere Signet über dem Zitat: es ist hier ein ruhiges
   Beiwerk in der Linie, keine eigene Bildmarke. */
.hero__signatur .hero__signet {
  width: 26px;
  flex: none;
  margin: 0;
  transform: none;
}
.hero__zitat cite {
  font-style: normal;
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 600;
}
.hero__zitat figcaption span {
  font-size: var(--step--1);
  color: rgba(255, 255, 255, 0.72);
}

/* --- Die drei Einstiege ------------------------------------------------- */
.einstiege { border-bottom: var(--rule) solid var(--line); }
.einstiege__reihe {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.einstieg {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-3) var(--s-4) 0;
  text-decoration: none;
  color: inherit;
  border-top: 3px solid transparent;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.einstieg + .einstieg { padding-left: var(--s-4); }
/* Senkrechte Linien aussen: dieselbe Staerke und Farbe wie die Trennlinien
   ZWISCHEN den Feldern (border-right weiter unten), damit die Gruppe eine
   einheitliche Rasterung bekommt. Erster Versuch am 27.08.2026 waren 3px in
   --ink - viel zu schwer und im Editorial-Raster deplatziert.
   Bewusst an den Feldern selbst und nicht an der Reihe: so beginnen die
   senkrechten Linien exakt auf Hoehe des border-top, der beim Ueberfahren
   gruen wird - Waagerechte und Senkrechte schliessen damit buendig ab. */
.einstiege__reihe .einstieg:first-child {
  border-left: var(--rule) solid var(--line);
  padding-left: var(--s-4);
}
/* Rueckmeldung beim Ueberfahren (ausgebaut 27.08.2026, zuletzt ueberarbeitet
   29.08.2026: der Akzentstrich lag an der Oberkante der Kachel und ging dort
   gegen den Videohintergrund darueber unter. Er sitzt jetzt stattdessen
   direkt unter der jeweiligen Ueberschrift/dem Pfeil - siehe
   .einstieg__kopf::after weiter unten - wo er vor hellem Papier statt vor
   dem Video liegt und deutlich sichtbar bleibt.

   Zusaetzlich schiebt sich die Kachel beim Ueberfahren sichtbar in den
   Videohintergrund darueber hinein (Wunsch 29.08.2026, zuletzt praezisiert:
   -6px hoben die Box nur leicht an, sollte aber wirklich ins Bild hineinragen
   - jetzt -32px, gut zwei Drittel des oberen Innenabstands). Kein Schatten
   mehr dahinter: das Hineinragen selbst ist bereits das Highlight, ein
   Schatten war auf Wunsch wieder raus.

   Damit die Kachel beim Ueberlappen nicht transparent uebers dunkle Video
   ragt (der Text waere darauf unlesbar), bekommt sie hier dauerhaft einen
   eigenen deckenden Hintergrund - vorher war sie nur "weiss", weil die Seite
   darunter weiss ist; ohne eigenen background haette der Videohintergrund an
   der ueberlappenden Kante durchgeschienen.

   .einstiege sitzt in der DOM-Reihenfolge direkt NACH .hero und malt daher
   schon von Haus aus obendrauf; .hero hat zwar position:relative, aber ohne
   eigenen z-index keinen eigenen Stapelkontext, blockiert das Ueberlappen
   also nicht - der Effekt braucht keinen z-index, nur die Bewegung selbst.

   Bewusst weiterhin NICHT die ganze Flaeche gruen: --accent ist ein sehr
   helles Gruen, gruener Text auf Weiss erreicht nur rund 1,7:1 Kontrast und
   waere beim Ueberfahren schlechter lesbar als vorher. Die Ueberschrift
   bleibt deshalb dunkel; die Ziffer bekommt weiterhin ein gefuelltes
   Akzentfeld als zweites Signal. */
.einstieg {
  position: relative;
  background: var(--paper);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
/* Spezifitaet bewusst ".einstiege__reihe .einstieg:hover" und nicht nur
   ".einstieg:hover": jede Kachel traegt data-reveal fuer die Scroll-
   Einblendung, und deren Regel ".js [data-reveal].ist-da { transform: none }"
   (siehe weiter oben in dieser Datei) hat mit Klasse+Attribut+Klasse eine
   hoehere Spezifitaet als ein einfaches ".einstieg:hover" und gewann bisher
   IMMER, unabhaengig vom Hover-Zustand - deshalb blieb der Hub beim ersten
   Testen aus. Mit der zusaetzlichen Ahnen-Klasse zieht dieser Selektor mit
   der Reveal-Regel gleich; bei gleicher Spezifitaet gewinnt die spaeter
   stehende Regel - und das ist diese hier. */
.einstiege__reihe .einstieg:hover,
.einstiege__reihe .einstieg:focus-visible {
  text-decoration: none;
  transform: translateY(calc(var(--s-4) * -1));
}
.einstieg:hover .einstieg__nr,
.einstieg:focus-visible .einstieg__nr {
  background: var(--accent);
  color: var(--accent-ink);
}
.einstieg__nr {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink-3);
}
.einstieg__text {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.einstieg__pfeil {
  margin-left: auto;
  color: var(--ink-3);
  transition: transform var(--dur) var(--ease);
}
.einstieg:hover .einstieg__pfeil { transform: translateY(4px); color: var(--ink); }

/* --- Vorstellung: gestaffelte H1 ---------------------------------------- */
.section--knapp { padding-block: clamp(var(--s-6), 7vw, var(--s-8)); }
/* Absolut, nicht in ch: ch misst bei 1rem in der Displayschrift und ergab
   knapp 280px — die Überschrift brach dann auf fünf Zeilen um. */
.vorstellung { max-width: min(100%, 46rem); }
.vorstellung__name {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-3);
  margin-bottom: var(--s-2);
}
.vorstellung__titel {
  font-size: clamp(2.2rem, 5vw, 4.2rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}
/* Die Ortsangabe steht kleiner — gleicher Text, andere Gewichtung. */
.vorstellung__ort {
  display: block;
  font-size: 0.44em;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink-2);
  margin-top: var(--s-2);
}
.vorstellung .hero__roles { margin-bottom: 0; }

/* ==========================================================================
   Hero und Vorstellung — Aufbau 1:1 nach dem Bestand
   ========================================================================== */

.hero__mitte {
  position: relative;
  z-index: 1;
  max-width: min(92%, 980px);
  text-align: center;
  color: var(--paper);
  padding: var(--s-5) var(--gutter);
  transform: translate3d(0, calc(var(--p, 0) * -16px), 0);
}
.hero__mitte > .hero__signet { width: 42px; margin: 0 auto var(--s-4); }

/* Vorzeile über dem Zitat — im Bestand ein eigener Textblock, nur auf Desktop
   sichtbar. Sie ordnet ein, ohne dem Zitat die Bühne zu nehmen. */
.hero__vorzeile {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}

/* Das Zitat in „Dry Brush", selbst gehostet (@font-face in base.css).
   Pinselschriften laufen optisch kleiner und brauchen mehr Zeilenabstand als
   eine Grotesk — daher der größere Grad und die offenere Zeile. */
/* margin: 0 auto, nicht margin: 0 - .hero__zitat ist mit max-width schmaler
   als .hero__mitte (980px); ohne auto blieb es links buendig, waehrend das
   Signet (eigenes margin:auto) korrekt zentriert war - beides zusammen sah
   aus wie ein falsch platziertes Signet, obwohl nur das Zitat daneben lag. */
.hero__zitat { margin: 0 auto; }
.hero__zitat p {
  font-family: var(--font-script);
  /* Zusätzlich an die Fensterhöhe gekoppelt: nur nach der Breite bemessen
     wuchs das Zitat auf flachen Fenstern so weit, dass es die drei Einstiege
     unter die Falz drückte. */
  font-size: min(clamp(1.9rem, 4.6vw, 3.9rem), 8svh);
  font-weight: 400;
  line-height: 1.24;
  letter-spacing: 0;
  margin: 0;
  text-wrap: balance;
  text-shadow: 0 2px 26px rgba(0, 0, 0, 0.34);
}

/* --- Die drei Einstiege: Überschrift, Satz, Pfeil ------------------------ */
.einstiege__reihe { gap: 0; }
.einstieg {
  display: block;
  padding: var(--s-5) var(--s-4) var(--s-5) 0;
  border-top: 3px solid transparent;
  border-right: var(--rule) solid var(--line);
}
.einstieg + .einstieg { padding-left: var(--s-4); }
/* Das letzte Feld behaelt seine Trennlinie - sie ist zugleich die aeussere
   rechte Kante der Gruppe (Wunsch vom 27.08.2026). Vorher stand hier
   border-right:0, weil aussen keine Linie sein sollte. Da Innen- und
   Aussenlinie jetzt dieselbe Staerke haben, genuegt schlicht: stehen lassen. */
/* Der Akzentstrich (siehe Kommentar bei .einstieg weiter oben) sitzt hier,
   direkt unter Ueberschrift + Pfeil, statt an der Kachel-Oberkante - auf
   hellem Papier, nicht mehr vor dem Videohintergrund. Position:relative
   nur auf .einstieg__kopf, nicht auf der ganzen Kachel: der Strich soll
   genau diese Zeile unterstreichen, nicht ueber die volle Kachelbreite
   laufen. Gleiche Technik wie beim Hauptnavigations-Hover: rechte Kante von
   100% auf 0 - wirkt wie von links nach rechts eingeblendet. */
.einstieg__kopf { display: flex; align-items: baseline; gap: var(--s-2); position: relative; padding-bottom: var(--s-1); }
.einstieg__kopf::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0;
  height: 2px;
  background: var(--accent);
  transition: right var(--dur) var(--ease);
}
.einstieg:hover .einstieg__kopf::after,
.einstieg:focus-visible .einstieg__kopf::after { right: 0; }
/* inline-block statt block, damit das Akzentfeld beim Ueberfahren nur die
   Ziffer umschliesst und nicht die ganze Zeilenbreite. Der Zeilenumbruch
   bleibt trotzdem: .einstieg__kopf danach ist ein Block. */
.einstieg__nr {
  display: inline-block;
  margin-bottom: var(--s-2);
  padding: 0.25em 0.55em;
  line-height: 1;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.einstieg__satz {
  display: block;
  /* var(--s-1) statt --s-2: .einstieg__kopf traegt seit 29.08.2026 selbst
     ein padding-bottom von --s-1 (Platz fuer den neuen Akzentstrich
     darunter). Beide zusammen ergeben wieder --s-2 (16px) Gesamtabstand
     zwischen Kopfzeile und Beschreibungstext - genau wie vorher, nur auf
     zwei Eigenschaften verteilt statt auf eine. */
  margin-top: var(--s-1);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 34ch;
}
.einstieg__pfeil { margin-left: auto; }
.einstieg:hover .einstieg__pfeil { transform: translateX(5px); }

/* --- Vorstellung -------------------------------------------------------- */
.vorstellung__kopf { margin-bottom: var(--s-6); }
.vorstellung__titel {
  font-size: clamp(2.1rem, 4.6vw, 3.9rem);
  line-height: 1.03;
  letter-spacing: -0.035em;
  margin: 0;
  text-wrap: balance;
}
.vorstellung__ort {
  display: block;
  font-size: 0.42em;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--ink-2);
  margin-top: var(--s-2);
}
/* Der Name steht unter der Überschrift, zurückgenommen — so, wie es der
   Bestand vorsieht. */
.vorstellung__name {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 500;
  color: var(--ink-3);
  margin-top: var(--s-3);
}

/* Hero und Einstiege zusammen genau eine Fensterhöhe: das Bild nimmt, was
   nach den Einstiegen übrig bleibt. So steht der ganze Einstieg über der Falz,
   ohne dass irgendwo eine Höhe geraten werden müsste. */
.hero {
  display: flex;
  flex-direction: column;
  min-height: calc(100svh - var(--header-h, 76px));
}
.hero__bild { flex: 1 1 auto; min-height: clamp(280px, 34svh, 520px); }
.einstiege { flex: 0 0 auto; }
.einstieg { padding-block: var(--s-4); }

/* Der Einstieg muss auf jeder Fensterhöhe über die Falz passen. Gemessen war
   der Zitatblock mit 613px die Untergrenze und die Einstiegsreihe 253px hoch —
   zusammen 44px zu viel bei 900px Fensterhöhe und 220px zu viel bei 700px.
   Deshalb sind Innenabstände und Schriftgrad zusätzlich an svh gekoppelt. */
.hero__mitte { padding-block: clamp(var(--s-3), 4svh, var(--s-5)); }
.hero__mitte > .hero__signet { margin-bottom: clamp(var(--s-2), 2svh, var(--s-4)); }
.hero__zitat p { font-size: min(clamp(1.8rem, 4.2vw, 3.6rem), 7svh); }
/* Abstand seit 27.08.2026 groesser: die Signatur soll deutlich unter dem
   Zitat stehen, das Zitat selbst optisch mittig. Bleibt an svh gekoppelt,
   damit der Einstieg auf flachen Fenstern weiter ueber die Falz passt. */
.hero__zitat figcaption { margin-top: clamp(var(--s-3), 3.5svh, var(--s-4)); }
.hero__signatur { margin-bottom: clamp(var(--s-2), 2vh, var(--s-3)); }
.einstieg { padding-block: clamp(var(--s-3), 2.6svh, var(--s-4)); }
.einstieg__satz { line-height: 1.5; }

/* ==========================================================================
   Vorstellung — Marke, große Bezeichnung, Punktfeld im Hintergrund
   Überschreibt die vorherige Fassung: der Name steht jetzt oben neben dem
   Signet, die Berufsbezeichnung trägt als Blickfang.
   ========================================================================== */
.vorstellung { position: relative; overflow: clip; }
.punktfeld {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  z-index: 0;
}
.vorstellung > .container { position: relative; z-index: 1; }

/* Lesbarkeit ueber dem Punktfeld: Einleitung und Akkordeon bekommen eine
   ruhige Papierflaeche, die Punkte bleiben in den Raendern und hinter dem
   Portraet sichtbar. padding + gleich grosses negatives margin, damit der
   Text an derselben Stelle im Raster stehen bleibt wie ohne die Flaeche -
   nur die sichtbare Flaeche wird groesser, nicht die Rasterspalte. */
.vorstellung .col-8.stack {
  position: relative;
  z-index: 2;
  background: var(--paper);
  padding: var(--s-4) var(--s-3);
  margin: calc(var(--s-4) * -1) calc(var(--s-3) * -1);
}

/* Dieselbe Punktfeld-Bühne, allgemein nutzbar für weitere Sektionen
   (Arbeitsproben- und Blog-Übersicht) - .vorstellung trägt daneben noch
   eigene, dort nicht passende Regeln (max-width etc.), deshalb ein eigenes
   Modifier statt die Klasse dort zu erweitern. */
.section--punktfeld { position: relative; overflow: clip; }
.section--punktfeld > .container { position: relative; z-index: 1; }

.vorstellung__kopf {
  margin-bottom: clamp(var(--s-6), 7vw, var(--s-8));
  max-width: 18ch;
}
/* Signet und Name in einer Zeile — die Marke steht vor der Aussage. */
.vorstellung__marke {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-4);
}
.vorstellung__signet { width: 26px; flex: none; color: var(--accent); }
.vorstellung__name {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
  margin: 0;
}

/* Der Blickfang. Deutlich größer als zuvor. font-weight:500 kommt seit
   29.08.2026 schon aus der allgemeinen h1-Regel (base.css) und muesste
   hier nicht mehr wiederholt werden - bewusst trotzdem stehen gelassen,
   falls .vorstellung__titel je auf ein anderes Element als <h1> zeigen
   sollte, ohne dass es hier unbemerkt wieder auf 700 zurueckfaellt. */
.vorstellung__titel {
  font-size: clamp(2.4rem, 6vw, 5.2rem);
  font-weight: 500;
  line-height: 1.0;
  letter-spacing: -0.04em;
  margin: 0;
  text-wrap: balance;
}
.vorstellung__ort {
  display: block;
  font-size: 0.3em;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--ink-3);
  margin-top: var(--s-3);
}

/* Korrektur zweier Erblasten aus der vorigen Fassung:
   1. .vorstellung war dort ein Div INNERHALB der Sektion und trug max-width:46rem.
      Seit die Klasse an der <section> hängt, kappte diese Regel die ganze
      Sektion auf 736px — Raster und Container inbegriffen.
   2. max-width in ch misst in der geerbten Fließtextschrift, nicht in der
      83px großen Überschrift. Aus 18ch wurden 169px und sechs Zeilen. */
.section.vorstellung { max-width: none; }
.vorstellung__kopf { max-width: min(100%, 64rem); }

/* Untergrenze für die Ortsangabe: 0.3em der Überschrift ergibt auf 390px
   Breite nur noch 11,5px. Sie skaliert mit, fällt aber nie unter die
   Fließtextgröße — sie gehört zur H1 und muss lesbar bleiben. */
.vorstellung__ort { font-size: max(0.3em, var(--step-0)); }

/* ==========================================================================
   Formular — Kontaktseite
   Keine eigene Optik erfunden: dieselben Mittel wie im Rest des Systems
   (Haarlinie statt Schatten, radius 0, Akzent nur im Fokusring).
   ========================================================================== */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--col-gap);
}
.form-feld { margin-bottom: var(--s-4); }
.form-feld--voll { grid-column: 1 / -1; }
.form-feld label {
  display: block;
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.02em;
  margin-bottom: var(--s-1);
}
.form-feld input,
.form-feld textarea {
  width: 100%;
  padding: var(--s-2);
  border: var(--rule) solid var(--line);
  border-radius: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--step-0);
  transition: border-color var(--dur) var(--ease);
}
.form-feld input:hover,
.form-feld textarea:hover { border-color: var(--ink-3); }
.form-feld textarea { resize: vertical; min-height: 8rem; }
.form-hinweis {
  font-size: var(--step--1);
  color: var(--ink-3);
  margin-top: var(--s-2);
  max-width: var(--measure);
}
.form-feld--einwilligung {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  font-size: var(--step--1);
  color: var(--ink-2);
}
/* width: auto ist der eigentlich entscheidende Teil dieser Regel. Die
   allgemeine ".form-feld input { width: 100% }" weiter oben gilt auch fuer
   diese Checkbox; "flex: none" ueberschreibt zwar flex-basis, nicht aber
   width - die Checkbox beanspruchte dadurch unsichtbar 100% der Zeilenbreite
   (1208px) als Flex-Basis, verdraengte das Label auf 0px Breite, und dessen
   Inhalt (der Datenschutz-Link) ragte sichtbar 44px ueber den Formularrand
   hinaus. document.documentElement.scrollWidth zeigte das NICHT an: die
   Sicherung html,body{overflow-x:clip} in base.css verhindert zwar eine
   Scrollleiste, macht scrollWidth dafuer aber blind gegen genau diesen Fall.
   Gefunden ueber eine element-genaue getBoundingClientRect-Pruefung
   (rebuild_alle_ueberstaende.py, rebuild_link_diag.py). */
.form-feld--einwilligung input { width: auto; margin-top: 0.3em; flex: none; }
/* min-width: 0 zusaetzlich als Sicherheitsnetz: Flex-Kinder verweigern per
   Spec-Voreinstellung (min-width: auto) das Schrumpfen unter ihre
   intrinsische Inhaltsbreite - ohne das koennte ein langer Einwilligungstext
   denselben Fehler auf andere Weise wieder herstellen. */
.form-feld--einwilligung label { display: inline; font: inherit; margin: 0; min-width: 0; flex: 1 1 auto; }
.form-status {
  margin-top: var(--s-3);
  padding: var(--s-3);
  border-left: 3px solid var(--ink);
  font-size: var(--step--1);
}
.form-status--ok { border-left-color: var(--accent); }
.form-status--fehler { border-left-color: #b3261e; }
/* Honeypot gegen einfache Formular-Bots: fuer Menschen nicht auffindbar
   (kein Tab-Stop, aus dem Bild geschoben statt display:none - manche Bots
   ueberspringen display:none gezielt). */
.hp-feld { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
altcha-widget {
  margin-top: var(--s-3);
  margin-bottom: var(--s-3);
  display: block;
  --altcha-color-base: var(--paper);
  --altcha-color-base-content: var(--ink);
  --altcha-border-color: var(--ink-3);
  --altcha-checkbox-border-color: var(--ink-3);
  --altcha-color-primary: var(--accent);
  --altcha-color-primary-content: var(--accent-ink);
  --altcha-color-neutral: var(--paper-2);
  --altcha-color-neutral-content: var(--ink);
  --altcha-max-width: 100%;
}
@media (max-width: 560px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* --- Nach-oben-Button ----------------------------------------------------
   Fester Pfeil unten rechts, erscheint erst nach dem Herunterscrollen (JS
   setzt/entfernt [hidden], siehe main.js). Auf Wunsch des Auftraggebers
   (26.08.2026), analog zum Pfeil-Muster der Arbeiten-Kacheln (.work__pfeil):
   selbe Farbe/Kantigkeit, damit es wie ein Teil desselben Designsystems wirkt. */
.nach-oben {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-4);
  z-index: 40;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 0;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.nach-oben.ist-sichtbar { opacity: 1; transform: none; }
.nach-oben:hover, .nach-oben:focus-visible { background: var(--ink); color: var(--paper); }
.nach-oben[hidden] { display: none; }
@media (max-width: 560px) {
  .nach-oben { right: var(--s-3); bottom: var(--s-3); width: 42px; height: 42px; font-size: 1.15rem; }
}

/* --- Blog-Relaunch: „Coming Soon" als Abschluss der Blogübersicht --------
   Nur auf blog/index.html im Einsatz. Bewusst als dunkle Sektion gesetzt,
   damit der Abschnitt sich klar vom Fließtext darüber absetzt und wie ein
   gewollter Neustart wirkt — nicht wie eine kaputte, leere Seite. Nutzt
   ausschließlich die vorhandenen Design-Tokens (kein neuer Farbwert). */
/* Weisser Trenner zum Footer: beide Flaechen sind nahezu schwarz
   (Sektion #111, Footer var(--ink)) und liefen sonst optisch ineinander.
   3px entspricht der Strichstaerke, die im Designsystem ohnehin fuer
   Akzentlinien gilt (Kennzahlen, Link-Unterstreichung) — dadurch wirkt der
   Abschluss gesetzt und nicht wie eine zufaellige Luecke. */
.blog-relaunch { overflow: clip; border-bottom: 3px solid var(--paper); }
.blog-relaunch__kicker {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: #9a9a9a;
  margin: 0 0 var(--s-4);
}
/* Kleiner Akzentpunkt, der ruhig pulsiert — signalisiert „hier passiert
   gerade etwas", ohne die Seite unruhig zu machen. */
.blog-relaunch__punkt {
  width: 10px;
  height: 10px;
  flex: none;
  background: var(--accent);
  animation: blogPuls 2.6s var(--ease) infinite;
}
@keyframes blogPuls {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.28; }
}
.blog-relaunch__titel {
  font-family: var(--font-display);
  font-size: var(--step-4);
  font-weight: 700;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--paper);
  margin: 0 0 var(--s-3);
  max-width: 18ch;
}
.blog-relaunch__claim {
  font-size: var(--step-1);
  line-height: 1.45;
  color: #c9c9c9;
  max-width: 46ch;
  margin: 0 0 var(--s-6);
}
.blog-relaunch__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  list-style: none;
  margin: 0 0 var(--s-6);
  padding: 0;
}
.blog-relaunch__tag {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: #d5d5d5;
  border: var(--rule) solid #3a3a3a;
  padding: 0.6em 1.1em;
  /* margin:0 ist Pflicht, nicht Kosmetik: der globale Listen-Reset
     (base.css „li + li { margin-top: var(--s-1) }") gibt sonst jeder Kachel
     ausser der ersten 8px Aussenabstand oben. Im Flexbox-Streckmodus wird die
     erste Kachel dadurch 8px hoeher als alle anderen — genau der Effekt, der
     am 27.08.2026 an der SEO-Kachel auffiel. Gleiche Falle wie beim
     Leistungsraster weiter oben in dieser Datei. */
  margin: 0;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.blog-relaunch__tag:hover {
  border-color: var(--accent);
  color: var(--accent);
}
/* Trennlinie + „Coming Soon": zweite Stufe der Hierarchie, deutlich vom
   Titel abgesetzt. Der Akzentstrich wächst beim Einblenden mit (gleiche
   Mechanik wie bei den Kennzahlen auf der Startseite). */
.blog-relaunch__soon {
  border-top: var(--rule) solid #333;
  padding-top: var(--s-5);
}
.blog-relaunch__soon-titel {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--paper);
  margin: 0 0 var(--s-2);
}
.blog-relaunch__soon-titel::after {
  content: "";
  display: block;
  height: 3px;
  width: var(--strich, 0%);
  max-width: 220px;
  background: var(--accent);
  margin-top: var(--s-3);
  transition: width 900ms var(--ease) 180ms;
}
.blog-relaunch__soon.ist-da .blog-relaunch__soon-titel::after { --strich: 100%; }
/* Ohne JavaScript (kein [data-reveal]-Handling) steht der Strich sofort. */
html:not(.js) .blog-relaunch__soon-titel::after { --strich: 100%; }
.blog-relaunch__text {
  font-size: var(--step-0);
  line-height: var(--leading-body);
  color: #c9c9c9;
  max-width: var(--measure);
  margin: var(--s-4) 0 0;
}
.blog-relaunch__text + .blog-relaunch__text { margin-top: var(--s-3); }

@media (max-width: 860px) {
  .blog-relaunch__titel { max-width: none; }
  .blog-relaunch__tag { padding: 0.5em 0.9em; }
}
@media (prefers-reduced-motion: reduce) {
  .blog-relaunch__punkt { animation: none; }
  .blog-relaunch__soon-titel::after { transition: none; --strich: 100%; }
}

/* ==========================================================================
   Blog-Uebersicht im Masonry-Raster (Vorschauseite /blog-relaunch/)
   --------------------------------------------------------------------------
   Aufbau nach der Referenz "Blog masonry - background overlap" (The7).
   Dort gemessen: Bild ueber die volle Kachelbreite, darunter eine weisse
   Textkarte mit 70 % Breite, die 100 px nach oben ins Bild gezogen ist.
   Genau dieser Versatz ist der Kniff - er verzahnt Bild und Text, statt sie
   nur untereinander zu stapeln.

   Uebernommen ist das Prinzip, nicht die Optik: keine runden Ecken, kein
   Schlagschatten, stattdessen die Akzentlinie und die Versalien-Meta des
   bestehenden Entwurfs.

   Das Raster selbst ist ein normales CSS-Grid. Die Masonry-Verzahnung setzt
   js/masonry.js, indem es je Kachel grid-row-end: span N rechnet. Ohne
   JavaScript bleibt ein sauberes, gleichmaessiges Raster stehen - nur eben
   ohne ineinandergreifende Reihen. Das ist der Grund fuer align-items:start.
   ========================================================================== */
.bmasonry {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(310px, 100%), 1fr));
  /* Zeilenrinne bewusst 0: Bei grid-auto-rows durchquert eine Kachel, die
     ueber N Zeilen spannt, auch N-1 Rinnen. Eine Zeilenrinne von 64px wuerde
     die Rasterweite damit faktisch von 4px auf 68px vergroebern - die
     Kachelhoehen koennten dann nur noch in 68px-Spruengen stehen und es
     entstuenden Luecken von mehreren hundert Pixeln. Der senkrechte Abstand
     kommt deshalb aus dem padding-bottom der Kachel. */
  column-gap: var(--s-5);
  row-gap: 0;
  align-items: start;
}

/* Erzeugt die senkrechte Rinne und zaehlt zur gemessenen Kachelhoehe. */
.bkachel { margin: 0; padding-bottom: var(--s-6); }

.bkachel__link {
  display: block;
  text-decoration: none;
  color: inherit;
  /* Die Textkarte ragt ins Bild. Ohne eigenen Stapelkontext liegt sie
     trotzdem korrekt oben, weil sie im Quelltext spaeter kommt.          */
  position: relative;
}
.bkachel__link:hover { text-decoration: none; }

.bkachel__bild {
  margin: 0;
  overflow: hidden;
  background: var(--paper-2);
}
.bkachel__bild img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform 600ms var(--ease);
}
.bkachel__link:hover .bkachel__bild img,
.bkachel__link:focus-visible .bkachel__bild img { transform: scale(1.04); }

/* Platzhalter, falls einem Beitrag einmal kein Motiv vorliegt. */
.bkachel__bild--leer {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  border: var(--rule) dashed var(--ink-3);
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 10px, rgba(0, 0, 0, 0.028) 10px 20px);
}
.bkachel__bild--leer span {
  font-family: var(--font-display);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Der eigentliche Overlap. Der Versatz waechst mit der Breite mit, damit die
   Karte auf schmalen Bildschirmen nicht mehr Bild verdeckt als sie darf.   */
.bkachel__inhalt {
  position: relative;
  z-index: 2;
  width: 84%;
  margin: calc(var(--versatz) * -1) auto 0;
  --versatz: clamp(2rem, 5.5vw, 4.5rem);
  background: var(--paper);
  padding: var(--s-4) var(--s-4) var(--s-3);
  border-top: 3px solid transparent;
  transition: border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.bkachel__link:hover .bkachel__inhalt,
.bkachel__link:focus-visible .bkachel__inhalt {
  border-top-color: var(--accent);
  transform: translateY(calc(var(--s-2) * -1));
}

.bkachel__meta {
  font-family: var(--font-display);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 var(--s-2);
}

.bkachel__titel {
  font-size: var(--step-1);
  font-weight: 700;
  line-height: var(--leading-tight);
  margin: 0 0 var(--s-2);
  text-wrap: balance;
}

.bkachel__text {
  font-size: var(--step--1);
  color: var(--ink-2);
  margin: 0 0 var(--s-3);
  max-width: none;
}

.bkachel__mehr {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.04em;
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
}
.bkachel__pfeil { transition: transform var(--dur) var(--ease); }
.bkachel__link:hover .bkachel__pfeil,
.bkachel__link:focus-visible .bkachel__pfeil { transform: translateX(0.3em); }

/* Auf schmalen Bildschirmen steht ohnehin nur eine Spalte - dort darf die
   Karte etwas breiter werden, sonst wirkt der Text eingezwaengt. */
@media (max-width: 700px) {
  .bkachel { padding-bottom: var(--s-5); }
  .bkachel__inhalt { width: 90%; }
}

@media (prefers-reduced-motion: reduce) {
  .bkachel__bild img,
  .bkachel__inhalt,
  .bkachel__pfeil { transition: none; }
  .bkachel__link:hover .bkachel__bild img { transform: none; }
  .bkachel__link:hover .bkachel__inhalt { transform: none; }
}
