:root{
  --bg:#16100c; --text:#f0e6da; --text-muted:rgba(240,230,218,.72);
  --accent:#d9481f; --accent-contrast:#17120a; --accent-text:#d9481f;
  --accent-2:#e0a049; --accent-2-text:#e0a049; --accent-display:#d9481f; --accent-2-display:#e0a049;
  --border:rgba(240,230,218,.16);
  --font-display:'Newsreader', Georgia, serif;
  --font-body:'Work Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --shell: 1180px;
}

*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
/* Drei Ebenen, die sich im Ton staffeln: das Stück selbst in der reinen
   --bg, die Seite drumherum eine Stufe abgesetzt, das Menü darüber noch
   eine. So liest sich das Menü als Schicht ÜBER dem Inhalt, statt mit ihm
   zu verschwimmen – und der Rahmen um jedes Stück bekommt eine sichtbare
   Grenze, auch wenn seine Akzentfarbe gerade blass ausfällt.

   Abgesetzt heißt im Lightmode heller, im Darkmode dunkler, jeweils
   ausgehend vom --bg des fokussierten Stücks, das beim Scrollen laufend
   überblendet. Vor dem ersten JS-Lauf greift prefers-color-scheme als
   Rückfall, danach übernimmt body[data-mode] – nur das kennt auch den
   manuellen Umschalter, den die Media Query nicht mitbekommt. */
:root{ --misch:black; }   /* Richtung, in die abgesetzte Flächen gehen */
@media (prefers-color-scheme: light){
  :root{ --misch:white; }
}
:root[data-mode="light"], body[data-mode="light"]{ --misch:white; }
:root[data-mode="dark"], body[data-mode="dark"]{ --misch:black; }

