/* WELTRAD – Rundgang am Fluss
   Ein Skalar treibt das Glas: --dissolve (1 = Schleier voll da, 0 = aufgelöst).
   Beim Scrubben schreibt main.js den Wert direkt; beim Ankommen legt .is-easing
   Transitions darüber, sodass derselbe Wert weich einschwebt. */

@font-face {
  font-family: 'Hanken Grotesk';
  src: url('assets/fonts/hanken-grotesk-var.woff2') format('woff2');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Cormorant';
  src: url('assets/fonts/cormorant-var.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Cormorant';
  src: url('assets/fonts/cormorant-italic-var.woff2') format('woff2');
  font-weight: 300 700;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Joane Engraved';
  src: url('assets/fonts/joane-engraved-regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Grundton der Clips: warmes Ufer-Olivbraun, keine harten Schwarz/Weiß-Kanten */
  --color-bg: #3b3527;
  --font-body: 'Hanken Grotesk', 'Avenir Next', 'Seravek', 'Segoe UI', sans-serif;
  --font-display: 'Cormorant', 'Didot', 'Bodoni MT', Georgia, serif;
  --font-hero: 'Joane Engraved', 'Cormorant', 'Didot', Georgia, serif;
  --text-color: #fff;
  --color-ivory: #f5efe3;
  --glass-blur: 3px;
  --glass-tint: rgba(255, 255, 255, 0.06);
  --ease-calm: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-in: 0.7s;
  --dur-out: 0.5s;
}

* { box-sizing: border-box; }

html {
  overscroll-behavior-y: none;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--text-color);
  font-family: var(--font-body);
  font-weight: 350;
  -webkit-font-smoothing: antialiased;
}

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

.stage {
  --dissolve: 0;
  /* Vorfrost: hebt in den letzten Bildern eines Warps nur das Glas
     (nie den Text) – der Schnitt auf die ruhende Station liegt dann
     schon unter dem Schleier. main.js treibt ihn bildgenau am Clip. */
  --frost: 0;
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  z-index: 1;
}

.layers {
  position: absolute;
  inset: 0;
  transition: transform 1.1s var(--ease-calm);
}

.layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  background: var(--color-bg);
}

.layer--visible { opacity: 1; }

/* Rückwärts-/Sprungwechsel: weiche Überblendung statt Warp */
.layers--fade .layer { transition: opacity var(--dur-out) var(--ease-calm); }

.layer--warp { z-index: 2; }
.layer--fading {
  opacity: 0;
  transition: opacity 0.3s var(--ease-calm);
}

/* ---------- Bildausschnitt Hochformat (Touch-Geräte) ---------- */

/* Die Clips sind breite Totalen; ein Hochformat-Telefon sähe nur einen
   schmalen Streifen. Darum ist der Loop hier breiter als der Schirm und
   ruht auf dem Blickpunkt – früher glitt er langsam über die Fassade
   (Blickpunkt → linker Rand → rechter Rand), dieser Ambient-Schwenk ist
   nun bewusst abgeschaltet. --focus und --clip-aspect setzt main.js. */
.layer--pan {
  --stage-h: 100vh;
  width: calc(var(--stage-h) * var(--clip-aspect, 1.7985));
  height: 100%;
  left: 0;
  right: auto;
  --pan-min: calc(100vw - var(--stage-h) * var(--clip-aspect, 1.7985));
  --pan-home: clamp(var(--pan-min),
                    calc(50vw - var(--focus, 0.5) * var(--stage-h) * var(--clip-aspect, 1.7985)),
                    0px);
  /* In Ruhe (Poster, noch kein Bildlauf) steht das Bild exakt dort, wo die
     Animation beginnt – Standbild und Schwenkstart sind per Konstruktion
     dieselbe Position, nichts kann springen. */
  transform: translateX(var(--pan-home));
}

/* Der seitliche Ambient-Schwenk ist abgeschaltet: Der Loop bleibt fest
   auf dem Blickpunkt (--pan-home) – derselben Lage, an der auch der Warp
   ansetzt. 'is-live' wird von main.js weiter gesetzt, treibt aber keine
   Bewegung mehr; parkPan/settlePan errechnen so eine Drift von 0. */

@supports (height: 100dvh) {
  .layer--pan { --stage-h: 100dvh; }
}

/* Eingefangen: vor der Reise weich auf den Blickpunkt gleiten – dort
   übernimmt der Warp ohne Sprung. Die Dauer setzt main.js nach Distanz
   (inline transition-duration); der Warp wartet, bis sie verstrichen ist. */
.layer--pan-park {
  transition: transform 0.5s var(--ease-calm);
}

/* ---------- Der Schleier ---------- */

.veil {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  /* Der weiße Glas-Frost UND ein leiser dunkler Grund, der nur in Ruhe atmet:
     er hebt den hellen Text über dem hellen Video, ohne die Reise zu
     verdunkeln – der dunkle Anteil hängt allein an --dissolve und weicht beim
     Warp wieder ganz. (0.34 = Startwert, frei justierbar.) */
  background:
    rgb(255 255 255 / calc(max(var(--dissolve), var(--frost)) * 0.06)),
    rgb(20 24 20 / calc(var(--dissolve) * 0.34));
  -webkit-backdrop-filter: blur(calc(max(var(--dissolve), var(--frost)) * var(--glass-blur)));
  backdrop-filter: blur(calc(max(var(--dissolve), var(--frost)) * var(--glass-blur)));
}

/* ---------- Glastext ---------- */

.panel {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  /* iPhone-Sicherheitsränder: an notch-losen Geräten ist env()=0, also bleibt
     2rem; auf dem iPhone weicht der mittige Block Notch/Home-Indikator/Seiten-
     Notch (Querformat) aus. Gleiches Muster bei .intro/.finale/.loader__inner. */
  padding: max(2rem, env(safe-area-inset-top)) max(2rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(2rem, env(safe-area-inset-left));
  text-align: center;
  text-decoration: none;
  color: var(--text-color);
  pointer-events: none;          /* nur in Ruhe klickbar, siehe .is-hot */
}

.panel.is-hot {
  pointer-events: auto;          /* die Schatullen/Knöpfe darin werden klickbar … */
  cursor: default;               /* … die Fläche selbst führt aber nirgendwohin */
}

/* Stille Vignette hinter dem Textblock: sichert die Lesbarkeit über hellen
   Bildpartien und atmet mit dem Schleier. */
.panel::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 58% at 50% 50%, rgb(18 22 18 / 0.64), transparent 76%);
  opacity: var(--dissolve);
}

.panel > * {
  position: relative;
  margin: 0;
  max-width: 34em;
  text-shadow: 0 1px 4px rgb(14 17 14 / 0.66), 0 4px 20px rgb(14 17 14 / 0.62), 0 8px 48px rgb(14 17 14 / 0.5);
  transform: translateY(calc((1 - var(--dissolve)) * 10px));
}

/* Die Küchenzeile über dem Namen: kleine Kapitälchen-Geste mit Haarlinien */
.panel__intro {
  display: inline-flex;
  align-items: center;
  gap: 1.5em;
  font-size: clamp(0.82rem, 1.5vw, 0.98rem);
  font-weight: 500;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--color-ivory);
  opacity: clamp(0, calc((var(--dissolve) - 0.45) / 0.55), 1);
}
/* Ohne Text wirklich verschwinden: das display:inline-flex oben überstimmt sonst
   das [hidden]-Attribut, sodass auf Hotel/Fahrrad die beiden Haarlinien (leer)
   stehen blieben. */
