/* ═══════════════════════════════════════════════════════════════════════
   ZWO3ZWO Open Air — Seite und Flyer-Komposition

   Die Farben sind aus den gelieferten PNG gemessen, nicht gewählt.
   Die Lagen in .rig tragen die Positionen der Photoshop-Vorlage; woher sie
   kommen, steht in tools/build-images.py und im README.
   ═══════════════════════════════════════════════════════════════════════ */

/* Eine Datei, alle Schnitte von Thin bis Black. Die ITF Free Font License
   verbietet Subsetting und Formatkonvertierung — diese woff2 ist deshalb
   unverändert die von Fontshare gelieferte. Siehe assets/fonts/LICENSE. */
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('/assets/fonts/CabinetGrotesk-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --blau: #2034ce;
  --blau-tief: #141f82;
  --blau-nacht: #0c1455;
  --gelb: #fcfc05;
  /* Die Füllfarbe zwischen den beiden Hochformat-Teilen, so in der
     Gestaltung vorgegeben. Gemessen treffen sich die Teile bei #28a7fd —
     zwei Stufen daneben, die Blende an beiden Bildkanten schluckt das. */
  --himmel: #2aa8fd;
  --weiss: #fff;

  --rand: clamp(18px, 4vw, 40px);
  --bahn: 1360px;
  --bahn-weit: 1760px;

  --schrift: 'Cabinet Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--schrift);
  font-weight: 500;
  font-size: clamp(16px, 1.05vw + 13px, 19px);
  line-height: 1.5;
  color: var(--blau-nacht);
  background: var(--himmel);
  overflow-x: hidden;
}

img {
  max-width: 100%;
}

a {
  color: inherit;
}

h1,
h2,
p,
dl,
dd,
dt,
ol,
ul {
  margin: 0;
}

ol,
ul {
  padding: 0;
  list-style: none;
}

[hidden] {
  display: none !important;
}

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

.wrap {
  max-width: var(--bahn);
  margin-inline: auto;
  padding-inline: var(--rand);
}

.skip {
  position: absolute;
  left: 50%;
  top: 0;
  z-index: 100;
  translate: -50% -120%;
  padding: 12px 20px;
  background: var(--gelb);
  color: var(--blau);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-decoration: none;
}

.skip:focus-visible {
  translate: -50% 0;
}

:focus-visible {
  outline: 3px solid var(--gelb);
  outline-offset: 3px;
}

/* ── Kopfleiste ───────────────────────────────────────────────────────────
   Ganz oben gibt es keine. Das Motiv soll die erste Bildschirmhöhe allein
   haben — eine Leiste darüber nähme ihm die Oberkante, und an der hängen die
   Container. Sie fährt erst herein, wenn gescrollt wird, und dann gleich in
   Blau: So braucht sie keinen Verlauf gegen die Sonne im Bild, und es gibt
   keinen Zustand, in dem weiße Schrift über hellem Himmel steht.

   `visibility` und nicht nur `opacity`: Sonst bliebe sie für die Tabulatortaste
   erreichbar, während niemand sie sieht. Der Sprunglink oben im Dokument
   führt ohnehin direkt zu den Tickets.

   Unter 1100 px steht der Menü-Knopf trotzdem von Anfang an da (siehe
   unten) — sonst käme man auf dem Telefon oben nirgends hin.

   Eingeblendet heißt `translate: none`, nicht `0 0`: Jeder andere Wert macht
   die Leiste zum Bezugsrahmen für `position: fixed`, und das Menü füllte dann
   nur die Leiste statt den Bildschirm. */

.topbar {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: clamp(12px, 3vw, 32px);
  padding: 10px var(--rand);
  background: var(--blau);
  box-shadow: 0 2px 0 var(--gelb);
  translate: 0 -100%;
  visibility: hidden;
  transition: translate 0.28s ease, visibility 0.28s;
}

.topbar.is-stuck,
.menu-offen .topbar {
  translate: none;
  visibility: visible;
}

.topbar__brand {
  margin-right: auto;
}

.topbar__brand img {
  display: block;
  width: auto;
  height: 44px;
}

/* ── Menü unter 1100 px ── */

.topbar__nav {
  display: none;
}

.topbar__menu {
  position: relative;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: var(--blau);
  cursor: pointer;
}

.topbar__menu span,
.topbar__menu span::before,
.topbar__menu span::after {
  display: block;
  width: 22px;
  height: 3px;
  background: var(--gelb);
  transition: rotate 0.2s ease, translate 0.2s ease, opacity 0.2s ease;
}

.topbar__menu span {
  position: relative;
}

.topbar__menu span::before,
.topbar__menu span::after {
  content: '';
  position: absolute;
  left: 0;
}

.topbar__menu span::before {
  translate: 0 -7px;
}

.topbar__menu span::after {
  translate: 0 7px;
}

.menu-offen .topbar__menu span {
  background: transparent;
}

.menu-offen .topbar__menu span::before {
  translate: 0 0;
  rotate: 45deg;
}

.menu-offen .topbar__menu span::after {
  translate: 0 0;
  rotate: -45deg;
}

.menu-offen {
  overflow: hidden;
}

.menu-offen .topbar__nav {
  position: fixed;
  inset: 0;
  z-index: -1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 90px var(--rand) 40px;
  background: var(--blau);
  overflow-y: auto;
}

.menu-offen .topbar__nav a {
  align-self: flex-start;
  color: var(--weiss);
  font-size: clamp(34px, 9vw, 56px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-decoration: none;
}

/* Social unten im Menü, klein — kein weiterer Menüpunkt. Hier nur
   Instagram; weitere Profile kämen als zusätzliche .topbar__social dazu. */
.menu-offen .topbar__nav .topbar__social {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 28px;
  font-size: 1.1em;
  letter-spacing: 0;
  text-transform: none;
}

.topbar__social svg {
  flex: none;
  width: 30px;
  height: 30px;
}

.menu-offen .topbar__nav a[aria-current='page'],
.menu-offen .topbar__nav a:hover {
  color: var(--gelb);
}

/* Unter 1100 px steht der Knopf auch ganz oben auf der Startseite: Die
   Leiste ist dann da, aber durchsichtig, und zeigt nur ihn. */
@media (max-width: 1099px) {
  .topbar {
    translate: none;
    visibility: visible;
  }

  .topbar:not(.is-stuck) {
    background: transparent;
    box-shadow: none;
  }

  .menu-offen .topbar:not(.is-stuck) {
    background: var(--blau);
  }

  html:not(.menu-offen) .topbar:not(.is-stuck) .topbar__brand,
  html:not(.menu-offen) .topbar:not(.is-stuck) .topbar__cta {
    visibility: hidden;
  }
}

.topbar__cta {
  padding: 9px 20px;
  background: var(--gelb);
  color: var(--blau);
  font-weight: 800;
  font-size: 0.86em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  transition: translate 0.15s ease;
}

.topbar__cta:hover {
  translate: 0 -2px;
}

/* ── Das Motiv ───────────────────────────────────────────────────────────
   Randlos über die ganze Breite. Zwei Lagen:

       Hintergrund   unter 760 px oben und unten je ein Bild, dazwischen
                     --himmel; ab 760 px ein Bild über die ganze Bühne
       .rig          Container und Balken als Einzelteile, im Fluss

   Die Bühne wächst mit ihrem Inhalt — das Verkaufsmodul ist mal 500, mal
   900 px hoch. Deshalb liegen die Hintergründe absolut darunter, und im
   Hochformat dehnt sich zwischen ihnen die Füllfarbe. */

.stage {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--himmel);
}