body{
  /* Die beiden Mischungen gehören auf dasselbe Element wie --misch, nicht
     auf :root: eine Custom Property wird dort aufgelöst, wo sie DEKLARIERT
     ist. Auf :root deklariert, läse sie weiter das --misch von :root – also
     die Systemeinstellung – und der manuelle Umschalter am body ginge ins
     Leere. Im Darkmode wurde die Fläche dadurch heller statt dunkler. */
  --bg-seite:color-mix(in srgb, var(--bg) 88%, var(--misch));
  --bg-menue:color-mix(in srgb, var(--bg) 80%, var(--misch));

  margin:0; background:var(--bg-seite); color:var(--text);
  font-family:var(--font-body); line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{ max-width:100%; display:block; }
a{ color:inherit; }
button{ font-family:inherit; cursor:pointer; }
h1,h2,h3{ font-family:var(--font-display); font-weight:500; margin:0; line-height:1.14; }
p{ margin:0; }
.u-container{ max-width:var(--shell); margin:0 auto; padding:0 clamp(1.15rem,4vw,3rem); }
:focus-visible{ outline:3px solid var(--accent-display); outline-offset:3px; border-radius:1px; }

.u-visually-hidden{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
.skip-link{
  position:absolute; left:1rem; top:-4rem; z-index:100;
  background:var(--knopf, var(--accent)); color:var(--knopf-text, var(--accent-contrast));
  padding:.8rem 1.3rem; border-radius:2px; text-decoration:none; font-weight:500;
  transition:top .25s ease;
}
.skip-link:focus{ top:1rem; }

/* Nur beim Light/Dark-Wechsel überblenden. Beim Scrollen bewusst keine
   Transition – dort setzt JS die Farben pro Frame, eine Transition
   würde hinterherhinken. */
body.is-mode-switching,
body.is-mode-switching .site-nav,
body.is-mode-switching .act{
  transition: background-color .45s ease, color .45s ease, border-color .45s ease;
}

/* ---------------- Navigation ----------------
   Zwei Ebenen: oben, was von dieser Seite wegführt (Inhaltsseiten,
   Farbmodus), darunter die Zeitleiste, die innerhalb der Seite springt.
   Der Unterschied ist keine Kosmetik – ein Klick auf „Ensemble“ lädt eine
   neue Seite, ein Klick auf „2019“ scrollt nur. Wenn beides gleich
   aussieht, ist die Erwartung beim Klicken nicht gedeckt. */
.site-nav{
  position:sticky; top:0; z-index:60;
  background:color-mix(in srgb, var(--bg-menue) 92%, transparent);
  backdrop-filter:blur(12px);
  border-bottom:1px solid var(--border);
  /* Der Schatten kommt erst beim Scrollen dazu (is-scrolled, aus dem JS):
     ganz oben liegt die Leiste ruhig auf, sobald Inhalt darunter
     durchläuft, hebt sie sich sichtbar ab. */
  transition:box-shadow .3s ease;
}
body.is-scrolled .site-nav{
  box-shadow:0 .6rem 1.4rem -0.9rem rgba(0,0,0,.55);
}
/* Das Logo liegt frei über beiden Zeilen (siehe .site-nav__brand), ist also
   kein Flex-Kind mehr. Deshalb flex-end statt space-between: sonst rutscht
   der verbliebene Inhalt an den linken Rand, unter das Logo. */
.site-nav__inner{
  display:flex; align-items:center; justify-content:flex-end;
  gap:.8rem; padding:0 clamp(1rem,4vw,3rem); flex-wrap:wrap;
}
.site-nav__zeitleiste .site-nav__inner{ justify-content:flex-start; }
.site-nav__haupt .site-nav__inner{ padding-block:.7rem; }
/* Inhaltsseiten und Moduswechsel gehören zusammen und stehen gemeinsam
   der Marke gegenüber – sonst verteilt space-between sie über die ganze
   Breite und die Gruppe zerfällt. */
.site-nav__rechts{
  display:flex; align-items:center; gap:clamp(.5rem,1.4vw,.9rem); flex-wrap:wrap;
}
/* Die Marke sitzt frei über BEIDEN Zeilen, statt eine davon in die Höhe zu
   treiben: aus dem Fluss genommen und links über Haupt- und Zeitleiste
   gelegt. Die beiden Zeilen halten per padding-inline-start den Platz frei,
   ihre Flächen laufen darunter durch.

   Die Breite ist fest, nicht gerechnet: Schriftzug und Zeichen sind
   gesetzt und ändern ihre Maße nicht mehr – anders als früher, als hier
   ein beliebig proportioniertes Logo hochgeladen werden konnte. */
.site-nav{
  --logo-rand:clamp(1rem,4vw,3rem);
  --kopf-breite:9.2rem;
}
/* Ohne Zeichen bleibt nur der Schriftzug, die Zeilen rücken nach. */
.site-nav--ohne-zeichen{ --kopf-breite:7.6rem; }

.site-nav__brand{
  position:absolute; z-index:3;
  left:var(--logo-rand); top:50%; transform:translateY(-50%);
  display:flex; align-items:center;
  text-decoration:none; line-height:0;
}
.site-nav__schriftzug{
  font-family:var(--font-display); font-style:italic; font-size:1.3rem;
  line-height:1.2; white-space:nowrap; color:var(--text);
}
.site-nav__schriftzug span{ color:var(--accent-display); font-style:normal; }
/* Das Zeichen färbt sich über currentColor mit dem Text um und braucht
   deshalb keine zweite Fassung für den Dunkelmodus.

   Der negative Einzug ist kein Kniff, sondern Ausgleich: Die Kegel laufen
   nach oben schmal zu, auf Schrifthöhe beginnt der kräftige erst bei gut
   einem Drittel der Bildbreite. Ein positiver Abstand addiert sich zu
   diesem unsichtbaren Vorlauf – Zeichen und Schriftzug fielen dann
   auseinander, obwohl im CSS wenig Abstand steht. Ein negativer gap ginge
   nicht: Flexbox verwirft negative Werte stillschweigend. */
.site-nav__zeichen{
  display:block; flex-shrink:0; width:auto; height:1.85rem;
  margin-left:-.2rem;
  color:var(--text); transition:height .3s ease;
}
/* Der Platz, den die Zeilen links frei lassen. */
.site-nav__inner{
  padding-inline-start:calc(var(--logo-rand) + var(--kopf-breite) + clamp(.8rem,2vw,1.6rem));
  transition:padding-inline-start .3s ease;
}

@media (prefers-reduced-motion: reduce){
  .site-nav__zeichen,
  .site-nav__inner{ transition:none; }
}

/* Die Zeitleiste: flacher, ruhiger und eine Spur tiefer im Ton als die
   Hauptzeile – sie ist Orientierung, nicht Hauptweg. */
.site-nav__zeitleiste{
  background:color-mix(in srgb, var(--bg) 55%, transparent);
  border-top:1px solid color-mix(in srgb, var(--border) 60%, transparent);
}
.site-nav__zeitleiste .site-nav__inner{ padding-block:.1rem; flex-wrap:nowrap; }

/* Abstand zwischen der sticky Nav und dem ersten Stück – ohne den klebt
   dessen Rahmen Linie an Linie unter der Nav-Trennlinie. */
#app{ padding-top:clamp(1.2rem,3vw,2.2rem); }

/* 14 Jahreszahlen passen nicht in eine Zeile. Auf schmalen Schirmen
   deshalb eine wischbare Leiste – anders als bei der Galerie ist das
   hier vertretbar: eine Navigationsleiste ist ein bekanntes Muster und
   verbirgt keine Inhalte, sondern nur Sprungziele.

   Die scrollende Fläche ist ein eigenes Element (.year-nav-scroll), nicht
   die Liste selbst: der Unterstrich unten sitzt als ein einzelnes Element
   daneben und wird zur aktiven Jahreszahl hin verschoben statt neu
   gezeichnet zu werden – dafür braucht er einen Bezugsrahmen, der beim
   Neuaufbau der Liste (build() ersetzt deren innerHTML bei jedem
   Farbmodus-Wechsel) nicht mit verschwindet. */
.year-nav-scroll{
  position:relative; overflow-x:auto; scrollbar-width:none; max-width:100%;
}
.year-nav-scroll::-webkit-scrollbar{ display:none; }
.year-nav{
  display:flex; align-items:center; gap:clamp(.55rem,1.5vw,1.25rem);
  list-style:none; margin:0; padding:.15rem .1rem;
}
.year-nav li{ flex:0 0 auto; }
/* Kleiner und ruhiger als die Schaltflächen darüber: die Zeitleiste zeigt,
   wo man gerade ist, und drängt sich nicht als Hauptweg auf. Die
   Ziffernbreite fixieren, damit der wandernde Marker nicht bei jedem Jahr
   eine andere Breite annimmt. */
.year-nav a{
  display:flex; align-items:center; justify-content:center;
  text-decoration:none; font-size:.8rem; color:var(--text-muted);
  padding:0 .3rem; position:relative; white-space:nowrap;
  font-variant-numeric:tabular-nums;
  transition:color .3s ease;
}
.year-nav a{ min-height:34px; min-width:34px; }
/* Am Finger bekommen alle Bedienelemente der Leiste die vollen 44px
   Trefferfläche. Eine Jahreszahl ist nur gut 30px breit, der Moduswechsel
   ohne Beschriftung noch kleiner – danebentippen und im falschen Jahrgang
   landen ist sonst leicht passiert. Am Mauszeiger bleibt alles flach.
   Bewusst echte Größe statt eines vergrößernden Pseudo-Elements: die
   Jahreszahlen stehen dicht beieinander, unsichtbar überlappende
   Trefferflächen würden die Fehlgriffe nur verlagern. */
@media (pointer:coarse){
  .year-nav a{ min-height:44px; min-width:44px; padding:0 .45rem; }
  .page-nav a,
  .site-nav__mode{ min-height:44px; }
  .site-nav__mode{ min-width:44px; justify-content:center; }
}
.year-nav a:hover{ color:var(--text); }
.year-nav a.is-active{ color:var(--text); font-weight:500; }

/* Wandert zur aktiven Jahreszahl, statt zwischen Positionen zu springen.
   left bleibt 0; die eigentliche Position kommt per transform aus dem
   JavaScript (moveIndicator) – das ist die güngstigere Eigenschaft für
   eine Animation, die bei jedem Scroll-Frame erneut anlaufen kann. Genauer:
   die günstigere Eigenschaft, weil sie kein Layout neu berechnet. */
.year-nav-indicator{
  position:absolute; left:0; bottom:1px; height:2px; width:0;
  background:var(--accent-display);
  transition:transform .4s cubic-bezier(.65,0,.35,1), width .4s cubic-bezier(.65,0,.35,1);
  pointer-events:none;
}
@media (prefers-reduced-motion: reduce){
  .year-nav-indicator{ transition:none; }
}
/* Links zu den Inhaltsseiten. Kommen aus dem Redaktionsbereich und werden
   serverseitig gesetzt – anders als die Jahresliste, die das Frontend-Skript
   aufbaut. Als umrandete Schaltflächen gesetzt, in derselben Pillenform wie
   der Moduswechsel: vorher hatten sie exakt dieselbe Schriftgröße wie die
   Jahreszahlen und standen in derselben Reihe – „Ensemble“ las sich dadurch
   wie ein weiterer Jahrgang statt wie ein eigener Ort. */
.page-nav{
  display:flex; align-items:center; gap:.45rem;
  list-style:none; margin:0; padding:0; flex-wrap:wrap;
}
.page-nav a{
  display:inline-flex; align-items:center;
  text-decoration:none; font-size:.88rem; font-weight:500; color:var(--text);
  padding:.35rem .9rem; white-space:nowrap;
  border:1px solid var(--border); border-radius:999px;
  transition:color .3s ease, border-color .3s ease, background-color .3s ease;
}
.page-nav a:hover{ color:var(--accent-text); border-color:var(--accent-display); }
/* Die aktive Seite ist gefüllt statt unterstrichen: bei einer Pillenform
   liegt ein Unterstrich seltsam unter der Rundung. */
.page-nav a.is-active{
  background:var(--knopf, var(--accent)); color:var(--knopf-text, var(--accent-contrast)); border-color:var(--knopf, var(--accent));
}
.page-nav a.is-active:hover{ color:var(--knopf-text, var(--accent-contrast)); }

.site-nav__actions{ display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; }
.site-nav__mode,
.site-nav__demo{
  border:1px solid var(--border); background:transparent;
  border-radius:999px; transition:border-color .3s ease, color .3s ease;
}
.site-nav__mode{
  display:inline-flex; align-items:center; gap:.4rem;
  color:var(--text); padding:.35rem .8rem; font-size:.8rem;
}
.site-nav__demo{ color:var(--text-muted); padding:.35rem .75rem; font-size:.74rem; }
.site-nav__mode:hover,
.site-nav__demo:hover{ border-color:var(--accent-display); color:var(--accent-text); }
.site-nav__demo.is-on{ background:var(--knopf, var(--accent)); color:var(--knopf-text, var(--accent-contrast)); border-color:var(--knopf, var(--accent)); }

/* Auf kleinen Schirmen bleiben nur Menü und Farbmodus neben der Marke. */
.site-nav__menu-toggle{
  display:inline-flex; align-items:center; justify-content:center; gap:.55rem;
  min-height:44px; padding:.4rem .85rem; border:1px solid var(--border);
  border-radius:999px; background:transparent; color:var(--text);
  font:inherit; font-size:.85rem; cursor:pointer;
}
.site-nav__mode[hidden], .site-nav__menu-toggle[hidden], .page-nav[hidden]{ display:none; }
.site-nav__menu-icon{ width:16px; height:12px; border-block:1.5px solid currentColor;
  position:relative; }
.site-nav__menu-icon::after{ content:''; position:absolute; left:0; right:0; top:50%;
  border-top:1.5px solid currentColor; transform:translateY(-50%); }
.site-nav__menu-toggle[aria-expanded="true"]{ background:var(--text); color:var(--bg); }
.site-nav__mode{ cursor:pointer; }

@media (max-width:880px){
  .site-nav__haupt{ position:relative; }
  .site-nav__inner{ padding-inline:1rem; }
  .site-nav__haupt .site-nav__inner{
    padding-block:.6rem; justify-content:space-between; gap:.75rem; min-height:64px;
  }
  .site-nav__brand{ position:static; transform:none; flex:0 1 auto; min-width:0; }
  .site-nav__schriftzug{ font-size:1.12rem; }
  .site-nav__rechts{ gap:.5rem; min-width:0; }
  .site-nav__actions{ flex-wrap:nowrap; flex-shrink:0; }
  .site-nav__mode{
    width:44px; height:44px; min-width:44px; min-height:44px;
    padding:0; gap:0; justify-content:center; font-size:1.2rem;
  }
  .site-nav__mode #mode-label{
    position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip-path:inset(50%); white-space:nowrap;
  }
  .site-nav__demo{ display:none; }
  .site-nav__zeitleiste .site-nav__inner{ padding-inline:1rem; }
  .has-mobile-menu .site-nav__inner, .has-mobile-menu .site-nav__rechts{ flex-wrap:nowrap; }
  .has-mobile-menu .page-nav{
    position:absolute; z-index:5; top:100%; left:1rem; right:1rem;
    display:flex; flex-direction:column; align-items:stretch; gap:.25rem;
    padding:.5rem; max-height:min(65svh,28rem); overflow-y:auto; overscroll-behavior:contain;
    background:var(--bg); border:1px solid var(--border); border-radius:12px;
    box-shadow:0 .8rem 2rem rgba(0,0,0,.2);
  }
  .has-mobile-menu .page-nav[hidden]{ display:none; }
  .page-nav a{ white-space:normal; overflow-wrap:anywhere; }
  .has-mobile-menu .page-nav a{
    display:flex; min-height:44px; width:100%; padding:.65rem .85rem;
    border-radius:7px; border-color:transparent; font-size:.95rem;
  }
}

/* ---------------- Buttons ---------------- */
.btn{
  display:inline-flex; align-items:center; gap:.5rem;
  padding:.8rem 1.5rem; border-radius:2px; font-size:.94rem; font-weight:500;
  text-decoration:none; border:1px solid transparent;
  transition:transform .25s ease, border-color .3s ease;
}
.btn--primary{ background:var(--knopf, var(--accent)); color:var(--knopf-text, var(--accent-contrast)); }
.btn--primary:hover{ transform:translateY(-2px); }
.btn--ghost{ border-color:var(--accent-2-display); color:var(--accent-2-text); }
.btn--ghost:hover{ border-color:var(--accent-display); color:var(--accent-text); }
@media (max-width:480px){
  .btn{ width:100%; justify-content:center; }
}

/* ---------------- Bühne ----------------
   Auf breiten Schirmen eingefasst statt randlos: über die volle Breite
   wirkt ein Bühnenbild wie ein Werbebanner, nicht wie eine Bühne.
   svh statt vh, weil vh auf Mobilgeräten die ein- und ausblendende
   Browserleiste ignoriert und die Bühne dadurch überläuft. */
/* Auf breiten Schirmen bekommt jedes Stück eine eigene Umrandung – Foto
   und Text als ein Rahmen, statt als loses Aneinanderreihen. Auf schmalen
   Schirmen bewusst randlos: eine Umrandung, die die Seite kaum breiter ist
   als der Bildschirm, wirkt dort nicht wie ein Rahmen, nur wie ein
   Reinschneiden in den Bildschirmrand. */
.act{ position:relative; z-index:1; }
@media (min-width:1100px){
  .act{
    max-width:1560px; margin-inline:auto;
    /* Die Akzentfarbe des Stücks statt der allgemeinen, sehr blassen
       --border-Variable: die ist für feine UI-Trennlinien gedacht, nicht
       für einen Rahmen, der auch gesehen werden soll. --stueck-akzent
       kommt als Inline-Variable vom JavaScript und ist fest – anders als
       --accent-display, die beim Scrollen laufend überblendet wird und
       sonst allen Rahmen gleichzeitig die Farbe der Sektion gäbe, die
       gerade im Fokus steht. Ohne JavaScript (Rückfall-Fassung) greift
       die zweite Alternative. */
    border:1.5px solid color-mix(in srgb, var(--stueck-akzent, var(--accent-display)) 38%, transparent);
    border-radius:10px;
    overflow:hidden;
    /* Innerhalb des Rahmens die reine --bg, unabhängig vom aufgehellten/
       abgedunkelten Seitenhintergrund außerhalb (siehe body oben). */
    background:var(--bg);
  }
}
/* Bühne als Spalte: Foto oben, Textblock darunter – beide im normalen
   Fluss. Vorher lag das Foto absolut positioniert hinter dem Text; wie
   viel Platz unten frei bleiben musste, war geraten und kippte bei
   langen Titeln oder flachen Fenstern. Jetzt kann sich das gar nicht
   mehr überlappen. Oben bleibt Raum für die Jahreszahl in der Ecke. */
.act__stage{
  position:relative; display:flex; flex-direction:column; justify-content:flex-end;
  overflow:hidden; min-height:74svh; background:var(--bg);
  padding-top:clamp(3.6rem,6.5vw,5.8rem);
}
.act__stage::before{
  content:''; position:absolute; inset:0;
  background:
    radial-gradient(120% 80% at 50% 0%, color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 62%),
    linear-gradient(180deg, transparent 55%, color-mix(in srgb, var(--bg) 92%, transparent) 100%);
}
.act--hero .act__stage{ min-height:90svh; }
@media (min-width:1100px){
  /* Breite und Rahmen kommen jetzt von .act – die Bühne füllt darin nur
     noch die Höhe. */
  .act__stage{ min-height:78svh; }
  .act--hero .act__stage{ min-height:88svh; }
}
@media (max-width:640px){
  .act__stage{ min-height:60svh; }
  .act--hero .act__stage{ min-height:80svh; }
}
/* Das Foto sitzt kleiner und gerahmt in der Bühne statt randlos –
   sonst verdeckt es die Lichtstrahlen vollständig. Festes
   Seitenverhältnis mit Höhendeckel: ohne das bestimmt die natürliche
   Bildhöhe den Rahmen, und ein hochformatiges Foto schiebt den Titel
   unter den sichtbaren Bereich. */
.act__media{
  position:relative; flex:0 1 auto;
  aspect-ratio:16/9; max-height:40svh; min-height:16svh;
  margin:0 clamp(1.6rem,8vw,5rem);
  border-radius:8px; overflow:hidden;
  box-shadow:0 1.6rem 3.5rem -1.4rem rgba(0,0,0,.45);
}
.act--hero .act__media{ max-height:42svh; }
@media (max-width:640px){
  /* 3/2 statt 4/3: der Redaktionsbereich lässt als Szenenbild nur noch
     Querformate ab 3:2 zu, ein höherer Rahmen würde sie seitlich
     beschneiden, ohne mehr Bild zu zeigen. */
  .act__media{ aspect-ratio:3/2; max-height:34svh; }
  .act--hero .act__media{ max-height:40svh; }
}
/* Der Bildausschnitt sitzt oberhalb der Mitte. Auf Theaterfotos stehen die
   Darsteller, die Gesichter liegen im oberen Drittel – ein mittiger
   Ausschnitt schneidet sie bei hohen Fotos ab und zeigt die Beine. Neue
   Szenenbilder sind zwar auf Querformat begrenzt, aber auch dort wird noch
   etwas beschnitten, und ältere Stücke haben ihr Bild bereits gesetzt. */
.act__media img{ width:100%; height:100%; object-fit:cover; object-position:50% 32%; }
.act__media::after{
  content:''; position:absolute; inset:0;
  background:linear-gradient(180deg, transparent 60%, rgba(0,0,0,.32) 100%);
}

/* ---- Gegenlicht: Strahlen über der Bühne ----
   Sie sitzen INNERHALB des Bühnenbildes, über dem Foto und unter dem
   Abdunkel-Verlauf (::after wird als Pseudo-Element nach allen Kindern
   gezeichnet). Eine bildschirmfüllende Lichtebene läge sonst genau
   hinter dem Fließtext und würde dessen Kontrast drücken.
   Kein blur(): die weichen Kanten kommen aus den Verläufen selbst. */
.stagelight{ position:absolute; inset:0; overflow:hidden; pointer-events:none; }
.ray{
  position:absolute; top:-60%; left:50%;
  width:38vmax; height:190%;
  transform-origin:50% 0; will-change:transform;
  clip-path:polygon(44% 0%, 56% 0%, 100% 100%, 0% 100%);
}
.ray--a{ background:linear-gradient(to bottom, var(--accent) 0%, transparent 82%); opacity:.52; }
.ray--b{ background:linear-gradient(to bottom, var(--accent-2) 0%, transparent 74%); opacity:.4; width:28vmax; }

.act__intro{ position:relative; z-index:1; flex:0 0 auto; width:100%; padding:clamp(1.6rem,4vw,2.8rem) 0 clamp(2.4rem,6vw,4rem); }
.act__eyebrow{
  font-size:clamp(.78rem,.9vw,.92rem); color:var(--accent-text);
  display:inline-flex; align-items:center; gap:.55rem; margin-bottom:.8rem; flex-wrap:wrap;
  letter-spacing:.04em; text-transform:uppercase;
}
/* Keine automatische Silbentrennung: ein Titel ist ein Name, und ein
   „Halbpen-sion“ mitten im Wort liest sich wie ein Satzfehler. Ganze
   Wörter wandern stattdessen in die nächste Zeile. hyphens:manual statt
   none, damit ein &shy; im Titel weiterhin greift, wenn die Redaktion
   bei einem sehr langen Wort selbst trennen will. overflow-wrap bleibt
   als Notnagel für Wörter, die allein breiter sind als die Spalte –
   sonst ragen die aus dem Rahmen.
   text-wrap:balance verteilt die Wörter gleichmäßig auf die Zeilen,
   statt eine volle Zeile und ein einzelnes Wort darunter zu setzen. */
/* Der Sprunglink setzt den Fokus auf <main>, damit die Navigation wirklich
   übersprungen wird. Ein Rahmen um den gesamten Inhaltsbereich wäre dabei
   aber nur verwirrend – die Sprungmarke ist kein Bedienelement. */
main:focus{ outline:none; }

.act__title{
  font-size:clamp(2rem,5.4vw,4.6rem); max-width:16ch; letter-spacing:-.01em;
  overflow-wrap:break-word; hyphens:manual; text-wrap:balance;
}
@media (max-width:640px){
  /* 16ch sind bei dieser Schriftgröße schmaler als die Spalte selbst und
     erzwingen Umbrüche, die auf dem Handy gar nicht nötig wären. */
  .act__title{ max-width:none; }
}
.act--past .act__title{ font-size:clamp(1.7rem,4.2vw,3.4rem); }
.act__lede{
  margin-top:1rem; max-width:46ch;
  font-size:clamp(.96rem,1.05vw,1.08rem); color:var(--text-muted);
}
/* Sitzt im Freiraum über dem Foto, nicht darauf. */
.act__year-mark{
  position:absolute; z-index:1; top:clamp(.7rem,1.8vw,1.5rem); right:clamp(1.6rem,8vw,5rem);
  font-family:var(--font-display); font-size:clamp(1.5rem,3.6vw,3.2rem);
  line-height:1.1;
  color:var(--accent-2-display); opacity:.9; letter-spacing:.02em;
}


/* ---------------- Bühne ohne Foto ----------------
   Fehlt ein Szenenbild, wird NICHT automatisch ein Ersatzbild
   eingesetzt. Ein Stück ohne Fotos soll nicht wirken, als sei die
   Seite kaputt, sondern als eigenständige, typografische Variante:
   Farbfläche, Lichtstrahlen und ein flächiger Titel. Gezeichnete
   Bühnenmotive gibt es weiterhin – aber nur, wenn sie pro Stück
   ausdrücklich angefordert werden (bilder.platzhalter). */
.act--past .act__stage--plain{ min-height:52svh; }
.act--hero .act__stage--plain{ min-height:76svh; }
@media (max-width:640px){
  .act--past .act__stage--plain{ min-height:46svh; }
}

/* Galerie ganz ohne Fotos: Abschnitt entfällt, kein Leerraum */
.act--nogallery .act__body{ padding-bottom:clamp(2.5rem,5vw,3.5rem); }


/* ---------------- Videos in der Galerie ---------------- */
.gallery__item{ margin:0; }
.gallery__item--video{ grid-column:span 2; }
@media (max-width:480px){ .gallery__item--video{ grid-column:span 2; } }
.gallery video{
  width:100%; height:auto; aspect-ratio:16/9; display:block;
  border-radius:3px; background:color-mix(in srgb, var(--text) 10%, transparent);
}
.gallery__item figcaption{
  margin-top:.4rem; font-size:.8rem; color:var(--text-muted);
}
.gallery__credit{
  font-size:.78rem; color:var(--text-muted);
  padding-bottom:clamp(2.5rem,5vw,3.5rem); margin-top:-.4rem;
}

/* ---- Verweis auf eine Galerieseite ----
   Unter den Fotos, in derselben Spalte wie sie. Ein Stück kann beides
   haben, nur Fotos, nur den Verweis oder keines von beidem – deshalb
   tragen Raster, Bildnachweis und Verweis den Fussabstand der Reihe nach
   nur dann, wenn sie das letzte Element sind. Sonst summierten sich drei
   Abstände übereinander. */
.act .gallery{ padding-bottom:0; }
.act .gallery:last-child{ padding-bottom:clamp(2.5rem,5vw,3.5rem); }
.gallery__credit:has(+ .gallery__seite){ padding-bottom:0; }
.gallery__seite{
  max-width:min(100%, 34rem);
  margin:.7rem 0 0; padding-bottom:clamp(2.5rem,5vw,3.5rem);
  font-size:.88rem;
}
.gallery__seite a{
  color:var(--accent-text); text-decoration:underline; text-underline-offset:.2em;
}
.gallery__seite a:hover{ text-decoration-thickness:2px; }

/* ---------------- Termine ---------------- */
.termine{ margin-top:1.6rem; padding:1rem 1.2rem; border:1px solid var(--border); border-radius:3px; }
.termine__head{ font-family:var(--font-display); font-size:1.05rem; font-weight:500; margin:0 0 .6rem; color:var(--text); }
.termine__list{ list-style:none; margin:0; padding:0; }
.termine__list li{
  display:flex; flex-wrap:wrap; gap:.3rem 1rem; align-items:baseline;
  padding:.55rem 0; border-bottom:1px solid var(--border); font-size:.9rem;
}
.termine__list li:last-child{ border-bottom:none; }
.termine__datum{ color:var(--accent-2-text); flex:1 1 100%; }
@media (min-width:560px){ .termine__datum{ flex:1 1 auto; } }
.termine__ort, .termine__preis{ color:var(--text-muted); font-size:.85rem; }

/* ---- Gemeinsamer Spielort ----
   Einmal über allen Terminen, deutlich statt klein und grau an jeder Karte.
   Gäste haben gemeldet, dass man die Adresse zu wenig sieht – sie stand an
   jedem Termin und ging gerade durch die Wiederholung unter. */
.termine__spielort{
  display:flex; align-items:flex-start; gap:.6rem;
  margin:0 0 .8rem; padding:.7rem .85rem;
  border-radius:4px;
  background:color-mix(in srgb, var(--text) 6%, transparent);
  border-left:3px solid var(--accent-text);
}
.termine__spielort-zeichen{ flex:0 0 auto; margin-top:.15rem; color:var(--accent-text); }
.termine__spielort-titel{
  display:block; font-size:.72rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--text-muted);
}
.termine__spielort-adresse{
  display:block; margin-top:.1rem;
  font-size:1.02rem; font-weight:500; color:var(--text); overflow-wrap:anywhere;
}
.termine__preis{ margin-left:auto; }
/* Link zum Spielort im Kartendienst (Einstellungen → Kartenlinks). Klein und
   in der lesbaren Akzentfarbe: ein Angebot neben der Adresse, nicht mit dem
   Reservieren-Knopf konkurrierend. */