.panel__intro[hidden] { display: none; }

.panel__intro::before,
.panel__intro::after {
  content: '';
  width: 3.4em;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgb(245 239 227 / 0.9));
}

.panel__intro::after {
  background: linear-gradient(270deg, transparent, rgb(245 239 227 / 0.9));
}

/* Der leise Vorname über dem Hausnamen: „Weltrad" über „Hotel" –
   zusammen gelesen, ohne den großen Schriftzug zu überladen. */
.panel__kicker {
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.3vw, 1.6rem);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--color-ivory);
  margin-bottom: -0.4rem;
  opacity: clamp(0, calc((var(--dissolve) - 0.45) / 0.55), 1);
}

/* Der Hausname trägt die Seite: gravierte Großserife, raumfüllend.
   Eine Schnittstärke – keine synthetische Fettung, die Gravur bliebe
   sonst nicht sauber. Der weiche Schein bleibt zart, damit die feinen
   Innenlinien der Gravur lesbar bleiben. */
.panel__label {
  font-family: var(--font-hero);
  font-size: clamp(3.4rem, 11vw, 9rem);
  font-weight: 400;
  font-synthesis: none;
  line-height: 1.02;
  letter-spacing: calc(0.02em + (1 - var(--dissolve)) * 0.05em);
  text-shadow: 0 1px 3px rgb(16 19 16 / 0.48), 0 4px 30px rgb(16 19 16 / 0.44);
  opacity: clamp(0, calc((var(--dissolve) - 0.45) / 0.55), 1);
  max-width: 100%;                 /* nie über die Spalte hinaus … */
  overflow-wrap: break-word;       /* … notfalls umbrechen statt aus dem Bild laufen */
}


.panel__line {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.3rem, 2.7vw, 1.75rem);
  font-weight: 525;
  /* Dichter an den Helden rücken (gegen die einheitliche Panel-Lücke), damit
     Titel und Zeile als ein Block lesen – der größere Abstand fällt danach zum
     Bilderfluss. */
  margin-top: -0.55rem;
  line-height: 1.45;
  letter-spacing: 0.015em;
  color: var(--color-ivory);
  text-shadow: 0 1px 3px rgb(10 12 10 / 0.8), 0 3px 16px rgb(10 12 10 / 0.66), 0 8px 40px rgb(10 12 10 / 0.5);
  opacity: clamp(0, calc((var(--dissolve) - 0.55) / 0.45), 1);
}

/* Die Wahl je Haus: eine oder mehrere offene Haarlinien-Schatullen –
   ungefüllt in Ruhe, beim Verweilen läuft die Füllung elfenbeinfarben
   von links ein. */
/* Mehrere Schatullen werden gleich breit (so breit wie die längste): gleich große
   Spalten, jeder Knopf füllt seine Spalte, Text mittig – dasselbe gleichmäßige
   Paar wie im Auftakt, ohne den „verschieden groß"-Eindruck. Ein einzelner Knopf
   (Hotel) bleibt inhaltsbreit und mittig. */
.panel__actions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  justify-content: center;
  gap: 1rem 1.2rem;
  margin-top: 2.2rem;
  max-width: none;
  opacity: clamp(0, calc((var(--dissolve) - 0.72) / 0.28), 1);
}

.panel__action {
  position: relative;
  z-index: 0;
  overflow: hidden;
  display: inline-block;
  padding: 1.05em 2.9em;
  font-size: clamp(0.82rem, 1.5vw, 0.92rem);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  text-decoration: none;
  text-shadow: 0 1px 3px rgb(16 19 16 / 0.5);
  color: var(--text-color);
  border: 1px solid rgb(245 239 227 / 0.72);
  /* Einen Hauch mehr Frost als der Schleier: das Glas der Schatulle blurrt den
     (vom Schleier bereits leicht geblurrten) Grund noch eine Spur weiter und
     liegt einen Tick heller darüber – so bleibt der Knopf auch unberührt sichtbar.
     Der eigene Blur stapelt sich auf den Schleier, darum genügt ein winziger Wert.
     An denselben --dissolve/--frost gekoppelt, damit er mit dem Glas kommt/geht. */
  background: rgb(255 255 255 / calc(max(var(--dissolve), var(--frost)) * 0.085));
  -webkit-backdrop-filter: blur(calc(max(var(--dissolve), var(--frost)) * 1.25px));
  backdrop-filter: blur(calc(max(var(--dissolve), var(--frost)) * 1.25px));
  transition:
    color 0.45s var(--ease-calm),
    border-color 0.45s var(--ease-calm);
}

.panel__action::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-ivory);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.5s var(--ease-calm);
}

/* Nur die Schatulle selbst reagiert – nicht die ganze klickbare Bühne. */
.panel.is-hot .panel__action:hover,
.panel.is-hot .panel__action:focus-visible {
  border-color: var(--color-ivory);
  color: #33301f;
  text-shadow: none;          /* dunkler Text auf elfenbein gefüllter Schatulle */
  outline: none;
}

.panel.is-hot .panel__action:hover::before,
.panel.is-hot .panel__action:focus-visible::before {
  transform: scaleX(1);
}

/* ---------- Bilderfluss ---------------------------------------------------
   Unter dem Hausnamen lädt ein zartes Symbol zu den Bildern ein. Es öffnet
   einen vollflächigen Strom: die Aufnahmen ziehen wie ein Fluss von links
   nach rechts, frei verschiebbar. Berühren (mobil) bzw. Klicken vergrößert
   eine Aufnahme; am Desktop wächst sie beim Überfahren eine Spur, beim Klick
   ganz. Schließen jederzeit über das Kreuz, die Leertaste außerhalb, oder Esc.
   ------------------------------------------------------------------------- */

/* Der Einladungs-Bilderfluss: winzige Vorschau-Abzüge treiben durch ein
   knopfgroßes, an beiden Rändern gefiedertes Fenster – ein lebendiger Vorbote
   der Galerie, in der Haarlinien-/Glas-Sprache der Seite, kein loses Symbol. */
.panel__river {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  margin: 0.85rem auto 0;        /* deutlicher Abstand zur Titel-Zeilen-Gruppe darüber */
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* erscheint mit dem Untertitel, nicht vor ihm */
  opacity: clamp(0, calc((var(--dissolve) - 0.62) / 0.38), 1);
}

.panel__river[hidden] { display: none; }

/* Das Fenster: knopfgroß, an beiden Rändern weich ausgefiedert, damit die
   Abzüge an einer Kante hereintreiben und an der anderen vergehen. */
.panel__river-window {
  display: block;
  width: clamp(11rem, 58vw, 16rem);
  height: 2.7rem;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 17%, #000 83%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 17%, #000 83%, transparent);
}

/* Die Bahn: zweimal dieselbe Folge, läuft per Animation um -50 % nahtlos um.
   Die Dauer setzt main.js nach Bahnbreite (so bleibt das Tempo je Station gleich). */
.panel__river-track {
  display: flex;
  width: max-content;
  height: 100%;
  will-change: transform;
  animation: panel-river-flow 30s linear infinite;
}

