/* ⚠️ KEIN @import auf theme.css. Der Import macht aus dem Laden eine Kette:
   HTML wartet auf globals.css, globals.css auf theme.css, theme.css auf die drei
   Schriften — drei serielle Runden, bevor der erste Buchstabe steht. theme.css wird
   deshalb im <head> davor VERLINKT (siehe tools/glut/build.py), dann laufen beide
   Stylesheets parallel. */

/* ============================================================ Grundlagen */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  background: var(--glut-void);
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: var(--sp-6);
}

body {
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--glut-cream);
  background: var(--glut-void);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }

h1, h2, h3 {
  font-family: var(--ff-display);
  font-weight: 800;
  line-height: var(--lh-head);
  font-stretch: 100%;
  text-wrap: balance;
}

/* Sichtbarer Fokusring, 2 px mit 2 px Versatz (Abschnitt 14). */
:where(a, button, input, select, [tabindex]):focus-visible {
  outline: 2px solid var(--glut-ember);
  outline-offset: 2px;
}

.springen {
  position: absolute; left: -9999px; top: 0; z-index: var(--z-preload);
  background: var(--glut-ember); color: var(--glut-void);
  padding: var(--sp-2) var(--sp-3);
  font-family: var(--ff-mono); font-size: var(--fs-label);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.springen:focus { left: 0; }

/* ============================================================ Raster */
.rand { width: 100%; padding-inline: var(--rand); }
.gitter {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gutter);
}
@media (max-width: 760px) { .gitter { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ============================================================ Bausteine */
.marke-klein {
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--glut-smoke);
}

.knopf {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-1);
  min-height: 48px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid transparent;
  border-radius: var(--r-pille);
  font-family: var(--ff-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  background: var(--glut-ember);
  color: var(--glut-void);
  transition: transform var(--d-kurz) var(--e-grund),
              background-color var(--d-kurz) var(--e-grund),
              color var(--d-kurz) var(--e-grund);
}
.knopf--linie { background: transparent; border-color: var(--glut-ash); color: var(--glut-cream); }
.knopf[disabled] { background: var(--glut-ash); color: var(--glut-smoke); cursor: not-allowed; }
@media (hover: hover) {
  .knopf:not([disabled]):hover { transform: translateY(-2px); }
  .knopf--linie:not([disabled]):hover { border-color: var(--glut-ember); color: var(--glut-ember); }
}
.knopf:not([disabled]):active { transform: scale(0.97); }

/* ============================================================ Korn und Vignette (5.4) */
.korn {
  position: fixed; inset: 0; z-index: var(--z-korn);
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: var(--korn-bild);
  background-size: 220px 220px;
}
.vignette::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  /* ⚠️ MUSS HINTER den Inhalt. Ohne z-index paint ein position:absolute-Pseudoelement
     UEBER dem normalen Textfluss: gemessen wurde dadurch die eigene Wortmarke am
     linken Rand von Creme (#F4EDE3) auf Grau abgedunkelt — das „G" war grau, das „T"
     cremefarben. .szene setzt position:relative + z-index, bildet also einen eigenen
     Stapelkontext; -1 bleibt darin und liegt trotzdem ueber dem Seitenhintergrund. */
  z-index: -1;
  background: var(--verlauf-vignette);
}

/* ============================================================ Szenen */
.szene { position: relative; z-index: var(--z-inhalt); }
.szene--voll { min-height: 100svh; display: grid; align-content: center; }
.szene--flaeche { background: var(--glut-char); }
.szene__kopf { margin-bottom: var(--sp-5); }
.szene__kopf h2 { font-size: var(--fs-h2); }
.szene__nummer { display: block; margin-bottom: var(--sp-2); }

/* --- S1 Hero ---
   Der Abstand oben muss die feste Kopfleiste (77 px) freihalten, darf aber auf
   niedrigen Fenstern nicht 168 px kosten: bei 390x667 allein die Polsterung 272 px.
   Deshalb an der Fensterhoehe bemessen, mit einem Boden ueber der Kopfleiste. */
.hero { padding-block: clamp(88px, 11svh, 168px) clamp(48px, 7svh, 104px); }
.hero__wort {
  font-size: var(--fs-hero);
  line-height: var(--lh-tight);
  font-weight: 900;
  font-stretch: 125%;
  letter-spacing: -0.02em;
  color: var(--glut-cream);
}
.hero__claim { font-size: var(--fs-h2); font-family: var(--ff-display); font-weight: 300;
  color: var(--glut-cream); margin-top: var(--sp-3); }
.hero__claim span { display: block; }
.hero__zahlen { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-5); }
.hero__zahl b { display: block; font-family: var(--ff-mono); font-size: var(--fs-h3);
  color: var(--glut-gold); font-variant-numeric: tabular-nums; }
