@font-face { font-family: Jost; src: url(/assets/fonts/jost-300.woff2) format('woff2'); font-weight: 300; font-display: swap; }
@font-face { font-family: Jost; src: url(/assets/fonts/jost-400.woff2) format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: Jost; src: url(/assets/fonts/jost-500.woff2) format('woff2'); font-weight: 500; font-display: swap; }
@font-face { font-family: Jost; src: url(/assets/fonts/jost-600.woff2) format('woff2'); font-weight: 600; font-display: swap; }

:root {
  --bg: #000;
  --fg: #fff;
  --schatten: rgb(0 0 0 / .75);
  --rand: clamp(24px, 3.85vw, 56px);
  --side: clamp(260px, 21.5vw, 330px);
  /* Andrei, PDF 23.09. (S.4): Text etwas rechts vom Beginn des Verlaufs und nur so breit wie die
     Menüspalte (vorher clamp(300px, 26vw, 400px), direkt am Spaltenrand). */
  --textbreite: var(--side);
  --text-einzug: clamp(16px, 1.8vw, 32px);
}
:root[data-ton="hell"], body[data-ton="hell"] { --fg: #141414; --schatten: rgb(255 255 255 / .85); }
/* Ganze Pixel gegen eine Naht zwischen Spalte und Bild. Ohne round() (Chrome < 125) bliebe sonst
   die Spaltenbreite ungültig und das ganze Raster zerfiele. */
@supports (width: round(1px, 1px)) { :root { --side: round(clamp(260px, 21.5vw, 330px), 1px); } }

.skip { position: absolute; left: 12px; top: -60px; z-index: 200; padding: 8px 12px; background: var(--bg); color: var(--fg); }
/* Fable, docs/AUFTRAG-SEO.md Punkt 6: genau eine h1 pro Seite, auch wo sie visuell nicht gebraucht
   wird (Startseite) — Standard-Muster für "für Screenreader/Suchmaschinen da, optisch unsichtbar". */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip:focus { top: 12px; }

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  background: var(--bg);
  color: var(--fg);
  font-family: Jost, system-ui, sans-serif;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Navigations-Links: erst der Mauszeiger zeigt per feinem Unterstrich, dass sie klickbar sind.
   Fund 21.09. (Matthias, Screenshot): besuchte Links (architecture/research, schon angeklickt)
   erschienen blau statt in der Textfarbe — "color: inherit" auf dem einfachen a-Selektor reicht
   dem Browser nicht immer, um seine eigene :visited-Farbe zu verdrängen. Jetzt beide Zustände
   ausdrücklich angesprochen. */
/* Nicht mehr auf .site beschränkt (Fund 21.09.: .liste-unter hängt auf Mobil per JS direkt am
   body, siehe app.js — die Farbe muss dort genauso gelten, sonst kommt wieder Browser-Blau durch). */
a, a:link, a:visited { color: inherit; }
.kopf a, .liste-unter a, .logo, .kontakt a, .recht a {
  text-decoration: underline 1px transparent;
  text-underline-offset: .24em;
  transition: text-decoration-color 180ms ease-out;
}
@media (hover: hover) {
  .kopf a:hover, .liste-unter a:hover, .logo:hover, .kontakt a:hover, .recht a:hover { text-decoration-color: currentColor; }
}
/* Links im Fließtext (Änderung 10) bleiben dauerhaft unterstrichen erkennbar, anders als die Navigation. */
.text p a { text-decoration: underline 1px currentColor; text-underline-offset: .18em; }

/* Ebenfalls nicht mehr auf .site beschränkt, gleicher Grund wie bei der Textfarbe oben. */
a, button { -webkit-tap-highlight-color: transparent; }
a:focus-visible, button:focus-visible { outline: 1px solid currentColor; outline-offset: 4px; text-decoration-color: currentColor; }
h1:focus { outline: none; }
.aktiv { font-weight: 500; }

.site { display: grid; grid-template-columns: var(--side) 1fr; min-height: 100vh; }

/* ---- linke Spalte ---- */
.side {
  position: sticky; top: 0;
  width: var(--side); height: 100vh;
  display: flex; flex-direction: column;
  padding: var(--rand) 24px calc(var(--rand) * .85) var(--rand);
  z-index: 3;
}
.kopf { order: 1; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.logo { order: 3; width: clamp(64px, 6.2vw, 90px); display: block; margin-bottom: 1.4em; flex: 0 0 auto; }
.logo svg { display: block; width: 100%; height: auto; }
.logo-maske {
  display: block; width: 100%; background: currentColor;
  -webkit-mask: var(--logo-url) center / contain no-repeat; mask: var(--logo-url) center / contain no-repeat;
}
/* Änderung 21.09., dritter Anlauf (Matthias, mit eingezeichnetem Rechteck): nicht auf die ganze
   Spaltenbreite verteilen (wirkte zerrissen), auch nicht nur eng links (wirkte zu klein) — die
   Icons sollen genau so breit verteilt sein wie die breiteste Zeile darüber/darunter tatsächlich
   ist ("Impressum · Datenschutz"). Ein einspaltiges Grid mit max-content-Spalte lässt alle drei
   Zeilen automatisch dieselbe, an den Inhalt angepasste Breite teilen.
   Vierter Anlauf, dann zurückgenommen (Matthias: war ein Missverständnis — gemeint war linksbündig
   auf gleicher Höhe mit Logo/Wortmarke/Menü, wie am Desktop schon immer, nicht mittig). Zentriert
   bleibt nur die mobile Variante weiter unten, dort war das ausdrücklich so gewünscht. */
.fuss { order: 4; flex: 0 0 auto; display: grid; grid-template-columns: max-content; }

/* Matthias, 22.09. (Screenshot "GHEORGHE test"): bricht die Wortmarke auf zwei Zeilen um, soll die
   zweite Zeile bündig mit dem ERSTEN Wort beginnen, nicht mit der "00"-Nummer/dem linken Rand —
   hängender Einzug: padding-left schiebt jede Zeile nach rechts, text-indent (nur auf die erste
   Zeile wirksam) holt "00" wieder an den echten linken Rand zurück. Wert per Live-Messung
   (getBoundingClientRect) kalibriert. */
.marke {
  display: inline-block; font-size: clamp(30px, 2.7vw, 41px); line-height: 1.12; letter-spacing: .01em; flex: 0 0 auto;
  padding-left: .53em; text-indent: -.53em;
}
/* Andrei, PDF 22.09. (S.1): GHEORGHE bekommt dieselbe "00" wie die Hauptpunkte darunter. */
.marke .nr {
  font-family: 'Jost', system-ui, sans-serif; font-size: .32em; font-weight: 300;
  color: color-mix(in srgb, var(--fg) 55%, transparent); letter-spacing: .04em; margin-right: .4em;
}

/* ---- Hauptmenü, Variante 5: nummeriert wie in Architekturplänen (Änderung 3) ---- */
/* Umgebaut 20.09. spät abends (Screenshot mit 20+ Probeprojekten): die Hauptpunkte (01/02/03)
   müssen immer sichtbar bleiben, auch wenn die Projektliste eines aktiven Punkts nicht mehr
   hineinpasst. Darum scrollt nicht mehr die ganze Liste, sondern nur noch .liste-unter — dafür
   wird genau das Element, das die aktive Unterliste enthält, zum flexiblen Rest (:has, siehe unten). */
.hauptmenue {
  list-style: none; margin: 2.4em 0 0; padding: 0 0 32px;
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  font-size: clamp(15px, 1.1vw, 16px); line-height: 1.65;
}
.hauptmenue > li { flex: 0 0 auto; margin-top: .55em; }
.hauptmenue > li:first-child { margin-top: 0; }
/* Der Hauptpunkt mit ausgeklappter Unterliste darf schrumpfen — dadurch bekommt .liste-unter
   darin eine echte Höhengrenze und kann für sich scrollen, wenn die Liste lang ist. Bewusst KEIN
   Wachsen (flex-grow: 0, Fund 21.09.: eine kurze Liste wuchs sonst trotzdem auf den ganzen
   Restplatz und schob die folgenden Hauptpunkte grundlos nach unten). Ist die Liste kurz, bleibt
   die Box so klein wie ihr Inhalt, die nächsten Punkte stehen direkt darunter. */
.hauptmenue > li:has(.liste-unter) { display: flex; flex-direction: column; min-height: 0; flex: 0 1 auto; }
.hauptmenue .kat, .hauptmenue .kat.leer { display: flex; align-items: baseline; gap: .55em; flex: 0 0 auto; }
.hauptmenue .kat.leer { cursor: default; color: color-mix(in srgb, var(--fg) 45%, transparent); }
.hauptmenue .nr {
  font-family: 'Jost', system-ui, sans-serif; font-size: .72em; font-weight: 300;
  color: color-mix(in srgb, var(--fg) 55%, transparent); letter-spacing: .04em;
}
.hauptmenue .kat.aktiv .nr { color: currentColor; }
/* Andrei, PDF 22.09. (S.1): kleiner +/- Hinweis, ob die Unterliste offen ist. */
.hauptmenue .kat .auf-zu {
  margin-left: .55em; font-family: 'Jost', system-ui, sans-serif; font-weight: 300;
  font-size: .85em; color: color-mix(in srgb, var(--fg) 55%, transparent);
}
.hauptmenue .kat.aktiv .auf-zu { color: currentColor; }

/* Andrei, PDF 22.09. (S.6): keine sichtbare Scrollleiste mehr — nur noch die Pfeile unten als
   Hinweis, dass sich die Liste scrollen lässt (vorher zusätzlich eine feine 4px-Leiste). */
.liste-unter, .liste-unter-scroll { scrollbar-width: none; }
.liste-unter::-webkit-scrollbar, .liste-unter-scroll::-webkit-scrollbar { display: none; }

.liste-unter {
  list-style: none; margin: .5em 0 0; padding: 0 0 0 1.75em;
  display: flex; flex-direction: column; gap: .15em; min-height: 0; overflow-y: auto; overflow-x: hidden;
  font-size: .96em; line-height: 1.6;
}
/* Projektnamen bleiben einzeilig und werden bei Überlänge mit „…" gekürzt: Fett ist ~7 % breiter,
   sonst würde der aktive Name umbrechen und Logo/Kontakt darunter verschieben.
   Das Backend begrenzt Titel auf 28 Zeichen (gemessene Breite bei 800–1920 px). */
.liste-unter .proj { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }

/* Änderung 7, umgebaut 20.09. und nochmal 21.09.: Hinweis, dass sich die Projektliste nach unten
   scrollen lässt. Fund 21.09. (Matthias, Screenshot): der Pfeil hing zwar zentriert, aber immer
   noch am ganzen Hauptpunkt-Block, nicht an der Unterliste selbst — er landete dadurch weit unten
   nahe test/Logo statt direkt an der Stelle, wo tatsächlich weitergescrollt wird. Jetzt sitzt der
   Träger (der aktive Hauptpunkt mit .liste-unter, siehe oben) selbst als Bezugsrahmen, Pfeil und
   Abblendung kleben also direkt am unteren Rand der Projektliste — darf den letzten sichtbaren
   Eintrag ruhig leicht überdecken (Matthias: "kannst den letzten sichtbaren Unterpunkt ruhig
   ausblenden"). */
.hauptmenue > li:has(.liste-unter) { position: relative; }
.hauptmenue > li.ueberlauft-unten::after {
  content: ""; position: absolute; left: 0; right: 8px; bottom: 0; height: 34px; pointer-events: none;
  background: linear-gradient(180deg, transparent, var(--bg));
}
/* Fund 21.09., zweiter Anlauf (Matthias, Screenshot): sobald man nach unten gescrollt hat, braucht
   es denselben Hinweis spiegelverkehrt am oberen Rand — sonst sieht man nicht, dass man auch wieder
   zurückscrollen kann.
   Dritter Anlauf (Matthias, Screenshot: Pfeil klebt am Kategorie-Titel statt an der Unterliste):
   "oben" heißt hier der obere Rand des ganzen Trägers (der Kategorie-Titel ist Teil davon), nicht
   der obere Rand der Unterliste selbst — --liste-oben (per JS gesetzt, app.js) verschiebt beide
   Elemente exakt an den tatsächlichen Beginn der Unterliste. */
.hauptmenue > li.ueberlauft-oben::before {
  content: ""; position: absolute; left: 0; right: 8px; top: var(--liste-oben, 0px); height: 34px; pointer-events: none;
  background: linear-gradient(0deg, transparent, var(--bg));
}
/* Andrei, PDF 22.09. (S.6): Pfeile ganz links statt zentriert — dort, wo vorher die Scrollleiste war. */
.scroll-pfeil {
  display: none; position: absolute; left: 0; z-index: 1;
  width: 20px; height: 20px; padding: 0; border: 0; background: none; color: var(--fg); cursor: pointer;
}
.scroll-pfeil-unten { bottom: 4px; animation: scroll-hinweis-unten 1.6s ease-in-out infinite; }
.scroll-pfeil-oben { top: calc(var(--liste-oben, 0px) + 4px); animation: scroll-hinweis-oben 1.6s ease-in-out infinite; }
.hauptmenue > li.ueberlauft-unten .scroll-pfeil-unten { display: block; }
.hauptmenue > li.ueberlauft-oben .scroll-pfeil-oben { display: block; }
.scroll-pfeil svg { width: 100%; height: 100%; }
@keyframes scroll-hinweis-unten { 0%, 100% { transform: translateY(0); opacity: .55; } 50% { transform: translateY(4px); opacity: 1; } }
@keyframes scroll-hinweis-oben { 0%, 100% { transform: translateY(0); opacity: .55; } 50% { transform: translateY(-4px); opacity: 1; } }

.kontakt { margin: 0; font-size: var(--tl-email-groesse, 13px); line-height: var(--tl-email-zeilenhoehe, 1.7); }
/* Änderung 21.09., vierter Anlauf (Matthias: nicht ganz an den Rand klatschen, "von der Mitte aus
   verteilt") — space-evenly statt space-between: bei zwei Icons lässt das genauso viel Platz vor
   dem ersten und nach dem letzten wie dazwischen, symmetrisch um die Mitte, ohne die Ränder zu
   berühren. Kommt ein drittes (X) dazu, verteilen sich alle drei weiter gleichmäßig. */
.social { display: flex; justify-content: space-evenly; gap: 18px; margin: .6em 0 0; }
/* Trefferfläche 24×24 (WCAG 2.2), sichtbar bleiben 18 px: Innenabstand wird per negativem Rand aufgefangen. */
.social a { display: block; width: 24px; height: 24px; padding: 3px; margin: -3px; box-sizing: border-box; }
.social svg { display: block; width: 100%; height: 100%; }
.social:empty { display: none; }
/* Entscheidung 24: der ganze Block links unten rückt enger zusammen, Telefonnummer fliegt hier raus. */
.recht { margin: .6em 0 0; font-size: 12px; }
.recht a { display: inline-block; padding: 4px 0; margin: -4px 0; }
/* Die Wisch-Pfeile am Textblock gibt es nur am Handy (siehe unten) — am Desktop kamen sie sonst als
   unformatierte 16-px-Knöpfe ans Textende (Abnahme-Review 22.09.). */
.text-pfeil { display: none; }

/* ---- rechte Seite ---- */
.buehne { position: relative; min-height: 100vh; }
.ansicht { position: relative; min-height: 100vh; }

/* Startseiten-Hintergrundvideo (Änderung 1+2) */
.start-video { position: fixed; inset: 0; left: var(--side); overflow: hidden; }
.start-video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.start-video::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  /* Andrei, PDF 22.09. (S.4): bei 0 % war trotzdem ein Verlauf sichtbar, weil die zweite und dritte
     Farbstufe vorher einen fixen Aufschlag (+15 Punkte) auf den eingestellten Wert bekamen — bei 0 %
     blieb dadurch ein sichtbarer Streifen von 0–15 % stehen. Beide Stufen jetzt als Anteil des
     eingestellten Werts selbst: bei 0 % fallen alle drei Stufen auf denselben Punkt (kein Verlauf,
     wie die Beschriftung "0 = kein Verlauf" verspricht), bei 100 % reicht er bis zum rechten Rand.
     Matthias, 22.09. (Screenshot "research"-Seite): immer noch sichtbare Längsstreifen — drei
     Zwischenstufen reichten nicht. Jetzt sechs feinere Stufen (kleinerer Sprung je Stufe) plus
     "in oklab" als Farbinterpolation (gleichmäßiger als das srgb-Standardverhalten, der übliche
     Trick gegen genau dieses Banding). Fallback zuerst (ohne "in oklab", falls ein Browser das
     nicht kennt — eine ungültige zweite Deklaration wird dann einfach ignoriert, die erste bleibt
     stehen), die feinere Fassung danach als Verbesserung obendrauf. */
  background: linear-gradient(90deg,
    var(--bg) 0,
    color-mix(in srgb, var(--bg) 92%, transparent) calc(var(--verlauf-prozent, 62%) * .25),
    color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--verlauf-prozent, 62%) * .42),
    color-mix(in srgb, var(--bg) 60%, transparent) calc(var(--verlauf-prozent, 62%) * .58),
    color-mix(in srgb, var(--bg) 40%, transparent) calc(var(--verlauf-prozent, 62%) * .72),
    color-mix(in srgb, var(--bg) 18%, transparent) calc(var(--verlauf-prozent, 62%) * .87),
    transparent var(--verlauf-prozent, 62%));
  background: linear-gradient(90deg in oklab,
    var(--bg) 0,
    color-mix(in srgb, var(--bg) 92%, transparent) calc(var(--verlauf-prozent, 62%) * .25),
    color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--verlauf-prozent, 62%) * .42),
    color-mix(in srgb, var(--bg) 60%, transparent) calc(var(--verlauf-prozent, 62%) * .58),
    color-mix(in srgb, var(--bg) 40%, transparent) calc(var(--verlauf-prozent, 62%) * .72),
    color-mix(in srgb, var(--bg) 18%, transparent) calc(var(--verlauf-prozent, 62%) * .87),
    transparent var(--verlauf-prozent, 62%));
}