.stage__oben,
.stage__unten {
  position: absolute;
  inset-inline: 0;
  z-index: -1;
}

.stage__oben {
  top: 0;
}

.stage__unten {
  bottom: 0;
}

.stage__oben img,
.stage__unten img {
  display: block;
  width: 100%;
  height: auto;
}

/* Blenden statt harter Kante: Die Bilder laufen in die Füllfarbe aus. Unten
   lang, weil dort nur Himmel ist; oben kurz, weil die Wolken sonst
   verwaschen. */
.stage__oben img {
  -webkit-mask-image: linear-gradient(to bottom, #000 78%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 78%, transparent 100%);
}

.stage__unten img {
  -webkit-mask-image: linear-gradient(to top, #000 70%, transparent 100%);
  mask-image: linear-gradient(to top, #000 70%, transparent 100%);
}

.stage__mid {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 2.2vw, 22px);
  /* Unten frei für Palmen und gelbe Dreiecke. Das untere Bild ist 0,89 ×
     Breite hoch; der Verkauf darf in die oberen Wedel ragen, sonst steht
     unter ihm eine halbe Bildschirmhöhe nur Bild. */
  padding: 0 var(--rand) 34vw;
}

/* ── Container und Balken ────────────────────────────────────────────────
   Jedes Teil steht über --x, --y, --w in seinem Rahmen (.rig): links und
   Breite in Prozent der Rahmenbreite, oben in Prozent der Rahmenhöhe. Der
   Rahmen hat das Seitenverhältnis der Vorlage (4000 × 2232, wie bg_quer),
   die Zahlen hat tools/build-images.py ausgegeben.

   **Auf jeder Breite dieselbe Anordnung**, nur verschieden groß. Eine eigene
   fürs Telefon (Datum oben, „2 Stages" darunter) gab es: Die Container
   hingen dann nicht mehr zusammen wie auf dem Flyer, und dem linken fehlt
   oben am Eckpfosten ein Stück, das in der Vorlage hinter dem
   Datums-Container liegt (tools/build-images.py) — getrennt war es zu sehen.

   Auf dem Telefon ist der Rahmen deshalb breiter als der Bildschirm und
   nach links versetzt: Sichtbar sind 19–88 % des Rahmens, die Schrift liegt
   bei 24–45 % und 52–87 %. Die Türenden laufen aus dem Bild, dafür werden
   Logo, Datum und Zeiten fast anderthalbmal so groß. */

.rig {
  position: relative;
  flex: none;
  align-self: flex-start;
  width: 145vw;
  margin-left: calc(-1 * var(--rand) - 28vw);
  aspect-ratio: 4000 / 2232;
}

/* Laufschrift hinter den Containern, nur auf dem Telefon (unten). */
.rig__lauf {
  display: none;
}

@media (max-width: 759px) {
  .rig__lauf {
    position: absolute;
    left: 0;
    top: 68%;
    display: block;
    width: 100%;
    overflow: hidden;
    pointer-events: none;
  }

  .rig__lauf div {
    display: flex;
    width: max-content;
    animation: rig-lauf 22s linear infinite;
  }

  .rig__lauf span {
    padding-right: 0.3em;
    font-size: 110px;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.04em;
    text-transform: uppercase;
    white-space: nowrap;
    color: transparent;
    -webkit-text-stroke: 2.5px rgb(255 255 255 / 90%);
  }

  /* Erst nach dem Einflug der Container einblenden. */
  .js .stage .rig__lauf {
    opacity: 0;
  }

  .js .stage.is-ready .rig__lauf {
    animation: rig-auf 1s ease-out 1.2s forwards;
  }

  .js .stage.is-still .rig__lauf {
    animation: none;
    opacity: 1;
  }
}

@keyframes rig-lauf {
  to {
    transform: translateX(-50%);
  }
}

@keyframes rig-auf {
  to {
    opacity: 1;
  }
}

.rig__teil {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
}

.rig__teil img {
  display: block;
  width: 100%;
  height: auto;
}

.rig__teil--stages { --x: 6.93%; --y: 0%; --w: 40.45%; }
.rig__teil--datum { --x: 44.8%; --y: 0%; --w: 54.02%; }
.rig__teil--b1 { --x: 19.3%; --y: 86.51%; --w: 6.12%; }
.rig__teil--b2 { --x: 33.42%; --y: 17.38%; --w: 11.45%; }
.rig__teil--b3 { --x: 39.73%; --y: 4.75%; --w: 9.95%; }
.rig__teil--b4 { --x: 82.23%; --y: 63.17%; --w: 13.45%; }

/* Coming soon: nur Container und Countdown, der Balken bleibt, wo er herkommt. */
.stage--bald .rig__teil--b4 { --x: 82.23%; --y: 63.17%; }

/* Kurze Seite: Unter dem Fuß soll kein Himmelblau durchscheinen. */
body:has(.stage--bald) {
  background: var(--blau-nacht);
}

/* Der Störer zum Flohmarkt. Die Schrift misst sich an ihm selbst (cqw), er
   wächst mit dem Rahmen. Auf dem Telefon größer, sonst ist sie nicht lesbar. */
.rig__teil--stoerer {
  --x: 60%;
  --y: 62%;
  --w: 25%;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  container-type: inline-size;
  rotate: 8deg;
  color: var(--blau);
  text-align: center;
  text-decoration: none;
  transition: scale 0.15s ease;
}

.rig__teil--stoerer:hover {
  scale: 1.06;
}

.rig__teil--stoerer svg {
  position: absolute;
  inset: 0;
  fill: var(--gelb);
  filter: drop-shadow(0 4px 8px rgb(12 20 85 / 35%));
}

.stoerer__text {
  position: relative;
  display: grid;
  gap: 2.5cqw;
  font-weight: 800;
  text-transform: uppercase;
}

.stoerer__text b {
  font-size: 14.5cqw;
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.02em;
}

.stoerer__text small {
  font-size: 7.6cqw;
  line-height: 1;
  letter-spacing: 0.02em;
}

/* ── Der Ticketverkauf im Himmel ─────────────────────────────────────────
   Weiß, weil das Verkaufsmodul Preise, Mengenwähler und Knöpfe lesbar
   zeigen muss — und weil Weiß im Flyer ohnehin die dritte Farbe ist. Harte
   Kanten, gelbe Oberkante, und ein Schatten, damit die Fläche über dem
   Himmel schwebt wie die Container an ihren Seilen. */

.shop {
  width: min(100%, 620px);
  /* Kommt zum Abstand der Leisten untereinander hinzu. Die drei Leisten sind
     eine Gruppe — was, wo, wann —, der Verkauf ist der nächste Schritt und
     braucht die Trennung. */
  margin-top: clamp(16px, 3.4vw, 34px);
  padding: clamp(22px, 3vw, 32px) clamp(18px, 2.6vw, 30px) clamp(26px, 3.4vw, 34px);
  background: var(--weiss);
  border-top: 10px solid var(--gelb);
  box-shadow: 0 26px 64px rgb(12 20 85 / 30%);
}

.shop__title {
  font-size: clamp(32px, 5vw, 48px);
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--blau);
}

.shop__lede {
  margin-top: 10px;
  margin-bottom: 22px;
  color: #3c4a7a;
}

.shop__fallback {
  margin-top: 14px;
}

/* Das Logo ist weiß, für den dunklen Fuß gemacht. Auf dem weißen Kasten
   per Filter schwarz statt einer zweiten Datei. */
.shop__powered {
  display: block;
  width: fit-content;
  margin: 18px auto 0;
}

.shop__powered img {
  display: block;
  width: 96px;
  height: auto;
  filter: brightness(0);
  opacity: 0.9;
  transition: opacity 0.15s ease;
}

.shop__powered:hover img {
  opacity: 1;
}

.shop__powered:focus-visible {
  outline-color: var(--blau);
}

/* ── Die Leisten unter dem Verkauf ───────────────────────────────────────
   Breiten im Verhältnis des Flyers: dort 86,76 % und 77,69 % der Seite.
   Beide sind auf dem Flyer praktisch mittig (Mitte bei 49,1 % und 48,8 %),
   deshalb stehen sie hier zentriert und nicht links. */

.bar {
  width: min(86%, 700px);
}

.bar--location {
  width: min(77%, 627px);
}

.bar img {
  display: block;
  width: 100%;
  height: auto;
}

.bar--countdown {
  width: min(86%, 700px);
}

/* ── Countdown ───────────────────────────────────────────────────────────
   Gelbe Leiste mit blauem Etikett — Entwurf 30 aus entwuerfe/countdown/,
   Farben umgekehrt. Direkt unter den Containern, über Genre und Ort. */

.countdown {
  display: grid;
  justify-items: start;
}

.countdown__reiter {
  position: relative;
  z-index: 1;
  margin-left: 14px;
  padding: 4px 12px;
  background: var(--blau);
  color: var(--gelb);
  font-size: 0.74em;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  rotate: -3deg;
  translate: 0 6px;
}

.countdown ol {
  display: flex;
  justify-content: center;
  gap: clamp(14px, 3vw, 30px);
  width: 100%;
  padding: 14px 20px 10px;
  background: var(--gelb);
  color: var(--blau);
}

.countdown li {
  display: grid;
  justify-items: center;
}

.countdown b {
  font-size: clamp(30px, 5vw, 52px);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.countdown span {
  font-size: 0.66em;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blau-tief);
}

.countdown__note {
  padding: 13px 16px;
  background: var(--blau);
  color: var(--gelb);
  font-weight: 800;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ── Einflug und Schweben ────────────────────────────────────────────────
   Ohne JavaScript steht alles sofort — die Lagen sind dann nicht unsichtbar,
   sondern einfach da. Erst `.js` nimmt sie für den Einflug zurück. */

@keyframes einflug {
  from {
    opacity: 0;
    transform: translateY(30px) scale(0.94);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Die Container hängen an Seilen, also fallen sie von oben herein und
   federn nach. Danach schaukelt die ganze Gruppe leicht — auf .rig, nicht
   je Container: Zwei Drehpunkte bewegen die Berührungsstelle gegeneinander,
   und hinter dem Datums-Container fehlt dem linken ein Stück. Einflug
   (transform je Teil), Parallax (translate je Teil) und Schaukeln (rotate
   auf .rig) überschreiben sich so nicht. */
/* Jeder Abschnitt mit eigener Kurve: Fallen wird schneller (ease-in),
   das Nachfedern wird langsamer (ease-out). Eine Kurve fürs Ganze ließ die
   Container in den ersten 300 ms ankommen — Einschnappen statt Fallen. */
@keyframes herab {
  from {
    transform: translateY(calc(-100% - 40vh));
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.35);
  }
  58% {
    transform: translateY(3%);
    animation-timing-function: cubic-bezier(0.2, 0.6, 0.4, 1);
  }
  78% {
    transform: translateY(-1.4%);
    animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
  }
  to {
    transform: none;
  }
}

@keyframes schaukeln {
  0%,
  100% {
    rotate: 0deg;
  }
  25% {
    rotate: 0.5deg;
  }
  75% {
    rotate: -0.5deg;
  }
}

@keyframes aufpoppen {
  from {
    opacity: 0;
    transform: scale(0.2) rotate(-25deg);
  }
  65% {
    opacity: 1;
    transform: scale(1.12) rotate(4deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.js .stage .rig__teil,
.js .stage .shop,
.js .stage .bar {
  opacity: 0;
}

.js .stage.is-ready .rig__teil--stages,
.js .stage.is-ready .rig__teil--datum {
  opacity: 1;
  animation: herab 1.3s linear both;
}

.js .stage.is-ready .rig__teil--stages {
  animation-delay: 0.22s;
}

.js .stage.is-ready .rig {
  transform-origin: 50% 0;
  animation: schaukeln 7s ease-in-out 1.6s infinite;
}

.js .stage.is-ready .rig__teil--balken,
.js .stage.is-ready .rig__teil--stoerer {
  animation: aufpoppen 0.6s cubic-bezier(0.3, 1.4, 0.5, 1) both;
}

.js .stage.is-ready .rig__teil--b3 {
  animation-delay: 0.95s;
}

.js .stage.is-ready .rig__teil--b2 {
  animation-delay: 1.05s;
}

.js .stage.is-ready .rig__teil--b4 {
  animation-delay: 1.15s;
}

.js .stage.is-ready .rig__teil--b1 {
  animation-delay: 1.25s;
}

.js .stage.is-ready .rig__teil--stoerer {
  animation-delay: 1.4s;
}

.js .stage.is-ready .shop,
.js .stage.is-ready .bar {
  animation: einflug 0.85s cubic-bezier(0.2, 0.85, 0.25, 1) both;
}

.js .stage.is-ready .bar--countdown {
  animation-delay: 0.7s;
}

.js .stage.is-ready .bar--genre {
  animation-delay: 0.8s;
}

.js .stage.is-ready .bar--location {
  animation-delay: 0.9s;
}

.js .stage.is-ready .shop {
  animation-delay: 1s;
}

.js .stage.is-still .rig,
.js .stage.is-still .rig__teil,
.js .stage.is-still .shop,
.js .stage.is-still .bar {
  animation: none;
  opacity: 1;
}

/* ── Eckdaten ─────────────────────────────────────────────────────────── */

.facts {
  background: var(--blau);
  color: var(--weiss);
  padding-block: clamp(30px, 5vw, 56px);
  scroll-margin-top: 80px;
}

.facts__list {
  display: grid;
  gap: clamp(20px, 3vw, 34px);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}

.facts dt {
  font-size: 0.68em;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gelb);
}

.facts dd {
  margin-top: 6px;
  font-size: clamp(19px, 1.5vw, 24px);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.facts dd small {
  display: block;
  margin-top: 4px;
  font-size: 0.68em;
  font-weight: 500;
  letter-spacing: 0;
  color: #c9d3ff;
}

.facts__maps {
  display: inline-block;
  margin-top: 10px;
  font-size: 0.72em;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gelb);
  text-underline-offset: 4px;
}

/* Der Flohmarkt hat eine eigene Seite — der Name ist der Link dorthin. */
.facts__link {
  color: inherit;
  text-decoration-color: var(--gelb);
  text-decoration-thickness: 3px;
  text-underline-offset: 5px;
}

.facts__link:hover {
  color: var(--gelb);
}

/* ── Rückblick ────────────────────────────────────────────────────────────
   Weiß zwischen dem Blau der Eckdaten und dem Gelb des Flohmarkts — die
   Fotos bringen genug Farbe mit. Harte Kanten, keine Rundungen, wie überall.

   Auf dem Telefon eine Reihe zum Wischen: Jedes Bild hat dieselbe Höhe und
   seine eigene Breite, das nächste schaut am Rand hervor und zeigt, dass es
   weitergeht. Ab 760 px eine Collage mit festen Flächen (siehe unten). */

.recap {
  background: var(--weiss);
  padding-block: clamp(44px, 7vw, 96px);
  scroll-margin-top: 80px;
}

.recap__head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 14px 32px;
  margin-bottom: clamp(22px, 3vw, 36px);
}

.recap__kicker {
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blau);
}

.recap__title {
  margin-top: 8px;
  font-size: clamp(40px, 6.4vw, 84px);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--blau);
}

.recap__insta {
  font-weight: 800;
  font-size: 0.9em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--blau);
  text-decoration-color: var(--gelb);
  text-decoration-thickness: 3px;
  text-underline-offset: 5px;
}

.recap__insta:focus-visible {
  outline-color: var(--blau);
}

/* Die Reihe läuft bis an den Bildschirmrand — `.wrap` gibt ihr deshalb
   keinen Innenabstand, sondern die Liste selbst, damit das erste Bild bündig
   mit der Überschrift beginnt und beim Wischen dorthin einrastet. */
.recap__wrap {
  padding-inline: 0;
}

.recap__grid {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--rand);
  padding-inline: var(--rand);
  scrollbar-width: none;
}

