/* ══════════════════════════════════════════════════════════════════════════
   So arbeitet das acessio-System — ein durchgehendes Beispiel

   Was hier bewusst NICHT passiert: kein Sticky, keine Texte, die an derselben
   Stelle ausgetauscht werden, keine Zwischenüberschriften, keine Cards. Die
   Sektion ist so lang wie ihr Text und keinen Bildschirm länger.

   Die Absätze erscheinen beim Eintritt gestaffelt — 16 px Weg, 120 ms
   Versatz — und bleiben danach dauerhaft stehen. Getrennt werden die
   Gedanken durch Abstand, nicht durch Beschriftung.
   ══════════════════════════════════════════════════════════════════════════ */

.bsp__kopf {
  max-width: 800px;
  margin: 0 auto;
  text-align: center;
}
.bsp__kopf h2 { margin-top: 22px; }

/* Hält zusammengesetzte Eigennamen in einer Zeile. */
.nowrap { white-space: nowrap; }

/* ── Vier Szenen statt vier Absätzen ──────────────────────────────────────
   Vorher standen hier rund 230 Wörter in vier Blöcken. Jetzt trägt jede
   Szene eine Zeichnung, einen Satz und einen Nachsatz — zusammen rund 60
   Wörter. Was die Absätze erklärt haben, zeigt jetzt das Bild.

   Zwei Spalten am Schreibtisch, eine am Telefon. Vier nebeneinander wären
   bei 1200 px je 270 px breit; dort passt keine Zeichnung mehr hin, die man
   noch lesen kann. */
.bsp__vorlauf {
  max-width: 46ch;
  margin: clamp(18px, 2.4vh, 28px) auto 0;
  text-align: center;
  font-size: clamp(15px, 1.2vw, 17px);
  color: var(--muted);
}