.bilder { position: fixed; top: 0; right: 0; bottom: 0; left: var(--side); overflow: hidden; }
.bild { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 900ms ease-in-out; cursor: pointer; }
.bild.an { opacity: 1; }
/* Änderung 9: Verlaufslänge einstellbar (--verlauf-prozent), statt fest an die Textbreite gebunden. */
/* Abnahme-Review 22.09. (Fable): Mit einem kleinen Verlauf (Andrei: 25 %) lief die weiße Schrift
   auf das helle Foto — die Textspalte ist breiter als der Verlauf. Erster Anlauf war eine
   Untergrenze für den Verlauf; gemessen reichte das nicht, weil der Verlauf am Textrand schon fast
   durchsichtig ist. Jetzt liegt hinter der Textspalte eine eigene, gleichmäßige Schutzschicht in
   der Hintergrundfarbe (Seiten MIT Text), die kurz hinter dem Text ausläuft — Andreis Verlauf-
   Einstellung bleibt davon unberührt und wirkt weiter über die ganze Breite. */
.bilder {
  --textschutz: linear-gradient(90deg,
    color-mix(in srgb, var(--bg) 78%, transparent) 0,
    color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--text-einzug) + var(--textbreite) + .5rem),
    transparent calc(var(--text-einzug) + var(--textbreite) + 8rem));
}
.bilder::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  /* Andrei/Matthias, PDF 22.09.: dieselbe Korrektur wie bei .start-video::after — Anteil statt
     fixem Aufschlag, sechs feine Zwischenstufen plus "in oklab" gegen Banding, siehe dort. */
  background: var(--textschutz), linear-gradient(90deg,
    var(--bg) 0,
    color-mix(in srgb, var(--bg) 92%, transparent) calc(var(--verlauf-prozent, 62%) * .25),
    color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--verlauf-prozent, 62%) * .42),
    color-mix(in srgb, var(--bg) 60%, transparent) calc(var(--verlauf-prozent, 62%) * .58),
    color-mix(in srgb, var(--bg) 40%, transparent) calc(var(--verlauf-prozent, 62%) * .72),
    color-mix(in srgb, var(--bg) 18%, transparent) calc(var(--verlauf-prozent, 62%) * .87),
    transparent var(--verlauf-prozent, 62%));
  background: var(--textschutz), linear-gradient(90deg in oklab,
    var(--bg) 0,
    color-mix(in srgb, var(--bg) 92%, transparent) calc(var(--verlauf-prozent, 62%) * .25),
    color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--verlauf-prozent, 62%) * .42),
    color-mix(in srgb, var(--bg) 60%, transparent) calc(var(--verlauf-prozent, 62%) * .58),
    color-mix(in srgb, var(--bg) 40%, transparent) calc(var(--verlauf-prozent, 62%) * .72),
    color-mix(in srgb, var(--bg) 18%, transparent) calc(var(--verlauf-prozent, 62%) * .87),
    transparent var(--verlauf-prozent, 62%));
}

