/* conSono — Tiefenkarte
   Die Seite ist kein Stapel von Sektionen, sondern eine Fahrt durch
   hintereinanderliegende Ebenen: genau eine liegt scharf, alles davor und
   dahinter läuft aus dem Fokus. Der Scroll rastet an jeder scharfen Stelle
   ein — Geschwindigkeit bleibt beim Nutzer, das Ziel nicht. */

:root {
  --ink: #07080a;
  --bone: #f2efe7;
  --blue: #1f3d85;

  /* Eine Schrift für alles: PP Telegraf, lokal aus assets/fonts. */
  --font: "PP Telegraf", "Helvetica Neue", Arial, sans-serif;
  /* Nur für die Kanji: eine Gothic, keine Mincho — blockig, nicht kalligrafisch. */
  --font-cjk: "conSono Kanji", "Kozuka Gothic Pr6N", "Hiragino Kaku Gothic ProN",
              "Yu Gothic", sans-serif;

  --gutter: clamp(1.25rem, 5vw, 5rem);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

* { box-sizing: border-box; }

/* Der Scroll rastet stufenweise an den scharfen Stellen ein. */
/* Kein Einrasten mehr durch das CSS. Am iPhone ist die Stufenhöhe nie genau
   so groß wie die Strecke, die ein Wisch zurücklegt — die Adressleiste fährt
   ein und aus, und je nachdem war die Stufe zu klein (ein Wisch trug über zwei
   Rastpunkte) oder zu groß (er kam nicht an und fiel zurück). Das Weiterrücken
   macht jetzt das Skript, genau eine Stufe je Geste. */

/* iOS vergroessert Text in Bloecken, die es fuer breit haelt, eigenmaechtig —
   abhaengig von der Textgroesse, die jemand im System eingestellt hat. Der
   Kasten wird dabei mit der kleinen Schrift gerechnet und der Text mit der
   grossen gezeichnet: die Zeilen brechen zu spaet und laufen rechts aus dem
   Bild. Darum sehen es manche Leute so und andere nicht. Hier abgestellt;
   die Schrift skaliert ohnehin schon mit dem Fenster. */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--font);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---------------------------------------------------------------- Bühne */

.stage { position: fixed; inset: 0; z-index: 1; overflow: hidden; contain: strict; }

.track { position: relative; z-index: 0; }

/* Die Strecke erzeugt nur den Scrollweg. Ohne pointer-events:none läge sie
   über der Bühne und würde jeden Klick auf Links und Knöpfe abfangen. */
.track { pointer-events: none; }

/* Ein Auslauf hinter der letzten Stufe, ohne eigenen Rastpunkt. Er loest das,
   wofuer vorher die Stufenhoehe herhalten musste: faehrt die Adressleiste aus,
   ist das Fenster groesser als die zuletzt gemessene Stufe, und ohne diesen
   Auslauf laege der letzte Rastpunkt hinter dem Ende der Strecke — „Tickets"
   waere nicht mehr ganz anzufahren. 120px, weil die Stufe erst ab dieser
   Abweichung neu vermessen wird; wo lvh und svh bekannt sind, mindestens die
   Hoehe der Leiste. */
.track { padding-bottom: 120px; }

@supports (height: 100lvh) and (height: 100svh) {
  .track { padding-bottom: max(120px, calc(100lvh - 100svh)); }
}

/* Eine Stufe je Ebene, und zwar so hoch wie das GRÖSSTE Fenster — am Handy
   also das ohne Adressleiste. Das ist keine Kosmetik, sondern die Bedingung
   dafür, dass der letzte Halt überhaupt erreichbar ist: bei n Stufen endet die
   Strecke bei n·Stufe, der letzte Rastpunkt liegt bei (n−1)·Stufe, und weiter
   als n·Stufe − Fensterhöhe kommt man nicht. Ist die Stufe kleiner als das
   Fenster, liegt der letzte Rastpunkt hinter dem Ende — „Tickets" wurde dann
   nie ganz scharf. Mit lvh ist die Stufe nie kleiner als das Fenster. */
/* Die Stufenhöhe.

   Sie kam lange aus dem Skript, als Pixelwert von innerHeight. Am Handy ist
   das eine wandernde Zahl: die Adressleiste fährt beim Scrollen ein und aus.
   Die Strecke hat dann mitten in der Geste ihre Länge geändert, und das
   Einrasten hat dagegen gearbeitet — es fühlt sich an, als rutsche die Seite
   beim Runterscrollen wieder hinauf.

   svh ist das KLEINE Fenster, also das mit sichtbarer Leiste. Dieser Wert
   ändert sich beim Ein- und Ausfahren der Leiste nicht. Damit ist die Stufe
   nie höher als der Schirm: ein Wisch über den Schirm bringt immer mindestens
   eine Stufe weit, und der letzte Rastpunkt ist immer erreichbar. */
:root { --step: 100vh; }

@supports (height: 100svh) {
  :root { --step: 100svh; }
}

.snap {
  height: var(--step, 100vh);
}

.plane {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: max(5rem, 10vh) var(--gutter) max(7rem, 14vh);
  transform-origin: 50% 50%;
  will-change: transform, opacity;
  pointer-events: none;
}

/* Die Ueberschrift steht im Markup VOR der Tusche und ist wie sie absolut
   gesetzt — ohne z-index entscheidet die Reihenfolge, und der Strich hat sie
   verdeckt. Das betraf „drei kuenste" und „partner", wo der Strich oben liegt. */
.plane > .ink { z-index: 0; }
.plane > .heading { z-index: 1; }

.plane > :where(*:not(.ink):not(.loop):not(.heading)) {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 74rem;
  will-change: filter;
}


.plane--bottom > :where(*:not(.ink):not(.loop):not(.heading)) { align-self: end; }

.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ---------------------------------------------------------------- Grund */

.ground { position: absolute; inset: 0; overflow: hidden; }

.ground__img {
  position: absolute;
  inset: -4%;
  width: 108%;
  height: 108%;
  object-fit: cover;
  /* Hochkantquelle: die Figur steht tiefer im Bild als auf dem alten Foto. */
  object-position: 50% 46%;
  will-change: transform, opacity;
}

.ground__img--blur { opacity: 0; }


.ground__veil {
  position: absolute;
  inset: 0;
  /* Dunkler als beim Standbild: das Video hat einen harten Lichtkegel, den der
     alte Schleier nicht mehr gehalten hat. Die Mitte bleibt der hellste Punkt,
     nur eben deutlich tiefer. */
  background:
    radial-gradient(130% 100% at 50% 30%, rgba(7, 8, 10, 0.24) 0%, rgba(7, 8, 10, 0.55) 58%, rgba(7, 8, 10, 0.93) 100%),
    linear-gradient(180deg, rgba(7, 8, 10, 0.58) 0%, rgba(7, 8, 10, 0.24) 34%, rgba(7, 8, 10, 0.8) 100%);
}