@keyframes panel-river-flow {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

.panel__river-track img {
  height: 100%;
  width: auto;
  display: block;
  margin-right: 0.42rem;
  border: 1px solid rgb(245 239 227 / 0.32);
  /* leicht verschleiert – auf der Temperatur der Seite; klärt beim Verweilen auf */
  filter: saturate(0.72) brightness(0.84);
  transition: filter 0.55s var(--ease-calm);
}

/* Reagiert auf Berührung, OHNE stehenzubleiben: die Abzüge klären auf, der
   Fluss läuft weiter. Nur in Ruhe klickbar (siehe .panel.is-hot). */
.panel.is-hot .panel__river:hover .panel__river-track img,
.panel.is-hot .panel__river:focus-visible .panel__river-track img {
  filter: saturate(1) brightness(1);
}
.panel__river:focus-visible { outline: none; }
.panel.is-hot .panel__river:focus-visible .panel__river-window {
  outline: 2px solid rgb(245 239 227 / 0.7);
  outline-offset: 3px;
}

/* Die Bildunterschrift: ein ruhiges Kapitälchen im Duktus der Satelliten. */
.panel__river-cap {
  font-family: var(--font-body);
  font-size: clamp(0.6rem, 1.15vw, 0.7rem);
  font-weight: 500;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  text-transform: uppercase;
  color: var(--color-ivory);
  text-shadow: 0 1px 3px rgb(16 19 16 / 0.5);
}

@media (prefers-reduced-motion: reduce) {
  .panel__river-track { animation: none; }
}

/* Die Bühne des Stroms. Über allem (der Lader ist längst fort). */
.gallery {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  background: rgb(26 28 22 / 0.82);
  -webkit-backdrop-filter: blur(20px) saturate(0.9);
  backdrop-filter: blur(20px) saturate(0.9);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.55s var(--ease-calm), visibility 0s linear 0.55s;
}

.gallery[hidden] { display: none; }

.gallery.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.55s var(--ease-calm);
}

.gallery__bar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* Notch-sichere Kopfleiste: das Schließen-✕ sitzt am rechten Ende und darf
     nicht unter Dynamic Island/Seiten-Notch rutschen. Ohne Notch ist env()=0,
     also bleibt der bisherige clamp-Wert. */
  padding: max(clamp(1rem, 3.2vh, 1.9rem), env(safe-area-inset-top)) max(clamp(1.1rem, 4.5vw, 2.8rem), env(safe-area-inset-right)) 0 max(clamp(1.1rem, 4.5vw, 2.8rem), env(safe-area-inset-left));
}

.gallery__title {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.2rem, 2.6vw, 1.7rem);
  letter-spacing: 0.01em;
  color: var(--color-ivory);
  display: inline-flex;
  align-items: baseline;
  gap: 0.9em;
}

.gallery__close {
  flex: none;
  width: 3rem;
  height: 3rem;
  border-radius: 999px;
  border: 1px solid rgb(245 239 227 / 0.5);
  background: rgb(255 255 255 / 0.05);
  color: var(--color-ivory);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.4s var(--ease-calm), border-color 0.4s var(--ease-calm), transform 0.4s var(--ease-calm);
}

.gallery__close svg { width: 1.05rem; height: 1.05rem; display: block; }

.gallery__close:hover,
.gallery__close:focus-visible {
  background: var(--color-ivory);
  border-color: var(--color-ivory);
  color: #33301f;
  outline: none;
  transform: scale(1.05);
}

/* Der Strom selbst: eine waagerechte Bahn, frei zu schieben. */
.gallery__river {
  flex: 1;
  min-height: 0;
  padding: clamp(1rem, 3vh, 2rem) clamp(1.2rem, 7vw, 7rem);
  overflow: hidden;                /* der Strom wird per translateX geführt, nicht nativ gerollt */
  overscroll-behavior: contain;
  touch-action: none;              /* Ziehen führen wir selbst – für Maus UND Berührung */
  user-select: none;
  cursor: grab;
}

/* Drei Ströme übereinander – jeder läuft mit eigener Periode endlos um (translateX
   in main.js). Der Wickel füllt nur die Bahn; die Reihen ragen darüber hinaus und
   werden von der Bahn beschnitten. */
.gallery__streams {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: clamp(0.7rem, 1.8vh, 1.5rem);
}

.gallery__stream {
  flex: 1;
  min-height: 0;
  width: max-content;              /* so breit wie ihre (vervielfachten) Bilder */
  display: flex;
  align-items: center;
  gap: clamp(0.6rem, 1.7vw, 1.5rem);
  will-change: transform;
}

.gallery__river.is-dragging { cursor: grabbing; }
.gallery__river::-webkit-scrollbar { height: 6px; }
.gallery__river::-webkit-scrollbar-track { background: transparent; }
.gallery__river::-webkit-scrollbar-thumb {
  background: rgb(245 239 227 / 0.25);
  border-radius: 999px;
}

.gallery__item {
  position: relative;
  flex: none;
  height: var(--h, 90%);          /* Anteil der Stromhöhe – leichte Varianz wirkt lebendig */
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  border-radius: 3px;
  overflow: hidden;
  cursor: zoom-in;
  box-shadow: 0 12px 44px rgb(0 0 0 / 0.4);
  transform: translateY(var(--drift, 0px));
  transition: transform 0.55s var(--ease-calm), box-shadow 0.55s var(--ease-calm);
}

.gallery__item img {
  display: block;
  height: 100%;
  width: auto;
  border-radius: inherit;
  user-select: none;
  -webkit-user-drag: none;         /* kein Geister-Bild beim Ziehen */
  pointer-events: none;            /* Ziel des Zeigers bleibt der Knopf */
}

/* Eine kleine Standzeit nach dem Öffnen, dann ziehen die Bilder herein. */
.gallery__item {
  opacity: 0;
  animation: gallery-arrive 0.7s var(--ease-calm) forwards;
  animation-delay: var(--in, 0s);
}

@keyframes gallery-arrive {
  from { opacity: 0; transform: translateY(calc(var(--drift, 0px) + 26px)); }
  to   { opacity: 1; transform: translateY(var(--drift, 0px)); }
}

@media (hover: hover) and (pointer: fine) {
  .gallery__item:hover {
    transform: translateY(var(--drift, 0px)) scale(1.05);
    box-shadow: 0 22px 70px rgb(0 0 0 / 0.55);
    z-index: 2;
  }
}

/* Leere Plätze für das Fahrradhaus, solange keine Aufnahmen vorliegen. */
.gallery__item--blank {
  cursor: default;
  height: var(--h, 90%);
  aspect-ratio: var(--ar, 3 / 2);   /* Breite folgt der Höhe – kein Bild zum Vermessen */
  background: rgb(245 239 227 / 0.045);
  border: 1px solid rgb(245 239 227 / 0.16);
  box-shadow: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgb(245 239 227 / 0.22);
}

.gallery__item--blank svg { width: 2.6rem; height: 2.6rem; display: block; }

@media (hover: hover) and (pointer: fine) {
  .gallery__item--blank:hover { transform: translateY(var(--drift, 0px)); box-shadow: none; }
}


/* Die größte Ansicht: ein Bild allein, mittig, über dem Strom. */
.gallery__focus {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3.5rem);
  background: rgb(18 20 16 / 0.66);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  cursor: zoom-out;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.42s var(--ease-calm), visibility 0s linear 0.42s;
}

.gallery__focus.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.42s var(--ease-calm);
}

.gallery__focus img {
  max-width: min(92vw, 1200px);
  max-height: 86vh;
  width: auto;
  height: auto;
  border-radius: 3px;
  box-shadow: 0 34px 100px rgb(0 0 0 / 0.6);
  transform: scale(0.95);
  transition: transform 0.46s var(--ease-calm);
}