.recap__grid::-webkit-scrollbar {
  display: none;
}

.recap__item {
  flex: 0 0 auto;
  height: clamp(300px, 92vw, 440px);
  max-width: 85vw;
  scroll-snap-align: start;
  background: var(--blau);
}

.recap__item img {
  display: block;
  width: auto;
  max-width: none;
  height: 100%;
  object-fit: cover;
}

.recap__item--c img,
.recap__item--h img,
.recap__item--f img,
.recap__item--s img,
.recap__item--a img,
.recap__item--g img,
.recap__item--p img,
.recap__item--l img {
  width: 85vw;
}

/* ── Line-up ──────────────────────────────────────────────────────────────
   Blau zwischen dem Weiß des Rückblicks und dem Gelb des Flohmarkts. Die
   Kacheln sind verdeckte Plätze: Fragezeichen in Gelb, leicht schräg und
   abwechselnd gedreht wie die Balken auf dem Flyer. */

.lineup {
  background: var(--blau);
  color: var(--weiss);
  padding-block: clamp(44px, 7vw, 96px);
  overflow: hidden;
  scroll-margin-top: 80px;
}

.lineup__head {
  display: grid;
  gap: 18px clamp(28px, 4vw, 64px);
  align-items: end;
}

.lineup__kicker {
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gelb);
}