/* ⚠️ `>` IST HIER NOETIG, NICHT KOSMETIK. Die Regel beschreibt die Beischrift
   („PLATTE", „PRO SEITE") — als `.hero__zahl span` traf sie aber AUCH die Zaehler-
   Huelle <span class="z"> innerhalb des <b>. Ergebnis: die Zahl 340 stand klein und
   grau da, waehrend die Einheit „°C" gross und gold blieb. In keiner Pruefzahl zu
   sehen, im Bildschirmfoto sofort. Die Beischrift ist ein direktes Kind, die Huelle
   ein Enkel — der Kindselektor trennt beide genau. */
.hero__zahl > span { font-size: var(--fs-label); color: var(--glut-smoke);
  font-family: var(--ff-mono); letter-spacing: 0.1em; text-transform: uppercase; }

/* --- S2 Zutaten --- */
.zutat { padding-block: var(--sp-5); border-top: 1px solid var(--glut-ash); }
.zutat__nr { font-family: var(--ff-mono); font-size: var(--fs-label);
  color: var(--glut-smoke); letter-spacing: 0.1em; }
.zutat h3 { font-size: var(--fs-h3); margin-block: var(--sp-1) var(--sp-2); }
.zutat p { color: var(--glut-smoke); max-width: 52ch; }

/* --- S3 Feuer --- */
.feuer__zeile { padding-block: var(--sp-5); border-top: 1px solid var(--glut-ash); }
.feuer__zahl { font-family: var(--ff-mono); font-size: var(--fs-h1);
  color: var(--glut-ember); font-variant-numeric: tabular-nums; display: block; }
.feuer__text { font-family: var(--ff-display); font-size: var(--fs-h3);
  font-weight: 300; color: var(--glut-cream); }

/* --- S4 Karte --- */
.rail { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: var(--gutter); }
.gericht { background: var(--glut-char); border: 1px solid var(--glut-ash);
  border-radius: var(--r-flaeche); display: flex; flex-direction: column; min-width: 0; }
.gericht__bild { aspect-ratio: 4 / 5; background: var(--glut-ash);
  display: grid; place-items: center; overflow: hidden; }
.gericht__bild img { width: 100%; height: 100%; object-fit: cover; }
.gericht__platzhalter { font-family: var(--ff-mono); font-size: var(--fs-label);
  color: var(--glut-smoke); text-align: center; padding: var(--sp-2); line-height: 1.6; }
.gericht__leib { padding: var(--sp-3); display: flex; flex-direction: column; flex: 1; gap: var(--sp-1); }
.gericht h3 { font-size: var(--fs-h3); font-stretch: 88%; }
.gericht p { font-size: 0.94rem; color: var(--glut-smoke); flex: 1; }
.gericht__fuss { display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--sp-2); margin-top: var(--sp-2); }
.gericht__preis { font-family: var(--ff-mono); color: var(--glut-gold); font-size: 1.05rem; }
.gericht--abschluss { justify-content: center; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-4); background: transparent; border-style: dashed; }

/* --- S5 Raum --- */
.raum__text p { margin-bottom: var(--sp-3); max-width: 46ch; color: var(--glut-cream); }
.raum__bilder { display: grid; gap: var(--gutter);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.raum__bild { aspect-ratio: 4 / 3; background: var(--glut-ash); display: grid; place-items: center; }
.raum__bild img { width: 100%; height: 100%; object-fit: cover; }

/* --- S6 Reservierung --- */
/* ⚠️ Das Formular stand allein und 860 px breit in einem 1296 px breiten Band — die
   rechte Haelfte der WICHTIGSTEN Sektion der Seite war leer. Jetzt zwei Spalten:
   Formular links, drei kurze Antworten auf die Fragen, die vor dem Absenden aufkommen,
   rechts. minmax(0,…) statt blankem fr, sonst wird die Inhaltsbreite zum Minimum. */
.res__paar { display: grid; gap: var(--gutter); align-items: start;
  grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) {
  .res__paar { grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); }
}
.res { background: var(--glut-char); border: 1px solid var(--glut-ash);
  padding: clamp(20px, 4vw, 56px); }
.beruhigung { display: grid; gap: var(--sp-4); padding-top: var(--sp-2); }
.beruhigung__punkt p + p { margin-top: var(--sp-1); color: var(--glut-smoke);
  max-width: 34ch; }
.beruhigung__ruf { margin-top: var(--sp-1); }
.res__gruppe { margin-bottom: var(--sp-5); }
.res__label { display: block; margin-bottom: var(--sp-2); }
.res__pillen { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.pille {
  min-height: 44px; padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--glut-ash); border-radius: var(--r-pille);
  background: transparent; color: var(--glut-cream);
  font-family: var(--ff-mono); font-size: var(--fs-label);
  cursor: pointer; letter-spacing: 0.06em;
  transition: border-color var(--d-kurz) var(--e-grund),
              color var(--d-kurz) var(--e-grund);
}
.pille[aria-pressed="true"] { border-color: var(--glut-ember); color: var(--glut-ember); }
.pille[disabled] { color: var(--glut-smoke); text-decoration: line-through; cursor: not-allowed; }
.tage { display: flex; gap: var(--sp-1); overflow-x: auto; padding-bottom: var(--sp-1);
  scroll-snap-type: x proximity; }