.copyright {
  position: absolute; right: 16px; bottom: 14px; z-index: 2; pointer-events: none;
  font-size: 11px; letter-spacing: .04em; padding: 3px 8px;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  opacity: 0; transition: opacity 900ms ease-in-out;
}
.copyright.an { opacity: 1; }
.steuerung { position: absolute; inset: 0 0 0 calc(var(--text-einzug) + var(--textbreite) + 1.5rem); z-index: 2; pointer-events: none; }
.steuerung button { pointer-events: auto; cursor: pointer; color: var(--fg); background: none; border: 0; padding: 0; }

/* Änderung 15: Story-Laufleiste wie bei Facebook Stories, ersetzt die schlichten Punkte. */
.storyleiste {
  position: absolute; left: 0; right: 0; bottom: calc(var(--rand) + .5rem);
  width: min(420px, calc(100% - 2 * var(--rand))); margin-inline: auto;
  display: flex; gap: 8px;
}
/* Andrei, 24.09.: dicker und leichter anklickbar, Füllung in der aktuellen Hintergrundfarbe.
   Das frühere overflow:hidden schnitt auch die unsichtbare Trefferfläche (::after) ab — klickbar
   waren nur die sichtbaren 4 px. Die Füllung bleibt über ihren eigenen Radius in der Kachel. */