.karte-link{
  display:inline-flex; align-items:center; gap:.25rem; min-height:24px;
  font-size:.82rem; color:var(--accent-text);
  text-decoration:underline; text-underline-offset:.2em; text-decoration-thickness:1px;
}
.karte-link:hover{ text-decoration-thickness:2px; }
.termine__spielort .karte-link{ margin-top:.3rem; }
.termine__kontakt{ margin-top:.7rem; font-size:.85rem; color:var(--text-muted); }
.termine__kontakt a{ color:var(--accent-text); }

/* ---------------- Textteil ---------------- */
.act__body{ padding:clamp(2.4rem,5vw,4rem) 0 clamp(.5rem,2vw,1.5rem); }
.act__body-inner{
  display:grid; grid-template-columns:minmax(0,1.3fr) minmax(0,.9fr);
  gap:clamp(1.8rem,4vw,3.5rem); align-items:start;
}
@media (max-width:900px){
  .act__body-inner{ grid-template-columns:1fr; gap:1.8rem; }
}
.act__story{ max-width:62ch; font-size:clamp(.98rem,1.05vw,1.06rem); color:var(--text-muted); }
.act__story p + p{ margin-top:1rem; }
.act__story h3{ font-size:1.2rem; color:var(--text); margin-bottom:.85rem; }