.tag { flex: none; min-width: 68px; min-height: 68px; scroll-snap-align: start;
  display: grid; place-content: center; text-align: center; gap: 2px;
  border: 1px solid var(--glut-ash); background: transparent; cursor: pointer;
  font-family: var(--ff-mono); color: var(--glut-cream); }
.tag small { display: block; font-size: 0.68rem; color: var(--glut-smoke); letter-spacing: 0.08em; }
.tag[aria-pressed="true"] { border-color: var(--glut-ember); color: var(--glut-ember); }
.tag[aria-pressed="true"] small { color: var(--glut-ember); }
.tag[disabled] { color: var(--glut-smoke); text-decoration: line-through; cursor: not-allowed; }
.feld { position: relative; margin-bottom: var(--sp-4); }
.feld label { display: block; margin-bottom: var(--sp-1); }
.feld input {
  width: 100%; background: transparent; border: 0; border-bottom: 1px solid var(--glut-ash);
  color: var(--glut-cream); font-family: var(--ff-body); font-size: var(--fs-body);
  padding: var(--sp-1) 0; min-height: 44px; border-radius: 0;
}
.feld input:focus { outline: none; border-bottom-color: var(--glut-ember); }
.feld input:focus-visible { outline: 2px solid var(--glut-ember); outline-offset: 4px; }
.feld__fehler { display: block; margin-top: var(--sp-1);
  font-family: var(--ff-mono); font-size: var(--fs-label); color: var(--glut-flame); }
/* Natives Datumsfeld: die Grundfassung, solange die Tages-Pillen nicht erzeugt sind. */
.feld__datum {
  width: 100%; max-width: 22ch; background: transparent; border: 0;
  border-bottom: 1px solid var(--glut-ash); color: var(--glut-cream);
  font-family: var(--ff-mono); font-size: var(--fs-body);
  padding: var(--sp-1) 0; min-height: 44px; border-radius: 0;
}
.feld__datum:focus { outline: none; border-bottom-color: var(--glut-ember); }
.feld__datum:focus-visible { outline: 2px solid var(--glut-ember); outline-offset: 4px; }
::-webkit-calendar-picker-indicator { filter: invert(1) opacity(0.6); cursor: pointer; }
.res__zustimmung { display: flex; gap: var(--sp-2); align-items: flex-start;
  margin-bottom: var(--sp-4); font-size: 0.94rem; color: var(--glut-smoke); }
.res__zustimmung input { width: 24px; height: 24px; flex: none; accent-color: var(--glut-ember); }
.res__fehlt { margin-top: var(--sp-2); }

/* --- S7 Ort --- */
.zeiten { width: 100%; border-collapse: collapse; font-family: var(--ff-mono);
  font-size: 0.92rem; }
.zeiten td { padding: var(--sp-1) 0; border-bottom: 1px solid var(--glut-ash);
  color: var(--glut-smoke); }
.zeiten td:last-child { text-align: right; }
.zeiten tr[data-heute="1"] td { color: var(--glut-cream); }
.zeiten tr[data-heute="1"] td:first-child::before { content: "▸ "; color: var(--glut-ember); }
.ort__karte { position: relative; aspect-ratio: 4 / 3; background: var(--glut-ash);
  display: grid; place-items: center; }
.ort__karte img { width: 100%; height: 100%; object-fit: cover; }

/* --- S8 Footer --- */
.fuss { padding-block: var(--sp-6) var(--sp-4); position: relative; overflow: hidden; }
/* Zierschrift, aber trotzdem lesbar: auf --glut-ash lag sie bei 1,29:1. */
.fuss__wort { font-family: var(--ff-display); font-size: var(--fs-hero); font-weight: 900;
  font-stretch: 62%; line-height: 0.78; color: var(--glut-ashh);
  letter-spacing: -0.03em; user-select: none; }
.laufband { overflow: hidden; border-block: 1px solid var(--glut-ash);
  padding-block: var(--sp-2); margin-bottom: var(--sp-5); }
.laufband__spur { display: flex; gap: var(--sp-4); white-space: nowrap; }
.laufband span { font-family: var(--ff-mono); font-size: var(--fs-label);
  letter-spacing: 0.2em; color: var(--glut-smoke); }
.fuss__links { display: flex; flex-wrap: wrap; gap: var(--sp-3);
  margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--glut-ash); }