.bsp__szenen {
  /* 1020 war 138 px je Seite schmaler als die Satzkante der übrigen
     Sektionen (72…1368 bei 1440 px). 1140 halbiert den Sprung, ohne die
     Karten auf 636 px zu blähen — bei zwei Spalten bleiben 558 px. */
  max-width: 1140px;
  margin: clamp(38px, 5vh, 64px) auto 0;
  display: grid;
  gap: clamp(16px, 1.8vw, 24px);
}
@media (min-width: 760px) {
  .bsp__szenen { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── Die Karte ────────────────────────────────────────────────────────────
   Im Ruhezustand nur eine Linie auf dem Seitengrund — keine gefüllte Kachel.
   Die Fläche kommt erst beim Zeigen dazu. So bleibt die Sektion ruhig und
   die Karten stapeln sich optisch nicht vor die Zeichnungen.

   Die Karten sind bewusst gleich gebaut: sie sind vier gleichrangige
   Aussagen, keine Rangfolge. Die Hierarchie steckt innerhalb der Karte —
   Zeichnung, Serifensatz, Fließtext.
   ───────────────────────────────────────────────────────────────────────── */
.bsp__szene {
  display: grid;
  gap: 14px;
  align-content: start;
  padding: clamp(22px, 2.3vw, 32px);
  border: 1px solid var(--line);
  border-radius: 18px;
  background: transparent;
  box-shadow: 0 0 0 0 rgba(25, 25, 28, 0);
}

/* Nur wo es einen Zeiger gibt. Auf dem Telefon bliebe der Zustand sonst nach
   der Berührung kleben. */
@media (hover: hover) {
  .bsp__szene:hover {
    border-color: color-mix(in oklab, var(--ergebnis) 34%, var(--line));
    background: var(--flaeche);
    box-shadow: 0 14px 34px -22px rgba(25, 25, 28, 0.42);
  }
  .bsp__szene:hover .bsp__bild { transform: translateY(-3px); }
}

.bsp__bild { transition: transform var(--dur-fast) var(--ease); }

/* Die Zeichnung steht ohne eigene Fläche direkt auf dem Seitengrund. Die
   frühere cremefarbene Kachel war ein Kasten um etwas, das ohnehin nur aus
   Linien besteht — sie hat die vier Felder in Container verwandelt, statt sie
   in die Seite zu setzen. */
.bsp__bild {
  display: block;
  width: 100%;
  height: auto;
  max-width: 300px;
  font-family: inherit;
  overflow: visible;
}

/* Derselbe Strich wie im Gehirn: dünn, runde Enden, keine Flächen. */
.bsp__bild .bsp__k, .bsp__bild .bsp__d,
.bsp__bild .bsp__g, .bsp__bild .bsp__gk, .bsp__bild .bsp__gl {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.bsp__bild .bsp__k  { stroke: var(--ink-2); stroke-width: 2; }
.bsp__bild .bsp__d  { stroke: var(--line-2); stroke-width: 2; }
.bsp__bild .bsp__g  { stroke: var(--ergebnis); stroke-width: 2; }
.bsp__bild .bsp__gk { stroke: var(--ergebnis); stroke-width: 2.4; }
.bsp__bild .bsp__gl { stroke: var(--ergebnis); stroke-width: 2; opacity: 0.75; }
.bsp__bild .bsp__gp { fill: var(--ergebnis); stroke: none; }

/* Beschriftung in der Zeichnung. Sie trägt keine Aussage, die nicht auch im
   Text darunter steht — die Zeichnungen sind deshalb aria-hidden. */
.bsp__bild .bsp__t  { fill: var(--ink-2); font-size: 12px; font-weight: 500; }
.bsp__bild .bsp__td { fill: var(--muted);  font-size: 11.5px; font-weight: 400; }
.bsp__bild .bsp__tg { fill: var(--ergebnis); font-size: 12px; font-weight: 600; }

/* ── Vier eigene Mikroszenen ──────────────────────────────────────────────
   Jede Szene läuft beim ersten Sichtkontakt und danach in ihrem eigenen Takt
   erneut — ausgelöst über `is-lauf`, das heim.js setzt, entfernt und wieder
   setzt. Bewusst NICHT über `is-an`: das trägt die Texteinblendung der
   ganzen Kachel, ein Neustart würde die Kachel jedes Mal wieder ausblenden.

   Zwischen zwei Durchläufen hält `both` den Endzustand fest — Haken bleiben
   gezeichnet, Balken bleiben voll. Es blinkt also nichts, die Szene spielt
   nur ihren Aufbau noch einmal.

   Die Ausgangszustände stehen absichtlich NUR in diesem Media-Block. Wer
   keine Bewegung möchte, sieht die Zeichnung sofort in ihrem Endzustand;
   ohne diese Klammer bliebe ein unsichtbar gesetztes Element dauerhaft
   unsichtbar.
   ───────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  /* Sämtliche Ausgangszustände hängen an `bsp--takt`. Diese Klasse setzt der
     Taktgeber in heim.js auf die Sektion, unmittelbar bevor er die Szenen zu
     beobachten beginnt.

     Das ist die Sicherung gegen einen halben Stand: fehlt das Skript, ist es
     veraltet im Zwischenspeicher oder bricht es vorher ab, dann kommt die
     Klasse nie an — und ohne sie gibt es keinen Ausgangszustand, der etwas
     versteckt. Die Zeichnungen stehen dann sofort fertig da. Vorher hätte
     derselbe Fall die ganze Sektion leer gelassen. */
  .bsp--takt .bsp__szene .an-ein { opacity: 0; }
  .bsp__szene.is-lauf .an-ein {
    animation: bspEin 460ms var(--ease) var(--t, 0ms) both;
  }

  /* Nur wenn der Takt wirklich läuft, ist „Neu" der Ausgangszustand. Sonst
     gilt der sichere Standard weiter unten und die Kachel bleibt weg. */
  .bsp--takt .bsp__szene .an-aus { opacity: 1; }
  .bsp__szene.is-lauf .an-aus {
    animation: bspAus 300ms var(--ease) var(--t, 0ms) both;
  }

  /* Der Haken zeichnet sich, statt zu erscheinen: pathLength="1" macht die
     Länge unabhängig von der tatsächlichen Geometrie. */
  .bsp--takt .bsp__szene .an-haken { stroke-dasharray: 1; stroke-dashoffset: 1; }
  .bsp__szene.is-lauf .an-haken {
    animation: bspStrich 420ms var(--ease) var(--t, 0ms) both;
  }

  /* Balken wachsen aus der linken Kante. transform-box: fill-box bezieht den
     Ursprung auf das Element selbst, nicht auf den ganzen viewBox-Rahmen. */
  .bsp--takt .bsp__szene .an-balken {
    transform-box: fill-box;
    transform-origin: left center;
    transform: scaleX(0.045);
  }
  .bsp__szene.is-lauf .an-balken {
    animation: bspBalken 640ms var(--ease) var(--t, 0ms) both;
  }

  /* Die losen Karten liegen schief und richten sich einmal aus. */
  .bsp--takt .bsp__szene .an-richt {
    transform-box: fill-box;
    transform-origin: center;
    transform: rotate(var(--r, 0deg));
  }
  .bsp__szene.is-lauf .an-richt {
    animation: bspRichten 720ms var(--ease) var(--t, 0ms) both;
  }
}

/* Vom Statuswechsel bleibt im Ruhefall nur der Endzustand: das erledigte
   Feld. Sonst lägen „Neu" und „Bearbeitet" übereinander. Das gilt ohne
   Bewegungswunsch genauso wie bei fehlendem Skript — deshalb steht es hier
   als Standard und nicht in einer Medienabfrage. */
.bsp__szene .an-aus { opacity: 0; }

@keyframes bspEin     { from { opacity: 0; } to { opacity: 1; } }
@keyframes bspAus     { from { opacity: 1; } to { opacity: 0; } }
@keyframes bspStrich  { to { stroke-dashoffset: 0; } }
@keyframes bspBalken  { to { transform: scaleX(1); } }
@keyframes bspRichten { to { transform: rotate(0deg); } }

.bsp__satz {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(20px, 1.9vw, 26px);
  line-height: 1.18;
  letter-spacing: -0.02em;
  color: var(--ink);
}
/* Ein einziger hervorgehobener Teil je Überschrift: das, was am Ende
   herauskommt. Kursiv wäre hier zu viel — die Serifenschrift trägt die
   Betonung schon, die Farbe reicht. */
.bsp__satz em {
  font-style: normal;
  color: var(--ergebnis);
}
.bsp__nach {
  max-width: 42ch;
  font-size: clamp(15px, 1.15vw, 16.5px);
  line-height: 1.55;
  color: var(--ink-2);
}

.bsp__text--schluss {
  max-width: clamp(460px, 45vw, 620px);
  margin: clamp(44px, 5.5vh, 72px) auto 0;
}

.bsp__schluss {
  margin-top: 0;
  padding-top: clamp(26px, 3.6vh, 42px);
  border-top: 1px solid var(--line);
  font-family: var(--serif);
  font-style: normal;
  font-size: clamp(22px, 2.3vw, 30px) !important;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ink) !important;
}
/* Der zweite Satz ist die Auflösung des Beispiels — und Grün heißt auf
   dieser Seite genau das: es kommt an. Deshalb hier, und nur hier. */
.bsp__schluss em { font-style: italic; color: var(--ergebnis); }

/* Erscheinen. Der Versatz steckt in --v und wird von heim.js gesetzt.

   Die drei Kartenwerte stehen mit in dieser Liste, obwohl sie thematisch zur
   Karte gehören: `transition` ist eine einzige Eigenschaft, und diese Regel
   steht weiter unten als `.bsp__szene`. Zwei getrennte Angaben hieße, dass
   die spätere die frühere vollständig ersetzt — der Hover würde springen.
   Für Kopf, Vorlauf und Schlusssatz laufen die drei Einträge ins Leere; die
   haben weder Rand noch Fläche. */
[data-bsp-t] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 620ms var(--ease) var(--v, 0ms),
              transform 620ms var(--ease) var(--v, 0ms),
              border-color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
[data-bsp-t].is-an { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-bsp-t] { opacity: 1; transform: none; transition: none; }
}