.story-segment {
  position: relative; flex: 1 1 0; height: 8px; border-radius: 4px;
  background: color-mix(in srgb, var(--fg) 40%, transparent);
  /* Änderung 21.09. (Matthias: Leiste geht auf Fotos komplett unter, Kacheln kaum zu erkennen):
     ein dünner Rand aus --schatten je Kachel (nicht als Filter auf die ganze Leiste — der würde
     über die Lücken hinweg verschwimmen) macht jede Kachel einzeln sichtbar, egal wie hell/dunkel
     das Foto darunter gerade ist. */
  box-shadow: 0 0 0 1px var(--schatten);
}
.story-segment::after { content: ""; position: absolute; inset: -10px -4px; } /* 8 px Leiste + 2×10 = 28 px Trefferfläche, seitlich bis in die Lücke */
.story-fuellung { position: absolute; inset: 0; width: 0; background: var(--bg); border-radius: inherit; }
.story-segment.abgeschlossen .story-fuellung { width: 100%; }
.story-segment.laeuft .story-fuellung { width: 0; animation: story-fuellen var(--bildwechsel-ms, 6000ms) linear forwards; }
.story-segment.laeuft.video .story-fuellung { animation-duration: var(--video-dauer-ms, 6000ms); }
.story-segment.pausiert .story-fuellung { animation-play-state: paused; }
@keyframes story-fuellen { from { width: 0; } to { width: 100%; } }