/* ---------------- Ensemble & Team als Ausklapper ----------------
   Native <details>: funktioniert mit Tastatur und Screenreader ohne
   eigenes JavaScript, und bleibt auch dann bedienbar, wenn Skripte
   scheitern. Auf großen Schirmen ist die Besetzung aufgeklappt
   vorgegeben, auf kleinen zugeklappt – dort kostet sie sonst
   zu viel Scrollweg. */
.act__aside{ display:flex; flex-direction:column; gap:.7rem; }

/* ---- Flyer / Plakat ----
   Bewusst schmal: Ein Flyer im Hochformat in voller Spaltenbreite wäre gut
   600 Pixel hoch und würde die Besetzung darunter aus dem Bild schieben –
   dieselbe Überschattung, die bei der Galerie schon zu viel war.

   Zwei Kopien im Markup, je eine pro Bildschirmbreite; die Grenze ist
   dieselbe, bei der Text und Besetzung untereinander rutschen (900px). */
.act__flyer{ margin:0; }
/* Block, nicht inline-block: Als inline-block richtete sich der Link in
   der Breite nach dem Bild und das Bild (width:100%) nach dem Link – eine
   Zirkelbeziehung, die auf null kollabierte. Gemessen 26 statt 430 Pixel
   Höhe, und ein Bild ohne Fläche lädt loading="lazy" nie nach. */
.act__flyer a{ display:block; border-radius:4px; line-height:0; }
.act__flyer img{
  display:block; width:100%; height:auto;
  border-radius:4px;
  box-shadow:0 6px 22px -10px rgba(0,0,0,.45);
}
.act__flyer a:focus-visible{ outline:2px solid var(--accent-text); outline-offset:3px; }
.act__flyer--desktop{ max-width:min(100%, 19rem); }
.act__flyer--mobil{ display:none; max-width:min(100%, 16rem); margin-bottom:1.4rem; }
@media (max-width:900px){
  .act__flyer--desktop{ display:none; }
  .act__flyer--mobil{ display:block; }
}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .act__flyer img{ transition:transform .25s ease; }
  .act__flyer a:hover img{ transform:translateY(-3px); }
}
.expander{
  border:1px solid var(--border); border-radius:4px;
  background:color-mix(in srgb, var(--text) 4%, transparent);
}
.expander > summary{
  list-style:none; cursor:pointer; padding:.85rem 1.1rem;
  display:flex; align-items:center; justify-content:space-between; gap:.8rem;
  font-family:var(--font-display); font-size:1.05rem;
  border-radius:4px;
}
.expander > summary::-webkit-details-marker{ display:none; }
.expander > summary:hover{ color:var(--accent-text); }
.expander__count{ font-family:var(--font-body); font-size:.76rem; color:var(--text-muted); }
.expander__chev{
  width:.6rem; height:.6rem; border-right:2px solid currentColor; border-bottom:2px solid currentColor;
  transform:rotate(45deg); transition:transform .25s ease; flex:0 0 auto; margin-left:auto;
}
.expander[open] > summary .expander__chev{ transform:rotate(225deg); }
.expander__body{ padding:0 1.1rem 1rem; }