.gallery__focus.is-open img { transform: scale(1); }

body.gallery-open { overflow: hidden; }

@media (max-width: 720px) {
  .gallery__river { padding-left: clamp(1rem, 5vw, 2rem); padding-right: clamp(1rem, 5vw, 2rem); }
  .gallery__focus img { max-height: 80vh; }
  /* der Bilderfluss wird auf dem Telefon eine Spur niedriger */
  .panel__river-window { height: 2.4rem; }
}

@media (prefers-reduced-motion: reduce) {
  .gallery, .gallery.is-open,
  .gallery__focus, .gallery__focus.is-open,
  .gallery__focus img,
  .gallery__item { transition-duration: 0.01s; }
  .gallery__item { animation: none; opacity: 1; }
}

/* ---------- Rechtliche Texte als Schleier (Impressum/Datenschutz/Kontakt) ---
   Dieselbe Glas-Sprache wie die Galerie: ein gefrosteter Schleier über dem
   Standbild, der ruhig langen Lesetext trägt. Der Inhalt kommt zur Laufzeit
   aus den gleichnamigen Seiten (main.legal); gestaltet wird er hier mit den
   Marken-Tokens, damit der Übergang aus dem Rundgang nahtlos bleibt. */
.legal-overlay {
  position: fixed;
  inset: 0;
  z-index: 130;                                  /* über der Galerie (120) */
  display: flex;
  flex-direction: column;
  background: rgb(26 28 21 / 0.88);
  -webkit-backdrop-filter: blur(22px) saturate(0.9);
  backdrop-filter: blur(22px) saturate(0.9);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.55s var(--ease-calm), visibility 0s linear 0.55s;
}
.legal-overlay[hidden] { display: none; }
.legal-overlay.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.55s var(--ease-calm);
}

.legal-overlay__bar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  max-width: 72ch;
  margin: 0 auto;
  /* Notch-sicher wie .gallery__bar. */
  padding: max(clamp(1rem, 3.2vh, 1.9rem), env(safe-area-inset-top)) max(clamp(1.25rem, 5vw, 2.5rem), env(safe-area-inset-right)) 0 max(clamp(1.25rem, 5vw, 2.5rem), env(safe-area-inset-left));
}
.legal-overlay__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.3rem, 3vw, 1.9rem);
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--color-ivory);
}
.legal-overlay__close {
  flex: none;
  width: 3rem;
  height: 3rem;
  border-radius: 999px;
  border: 1px solid rgb(245 239 227 / 0.5);
  background: rgb(255 255 255 / 0.05);
  color: var(--color-ivory);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.4s var(--ease-calm), border-color 0.4s var(--ease-calm), transform 0.4s var(--ease-calm);
}
.legal-overlay__close svg { width: 1.05rem; height: 1.05rem; display: block; }
.legal-overlay__close:hover,
.legal-overlay__close:focus-visible {
  background: var(--color-ivory);
  border-color: var(--color-ivory);
  color: #33301f;
  outline: none;
  transform: scale(1.05);
}

/* Die Lesefläche: frei scrollbar, eine ruhige Spalte mittig. */
.legal-overlay__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgb(245 239 227 / 0.3) transparent;
  color: rgb(245 239 227 / 0.9);
  font-family: var(--font-body);
  font-weight: 350;
  font-size: 1.0625rem;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
.legal-overlay__scroll:focus { outline: none; }
.legal-overlay__scroll::-webkit-scrollbar { width: 8px; }
.legal-overlay__scroll::-webkit-scrollbar-track { background: transparent; }
.legal-overlay__scroll::-webkit-scrollbar-thumb {
  background: rgb(245 239 227 / 0.22);
  border-radius: 999px;
}

.legal-overlay .legal {
  max-width: 64ch;
  margin: 0 auto;
  padding: clamp(1.4rem, 3.5vh, 2.4rem) clamp(1.25rem, 5vw, 2.5rem) clamp(3rem, 9vh, 6rem);
}
.legal-overlay .legal [id] { scroll-margin-top: 1rem; }
.legal-overlay .legal h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.4rem, 3.5vw, 1.8rem);
  line-height: 1.2;
  color: var(--color-ivory);
  margin: 2.75rem 0 0.85rem;
}
.legal-overlay .legal h3 {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.02rem;
  letter-spacing: 0.01em;
  color: var(--color-ivory);
  margin: 1.6rem 0 0.5rem;
}
.legal-overlay .legal p { margin: 0 0 1rem; }
.legal-overlay .legal strong { color: var(--color-ivory); font-weight: 600; }
.legal-overlay .legal a {
  color: var(--color-ivory);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: rgb(245 239 227 / 0.32);
  word-break: break-word;
}
.legal-overlay .legal a:hover { text-decoration-color: currentColor; color: #fff; }
.legal-overlay .legal ul { margin: 0 0 1rem; padding-left: 1.2rem; }
.legal-overlay .legal li { margin: 0.2rem 0; }
.legal-overlay .legal .lead { color: rgb(245 239 227 / 0.92); font-size: 1.12rem; }
.legal-overlay .legal .meta { color: rgb(245 239 227 / 0.6); font-size: 0.92rem; }
.legal-overlay .legal address { font-style: normal; margin: 0 0 1rem; line-height: 1.6; }
.legal-overlay .legal dl.contact {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1.25rem;
  margin: 0 0 1.5rem;
}
.legal-overlay .legal dl.contact dt { color: rgb(245 239 227 / 0.6); }
.legal-overlay .legal dl.contact dd { margin: 0; }
.legal-overlay .legal .toc { columns: 2; column-gap: 2.5rem; }
.legal-overlay .legal .toc li { break-inside: avoid; }
@media (max-width: 560px) { .legal-overlay .legal .toc { columns: 1; } }
.legal-overlay a:focus-visible {
  outline: 2px solid var(--color-ivory);
  outline-offset: 3px;
  border-radius: 2px;
}

body.legal-open { overflow: hidden; }

/* Lite: dieselbe flächige Tönung wie bei der Galerie statt teurer Unschärfe. */
html.lite .legal-overlay {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: rgb(22 24 19 / 0.97);
}

@media (prefers-reduced-motion: reduce) {
  .legal-overlay, .legal-overlay.is-open { transition-duration: 0.01s; }
}

/* Ankommen: dieselben Werte, nur weich – Schleier zuerst, Text gestaffelt,
   das „Eintreten" zuletzt. */
.is-easing .veil {
  transition:
    background-color var(--dur-in) var(--ease-calm),
    -webkit-backdrop-filter var(--dur-in) var(--ease-calm),
    backdrop-filter var(--dur-in) var(--ease-calm);
}

.is-easing .panel__intro,
.is-easing .panel__kicker,
.is-easing .panel__label {
  transition:
    opacity var(--dur-in) var(--ease-calm) 0.22s,
    transform var(--dur-in) var(--ease-calm) 0.22s,
    letter-spacing var(--dur-in) var(--ease-calm) 0.22s;
}

.is-easing .panel__line {
  transition:
    opacity var(--dur-in) var(--ease-calm) 0.38s,
    transform var(--dur-in) var(--ease-calm) 0.38s;
}

.is-easing .panel__actions {
  transition:
    opacity var(--dur-in) var(--ease-calm) 0.55s,
    transform var(--dur-in) var(--ease-calm) 0.55s;
}

/* Durch die Tür: kleines Hineinwachsen, weiches Abdunkeln – kein Blitz */
.stage::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background: var(--color-bg);
  opacity: 0;
  transition: opacity 0.9s var(--ease-calm);
}