.fuss__links a { font-family: var(--ff-mono); font-size: var(--fs-label);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--glut-smoke);
  padding-block: var(--sp-1); }
.fuss__links a:hover { color: var(--glut-cream); }

/* ============================================================ Bestaendige Bedienung */
.leiste {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-leiste);
  display: flex; align-items: center; justify-content: center;
  min-height: 56px; padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--glut-ember); color: var(--glut-void);
  font-family: var(--ff-mono); font-size: var(--fs-label);
  letter-spacing: 0.14em; text-transform: uppercase;
  transform: translateY(100%);
  /* ⚠️ transform allein reicht NICHT. Ohne visibility bleibt die ausgeparkte Leiste in
     der Tab-Reihenfolge: wer durchtabbt, landet auf einem unsichtbaren Knopf. Genau
     dieser Fehler steckte in 20 Demos dieses Bestands und in der Firmenseite.
     Die Umschaltung kommt ERST NACH dem Wegfahren (visibility 0s linear <Dauer>),
     sonst wird die Bewegung abgeschnitten. Keine Sammelangabe bei transition. */
  visibility: hidden; pointer-events: none;
  transition: transform var(--d-mittel) var(--e-grund),
              visibility 0s linear var(--d-mittel);
}
.leiste[data-sichtbar="1"] {
  transform: none; visibility: visible; pointer-events: auto;
  transition: transform var(--d-mittel) var(--e-grund), visibility 0s;
}
@media (min-width: 900px) {
  .leiste { left: auto; right: var(--rand); bottom: auto; top: var(--sp-3);
    min-height: 44px; padding-inline: var(--sp-4); border-radius: var(--r-pille);
    transform: translateY(-160%); }
}

.kopfleiste {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-leiste);
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-2) var(--rand);
  /* ⚠️ Hier stand `mix-blend-mode: difference`. Das ist elegant gedacht und in der
     Praxis falsch: ueber dunklem Text wird die Kopfzeile fast unsichtbar, ueber
     mitteldunklen Flaechen matschig, und ein Kontrast laesst sich gar nicht mehr
     rechnen (der Wert haengt vom durchscheinenden Inhalt ab). Im Bildschirmfoto lag
     „GLUT MENUE" auf dem Handy quer ueber den Ueberschriften.
     Stattdessen ein Verlauf, der nach unten ausblendet: immer lesbar, messbar,
     und er verdeckt den Inhalt nicht mit einer harten Kante.
     Kein backdrop-filter — die Schublade ist zwar ein Geschwister und kein Kind,
     aber ein Filter hier waere genau die Falle, die in diesem Projekt schon
     dreimal das Handy-Menue zerlegt hat. */
}
.kopfleiste::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 210%;
  background: var(--verlauf-kopf); pointer-events: none; z-index: -1;
}
.kopfleiste__marke { font-family: var(--ff-mono); font-size: var(--fs-label);
  letter-spacing: 0.24em; color: var(--glut-cream); }
.menue-schalter { background: none; border: 0; cursor: pointer;
  font-family: var(--ff-mono); font-size: var(--fs-label); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--glut-cream);
  min-height: 44px; padding-inline: var(--sp-1); }

.overlay {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  background: var(--glut-char);
  display: grid; align-content: center; gap: var(--sp-2);
  padding: var(--rand);
  clip-path: circle(0% at 100% 0%);
  visibility: hidden;
  transition: clip-path var(--d-mittel) var(--e-beides), visibility 0s linear var(--d-mittel);
}
.overlay[data-offen="1"] { clip-path: circle(150% at 100% 0%); visibility: visible;
  transition: clip-path var(--d-mittel) var(--e-beides), visibility 0s; }
.overlay a { font-family: var(--ff-display); font-size: var(--fs-h1); font-weight: 800;
  font-stretch: 100%; color: var(--glut-cream); padding-block: var(--sp-1); width: fit-content; }
@media (hover: hover) { .overlay a:hover { color: var(--glut-ember); } }
.overlay__schliessen { position: absolute; top: var(--sp-2); right: var(--rand); }

.fortschritt {
  position: fixed; z-index: var(--z-leiste); background: var(--glut-ember);
  transform-origin: 0 0; pointer-events: none;
}
@media (max-width: 899px) { .fortschritt { top: 0; left: 0; right: 0; height: 2px;
  transform: scaleX(var(--fort, 0)); } }
@media (min-width: 900px) { .fortschritt { top: 0; bottom: 0; left: 0; width: 2px;
  transform: scaleY(var(--fort, 0)); } }