/* ═══ Projekte ════════════════════════════════════════════════════════════
   Zwei Projekte, gleiches Bildformat, Titel unter dem Bild. Kein Text auf
   dem Screenshot — der Screenshot ist die Aussage. Die ganze Fläche ist ein
   Link; auf dem Telefon steht der Titel ohne Hover zur Verfügung.
   ═════════════════════════════════════════════════════════════════════════ */

/* Die Projektsektion darf breiter laufen als der Textteil der Seite: vier
   Kacheln nebeneinander werden im 1200er Satzspiegel und mit 72 px Rand sonst
   nur 305 px breit. Mit eigenem, schmalerem Rand sind es 323 px, und im
   quadratischen Format wächst die Fläche um die Hälfte. */
/* Die Projektsektion lief mit eigener Breite (1560 px) und eigenem Rand aus
   der Satzkante der Seite heraus — gemessen bei 1440 px Fenster: 43…1397
   statt 72…1368, also 29 px Überstand auf jeder Seite. Sichtbar wurde das
   an der Kopfzeile, die genau auf 72 und 1368 sitzt.

   Jetzt gilt auch hier die normale .wrap-Kante. Die Kacheln werden dadurch
   etwas schmaler, aber sie stehen in derselben Spalte wie alles andere. */
.pj.wrap {
  max-width: var(--max);
  padding-inline: var(--gutter);
}
.pj__liste {
  display: grid;
  gap: clamp(16px, 1.8vw, 26px);
  margin-top: clamp(34px, 4vw, 58px);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 900px) {
  .pj__liste { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.pj__p {
  display: grid;
  gap: 14px;
  align-content: start;
  color: inherit;
  text-decoration: none;
}
/* Grüner Rand um jede Projektkarte. Der Wert steht ausgeschrieben, weil
   --ergebnis in heim.css definiert ist und die nur die Startseite lädt;
   die Referenzenseite bekäme sonst gar keinen Rand. Dünn und gedeckt —
   ein voll gesättigtes Grün würde mit den Screenshots konkurrieren. */
.pj__rahmen {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--canvas-2);
  /* Quadratisch, und genau so aufgenommen: ein 4:3-Bild würde `cover` hier
     seitlich um ein Viertel beschneiden. */
  aspect-ratio: 1 / 1;
}
.pj__rahmen img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0;
  transform: scale(1);
  transition: transform 800ms var(--ease);
}
.pj__p:hover .pj__rahmen img,
.pj__p:focus-visible .pj__rahmen img { transform: scale(1.04); }