.ground__wash { position: absolute; inset: 0; background: var(--ink); opacity: 0; }

/* ---------------------------------------------------------------- Tusche */

/* Die Striche sind gewöhnliche Bilder: die blaue Farbe steckt schon im PNG.
   Das Aufziehen macht ein Verlaufsausschnitt entlang der Strichrichtung —
   --reveal geht von 0 auf 1. Kein SVG-Filter, keine SVG-Maske: beides hat in
   Safari pro Bild einen eigenen Zwischenspeicher erzwungen. */
.ink {
  position: absolute;
  max-width: none;
  pointer-events: none;
  --reveal: 0;
  --ang: 90deg;
  -webkit-mask-image: linear-gradient(var(--ang),
    #000 calc(var(--reveal) * 134% - 34%), rgba(0, 0, 0, 0) calc(var(--reveal) * 134%));
  mask-image: linear-gradient(var(--ang),
    #000 calc(var(--reveal) * 134% - 34%), rgba(0, 0, 0, 0) calc(var(--reveal) * 134%));
}

/* Gespiegelt: derselbe Strich zieht von rechts nach links auf. */
.ink--flip { transform: scaleX(-1); }

/* Ein gerader Zug, so weit herangezoomt, dass seine DICKE zur Höhe des
   Textblocks passt — nicht seine Länge zur Breite. Deshalb hängt die Größe an
   `height`, und `width: auto` lässt die Länge aus dem Seitenverhältnis folgen:
   bei 5,8 : 1 wird der Zug dabei so lang, dass der schwere Kopf links aus dem
   Bild hängt. Der Block muss die Hülle sein, sonst gäbe es keine Höhe, auf die
   sich die Prozente beziehen könnten. */
.inkblock { position: relative; z-index: 0; }
.inkblock > .ink { z-index: 0; }
.inkblock > :not(.ink) { position: relative; z-index: 1; }

.inkblock--prose {
  font-size: clamp(1.05rem, 2.1vw, 1.75rem);
  /* 34ch ist das Mass fuer die Zeilenlaenge, nicht fuer die Breite: ch haengt
     an der Schrift, und solange die eigene noch nicht geladen ist, misst der
     Browser mit der Ersatzschrift. Der Kasten bleibt darum in jedem Fall
     innerhalb des Fensters. */
  width: min(34ch, 100%);
  max-width: 100%;
}

.inkblock--prose .prose { font-size: 1em; max-width: none; }

/* Der Zoomfaktor ist keine Geschmacksfrage, sondern eine Division. --core ist
   der Anteil der Leinwand, den die Tusche wirklich füllt (gemessen, steht in
   strokes.json); soll der Kern --fit mal so dick sein wie der Textblock, muss
   die Leinwand --fit / --core mal so hoch sein. --mid rückt ihn senkrecht
   zurecht, weil der Kern selten genau mittig auf der Leinwand sitzt. */
.ink--wide {
  --ang: 90deg;
  --core: 0.453;
  --mid: 0.529;
  --fit: 1.15;
  /* So weit nach links, dass der schwere Kopf UND der ausgefranste Auslauf
     jenseits des Fensters liegen: sichtbar ist nur das Mittelstück. */
  left: -105%;
  top: 50%;
  height: calc(var(--fit) * 100% / var(--core));
  width: auto;
  transform: translateY(calc(var(--mid) * -100%));
}
.ink--tall      { --ang: 179deg; right: -6%; top: -24%; height: 152%; width: auto; }
.ink--full      { --ang: 168deg; left: -20%; top: -26%; width: 146%; }
.ink--underline { --ang: 91deg;  left: -16%; bottom: -0.22em; width: 132%; }

/* Der dicke Kopf haengt links aus dem Bild und schiesst herein, wie in den
   Kuenstlerzeilen. --shift kommt aus depth.js. */
.ink--date {
  --ang: 91deg;
  left: -430%;
  top: 50%;
  width: 760%;
  opacity: 0.9;
  transform: translateY(-50%) translateX(calc(var(--shift, 0) * -1px)) scaleY(0.42);
}

/* Dasselbe bei den Künstlern: die Dicke des Zugs richtet sich nach der Höhe
   des Textblocks, die Länge folgt daraus — und der schwere Kopf hängt links
   aus dem Bild und schießt herein. */
.ink--row {
  --ang: 90deg;
  --core: 0.553;
  --mid: 0.495;
  --fit: 1.3;
  --dir: -1;
  left: -40%;
  top: 50%;
  height: calc(var(--fit) * 100% / var(--core));
  width: auto;
  opacity: 0.92;
  transform: translateY(calc(var(--mid) * -100%))
             translateX(calc(var(--shift, 0) * var(--dir) * 1px));
}

.ink--row-2 { --ang: 90deg; --core: 0.578; --mid: 0.5; }
.ink--row-3 { --ang: 90deg; --core: 0.415; --mid: 0.532; }

/* Gespiegelte Zeile: der Kopf hängt rechts hinaus. */
.ink--row.ink--flip {
  --dir: 1;
  left: auto;
  right: -40%;
  transform: translateY(calc(var(--mid) * -100%))
             translateX(calc(var(--shift, 0) * var(--dir) * 1px))
             scaleX(-1);
}

/* Die vier Striche der Anfangsschleife */
.loop { position: absolute; inset: 0; pointer-events: none; }
.loop .ink { opacity: 0; }
.ink--lt { --ang: 94deg;  left: -34%;  top: 9%;    width: 178%; }
.ink--lb { --ang: 91deg; left: -28%;  bottom: 6%; width: 168%; }
.ink--ll { --ang: 179deg; left: -14%;  top: -26%;  height: 158%; width: auto; }
.ink--lr { --ang: 128deg; right: -30%; top: -22%;  width: 104%; }

/* ---------------------------------------------------------------- Typografie */

.kanji {
  font-family: var(--font-cjk);
  font-weight: 400;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  font-size: clamp(1rem, 1.9vw, 1.5rem);
  color: rgba(242, 239, 231, 0.72);
  margin: 0 0 clamp(1.2rem, 3vh, 2.4rem);
}

/* Im Startbild dicht an den Titel — der große Abstand stammte aus der
   allgemeinen Regel, nicht aus einer Entscheidung. Muss NACH .kanji stehen,
   sonst gewinnt bei gleicher Spezifität die spätere Regel. */
.kanji--eng { margin-bottom: clamp(0.1rem, 0.4vh, 0.35rem); }

/* Seit das Datum unter dem Titel steht, ist es eine Angabe und keine
   Schlagzeile mehr — YOKŌ trägt die Größe allein. */
.date {
  font-size: clamp(1.35rem, 3vw, 2.4rem);
  font-weight: 700;
  letter-spacing: 0.005em;
  line-height: 1;
  /* Datum und Titel gehören zusammen, der Untertitel ist eine eigene Aussage —
     deshalb oben wenig und unten viel. Ganz ohne Abstand klebt das Datum an
     der Grundlinie von YOKŌ, weil der Titel mit 0.82 sehr eng läuft. */
  margin: clamp(0.7rem, 2vh, 1.5rem) 0 clamp(1.6rem, 4.5vh, 3.4rem);
}

/* Im Abbinder ist „Tickets" wieder das große Wort. */
.plane:last-of-type .date { font-size: clamp(1.9rem, 5.6vw, 4.4rem); letter-spacing: -0.015em; }

/* Jede Ebene bekommt eine Überschrift: fett, klein geschrieben, zentriert und
   oben — sie gehört zur Ebene, nicht zum Textblock, deshalb absolut gesetzt. */
.heading {
  position: absolute;
  top: max(4.6rem, 10vh);
  left: var(--gutter);
  right: var(--gutter);
  margin: 0;
  text-align: center;
  text-transform: lowercase;
  font-size: clamp(1.4rem, 3.4vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}

.underlined { position: relative; display: inline-block; }
.underlined > span { position: relative; }

/* Wort auf dem Strich — dieselbe Schichtung wie bei den Künstlernamen:
   der Strich liegt dahinter, das Wort davor. */
.onink { position: relative; z-index: 0; display: inline-block; }
.onink > .ink { z-index: 0; }
.onink > span { position: relative; z-index: 1; }

.title {
  font-size: clamp(3.5rem, 14.6vw, 12.8rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 0.82;
  margin: 0.06em 0 0;
}

.subtitle {
  font-size: clamp(0.95rem, 2.2vw, 1.6rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  color: rgba(242, 239, 231, 0.82);
  margin: 0;
}

.prose {
  font-size: clamp(1.05rem, 2.1vw, 1.75rem);
  font-weight: 400;
  line-height: 1.5;
  max-width: 34ch;
  margin: 0;
  text-wrap: pretty;
}

.prose + .prose { margin-top: 1.1em; }

/* Die drei Künste stehen fett — wie die Zeile im Titelbild. Sie waren
   vorher auf Regular, weil nie ein Gewicht gesetzt war. */
.senses {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 7vw, 6rem);
  justify-content: center;
  font-size: clamp(1.1rem, 3.2vw, 2.4rem);
  font-weight: 700;
  letter-spacing: 0.06em;
}

.center { text-align: center; }
.stack  { display: grid; justify-items: center; }

/* ---------------------------------------------------------------- Künstler */

/* Alle in einem Feld, alle gleichzeitig scharf. Reicht der Platz nicht,
   scrollt das Feld in sich statt die Seite zu sprengen. */
/* Breiter als der übrige Satzspiegel — nicht aus Layoutlaune, sondern weil der
   schwere Kopf des Strichs aus dem Bild hängen soll UND der Name noch auf dem
   dichten Teil liegen muss. Bei 58 rem begann der Textblock so weit rechts,
   dass beides zusammen nicht mehr in die Länge des Zugs passte. */
/* Sind Biographien aufgeklappt, wächst die Liste über den Schirm hinaus. Dann
   scrollt dieses Feld IN SICH bis zum Ende und gibt den Scroll erst danach an
   die Seite weiter. Das ist das eingebaute Verhalten von overflow, kein
   abgefangenes Scrollereignis — die Seite rastet deshalb weiterhin selbst ein,
   und die Geschwindigkeit bleibt beim Nutzer.

   Es ist volle Fensterbreite, weil ein Scrollcontainer auch waagrecht
   beschneidet: bei 72 rem wäre der Strichüberstand am Containerrand
   abgeschnitten statt erst am Bildrand, wo ihn die Bühne ohnehin kappt. */
.plane > .artists__feld {
  width: 100vw;
  max-width: 100vw;
  margin-inline: calc(50% - 50vw);
  max-height: 100%;
  /* Zu. „auto" hat schon bei wenigen Pixeln Überhang — Innenabstand, ein
     angeschnittener Buchstabe — einen Scrollbereich gemacht, und das Feld ließ
     sich ohne offene Biographie ein paar Pixel auf und ab wackeln. Freigegeben
     wird es erst per data-frei, wenn der Inhalt wirklich nicht mehr hineinpasst
     — also praktisch, sobald eine Biographie offen ist. */
  overflow-y: hidden;
  overflow-x: hidden;
  /* contain, nicht auto. Mit auto haengt der Browser den Scrollvorgang des
     Feldes am unteren Rand an die Seite weiter — noch im selben Wisch, ohne
     dass ein Ereignis davon erzaehlt. Am Handy war das die Ursache dafuer,
     dass die Seite mitten in einer Geste frei durchlief und zwischen zwei
     Ebenen stehenblieb. contain laesst die Geste im Feld enden; aus dem Feld
     heraus fuehrt nur eine neue. */
  overscroll-behavior-y: contain;
  padding-block: 0.4rem;
  /* Der Freiraum für den Tickets-Knopf gehört INS Feld, nicht um das Feld
     herum. Lag er als Polster der Ebene darunter, war das unterste Stück des
     Schirms ein toter Streifen: dort griff nicht das Feld, sondern die Seite,
     und man sah einen Balken, der den Text abschnitt. */
  padding-bottom: 0.4rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(242, 239, 231, 0.22) transparent;
}

.plane > .artists__feld[data-frei="ja"] { overflow-y: auto; }

/* Das Feld soll die ganze Hoehe der Ebene fuellen, nicht nur so viel, wie
   seine Zeilen gerade brauchen. Vorher war es bei 1067 px Fensterhoehe nur
   513 px hoch, obwohl 811 zur Verfuegung standen — darunter blieben fast
   300 px leer, und die oberste Zeile lag im Anschnitt. Die Ueberschrift liegt
   absolut und belegt keine Zeile; der Abstand zu ihr steckt deshalb als
   Polster IM Feld. Unten ebenso, damit die Liste unter dem Tickets-Knopf
   durchlaeuft, statt davor zu enden. */
.plane.plane--kuenstler {
  grid-template-rows: minmax(0, 1fr);
  align-items: stretch;
  padding-bottom: max(2rem, 4vh);
}

.plane.plane--kuenstler > .artists__feld {
  align-self: stretch;
  padding-top: max(3.4rem, 6.5vh);
  padding-bottom: max(5.5rem, 11vh);
}

/* Am Handy reicht das Künstlerfeld bis an den unteren Bildrand; der Abstand
   zum Tickets-Knopf steckt als Polster im Feld selbst. */
/* Zwei Klassen im Selektor, damit die Regel auch die Kurzschreibweise
   .plane { padding: … } aus dem 640er-Block sticht — die steht spaeter in der
   Datei und haette bei gleicher Gewichtung gewonnen. */
@media (max-width: 760px) {
  /* Die Reihe bekommt eine feste Hoehe (1fr) statt einer inhaltsabhaengigen.
     Nur dann loest max-height: 100% im Feld ueberhaupt auf — vorher blieb
     darunter ein Streifen stehen, den das Feld nicht ausgefuellt hat. */
  .plane.plane--kuenstler {
    padding-bottom: max(1rem, 2vh);
    grid-template-rows: minmax(0, 1fr);
    align-items: stretch;
  }

  /* Das Feld reicht jetzt bis unter die Ueberschrift hinauf — der Abstand
     dorthin gehoert deshalb ebenfalls ins Feld, sonst laeuft die erste Zeile
     durch „kuenstler" hindurch. */
  .plane.plane--kuenstler > .artists__feld {
    padding-top: max(3.4rem, 7vh);
    padding-bottom: max(7rem, 14vh);
    align-self: stretch;
  }
}

.artists__feld::-webkit-scrollbar { width: 4px; }
.artists__feld::-webkit-scrollbar-track { background: transparent; }
.artists__feld::-webkit-scrollbar-thumb {
  background: rgba(242, 239, 231, 0.22);
  border-radius: 2px;
}

.artists {
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  /* Sechs Zeilen müssen gleichzeitig scharf auf den Schirm passen — bei drei
     durfte der Abstand das Doppelte sein. Die Zeile selbst ist dafür knapper
     gebaut: Rolle, Name, „weiterlesen“, mehr nicht. */
  gap: clamp(1.3rem, 3vh, 2.4rem);
  max-width: 72rem;
}

.artist {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.1rem, 3.5vw, 2.6rem);
  opacity: 0;
  will-change: opacity, transform;
}

/* Inhalt über den Strich, nicht darunter */
.artist__portrait,
.artist__body { position: relative; }

/* Hülle um Rolle, Name, Zeile und Fuß — an ihrer Höhe hängt die Dicke des
   Strichs. Die Biographie liegt bewusst DAVOR im Markup zu Ende, sonst würde
   der Strich beim Aufklappen mitwachsen. z-index 0 sperrt die überstehende
   Tusche in diese Hülle ein; der Inhalt liegt auf Stufe 1 und bleibt frei. */
.artist__block { position: relative; z-index: 0; }
.artist__block > .ink { z-index: 0; }
.artist__block > :not(.ink) { position: relative; z-index: 1; }

.artist__portrait,
.artist__role,
.artist__line,
.artist__foot,
.bio { position: relative; z-index: 1; }

/* Fotonachweis. Steht im aufgeklappten Text, nicht an der Zeile: er gehört zum
   Bild, soll aber die Zeile nicht aufblähen. */
.artist__credit {
  margin: 0.7rem 0 0;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: rgba(242, 239, 231, 0.4);
}

/* Noch kein Foto geliefert: der Ring bleibt leer und gestrichelt. Die frühere
   Beschriftung „foto folgt" stand bei 8 px im Kreis — zu klein, um lesbar zu
   sein, und damit reine Alibibeschriftung. Der leere Ring zwischen fünf
   Porträts sagt dasselbe deutlicher. */
.artist__portrait--leer {
  background: rgba(242, 239, 231, 0.03);
  box-shadow: none;
  border: 1px dashed rgba(242, 239, 231, 0.26);
}

.artist__portrait--leer span { display: none; }

/* Umgekehrt: Porträt wandert auf die andere Seite. */
.artist--right { direction: rtl; }
.artist--right > * { direction: ltr; }
.artist--right .artist__body { text-align: right; }
.artist--right .artist__foot { justify-content: flex-end; }

.artist__portrait {
  width: clamp(3.2rem, 5.6vw, 4.6rem);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: rgba(242, 239, 231, 0.05);
  box-shadow: inset 0 0 0 1px rgba(242, 239, 231, 0.22);
}

.artist__portrait img { width: 100%; height: 100%; object-fit: cover; }

.artist__portrait span {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: rgba(242, 239, 231, 0.35);
}

.artist__role {
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  color: rgba(242, 239, 231, 0.52);
  margin: 0 0 0.3rem;
}

.artist__name {
  position: relative;
  font-size: clamp(1.1rem, 2.1vw, 1.6rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.05;
  margin: 0 0 0.3rem;
}

.artist__line {
  font-size: clamp(0.88rem, 1.25vw, 1.02rem);
  line-height: 1.45;
  color: rgba(242, 239, 231, 0.72);
  margin: 0 0 0.6rem;
  max-width: 40ch;
}

.artist--right .artist__line { margin-left: auto; }

.artist__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
}

.artist__foot .unfold { margin-left: 0.4rem; }

.artist__foot a {
  display: inline-grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  color: rgba(242, 239, 231, 0.6);
  transition: color 0.3s var(--ease);
}

.artist__foot a svg { width: 100%; height: 100%; display: block; }
.artist__foot a:hover { color: var(--bone); }

.unfold {
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  text-decoration: none;
}
.artist__foot a:focus-visible,
.unfold:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }

/* Ein Knopf sieht auf der ganzen Seite gleich aus: helle Pille, blau beim
   Überfahren — „Tickets sichern", „erfahre mehr", die Menükarten und hier
   „weiterlesen". Der mitwachsende Strich von früher ist damit hinfällig. */
.unfold {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: 999px;
  background: var(--bone);
  color: var(--ink);
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}

.unfold:hover { background: var(--blue); color: var(--bone); }

/* Aufklappen ohne Sprung: 0fr -> 1fr lässt sich animieren, height:auto nicht. */
.bio {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.45s var(--ease);
}

.bio > div { overflow: hidden; }
.artist--open .bio { grid-template-rows: 1fr; }

.bio p {
  font-size: 0.9rem;
  line-height: 1.55;
  color: rgba(242, 239, 231, 0.66);
  margin: 0.7rem 0 0;
  max-width: 48ch;
}

.artist--right .bio p { margin-left: auto; }

/* ---------------------------------------------------------------- Termine */

/* Werkliste: Komponist links, Werk rechts. Auf Schmalbild untereinander, weil
   die Titel sonst in zwei Buchstaben pro Zeile umbrechen. */
/* Keine Trennlinien: die Gliederung trägt der Abstand. Dafür muss er
   deutlich größer sein als der Zeilenabstand innerhalb einer Zeile. */
.werke { display: grid; gap: clamp(1.5rem, 3.6vh, 2.6rem); }

.werk {
  display: grid;
  grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
  gap: clamp(0.6rem, 2.5vw, 2rem);
  align-items: baseline;
}

.werk__komponist {
  font-size: clamp(0.92rem, 1.5vw, 1.15rem);
  font-weight: 500;
}

.werk__titel {
  font-size: clamp(0.82rem, 1.25vw, 1rem);
  color: rgba(242, 239, 231, 0.66);
  text-wrap: pretty;
}

@media (max-width: 720px) {
  .werk { grid-template-columns: 1fr; gap: 0.15rem; }
}

/* Zeit- und Gattungszeile unter dem Untertitel im Startbild. */
.zeit {
  margin: clamp(1.4rem, 3.5vh, 2.6rem) 0 0;
  font-size: clamp(0.8rem, 1.3vw, 1rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--bone);
}

/* Ein einzelner, breiterer Satz unter den drei Künsten. */
.prose--weit { max-width: 46ch; margin-top: clamp(1.8rem, 4.5vh, 3.2rem); }

.dates { display: grid; gap: clamp(1.8rem, 4.2vh, 3.2rem); }

/* Titel, Datum, Untertitel — und ganz rechts der Knopf. Das Datum steht
   zwischen Titel und Untertitel, weil es die Angabe ist, nach der man sucht. */
.dates__row {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(0.9rem, 3vw, 2.2rem);
}

.dates__name {
  font-size: clamp(1.5rem, 5vw, 3.4rem);
  font-weight: 600;
  letter-spacing: -0.02em;
}

.dates__sub {
  font-size: clamp(0.85rem, 1.5vw, 1.1rem);
  color: rgba(242, 239, 231, 0.58);
}

.dates__when {
  font-variant-numeric: tabular-nums;
  font-size: clamp(0.9rem, 1.6vw, 1.2rem);
  font-weight: 700;
  color: var(--bone);
  white-space: nowrap;
}

/* ---------------------------------------------------------------- Chrom */

.chrome {
  position: fixed;
  inset: 0;
  z-index: 30;
  pointer-events: none;
  padding: clamp(1rem, 2.2vw, 1.7rem) var(--gutter);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: 1rem;
}

/* Klein, weiß, oben — der Weg zurück auf die Startseite, sonst nichts. */
/* Die Marke wird in ihrer GRÖSSTEN Größe angelegt und nur noch
   herunterskaliert. Andersherum — klein anlegen, hochskalieren — rastert der
   Browser die Datei in der kleinen Größe und zieht das Bild auf: das SVG sieht
   dann unscharf aus, obwohl es eine Vektordatei ist. --mk-faktor setzt das
   Skript; ohne Skript bleibt es bei 1 und damit bei der normalen Größe. */
.mark {
  grid-column: 2;
  display: block;
  --mk-klein: clamp(5rem, 7vw, 6.5rem);
  width: calc(var(--mk-klein) * var(--mk-faktor, 1));
  pointer-events: auto;
}

.mark img { width: 100%; height: auto; display: block; }
/* Wächst nach unten aus der Kopfzeile heraus, damit die Zeile selbst
   ihre Höhe behält und das Titelbild darunter nicht springt. */
.mark { transform-origin: 50% 0; }
.mark:focus-visible { outline: 2px solid var(--bone); outline-offset: 6px; }

.lang {
  grid-column: 3;
  justify-self: end;
  display: flex;
  gap: 0.3rem;
  align-items: center;
  font-family: var(--font);
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  pointer-events: auto;
}

.lang button {
  background: none;
  border: 0;
  padding: 0.25rem;
  font: inherit;
  letter-spacing: inherit;
  color: rgba(242, 239, 231, 0.45);
  cursor: pointer;
}

.lang button[aria-pressed="true"] { color: var(--bone); }
.lang button:focus-visible { outline: 2px solid var(--bone); outline-offset: 2px; }
.lang span { color: rgba(242, 239, 231, 0.35); }

/* Zwei Knoepfe, eine Leiste. Die Leiste traegt die Position, die Knoepfe
   nur noch ihr Aussehen — sonst muesste jeder von beiden seine eigene
   Mitte rechnen, und bei zwei Breiten geht das nicht auf. */
.aktionen {
  position: fixed;
  left: 0;
  right: 0;
  bottom: clamp(1.2rem, 3.5vh, 2.6rem);
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.55rem;
  padding-inline: 0.8rem;
  /* Die Leiste liegt jetzt ueber die ganze Breite, damit sie zum Umbrechen
     die ganze Breite zur Verfuegung hat: mit left:50% waere der Platz nur
     die halbe Seite, und am Handy brach sie deshalb grundlos in zwei Zeilen.
     Dafuer darf sie selbst nichts abfangen — nur die Knoepfe. */
  pointer-events: none;
}

.aktionen > * { pointer-events: auto; }

.tickets {
  display: inline-flex;
  align-items: center;
  padding: 0.95rem 1.9rem;
  border: 0;
  border-radius: 999px;
  background: var(--bone);
  color: var(--ink);
  text-decoration: none;
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}

.tickets:hover { background: var(--blue); color: var(--bone); }

.tickets--still {
  background: transparent;
  color: var(--bone);
  box-shadow: inset 0 0 0 1px rgba(242, 239, 231, 0.42);
  text-transform: lowercase;
}
.tickets--still:hover {
  background: var(--bone);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--bone);
}
.tickets:focus-visible { outline: 2px solid var(--bone); outline-offset: 4px; }

/* Entfernungsskala — zeigt, wo in der Tiefe man steht. */
.depthscale {
  position: fixed;
  right: clamp(0.7rem, 1.8vw, 1.5rem);
  top: 50%;
  transform: translateY(-50%);
  z-index: 20;
  width: 1px;
  height: min(38vh, 19rem);
  background: rgba(242, 239, 231, 0.18);
  pointer-events: none;
}

.depthscale i {
  position: absolute;
  left: -2px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--bone);
  top: 0;
  margin-top: -2px;
  will-change: top;
}

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