.stage.is-entering .layers { transform: scale(1.045); }
.stage.is-entering::after { opacity: 0.45; }
.stage.is-entering .veil,
.stage.is-entering .panel { transition: opacity 0.6s var(--ease-calm); opacity: 0; }

/* ---------- Zielmarke (eigener Mauszeiger) ---------- */

/* Nur auf Geräten mit feiner Zeigerführung: eine elegante Zielmarke –
   Haarlinienring mit Kardinalstrichen, Lichtkern und leisem Schein.
   Der native Cursor verschwindet erst, wenn die Marke wirklich lebt. */
@media (pointer: fine) {
  html.has-cursor,
  html.has-cursor * {
    cursor: none !important;
  }
}

.cursor-dot,
.cursor-scope {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s var(--ease-calm);
}

.cursor-dot.is-on,
.cursor-scope.is-on { opacity: 1; }

/* Der Lichtkern folgt der Hand unmittelbar */
.cursor-dot {
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  border-radius: 50%;
  background: var(--color-ivory);
  box-shadow: 0 0 8px rgb(245 239 227 / 0.9), 0 0 2px rgb(245 239 227 / 1);
}

/* Die Zielmarke schwebt mit leichtem Nachlauf hinterher: ein Kreis mit
   einem Schnitt durch die Mitte – zwei symmetrische Außenbögen,
   dazwischen Leere. */
.cursor-scope {
  width: 38px;
  height: 38px;
  margin: -19px 0 0 -19px;
}

/* Die beiden Bögen: maskierter Haarlinienring, weich leuchtend */
.cursor-scope::before {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid rgb(245 239 227 / 0.8);
  border-radius: 50%;
  -webkit-mask: linear-gradient(90deg, #000 0 36%, transparent 36% 64%, #000 64% 100%);
  mask: linear-gradient(90deg, #000 0 36%, transparent 36% 64%, #000 64% 100%);
  filter: drop-shadow(0 0 6px rgb(245 239 227 / 0.55));
  transition: opacity 0.35s var(--ease-calm);
}

/* Der leise Schein dahinter */
.cursor-scope::after {
  content: '';
  position: absolute;
  inset: -9px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(245 239 227 / 0.18), transparent 62%);
  opacity: 0.75;
  transition: opacity 0.35s var(--ease-calm);
}

/* Über Klickbarem verschwinden die Bögen – nur das Licht bleibt */
.cursor-scope.is-active::before {
  opacity: 0;
}

.cursor-scope.is-active::after {
  opacity: 1;
}

/* ---------- Stationen-Leiste (Karussell-Anzeige) ---------- */

/* Linke Kante: was war, was ist, was kommt. Erscheint nur in Ruhe –
   die Deckkraft hängt am selben Schleier-Skalar wie alles andere. */
.rail {
  position: absolute;
  /* Querformat: hinter dem Seiten-Notch nicht verschwinden (env()=0 sonst). */
  left: max(clamp(1.4rem, 3.5vw, 3.2rem), env(safe-area-inset-left));
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  opacity: var(--dissolve);
  pointer-events: none;
}

.rail ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.9rem;
}

.rail button {
  display: inline-flex;
  align-items: center;
  gap: 1.1em;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  text-align: left;
  line-height: 1.6;
  max-width: 24ch;
  color: rgb(255 255 255 / 0.97);
  text-shadow: 0 1px 3px rgb(10 12 10 / 0.92), 0 2px 12px rgb(10 12 10 / 0.92), 0 0 22px rgb(10 12 10 / 0.55);
  pointer-events: none;
  transition: color 0.35s var(--ease-calm);
}

.stage.is-hot .rail button { pointer-events: auto; }

/* Der Strich führt von der Kante zur Schrift */
.rail button::before {
  content: '';
  flex: none;
  width: 1.4em;
  height: 1px;
  background: currentColor;
  transition: width 0.45s var(--ease-calm), background-color 0.35s var(--ease-calm);
}

.rail button:hover,
.rail button:focus-visible {
  color: rgb(255 255 255 / 1);
  outline: none;
}

.rail .is-current button {
  color: var(--color-ivory);
}

.rail .is-current button::before {
  width: 3.8em;
  background: var(--color-ivory);
}

@media (max-width: 720px) {
  .rail { left: max(1rem, env(safe-area-inset-left)); }
  .rail ol { gap: 1.3rem; }
  .rail button { font-size: 0.74rem; max-width: 17ch; }
  /* Auf kleinen Schirmen tragen nur die Striche die Nachbarn,
     die aktuelle Station behält ihren Namen. */
  .rail li:not(.is-current) .rail__label { display: none; }
}

/* Hochformat-Telefone: ruhigere Sperrungen, schlankere Schatullen,
   die Leiste nur noch als Striche mit ausreichender Tippfläche. */
@media (max-width: 520px) {
  .panel { padding: max(1.25rem, env(safe-area-inset-top)) max(1.25rem, env(safe-area-inset-right)) max(1.25rem, env(safe-area-inset-bottom)) max(1.25rem, env(safe-area-inset-left)); gap: 0.9rem; }
  /* Auf Telefonen folgt der Hausname der Breite (statt fester 3.4rem-Boden, der
     »Restaurant« bis an den Rand drückte) – bleibt so mit Luft zur Kante. */
  .panel__label { font-size: clamp(1.7rem, 10.5vw, 3.6rem); }
  /* Die Kapitälchen-Zeile schmaler halten: kürzere Striche, engerer Abstand –
     die Haarlinien sitzen nah am Text statt weit an den Bildrändern. */
  .panel__intro { letter-spacing: 0.2em; gap: 0.85em; }
  .panel__intro::before,
  .panel__intro::after { width: 1.25em; }
  .panel__kicker { letter-spacing: 0.22em; text-indent: 0.22em; }
  /* Auf dem Telefon bleiben zwei Schatullen nebeneinander (nie untereinander):
     die Reihe bricht nicht mehr um, und die Knöpfe schrumpfen stattdessen mit
     der Schirmbreite – Schrift per vw mit festem Boden, engere Sperrung und
     schlankere Polsterung. Das längste Paar (»mieten« / »Fahrradhandel«) passt
     so bis hinab zu sehr schmalen Geräten. Ein einzelner Knopf (Hotel) bleibt
     unberührt inhaltsbreit und mittig. NB: vw, nicht cqi – siehe Notiz. */
  .panel__actions { gap: 0.6rem; margin-top: 1.8rem; }
  .panel__action {
    min-width: 0;
    padding: 0.85em 1.1em;
    font-size: clamp(0.66rem, 3vw, 0.86rem);
    letter-spacing: 0.14em;
    text-indent: 0.14em;
    white-space: nowrap;
  }
  .rail { left: 0.9rem; }
  .rail .rail__label { display: none; }
  .rail ol { gap: 0.5rem; }
  .rail button { padding: 0.75rem 0.5rem 0.75rem 0; }
  .scroll-nav { width: 3rem; height: 3rem; }
  .scroll-nav svg { width: 1.75rem; }
}