/* Vierte Kachel: kein Bild, sondern der Weg zu allen Projekten. Schwarz,
   damit sie sich als das zu erkennen gibt, was sie ist — kein Projekt. */
.pj__rahmen--alle {
  display: grid;
  place-content: center;
  border-color: var(--ink);
  background: var(--ink);
  color: var(--canvas);
  text-align: center;
}
.pj__alle-wort {
  font-family: var(--serif);
  font-size: clamp(19px, 1.7vw, 25px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  max-width: 12ch;
}
/* Der Ring sitzt am Link selbst, nicht am Bildrahmen darin. Am Kind wäre er
   zwar sichtbar, aber ein Prüfwerkzeug — und mancher Screenreader-Modus —
   sucht ihn am fokussierten Element. */
.pj__p:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
  border-radius: 22px;
}

/* Der Name füllt die Breite der Kachel. Ohne Pfeil: die ganze Fläche ist der
   Link, das Zeichen wiederholte nur, was die Kachel ohnehin sagt. */
.pj__titel {
  display: block;
  /* Der Name steht mittig unter der Kachel, nicht linksbündig — sonst zieht
     er bei kurzen Namen optisch aus der Karte heraus. */
  text-align: center;
}
.pj__titel h3 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(19px, 1.7vw, 25px);
  line-height: 1.16;
  letter-spacing: -0.02em;
}
.pj__pfeil, .pj__alle-pfeil { display: none; }
.pj__p:hover .pj__pfeil,
.pj__p:focus-visible .pj__pfeil { transform: translateX(4px); color: var(--ink); }

.pj__mehr { margin-top: clamp(26px, 3vw, 40px); font-size: 14.5px; text-align: center; }
.pj__mehr a { color: var(--muted); text-decoration: none; }
.pj__mehr a:hover, .pj__mehr a:focus-visible { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .pj__rahmen img { transition: none; }
  .pj__p:hover .pj__rahmen img { transform: none; }
}

/* ═══ Persönlich in Stuttgart ══════════════════════════════════════
   Erst das Wort, dann der Ort. Links der Ansprechpartner, rechts das Office.

   Das Portrait läuft im Seitenverhältnis der Vorlage (1000 × 1500 = 2:3).
   Dadurch ist es vollständig zu sehen — jedes andere Verhältnis würde bei
   `object-fit: cover` oben oder unten etwas abschneiden. Seine Höhe bestimmt
   die Zeile; die Slideshow daneben füllt sie aus.

   Kein Handlungsaufruf in dieser Sektion: der steht direkt darunter im
   Abschluss, und zweimal derselbe Knopf kurz hintereinander schwächt beide.
   ══════════════════════════════════════════════════════════════════════════ */

/* 33 em statt 60ch: die ch-Einheit misst die Breite der Null, und die ist in
   Inter deutlich schmaler als das mittlere Zeichen — 60ch trugen gemessen 72
   Zeichen. 33 em landen bei rund 66. */
.of__wort {
  max-width: 33em;
  margin: clamp(24px, 3vw, 36px) auto 0;
  display: grid;
  gap: 16px;
  text-align: center;
}
.of__wort p {
  margin-inline: auto;
  font-size: clamp(16px, 1.2vw, 18px);
  line-height: 1.6;
  color: var(--ink-2);
}

/* ── Ort: links der Text, rechts die Galerie ──────────────────────────────
   Kompakt statt großzügig: die Sektion soll möglichst in einen Bildschirm
   passen. Vorher lief die Galerie über die volle Breite und der Text stand
   mittig darüber — zusammen weit über eine Bildschirmhöhe.

   Der Gründerblock ist hier entfallen. Er stand doppelt: im Hero und noch
   einmal hier.

   Beide Spalten sind oben bündig verankert, damit Überschrift und Bildkante
   auf einer Linie beginnen. */