.text {
  position: relative; z-index: 2;
  width: var(--textbreite); margin-left: var(--text-einzug);
  /* Andrei, PDF 22.09. (S.1): Unterkante der Projektüberschrift soll auf Höhe der Unterkante von
     GHEORGHE liegen. Gemessen (getBoundingClientRect, einwortige Wortmarke) bei 1024/1280/1920 px:
     +8.6 / +3.5 / -3.7 px Differenz — die beiden clamp()-Kurven von --rand und der Wortmarken-
     Schriftgröße wachsen nicht exakt gleich, ein fixer Wert kann also nicht bei jeder Breite
     perfekt treffen. -3.5px (der Wert bei 1280px, einer üblichen Laptop-Breite) trifft den
     Durchschnitt am besten.
     Andrei, 24.09.: jetzt stattdessen auf der Oberkante des ersten Hauptmenüpunkts — das misst
     app.js (titelAusrichten) und setzt padding-top; dieser Wert gilt nur, bis das Skript läuft. */
  padding: calc(var(--rand) + .2em - 3.5px) 0 var(--rand);
  font-size: var(--tl-fliesstext-groesse, 16px); line-height: var(--tl-fliesstext-zeilenhoehe, 1.5);
  hyphens: auto; text-wrap: pretty;
}
/* Änderung 21.09. (Matthias: "über uns" wirkt gequetscht) — margin:0 war für den Fall gedacht, dass
   direkt danach der Untertitel (.unter) mit eigenem Abstand kommt; ohne Untertitel (z. B. "über
   uns") stieß die Überschrift sonst direkt an den ersten Absatz. */
.text h1 { margin: 0 0 .7em; font-size: var(--tl-projekttitel-groesse, 18px); line-height: var(--tl-projekttitel-zeilenhoehe, 1.3); font-weight: 500; }
.text .unter { margin: .3em 0 1.8em; font-size: var(--tl-untertitel-groesse, 18px); line-height: var(--tl-untertitel-zeilenhoehe, 1.3); }
/* Änderung 21.09.: jeder Enter bleibt ein eigener Absatz (absaetze() in text.php), aber ohne
   Abstand dazwischen — sie sitzen direkt übereinander wie im Eingabefeld. Der leere Absatz, den
   eine bewusst freigelassene Zeile erzeugt, bringt durch seine eigene Zeilenhöhe den zusätzlichen
   Abstand, wenn jemand das will — kein Sonderfall im Code nötig. Gilt für jedes längere Textfeld
   (über uns, Projekttext, Datenschutz, AGB), weil alle .text nutzen. */
/* Fund 21.09. (Matthias, Screenshot): Fließtext wahlweise als Blocksatz statt nur linksbündig,
   einstellbar im Backend (Textlayout) — --tl-fliesstext-ausrichtung kommt aus textlayout_css().
   .unter und .adresse sind auch <p>, aber kurze Einzeiler/Titelzeilen statt Fließtext — Blocksatz
   ergäbe dort nur ein einziges, hässlich auseinandergezogenes Wortpaar statt echten Blocksatz. */
.text p:not(.unter):not(.adresse) { margin: 0; text-align: var(--tl-fliesstext-ausrichtung, left); }
/* Andrei, PDF 25.09. (S.2): Der leere Absatz einer freigelassenen Zeile hatte keine Höhe — die
   Leerzeile verschwand, er half sich mit einem „.". Ein geschütztes Leerzeichen gibt ihm eine Zeile. */
.text p:empty::before { content: "\00a0"; }
.text .adresse { margin-top: 2.2em; font-size: var(--tl-email-groesse, 16px); line-height: var(--tl-email-zeilenhoehe, 1.75); }
.nur-text .text { width: min(560px, 100%); }
.angaben { margin: 1.8em 0 0; }
.angaben dt { font-weight: 500; }
.angaben dd { margin: 0 0 .8em; }
.folgt { opacity: .55; font-style: italic; }

.copyright, .steuerung .story-segment { font-size: var(--tl-bildbeschriftung-groesse, 11px); }

/* Andrei, PDF 23.09. (S.4), Alternative zum Vergleichen (Einstellungen → Textlayout → Textspalte):
   Bild und Verlauf beginnen erst rechts neben dem Text, der Text steht auf der reinen Hintergrund-
   farbe. Nur Seiten mit Text (Projekt, über uns) und nur am Computer — die Bedingung ist die genaue
   Umkehrung der Handy-Abfrage unten. */