/* ============================================================ Vorlader
   ⚠️ ER MELDET SICH AN, ER MELDET SICH NICHT AB. Standardmaessig ist er WEG.
   Sichtbar wird er NUR, wenn scripts/motion.js zu Beginn data-vorlader="laeuft"
   setzt — also nur dann, wenn es ueberhaupt etwas zu laden gibt.

   Zwei Fehler steckten in der ersten Fassung, beide gemessen:
   1. Er lag als position:fixed ueber allem und wurde erst per Skript entfernt. OHNE
      JavaScript deckte er die komplette Seite zu und ging nie weg — im Bildschirmfoto
      stand nur „000" auf Schwarz. Dieselbe Fehlerklasse wie .reveal{opacity:0} ohne
      Sicherheitsnetz, die in diesem Projekt schon zweimal live war.
   2. Danach haing er an html[data-js] und lag damit auch dann 4 Sekunden ueber der
      Seite, wenn gar kein Motion-Skript existiert (elementFromPoint lieferte mitten
      auf der Wortmarke DIV.vorlader). Vier Sekunden Deckung sind vier Sekunden LCP. */
.vorlader { display: none; }
html[data-vorlader="laeuft"] .vorlader {
  position: fixed; inset: 0; z-index: var(--z-preload);
  background: var(--glut-void);
  display: grid; place-content: center; justify-items: center; gap: var(--sp-3);
}
.vorlader__zahl { font-family: var(--ff-mono); font-size: var(--fs-h2);
  color: var(--glut-smoke); font-variant-numeric: tabular-nums; }
.vorlader__linie { width: 0; height: 1px; background: var(--glut-ember); }
.vorlader__wort { font-family: var(--ff-display); font-size: var(--fs-h1);
  font-weight: 900; font-stretch: 100%; color: var(--glut-cream); opacity: 0; }

/* ============================================================ Reduzierte Bewegung
   Kein Notbehelf, sondern ein zweiter, gleichwertiger Modus (Abschnitt 14). */
@media (prefers-reduced-motion: reduce) {
  /* Kein !important (Abschnitt 20). Es wird auch keines gebraucht: unter reduzierter
     Bewegung werden GSAP-Zeitleisten gar nicht erst erzeugt (siehe scripts/motion.js),
     also gibt es keine Inline-Stile, die ueberstimmt werden muessten. Hier stehen nur
     die rein deklarativen Bewegungen der Seite. */
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms; animation-iteration-count: 1;
    transition-duration: 0.01ms; }
  /* Wer reduzierte Bewegung eingestellt hat, will keine Eingangsinszenierung. */
  html[data-vorlader="laeuft"] .vorlader { display: none; }
  .korn { display: none; }
  .laufband__spur { animation: none; }
  /* ⚠️ BEIDE Selektoren, sonst greift die Uebersteuerung nicht. `.overlay` allein
     (0,1,0) verliert gegen `.overlay[data-offen="1"]` (0,2,0), und dort steht die
     transition-Sammelangabe mit 0,7 s. Gemessen: bei reduzierter Bewegung blieb das
     Menue auf `clip-path: circle(0%)` stehen — es oeffnete sich also gar nicht, und
     der Fokus konnte nicht hinein. Eine Uebersteuerung, die den Spezifitaetsvergleich
     verliert, ist keine Uebersteuerung. (Gleiche Familie wie `.recht a` gegen `.btn-p`
     auf der Firmenseite.) */
  /* ⚠️ `transition: none`, NICHT `transition-duration: 0.01ms`.
     Zwei Fehler in Folge an derselben Stelle, beide gemessen:
     1. `.overlay { transition-duration: 0.01ms }` allein (0,1,0) VERLIERT gegen
        `.overlay[data-offen="1"]` (0,2,0), wo die transition-Sammelangabe mit 0,7 s
        steht. Das Menue blieb bei reduzierter Bewegung auf `clip-path: circle(0%)`
        stehen, oeffnete sich also gar nicht.
     2. Mit beiden Selektoren griff die Uebersteuerung — und machte es schlimmer: der
        offene Zustand hat `visibility 0s`, also GAR KEINEN Uebergang. Eine Dauer von
        0,01 ms macht daraus einen laufenden Uebergang, und ein laufender Uebergang
        liefert beim ersten Lesen den ALTEN Wert. Gemessen: visibility blieb `hidden`,
        der Fokus konnte nicht ins Menue.
     `transition: none` nimmt alle Uebergaenge weg; die Werte gelten sofort. Genau das
     will jemand, der reduzierte Bewegung eingestellt hat. */
  .overlay,
  .overlay *,
  .overlay[data-offen="1"] { transition: none; }
  /* ⚠️ `.overlay *` MUSS mit. Die globale Regel `* { transition-duration: 0.01ms }`
     macht aus JEDER Aenderung eines Kindes einen laufenden Uebergang — auch aus der
     VERERBTEN visibility. Und ein laufender Uebergang liefert beim ersten Lesen den
     alten Wert: gemessen stand das Overlay auf `visible`, der Link darin aber weiter
     auf `hidden`, und `focus()` scheitert auf einem unsichtbaren Element still.
     Mit `transition: none` gilt der geerbte Wert sofort. */
}