/* ---------------------------------------------------------------- Schmal */

@media (max-width: 760px) {
  .artist { grid-template-columns: auto minmax(0, 1fr); gap: 0.8rem; }
  .artist__line { display: none; }
  /* Deutlich mehr Luft zwischen den sechs Zeilen — am Handy standen sie fast
     aneinander, und die Striche liefen dabei ineinander. */
  .artists { gap: clamp(1.7rem, 4vh, 2.8rem); }
  /* Und die Striche selbst etwas schmaler, damit sie die Zeile begleiten
     statt sie zu tragen. */
  .ink--row { --fit: 0.95; }
  .ink--wide { --fit: 0.88; }
}

@media (max-width: 640px) {
  .aktionen { gap: 0.45rem; }
  .tickets { padding: 0.8rem 1.25rem; font-size: 0.74rem; letter-spacing: 0.03em; }
  .plane { padding: max(4.5rem, 9vh) var(--gutter) max(8rem, 16vh); }
  .prose { max-width: none; }
  /* line-height 0.82 lässt die Versalien oben aus ihrem Kasten ragen. Am
     großen Fenster ist darüber genug Luft, am Handy stößt der Titel sonst ins
     Datum — die Kästen überlappen dabei nicht, nur die Buchstaben. */
  .title { margin-top: 0.24em; }
  .dates__row {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.3rem clamp(0.8rem, 3vw, 1.4rem);
  }
  .dates__name { grid-column: 1; }
  .dates__when { grid-column: 1; }
  .dates__sub  { grid-column: 1; }
  .mehr { grid-column: 2; grid-row: 1 / span 3; }
  .depthscale { display: none; }
}