.credit-list{ list-style:none; margin:0; padding:0; }
/* Umbruch erlauben: bei vergrößerter Schrift passen Name und Rolle nicht
   mehr nebeneinander, und ohne wrap schob die Rolle über den Rand hinaus –
   wo body{overflow-x:hidden} sie abgeschnitten hätte. */
.credit-list li{
  display:flex; justify-content:space-between; gap:.4rem 1rem; align-items:baseline;
  flex-wrap:wrap;
  padding:.6rem 0; border-bottom:1px solid var(--border);
}
.credit-list li:last-child{ border-bottom:none; }
.credit-list .name{ font-family:var(--font-display); font-size:1rem; color:var(--accent-2-text); }
.credit-list .role{ color:var(--text-muted); font-size:.85rem; text-align:right; }
.credit-note{ margin-top:.7rem; font-size:.8rem; color:var(--text-muted); font-style:italic; }

/* ---------------- Galerie ----------------
   Kein horizontales Scrollen mehr: ein Seitwärts-Container in einer
   vertikal scrollenden Seite schluckt auf Touchgeräten die Wischgeste
   und versteckt Fotos außerhalb des Sichtfelds. Stattdessen ein
   Raster. Gezeigt werden auf Anhieb höchstens vier Bilder – bei einem
   Jahrzehnt an Stücken wäre eine ganze Wand an Fotos pro Stück schnell
   erschlagend; der Rest liegt hinter der Kachel .gallery-mehr. */
.gallery{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap:clamp(.45rem,1.2vw,.9rem);
  padding:clamp(.8rem,2vw,1.4rem) 0 clamp(2.8rem,6vw,4.5rem);
}
.gallery img{
  width:100%; height:100%; aspect-ratio:4/3; object-fit:cover;
  border-radius:6px;
}

/* ---- Bühnengalerie: Leitbild und Streifen ----
   Breite an der Textspalte, nicht am Seitenrand: Über die volle Breite war
   das Leitbild höher als das Szenenbild des Stücks selbst – die Beigabe
   überstrahlte den Inhalt.

   Fluss statt Raster: In einem Raster mit fester Spaltenzahl geht die letzte
   Reihe nur bei passender Bildanzahl auf; beim Aufklappen der versteckten
   Fotos ändert sich diese Zahl aber. Im Fluss wächst die letzte Reihe auf
   volle Breite mit, egal wie viele Bilder dazukommen. */
.act .gallery{
  display:flex;
  flex-wrap:wrap;
  max-width:min(100%, 34rem);
  margin-inline:0;
  gap:.4rem;
}
/* 30 % als Ausgangsbreite: Drei passen nebeneinander, vier nicht mehr. Wer
   die Reihe nicht füllt, wird breiter, statt eine Lücke zu lassen.

 */
.act .gallery > *{ flex:1 1 30%; min-width:0; }
.act .gallery > :first-child{
  flex:0 0 100%;
  /* height:auto statt 100%: sonst überstimmt die Zeilenhöhe das
     Seitenverhältnis, und das Leitbild bekam die Form, die gerade übrig
     war – gemessen 1,32 statt der vorgesehenen 1,5. */
  height:auto;
  aspect-ratio:2.4;
}

/* ---- Die Kachel zu den weiteren Fotos ----
   Sitzt als letzte Kachel im Streifen statt als Ausklapper darunter: Ein
   eigenes Bedienelement unter dem Raster wirkte angeklebt. Sie zeigt das
   nächste Foto abgedunkelt – der Hinweis ist damit selbst ein Blick auf
   das, was er ankündigt.

   Warum <details> und nicht ein Knopf mit JavaScript: Die Seite baut ihre
   Stückbereiche zwar im Browser neu auf, die Serverfassung muss aber ohne
   Skript bedienbar bleiben. <details> bringt Tastatur und Vorlesesoftware
   von Haus aus mit. */
.gallery-mehr{ position:relative; }
.gallery-mehr > summary{
  display:block; position:relative; cursor:pointer;
  list-style:none; border-radius:6px; overflow:hidden;
}
.gallery-mehr > summary::-webkit-details-marker{ display:none; }
.gallery-mehr > summary img{ filter:brightness(.42); }
.gallery-mehr__zahl{
  position:absolute; inset:0; display:grid; place-items:center;
  color:#fff; font-size:1.15rem; font-weight:600; letter-spacing:.02em;
  text-shadow:0 1px 3px rgba(0,0,0,.5);
}
.gallery-mehr > summary:hover img,
.gallery-mehr > summary:focus-visible img{ filter:brightness(.55); }
.gallery-mehr > summary:focus-visible{ outline:2px solid var(--accent-text); outline-offset:2px; }
/* Solange die Kachel zu ist, bleiben die Fotos dahinter verborgen; ist sie
   offen, verschwindet sie selbst und die Fotos rücken an ihre Stelle. Ein
   Weg zurück fehlt bewusst: Er bräuchte eine eigene Kachel, die den
   Streifen wieder unrund macht, und niemand klappt eine Fotostrecke zu. */
.gallery-mehr:not([open]) ~ *{ display:none; }
.gallery-mehr[open]{ display:none; }

.gallery--placeholder img{ opacity:.85; border:1px dashed var(--border); }

/* Auf dem Handy enger zusammen: Der Streifen soll als eine Einheit lesbar
   bleiben und nicht als drei einzelne Kacheln zerfallen. */
@media (max-width:480px){ .gallery{ gap:.4rem; } }

/* Zurückhaltender Hinweis, dass die Bilder zusammengehören: Beim Überfahren
   hebt sich das Bild einen Hauch. Nur für Zeigegeräte – auf dem Touchscreen
   bliebe der Zustand nach dem Tippen kleben. Und nur, wo Bewegung erwünscht
   ist. */
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .act .gallery img{ transition:transform .25s ease, filter .25s ease; }
  .act .gallery img:hover{ transform:translateY(-3px); filter:brightness(1.04); }
}
/* Natives <details>: funktioniert ohne JavaScript und mit Tastatur wie
   Screenreader von Haus aus, genau wie .expander bei Besetzung & Team. */

.missing-note{
  font-size:.85rem; color:var(--text-muted); font-style:italic; max-width:60ch;
  padding-bottom:clamp(2.5rem,5vw,3.5rem);
}

/* ---------------- Zwischenakt ----------------
   Die Strecke zwischen zwei Stücken. Im Theater wechselt die Szene im
   Dunkeln: Licht runter, Umbau, Licht hoch. Genau das macht diese Strecke –
   sie schafft Abstand, gibt dem Auge eine Pause, und der Farbwechsel läuft
   hier ab statt schon unter dem vorigen Stück.

   Sichtbar bleibt nur ein Lichtspalt, wie unter einem geschlossenen
   Vorhang, plus die Jahreszahl des Stücks, das gleich kommt. Der Spalt
   arbeitet mit der Akzentfarbe statt mit Schwarz oder Weiß: die Seite hat
   eine helle und eine dunkle Fassung, und ein Akzentton trägt in beiden.

   Der Inhalt sitzt bewusst nicht in der Mitte, sondern per padding-top
   nach unten verschoben: der Abstand zum vorigen Stück soll größer sein
   als der zur neuen Bühne, auf die der Titel ja bereits einstimmt. */
/* ---------------- Sponsoren ----------------
   Das Band sitzt zwischen dem aktuellen Stück und dem Archiv. Diese Seite
   wird mit jedem Jahrgang länger; ein Logo im Fußbereich hinter vierzehn
   Stücken sähe praktisch niemand.

   Eigene Fläche statt der Palettenfarbe, die beim Scrollen laufend
   wechselt – aber wie der Rest der Seite ruhig zwischen hell und dunkel
   mitgehend, statt fest auf Weiß zu stehen. */
.sponsoren{
  position:relative; z-index:1;
  background:var(--bg-menue);
  padding:clamp(2.2rem,5vw,3.4rem) 0;
  border-block:1px solid var(--border);
}
.sponsoren__titel{
  font-family:var(--font-body); font-weight:500;
  font-size:.78rem; letter-spacing:.09em; text-transform:uppercase;
  text-align:center; color:var(--text-muted);
  margin-bottom:clamp(1.2rem,3vw,1.9rem);
}
/* Jedes Logo bekommt denselben Platz, unabhängig davon, wie es hochgeladen
   wurde – ein Hochformat, ein Panorama und ein Quadrat stehen in gleich
   großen Feldern nebeneinander. contain skaliert das Bild hinein, ohne es
   zu beschneiden oder zu verzerren; freier Raum im Feld bleibt einfach
   leer. So bestimmt nicht die Bilddatei die Gewichtung, sondern das
   Layout. */