/* ============================================================ Nachbesserungen
   Steht bewusst am ENDE: hier werden nur Groessen und Umbrueche nachgezogen, die der
   Pre-Flight namentlich gemeldet hat. Jede Regel nennt den gemessenen Wert.
   ⚠️ KEINE dieser Regeln fasst `display` an. Genau daran ist dieselbe Korrektur auf der
   Firmenseite gescheitert: `inline-flex` ueberstimmte dort `display:none` beim Burger
   und verschluckte das Leerzeichen im eigenen Firmennamen. Innenabstand vergroessert
   die Flaeche, ohne Textfluss oder Zeilenhoehe anzufassen. */

/* Lange Fachwoerter duerfen die Seite nicht aufspannen. Gemessen: die Ueberschrift
   „Datenschutzerklaerung" ist bei 390 px ein einziges 440-px-Wort und machte die Seite
   um 78 px seitlich schiebbar (scrollLeft liess sich auf 78 setzen, war also echt).
   Trennung nur im Rechtstext-Titel; sonst gilt weiter hyphens:manual, sonst steht da
   „Kategori-en" — der Fehler ist auf der Iren-Seite schon einmal passiert. */
h1, h2, h3 { overflow-wrap: break-word; }
.recht__titel { hyphens: auto; }

/* Beruehrflaechen auf 44 px. Die gemessenen Ausgangswerte stehen dahinter.
   ⚠️ Beim ersten Versuch stand hier fuer die Fusszeilen-Links `padding-block:5px` —
   WENIGER als das bereits gesetzte var(--sp-1)=8px weiter oben. Weil dieser Block am
   Ende steht, hat er den groesseren Wert ueberschrieben und die Flaeche von 35 auf
   29 px VERKLEINERT. Eine Nachbesserung am Dateiende muss immer der groessere Wert
   sein, sonst verschlimmbessert sie. */
.kopfleiste__marke {                                   /* war 40x19, dann 40x45 */
  padding-block: 13px;
  padding-inline: 4px; margin-inline-start: -4px;      /* Breite 40 -> 48, Optik bleibt */
}
.gericht__fuss a { padding-block: 13px; }              /* war 137x19 -> 137x45 */
.fuss__links a   { padding-block: 13px; }              /* Inhalt 19 px -> 45 */
.zeiten a, .ort__karte { min-height: 44px; }

/* ============================================================ Bewegungszustaende
   Nur wirksam, wenn das Kopf-Skript data-bewegt gesetzt hat — also NICHT bei
   reduzierter Bewegung und NICHT ohne JavaScript. Wer nichts ausfuehrt, sieht die
   Seite fertig. Das ist dieselbe Regel wie beim Vorlader und der Grund, warum hier
   nirgends `opacity:0` ohne Bedingung steht. */
html[data-bewegt] [data-tritt="warten"] {
  opacity: 0;
  transform: translateY(20px);
  /* ⚠️ visibility MUSS mit. opacity:0 allein laesst alles darin in der
     TAB-REIHENFOLGE: der Pre-Flight fand 21 unsichtbare, aber anspringbare
     Tages-Knoepfe („Di4Aug, Fr7Aug, …"). Dieselbe Falle steckte in 20 Demos
     dieses Bestands und in der Firmenseite — hier habe ich sie mit den Eintritten
     selbst neu gebaut.
     Kein Uebergang auf visibility und keine Sammelangabe: motion.js kippt das
     Attribut, damit faellt diese Regel weg und der GSAP-Startwert (opacity 0,
     inline durch fromTo) uebernimmt. */
  visibility: hidden;
  pointer-events: none;
}
html[data-bewegt] [data-tritt="warten"] .gericht__bild img,
html[data-bewegt] [data-tritt="warten"] .raum__bild img {
  transform: scale(1.06);
}
/* GSAP setzt beim Eintritt Inline-Stile. Damit sie nicht mit einem CSS-Uebergang
   kollidieren, gibt es hier bewusst KEINE transition auf diesen Eigenschaften. */

/* Laufband in der Fusszeile. Die Spur traegt zwei gleiche Saetze, deshalb -50 %. */
@keyframes laufband {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
.laufband__spur {
  display: flex; gap: var(--sp-3); width: max-content;
  align-items: center;
  font-family: var(--ff-mono); font-size: var(--fs-label);
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--glut-smoke);
  animation: laufband 42s linear infinite;
}
/* ⚠️ Kein will-change auf der Spur. Auf dem iPhone hat genau das in diesem Repo
   schon einmal eine ueber 5600 Geraetepixel breite GPU-Ebene erzeugt und das Band
   sekundenlang leer gelassen. */
@media (hover: hover) { .laufband:hover .laufband__spur { animation-play-state: paused; } }