/* ---------------------------------------------------------------- Ruhe */

@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }
  .bio, .unfold::after, .tickets, .aktionen, .artist__foot a { transition: none; }
}

/* ---------------------------------------------------------------- Menü */

.menubtn {
  grid-column: 1;
  justify-self: start;
  background: none;
  border: 0;
  display: grid;
  gap: 6px;
  width: 26px;
  padding: 8px 0;
  cursor: pointer;
  pointer-events: auto;
}

.menubtn span {
  display: block;
  height: 1.5px;
  width: 100%;
  background: var(--bone);
  transition: transform 0.35s var(--ease), opacity 0.3s var(--ease);
}

.menubtn[aria-expanded="true"] span:first-child { transform: translateY(3.75px) rotate(45deg); }
.menubtn[aria-expanded="true"] span:last-child  { transform: translateY(-3.75px) rotate(-45deg); }

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

/* Das Menü liegt über allem, was die Seite sonst zeigt — auch über dem
   grossen Zeichen der Eröffnung, das vorher davor stand. Nur die Kopfzeile
   bleibt darüber, sonst käme man an das Kreuz zum Schliessen nicht heran.
   Dahinter wird alles weich und dunkel, damit das Menü allein steht. */
.menu {
  position: fixed;
  inset: 0;
  z-index: 28;
  display: grid;
  place-items: center;
  background: rgba(7, 8, 10, 0.74);
  -webkit-backdrop-filter: blur(20px) saturate(0.85) brightness(0.6);
  backdrop-filter: blur(20px) saturate(0.85) brightness(0.6);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0.4s;
}