.lineup__title {
  margin-top: 8px;
  font-size: clamp(48px, 8vw, 112px);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}

.lineup__title span {
  display: inline-block;
  padding: 0.04em 0.16em 0.08em;
  background: var(--gelb);
  color: var(--blau);
  rotate: -2deg;
}

.lineup__text p {
  max-width: 30em;
  color: #e3e8ff;
}

.lineup__insta {
  display: inline-block;
  margin-top: 14px;
  font-weight: 800;
  font-size: 0.9em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gelb);
  text-decoration-thickness: 3px;
  text-underline-offset: 5px;
}

.lineup__slots {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(8px, 1.4vw, 20px);
  margin-top: clamp(28px, 4vw, 52px);
}

.lineup__slot {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 5 / 6;
  background: var(--blau-tief);
  border: 2px solid rgb(255 255 255 / 12%);
  rotate: -1.5deg;
}

.lineup__slot:nth-child(even) {
  rotate: 1.5deg;
  translate: 0 clamp(6px, 1.4vw, 18px);
}

.lineup__slot span {
  font-size: clamp(40px, 8vw, 120px);
  font-weight: 800;
  line-height: 1;
  color: var(--gelb);
}

.lineup__slot::after {
  content: 'TBA';
  position: absolute;
  bottom: clamp(8px, 1.2vw, 16px);
  font-size: clamp(10px, 0.9vw, 13px);
  font-weight: 800;
  letter-spacing: 0.16em;
  color: rgb(255 255 255 / 55%);
}

/* Auf dem Telefon drei Plätze — fünf wären Briefmarken. */
@media (max-width: 559px) {
  .lineup__slots {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .lineup__slot:nth-child(n + 4) {
    display: none;
  }
}

/* ── Flohmarkt ────────────────────────────────────────────────────────────
   Gelb nach dem Blau der Eckdaten: ein eigener Abend, nicht noch eine
   Eckdatenzeile. Der Titel wie auf der Flohmarktseite, nur kleiner und
   umgekehrt — dort Gelb auf Blau, hier Blau auf Gelb. */

.flohmarkt {
  position: relative;
  overflow: hidden;
  background: var(--gelb);
  color: var(--blau-nacht);
  padding-block: 0 clamp(36px, 6vw, 72px);
  scroll-margin-top: 80px;
}

.flohmarkt__wrap {
  display: grid;
  gap: clamp(22px, 3vw, 40px);
  align-items: end;
}

/* Diagonal geteilt: Unter 1100 px das Bild oben über die volle Breite,
   darunter der Text. Ab 1100 px liegt es rechts hinter einer schrägen
   Kante, davor eine blaue Schräge als Trenner. */
.flohmarkt__bild {
  position: relative;
  margin: 0 0 clamp(30px, 5vw, 48px);
  aspect-ratio: 16 / 10;
}

.flohmarkt__bild img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 55% 40%;
}


.flohmarkt__kicker {
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blau);
}