/* Vorlader-Bausteine, die das Skript ansteuert */
.vorlader__linie { width: min(280px, 40vw); height: 1px; background: var(--glut-ash);
  position: relative; overflow: hidden; }
.vorlader__linie::after { content: ""; position: absolute; inset: 0;
  background: var(--glut-ember); transform: scaleX(var(--fortschritt, 0));
  transform-origin: 0 50%; }
.vorlader--weg { pointer-events: none; }

/* Zaehler im Hero und in S3: die Ziffer bekommt eine eigene Huelle, damit die
   Einheit beim Hochzaehlen nicht mitspringt. tabular-nums haelt die Breite fest. */
.z { font-variant-numeric: tabular-nums; }

/* Tages-Pillen: das Skript schreibt drei Spans, nicht <small>. Ohne diese Regeln
   griffe die vorhandene .tag small-Regel ins Leere und alle drei Zeilen kaemen in
   derselben Groesse — im Bildschirmfoto sofort sichtbar, in keiner Pruefzahl. */
.tag__wt { display: block; font-size: 0.68rem; letter-spacing: 0.1em;
  color: var(--glut-smoke); text-transform: uppercase; }
.tag__nr { display: block; font-size: 1.15rem; line-height: 1.1; }
.tag__mo { display: block; font-size: 0.66rem; letter-spacing: 0.08em;
  color: var(--glut-smoke); }
.tag[aria-pressed="true"] .tag__wt,
.tag[aria-pressed="true"] .tag__mo { color: var(--glut-ember); }
.tag:focus-visible { outline: 2px solid var(--glut-ember); outline-offset: 2px; }

/* Bei offenem Menue darf die Seite dahinter nicht mitscrollen. */
html[data-menue="offen"] { overflow: hidden; }

/* ⚠️ JEDE display-Angabe UEBERSTIMMT das hidden-Attribut. Genau das ist mir hier
   passiert: `#res-erfolg { display: grid }` machte die Erfolgsmeldung „Angefragt.
   Wir bestaetigen innerhalb von 2 Stunden per SMS." auf JEDEM Seitenaufruf sichtbar,
   bevor irgendetwas abgeschickt war. In keiner Pruefzahl zu sehen, im Bildschirmfoto
   sofort. Zwei Vorkehrungen, damit das nicht wiederkommt:
   1. ein ausdruecklicher Reset fuer [hidden] — die UA-Regel ist zu schwach,
   2. die Layout-Regel gilt nur, solange NICHT versteckt ist.
   Verwandt mit der 44-px-Lektion von der Firmenseite: eine Regel, die nur eine
   Groesse oder ein Layout nachbessern soll, darf `display` nicht blind setzen. */
[hidden] { display: none; }
#res-erfolg:not([hidden]) { display: grid; justify-items: start; }

/* ============================================================ Phase 3: Szenen-Momente
   Alles hier ist ZUSTAND, den motion.js ansteuert. Keine Regel versteckt etwas
   dauerhaft, und keine greift ohne data-bewegt. */

/* --- S3: die Hitze waechst beim Scrollen -------------------------------
   Ein Glimmen hinter den Zahlen, gesteuert ueber --hitze (0 bis 1). Es liegt HINTER
   dem Inhalt (z-index:-1), sonst dunkelt es den eigenen Text ab — genau der Fehler,
   der bei der Vignette schon einmal die Wortmarke grau gemacht hat. */
/* ⚠️ Erster Entwurf: `width: 120vmax` mit `left:50%; translate:-50%`. Bei 390 px
   Fenster sind das 1013 px, mittig — die Seite liess sich um 84 px seitwaerts
   schieben. Und der Befund war schwer zu finden: `getBoundingClientRect()` erfasst
   PSEUDOELEMENTE NICHT, meine Querlauf-Suche ueber alle Elemente kam deshalb leer
   zurueck. Bei jedem Querlauf ohne sichtbaren Verursacher zuerst die Pseudoelemente
   mit getComputedStyle(el, '::before') nachrechnen.
   Jetzt haengt das Glimmen an der SEKTION statt am Fenster: waagerecht kann es
   nicht mehr hinauslaufen, senkrecht darf es ueberstehen. `overflow: clip` klemmt
   den Rest — anders als `hidden` erzeugt es keinen Scrollrahmen. */
#feuer { --hitze: 0; isolation: isolate; overflow: clip; }
#feuer::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  inset: -22% 0;
  background: radial-gradient(circle at 50% 50%,
      rgba(255, 74, 22, 0.20) 0%, rgba(255, 74, 22, 0.07) 38%, rgba(255, 74, 22, 0) 68%);
  opacity: var(--hitze);
  scale: calc(0.62 + var(--hitze) * 0.38);
}