/* Wo der Hintergrund nicht weichgezeichnet werden kann, deckt dafür die
   Fläche stärker ab — sonst stünde das Zeichen mitten im Menü. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .menu { background: rgba(7, 8, 10, 0.97); }
}

.menu[data-open="true"] { opacity: 1; visibility: visible; }

.menu nav {
  display: grid;
  gap: clamp(0.6rem, 2.4vh, 1.4rem);
  text-align: center;
  padding: var(--gutter);
}

.menu a {
  font-size: clamp(1.8rem, 6vw, 3.6rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--bone);
  text-decoration: none;
  transition: color 0.3s var(--ease);
}

.menu a:hover { color: #6d8ede; }
.menu a:focus-visible { outline: 2px solid var(--bone); outline-offset: 6px; }

.menu small {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: rgba(242, 239, 231, 0.4);
  margin-top: 1.6rem;
}

/* Instagram und die Pflichtseiten sitzen unter den Menüpunkten. Beide
   brauchen eine ZWEITE Klasse im Selektor: .menu a setzt die große
   Menüschrift, und eine Klasse allein wäre dagegen zu schwach. */
.menu .menu__ig {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: clamp(0.9rem, 2.4vh, 1.5rem);
  font-size: clamp(0.85rem, 2.4vw, 1rem);
  font-weight: 400;
  letter-spacing: 0.04em;
  color: rgba(242, 239, 231, 0.7);
}