.sponsoren__liste{
  list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; justify-content:center; align-items:center;
  gap:clamp(1rem,2.5vw,2rem);
}
.sponsoren__liste li{
  display:flex; align-items:center; justify-content:center;
  width:clamp(8rem,15vw,11rem);
  height:clamp(3.2rem,6vw,4.4rem);
}
.sponsoren__liste img,
.sponsoren__liste a{ width:100%; height:100%; }
.sponsoren__liste img{ object-fit:contain; }
/* Die Logos selbst sind für einen hellen Grund gezeichnet – ein dunkles
   Logo im Darkmode wäre sonst unsichtbar. Jedes bekommt deshalb eine
   eigene helle Plakette, während das Band drumherum den Farbmodus
   mitmacht. */
.sponsoren__liste a{
  display:flex; align-items:center; justify-content:center; border-radius:3px;
  background:#f4f1ec; padding:.5rem .8rem;
  transition:opacity .25s ease;
}
.sponsoren__liste a:hover{ opacity:.7; }
/* Der Fokusrahmen der Seite ist auf die Akzentfarbe des Stücks eingestellt –
   auf der ruhigen Bandfläche kann die untergehen. Hier deshalb ein eigener,
   der wie der Fließtext mit dem Farbmodus mitgeht. */
.sponsoren__liste a:focus-visible{ outline:3px solid var(--text); outline-offset:4px; }

.interlude{
  position:relative; z-index:1;
  min-height:88svh;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding-top:clamp(4rem,9vw,7.5rem);
  gap:clamp(1.1rem,2.5vw,1.8rem);
  overflow:hidden;
}
@media (max-width:640px){
  .interlude{ min-height:68svh; padding-top:clamp(2.6rem,7vw,4.5rem); }
}

/* Größe für einen Titel wie "Anstand statt Handstand" bemessen (die
   längsten liegen bei rund 23 Zeichen), nicht mehr für eine vierstellige
   Jahreszahl – max-width und Zentrierung sorgen für einen sauberen
   Zeilenumbruch bei langen Titeln. */
.interlude__titel{
  position:relative;
  font-family:var(--font-display); font-style:italic;
  font-size:clamp(1.5rem,3.4vw,2.5rem); line-height:1.2;
  max-width:min(80vw,26ch); text-align:center;
  color:var(--interlude-text, var(--text)); opacity:1;
}

/* Der Spalt selbst: eine Haarlinie, die an den Enden ausläuft. */
.interlude__line{
  position:relative;
  width:min(62vw,620px); height:1px;
  background:linear-gradient(90deg,
    transparent 0%, color-mix(in srgb, var(--accent-display) 85%, transparent) 50%, transparent 100%);
}

/* Auftritt: der Spalt öffnet sich aus der Mitte, die Jahreszahl steigt
   leicht auf. Nur mit laufendem JavaScript – ohne bleibt beides sichtbar. */
body.anim-ready .interlude__line{
  transform:scaleX(.18); opacity:0;
  transition:transform 1.1s cubic-bezier(.22,.61,.36,1), opacity .8s ease;
}
body.anim-ready .interlude__titel{
  transform:translate3d(0,.6rem,0); opacity:0;
  transition:transform .9s cubic-bezier(.22,.61,.36,1) .1s, opacity .9s ease .1s;
}
body.anim-ready .interlude.is-in .interlude__line{ transform:scaleX(1); opacity:1; }
body.anim-ready .interlude.is-in .interlude__titel{ transform:none; opacity:1; }

/* Ohne Bewegungswunsch steht der Zwischenakt sofort fertig da, statt sich
   aufzubauen. */
@media (prefers-reduced-motion: reduce){
  body.anim-ready .interlude__line,
  body.anim-ready .interlude__titel{
    transform:none !important; transition:none !important;
  }
  body.anim-ready .interlude__line{ opacity:1 !important; }
  body.anim-ready .interlude__titel{ opacity:1 !important; }
}

/* ---------------- Platzhalter-Startseite ---------------- */
.placeholder{
  position:relative; z-index:1;
  background:var(--bg); color:var(--text);
  min-height:88svh; display:flex; align-items:center; overflow:hidden;
}
/* Eingefasst wie die Stücke, damit die Startseite auf breiten Schirmen
   nicht aus der Reihe fällt. */
@media (min-width:1100px){
  .placeholder{
    max-width:1560px; margin-inline:auto; border-radius:10px;
    border:1.5px solid color-mix(in srgb, var(--accent-display) 38%, transparent);
  }
}
.placeholder__content{
  position:relative; z-index:1; text-align:center;
  max-width:620px; margin:0 auto; padding:2rem clamp(1.15rem,4vw,3rem);
}
.placeholder__title{
  font-family:var(--font-display); font-style:italic;
  font-size:clamp(1.8rem,4.4vw,3rem); color:var(--text);
  text-wrap:balance;
}
/* Nicht --text-muted: Der gedämpfte Ton ist für ruhige Flächen gedacht.
   Über einem Motiv fällt er unter die Lesbarkeitsschwelle, deshalb hier
   die volle Textfarbe, nur leicht zurückgenommen. */
.placeholder__lede{
  margin-top:1rem; font-size:1.06rem; line-height:1.6;
  color:color-mix(in srgb, var(--text) 86%, var(--bg));
}
.placeholder__actions{ margin-top:2rem; display:flex; gap:.8rem; justify-content:center; flex-wrap:wrap; }

/* ---------------- Geschlossener Vorhang ----------------
   Eine Guckkastenbühne aus reinen CSS-Flächen, kein Bild: Sie skaliert
   mit jeder Breite, und die Farben laufen beim Scrollen mit der Palette
   mit. Die Töne rechnet farben.js aus (vorhangFarben) – dort ist auch
   gesichert, dass die Schrift auf dem Samt lesbar bleibt. Die Werte
   hinter dem Komma sind der Rückfall ohne JavaScript: roter Samt.

   Bewusst zurückhaltend: zwei Vorhanghälften mit Falten, oben ein
   schmaler Volant mit Borte, unten ein dunkler Bühnenrand. Der Text
   steht im Spot auf dem Vorhang. Fußlichter, Bretter und Bögen am Volant
   gab es in 1.6.1 – das war zu viel Kulisse für eine Startseite. */