.of__spalten {
  margin-top: clamp(22px, 2.6vw, 34px);
  display: grid;
  gap: clamp(24px, 3vw, 48px);
}
@media (min-width: 900px) {
  .of__spalten {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}

/* Der Textblock steht linksbündig und geschlossen — nicht mittig wie zuvor. */
.of .of__wort {
  max-width: 46ch;
  margin: 0;
  text-align: left;
}
.of .of__wort p + p { margin-top: clamp(12px, 1.4vw, 18px); }

.of__buehne { margin-top: 0; }

/* ── Slideshow ────────────────────────────────────────────────────── */

.of__lauf {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--canvas-2);
  aspect-ratio: 4 / 3;
}
/* Vorher stand hier `height: 100%` — die Höhe kam von dem Porträt, das daneben
   stand. Seit die Slideshow allein über die Satzbreite läuft, hat sie keinen
   Bezug mehr und fiel damit auf null zusammen: die Sektion war leer.
   Jetzt trägt sie ihr eigenes Verhältnis. */
@media (min-width: 860px) { .of__lauf { aspect-ratio: 16 / 9; height: auto; } }
.of__lauf .team-carousel__slide { position: absolute; inset: 0; margin: 0; }
.of__lauf img { width: 100%; height: 100%; object-fit: cover; }
.of__lauf figcaption {
  position: absolute;
  left: 14px;
  bottom: 14px;
  padding: 7px 13px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(18, 18, 20, 0.46);
  backdrop-filter: blur(10px);
  color: #fff;
  font-size: 12.5px;
  letter-spacing: 0.01em;
}

/* ═══ Abschluss ═══════════════════════════════════════════════════════════
   Der Schlusssatz lief bisher auf --fs-display, also bis 108 px. In dieser
   Größe schreit er die Seite an, obwohl direkt darunter der Knopf steht, der
   die eigentliche Aufforderung trägt. Eine Stufe kleiner reicht.
   ═════════════════════════════════════════════════════════════════════════ */
.final__title { font-size: clamp(30px, 4.2vw, 58px); max-width: 24ch; }
.final__hinweis { margin-top: 18px; font-size: 13.5px; color: var(--muted); }

/* Kunden werden in der Leiste grün ausgezeichnet: die Rolle unterscheidet
   zwischen „wir haben für sie gebaut" und „damit arbeiten wir". Nur das
   Erste ist eine Referenz, und Grün heißt auf dieser Seite Ergebnis. */
.logomarquee__rolle--kunde { color: var(--ergebnis, #516C43); font-weight: 600; }

/* Die Wortmarke in der Überschrift. Sie sitzt auf der Höhe der
   Kleinbuchstaben und wächst mit dem Schriftgrad mit — als festes Pixelmaß
   würde sie bei jeder Fenstergröße anders zur Zeile stehen.
   0.72em entspricht der Versalhöhe der Serifenschrift in dieser Größe. */
.marke-inline {
  display: inline-block;
  height: 0.72em;
  width: auto;
  vertical-align: baseline;
  transform: translateY(0.02em);
}

/* Kopf der Ortssektion linksbündig: die Überschrift teilt ihre Kante mit dem
   Textblock darunter, nicht mit der Bildmitte. */
.of .sec-head { text-align: left; max-width: 46ch; }

/* Kompakter: die Sektion lief mit dem Standardabstand der Seite auf 1010 px
   bei 900 px Bildschirmhöhe. Weniger Luft oben und unten, kleinere
   Überschrift — in der halbbreiten Spalte brach sie sonst auf drei Zeilen. */
.of.section { padding-block: clamp(52px, 6.5vw, 92px); }
.of .sec-head h2 {
  font-size: clamp(27px, 2.5vw, 38px);
  line-height: 1.08;
  max-width: 15ch;
}
.of .sec-head { max-width: none; }
.of .of__wort { max-width: 50ch; }

/* Überschrift und Text teilen sich die linke Spalte und damit eine Kante.
   Vorher stand der Kopf als eigene Zeile über beiden Spalten und war zentriert
   — dadurch schwebte er mittig über dem Bild statt über seinem eigenen Text. */
.of__text { display: grid; align-content: start; }
.of .sec-head { text-align: left; margin: 0 0 clamp(14px, 1.8vw, 24px); max-width: none; }
.of .sec-head h2 { margin-top: 0; }

/* Die h2 trägt aus der Grundfassung ein `margin-inline: auto` und stand
   dadurch mittig in ihrer Spalte, obwohl der Kopf schon linksbündig war. */
.of .sec-head h2 { margin-inline: 0; }
.of .eyebrow { text-align: left; }