.menu .menu__ig svg { width: 1.2em; height: 1.2em; flex: none; }
.menu .menu__ig:hover { color: var(--bone); }

/* Offene Stellen in den Gerüstseiten — gleiche Lesart wie im Impressum:
   sie sollen auffallen, nicht sich einfügen. */
.offen {
  margin: 0;
  color: #c98b8b;
  font-style: italic;
  line-height: 1.7;
  font-size: clamp(0.95rem, 1.8vw, 1.15rem);
}

/* ---------------------------------------------------- Impressum, Datenschutz */

.recht { display: grid; gap: clamp(2.2rem, 5.5vh, 3.6rem); max-width: 62ch; }

.recht__satz { display: grid; gap: 0.7rem; }

.recht__satz h2 {
  margin: 0;
  font-size: clamp(0.72rem, 0.95vw, 0.84rem);
  font-weight: 400;
  /* 0.12em wie alle kleinen Label der Seite — Fusszeile, Partnerrollen,
     Menuezeile. Hier stand als einziger Ort noch 0.14. */
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: rgba(242, 239, 231, 0.45);
}

.recht__satz p { margin: 0; line-height: 1.62; }
.recht__satz a { color: inherit; border-bottom: 1px solid rgba(242, 239, 231, 0.3); text-decoration: none; }
.recht__satz a:hover { border-color: var(--bone); }

/* Offene Pflichtangaben. Sie sollen auffallen, nicht sich einfügen — wer die
   Seite ansieht, soll sofort erkennen, dass hier noch etwas fehlt. */
.recht__offen {
  color: #c98b8b;
  font-style: italic;
  line-height: 1.7;
}

/* ------------------------------------------------------- Eröffnung */

/* Zwei gelieferte Dateien nebeneinander. Die Prozente stammen aus den
   viewBoxes: „con" ist 364.05 breit, „Sono" 717.54, die volle Marke 1082.54.
   So sitzen beide Hälften ohne Zutun genau dort, wo sie im vollen Logo
   stehen — und am Ende passt die Bewegung nahtlos auf die Kopfzeile, weil
   dort dieselbe Zeichnung liegt. */