.flohmarkt__title {
  margin-top: 8px;
  font-size: clamp(40px, 6.4vw, 84px);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--blau);
}

.flohmarkt__title span {
  display: inline-block;
  margin-top: 0.06em;
  padding: 0.04em 0.16em 0.08em;
  background: var(--blau);
  color: var(--gelb);
  rotate: -2deg;
}

.flohmarkt__text {
  max-width: 34em;
  margin-top: clamp(16px, 2vw, 24px);
}

.flohmarkt__when {
  display: grid;
  gap: 4px;
}

.flohmarkt__when time {
  font-size: clamp(34px, 4vw, 52px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--blau);
}

.flohmarkt__when span {
  font-weight: 700;
}

.flohmarkt__links {
  margin-top: 24px;
}

.flohmarkt__cta {
  display: inline-block;
  padding: 12px 22px;
  background: var(--blau);
  color: var(--weiss);
  font-weight: 800;
  font-size: 0.9em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  transition: translate 0.15s ease;
}

.flohmarkt__cta:hover {
  translate: 0 -2px;
}

/* Gelb auf Gelb sieht man nicht — hier ist der Fokus blau. */
.flohmarkt :focus-visible {
  outline-color: var(--blau);
}

/* ── Jobs & Ehrenamt ──────────────────────────────────────────────────────
   Weiß nach dem Gelb des Flohmarkts. Je Weg eine große Bildkarte — die
   Fotos tragen den Abschnitt, der Fuß der Karte sagt in Blau oder Gelb,
   worum es geht, wie die beiden Spalten auf /mitmachen/. */

.anpacken {
  background: var(--weiss);
  padding-block: clamp(44px, 7vw, 96px);
  scroll-margin-top: 80px;
}

.anpacken__head {
  display: grid;
  gap: 14px clamp(28px, 4vw, 64px);
  align-items: end;
  margin-bottom: clamp(24px, 3.4vw, 44px);
}

.anpacken__kicker {
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blau);
}

.anpacken__title {
  margin-top: 8px;
  font-size: clamp(40px, 6.4vw, 84px);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--blau);
}

.anpacken__title span {
  display: inline-block;
  padding: 0.04em 0.16em 0.08em;
  background: var(--gelb);
  color: var(--blau);
  rotate: -2deg;
}

.anpacken__text {
  max-width: 30em;
  color: #2c3660;
}

.anpacken__karten {
  display: grid;
  gap: clamp(14px, 2vw, 28px);
}

.karte {
  display: flex;
  flex-direction: column;
  height: 100%;
  text-decoration: none;
}

.karte__bild {
  display: block;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--blau);
}

.karte__bild img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: scale 0.5s cubic-bezier(0.2, 0.85, 0.25, 1);
}

.karte--job .karte__bild img {
  /* Sie steht rechts der Mitte; oben ist nur Decke. */
  object-position: 60% 45%;
}

.karte--ehrenamt .karte__bild img {
  object-position: 50% 30%;
}

.karte:hover .karte__bild img {
  scale: 1.04;
}

.karte__fuss {
  position: relative;
  display: grid;
  gap: 6px;
  flex: 1;
  padding: clamp(22px, 2.4vw, 30px) clamp(20px, 2.4vw, 30px) clamp(20px, 2.4vw, 28px);
}

.karte--job .karte__fuss {
  background: var(--blau);
  color: var(--weiss);
}

.karte--ehrenamt .karte__fuss {
  background: var(--gelb);
  color: var(--blau);
}

/* Der Stempel sitzt auf der Kante zwischen Bild und Fuß. */
.karte__tag {
  position: absolute;
  top: 0;
  left: clamp(20px, 2.4vw, 30px);
  translate: 0 -55%;
  padding: 4px 10px 5px;
  font-size: 0.74em;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  rotate: -3deg;
}

.karte--job .karte__tag {
  background: var(--gelb);
  color: var(--blau);
}

.karte--ehrenamt .karte__tag {
  background: var(--blau);
  color: var(--gelb);
}

.karte__title {
  font-size: clamp(26px, 3vw, 40px);
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.karte__mehr {
  justify-self: start;
  margin-top: 6px;
  font-size: 0.86em;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: underline;
  text-decoration-thickness: 3px;
  text-underline-offset: 5px;
}

.karte--job .karte__mehr {
  color: var(--gelb);
}

.anpacken :focus-visible {
  outline-color: var(--blau);
}

/* ── FAQ und Kontakt ──────────────────────────────────────────────────────
   Blau nach dem Weiß von „Pack mit an!", vor dem dunklen Fuß. Links die
   Fragen als aufklappbare Zeilen, rechts das Formular als weißer Kasten mit
   gelber Oberkante (formular.css) — wie der Ticketkasten oben. */

.fragen {
  background: var(--blau);
  color: var(--weiss);
  padding-block: clamp(48px, 8vw, 110px);
}

.fragen__wrap {
  display: grid;
  gap: clamp(36px, 5vw, 72px);
  align-items: start;
}

.faq,
.kontakt {
  scroll-margin-top: 90px;
}

.fragen__kicker {
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gelb);
}

.fragen__title {
  margin-top: 8px;
  font-size: clamp(48px, 8vw, 112px);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}

.faq__liste {
  margin-top: clamp(22px, 3vw, 36px);
  border-top: 2px solid rgb(255 255 255 / 20%);
}

.faq__item {
  border-bottom: 2px solid rgb(255 255 255 / 20%);
}

.faq__item summary {
  position: relative;
  padding: 16px 44px 16px 0;
  font-size: clamp(17px, 1.5vw, 21px);
  font-weight: 800;
  line-height: 1.3;
  cursor: pointer;
  list-style: none;
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

/* Plus als zwei Balken, wird beim Öffnen zum Minus. */
.faq__item summary::before,
.faq__item summary::after {
  content: '';
  position: absolute;
  right: 6px;
  top: 50%;
  width: 18px;
  height: 4px;
  margin-top: -2px;
  background: var(--gelb);
  transition: rotate 0.2s ease;
}

.faq__item summary::after {
  rotate: 90deg;
}

.faq__item[open] summary::after {
  rotate: 0deg;
}

.faq__item summary:hover {
  color: var(--gelb);
}

.faq__item p {
  max-width: 36em;
  padding: 0 0 18px;
  color: #e3e8ff;
}

.faq__item a {
  color: var(--gelb);
  font-weight: 700;
}

.kontakt .anfrage {
  color: var(--blau-nacht);
}

.kontakt__lede {
  margin-top: -6px;
  color: #3c4a7a;
}

/* Die Felder stehen im Formular-Raster wie vorher. */
.kontakt__felder {
  display: grid;
  gap: 16px;
}

.kontakt__auf {
  display: none;
}

/* Unter 1100 px eingeklappt, bis jemand tippt (faq-kontakt.js). Nur mit
   JavaScript — ohne bleibt alles offen. */
@media (max-width: 1099px) {
  .js .kontakt__auf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 14px 18px;
    border: 0;
    background: var(--blau);
    color: var(--weiss);
    font: inherit;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
  }

  .js .kontakt__auf::after {
    content: '+';
    font-size: 1.5em;
    line-height: 1;
    color: var(--gelb);
  }

  .js .kontakt__auf[aria-expanded='true']::after {
    content: '–';
  }

  .js .anfrage:not(.is-offen) .kontakt__felder {
    display: none;
  }
}