/* Leiste an der Oberkante. Gesetzt von main.js (updateRailPlacement) – nicht
   per Media-Query: nicht nur Hochkant-Telefonen geht der linke Rand aus, sondern
   jedem Schirm, auf dem der große, mittig zentrierte Hausname die seitliche
   Leiste streifen würde. Dann läuft sie quer, im selben Duktus wie die senkrechte
   Fassung: Strich führt zur Schrift, alle Namen bleiben sichtbar, die aktuelle
   Station trägt den langen Strich. (Der Rundgang braucht ohnehin JavaScript –
   ohne JS gibt es keine Leiste, daher ist die Klassensteuerung sicher.) */
.stage.rail-top .rail {
  left: 0;
  right: 0;
  top: 0;
  transform: none;
  padding-top: max(0.95rem, env(safe-area-inset-top));
}
.stage.rail-top .rail ol {
  flex-direction: row;
  align-items: center;
  gap: clamp(0.8rem, 3.5vw, 1.5rem);
  padding: 0 1rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.stage.rail-top .rail ol::-webkit-scrollbar { display: none; }
/* Mittig, solange die Reihe passt; läuft sie über (sehr schmale Geräte),
   bleibt der Anfang erreichbar – darum auto-Ränder statt justify-content. */
.stage.rail-top .rail li:first-child { margin-left: auto; }
.stage.rail-top .rail li:last-child { margin-right: auto; }
.stage.rail-top .rail button {
  /* Oben darf die Reihe eine Spur größer stehen als auf dem schmalsten Telefon –
     Strich und Abstände sind em-basiert und wachsen mit. Auf sehr schmalen
     Geräten bleibt die Reihe scrollbar (overflow-x am ol), bricht also nicht. */
  font-size: clamp(0.66rem, 2.7vw, 0.82rem);
  letter-spacing: 0.2em;
  gap: 0.8em;
  max-width: none;
  white-space: nowrap;
  padding: 0.72rem 0.1rem;
}
.stage.rail-top .rail li:not(.is-current) .rail__label,
.stage.rail-top .rail .rail__label { display: inline; }
/* Quer ist Breite das knappe Gut: der lange Strich wächst auf gut das Doppelte
   statt aufs 2,7-Fache – die Geste bleibt, die Reihe verschiebt sich kaum. */
.stage.rail-top .rail .is-current button::before { width: 2.6em; }
/* Quer liegt die Leiste an der Oberkante – die Aufwärts-Spitze bleibt bei 15vh,
   fällt aber nie höher als knapp unter die Stationen-Reihe. */
.stage.rail-top .scroll-nav--up { top: max(15vh, calc(env(safe-area-inset-top) + 4.5rem)); }

/* ---------- Auftakt: Überblick vor dem Rundgang ----------
   Großes WELTRAD über der Stationen-Reihe (der echten Leiste, hierher
   verlegt), darunter »Entdecken«. Beim Start gleiten dieselben Knöpfe in
   die senkrechte Navigationsleiste – ein Karussell, das sich nur umordnet. */
.intro {
  position: absolute;
  inset: 0;
  z-index: 6;                       /* über Bild, Schleier, Glastext */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(2rem, env(safe-area-inset-top)) max(2rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(2rem, env(safe-area-inset-left));
  text-align: center;
  opacity: 0;                       /* fällt der Vorhang, blendet der Auftakt ein */
  transition: opacity 0.9s var(--ease-calm);
}
.intro.is-in { opacity: 1; }
.intro[hidden] { display: none; }

/* Stille Verdunklung, damit Wortmarke und Stationen über dem hellen
   Restaurant-Standbild ruhig lesbar bleiben – derselbe Duktus wie die
   Vignette hinter dem Glastext. */
.intro::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 72% 62% at 50% 46%, rgb(22 26 22 / 0.5), transparent 72%),
    linear-gradient(rgb(22 26 22 / 0.26), rgb(22 26 22 / 0.46));
}

.intro__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(2rem, 6vh, 3.6rem);
  max-width: min(92vw, 60rem);
}

/* Wortmarke als Logo – der Auftakt-Held über Leiste und Knöpfen. Der
   Schatten der Textfassung lebt als drop-shadow weiter, damit das Weiß
   auch über dem hellen Restaurant-Standbild ruhig steht. */
.intro__mark {
  display: block;
  width: min(82vw, 33rem);
  max-width: 100%;
  height: auto;
  filter: drop-shadow(0 1px 3px rgb(20 24 20 / 0.4)) drop-shadow(0 6px 44px rgb(20 24 20 / 0.45));
}

/* Der Slot, in dem im Auftakt die echte Stationen-Leiste sitzt. */
.intro__rail { position: relative; }

/* »Entdecken« und »Kontakt« stehen nebeneinander in einer Reihe, mittig;
   auf sehr schmalen Telefonen darf »Kontakt« darunter umbrechen. */
/* Beide Knöpfe exakt gleich breit (so breit wie der längere): zwei gleich
   große Spalten, der Knopf füllt seine Spalte, Text mittig. Damit verschwindet
   die optische Täuschung „unterschiedlich groß" – sie sind ein gleiches Paar.
   Die 1fr-Spalten richten sich am breiteren Inhalt aus und skalieren mit. */
.intro__actions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  justify-content: center;
  gap: clamp(0.9rem, 2.6vw, 1.6rem);
}

/* »Entdecken« – dieselbe Haarlinien-Schatulle wie die Stationswahl,
   hier dauerhaft klickbar (nicht an --dissolve gekoppelt). */
.intro__cta {
  position: relative;
  z-index: 0;
  overflow: hidden;
  display: inline-block;
  white-space: nowrap;             /* einzeilig: gleiche Höhe; die Breite kommt aus der Gitterspalte */
  padding: 1.05em 2.9em;
  font-family: var(--font-body);
  font-size: clamp(0.82rem, 1.5vw, 0.92rem);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  color: var(--color-ivory);
  background: rgb(255 255 255 / 0.06);
  border: 1px solid rgb(245 239 227 / 0.72);
  text-shadow: 0 1px 3px rgb(16 19 16 / 0.5);
  cursor: pointer;
  transition: color 0.45s var(--ease-calm), border-color 0.45s var(--ease-calm);
}
.intro__cta::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-ivory);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.5s var(--ease-calm);
}
.intro__cta:hover,
.intro__cta:focus-visible {
  border-color: var(--color-ivory);
  color: #33301f;
  text-shadow: none;
  outline: none;
}
.intro__cta:hover::before,
.intro__cta:focus-visible::before { transform: scaleX(1); }

/* Auf Telefonen bleiben »Entdecken« und »Kontakt« nebeneinander: ein etwas
   knapperes Polster und engere Sperrung lassen beide in eine Zeile passen –
   bis hinab zu sehr schmalen Geräten; kein Umbruch mehr. */
@media (max-width: 500px) {
  .intro { padding: max(1.5rem, env(safe-area-inset-top)) max(1.5rem, env(safe-area-inset-right)) max(1.5rem, env(safe-area-inset-bottom)) max(1.5rem, env(safe-area-inset-left)); }
  .intro__mark { width: min(80vw, 22rem); }   /* Logo mit Luft zur Kante */
  .intro__actions { gap: clamp(0.45rem, 2.6vw, 0.85rem); }
  .intro__actions .intro__cta {
    padding: 0.95em 1.15em;
    letter-spacing: 0.15em;
    text-indent: 0.15em;
  }
}

/* Im Auftakt liegt die Leiste waagerecht und mittig statt links-senkrecht –
   gleiche Knöpfe, gleiche Schrift, nur die Anordnung ändert sich. Sie ist
   hier reiner Überblick (kein Sprung), darum ohne Zeiger. */