.placeholder--vorhang{
  --falte:clamp(2.6rem, 5.2vw, 5rem);
  --volant:clamp(2.4rem, 8svh, 4.6rem);
  --rampe:clamp(1rem, 3svh, 1.6rem);
  background:var(--vorhang-raum, #1a0306);
  color:var(--vorhang-tinte, #fff6f2);
  padding-block:var(--volant) var(--rampe);
}
.vorhang{ position:absolute; inset:0; pointer-events:none; }

.vorhang__haelfte{
  position:absolute; top:0; bottom:var(--rampe); width:51%;
  background:
    /* Schatten unter dem Volant und zum Boden hin */
    linear-gradient(180deg, rgba(0,0,0,.5) 0%, transparent 28%, transparent 78%, rgba(0,0,0,.28) 100%),
    /* Zweite Faltenlage mit krummer Periode: Sie bricht das gleichmässige
       Raster auf, sonst liest sich der Stoff als gestreifte Tapete. Nur
       abdunkelnd – heller als die berechnete Lichtkante wird es nie. */
    repeating-linear-gradient(90deg,
      transparent 0, rgba(0,0,0,.26) calc(var(--falte) * .8),
      transparent calc(var(--falte) * 1.55), transparent calc(var(--falte) * 2.1),
      rgba(0,0,0,.18) calc(var(--falte) * 2.45), transparent calc(var(--falte) * 2.9)),
    /* Falten: Schatten – Samt – Lichtkante – Samt – Schatten */
    repeating-linear-gradient(90deg,
      var(--vorhang-tief, #3a060d) 0,
      var(--vorhang, #6e0c19) calc(var(--falte) * .3),
      var(--vorhang-licht, #8d1424) calc(var(--falte) * .52),
      var(--vorhang, #6e0c19) calc(var(--falte) * .72),
      var(--vorhang-tief, #3a060d) var(--falte));
  background-position:right top; transform-origin:50% 0;
}
/* Die Falten laufen von der Mitte nach außen, damit beide Hälften
   spiegelbildlich an der Naht zusammentreffen. */
.vorhang__haelfte--links{ left:0; }
.vorhang__haelfte--rechts{ right:0; transform:scaleX(-1); }
/* Naht: Die Hälften überlappen leicht und werfen Schatten aufeinander. */
.vorhang__haelfte::after{
  content:''; position:absolute; top:0; bottom:0; right:0; width:clamp(1.2rem,3vw,2.4rem);
  background:linear-gradient(270deg, rgba(0,0,0,.55), transparent);
}

.vorhang__volant{
  position:absolute; top:0; left:0; right:0; height:var(--volant);
  background:
    linear-gradient(180deg, rgba(0,0,0,.45), transparent 70%),
    repeating-linear-gradient(90deg,
      var(--vorhang-tief, #3a060d) 0,
      var(--vorhang-licht, #8d1424) calc(var(--falte) * .25),
      var(--vorhang, #6e0c19) calc(var(--falte) * .5));
  box-shadow:0 .9rem 1.6rem rgba(0,0,0,.45);
}
.vorhang__volant::before{
  content:''; position:absolute; left:0; right:0; bottom:0; height:2px;
  background:var(--vorhang-borte, #d9a441); opacity:.8;
}

.vorhang__rampe{
  position:absolute; left:0; right:0; bottom:0; height:var(--rampe);
  background:var(--vorhang-raum, #1a0306);
  box-shadow:0 -1px 0 rgba(255,255,255,.06);
}

/* Der Spot: Er hellt den Samt hinter dem Text auf. Die Deckkraft steht
   als VORHANG_SPOT auch in farben.js – nur gemeinsam geändert ist der
   Kontrast weiter gesichert. */
.placeholder--vorhang .placeholder__content::before{
  content:''; position:absolute; z-index:-1; left:50%; top:50%;
  width:min(150%, 92vw); aspect-ratio:1.5; transform:translate(-50%,-50%);
  background:radial-gradient(closest-side, color-mix(in srgb, var(--vorhang-tinte, #fff6f2) 16%, transparent), transparent);
}
.placeholder--vorhang .placeholder__title,
.placeholder--vorhang .placeholder__lede{
  color:var(--vorhang-tinte, #fff6f2);
  text-shadow:0 1px 18px rgba(0,0,0,.55);
}
.placeholder--vorhang .btn--ghost{
  color:var(--vorhang-tinte, #fff6f2);
  border-color:var(--vorhang-borte, #d9a441);
  background:rgba(0,0,0,.25);
}
.placeholder--vorhang .btn--ghost:hover{ color:var(--vorhang-tinte, #fff6f2); background:rgba(0,0,0,.45); }

/* Ein leises Atmen im Stoff – wie ein Vorhang, hinter dem jemand vorbeigeht. */
@media (prefers-reduced-motion:no-preference){
  .vorhang__haelfte--links{ animation:vorhang-wehen 9s ease-in-out infinite alternate; }
  .vorhang__haelfte--rechts{ animation:vorhang-wehen-r 11s ease-in-out infinite alternate; }
}
@keyframes vorhang-wehen{ from{ transform:skewX(0deg); } to{ transform:skewX(.6deg); } }
@keyframes vorhang-wehen-r{ from{ transform:scaleX(-1) skewX(0deg); } to{ transform:scaleX(-1) skewX(.5deg); } }

/* ---------------- Footer ---------------- */
.site-footer{ position:relative; z-index:1; border-top:1px solid var(--border); padding:2.5rem 0; }
/* Luft über der Trennlinie, sobald die Stücke einen sichtbaren Rahmen haben.
   Zwischen zwei Stücken sorgt das jeweils folgende Element für den Abstand
   (Sponsorenblock, Zwischentitel); nach dem letzten folgt nur noch die
   Fusszeile, und deren Linie lag dadurch direkt auf dem Rahmen auf. Der
   gleiche Abstandswert wie im Sponsorenblock, damit die Seite unten in
   ihrem Rhythmus bleibt. Unterhalb von 1100px gibt es keinen Rahmen, der
   aufliegen könnte – dort bleibt es wie es ist. */
@media (min-width:1100px){
  .site-footer{ margin-top:clamp(2.2rem,5vw,3.4rem); }
}
.site-footer p{ color:var(--text-muted); font-size:.85rem; }
/* Nur der Abstand, keine zweite Abdunklung: Die Zeile erbt bereits
   --text-muted (80 % Deckkraft) von .site-footer p. Ein zusätzliches
   opacity:.75 ergab daraus effektiv 60 % – in 15 der 32 Paletten- und
   Modus-Kombinationen unter den 4,5:1, die WCAG für Text dieser Größe
   verlangt. Das font-size:.75rem stand hier ohnehin wirkungslos: ».site-footer p«
   ist spezifischer und hat es nie zum Zug kommen lassen. */
.site-footer__version{ margin-top:.35rem; }
.footer-link{ color:var(--text); text-decoration:underline; text-underline-offset:.2em; }
.footer-link:hover{ color:var(--accent-text); }

.scroll-cue{
  position:absolute; bottom:1.4rem; left:50%; transform:translateX(-50%); z-index:2;
  font-size:.74rem; color:var(--text-muted); letter-spacing:.06em;
  transition:opacity .4s ease; text-align:center; width:100%;
}
.scroll-cue.is-hidden{ opacity:0; }

/* ---------------- Auftritt der Inhalte ----------------
   Nur aktiv, wenn JS läuft (body.anim-ready) – sonst bliebe die Seite
   bei einem Skriptfehler leer. */
body.anim-ready .act__eyebrow,
body.anim-ready .act__title,
body.anim-ready .act__lede,
body.anim-ready .act__story,
body.anim-ready .act__aside{
  opacity:0; transform:translate3d(0,20px,0);
  transition:opacity .7s cubic-bezier(.22,.61,.36,1), transform .7s cubic-bezier(.22,.61,.36,1);
}
body.anim-ready .is-in .act__eyebrow,
body.anim-ready .is-in .act__title,
body.anim-ready .is-in .act__lede,
body.anim-ready .is-in .act__story,
body.anim-ready .is-in .act__aside{
  opacity:1; transform:none;
}
body.anim-ready .is-in .act__title{ transition-delay:.08s; }
body.anim-ready .is-in .act__lede{ transition-delay:.16s; }
body.anim-ready .is-in .act__aside{ transition-delay:.12s; }

@media (prefers-reduced-motion: reduce){
  *{ animation-duration:.001ms !important; transition-duration:.001ms !important; scroll-behavior:auto !important; }
  .ray{ transition:none !important; }
  body.anim-ready .act__eyebrow, body.anim-ready .act__title,
  body.anim-ready .act__lede,
  body.anim-ready .act__story, body.anim-ready .act__aside{
    opacity:1 !important; transform:none !important;
  }
}

/* Serverseitige Fassung: sichtbar, solange das JavaScript nicht übernommen
   hat. Die Auftritts-Animation blendet Inhalte erst nach dem Aufbau ein –
   ohne diese Regel wären sie im Rückfall unsichtbar. */
body:not(.anim-ready) .act__eyebrow,
body:not(.anim-ready) .act__title,
body:not(.anim-ready) .act__lede,
body:not(.anim-ready) .act__story,
body:not(.anim-ready) .act__aside{
  opacity:1; transform:none;
}
.fallback-leer{ padding:6rem 0; text-align:center; }
.fallback-leer h2{ font-family:var(--font-display); font-size:1.6rem; }
.fallback-leer p{ margin-top:.8rem; color:var(--text-muted); }

/* ---------------- Inhaltsseiten ----------------
   Ensemble, Verein, Kontakt: ruhige Lesespalte statt Bühne. Farben kommen
   aus denselben Variablen, damit die Seiten nicht wie ein Fremdkörper
   neben dem Spielplan stehen. */
.seite{ padding:clamp(3rem,7vw,5.5rem) 0 clamp(4rem,8vw,7rem); }
.seite__titel{
  font-family:var(--font-display); font-size:clamp(2rem,5vw,3.6rem);
  letter-spacing:-.01em; max-width:24ch;
}
.seite__vorspann{
  margin-top:1.2rem; max-width:52ch;
  font-size:clamp(1.02rem,1.3vw,1.25rem); color:var(--text-muted);
}
.seite__text{ margin-top:clamp(2rem,4vw,3rem); max-width:64ch; font-size:clamp(.98rem,1.05vw,1.06rem); }
.seite__text p{ color:var(--text-muted); }
.seite__text p + p{ margin-top:1rem; }
.seite__text h2{
  font-family:var(--font-display); font-size:clamp(1.3rem,2.2vw,1.7rem);
  color:var(--text); margin:2.2rem 0 .8rem;
}
.seite__text h3{
  font-family:var(--font-display); font-size:1.15rem;
  color:var(--text); margin:1.6rem 0 .6rem;
}
.seite__text ul{ margin:.9rem 0; padding-left:1.2rem; color:var(--text-muted); }
.seite__text li + li{ margin-top:.35rem; }
.seite__text strong{ color:var(--text); font-weight:600; }
.seite__text a{ color:var(--accent-text); text-underline-offset:.2em; }
.seite .gallery{ margin-top:clamp(2.2rem,5vw,3.5rem); }
.seite__fuss{
  display:flex; justify-content:space-between; gap:1rem; flex-wrap:wrap;
  margin-top:clamp(3rem,6vw,4.5rem); padding-top:1.4rem;
  border-top:1px solid var(--border);
  font-size:.85rem; color:var(--text-muted);
}
.seite__fuss a{ color:var(--accent-text); text-decoration:none; }
.seite__fuss a:hover{ text-decoration:underline; }

/* Palettenfilter: eigene Ebene, das Original bleibt unverändert. */
.act__media{ isolation:isolate; position:relative; }
.act__media::before{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(135deg,var(--bild-akzent),var(--bild-akzent-2));
  mix-blend-mode:color; opacity:var(--bildfilter,0);
}

/* Vorstellungen als gut lesbare Karten mit einer eindeutigen Reservierungsaktion. */
.termine{ padding:1.3rem; border-radius:12px; }
.termine__head{ font-size:1.4rem; margin-bottom:1rem; }
.termine__list .termin-karte{ display:flex; align-items:center; gap:1rem; padding:1.1rem 0; }
.termin-karte__angaben{ flex:1; min-width:0; }
.termin-karte__angaben .termine__datum{ display:block; font-size:1rem; font-weight:500; }
/* Ort und Eintritt: Bezeichnung und Wert in zwei Spalten, damit lange und
   kurze Adressen gleich gegliedert stehen. Der Kartenlink hat seine eigene
   Zeile unter der Adresse und bricht nie mitten in sie hinein. */
.termin-karte__details{
  display:grid; grid-template-columns:max-content minmax(0,1fr); align-items:baseline;
  gap:.3rem .9rem; margin:.5rem 0 0; font-size:.88rem;
}
.termin-karte__zeile{ display:contents; }
.termin-karte__details dt{
  font-size:.68rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase; color:var(--text-muted);
}
.termin-karte__details dd{ margin:0; color:var(--text); overflow-wrap:anywhere; }
.termin-karte__details .termine__ort, .termin-karte__details .termine__preis{ color:var(--text); font-size:inherit; margin:0; }
.termin-karte__details .karte-link{ display:flex; width:fit-content; margin-top:.15rem; }
.termin-karte--vergangen .termin-karte__details dd{ color:var(--text-muted); }
/* Gefüllt in der Akzentfarbe des Stücks – die eine Handlung, um die es in
   der Terminliste geht. Fläche und Schrift rechnet farben.js je Palette
   und Überblendung aus (knopfFarben): mindestens 4,5:1. */
.termin-karte__reservieren{ display:inline-flex; justify-content:center; align-items:center; gap:.8rem;
  flex-shrink:0; min-height:44px; padding:.65rem 1.1rem; border:0;
  border-radius:6px; background:var(--knopf, var(--accent)); color:var(--knopf-text, var(--accent-contrast));
  text-decoration:none; font-size:.88rem; font-weight:600;
  box-shadow:0 1px 2px color-mix(in srgb, var(--text) 18%, transparent);
  transition:transform .2s ease, box-shadow .2s ease; }
.termin-karte__reservieren:hover{ transform:translateY(-1px);
  box-shadow:0 4px 12px color-mix(in srgb, var(--accent) 35%, transparent); }
.termin-karte__status{ font-size:.75rem; color:var(--text-muted); }
/* Vergangene Termine: als zurückgetretene Fläche statt nur mit grauem
   Datum. Keine Deckkraft – die senkte den Kontrast der Schrift unter das,
   was noch lesbar ist, und vorbei heisst nicht unwichtig. Stattdessen eine
   leicht getönte Karte, normales Gewicht, gedämpfte Farbe. */
.termine__list .termin-karte--vergangen{
  margin:.35rem 0; padding:.75rem .9rem; border-radius:6px; border-bottom:none;
  background:color-mix(in srgb, var(--text) 5%, transparent);
}
.termin-karte--vergangen .termine__datum{ color:var(--text-muted); font-weight:400; }
.termin-karte__status--vergangen{ display:inline-flex; align-self:center; flex-shrink:0; padding:.35rem .65rem; border:1px solid var(--border); border-radius:999px; font-weight:500; }
/* ---- Ausverkauft als Ehrung ----
   Ein ausverkaufter Abend ist eine Auszeichnung, keine Absage – er bleibt
   deshalb auch im Archiv sichtbar und trägt einen Stern. Ein Abzeichen für
   beide Fälle: gross wie der Reservieren-Knopf bei kommenden Terminen, damit
   Karten untereinander nicht springen; klein bei vergangenen, wo daneben nur
   noch Pillen stehen.

   Schrift und Rahmen in --accent-2-text, ohne getönte Fläche dahinter: Die
   Farbe ist in farben.js genau auf 4,5:1 gegen den Seitenhintergrund
   gerechnet, jede Tönung drückt das darunter. */
.termin-karte__ehrung{
  display:inline-flex; align-items:center; gap:.35rem; flex-shrink:0; align-self:center;
  padding:.35rem .7rem; border:1.5px solid var(--accent-2-text); border-radius:999px;
  color:var(--accent-2-text); background:transparent;
  font-size:.72rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
}
.termin-karte__ehrung--gross{
  justify-content:center; min-height:44px; padding:.6rem .95rem; border-radius:6px;
  font-size:.8rem; letter-spacing:.09em;
}
/* Eine vergangene, ausverkaufte Vorstellung steht ohne die getönte Fläche
   der übrigen vergangenen Termine: Auf ihr fiele das Abzeichen unter die
   Kontrastgrenze, und gerade dieser Abend soll nicht zurücktreten. */
.termine__list .termin-karte--vergangen.termin-karte--ausverkauft{
  background:transparent;
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--text) 12%, transparent);
}
/* Zusammenfassung neben der Überschrift der Terminliste. */
.termine__ehrung{
  display:inline-flex; align-items:center; gap:.3rem; margin-left:.5rem; vertical-align:middle;
  font-family:var(--font-body, inherit); font-size:.7rem; font-weight:700;
  letter-spacing:.08em; text-transform:uppercase; color:var(--accent-2-text);
}
@media(max-width:700px){
  .termine__list .termin-karte{ align-items:stretch; flex-direction:column; gap:.8rem; }
  .termin-karte__reservieren,
  .termin-karte__ehrung--gross{ width:100%; }
}

.act__reservieren{ margin-top:1rem; }
.termine[id]{ scroll-margin-top:9rem; }

/* Ensemble: ruhige Liste statt Karten-Raster – kleines Porträt links,
   Name und Text rechts, Zeilen durch eine schlichte Linie getrennt (wie
   bei .termine__list). */
.ensemble{ margin-top:clamp(2.5rem,6vw,4.5rem); }
.ensemble__person{
  display:flex; gap:clamp(1.1rem,3vw,1.8rem); align-items:flex-start;
  padding:clamp(1.3rem,2.5vw,1.8rem) 0; border-bottom:1px solid var(--border);
}
.ensemble__person:first-child{ padding-top:0; }
.ensemble__person:last-child{ border-bottom:none; }
.ensemble__foto{
  display:block; flex:0 0 auto; width:clamp(84px,14vw,132px); height:auto;
  aspect-ratio:4/5; object-fit:cover; object-position:center 25%;
  border-radius:4px; background:#252a31;
}
.ensemble__inhalt{ min-width:0; padding-top:.15rem; overflow-wrap:anywhere; }
.ensemble__name{ font-family:var(--font-display); font-size:clamp(1.25rem,2vw,1.55rem); line-height:1.2; }
.ensemble__text{ margin-top:.5rem; font-size:.92rem; }
.seite--ensemble .seite__titel, .seite--galerie .seite__titel{ font-size:clamp(2.6rem,6vw,5rem); }
.seite--galerie .gallery--seite{ grid-template-columns:repeat(3,minmax(0,1fr)); gap:clamp(1rem,2vw,1.8rem); padding-bottom:0; }
.gallery--seite .gallery__item{ min-width:0; }
.gallery--seite .gallery__item--video{ grid-column:span 2; }
.gallery--seite img, .gallery--seite img:first-child{ display:block; width:100%; height:auto; aspect-ratio:4/3; object-fit:cover; }
.gallery--seite video{ display:block; width:100%; aspect-ratio:16/9; background:#111; }
.gallery--seite .gallery__item figcaption{ margin-top:.65rem; overflow-wrap:anywhere; }
@media (max-width:960px){
  .seite--galerie .gallery--seite{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:600px){
  .seite--galerie .gallery--seite{ grid-template-columns:minmax(0,1fr); }
  .gallery--seite .gallery__item--video{ grid-column:auto; }
  .ensemble__foto{ width:76px; }
}

/* Jahreslinks landen mit Abstand unter dem gemeinsamen, klebenden Kopf. */
[id^="stueck-"]{ scroll-margin-top:var(--nav-hoehe, 8rem); }

/* Semantische Akzente folgen der aktuellen Palette, auch beim Moduswechsel. */
.text-akzent{ color:var(--accent-text); background:none; font-weight:700; }
.act__story > p{ overflow-wrap:anywhere; }
.act__story > p a{ color:var(--accent-text); text-decoration:underline; text-underline-offset:.2em; }