.intro {
  position: fixed;
  inset: 0;
  z-index: 26;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.intro[hidden] { display: none; }

.intro__marke {
  position: relative;
  width: min(78vw, 52rem);
  aspect-ratio: 1082.54 / 215.13;
  transform-origin: 50% 50%;
  will-change: transform;
}

.intro__teil {
  position: absolute;
  top: 0;
  height: auto;
  opacity: 0;
  filter: blur(20px);
}

.intro__teil--con  { left: 0;      width: 33.63%; }
.intro__teil--sono { left: 33.72%; width: 66.28%; }

.intro__teil--an {
  opacity: 1;
  filter: blur(0);
  transition: opacity 0.95s var(--ease), filter 0.95s var(--ease);
}

/* Solange die Eröffnung läuft, steht die Seite still — der erste Scrollversuch
   ist die Geste, die das Zeichen nach oben schickt, und soll nicht nebenbei
   schon die Seite verschieben. */
html.halt { overflow: hidden; }
html.halt body { touch-action: none; }

/* Während der Eröffnung ist die Marke in der Kopfzeile unsichtbar; danach
   setzt das Skript ihre Deckkraft je nach Scrollwert. */
body[data-intro="ja"] .mark { opacity: 0; }

body[data-intro="ja"] .plane > .stack,
body[data-intro="ja"] .plane > :not(.ink):not(.loop):not(.heading) { opacity: 0; }

body[data-intro="fertig"] .plane > .stack,
body[data-intro="fertig"] .plane > :not(.ink):not(.loop):not(.heading) {
  opacity: 1;
  transition: opacity 0.7s var(--ease);
}

/* Für Vorleseprogramme da, für das Auge nicht. Nicht display:none — das
   nähme es auch dem Vorleseprogramm weg. */
.nur-vorlesen {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------ Startseite */

.prose--klein {
  position: relative;
  z-index: 1;
  margin-top: clamp(1.6rem, 4vh, 2.8rem);
}

.prose--klein a {
  display: inline-flex;
  align-items: center;
  padding: 0.7rem 1.5rem;
  border: 0;
  border-radius: 999px;
  background: var(--bone);
  color: var(--ink);
  text-decoration: none;
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}

.prose--klein a:hover { background: var(--blue); color: var(--bone); }

/* Der Knopf je Termin — dieselbe Form wie „Tickets sichern", nur kleiner. */
.mehr {
  justify-self: end;
  align-self: center;
  display: inline-flex;
  align-items: center;
  padding: 0.7rem 1.5rem;
  border: 0;
  border-radius: 999px;
  background: var(--bone);
  color: var(--ink);
  text-decoration: none;
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}

.mehr:hover { background: var(--blue); color: var(--bone); }

/* Auf der Ticketebene steht der Knopf im Bild statt zu schweben — der
   schwebende tritt dort zurück, sobald das Verzeichnis aufliegt. */
.ticketzeile { margin: clamp(1.8rem, 5vh, 3.2rem) 0 0; }
.mehr--gross { padding: 0.95rem 1.9rem; font-size: 0.82rem; }
.mehr:focus-visible { outline: 2px solid var(--bone); outline-offset: 4px; }

/* ----------------------------------------------------- Menükarten */

.menu .menu__auf {
  justify-self: center;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--font);
  font-size: clamp(1.8rem, 6vw, 3.6rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--bone);
  transition: color 0.3s var(--ease);
}

.menu .menu__auf:hover { color: #6d8ede; }
.menu .menu__auf[aria-expanded="true"] { color: #6d8ede; }

.karten {
  display: grid;
  gap: 0.9rem;
  justify-items: center;
  margin: 0.4rem 0 0.2rem;
}

.karten[hidden] { display: none; }

.menu .karte {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.9rem;
  padding: 0.75rem 1.7rem;
  min-width: min(20rem, 76vw);
  border: 0;
  border-radius: 999px;
  background: var(--bone);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}

.menu .karte:hover { background: var(--blue); color: var(--bone); }
.menu .karte:focus-visible { outline: 2px solid var(--bone); outline-offset: 4px; }

.karte__name { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
.karte__wann { font-size: 0.82rem; letter-spacing: 0.06em; opacity: 0.72; }

/* ------------------------------------------------------- Fußzeile */

/* Das Verzeichnis der Seite, in Spalten mit Einträgen untereinander. Auf den
   Ebenenseiten liegt es fest am unteren Rand, ist aber erst da, wenn man ganz
   unten angekommen ist — vorher wäre es ein Balken, der ständig mitfährt.
   Auf den Leseseiten steht es einfach am Ende des Textes. */
.fuss {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 22;
  background: var(--blue);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity 0.45s var(--ease), transform 0.45s var(--ease), visibility 0.45s;
}

body[data-fuss="an"] .fuss { opacity: 1; visibility: visible; transform: none; }

/* Solange das Verzeichnis liegt, tritt der schwebende Knopf zur Seite —
   auf der letzten Ebene ist das Ticket ohnehin das Thema der Seite. */
body[data-fuss="an"] .aktionen { opacity: 0; pointer-events: none; }

.fuss__innen {
  display: flex;
  flex-wrap: wrap;
  align-items: start;
  gap: clamp(1.6rem, 5vw, 4.5rem);
  padding: clamp(1.4rem, 3.5vh, 2.4rem) var(--gutter);
  margin-inline: auto;
  max-width: 88rem;
}

.fuss__spalte { display: grid; gap: 0.35rem; align-content: start; }

/* Instagram steht als Letztes ganz aussen — der freie Platz sammelt sich
   davor, nicht dahinter. */
.fuss__spalte--ende { margin-left: auto; }

@media (max-width: 720px) {
  .fuss__spalte--ende { margin-left: 0; }
}

.fuss__titel {
  margin: 0 0 0.25rem;
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: rgba(242, 239, 231, 0.5);
}

.fuss a {
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  color: rgba(242, 239, 231, 0.8);
  text-decoration: none;
  transition: color 0.3s var(--ease);
}

.fuss a:hover { color: var(--bone); }
.fuss a:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }

.fuss__ig { display: inline-flex; align-items: center; gap: 0.45rem; }
.fuss__ig svg { width: 1.05rem; height: 1.05rem; flex: none; }

/* Auf den Leseseiten fließt es mit und braucht keinen Schalter. */
.page .fuss {
  position: static;
  opacity: 1;
  visibility: visible;
  transform: none;
  margin-top: clamp(3rem, 9vh, 6rem);
}

@media (max-width: 640px) {
  .fuss__innen { gap: 1.4rem 2.6rem; padding-block: 1.2rem; }
  .fuss a { font-size: 0.8rem; }
}

.aktionen { bottom: clamp(1.2rem, 3.5vh, 2.6rem); transition: opacity 0.35s var(--ease); }
.tickets { transition: background 0.35s var(--ease), color 0.35s var(--ease), box-shadow 0.35s var(--ease); }

/* --------------------------------------------------- Partnerrollen */

.partner { display: grid; justify-items: center; gap: clamp(0.9rem, 2.4vh, 1.4rem); }

.partner__rolle {
  margin: 0;
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: rgba(242, 239, 231, 0.45);
}

/* ---------------------------------------------------------------- Unterseiten */

/* Seiten, die gelesen statt durchfahren werden: kein fester Ausschnitt,
   keine Tiefenmechanik, normaler Fluss. */
.page { scroll-snap-type: none; }
html:has(.page) { scroll-snap-type: none; }

.sheet {
  max-width: 62rem;
  margin: 0 auto;
  padding: max(7rem, 16vh) var(--gutter) 10rem;
  display: grid;
  gap: clamp(3rem, 9vh, 6rem);
}

.sheet__head { position: relative; display: grid; justify-items: start; }

.sheet__ink {
  position: absolute;
  left: -30%;
  top: 12%;
  width: 150%;
  max-width: none;
  pointer-events: none;
  z-index: -1;
}

.sheet__ink--low { top: auto; bottom: -14%; left: -26%; width: 146%; }

.sheet__title {
  font-size: clamp(2.6rem, 9vw, 6rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 0.9;
  margin: 0 0 clamp(1.2rem, 3vh, 2rem);
}

.team { display: grid; gap: clamp(2.5rem, 7vh, 4.5rem); }

.member {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: clamp(1.4rem, 4vw, 3rem);
}

.member--right { direction: rtl; }
.member--right > * { direction: ltr; }
.member--right > div:last-child { text-align: right; }
.member--right .artist__foot { justify-content: flex-end; }
.member--right .member__bio { margin-left: auto; }

.member .artist__portrait { width: clamp(6rem, 13vw, 10rem); }

/* Danach, nicht davor: die Zeile darüber ist gleich stark gewichtet, also
   entscheidet die Reihenfolge — und Marikos Bild hat vorher verloren.
   Sie trägt die Reihe, ihr Bild ist gross und quadratisch; Catharina steht
   daneben, nicht dagegen: kleiner und weiterhin rund. */
.member .artist__portrait--gross {
  width: clamp(12rem, 30vw, 24rem);
  border-radius: 2px;
}

.member .artist__portrait--klein { width: clamp(3.4rem, 6vw, 5rem); }

.member--haupt { align-items: start; gap: clamp(1.6rem, 4.5vw, 3.4rem); }

@media (max-width: 720px) {
  .member .artist__portrait--gross { width: min(78vw, 22rem); }
}

.member__bio {
  font-size: 1rem;
  line-height: 1.6;
  color: rgba(242, 239, 231, 0.72);
  margin: 0 0 1.1rem;
  max-width: 44ch;
}

.roster { position: relative; }

/* Ohne Abstand zwischen den Einträgen lief die letzte Zeile des einen in die
   Rolle des nächsten — auf dem Handy, wo alles untereinander steht, war das
   nicht mehr als Liste zu lesen. */
.roster__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(1.1rem, 2.6vh, 1.9rem);
}

.roster__list li {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(0.8rem, 3vw, 2rem);
}

.roster__role {
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  color: rgba(242, 239, 231, 0.5);
}

.roster__name {
  font-size: clamp(1.1rem, 2.2vw, 1.6rem);
  font-weight: 500;
  letter-spacing: -0.015em;
}

.roster__link {
  font-size: 0.85rem;
  color: rgba(242, 239, 231, 0.68);
  text-decoration: none;
  border-bottom: 1px solid rgba(242, 239, 231, 0.25);
  padding-bottom: 0.15rem;
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
  white-space: nowrap;
}

.roster__link:hover { color: var(--bone); border-color: var(--bone); }

/* Ein Logo statt einer Adresse: dann keine Unterstreichung, die säße unter
   dem Bild statt unter einem Wort. */
.roster__link--logo { border-bottom: 0; padding-bottom: 0; }
.roster__link--logo img { height: 1.5rem; width: auto; opacity: 0.8; transition: opacity 0.3s var(--ease); }
.roster__link--logo:hover img { opacity: 1; }

.sheet__foot { display: grid; gap: 0.6rem; }
.sheet__foot a { color: inherit; text-decoration: none; border-bottom: 2px solid rgba(242, 239, 231, 0.3); }
.sheet__foot a:hover { border-color: var(--bone); }

@media (max-width: 720px) {
  .member { grid-template-columns: 1fr; justify-items: start; }
  .member--right { direction: ltr; }
  .member--right > div:last-child { text-align: left; }
  .member--right .artist__foot { justify-content: flex-start; }

/* Rolle und Name spiegeln mit, der Fließtext nicht: zwanzig Zeilen
   rechtsbündiger Flattersatz sind spürbar mühsamer zu lesen, und der Spiegel
   liest sich auch ohne ihn — über die Seite des Porträts. */
.member--right .member__bio { text-align: left; }
.member__bio { max-width: 58ch; }
.member--right .member__bio { margin-left: auto; }

  .member--right .member__bio { margin-left: 0; }
  .roster__list { gap: clamp(1.7rem, 4.2vh, 2.6rem); }
  /* start statt stretch: sonst wird der Link so breit wie die Spalte und seine
     Unterstreichung zieht sich als Strich über die ganze Seite. */
  .roster__list li {
    grid-template-columns: 1fr;
    gap: 0.3rem;
    justify-items: start;
  }
}

/* ---------------------------------------------------------------- Partner */

.partners {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(2rem, 6vw, 4.4rem);
  margin-top: clamp(2.4rem, 6vh, 4rem);
}

/* Die drei Logos haben sehr verschiedene Seitenverhältnisse (3,4 : 1 bis
   4,5 : 1). Gleiche Höhe ließe das breiteste doppelt so groß wirken, deshalb
   ist die Höhe je Logo optisch angeglichen statt rechnerisch gleich. */
.partners__logo {
  width: auto;
  opacity: 0.8;
  transition: opacity 0.3s var(--ease);
}

.partners__logo--kahan { height: clamp(3.2rem, 7vh, 5rem); }
.partners__logo--tu    { height: clamp(3.4rem, 7.4vh, 5.2rem); }
.partners__logo--zr    { height: clamp(2.6rem, 5.6vh, 4rem); }

.partners a:hover .partners__logo { opacity: 1; }

.partners__slot {
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  color: rgba(242, 239, 231, 0.55);
  padding: 0.7rem 1.1rem;
  border: 1px dashed rgba(242, 239, 231, 0.22);
  border-radius: 2px;
}