.kontakt__aus {
  padding: 22px 24px;
  background: var(--weiss);
  border-top: 10px solid var(--gelb);
  color: var(--blau-nacht);
  font-weight: 700;
}

/* ── Sponsoren ────────────────────────────────────────────────────────────
   Weiß nach dem Blau von FAQ/Kontakt. Freie Plätze als gestrichelte
   Kacheln, die letzte gelb und klickbar. */

.sponsoren {
  background: var(--weiss);
  padding-block: clamp(48px, 8vw, 110px);
  scroll-margin-top: 80px;
}

.sponsoren__wrap {
  display: grid;
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}

.sponsoren__kicker,
.anfahrt__kicker {
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blau);
}

.sponsoren__title,
.anfahrt__title {
  margin-top: 8px;
  font-size: clamp(44px, 7vw, 96px);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  color: var(--blau);
}

.sponsoren__title span {
  display: inline-block;
  margin-top: 0.06em;
  padding: 0.04em 0.16em 0.08em;
  background: var(--gelb);
  color: var(--blau);
  font-size: 0.6em;
  rotate: -2deg;
}

.sponsoren__text {
  max-width: 30em;
  margin-top: clamp(16px, 2vw, 24px);
  color: #2c3660;
}

.sponsoren__cta {
  display: inline-block;
  margin-top: clamp(20px, 3vw, 30px);
  padding: 14px 26px;
  background: var(--blau);
  color: var(--weiss);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 5px 5px 0 var(--gelb);
  transition: translate 0.15s ease, box-shadow 0.15s ease;
}

.sponsoren__cta:hover {
  translate: -2px -2px;
  box-shadow: 7px 7px 0 var(--gelb);
}

.sponsoren__slots {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(8px, 1.4vw, 16px);
}

.sponsoren__slot {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 2;
  border: 2px dashed rgb(32 52 206 / 30%);
  color: rgb(32 52 206 / 45%);
  font-size: clamp(11px, 1vw, 14px);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
}

.sponsoren__slot--frei {
  border: 0;
  background: var(--gelb);
  rotate: 2deg;
}

.sponsoren__slot--frei a {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  color: var(--blau);
  line-height: 1.15;
  text-decoration: none;
}

.sponsoren :focus-visible,
.anfahrt :focus-visible {
  outline-color: var(--blau);
}

/* ── Anfahrt ──────────────────────────────────────────────────────────────
   Gelb, die Karte als blaue Fläche — wie ein Container. Schematisch,
   gezeichnet in SVG, keine eingebettete Karte. Bewegung startet, wenn die
   Karte ins Bild kommt (main.js, `data-anim`): Straßen zeichnen sich,
   der Container schwebt ein, auf dem Fußweg vom ZOB laufen zwei Punkte. */

.anfahrt {
  background: var(--gelb);
  color: var(--blau-nacht);
  padding-block: clamp(48px, 8vw, 110px);
  scroll-margin-top: 80px;
}

.anfahrt__wrap {
  display: grid;
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}

.anfahrt__wrap > * {
  min-width: 0;
}

.anfahrt__adresse {
  margin-top: clamp(18px, 2.4vw, 28px);
  font-style: normal;
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.35;
}

.anfahrt__adresse b {
  display: block;
  font-size: 1.2em;
  color: var(--blau);
}

.anfahrt__wege {
  display: grid;
  gap: 14px;
  margin-top: clamp(20px, 2.6vw, 30px);
}

.anfahrt__wege li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px;
  align-items: start;
}

.anfahrt__wege b {
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--blau);
}

.anfahrt__wege p {
  margin-top: 2px;
  color: #2c3660;
}

.anfahrt__icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  background: var(--blau);
  color: var(--weiss);
  font-weight: 800;
}

.anfahrt__icon--bus {
  border-radius: 50%;
  background: var(--blau-nacht);
  color: var(--gelb);
}

.anfahrt__icon--ticket {
  background: var(--weiss);
  color: var(--blau);
}

.anfahrt__links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 14px;
  max-width: 480px;
  margin-top: clamp(22px, 3vw, 32px);
}

.anfahrt__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 18px;
  background: var(--blau);
  color: var(--weiss);
  font-weight: 800;
  font-size: 0.92em;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 5px 5px 0 var(--blau-nacht);
  transition: translate 0.15s ease, box-shadow 0.15s ease;
}

.anfahrt__btn--hell {
  background: var(--weiss);
  color: var(--blau);
}

.anfahrt__btn:hover {
  translate: -2px -2px;
  box-shadow: 7px 7px 0 var(--blau-nacht);
}