@media (min-width: 761px) and (orientation: landscape), (min-width: 1101px) {
  [data-textspalte="daneben"] .ansicht:has(> .text) .bilder {
    left: calc(var(--side) + 2 * var(--text-einzug) + var(--textbreite));
    --textschutz: linear-gradient(transparent, transparent);
  }
  [data-textspalte="daneben"] .ansicht:has(> .text) .steuerung { inset: 0; }

  /* Andrei, PDF 25.09. (S.4/5): beim Scrollen lief der Text oben über die Wortmarke und unten unter
     Impressum/Datenschutz hinaus. Jetzt scrollt nur noch die Textspalte, in einem Fenster von der
     Oberkante des ersten Hauptmenüpunkts bis zur Unterkante von Impressum/Datenschutz — beide Linien
     misst app.js (textFensterSetzen) und legt sie als --fenster-oben/--fenster-unten ab. Oben blendet
     der Text auf wenigen Pixeln aus, unten läuft er weich aus und ist AUF der Linie von Impressum/
     Datenschutz ganz weg (Matthias, 25.09.: vorher reichte die Ausblendung noch unter die Linie).
     Das Mausrad scrollt den Text auch über dem Bild. */
  .ansicht > .text {
    position: fixed; top: 0; bottom: 0; left: calc(var(--side) + var(--text-einzug)); margin-left: 0;
    overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
    padding-bottom: calc(100vh - var(--fenster-unten, 100vh) + 1em);
    --kante-leer: calc(var(--fenster-oben, 0px) - 20px);
    --kante-voll: calc(var(--fenster-oben, 0px) - 6px);
    --fenster: linear-gradient(transparent var(--kante-leer), #000 var(--kante-voll),
      #000 calc(var(--fenster-unten, 100vh) - 28px), transparent var(--fenster-unten, 100vh));
    -webkit-mask-image: var(--fenster); mask-image: var(--fenster);
  }
  /* Matthias, 26.09. (Screenshot): gescrollt lief der Text noch über die Oberkante von „strategy“.
     Sobald gescrollt ist, endet er genau dort und blendet darunter ein. Ungescrollt bleibt die
     Kante darüber, sonst würde die Überschrift angeschnitten, die auf dieser Linie steht. */
  .text-mehr-oben > .text { --kante-leer: var(--fenster-oben, 0px); --kante-voll: calc(var(--fenster-oben, 0px) + 24px); }
  .ansicht > .text::-webkit-scrollbar { display: none; }
  /* Andrei, PDF 25.09. (S.1): Scroll-Pfeile links an der Textspalte, oben und unten am Textfenster. */
  .text-scroll-oben, .text-scroll-unten { position: fixed; z-index: 3; left: calc(var(--side) + var(--text-einzug) - 28px); }
  .text-scroll-oben { top: var(--fenster-oben, 0px); animation: scroll-hinweis-oben 1.6s ease-in-out infinite; }
  .text-scroll-unten { top: calc(var(--fenster-unten, 100vh) - 20px); animation: scroll-hinweis-unten 1.6s ease-in-out infinite; }
  .text-mehr-oben > .text-scroll-oben, .text-mehr-unten > .text-scroll-unten { display: block; }
  .ansicht > .text:focus-visible { outline: none; }
}

@media (prefers-reduced-motion: reduce) {
  .bild, .copyright, .kopf a, .liste-unter a, .story-fuellung, .scroll-pfeil { transition: none; animation: none; }
}

/* ---- Handy, dazu Tablets im Hochformat (quer bekommen sie die Computer-Ansicht) ---- */
@media (max-width: 760px), (orientation: portrait) and (max-width: 1100px) {
  .site { display: flex; flex-direction: column; min-height: 100svh; }
  .side { display: contents; }
  .kopf { display: contents; }
  .logo { order: 0; width: 46px; margin: 30px auto 14px; }
  .marke { order: 1; display: block; text-align: center; padding: 0 20px; text-indent: 0; }
  .marke { font-size: clamp(32px, 12.3vw, 52px); }
  /* Matthias, 22.09. (WhatsApp-Screenshot): Zahlen (00/01/02…) und das +/- nur am Desktop — mobil
     wirken sie neben den schon kurzen, eng nebeneinander stehenden Menüpunkten gequetscht. Der
     hängende Einzug oben ist für die Zahl vor GHEORGHE gedacht (siehe .marke .nr weiter oben) und
     damit hier gegenstandslos — text-indent bleibt trotzdem zurückgesetzt (siehe Zeile darüber),
     falls doch mal zwei Wörter vorkommen. */
  .nr, .auf-zu { display: none; }

  /* Hauptpunkte als Wischleiste, nummeriert. Fund 21.09.: flex-grow:1 (für die Desktop-Spalte
     gedacht) wirkte über .kopf { display:contents } mobil direkt auf .site durch und streckte die
     ganze Zeile auf fast Bildschirmhöhe, obwohl der Inhalt nur eine Zeile braucht — flex-grow:0
     setzt das zurück auf reine Inhaltsgröße. */
  .hauptmenue {
    order: 2; display: flex; flex-direction: row; flex-grow: 0; align-items: flex-start; gap: 1.8em; margin: .6em 0 0; padding: 0 28px;
    overflow-x: auto; overflow-y: visible; scrollbar-width: none; white-space: nowrap; font-size: 17px; line-height: 2.6;
    mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
  }
  /* Fund 21.09. (Matthias: Unterliste + Fußzeile mobil verschwunden): ohne align-items:flex-start
     oben streckte sich der Hauptpunkt mit .liste-unter (der am Desktop bewusst
     display:flex/flex-direction:column ist) über die ganze Zeilenhöhe, und die Reihe wuchs mit ihm
     auf über 300px — dadurch rutschte alles Folgende weit nach unten. Auf Mobil ist das Spalten-
     Verhalten der Unterliste ohnehin irrelevant (sie ist eigenes Flex-Kind von .site, siehe app.js),
     darum hier zurück auf die normale Blockdarstellung. */
  .hauptmenue > li:has(.liste-unter) { display: block; position: static; }
  .hauptmenue::-webkit-scrollbar { display: none; }
  .hauptmenue > li { margin-top: 0 !important; flex: 0 0 auto; }
  .hauptmenue > li:first-child { margin-left: auto; }
  .hauptmenue > li:last-child { margin-right: auto; }
  .kopf.ueberlauft-unten::after, .kopf .scroll-pfeil { display: none; }
  /* Änderung 21.09. (Matthias: Hauptpunkte "springen umher" beim Wechseln): echtes font-weight
     ändert die Zeichenbreite, dadurch rutschen alle folgenden Punkte in der Wischleiste seitlich.
     Hier stattdessen ein doppelter Text-Schatten als optisches "Fett" — sieht ähnlich kräftig aus,
     ändert aber nie die Breite. Nur mobil, am Desktop (Liste untereinander) gibt es das Problem nicht. */
  .hauptmenue .kat.aktiv { font-weight: 300; text-shadow: 0 0 .5px currentColor, 0 0 .5px currentColor; }

  /* Fund 21.09., zweiter Anlauf (Matthias, Screenshot mit Pfeil von "architecture" zur alten
     Position ganz unten): die Projektliste soll direkt an der Hauptleiste hängen und mit ihr
     links-rechts scrollen, nicht unten am Bildschirmrand als eigenes Panel kleben. Keine feste
     Position mehr — .liste-unter wird per JS (siehe app.js) zu einem echten Kind von .site gemacht
     und reiht sich per order direkt nach der Hauptleiste ein, ganz normal im Textfluss. Dadurch
     fallen auch die Fußzeilen-Ausblendung und der Bühnen-Puffer von vorher weg — die gab es nur,
     weil die Liste damals fest positioniert war und mit der Fußzeile kollidierte. */
  .liste-unter {
    order: 3; display: flex; flex-direction: row; flex: 0 0 auto; gap: 1.6em; margin: .5em 0 0; padding: 0 28px;
    overflow-x: auto; overflow-y: visible; scrollbar-width: none; white-space: nowrap; font-size: 17px; line-height: 1.6;
    mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
  }
  .liste-unter::-webkit-scrollbar { display: none; }
  .liste-unter .proj { max-width: none; overflow: visible; white-space: nowrap; }
  .liste-unter li:first-child { margin-left: auto; }
  .liste-unter li:last-child { margin-right: auto; }

  .buehne { order: 4; min-height: 0; flex: 1; }
  /* Fund 21.09. (Matthias: Fußzeile klebt am linken Rand): .fuss ist ein Grid mit einer
     max-content-Spalte (siehe oben, für die Icon-Ausrichtung) — die Spalte selbst sitzt per
     Grid-Standard links im Container, text-align allein wirkt nur auf Inhalt INNERHALB der Spalte,
     nicht auf die Spalte selbst. justify-content zentriert die Spalte im verfügbaren Platz — gilt
     nur mobil, am Desktop soll die Fußzeile linksbündig mit Logo/Menü bleiben (siehe Basisregel oben). */
  .fuss { order: 5; text-align: center; justify-content: center; padding: 36px 20px 28px; }

  .ansicht { display: flex; flex-direction: column; min-height: 0; margin-top: 1.4em; }
  .bilder, .start-video { position: relative; inset: auto; left: auto; height: 62svh; order: 2; }
  /* Änderung 17, überarbeitet 21.09. (Matthias: Verlauf zu schwach, soll wie am Desktop wirken):
     dasselbe dreistufige Muster wie der horizontale Verlauf oben (Änderung 9), nur um 90° gedreht —
     von oben nach unten statt links nach rechts, mit derselben einstellbaren Länge. Gilt jetzt
     einheitlich für Start-/Kategorie- und Projektbilder (die frühere schwächere Extra-Regel für
     Projektbilder ist damit hinfällig). */
  .bilder::after, .start-video::after {
    /* Andrei/Matthias, PDF 22.09.: dieselbe Korrektur wie am Desktop, nur senkrecht. */
    background: linear-gradient(180deg,
      var(--bg) 0,
      color-mix(in srgb, var(--bg) 92%, transparent) calc(var(--verlauf-prozent, 62%) * .25),
      color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--verlauf-prozent, 62%) * .42),
      color-mix(in srgb, var(--bg) 60%, transparent) calc(var(--verlauf-prozent, 62%) * .58),
      color-mix(in srgb, var(--bg) 40%, transparent) calc(var(--verlauf-prozent, 62%) * .72),
      color-mix(in srgb, var(--bg) 18%, transparent) calc(var(--verlauf-prozent, 62%) * .87),
      transparent var(--verlauf-prozent, 62%));
    background: linear-gradient(180deg in oklab,
      var(--bg) 0,
      color-mix(in srgb, var(--bg) 92%, transparent) calc(var(--verlauf-prozent, 62%) * .25),
      color-mix(in srgb, var(--bg) 78%, transparent) calc(var(--verlauf-prozent, 62%) * .42),
      color-mix(in srgb, var(--bg) 60%, transparent) calc(var(--verlauf-prozent, 62%) * .58),
      color-mix(in srgb, var(--bg) 40%, transparent) calc(var(--verlauf-prozent, 62%) * .72),
      color-mix(in srgb, var(--bg) 18%, transparent) calc(var(--verlauf-prozent, 62%) * .87),
      transparent var(--verlauf-prozent, 62%));
  }
  :root[data-ansicht="projekt"] .buehne, [data-ansicht="projekt"] .buehne { scroll-snap-type: y proximity; }
  [data-ansicht="projekt"] .bilder { height: 100vh; height: 100lvh; scroll-snap-align: start; }

  /* Änderung 21.09. (Matthias, Screenshot): mittig zentriert lässt kurze Zeilen (Adresse, kurze
     Absätze) seltsam in der Mitte "schweben" — linksbündig, nur die E-Mail-Zeile bleibt zentriert. */
  /* Andrei, PDF 23.09. (S.5): am Handy griffen die Schriftgrößen aus Einstellungen → Textlayout nicht,
     hier standen feste Werte. Jetzt dieselben Variablen wie am Computer, die alten Werte nur als Ersatz. */
  .text { order: 1; width: auto; max-width: 560px; margin-inline: auto; padding: 1.4em 24px 1.8em; text-align: left; font-size: var(--tl-fliesstext-groesse, 14.5px); line-height: var(--tl-fliesstext-zeilenhoehe, 1.45); }
  .text p:not(.unter):not(.adresse) { text-align: var(--tl-fliesstext-ausrichtung-mobil, left); }
  .text .adresse { text-align: center; }
  /* Änderung 21.09., zweiter Anlauf (Matthias, eingekreister Screenshot): Titel + Untertitel eines
     Projekts sind wie die Adresse kurze, eigenständige Zeilen — dieselbe Ausnahme von der
     Linksbündig-Regel oben (die war für lange Fließtexte gedacht, nicht für die Titelzeile). */
  .text h1, .text .unter { text-align: center; }
  .nur-text .text { width: auto; }
  .steuerung { inset: 0; }
  /* Wischen wird auch im Textblock ausgewertet (Fund 21.09., siehe app.js: nächstes/voriges Projekt) —
     pan-y lässt den Browser trotzdem senkrecht normal scrollen, statt das Wischen selbst zu übernehmen. */
  .bilder, .text { touch-action: pan-y; }
  .copyright { right: 12px; bottom: 60px; }
  .storyleiste { bottom: 96px; width: min(300px, calc(100% - 40px)); }

  /* Andrei, PDF 22.09. (S.9): "Pfeile links/rechts mit Funktion hinterlegen" — waren bis jetzt reine
     CSS-Pseudoelemente (pointer-events: none), nur ein Hinweis, dass sich der Textblock zum
     nächsten/vorigen Projekt wischen lässt (app.js). Jetzt echte <button> (dort per JS eingefügt,
     Funktion projektWischenInit), die dasselbe projektWechseln() wie die Wischgeste auslösen.
     .text--wischbar steuert weiterhin nur, ob es sie überhaupt gibt (mind. 2 Projekte). */
  .text-pfeil {
    display: block; position: absolute; top: 50%; translate: 0 -50%; z-index: 3;
    width: 26px; height: 26px; padding: 0; border: 0; background: none; color: var(--fg); cursor: pointer;
    opacity: .45; animation: wisch-hinweis 1.8s ease-in-out infinite;
  }
  .text-pfeil svg { width: 100%; height: 100%; }
  .text-pfeil-links { left: -4px; }
  .text-pfeil-rechts { right: -4px; }
  @keyframes wisch-hinweis { 0%, 100% { opacity: .3; } 50% { opacity: .65; } }
}