body.is-intro { overflow: hidden; }
.is-intro .rail {
  position: static;
  left: auto;
  top: auto;
  transform: none;
  opacity: 1;
}
/* Im Überblick sind die Stationen Links (zur jeweiligen Buchung/Seite),
   darum hier klickbar – anders als die nur-in-Ruhe klickbare Leiste im
   Rundgang. */
.is-intro .rail,
.is-intro .rail button { pointer-events: auto; }
.is-intro .rail ol {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(1.4rem, 5vw, 3.4rem);
}

/* Auf Telefonen bleibt die Auftakt-Reihe immer einzeilig: die drei
   Stationen stehen stets nebeneinander, nichts rutscht darunter. Kein
   Umbruch; Abstand, Schrift und Strich skalieren mit der Breite, damit
   alle drei in eine Zeile passen – in Hoch- wie Querformat. */
@media (max-width: 720px) {
  .is-intro .rail ol {
    flex-wrap: nowrap;
    gap: clamp(0.55rem, 3.2vw, 1.6rem);
  }
  .is-intro .rail button {
    font-size: clamp(0.5rem, 2.7vw, 0.72rem);
    letter-spacing: 0.12em;
    gap: 0.55em;
    max-width: none;
    white-space: nowrap;
  }
  .is-intro .rail button::before { width: 0.9em; }
  .is-intro .rail .is-current button::before { width: 1.6em; }
  /* Im Überblick tragen alle Stationen ihren Namen, auch im Querformat. */
  .is-intro .rail li:not(.is-current) .rail__label,
  .is-intro .rail .rail__label { display: inline; }
}

/* Übergang Auftakt → Rundgang: die fliegende Leiste bleibt sichtbar und
   liegt über dem ausblendenden Auftakt, bis --dissolve sie wieder trägt. */
.stage.is-launch .rail { opacity: 1; z-index: 7; }

@media (prefers-reduced-motion: reduce) {
  .intro { transition-duration: 0.01s; }
}

/* ---------- Hinweise ---------- */

/* Wegweiser-Pfeilspitzen: oben/unten mittig, als echte Knöpfe (großzügige
   Tippfläche). Sie ruhen unsichtbar; main.js gibt je Abschnitt eine Richtung
   frei (.can-nav-up / .can-nav-down auf der Bühne). Die Deckkraft bleibt – wie
   beim früheren Hinweis – an --dissolve gekoppelt, also verblassen sie im Warp
   und kehren in der Ruhe zurück. */
.scroll-nav {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;                       /* über dem Panel-Klickfeld (4), unter dem Auftakt (6) */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.4rem;                    /* nur Tippfläche ≥ 44px; sichtbar ist allein die Spitze */
  height: 3.4rem;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  /* Keine Scheibe – nur die Spitze. Ein enger dunkler Saum (drop-shadow ohne
     Versatz) gibt ihr eine Kontur, damit die weiße Spitze auch auf hellem,
     unruhigem Video klar steht; ein zweiter, weicherer Schatten setzt sie ab. */
  filter:
    drop-shadow(0 0 2px rgb(10 12 10 / 0.9))
    drop-shadow(0 1px 6px rgb(10 12 10 / 0.7));
  cursor: pointer;
  opacity: 0;                       /* erst sichtbar, wenn die Richtung freigegeben ist */
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.6s var(--ease-calm), filter 0.4s var(--ease-calm);
  -webkit-tap-highlight-color: transparent;
}
.scroll-nav svg { width: 2rem; height: auto; display: block; }
.scroll-nav svg path { stroke-width: 2.6; }   /* kräftige Spitze, klar lesbar */

/* Etwa auf halbem Weg zwischen Schirmrand und dem mittigen Glastext – nicht
   mehr an die Kante geklemmt, sondern näher an die Hauptsache herangerückt. */
.scroll-nav--down { bottom: 15vh; }
.scroll-nav--up   { top: 15vh; }

/* Freigabe der jeweiligen Richtung: sichtbar, klickbar. Voll deckend in der
   Ruhe (--dissolve = 1), und im Warp mit dem Glas verblassend (--dissolve → 0). */
.stage.can-nav-down .scroll-nav--down,
.stage.can-nav-up .scroll-nav--up {
  visibility: visible;
  pointer-events: auto;
  opacity: var(--dissolve);
}

.scroll-nav:hover,
.scroll-nav:focus-visible {
  filter:
    drop-shadow(0 0 2px rgb(10 12 10 / 0.95))
    drop-shadow(0 1px 8px rgb(10 12 10 / 0.8));
}
.scroll-nav:focus-visible {
  outline: 2px solid var(--color-ivory);
  outline-offset: 6px;
  border-radius: 6px;
}

/* Ruhiges Wippen in Reiserichtung – nur, wo Bewegung erwünscht ist. Die
   Deckkraft bleibt hoch (kein Verschwinden), das Wippen ist der Hinweis. */
@media (prefers-reduced-motion: no-preference) {
  .scroll-nav--down svg { animation: nav-bob-down 2.6s var(--ease-calm) infinite; }
  .scroll-nav--up svg   { animation: nav-bob-up 2.6s var(--ease-calm) infinite; }
}
@keyframes nav-bob-down {
  0%, 100% { transform: translateY(-0.22rem); opacity: 0.9; }
  50%      { transform: translateY(0.22rem);  opacity: 1; }
}
@keyframes nav-bob-up {
  0%, 100% { transform: translateY(0.22rem);  opacity: 0.9; }
  50%      { transform: translateY(-0.22rem); opacity: 1; }
}

/* ---------- Vorhang (Ladebild) ---------- */

/* Solange der Vorhang steht, scrollt nichts: die Reise beginnt bei null. */
body.is-booting { overflow: hidden; }

.loader {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background:
    radial-gradient(ellipse 95% 75% at 50% 36%, rgb(74 67 48 / 0.5), transparent 72%),
    var(--color-bg);
  transition: opacity 1.1s var(--ease-calm), visibility 0s linear 1.1s;
}

.loader.is-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.loader__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.4rem;
  padding: max(2rem, env(safe-area-inset-top)) max(2rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(2rem, env(safe-area-inset-left));
}

/* Die Wortmarke als Logo – klein und ruhig über dem Ring (kein Plakat). */
.loader__mark {
  display: block;
  width: clamp(190px, 48vw, 270px);
  height: auto;
  animation: loader-breathe 3.6s var(--ease-calm) infinite;
}

/* Fortschritt als Haarlinien-Ring, Prozentzahl mittig. Der Bogen beginnt
   oben (Drehung um −90°); den Stand treibt main.js über stroke-dashoffset
   (Umfang 2π·46 ≈ 289 im 100er-viewBox). */
.loader__ring {
  position: relative;
  width: clamp(96px, 24vw, 118px);
  aspect-ratio: 1;
}

.loader__ring svg {
  display: block;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  overflow: visible;
}

.loader__track,
.loader__arc {
  fill: none;
  stroke-width: 1.5;
}

.loader__track {
  stroke: rgb(245 239 227 / 0.14);
}

.loader__arc {
  stroke: var(--color-ivory);
  stroke-linecap: round;
  stroke-dasharray: 289.03;
  stroke-dashoffset: 289.03;
  filter: drop-shadow(0 0 6px rgb(245 239 227 / 0.35));
  transition: stroke-dashoffset 0.2s linear;
}

.loader__pct {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.92rem;
  font-weight: 330;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  font-variant-numeric: tabular-nums;
  color: rgb(245 239 227 / 0.85);
}