.anfahrt__btn svg {
  flex: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.anfahrt__btn svg circle {
  fill: currentColor;
  stroke: none;
}

.karte-schema {
  margin: 0 12px 12px 0;
  box-shadow: 12px 12px 0 var(--blau-nacht);
  rotate: 1deg;
}

.karte-schema svg {
  display: block;
  width: 100%;
  height: auto;
  font-family: var(--schrift);
}

.ks-strasse {
  fill: none;
  stroke: rgb(255 255 255 / 85%);
  stroke-width: 22;
  stroke-linecap: round;
}

.ks-strasse--klein {
  stroke: rgb(255 255 255 / 35%);
  stroke-width: 10;
}

.ks-strassenname {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: var(--blau);
}

.ks-strassenname--klein {
  font-size: 11px;
  fill: rgb(255 255 255 / 70%);
}

.ks-weg {
  fill: none;
  stroke: var(--gelb);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-dasharray: 2 12;
}

.ks-person {
  fill: var(--gelb);
  stroke: var(--blau);
  stroke-width: 2;
  offset-path: path('M120 335 C 150 385, 220 402, 290 397 C 325 394, 325 320, 315 272');
  offset-distance: 0%;
  opacity: 0;
}

.ks-p text,
.ks-zob text {
  font-size: 30px;
  font-weight: 800;
}

.ks-p text {
  fill: var(--blau);
}

.ks-zob text {
  fill: var(--blau);
}

.ks-label {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  fill: var(--weiss);
}

.ks-container-schrift {
  font-size: 20px;
  font-weight: 800;
  fill: var(--weiss);
}

.ks-container-klein {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.2em;
  fill: var(--gelb);
}

.ks-hinweis {
  font-size: 11px;
  fill: rgb(255 255 255 / 55%);
}

/* Bewegung — erst mit .is-sichtbar, und nur ohne „Bewegung reduzieren". */
@media (prefers-reduced-motion: no-preference) {
  .js .karte-schema .ks-strasse {
    stroke-dasharray: 900;
    stroke-dashoffset: 900;
  }

  .js .karte-schema .ks-container {
    translate: 0 -320px;
  }

  .js .karte-schema .ks-p,
  .js .karte-schema .ks-zob {
    opacity: 0;
  }

  .karte-schema.is-sichtbar .ks-strasse {
    animation: zeichnen 1.4s ease-out forwards;
  }

  .karte-schema.is-sichtbar .ks-strasse--klein {
    animation-delay: 0.3s;
  }

  .karte-schema.is-sichtbar .ks-container {
    animation: einschweben 1.3s cubic-bezier(0.3, 1.25, 0.5, 1) 0.6s forwards,
      pendeln 6s ease-in-out 2s infinite;
    transform-origin: 490px 70px;
  }

  .karte-schema.is-sichtbar .ks-p {
    animation: aufploppen 0.5s ease-out 1.2s forwards;
  }

  .karte-schema.is-sichtbar .ks-zob {
    animation: aufploppen 0.5s ease-out 1.35s forwards;
  }

  .karte-schema.is-sichtbar .ks-weg {
    animation: marschieren 1.2s linear infinite;
  }

  .karte-schema.is-sichtbar .ks-person {
    animation: laufen 5s ease-in-out 1.6s infinite;
  }

  .karte-schema.is-sichtbar .ks-person--2 {
    animation-delay: 4.1s;
  }
}

@keyframes zeichnen {
  to { stroke-dashoffset: 0; }
}

@keyframes einschweben {
  to { translate: 0 0; }
}

@keyframes pendeln {
  0%, 100% { rotate: 0deg; }
  50% { rotate: 1.5deg; }
}

@keyframes aufploppen {
  from { opacity: 0; scale: 0.4; }
  to { opacity: 1; scale: 1; }
}

@keyframes marschieren {
  to { stroke-dashoffset: -28; }
}

@keyframes laufen {
  0% { offset-distance: 0%; opacity: 0; }
  10% { opacity: 1; }
  85% { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* ── KI-Hinweis ───────────────────────────────────────────────────────────
   Die Flohmarkt-Bilder sind KI-generiert und sehen aus wie echte Fotos.
   Gekennzeichnet mit einem kleinen ✦ in der Ecke; der Satz erscheint bei
   Hover, Fokus oder Antippen (nav.js). Für Screenreader steht er immer im
   Dokument — nur unsichtbar, nicht entfernt. Entwurf 03 aus dem Vergleich
   vom 29.10.2026. Das Bild braucht `position: relative`. */

.ki {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 6px;
}

.ki__zeichen {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(0 0 0 / 35%);
  color: var(--weiss);
  font: inherit;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}

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

.ki__text {
  order: -1;
  padding: 2px 7px 3px;
  background: rgb(12 20 85 / 78%);
  color: var(--weiss);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
  opacity: 0;
  translate: 6px 0;
  transition: opacity 0.2s ease, translate 0.2s ease;
}

.ki:hover .ki__text,
.ki__zeichen:focus-visible + .ki__text,
.ki__zeichen[aria-expanded='true'] + .ki__text {
  opacity: 1;
  translate: 0 0;
}

/* ── Fuß ─────────────────────────────────────────────────────────────────
   Entwurf 03 aus entwuerfe/footer/: Logo mit Termin, dann Festival, Hilfe,
   Folgen; darunter Rechtliches und Clubinio. */

.footer {
  background: var(--blau-nacht);
  color: #dfe4ff;
  padding-block: clamp(36px, 5vw, 64px);
  font-size: 0.92em;
}

.footer .wrap {
  display: grid;
  gap: 28px 24px;
  grid-template-columns: 1fr 1fr;
}

.footer a {
  color: inherit;
  text-underline-offset: 4px;
}

.footer a:hover {
  color: var(--gelb);
}

.footer__spalte {
  display: grid;
  gap: 6px;
  align-content: start;
  justify-items: start;
}

.footer__spalte:first-child {
  grid-column: 1 / -1;
}

.footer__brand img {
  display: block;
  width: 110px;
  height: auto;
}

.footer__termin {
  margin-top: 10px;
  font-size: 0.86em;
  color: #aeb9f0;
}

.footer__label {
  margin-bottom: 6px;
  font-size: 0.72em;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gelb);
}

.footer__social svg {
  display: block;
  width: 28px;
  height: 28px;
}

.footer__unten {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 14px 24px;
  padding-top: 22px;
  border-top: 1px solid rgb(255 255 255 / 15%);
}

.footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  font-size: 0.88em;
  color: #aeb9f0;
}

.footer__powered img {
  display: block;
  width: 110px;
  height: auto;
  opacity: 0.7;
}

.footer__powered:hover img {
  opacity: 1;
}

/* ── Ab 760 px: Querformat ───────────────────────────────────────────────
   Der Wechsel hängt am Bild, nicht an einem Spaltenlayout — Spalten gibt es
   hier keine mehr. Das Hochformat über eine Tabletbreite gezogen wäre ein
   Container von 1300 px Höhe. */

@media (min-width: 760px) {
  /* Ein Bild über die ganze Bühne, unten verankert: Wie hoch die Bühne
     auch wird, Palmen und Dreiecke stehen am Fuß, nach oben wächst Himmel.
     `cover` darf hier skalieren — die Container sind nicht mehr im Bild. */
  .stage__oben {
    inset: 0;
  }

  .stage__oben picture,
  .stage__oben img {
    width: 100%;
    height: 100%;
  }

  .stage__oben img {
    object-fit: cover;
    object-position: 50% 100%;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .stage__unten {
    display: none;
  }

  .stage__mid {
    padding-bottom: clamp(70px, 8vw, 150px);
  }

  /* Die ganze Vorlage, randlos über die volle Breite. */
  .rig {
    align-self: center;
    width: 100vw;
    margin-left: 0;
  }

  /* Ab hier kein Stern, sondern ein Schild, das unter dem Datums-Container
     an zwei Seilen hängt. Dieselbe Neigung wie dessen Unterkante. */
  .rig__teil--stoerer {
    --x: 53.8%;
    --y: 72%;
    --w: 36%;
    aspect-ratio: auto;
    background: var(--gelb);
    box-shadow: 6px 6px 0 var(--blau);
    rotate: -7deg;
  }

  /* Das Schild steht mittig unter dem Container, dort lag dieser Balken. */
  .rig__teil--b4 {
    --x: 85%;
    --y: 88%;
  }

  .rig__teil--stoerer::before,
  .rig__teil--stoerer::after {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 12%;
    width: 3px;
    height: 70%;
    background: rgb(50 50 50 / 75%);
  }

  .rig__teil--stoerer::after {
    left: auto;
    right: 12%;
  }

  .rig__teil--stoerer svg,
  .stoerer__text br {
    display: none;
  }

  .stoerer__text {
    grid-template-columns: 1fr auto;
    gap: 1.6cqw 4cqw;
    width: 100%;
    padding: 4.6cqw 5cqw 4.2cqw;
    text-align: left;
  }

  .stoerer__text b {
    grid-column: 1 / -1;
    order: -1;
    font-size: 9.9cqw;
    white-space: nowrap;
  }

  .stoerer__text small {
    font-size: 4.7cqw;
    letter-spacing: 0.06em;
  }

  .bar {
    width: min(44%, 700px);
  }

  .bar--location {
    width: min(39%, 627px);
  }

  .bar--countdown {
    width: min(44%, 700px);
  }

  .flohmarkt__wrap {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .lineup__head {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .anpacken__head {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .anpacken__karten {
    grid-template-columns: 1fr 1fr;
  }

  /* Die Collage: vier Spalten, sechs Zeilen, jede Fläche fest vergeben.
     Ein `dense`-Raster würde je nach Breite Löcher lassen; so passt es
     immer. Hochformate stehen in den hohen Flächen, damit `cover` bei ihnen
     wenig abschneidet. */
  .recap__wrap {
    padding-inline: var(--rand);
  }

  .recap__grid {
    display: grid;
    overflow: visible;
    padding-inline: 0;
    gap: clamp(6px, 0.8vw, 12px);
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-rows: repeat(6, clamp(120px, 15vw, 220px));
    grid-template-areas:
      'c c e p'
      'c c e b'
      'h h w b'
      'f f w y'
      's s l y'
      'g g a a';
  }

  .recap__item {
    height: auto;
    max-width: none;
    overflow: hidden;
  }

  .recap__item img,
  .recap__item--c img,
  .recap__item--h img,
  .recap__item--f img,
  .recap__item--s img,
  .recap__item--a img,
  .recap__item--g img,
  .recap__item--p img,
  .recap__item--l img {
    width: 100%;
    height: 100%;
    transition: scale 0.5s cubic-bezier(0.2, 0.85, 0.25, 1);
  }

  .recap__item:hover img {
    scale: 1.04;
  }

  .recap__item--c {
    grid-area: c;
  }

  .recap__item--e {
    grid-area: e;
  }

  .recap__item--p {
    grid-area: p;
  }

  .recap__item--b {
    grid-area: b;
  }

  .recap__item--h {
    grid-area: h;
  }

  .recap__item--w {
    grid-area: w;
  }

  .recap__item--f {
    grid-area: f;
  }

  .recap__item--y {
    grid-area: y;
  }

  .recap__item--s {
    grid-area: s;
  }

  .recap__item--a {
    grid-area: a;
  }

  .recap__item--g {
    grid-area: g;
  }

  .recap__item--l {
    grid-area: l;
  }


  .footer .wrap {
    grid-template-columns: 1.2fr 1fr 1fr 1fr;
  }

  .footer__spalte:first-child {
    grid-column: auto;
  }
}


/* ── Ab 1100 px: Links in der Leiste, kein Menü-Knopf ── */

@media (min-width: 1100px) {
  .flohmarkt {
    min-height: 500px;
    padding-top: clamp(48px, 6vw, 80px);
  }

  .flohmarkt__bild {
    position: absolute;
    inset: 0 0 0 36%;
    margin: 0;
    aspect-ratio: auto;
    clip-path: polygon(40% 0, 100% 0, 100% 100%, 0 100%);
  }

  /* Die blaue Schräge vor der Bildkante. */
  .flohmarkt::before {
    content: '';
    position: absolute;
    inset: 0 0 0 36%;
    z-index: 1;
    background: var(--blau);
    clip-path: polygon(37% 0, 40% 0, 3% 100%, 0 100%);
  }

  .flohmarkt__wrap {
    position: relative;
    z-index: 2;
    grid-template-columns: minmax(0, 470px);
    margin-left: max(0px, calc((100vw - var(--bahn)) / 2));
  }

  .fragen__wrap {
    grid-template-columns: minmax(0, 1fr) minmax(460px, 600px);
  }

  .sponsoren__wrap {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  }

  .anfahrt__wrap {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  }

  .topbar__nav {
    display: flex;
    gap: 26px;
  }

  .topbar__nav a {
    font-weight: 700;
    font-size: 0.86em;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--weiss);
  }

  .topbar__nav a:hover,
  .topbar__nav a[aria-current='page'] {
    color: var(--gelb);
  }

  .topbar__menu {
    display: none;
  }

  /* Instagram nur im Menü, nicht in der Zeile — dort steht es im Fuß. */
  .topbar__social {
    display: none;
  }
}

/* ── Ab 1360 px: Verkauf rechts im Himmel ───────────────────────────────
   Die Container rücken nach links oben, der Verkauf steht rechts daneben
   im offenen Himmel, Leisten und Countdown unter den Containern. Das geht
   erst, seit die Container Einzelteile sind: Vorher steckten sie im Bild,
   und der Verkauf musste sich nach ihnen richten.

   Die Container bleiben in ihrem Rahmen — derselben Komposition wie
   darunter, nur kleiner. */

@media (min-width: 1360px) {
  .stage__mid {
    width: 100%;
    max-width: var(--bahn-weit);
    margin-inline: auto;
    padding: 0 clamp(28px, 3.6vw, 72px) clamp(56px, 5vw, 110px);
    display: grid;
    align-items: start;
    justify-items: center;
    gap: 14px clamp(28px, 4vw, 72px);
    grid-template-columns: minmax(0, 1fr) minmax(430px, 560px);
    grid-template-areas:
      'rig   shop'
      'count shop'
      'genre shop'
      'ort   shop'
      '.     shop';
  }

  .stage--bald .stage__mid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'rig'
      'count';
  }

  .rig {
    grid-area: rig;
    width: 100%;
  }

  .stage--bald .rig {
    width: min(100%, 1040px);
  }

  .bar--genre {
    grid-area: genre;
  }

  .bar--location {
    grid-area: ort;
  }

  .bar--countdown {
    grid-area: count;
  }

  .shop {
    grid-area: shop;
    align-self: start;
    justify-self: stretch;
    width: 100%;
    max-width: none;
    /* Ganz oben gibt es keine Kopfleiste, der Verkauf darf bis an den
       Himmel. Beim Scrollen schiebt sich die Leiste darüber — gewolltes
       Verhalten einer festen Leiste. */
    margin-top: clamp(36px, 3.4vw, 56px);
  }

  /* Schmaler als die Container darüber — sonst stehlen die Leisten ihnen
     die Schau. Das Verhältnis der beiden ist das des Flyers (86,76 % zu
     77,69 %). */
  .bar,
  .bar--countdown {
    width: min(64%, 520px);
  }

  .bar--location {
    width: min(57.4%, 466px);
  }
}

/* ── Bewegung aus ─────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .rig__lauf div {
    animation: none;
  }

  .js .stage .rig__lauf,
  .js .stage .rig,
  .js .stage .rig__teil,
  .js .stage .shop,
  .js .stage .bar {
    opacity: 1;
    animation: none !important;
  }

  * {
    transition-duration: 0.01ms !important;
  }

  .karte:hover .karte__bild img {
    scale: none;
  }
}