/* Andrei, PDF 23.09. (S.5): am Handy weicher Übergang beim Wischen zum nächsten/vorigen Projekt,
   wie Umblättern. Cross-Document View Transition; ob sie läuft, entscheiden pageswap/pagereveal
   (app.js und <head>) — jeder andere Seitenaufruf wird übersprungen. Nur der Inhalt (Text + Bild)
   blättert, Wortmarke und Menü bleiben stehen. */
/* Andrei, PDF 25.09. (S.7): die Projekte kamen schräg von oben statt waagrecht. Mit EINEM gemeinsamen
   Namen schiebt der Browser das Blatt von der alten Lage (weiter unten im Text gescrollt, also weit
   oben) zur neuen (Seitenanfang) — zusätzlich zur Seitwärtsbewegung, das ergab die Diagonale. Jetzt
   bekommt das alte Blatt beim Verlassen einen eigenen Namen (pageswap in app.js): zwei getrennte
   Blätter, jedes bleibt an seiner Stelle und bewegt sich nur waagrecht. */
@view-transition { navigation: auto; }
@media (max-width: 760px), (orientation: portrait) and (max-width: 1100px) {
  .ansicht { view-transition-name: blatt-neu; }
}
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
html:active-view-transition-type(vor)::view-transition-old(blatt-alt) { animation: blatt-raus-links 380ms cubic-bezier(.4, 0, .2, 1) both; }
html:active-view-transition-type(vor)::view-transition-new(blatt-neu) { animation: blatt-rein-rechts 380ms cubic-bezier(.4, 0, .2, 1) both; }
html:active-view-transition-type(zurueck)::view-transition-old(blatt-alt) { animation: blatt-raus-rechts 380ms cubic-bezier(.4, 0, .2, 1) both; }
html:active-view-transition-type(zurueck)::view-transition-new(blatt-neu) { animation: blatt-rein-links 380ms cubic-bezier(.4, 0, .2, 1) both; }
@keyframes blatt-raus-links { to { transform: translateX(-35%); opacity: 0; } }
@keyframes blatt-rein-rechts { from { transform: translateX(35%); opacity: 0; } }
@keyframes blatt-raus-rechts { to { transform: translateX(35%); opacity: 0; } }
@keyframes blatt-rein-links { from { transform: translateX(-35%); opacity: 0; } }

/* Tablet im Hochformat: Anordnung wie am Handy, nur mit etwas größerer Schrift. */
@media (orientation: portrait) and (min-width: 761px) and (max-width: 1100px) {
  .hauptmenue, .liste-unter { font-size: 19px; }
}