.loader__unit {
  margin-left: 0.22em;
  font-size: 0.72em;
  color: rgb(245 239 227 / 0.55);
}

/* Leer im Normalfall; trägt nur die Fehlermeldung, falls copy.json scheitert. */
.loader__status {
  margin: 0;
  min-height: 1em;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 0.95rem;
  font-weight: 420;
  letter-spacing: 0.06em;
  color: rgb(245 239 227 / 0.66);
}

@keyframes loader-breathe {
  0%, 100% { opacity: 0.78; }
  50%      { opacity: 1; }
}

/* ---------- Scrollstrecke ---------- */

.track {
  position: relative;
  z-index: 0;
  /* Startwert vor dem Boot; main.js setzt die exakte Höhe
     (Zonen × 160 % Viewport plus Finale-Strecke). */
  height: 580vh;
}

/* ---------- Finale: letzte Frostung über dem Standbild ---------- */

/* --epilogue läuft 0 → 1, während der Besucher hinter der letzten Station
   weiterscrollt. Der Schleier legt sich zurück aufs Bild, der Abschluss
   schwebt als Glas darüber. */
.finale {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2.2rem;
  padding: max(2rem, env(safe-area-inset-top)) max(2rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(2rem, env(safe-area-inset-left));
  text-align: center;
  visibility: hidden;
  pointer-events: none;
}

.stage.is-epilogue .finale { visibility: visible; }
/* Nur die Rechts-Verweise fangen Klicks – nicht der ganze, deckungsgleiche
   Schleier: er liegt (gleiche z-Ebene, später im DOM) über der Aufwärts-Spitze
   und würde sonst deren Klick schlucken, sodass aus dem Finale nur das Scrollen
   zurückführt. So bleibt die Spitze der zugesagte Weg zurück. */
.finale.is-ready .finale__legal { pointer-events: auto; }

/* Eigene stille Vignette für die Lesbarkeit des Abschlusses */
.finale::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 52% at 50% 50%, rgb(22 26 22 / 0.45), transparent 74%);
  opacity: var(--epilogue, 0);
}

.finale > * {
  margin: 0;
  transform: translateY(calc((1 - var(--epilogue, 0)) * 22px));
}

/* Vier dünne Worte, untereinander, mittig – sie allein tragen den Abschluss.
   Jedes Wort schwebt mit eigenem Versatz ein, von oben nach unten. */
.finale__legal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.6rem, 4vh, 2.6rem);
  font-size: clamp(0.95rem, 2.4vw, 2.2rem);
  font-weight: 250;
  letter-spacing: 0.12em;
  text-indent: 0.12em;
  text-transform: uppercase;
}

.finale__legal a {
  --at: 0.4;                /* Epilog-Stand, ab dem dieses Wort einschwebt */
  color: rgb(245 239 227 / 0.8);
  text-decoration: none;
  text-shadow: 0 1px 3px rgb(16 19 16 / 0.55), 0 1px 12px rgb(22 26 22 / 0.55);
  opacity: clamp(0, calc((var(--epilogue, 0) - var(--at)) / 0.28), 1);
  transform: translateY(calc(
    (1 - clamp(0, calc((var(--epilogue, 0) - var(--at)) / 0.28), 1)) * 14px));
  transition:
    color 0.4s var(--ease-calm),
    letter-spacing 0.4s var(--ease-calm);
}

.finale__legal a:nth-child(1) { --at: 0.28; }
.finale__legal a:nth-child(2) { --at: 0.38; }
.finale__legal a:nth-child(3) { --at: 0.48; }
.finale__legal a:nth-child(4) { --at: 0.58; }

.finale__legal a:hover,
.finale__legal a:focus-visible {
  color: var(--color-ivory);
  letter-spacing: 0.17em;
  outline: none;
}

/* Schmale Schirme: „Datenschutzerklärung" muss in eine Zeile passen –
   enger gesperrt und eine Stufe kleiner. */
@media (max-width: 640px) {
  .finale__legal {
    font-size: clamp(1rem, 4.8vw, 1.3rem);
    letter-spacing: 0.08em;
    text-indent: 0.08em;
  }
  .finale__legal a:hover,
  .finale__legal a:focus-visible {
    letter-spacing: 0.12em;
  }
}

/* Im Finale schweigt alles andere; der Schleier frostet eine Spur kräftiger. */
/* Im Finale schweigen Panel und Leiste; die Aufwärts-Spitze bleibt als
   einziger Wegweiser zurück (von main.js über .can-nav-up freigegeben). */
.stage.is-epilogue .panel,
.stage.is-epilogue .rail {
  visibility: hidden;
}

.stage.is-epilogue .veil {
  background:
    rgb(255 255 255 / calc(max(var(--dissolve), var(--frost)) * 0.10)),
    rgb(20 24 20 / calc(var(--dissolve) * 0.22));
  -webkit-backdrop-filter: blur(calc(max(var(--dissolve), var(--frost)) * 6px));
  backdrop-filter: blur(calc(max(var(--dissolve), var(--frost)) * 6px));
}

/* ---------- Fallbacks ---------- */

/* Ohne backdrop-filter: solide durchscheinende Fläche hinter dem Text */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .veil,
  .stage.is-epilogue .veil {
    background: rgb(46 52 48 / calc(max(var(--dissolve), var(--frost)) * 0.45));
  }
  .panel__action {
    background: rgb(24 30 28 / 0.55);
  }
}

/* ---------- Lite-Modus: schwache / softwaregerenderte Grafik ----------
   main.js setzt .lite, wenn der Renderer als Software erkannt wird ODER der
   Bildratenwächter anhaltendes Ruckeln misst. Jede ganzflächige backdrop-
   Unschärfe (Schleier, Schatullen, Galerie, Finale) wird je Bild neu über das
   laufende Video gerechnet – das bricht ohne GPU ein. Lite ersetzt sie durch
   eine flächige Tönung (praktisch gratis) und nimmt den Layer-Zoom sowie den
   eigenen Cursor heraus. Das Video und die Reise bleiben unverändert. */
html.lite .veil,
html.lite .stage.is-epilogue .veil {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: rgb(46 52 48 / calc(max(var(--dissolve), var(--frost)) * 0.5));
}
html.lite .panel__action {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: rgb(24 30 28 / 0.55);
}
html.lite .gallery {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: rgb(22 24 19 / 0.95);
}
html.lite .gallery__focus {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: rgb(14 15 12 / 0.92);
}
/* Kein Zoom des Videolayers (zwingt sonst Neuraster je Bild). */
html.lite .stage.is-entering .layers { transform: none; }
/* Eigener Cursor ist reine Zier und kostet je Bild Kompositing. */
html.lite .cursor-dot,
html.lite .cursor-scope { display: none; }

@media (prefers-reduced-motion: reduce) {
  .loader__mark { animation: none; }
  .loader { transition-duration: 0.01s; }
  .layers--fade .layer { transition-duration: 0.25s; }
  .is-easing .veil,
  .is-easing .panel__intro,
  .is-easing .panel__kicker,
  .is-easing .panel__label,
  .is-easing .panel__line,
  .is-easing .panel__actions {
    transition-duration: 0.01s;
    transition-delay: 0s;
  }
  .stage.is-entering .layers { transform: none; }
}

/* ---------- noscript ---------- */

.noscript {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 1rem;
  padding: 2rem;
  background: var(--color-bg);
  text-align: center;
}

.noscript ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }
.noscript a { color: #fff; }