/* --- S4: die Karte als waagerechte Fahrt ------------------------------
   Wird NUR per Skript zugeschaltet (Stufe A/B, ab 900 px). Ohne die Klasse bleibt
   das Raster aus Phase 1 stehen — das ist der Rueckfall, nicht ein Notbehelf. */
.karte--fahrt {
  min-height: 100svh; display: grid; align-content: center;
  /* ⚠️ minmax(0, 1fr) IST PFLICHT. Ohne die Angabe ist die Grid-Spalte `auto`, also
     max-content — und weil die Reihe `width: max-content` hat, WUCHS die Spalte mit:
     gemessen 2678 px breites .rand bei 1440 px Fenster. Damit war
     `scrollWidth - Elternbreite` immer negativ, die Fahrt hat sich selbst abgeschaltet
     (data-fahrt="nein") und niemand hat den Signaturmoment je gesehen. */
  grid-template-columns: minmax(0, 1fr);
  overflow: hidden;
}
.karte--fahrt .rail {
  display: flex; width: max-content; gap: var(--gutter);
  grid-template-columns: none;
}
.karte--fahrt .gericht { flex: 0 0 clamp(280px, 24vw, 400px); }
.karte--fahrt .gericht--abschluss { flex: 0 0 clamp(260px, 20vw, 340px); }

/* --- S5: die vier Raumbilder liegen versetzt --------------------------
   Kein gleichmaessiges Viererband: zwei Bilder sitzen tiefer, dadurch entsteht beim
   Scrollen echte Tiefe statt einer Reihe. Nur am Schreibtisch, am Handy waere der
   Versatz nur Luecke. */
@media (min-width: 900px) {
  .raum__bilder { align-items: start; }
  .raum__bild:nth-child(2) { margin-top: var(--sp-5); }
  .raum__bild:nth-child(4) { margin-top: var(--sp-4); }
}

/* --- S2: die laufende Nummer bleibt stehen ----------------------------
   Sie sagt „bei welcher der sieben Schichten bin ich" — die Antwort auf die Frage,
   die eine lange Liste sonst offen laesst. */
.schicht-stand {
  position: sticky; top: calc(50svh - 3rem); align-self: start;
  font-family: var(--ff-mono); color: var(--glut-smoke);
  font-size: var(--fs-label); letter-spacing: 0.18em;
  display: grid; gap: var(--sp-1);
}
.schicht-stand b { font-family: var(--ff-display); font-weight: 900;
  font-stretch: 88%; font-size: clamp(2.5rem, 6vw, 5rem); line-height: 0.9;
  color: var(--glut-cream); font-variant-numeric: tabular-nums; }
.schicht-stand i { display: block; height: 1px; background: var(--glut-ash);
  position: relative; overflow: hidden; }
.schicht-stand i::after { content: ""; position: absolute; inset: 0;
  background: var(--glut-ember);
  transform: scaleX(var(--schichten, 0)); transform-origin: 0 50%; }
.zutaten--zwei { display: grid; gap: var(--gutter) var(--sp-5); }
@media (min-width: 900px) {
  .zutaten--zwei { grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); }
}
@media (max-width: 899px) { .schicht-stand { display: none; } }

/* --- S0: der Vorhang hebt sich, statt zu verblassen ------------------- */
.vorlader { clip-path: inset(0 0 0 0); }

/* Am Handy ist die Reservierungsleiste ein Band am unteren Rand. Ohne diesen Abstand
   liegt sie am Seitenende dauerhaft auf dem letzten Inhalt — dieselbe Stelle, an der
   auf der Iren-Seite die festen Kanal-Knoepfe auf dem Anrufen-Knopf lagen.
   ⚠️ Die Hoehe kommt aus der Leiste selbst (56 px) plus env(safe-area-inset-bottom),
   NICHT aus einer vh-Rechnung: auf iOS aendert sich die Fensterhoehe beim Scrollen. */
@media (max-width: 899px) {
  body { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); }
}

/* ============================================================ Funkenflug (Phase 4)
   Die Leinwand liegt HINTER dem Inhalt. Sie ist nur Atmosphaere: kein Text, kein
   Bedienelement, nichts, was jemand braucht. Deshalb pointer-events:none und
   aria-hidden — und deshalb ist es kein Verlust, wenn sie ausbleibt.
   ⚠️ Sie ist standardmaessig UNSICHTBAR und wird nur sichtbar, wenn scripts/glut3d.js
   sich mit data-funken="an" gemeldet hat. Gleiche Regel wie beim Vorlader: was sich
   nicht anmeldet, ist nicht da. Ohne das laege eine schwarze Flaeche ueber dem
   Seitenhintergrund, wenn WebGL fehlt. */
.funken { display: none; }
html[data-funken="an"] .funken {
  display: block;
  position: fixed; inset: 0; z-index: var(--z-canvas);
  width: 100%; height: 100%;
  pointer-events: none;
}
