/*! © 2026 Bemuar Technology (Resmuar). Alle Rechte vorbehalten. Urheberrechtlich geschützt (§§ 2, 69a UrhG): Vervielfältigung, Weitergabe und Nachbau ohne schriftliche Zustimmung nicht gestattet. https://resmuar.de/impressum */
/* Public site styles — consume tokens.css. No colours/sizes hardcoded here that
   belong in tokens. Photo-resilient, type-led, calm. */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--sans);
    font-size: 1rem;
    line-height: 1.65;
    transition: background var(--t), color var(--t);
}
/* ⛔ AUF DEM TELEFON WAR DIE SCHRIFT ZU DÜNN — Rückmeldung des Betreibers (18.09.2026) zur Bühne.
      Der Fliesstext ist Public Sans 400, und die ist auf einem kleinen, hell beleuchteten
      Bildschirm ein Haarstrich, am deutlichsten in der gedämpften Farbe (Adresse, Hinweise,
      Unterzeilen). Beide Schriften sind Variable Fonts (100–900, gemessen: die Breite wächst mit
      dem Gewicht), also ist 500 eine echte Zwischenstufe und kein künstlich verdickter Schnitt.

   ⚠️ NUR, WAS ERBT. Überschriften tragen ihr eigenes Gewicht (600) und bleiben, wo sie sind;
      `strong` rechnet `bolder` und landet weiterhin bei 700. Was ausdrücklich 400 setzt (eine
      Zeilennotiz, ein Hinweis), soll leiser sein als seine Umgebung und bleibt es.

   ⚠️ NUR BÜHNE. Kontor ist eigens typografisch gesetzt (siehe dessen Block am Dateiende); eine
      Änderung für die eine Gestaltung darf die andere nicht still mitnehmen. */
@media (max-width: 860px) {
    .layout-buehne { font-weight: 500; }
}
/* `overflow-wrap: break-word` is the structural guard, and German is why it is not optional.
   Measured at 375px: <h1>Datenschutzerklärung</h1> is one unbreakable 20-character token that
   laid out 360px wide inside a 316px column, and the page gained a horizontal scrollbar —
   document.body.scrollWidth 382 against an innerWidth of 375. It will happen again with
   Lebensmittelinformationsverordnung, with Öffnungszeiten-Änderung, and with half the
   restaurant names on this platform. Breaking a word is ugly; a page that scrolls sideways on
   a phone is broken. */
h1, h2, h3, h4 { font-family: var(--serif); font-weight: 600; line-height: 1.12; margin: 0 0 .5em; letter-spacing: -.01em; overflow-wrap: break-word; }
p { margin: 0 0 1em; }
/* A postal address is the correct element for a postal address, and every browser sets it in
   italic — which on a street address next to a heading reads as an aside rather than as the
   thing the band exists to tell you. Reset once here rather than fought per page. */
address { font-style: normal; margin: 0 0 1em; }
a { color: var(--link); text-underline-offset: 3px; }
img { max-width: 100%; display: block; }
/* THE ALLERGEN FILTER SILENTLY DID NOTHING, and this one line is why.

   `hidden` is an attribute whose whole effect is `[hidden] { display: none }` in the BROWSER'S
   sheet, and any author `display` at all outranks a UA sheet. menu.js hides a dish with
   `el.hidden = true`; `.mdish` two hundred lines below says `display: flex`. Measured on a real
   card (118 dishes) by clicking the "G · Milch" box the way a guest does: 10 dishes took
   `hidden="true"`, 10 kept `display: flex` and 186px of height, and not one of them left the
   screen. Only whole categories vanished — `.mcat` happens to declare no display — which is
   what made it look half-working rather than broken.

   That is a guest with a milk allergy reading a card that tells them it has filtered itself.

   `!important` rather than source order: a plain `[hidden]` rule (0,1,0) still loses to any
   two-class selector, and this sheet has several (`.dishcard__photo.ph-tile`). The attribute
   means "not relevant in any presentation" — there is no cascade argument to have with it.
   `img { display: block }` one line up is the same trap waiting for any hidden image. */
[hidden] { display: none !important; }
/*
 * TWO RINGS, BECAUSE ONE GROUND IS NOT ENOUGH.
 *
 * The ring was the restaurant's own accent, and inside `.hero--foto` — a near-black plate — that
 * measured 1.73:1. Every focusable element on the first screen, including both call-to-action
 * buttons and the submit button on the booking page, had an indicator a keyboard user could not
 * see. The outer white ring is what makes it work on any ground: the inner line carries the
 * brand, the outer one guarantees it is visible against whatever is behind.
 */
:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px;
    box-shadow: 0 0 0 5px color-mix(in oklab, var(--on-dark) 62%, transparent);
}
.hero--foto :focus-visible, .menu-hero :focus-visible,
.cater-hero :focus-visible, .gal-hero :focus-visible, .site-footer :focus-visible {
    outline-color: var(--on-dark);
    box-shadow: 0 0 0 5px color-mix(in oklab, #000 55%, transparent);
}

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--wrap-rand); }
.wrap--narrow { max-width: var(--wrap-narrow); }
/* ⛔ `left: -999px` WAR EIN VERSTECK, DAS VOM ELTERNTEIL ABHING — und genau daran ist es zerbrochen.
 *
 *    Ein absolut positioniertes Element rechnet gegen den nächsten POSITIONIERTEN Vorfahren, nicht
 *    gegen die Seite. Sobald `.skip` in einem Knopf mit `position: relative` sass, hiess -999px
 *    nicht mehr «weit links ausserhalb», sondern «999px links von diesem Knopf» — und das ist auf
 *    einem 1440px-Schirm mitten in der Kopfzeile. Gemessen: der Text «Mein Konto» stand bei x=201
 *    quer über dem Namen des Hauses, der bei x=202 beginnt.
 *
 *    Die Zuschneide-Technik hat keinen Bezugspunkt: 1px gross, weggeschnitten, egal worin sie
 *    steht. Damit kann dieselbe Falle nicht wieder zuschnappen — und `.nav__social`,
 *    `.footer-social` und die Ladenkopf-Zeile benutzen denselben Helfer.
 *
 * ⚠️ `position: fixed` IM FOKUS, aus demselben Grund: der Sprunglink soll oben links am
 *    BILDSCHIRM erscheinen, nicht oben links in irgendeinem Kasten. */
.skip {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.skip:focus {
    position: fixed;
    left: 12px;
    top: 12px;
    width: auto;
    height: auto;
    margin: 0;
    padding: 10px 14px;
    overflow: visible;
    clip-path: none;
    background: var(--surface);
    color: var(--text);
    border-radius: 8px;
    z-index: 100;
}

/* Optional second-voice label (Greek, Turkish, ...) — see data/content.php */
/*
 * ⛔ `--gold-ink` UND NICHT `--gold`, UND DAS IST EIN GEMESSENER FEHLER GEWESEN. Das Beiwort ist
 *    KLEINER TEXT auf Papier, und `--gold` trägt dort: Abend 3,33:1 · Tafel 2,87:1 · Markt
 *    5,00:1. WCAG verlangt 4,5:1 — zwei von drei Themes lagen darunter, Tafel deutlich. In der
 *    Praxis heisst das: ein älterer Gast oder ein Telefon in der Sonne liest das Wort nicht,
 *    das die Küche als ihre Herkunft nennt.
 *
 *    `--gold-ink` ist genau dafür da (`tokens.css:104-122`, dieselbe Farbe 72 % in oklab gegen
 *    ein dunkles Braun gemischt) und trägt 5,33:1 · 4,81:1 · 7,32:1 — nachgerechnet, nicht
 *    übernommen. Die Datei benutzte es bisher an einer einzigen Stelle im Grundblatt
 *    (`.badge--halal`) und sonst nur im Kontor-Block; der Aufbau, den heute JEDES live
 *    geschaltete Haus fährt, bekam die Korrektur nicht.
 *
 * ⚠️ DIE LINIEN BEHALTEN `--gold`. Für eine Regel, eine Zierlinie oder ein Icon reichen 3:1, und
 *    der metallische Ton IST die Zierde — ihn überall dunkler zu machen hiesse, den Charakter
 *    gegen eine Schwelle einzutauschen, die dort gar nicht gilt.
 *
 * ⚠️ UND JEDER DUNKLE GRUND BEHÄLT IHN AUCH. Wo das Beiwort auf einer Fotoplatte steht —
 *    `.hero--foto`, `.menu-hero`, `.cater-hero`, `.gal-hero`, der Fuss, `.cater-shot__eyebrow`
 *    über seinem Verlauf — deklarieren die Regeln dort ihre eigene Farbe, und helles Gold auf
 *    Dunkel ist genau richtig. Nachgesehen, Stelle für Stelle, statt gesucht und ersetzt.
 */
.accent-script { font-family: var(--serif); color: var(--gold-ink); font-size: .95em; letter-spacing: .02em; }
.eyebrow { font-size: .8125rem; color: var(--muted); font-family: var(--sans); font-weight: 600; }

/* THE TWO TEXT UTILITIES THE GUEST PAGES ACTUALLY ASK FOR, and the only two rules in this
   commit that are new names rather than existing ones.

   `.muted` was written in four templates and defined in exactly one place — scoped under
   `.m-allergen__body`, on the Speisekarte. Everywhere else (the 404's "zurück zur Startseite",
   the vegan page's allergen footnote, the booking receipt's "save this link") it was body text
   at body weight, so the aside and the sentence above it read as equals. Promoted here; the
   scoped rule keeps only its own size override.

   `.legal-missing` marks an Impressum or Datenschutz field the restaurant has not filled in.
   It has to be visible enough that the owner notices on their own site and calm enough that a
   guest does not read it as an error — an incomplete Impressum is the most commonly abgemahnt
   thing on a German small-business website, and "it looked fine" is how it stays that way for
   two years. Brass rule, muted italic: a margin note, not a red banner. */
.muted { color: var(--muted); }
.legal-missing {
    color: var(--muted); font-style: italic;
    border-left: 3px solid color-mix(in srgb, var(--gold) 60%, transparent);
    padding: 2px 0 2px 14px;
}

/* DER MUSTERMODUS — Beispielinhalt in der Vorschau eines Hauses im Aufbau (App\Site\Muster). Die
   Klassen setzt nur `muster.js`, und das Skript steht nur auf einer Seite mit gültiger
   Mustermarke; ein Gast sieht keine dieser Regeln je greifen.

   Dieselbe Haltung wie `.legal-missing` darüber: eine Randnotiz für die Inhaberin, kein Alarm.
   Die Linie in `--gold` (für eine Linie reichen 3:1), das Schild in vertauschten Seitenfarben
   (`--text` auf `--bg`), damit es auf hellem wie auf dunklem Papier und über einem Foto lesbar
   bleibt. Keine Bewegung.

   `--anker` nur dort, wo das Element keine eigene Lage hat (das Skript misst das), und
   `--innen`, wo ein Kasten Überstehendes abschneidet: dann steht das Schild innen statt darüber.
   Das Schild ist ein eigenes Element (`__schild`), kein `::before` — die Pseudo-Elemente gehören
   vielen Bauteilen schon selbst. */
.muster {
    outline: 2px dashed var(--gold);
    outline-offset: 4px;
}
.muster--anker { position: relative; }
.muster--innen { outline-offset: -4px; }
.muster__schild {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 5;
    transform: translateY(calc(-100% - 8px));
    max-width: min(100%, 34rem);
    padding: 3px 9px;
    border-radius: var(--r-xs);
    background: var(--text);
    color: var(--bg);
    font: 600 .75rem/1.4 var(--sans);
    letter-spacing: normal;
    text-transform: none;
    text-align: left;
    white-space: normal;
    pointer-events: none;
}
.muster--innen > .muster__schild {
    top: 8px;
    left: 8px;
    transform: none;
}

/* ---------- Standortband ----------
   Nur bei einem Haus mit mehr als einem Standort. Es steht ÜBER dem Header, weil die erste
   Frage eines Gastes «welches Haus ist das hier?» ist und sie beantwortet sein muss, bevor er
   eine Telefonnummer oder Öffnungszeiten liest — sonst ruft er die falsche Filiale an.

   ⛔ NICHT `sticky`. Der Header ist bereits sticky (z-index 40), und die Speisekarte hat
      zusätzlich eine klebende Kategorieleiste; ein drittes klebendes Element hätte auf einem
      375px-Telefon rund 100px Bildschirm gefressen, bevor ein einziges Gericht zu sehen ist.
      Das Band scrollt weg — es beantwortet eine Frage einmal, es begleitet nicht.

   Die Schrift ist klein, die Trefferfläche nicht: 44px Mindesthöhe, weil das auf einem Telefon
   ein echter Umschalter ist und keine Fußnote. */
.standorte {
    background: var(--plate);
    border-bottom: 1px solid var(--line-soft);
    font-size: .78rem;
    font-family: var(--sans);
}
.standorte__bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.standorte__label { font-size: .8125rem;
    color: var(--muted); font-weight: 600; flex: 0 0 auto;
}
.standorte__list { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.standorte__list a,
.standorte__here {
    display: inline-flex; align-items: center; min-height: 44px;
    padding: 0 10px; border-radius: 8px; text-decoration: none; letter-spacing: .01em;
}
/* Der aktuelle Standort ist KEIN Link und sieht auch nicht wie einer aus — ein Link auf die
   Seite, auf der man gerade steht, ist die häufigste kleine Lüge in Navigationen. */
.standorte__here { color: var(--text); font-weight: 600; background: var(--surface); box-shadow: var(--shadow-sm); }
.standorte__list a { color: var(--muted); }
.standorte__list a:hover { color: var(--text); background: var(--surface); }
.standorte__list a:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ---------- Standortwahl beim ersten Besuch ----------

   ⛔ KEIN OVERLAY, KEIN `position: fixed`, KEIN VERDUNKELTER HINTERGRUND. Das sähe nach Modal
      aus und wäre eines — und ein Modal ohne JavaScript lässt sich nicht schliessen. Dies ist
      ein Abschnitt oben auf der Startseite: er schiebt den Inhalt nach unten statt ihn zu
      verdecken, jede Auswahl ist ein Link, und wer gar nichts anklickt, scrollt einfach vorbei
      und sieht die ganze Seite. Genau das ist bei einem Fenster, das man wegklicken MUSS, nicht
      möglich — und der Gast steht dabei manchmal mit einem Balken Empfang vor der Tür.

   Es trägt die Markenfarbe des Hauses, weil es das Erste ist, was ein Gast sieht. */
.standortwahl {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--accent) 10%, var(--bg)) 0%,
        var(--bg) 100%);
    border-bottom: 1px solid var(--line-soft);
    padding: 28px 0 24px;
}
.standortwahl__box { max-width: 760px; }
.standortwahl__frage {
    font-family: var(--serif); font-size: clamp(1.5rem, 4vw, 2.1rem);
    margin: 0 0 6px; color: var(--text); line-height: 1.15;
}
.standortwahl__hinweis { color: var(--muted); font-size: .95rem; margin: 0 0 20px; max-width: 46ch; }

/* ZWEI GLEICH BREITE KARTEN, die auf dem Telefon untereinander rutschen. `1fr` statt fester
   Breiten: die Namen sind verschieden lang («Nord» und «Fallersleben»), und zwei verschieden
   breite Karten sähen aus, als sei eine wichtiger. */
.standortwahl__liste {
    list-style: none; margin: 0 0 18px; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px;
}
.standortwahl__eintrag { display: flex; }
.standortwahl__ort {
    display: flex; flex-direction: column; gap: 6px; flex: 1;
    /* Grosszügig, weil dies der erste Klick auf der Website ist und mit dem Daumen kommt. */
    min-height: 96px; padding: 16px 18px;
    border: 1px solid var(--line); border-radius: 14px;
    background: var(--surface); text-decoration: none; color: var(--text);
    box-shadow: var(--shadow-sm);
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.standortwahl__ort:hover {
    border-color: var(--accent);
    box-shadow: var(--shadow-md, var(--shadow-sm));
    transform: translateY(-1px);
}
.standortwahl__ort:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
/* Der Standort, auf dem der Gast gerade steht, ist markiert — aber NICHT ausgegraut: er ist
   eine gültige Wahl, und wer ihn anklickt, hat sich entschieden. */
.standortwahl__ort--hier { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, var(--surface)); }
.standortwahl__kopf { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.standortwahl__name { font-family: var(--serif); font-size: 1.2rem; font-weight: 600; }
.standortwahl__hier {
    font-size: .8125rem; font-weight: 600;
    color: var(--accent-ink);
}
.standortwahl__adresse { color: var(--muted); font-size: .88rem; line-height: 1.35; }
/* Zustand: Wort UND Punkt. Der Punkt allein wäre für eine Rot-Grün-Schwäche keine Auskunft. */
.standortwahl__zustand {
    display: inline-flex; align-items: center; gap: 6px; margin-top: auto;
    font-size: .78rem; color: var(--muted);
}

.standortwahl__zustand--offen { color: var(--enamel, #2f7d4f); font-weight: 600; }
/* Der Ausweg ist ein Link und kein Knopf: er ist die leisere der beiden Möglichkeiten und
   soll auch so aussehen. Trotzdem 44 px hoch, weil er auf einem Telefon getroffen werden muss. */
.standortwahl__spaeter {
    display: inline-flex; align-items: center; min-height: 44px;
    color: var(--muted); font-size: .88rem; text-decoration: underline;
    text-underline-offset: 3px;
}
.standortwahl__spaeter:hover { color: var(--text); }
.standortwahl__spaeter:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* DIE MARKENTÜR — `ghien.de`, bevor der Gast weiss, in welches Haus er will.

   Sie benutzt dieselbe `.standortwahl` wie die Filialseite und stellt sie nur anders auf: dort
   ist die Frage ein Abschnitt OBEN AUF einer Seite, hier ist sie die ganze Seite. Deshalb keine
   eigene Stilsprache, sondern drei Regeln, die den Rahmen wegnehmen, den es hier nicht braucht.

   ⚠️ `min-height: 100svh` UND NICHT `100vh`. Auf einem Telefon zählt `vh` die Adressleiste mit,
      die beim Scrollen verschwindet — die Seite wäre bei jedem Aufruf ein Stück zu hoch und
      liesse sich scrollen, obwohl es nichts zu scrollen gibt. */
.page-markentuer {
    min-height: 100svh;
    display: flex; flex-direction: column;
    background: var(--bg); color: var(--text);
}
.page-markentuer #main { flex: 1; display: flex; flex-direction: column; justify-content: center; }

/* Kein Trennstrich nach unten: darunter kommt nichts mehr, was abgegrenzt werden müsste. */
.page-markentuer .standortwahl { border-bottom: 0; padding: 32px 0 28px; }

/* Das Zeichen der MARKE, nicht der Name der Filiale — die Begründung steht im Kopf von
   `markentuer.blade.php`. Höhe fest, Breite dem Bild folgend, wie im Seitenkopf. */
.markentuer__zeichen { text-align: center; padding: 40px 20px 0; }
.markentuer__zeichen img { height: 64px; width: auto; }

.markentuer__fuss {
    padding: 24px 0 32px; text-align: center;
    color: var(--muted); font-size: .85rem;
}
/* 44 px, weil auch ein Pflichtlink auf einem Telefon getroffen werden muss. */
.markentuer__fuss a {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 10px;
    color: var(--muted); text-decoration: underline; text-underline-offset: 3px;
}
.markentuer__fuss a:hover { color: var(--text); }
.markentuer__fuss a:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/*
 * ⛔ AUF DEM TELEFON NAHM DIESE FRAGE DEN HALBEN ERSTEN BILDSCHIRM. Gemessen bei einem Haus
 *    mit zwei Filialen, 390 × 844: rund 370 px für eine Frage mit zwei Antworten — und darunter
 *    beginnt der Aufmacher, dessen Inhalt am unteren Rand sitzt. Zusammen war der erste
 *    Bildschirm vollständig belegt, bevor das Haus ein einziges Wort über sich gesagt hatte.
 *
 * ⚠️ NICHTS FÄLLT WEG, ALLES WIRD ENGER. Adresse und «Jetzt geöffnet» sind der ausgeschriebene
 *    Grund, warum dieses Fenster mehr ist als das Band (siehe Partial) — sie bleiben. Kleiner
 *    werden die Frage, die Abstände und die Mindesthöhe der Karten; die 44-px-Grenze für den
 *    Daumen ist damit weiterhin doppelt eingehalten.
 */
@media (max-width: 620px) {
    .standortwahl { padding: 18px 0 16px; }
    .standortwahl__frage { font-size: 1.35rem; }
    .standortwahl__hinweis { font-size: .88rem; margin: 0 0 14px; }
    .standortwahl__liste { gap: 9px; margin: 0 0 10px; }
    .standortwahl__ort { min-height: 0; padding: 12px 14px; gap: 3px; }
    .standortwahl__name { font-size: 1.05rem; }
    .standortwahl__spaeter { min-height: 40px; }
}

/* ---------- Header ---------- */
.site-header {
    position: sticky; top: 0; z-index: 40;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: saturate(1.3) blur(8px);
    border-bottom: 1px solid var(--line-soft);
}
/* ⛔ `padding-top/bottom` UND NICHT DIE KURZSCHREIBWEISE — sonst loescht die Zeile den
 *    seitlichen Abstand, den `.wrap` eine Regel weiter oben gibt (`padding: 0 22px`).
 *
 *    Gemessen auf einem emulierten Telefon (390px, DPR 3): `padding-left` war 0, die Marke sass
 *    auf x=0 und der Menueknopf endete auf x=390 — Name und Knopf klebten am Glas. Auf dem
 *    Schreibtisch faellt es nicht auf, weil die Seite bei 1080px ohnehin mittig steht und links
 *    und rechts Luft hat; erst unter der Wrap-Breite wird die Null sichtbar. Es ist die erste
 *    Zeile, die ein Gast auf dem Telefon sieht.
 *
 * ⚠️ DIE 22px WERDEN HIER NICHT WIEDERHOLT. Sie stehen in `.wrap`, und ein zweiter Ort waere
 *    ein zweiter Ort, an dem sie auseinanderlaufen koennen. */
.site-header__bar { display: flex; align-items: center; gap: 16px; padding-top: 12px; padding-bottom: 12px; }
.brand { display: inline-flex; align-items: center; gap: 11px; text-decoration: none; color: var(--text); line-height: 1.05; }
/* ⛔ DAS ZEICHEN BEHÄLT SEINE FORM — ES WURDE VORHER GEQUETSCHT.
      Hier stand `width: 42px; height: 42px` ohne `object-fit`, und die Vorgabe ist `fill`:
      ein Logo, das nicht quadratisch ist, wurde in das Quadrat GEDRÜCKT. Gemessen mit einem
      Zeichen im Verhältnis 3:1 — gezeichnet wurde 1:1, aus dem Kreis wurde ein Ei und die
      Schrift war nicht mehr zu lesen. Das Feld im Panel rät zu einem quadratischen Logo, es
      verlangt es aber nicht, und ein Gasthaus-Logo ist meistens ein breiter Schriftzug.
      Jetzt gibt die HÖHE das Mass und die Breite folgt dem Bild: quadratisch bleibt
      quadratisch, breit bleibt breit — bis zu einer Grenze, damit ein sehr langer Schriftzug
      nicht die halbe Kopfzeile nimmt. */
.brand__mark {
    height: 42px; width: auto; max-width: 168px; object-fit: contain;
    flex: 0 0 auto; background: none; padding: 0; border-radius: 0; box-shadow: none;
}
.brand__text { display: inline-flex; flex-direction: column; }
.brand__name { font-family: var(--serif); font-size: 1.15rem; }
.brand__accent { font-size: .74rem; color: var(--gold-ink); }
@media (max-width: 400px) { .brand__mark { height: 36px; max-width: 132px; } .brand__name { font-size: 1.02rem; } }

/* ══ ZWEI ZEICHEN — das Logo für Papier, eine helle Fassung für dunkle Flächen (D-164) ════════
   Ein Logo ist fast immer für hellen Grund gezeichnet, und der Kopf ist nicht immer hell: die
   Bühne trägt ihn über dem Titelfoto, Ofen über dem Film, jeder Aufbau im Nachtmodus, die
   Fusszeile immer. Bis hierher stand das eine Zeichen dort auf einer hellen Platte (`--plate`);
   der Betreiber sah die Platte und fragte, warum das Logo einen Hintergrund hat.

   Die Regel ist der GRUND, nicht das Thema: das Haus lädt eine zweite, helle Fassung hoch
   (`brand.logo_dunkel`), beide stehen im Markup, und das Blatt zeigt je Fläche eines. Wo die
   Fläche dunkel wird, sagt der Aufbau (buehne.css, ofen.css) oder der Nachtmodus (hier).

   ⛔ NIRGENDS EINE PLATTE, AUCH NICHT BEI NUR EINEM ZEICHEN (04.10.2026). Bis hierher stellten
      wir ein einzelnes Logo auf `--plate`, damit es im Dunkeln nicht verschwindet. Der Betreiber
      hat ein PNG ohne Hintergrund hochgeladen und genau diese Platte gesehen: «png arka plani
      olmayan her logoyu arka plan olmadan koymasi gerekiyor». Ein Zeichen ohne Hintergrund wird
      ohne Hintergrund gezeigt — überall. Wer sein Logo auf dunklem Grund halten will, lädt die
      helle Fassung hoch; das Feld dafür steht im Panel und sagt es auch.

   ⚠️ `.brand__mark--dunkel` TRÄGT AUCH `.brand__mark`, damit Mass und Form dieselben sind; nur
      Platte und Sichtbarkeit unterscheiden sich. HauszeichenTest liest den `.brand__mark`-Block
      darüber und verlangt dort `object-fit: contain` und `width: auto` — der bleibt, wie er ist. */
/* ⚠️ DIE HELLE FASSUNG STEHT HIER MIT `:not(…)`, NICHT ALS NACKTES `.ladenkopf__mark {`:
      HauszeichenTest liest den ERSTEN Block, dessen Wähler so endet, und verlangt dort Mass und
      `object-fit` — das ist der Block des Ladenkopfs weiter unten, nicht dieser. */
.brand__mark--dunkel,
.ladenkopf__mark--dunkel { display: none; background: none; padding: 0; border-radius: 0; box-shadow: none; }
.brand:has(.brand__mark--dunkel) .brand__mark:not(.brand__mark--dunkel),
.ladenkopf__inner:has(.ladenkopf__mark--dunkel) .ladenkopf__mark:not(.ladenkopf__mark--dunkel) {
    background: none; padding: 0; border-radius: 0; box-shadow: none;
}
:root[data-theme="dark"] .brand:has(.brand__mark--dunkel) .brand__mark:not(.brand__mark--dunkel),
:root[data-theme="dark"] .ladenkopf__inner:has(.ladenkopf__mark--dunkel) .ladenkopf__mark:not(.ladenkopf__mark--dunkel) { display: none; }
:root[data-theme="dark"] .brand__mark--dunkel,
:root[data-theme="dark"] .ladenkopf__mark--dunkel { display: block; }
.nav { display: flex; gap: 4px; margin-left: auto; }
/* Direct children only. `.nav a` also matched the address, phone, mail, social and CTA links
   inside the mobile panel and outranked their own rules on specificity, so each of them wore
   menu-item padding, size and opacity it was never meant to have. */
.nav > a { text-decoration: none; color: var(--text); font-size: .92rem; padding: 8px 12px; border-radius: 8px; opacity: .85; }
.nav > a:hover, .nav > a[aria-current="page"] { opacity: 1; color: var(--accent-ink); }
/* `.hcontrols` deleted: a header control cluster with no markup. `.header-actions` beside it
   does the same job and is the one the layout renders. */
/* ⛔ 44 × 44 px, UND DAS IST KEINE AUFRUNDUNG VON 38.
 *
 *    Hier standen `min-width: 38px; height: 38px`, ohne jede Medienabfrage — und an dieser
 *    Klasse hängen die ZWEI Knöpfe, die ein Gast auf dem Telefon am häufigsten trifft: der
 *    Menüknopf (`.navtoggle`) und die Tür zum Konto (`.kontobtn`). Beide sitzen oben rechts,
 *    also unter dem Daumen der Hand, die das Gerät hält, und hinter beiden liegt der einzige
 *    Weg zu dem, was sie öffnen. 38 px sind sechs Pixel unter der Untergrenze, die WCAG 2.2
 *    in 2.5.8 «Target Size (Minimum)» nennt — und sechs Pixel sind auf einem Telefon der
 *    Unterschied zwischen «getroffen» und «die Seite hat gescrollt».
 *
 * ⚠️ DIE BEGRÜNDUNG STEHT WEITER UNTEN SCHON EINMAL AUSGESCHRIEBEN, im Bestellweg bei
 *    `.mdish__add`: «THE BUTTON IS 44px, and that is not a rounding of 42.» Der Bestellweg hat
 *    es von Anfang an so gebaut, der Kopf der Seite nicht. Es ist dieselbe Hand und dasselbe
 *    Telefon; ein Haus mit zwei Massen für denselben Daumen hat kein Mass.
 *
 * ⚠️ `min-height` STATT `height`, UND DAS ZEICHEN BLEIBT BEI 19 px. Die Fläche wächst, das
 *    Bild darin nicht — ein grösserer Knopf, kein grösseres Symbol. Gemessen in der Kopfzeile:
 *    `.brand__mark` ist 42 px hoch (`border-box`), die Zeile wird durch die 44 px also um
 *    genau 2 px höher, nicht um sechs. */
.iconbtn { background: transparent; border: 1px solid var(--line); color: var(--text); border-radius: 8px; min-width: 44px; min-height: 44px; cursor: pointer; font: inherit; font-size: .8rem; display: inline-flex; align-items: center; justify-content: center; }
.iconbtn:hover { border-color: var(--accent); color: var(--accent-ink); }
/* Der Sprachwechsel (D-190): zwei Buchstaben im selben Rahmen wie das Kontozeichen. */
.sprachwechsel { text-decoration: none; font-weight: 600; letter-spacing: .04em; }
.header-actions { display: flex; align-items: center; gap: 6px; }
.navtoggle { display: none; }
.nav__head, .nav__foot, .nav__contact { display: none; }   /* only inside the mobile off-canvas panel */
.navtoggle__bars { display: inline-flex; flex-direction: column; justify-content: center; gap: 4px; width: 18px; }
.navtoggle__bars span { display: block; height: 2px; width: 100%; background: currentColor; border-radius: 2px; }

/* Der Weg ins Gästekonto — ein Zeichen im Kopf, kein Wort.
 *
 * ⚠️ `flex: 0 0 auto` UND FESTE MASSE AM SVG. `.iconbtn` ist eine inline-flex-Box, das SVG
 *    darin also ein Flex-Element ohne eigene Breite: unter Druck schrumpft es auf nichts und
 *    zurück bleibt ein leerer Rahmen. Dieselbe Stelle ist an `.iconbtn2 svg`,
 *    `.nav__social a svg` und `.wa-fab__btn svg` schon dreimal dokumentiert.
 *
 * ⚠️ `fill: currentColor`, damit das Zeichen den Hover von `.iconbtn` mitmacht, statt in einer
 *    zweiten Farbe stehen zu bleiben, die niemand pflegt. */
.kontobtn { position: relative; }
.kontobtn svg { width: 19px; height: 19px; flex: 0 0 auto; fill: currentColor; }

/* Der Punkt sagt «Sie sind angemeldet», und ohne ihn ist ein Klick der einzige Weg, das
 * herauszufinden. Der Ring in `--bg` trennt ihn vom Rahmen darunter, sonst verschmelzen die
 * beiden Linien bei 9px zu einem Fleck. */
.kontobtn.is-angemeldet::after {
    content: '';
    position: absolute;
    top: -3px;
    right: -3px;
    width: 9px;
    height: 9px;
    border-radius: 999px;
    background: var(--accent);
    border: 2px solid var(--bg);
}

/* Mobile nav — premium off-canvas panel */
@media (max-width: 860px) {
    .navtoggle { display: inline-flex; }
    .header-actions { margin-left: auto; }
    /* backdrop-filter on the header creates a containing block that would trap the
       position:fixed off-canvas panel to the header's height — drop it on mobile so
       the panel spans the full viewport; give the header a solid background instead. */
    .site-header { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--bg); }
    .nav {
        position: fixed; inset: 0 0 0 auto;
        width: min(86vw, 340px);
        background: var(--surface); color: var(--text);
        flex-direction: column; gap: 0; padding: 0; margin: 0;
        transform: translateX(100%); transition: transform var(--t), box-shadow var(--t);
        border-left: 1px solid var(--line-soft);
        overflow-y: auto; -webkit-overflow-scrolling: touch;
    }
    /* ⛔ DER SCHATTEN NUR, WENN DAS PANEL OFFEN IST. Geschlossen steht es rechts neben dem Bild
       (`translateX(100%)`), aber sein Schatten reichte 68px NACH LINKS hinein: ein grauer
       Verlauf am rechten Rand jeder Seite auf jedem Telefon, quer über Fotos, Karten und die
       Daumenleiste. Gemessen auf 390px: `.nav` bei x = 390, `box-shadow: -18px 0 50px`. */
    .nav.is-open { transform: translateX(0); box-shadow: -18px 0 50px rgba(20, 16, 12, .28); }
    /* ⛔ AUF DER LADENSEITE LAG DAS PANEL UNTER DEM LADENKOPF. `.page-laden .site-header` ist
       `static` (Abschnitt Ladenkopf, mit Grund) — sein z-index 40 zählt dort also nicht mehr.
       Einen Stapelkontext bildet der Kopf TROTZDEM, wegen `view-transition-name: masthead`; nur
       liegt dieser Kontext jetzt auf Stufe «auto» im Wurzelkontext, und der klebende Ladenkopf
       (40), die Rubrikenleiste (35) und jede positionierte Karte der Speisekarte zeichneten
       darüber — samt dem Panel, das IM Kopf steckt. Zu sehen war nur der Kopf des Panels und der
       Kontaktblock; die Menüpunkte lagen hinter dem Heldenbild. Am Telefon des Betreibers gesehen,
       headless nachgemessen: nav fixed/auto, ladenkopf sticky/40.
       ⛔ DER ERSTE VERSUCH — z-index am Panel selbst — ÄNDERTE NICHTS, weil ein z-index nur
          innerhalb des eigenen Kontexts zählt und der Kontext des Kopfes unten blieb. Gehoben
          wird der KOPF: `relative` statt `static` ändert am Fluss nichts (kein Kleben, das war der
          Grund für `static`), gibt seinem z-index aber wieder eine Bedeutung.
       ⚠️ NUR AUF `.page-laden`, und mit `body.` davor, weil die `static`-Regel weiter unten in der
          Datei steht und bei gleicher Spezifität gewänne. Überall sonst lebt das Panel im
          klebenden Kopf (40) und der Schleier (39) darunter — dort stimmt die Ordnung. */
    body.page-laden .site-header { position: relative; z-index: 60; }
    .page-laden .nav-backdrop { z-index: 49; }
    .nav__head {
        display: flex; align-items: center; justify-content: space-between; gap: 12px;
        padding: 17px 20px; border-bottom: 1px solid var(--line-soft);
        position: sticky; top: 0; background: var(--surface); z-index: 1;
    }
    .nav__brand { display: flex; flex-direction: column; font-family: var(--serif); font-size: 1.02rem; line-height: 1.2; color: var(--text); }
    .nav__brand .accent-script { font-size: .72rem; }
    /* ⚠️ 44 px WIE `.iconbtn` — die Begründung steht dort ausgeschrieben. Dieser Knopf ist der
       Gegenknopf zum Menüknopf: wer das Panel geöffnet hat, schliesst es hier, und ein Ausgang,
       der kleiner ist als der Eingang, ist die schlechtere Hälfte des Tauschs. */
    .nav__close {
        flex: 0 0 auto; min-width: 44px; min-height: 44px; border-radius: 8px; cursor: pointer;
        background: transparent; border: 1px solid var(--line); color: var(--text);
        font-size: 1rem; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
    }
    .nav__close:hover { border-color: var(--accent); color: var(--accent-ink); }
    .nav > a {
        display: flex; align-items: center; justify-content: space-between;
        padding: 15px 20px; font-size: 1.06rem; font-family: var(--serif);
        color: var(--text); opacity: 1; border-radius: 0; border-bottom: 1px solid var(--line-soft);
    }
    /* The contact block brings its own top rule; without this the two stack into a double line. */
    .nav > a:last-of-type { border-bottom: 0; }
    .nav > a[aria-current="page"] { color: var(--accent-ink); }

    .nav__foot { display: flex; gap: 10px; padding: 18px 20px; margin-top: auto; border-top: 1px solid var(--line-soft); }
    .nav__cta {
        flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
        padding: 12px; border-radius: 999px; text-decoration: none; font-weight: 600; font-size: .92rem;
        border: 1px solid var(--line); color: var(--text); font-family: var(--sans);
    }
    .nav__cta:hover { border-color: var(--accent); color: var(--accent-ink); }
    /* contact + social inside the off-canvas panel */
    .nav__contact { display: block; padding: 16px 20px; border-top: 1px solid var(--line-soft); }
    .nav__addr { font-family: var(--serif); color: var(--muted); margin: 0 0 10px; line-height: 1.5; font-size: .96rem; }
    /* Grid rather than flex: a mail address is long enough to wrap in a 340px panel, and a
       second flex line would slide back under the icon. A fixed icon column keeps every
       wrapped line aligned with the first. */
    .nav__cline {
        display: grid; grid-template-columns: 16px 1fr; align-items: start; gap: 10px;
        padding: 12px 0; color: var(--text); text-decoration: none;   /* über 44 px Tippfläche (vorher 34) */
        font-family: var(--sans); font-size: .93rem; line-height: 1.45; overflow-wrap: anywhere;
    }
    .nav__cline svg { color: var(--gold); margin-top: 2px; }
    .nav__cline:hover { color: var(--accent-ink); }
    .nav__social { display: flex; gap: 10px; margin-top: 14px; }
    /* ⚠️ 44 px, VIER MEHR ALS VORHER — siehe `.iconbtn`. Die Ringe stehen nebeneinander in einer
       Reihe mit 10 px Abstand; bei vier Kanälen sind das 4 × 44 + 3 × 10 = 206 px in einem Panel
       von min(86vw, 340px) abzüglich 2 × 20 px Polster, also 300 px. Es passt, und es passt auch
       noch bei fünf. */
    .nav__social a { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; border-radius: 999px; border: 1px solid var(--line); color: var(--text); }
    .nav__social a:hover { color: var(--accent-ink); border-color: var(--accent); }
    /* An SVG is a flex item with no intrinsic width to defend, so it shrinks to 0 and the
       button renders as an empty ring. The phone and mail icons sit in a grid column and are
       safe; these two are not, which is why only they went blank. */
    .nav__social a svg { flex: 0 0 auto; }
    .nav-backdrop {
        position: fixed; inset: 0; background: rgba(20, 16, 12, .5);
        opacity: 0; pointer-events: none; transition: opacity var(--t); z-index: 39;
        -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    }
    .nav-backdrop.is-open { opacity: 1; pointer-events: auto; }
}

/* ---------- Announcement ---------- */

/* ---------- Hero ---------- */
.hero__accent-watermark {
    position: absolute; right: -2%; top: 50%; transform: translateY(-50%);
    font-family: var(--serif); font-size: clamp(120px, 34vw, 460px); line-height: .8;
    color: transparent; -webkit-text-stroke: 1.5px color-mix(in srgb, var(--gold) 42%, transparent);
    opacity: .5; pointer-events: none; white-space: nowrap; z-index: 0; user-select: none;
}
.hero__inner { position: relative; z-index: 1; max-width: 720px; }
.hero__title { font-size: clamp(2.3rem, 6.2vw, 4.1rem); margin: .18em 0 .35em; }
.hero__intro { font-size: clamp(1.05rem, 2.3vw, 1.3rem); color: var(--muted); max-width: 34em; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }

/* `.hero--photo` LIVED HERE AND HAD NO MARKUP ANYWHERE. It was a second photographic hero
   beside `.hero--foto` (further down, the one the homepage actually renders), and it pointed at
   a hardcoded `/assets/img/hero.webp` — a path that does not exist in this repository and that
   twenty restaurants would have had to share if it did. Deleted rather than wired up: the
   photograph arrives per restaurant as `--hero-photo`, never as a path written into this file. */

/* ---------- Buttons ---------- */
:root { --btn-lift: 0; }
/* NO HOVER LIFT. `transform: translateY(-2px)` on every button, card and link was the house
   style of about 2018 and it is the single loudest dated signal on the page — a premium room
   does not bounce when you look at it. What replaces it is what a printed piece does: the
   surface deepens and the edge sharpens. Cheaper too, because a colour change does not
   invalidate layout.

   And it removes an accessibility hole for free: four hover transforms were outside every
   `prefers-reduced-motion` block. */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
    text-decoration: none; font: inherit; font-size: var(--fs-1); font-weight: 600;
    cursor: pointer; padding: var(--s-3) var(--s-5);
    border-radius: var(--r-btn); border: 1px solid transparent;
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast),
                box-shadow var(--t-fast);
}
.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover { background: var(--accent-strong); box-shadow: 0 6px 18px color-mix(in oklab, var(--accent) 26%, transparent); }
.btn--ghost { border-color: var(--line); color: var(--text); background: transparent; }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent-ink); background: color-mix(in oklab, var(--accent) 5%, transparent); }

/* ---------- Sections ---------- */
section { padding: var(--s-8) 0; }
/*
 * ⛔ DIE HAUSFARBE MACHTE FAST KEINE ARBEIT. Gemessen an einer ausgelieferten Startseite: sie
 *    stand auf zwei Knöpfen, auf den Preisen und in einem 3-px-Streifen ganz oben — zusammen
 *    rund ein Prozent der Fläche. Das eine, was Pinocchio von Kalyos unterscheiden soll, war
 *    damit das Unauffälligste auf der Seite; ein Kebaphaus, dessen Zeichen rot ist, bekam
 *    «beige mit orangefarbenen Knöpfen».
 *
 * ⚠️ EIN STRICH ÜBER JEDER ABSCHNITTSÜBERSCHRIFT, und zwar aus zwei Gründen der zurückhaltende
 *    Weg: er wiederholt sich fünf- bis achtmal auf einer Seite, und er ist ZIERDE, kein Text.
 *    Für eine Regel oder eine Zierlinie genügen 3:1 — dieselbe Rechnung, mit der `--gold` in
 *    dieser Datei seine Linien behalten durfte, während kleiner Text auf `--gold-ink` musste.
 *    Die Hausfarbe als kleine Schrift auf Papier wäre bei einem hellen Orange unter 3:1
 *    gelandet; als Strich trägt sie.
 */
.section-head { max-width: 40em; margin-bottom: 34px; }
.section-head h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); }

.section--surface { background: var(--surface); }

/* Soft-arc section divider — a quiet ornament between bands */
.rule-ornament { height: 40px; background: radial-gradient(120% 100% at 50% 0, transparent 69%, var(--surface) 70%); }
.rule-ornament--up { background: radial-gradient(120% 100% at 50% 100%, transparent 69%, var(--surface) 70%); }

/* ---------- Dish grid ---------- */
.dish-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; }
.dishcard { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); padding: 20px; transition: transform var(--t), box-shadow var(--t); }
.section--surface .dishcard { background: var(--bg); }
/* Same argument as the button. A card that jumps 4px under the cursor is a card that was
   designed when that was new; a card whose edge warms is a card. */
.dishcard:hover { border-color: color-mix(in oklab, var(--gold) 44%, var(--line-soft)); background: color-mix(in oklab, var(--gold) 3%, var(--surface)); }
.dishcard__accent { color: var(--gold-ink); font-family: var(--serif); font-size: .85rem; }
/*
 * ⛔ NAME UND PREIS AUF EINER ZEILE, UND ZWAR AUF JEDER KARTE. Bis hierher standen sie als vier
 *    Blöcke untereinander — Foto, Name, Beschreibung, Preis — in einer Spalte von 230 Pixeln:
 *    sechs Arten Auskunft in vier Schriftgrössen, gestapelt. Die Speisekarte macht es seit jeher
 *    richtig (`.mdish__head`), und die fotolose Fassung dieser Karte seit dem letzten Durchgang;
 *    die Karte MIT Foto war die letzte, die es noch anders machte.
 *
 * ⚠️ AUF EINER GEDRUCKTEN KARTE STEHT DER PREIS IMMER AUF DER HÖHE DES GERICHTS. `grid-row: 2`
 *    setzt ihn neben die Beschreibung — genau der Fehler, den D-91 auf der Kontor-Seite schon
 *    einmal gekostet hat.
 *
 * ⚠️ KONTOR BLEIBT UNBERÜHRT: seine eigenen Regeln (`.layout-kontor .dishcard`, 0,2,0) stehen
 *    später in dieser Datei und überstimmen jede dieser Zeilen. Nachgesehen, nicht gehofft.
 */
/*
 * ⛔ DER PREIS UND DIE ZEICHEN TEILEN SICH DIE LETZTE ZEILE. Vorher waren es vier Blöcke
 *    untereinander — Preis, Buchstaben, «halal», «vegan» — in einer Spalte von 230 Pixeln.
 *    Gemessen an der echten Karte: eine Kachel wurde dadurch höher als ihr eigenes Foto, und
 *    vier Kacheln nebeneinander waren vier verschieden hohe Türme.
 *
 * ⛔ UND KEINE PUNKTLINIE AUF DIESER KARTE, obwohl sie hier zuerst gebaut wurde. Ausprobiert
 *    und am Bildschirm verworfen: bei vier Karten auf 1280 px ist eine Spalte 230 px breit, der
 *    Name bricht auf drei Zeilen, und von der Linie zum Preis bleiben vier Punkte übrig. Die
 *    Geste braucht Breite — sie steht deshalb bei der fotolosen Fassung weiter unten, wo zwei
 *    Karten nebeneinander stehen, und auf der Speisekarte, wo die Zeile die ganze Seite hat.
 *
 * ⚠️ KONTOR BLEIBT UNBERÜHRT: seine eigenen Regeln (`.layout-kontor .dishcard`, 0,2,0) stehen
 *    später in dieser Datei und überstimmen jede dieser Zeilen. Nachgesehen, nicht gehofft.
 */
.dishcard {
    display: grid;
    grid-template-columns: auto 1fr;
    align-content: start;
    column-gap: 10px;
}

.dishcard__photo { grid-row: 1; grid-column: 1 / -1; }
.dishcard__name { grid-row: 2; grid-column: 1 / -1; font-family: var(--serif); font-size: 1.16rem; margin: 2px 0 0; }
.dishcard__desc { grid-row: 3; grid-column: 1 / -1; color: var(--muted); font-size: .88rem; margin: 8px 0 0; }

.dishcard__price {
    grid-row: 4; grid-column: 1;
    align-self: center;
    margin-top: 12px;
    font-family: var(--serif); font-weight: 600; color: var(--accent-ink);
    font-variant-numeric: tabular-nums;
}

/* ⛔ EINE ZEILE STATT DREIER ABSÄTZE. Allergenbuchstaben, «halal» und «vegan» standen als drei
      eigene Blöcke untereinander; in einer 230-px-Spalte sind das drei Umbrüche für Angaben von
      je vier Zeichen. Gemessen: eine Kachel wurde dadurch höher als ihr eigenes Foto. */
.dishcard__tags {
    grid-row: 4; grid-column: 2;
    align-self: center; justify-self: end;
    display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px;
    margin-top: 12px;
}
/* ⛔ DIE ALLERGENBUCHSTABEN LIEGEN DIREKT IN DER KARTE. `.dishcard__tags` oben steht in keiner
      Vorlage mehr (Kontor-Umbau D-191), und das Aktionsband (D-219), die Vegan- und die
      Stadtseite schreiben `<p class="codes">` als Kind der Karte. Ohne Platz im Raster fiel der
      Kasten in die erste freie Zelle und füllte sie: neben dem Preis (Bühne, Tatami) als Streifen in
      voller Zeilenhöhe, in Ofen als Leiste ganz oben über dem Namen, in Kontor zwischen Name und
      Beschreibung. Er sitzt jetzt dort, wo die Tags-Zeile saß: in der letzten Zeile, dem Preis
      gegenüber, nur so breit wie seine Buchstaben und auf der Höhe des Preises. */
.dish-grid:not(.dish-grid--ohne-foto) > .dishcard > .codes {
    grid-row: 4; grid-column: 2;
    align-self: center; justify-self: end;
    margin-top: 12px;
}
/* DIE ZEICHEN DES HAUSES — 🌶️ am scharfen Gericht, ⭐ an der Empfehlung.

   SIE STEHEN VOR DEN ABZEICHEN UND SEHEN ANDERS AUS ALS SIE. Ein Abzeichen ist ein Wort in
   einer Pille («vegan»), ein Zeichen ist ein Bild ohne Rahmen — sonst liest das Auge beide als
   dieselbe Art Aussage, und die Allergenbuchstaben weiter unten wären die dritte.

   `line-height: 1` und die feste Grösse, weil Emoji je nach Betriebssystem unterschiedlich hoch
   sitzen und eine Zeile sonst je Gericht anders hoch wird. */
.dish-icons { display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 10px; margin-right: 8px; }
.dish-icon { font-size: 1rem; line-height: 1; cursor: default; }
.badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.badge { display: inline-flex; align-items: center; gap: .3em; font-size: .8125rem; font-weight: 700; }
/* Das Kennzeichen neben dem Wort (12.10.2026): Teller mit حلال, Blatt im Kreis. Etwas grösser
   als die Schrift, weil ein Kreis mit Zeichnung darin bei Schrifthöhe nur ein Punkt wäre. */
.badge .kz { width: 1.5em; height: 1.5em; flex: none; }
.badge--vegan { color: var(--enamel); }
/* HALAL — a mark, not a decoration, and deliberately NOT the vegan green. Two dietary claims in
   one colour read as one claim. This takes the brass the site already uses for anything the
   house says about itself. */
.badge--halal { color: var(--gold-ink); }

/* The sourcing sentence, under the card. Quiet: it is a fact, not a boast. */
.m-halal-note { color: var(--muted); font-size: var(--fs-1); margin: var(--s-5) auto 0; max-width: var(--wrap-narrow); }
.badge--vegetarian { color: var(--enamel); }
.badge--spicy { color: var(--accent-ink); }

/* ---------- Feature bands ---------- */
.lede { font-size: clamp(1.15rem, 2.6vw, 1.5rem); font-family: var(--serif); line-height: 1.4; max-width: 20em; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 5vw, 60px); align-items: center; }
@media (max-width: 760px) { .split { grid-template-columns: 1fr; } }

/* ---------- Info / contact ---------- */
.hours-list { list-style: none; padding: 0; margin: 0; }
.hours-list li { display: flex; justify-content: space-between; gap: 16px; padding: 8px 0; border-bottom: 1px solid var(--line-soft); }
.hours-list b { font-weight: 600; }
/* Wunsch zu einer Bestellzeile auf der Quittung — unter dem Gericht, leiser als das Gericht. */
.hours-list .zeilennotiz { display: block; font-weight: 400; color: var(--muted); }
/* "Feiertage: geöffnet" highlighted so guests notice we open on public holidays */
/* HEUTE: der Tag mit einem Punkt in der Hausfarbe, die Zeit in der Textfarbe und fett — nicht
   mehr in Grün. Das Grün war ein Fremdkörper in jedem Haus, dessen Farbe nicht grün ist, und es
   las sich als «offen», obwohl die Zeile nur «heute» weiss. Dieselbe Regel wie in der Fusszeile;
   `hours-heute` setzt das Partial auch an einem Ruhetag. */
.hours-list li.hours-open span { color: var(--text); font-weight: 700; }
/* HEUTE ohne Punkt davor (25.09.2026): Gewicht und Textfarbe tragen es. */
.hours-list li.hours-heute b,
.hours-list li.hours-heute span { color: var(--text); font-weight: 700; }
/* GRÜN NUR, WENN DIE TÜR JETZT OFFEN IST (10.10.2026): `hours-jetzt` setzt das Partial aus
   `isOpenAt()`, nicht aus «heute hat Fenster» — das Grün von früher stand um 23:30 auf einer
   Zeile, hinter der die Tür seit Stunden zu war. */
.hours-list li.hours-jetzt b,
.hours-list li.hours-jetzt span { color: var(--enamel); }

/* Die Fusszeile hebt HEUTE anders hervor: `.footer-hours li.hours-heute`, im Fusszeilenblock. */
.feiertag-note { display: inline-flex; align-items: center; gap: 8px; margin: 14px 0 0; font-weight: 600; color: var(--enamel); font-size: .95rem; }
.feiertag-note span { font-weight: 800; }

/* `.map-card` / `.map-attrib` ARE GONE, and this is the one deletion that removes something
   good. The component is a static map PICTURE behind a link — no embed, no third-party request,
   exactly what the Datenschutz page promises. It needs one thing this codebase does not have:
   somewhere for a restaurant to put that picture. There is no `contact.map_image` setting and no
   panel field to fill it, so every restaurant would render the same empty frame or none at all.
   Rather than ship a component nobody can switch on, the rules go; see the handover note. */

/* ---------- Ratgeber / long-form article ---------- */
.article-hero { padding: clamp(40px, 6vw, 72px) 0 clamp(18px, 3vw, 30px); }
.article-hero__title { font-size: clamp(2rem, 4.6vw, 3.1rem); margin: .12em 0 .3em; }
.article-hero__lead { font-size: clamp(1.1rem, 2.2vw, 1.35rem); color: var(--muted); font-family: var(--serif); line-height: 1.5; max-width: 34em; }
.breadcrumb { font-size: .82rem; color: var(--muted); margin: 8px 0 22px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.breadcrumb a { color: var(--muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--accent-ink); }
.breadcrumb [aria-current] { color: var(--text); }
.article { padding: clamp(28px, 4vw, 52px) 0 clamp(40px, 6vw, 72px); }
/* `.article__title` and `.article__lead` are deleted: a SECOND set of names for the article
   headline and standfirst, sized almost identically to `.article-hero__title` and
   `.article-hero__lead` above, which are the pair ratgeber-artikel.blade.php actually
   renders. Two names for one element is how the wrong one ends up in the next template —
   and here the unused pair was the one that looked more obvious. */
/* THE MEASURE LIVES HERE, and that is the whole shell decision for the text pages.
   Eight guest pages were built out of class names — `.section`, `.prose`, `.page-head` — that
   this stylesheet has never defined, so they rendered with no vertical band at all and their
   paragraphs ran the full 1036px of `.wrap`. Rather than invent a second page vocabulary beside
   the one the design already has, those pages now use the real names: `<section>` for the band
   (44–88px, line 195) and `.wrap--narrow` + this rule for the column.

   The cap sits on the RUNNING TEXT, not on `.article__body` itself. Capping the block would
   also have capped the table inside it, and a table is the one thing on a long page that wants
   every pixel of its column. Measured at 1280px: a paragraph was 676px wide and is now 564px —
   about 66 characters at 1.05rem, inside the 45–75 an eye tracks without losing the line —
   while `.article__body table` still spans the full 676px. */
.article__body { font-size: 1.05rem; line-height: 1.72; }
.article__body > p, .article__body > ul, .article__body > ol, .article__body > blockquote { max-width: 66ch; }
/* THERE WAS NO h1 RULE. This block sized h2 and h3 and stopped, so the page title on the
   Impressum, the Datenschutzerklärung and the invitation fell through to the user agent's
   `2em` — 32px, fixed, on a 316px phone column, which is what put the 382px scrollbar on the
   Datenschutz page. Fluid like every other heading here, and smaller at the bottom of the
   clamp than h2's own maximum would suggest, because these titles are single long German
   compounds rather than sentences. */
.article__body h1 { font-size: clamp(1.75rem, 5vw, 2.6rem); margin: 0 0 .45em; }
.article__body h2 { font-size: clamp(1.4rem, 3vw, 1.9rem); margin: 1.7em 0 .5em; }
.article__body h3 { font-size: 1.2rem; margin: 1.4em 0 .4em; }
.article__body p { margin: 0 0 1.1em; }
.article__body ul, .article__body ol { margin: 0 0 1.2em; padding-left: 1.3em; }
.article__body li { margin: .3em 0; }
.article__body a { color: var(--link); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.article__body a:hover { color: var(--accent-ink); }
.article__body blockquote { margin: 1.4em 0; padding: 4px 0 4px 20px; border-left: 3px solid var(--gold); font-family: var(--serif); font-size: 1.15rem; }
.article__body table { width: 100%; border-collapse: collapse; margin: 1.4em 0; font-size: .96rem; display: block; overflow-x: auto; }
.article__body th, .article__body td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.article__body thead th { background: var(--surface); font-family: var(--serif); font-weight: 600; border-bottom: 2px solid color-mix(in srgb, var(--gold) 40%, var(--line-soft)); }
.article__cta { display: flex; flex-wrap: wrap; gap: 12px; margin: 34px 0; }
/* `.article__related` (a "further reading" block) and `.rg-cluster__title` are deleted. No
   template has rendered either, and the Ratgeber index already links every article; a
   related-articles rail on a restaurant with four of them points back at itself. */
.rg-cluster { margin: 40px 0; }
.rg-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.rg-card { display: flex; flex-direction: column; gap: 6px; padding: 18px 20px; border: 1px solid var(--line-soft); border-radius: var(--r); background: var(--surface); text-decoration: none; color: var(--text); transition: transform var(--t), box-shadow var(--t), border-color var(--t); }
.section--surface .rg-card { background: var(--bg); }
.rg-card:hover { box-shadow: var(--shadow-sm); border-color: color-mix(in oklab, var(--gold) 44%, var(--line-soft)); }
.rg-card__cat { font-size: .8125rem; color: var(--gold-ink); font-weight: 600; }
.rg-card__title { font-family: var(--serif); font-size: 1.14rem; line-height: 1.25; }
.rg-card__teaser { font-size: .9rem; color: var(--muted); line-height: 1.5; }
.rg-card__more { margin-top: auto; font-size: .86rem; font-weight: 600; color: var(--accent-ink); }
.rg-card--hub { background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }

/* The `.faq` accordion is deleted, not left waiting for markup. Nothing in this repository has
   ever rendered it, and the reason it would stay that way is a product one: the questions have
   to be WRITTEN, by a restaurant owner, and an accordion with two rows in it looks emptier than
   the paragraph it replaced. The Ratgeber already carries anything worth answering at length. */

/* ---------- Footer ---------- */
/* DIE FUSSZEILE, ZWEITE FASSUNG (24.09.2026): ZWEI EBENEN, VIER SPALTEN, EIN MASS.
   Ebene 1 — Haus · Entdecken · Öffnungszeiten · Handlung — soll auf dem Breitbild etwa 320–380px
   Inhalt tragen, nicht 700px schwarze Fläche; darunter, falls SEO-Seiten live sind, eine Zeile
   «Gut zu wissen». Ebene 2 — die Rechtszeile als dünnes Band in drei Feldern: Haus links,
   Pflichtwege mittig, «Mein Konto» und «Intern» rechts. Kein Zeichen mehr rechts unten.

   DIESELBE FUSSZEILE AUF JEDER SEITE UND IN JEDEM HAUS — die Begründung steht in layout.blade.php.
   Die Bauteile sind für vier Spalten gedacht, von denen zwei kommen und gehen (Zeiten, Handlung);
   nichts darf davon abhängen, dass eine bestimmte Spalte da ist.

   ⚠️ HAARLINIEN UND DER TON DES BANDS AUS `currentColor`, NICHT AUS FESTEN WERTEN. Ofen malt den
      Fuss auf seine Platte, das helle Layout auf Papier, die Bühne auf Nacht. Eine Linie, die zu
      zehn Prozent aus der Schriftfarbe besteht, ist auf jedem dieser Gründe eine Linie; ein festes
      rgba(255,255,255,.1) war auf Papier unsichtbar und auf der Platte ein Fremdton. */
.site-footer { background: var(--footer-bg); color: var(--footer-text); margin-top: 40px; border-top: 1px solid color-mix(in srgb, currentColor 10%, transparent); }
.site-footer a { color: var(--footer-text); text-decoration: none; }
.site-footer a:hover { color: var(--gold); }
/* Der Fuss hat sein eigenes Mass: 1320px statt der 1080px der Textseiten. Vier Spalten brauchen
   die Breite, und ein Fuss ist kein Fliesstext, der eine Zeilenlänge halten muss. `max()` gegen
   das fliessende --wrap: seit die Spalte auf grossen Schirmen bis 1360px wächst, darf der Fuss
   nicht schmaler stehen als der Inhalt darüber. Auf dem Laptop weiter exakt 1320px. */
.site-footer .footer-wrap { max-width: max(1320px, var(--wrap)); padding-left: clamp(20px, 3vw, 40px); padding-right: clamp(20px, 3vw, 40px); }
/* Flex statt Grid, weil die Zahl der Spalten eine Laufzeittatsache ist (siehe oben): ein Raster
   mit vier Spuren hielt eine davon dauerhaft leer. Die Anteile sind das asymmetrische Raster —
   das Haus breit, das Verzeichnis schmal, die Zeiten mit Platz für «11:30–14:30, 17:00–22:00».
   `min-width: 0` ist die Umbruchsicherung: eine Post-Adresse ist ein einziges langes Wort. */
.footer-grid { display: flex; flex-wrap: wrap; gap: 32px 40px; padding: 44px 0 36px; }
.footer-grid > * { flex: 1 1 160px; min-width: 0; }
.footer-brand { flex: 1.35 1 230px; }
.footer-verzeichnis { flex: .85 1 150px; }
.footer-zeiten { flex: 1.15 1 240px; }
.footer-tat { flex: 1 1 210px; }
/* ALLE SPALTEN BEGINNEN AUF EINER LINIE: der Kolumnentitel ist 18px hoch und hat 14px Luft
   darunter; das Zeichen des Hauses steht statt eines Titels oben in seiner Spalte. */
.footer-brand__mark {
    display: block; height: 40px; width: auto; max-width: 160px; object-fit: contain;
    margin: 0 0 12px; background: none; padding: 0; border-radius: 0;
}
/* Die helle Fassung in der Fusszeile (D-164): keine Platte, kein Rand — die Fläche ist dunkel. */
.footer-brand__mark--dunkel { background: none; padding: 0; border-radius: 0; }
.footer-brand__name { font-family: var(--serif); font-size: 1.35rem; font-weight: 600; color: #fff; margin: 0 0 2px; display: block; line-height: 1.2; letter-spacing: -.005em; }
/* Der Zusatz («Καλώς ήρθατε», die Schrift des Hauses in seiner Sprache) steht als Geschwister NEBEN
   dem Namen, nicht darin. Auf dem dunklen Grund gilt das Gold, das für dunkle Gründe gemischt ist. */
.footer-brand .accent-script { display: block; font-size: .8rem; color: var(--on-dark-accent); margin: 0 0 8px; }
/* Der Claim des Hauses (`restaurant.tagline`) als ein Satz unter dem Namen — gedämpft und schmal
   gesetzt, damit er eine Zeile bleibt und keine Spalte wird. */
.footer-brand__claim { margin: 0 0 16px; max-width: 30ch; font-size: .92rem; line-height: 1.5; color: var(--footer-muted); }
/* Adresse, Telefon, Post: das Zeichen in einer festen 16px-Spalte, damit eine umbrechende Adresse
   unter ihrer ersten Zeile weiterläuft und nicht unter dem Zeichen. */
.footer-kontakt { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 6px; font-size: .9rem; line-height: 1.45; }
.footer-kontakt li { display: grid; grid-template-columns: 16px 1fr; gap: 10px; align-items: start; color: var(--footer-muted); overflow-wrap: anywhere; }
.footer-kontakt svg { width: 16px; height: 16px; margin-top: 2px; color: var(--gold); }
.footer-kontakt a { color: var(--footer-text); }
.footer-kontakt a:hover { color: var(--gold); }
/* Die Spaltentitel als Kolumnentitel: klein, gesperrt, in Versalien, im Gold für dunkle Gründe. */
.footer-h { font-family: var(--sans); font-weight: 600; font-size: .8125rem; color: var(--on-dark-accent); margin: 0 0 14px; line-height: 1.3; }
/* Das Verzeichnis gedämpft, beim Zeigen weiss: die Wege sind da, sie rufen nicht. */
.footer-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; font-size: .9rem; }
.footer-links a { color: var(--footer-muted); }
.footer-links a:hover { color: #fff; }
/* Die Zustandszeile: ein Punkt, ein Wort, eine Uhrzeit. Der Punkt trägt die Farbe — grün mit
   einem weichen Hof, wenn offen; das gedämpfte Grau der Fusszeile, wenn zu. */
.footer-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 8px; font-size: .86rem; color: #fff; }

.footer-status__wort { font-weight: 600; }
.footer-status__zeit { color: var(--footer-muted); }
.footer-status__zeit::before { content: "·"; margin-right: 8px; opacity: .6; }
/* DIE WOCHE KNAPP: 4px je Zeile, .86rem, Haarlinien aus der Schriftfarbe, Tabellenziffern rechts.
   Sieben Zeilen sind so 190px hoch, nicht 260 — die Zeiten sind eine Auskunft, kein Aufmacher. */
.footer-hours { list-style: none; margin: 0; padding: 0; }
.footer-hours li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 4px 0; border-bottom: 1px solid color-mix(in srgb, currentColor 8%, transparent); font-size: .86rem; line-height: 1.35; }
.footer-hours li:last-child { border-bottom: 0; }
.footer-hours b { color: var(--footer-text); font-weight: 500; }
/* Tabellenziffern, damit «17:00–22:00» unter «11:30–14:30, 17:00–22:00» in der Spalte steht. */
.footer-hours span { color: var(--footer-muted); font-variant-numeric: normal; text-align: right; }
/* HEUTE: ein goldener Punkt vor dem Tag, Tag und Zeit in Weiss — nicht in Grün. Grün hiess in der
   ersten Fassung «heute hat das Haus Fenster», und um 23:30 stand die Zeile grün da, während die
   Tür seit anderthalb Stunden zu war. Ob GERADE offen ist, sagt die Zeile darüber; die Tabelle
   sagt nur, welcher Tag heute ist — auch wenn heute Ruhetag ist. */
.footer-hours li.hours-heute b, .footer-hours li.hours-heute span { color: #fff; font-weight: 600; }
/* Grün nur, solange die Tür JETZT offen ist (`hours-jetzt`, siehe `.hours-list` oben). */
.footer-hours li.hours-jetzt b, .footer-hours li.hours-jetzt span,
.footer-status__wort--offen { color: var(--footer-open); }

.footer-note { color: var(--footer-dim); font-size: .8rem; margin: 8px 0 0; }
/* Die Netzwerke als kleine Ringe, 34px, Linie aus der Schriftfarbe: leise genug, dass sie das Haus
   nicht überstimmen, gross genug für einen Daumen. `flex: 0 0 auto` am SVG, weil ein Bild ohne
   eigene Breite im Flex sonst zum leeren Ring zusammenfällt. */
.footer-social { display: flex; gap: 8px; margin: 0; }
.footer-social a { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 999px; border: 1px solid color-mix(in srgb, currentColor 22%, transparent); color: var(--footer-text); transition: color var(--t), border-color var(--t), background var(--t); }
.footer-social a:hover { color: var(--gold); border-color: currentColor; background: color-mix(in srgb, currentColor 6%, transparent); }
.footer-social a svg { width: 16px; height: 16px; flex: 0 0 auto; fill: currentColor; }
/* DIE HANDLUNG: zwei Knöpfe untereinander, 42px hoch, nicht breiter als 260px — deutlich, nicht
   riesig. Der volle trägt die Hausfarbe, das einzige farbige Bauteil der Fusszeile; der zweite nur
   eine Linie. Drei Klassen tief, damit weder `.site-footer a` noch die Regel des hellen Layouts
   die Schrift auf der Fläche umfärben. Darunter die Nummer als dritter Weg. */
.footer-tat__knoepfe { display: grid; gap: 8px; max-width: 260px; }
.site-footer .footer-tat__knopf {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    min-height: 44px; padding: 0 16px; border-radius: var(--r-btn); border: 1px solid transparent;
    font-weight: 600; font-size: .9rem; line-height: 1.2;
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.site-footer .footer-tat__knopf svg { flex: 0 0 auto; }
.site-footer .footer-tat__knopf.footer-tat__knopf--voll { background: var(--accent); color: var(--on-accent); }
.site-footer .footer-tat__knopf.footer-tat__knopf--voll:hover { background: var(--accent-strong); color: var(--on-accent); box-shadow: 0 6px 18px color-mix(in oklab, var(--accent) 26%, transparent); }
.site-footer .footer-tat__knopf.footer-tat__knopf--rand { border-color: color-mix(in srgb, currentColor 28%, transparent); color: inherit; }
.site-footer .footer-tat__knopf.footer-tat__knopf--rand:hover { border-color: currentColor; background: color-mix(in srgb, currentColor 6%, transparent); color: inherit; }
.footer-tat__hinweis { margin: 12px 0 0; font-size: .82rem; color: var(--footer-dim); }
.footer-tat__hinweis a { color: var(--footer-muted); }
/* GUT ZU WISSEN ALS EINE ZEILE unter den Spalten: Kolumnenwort links, die Themen daneben, mit
   Punkten getrennt; bricht die Zeile, bricht sie wie ein Absatz, nicht wie eine Tabelle. */
.footer-themen { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px; padding: 14px 0 22px; border-top: 1px solid color-mix(in srgb, currentColor 8%, transparent); font-size: .84rem; }
.footer-themen__wort { font-family: var(--sans); font-weight: 600; font-size: .8125rem; color: var(--on-dark-accent); white-space: nowrap; }
.footer-themen__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 0; }
.footer-themen__liste li + li::before { content: "·"; margin: 0 10px; opacity: .45; }
.footer-themen__liste a { color: var(--footer-muted); }
.footer-themen__liste a:hover { color: #fff; }
/* EBENE 2 — die Rechtszeile als dünnes Band, eine Spur heller als der Fuss (auf Papier: eine
   Spur dunkler), durch eine Haarlinie getrennt. Drei Felder: Haus | Pflichtwege | Türen. Die
   mittlere Spur ist `auto`, die äusseren gleich breit — so steht die Mitte wirklich mittig. */
.footer-bar { background: color-mix(in srgb, currentColor 4%, transparent); border-top: 1px solid color-mix(in srgb, currentColor 10%, transparent); font-size: .78rem; }
.footer-bar__zeile { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px 24px; padding-top: 12px; padding-bottom: 12px; }
/* Die Rechtszeile gedämpft, die Wege darin in der Textfarbe; die Punkte dazwischen kommen aus dem
   Blatt, nicht aus dem Text — so steht am Zeilenende nie ein Punkt allein. */
.footer-legal { margin: 0; color: var(--footer-muted); display: flex; flex-wrap: wrap; align-items: center; gap: 2px 0; }
.footer-legal--haus { justify-content: flex-start; }
.footer-legal--recht { justify-content: center; }
.footer-legal--intern { justify-content: flex-end; }
.footer-legal > * + *::before { content: "·"; margin: 0 10px; opacity: .45; }
.footer-legal__jahr { color: var(--footer-text); }
/* DIE SIGNATUR DES WERKZEUGS (D-126): nur die Wortmarke, 14px hoch, gut zwei Drittel Deckkraft,
   voll beim Zeigen — als letztes Glied hinter «Intern», mit demselben Punkt davor wie jeder Weg.
   Die Deckkraft sitzt auf dem Link, weil er nichts enthält als das Bild. height AND width stehen
   auch auf dem <img> (Layoutstabilität); die Regel hier gewinnt über diese Hinweise. */
.signature { display: inline-flex; align-items: center; text-decoration: none; color: inherit; opacity: .72; transition: opacity var(--t); }
.signature__mark { height: 14px; width: auto; display: block; }
/* Zwei Fassungen im Markup, eine sichtbar: die weisse auf dunklem Fuss, die dunkle dort, wo ein
   Layout den Fuss auf Papier malt (unten bei dessen Regeln). Kein Filter mehr — der drehte die
   Flamme des Zeichens ins Gegenteil. */
.signature__mark--dunkel { display: none; }
.signature:hover,
.signature:focus-visible { opacity: 1; }
@media (max-width: 1100px) { .footer-grid { gap: 30px 32px; } }
@media (max-width: 900px) {
    .footer-grid { gap: 28px 32px; padding: 40px 0 32px; }
    /* Das Band stapelt seine drei Felder links untereinander, sobald sie nicht mehr in eine Zeile passen. */
    .footer-bar__zeile { grid-template-columns: 1fr; gap: 6px; }
    .footer-legal--recht, .footer-legal--intern { justify-content: flex-start; }
}
@media (max-width: 520px) {
    /* Eine Spalte, als Basis gesagt statt als Vorlage: das Raster ist eine Flex-Zeile. Die Handlung
       wird dabei so breit wie die Seite; die Wege sind ohnehin 44px hoch (Daumenregel weiter oben),
       darum kein Abstand mehr obendrauf; die Rechtszeile bricht ohne Punkte. */
    .footer-grid { gap: 26px; padding: 36px 0 28px; }
    .footer-grid > *, .footer-brand, .footer-verzeichnis, .footer-zeiten, .footer-tat { flex-basis: 100%; }
    .footer-links { gap: 2px; }
    .footer-tat__knoepfe { max-width: none; }
    .footer-themen { padding: 12px 0 18px; gap: 6px 14px; }
    .footer-themen__liste { gap: 4px 14px; }
    .footer-themen__liste li + li::before { display: none; }
    .footer-legal { gap: 2px 16px; }
    .footer-legal > * + *::before { display: none; }
    .footer-bar__zeile { padding-top: 12px; padding-bottom: 16px; }
}

/* ---------- Die Daumenleiste (Telefon) ----------

   ⛔ SIE SAH AUS WIE EIN FUSS, NICHT WIE EIN BEDIENTEIL. Eine weisse Leiste von Kante zu Kante,
      drei Zeichen über drei Wörtern, «Speisekarte» dauerhaft in der Hausfarbe — auf JEDER Seite,
      also auch dort, wo der Gast gar nicht auf der Speisekarte stand. Die Farbe sagte «hier bist
      du» und meinte «hierhin solltest du».

   DREI GETRENNTE AUSSAGEN, UND JEDE HAT IHR EIGENES ZEICHEN:
   · WO BIN ICH — die Pille (seit D-182 ein Kreis über der Kante) am Ziel der aktuellen Seite,
     vom Server gesetzt. Auf Seiten, die kein Ziel der Leiste sind (auch der Startseite), steht
     sie an der Speisekarte in der Mitte: Betreiber 27.09., «ilk açıldığında Speisekarte oyuklu».
   · WAS SOLL ICH TUN — «Reservieren» sitzt in einer kleinen erhabenen Kapsel mit dem Zeichen in
     der Hausfarbe. Gleich gross wie die Nachbarn; sie hebt sich ab, sie drängt sich nicht vor.
   · WAS GEHT NOCH — Anrufen, Warenkorb: ruhig, grau, dieselbe Grösse.

   ⚠️ DIE PILLE IST EIN EINZIGES ELEMENT, UND SIE WANDERT. Beim Tippen schiebt `site.js` dasselbe
      Element unter das neue Ziel und lässt es vom alten Platz hinübergleiten (nur `transform`);
      die Seitenüberblendung trägt es als benanntes Element weiter. Es wird nie eines abgebaut und
      ein anderes aufgebaut. Ohne Skript steht es einfach am richtigen Platz.

   ⛔ UND SIE KOMMT AUF DER NEUEN SEITE AN — der Teil, der am 19.09. auf dem Telefon fehlte
      («hâlâ aynı»). Die alte Seite ist auf einem schnellen Netz weg, bevor die Pille gleiten
      kann, und ohne Seitenüberblendung stand sie auf der neuen einfach schon da. Jetzt übergibt
      die alte Seite den Platz (site.js, `pagehide`), und die neue lässt sie von dort herüber-
      gleiten (leiste-init.js + «ANKUNFT» unten). Leiste, Pille und Kapsel sind seitdem volle
      Kapseln (`--leiste-rundung`), und die Pille ist eine Spur kräftiger, damit man den Weg sieht.

   ⚠️ SCHWEBEND, NICHT ANGEKLEBT. Abstand zu drei Rändern, die Seite hält unten `--leiste-reserve`
      frei, damit ihr Ende über der Leiste zu liegen kommt. Auf breiten Telefonen und Tablets
      bleibt sie bei 520px und steht mittig — eine 840px lange Leiste mit drei Zielen darin ist
      eine Leiste voller Luft.

   ⚠️ EIN GEGENSTAND, KEIN STREIFEN (Feinschliff 19.09.2026, D-143). Warmes Weiss zu 94 %, dahinter
      ein leichter Weichzeichner, damit ein Foto darunter als Ton durchscheint und nicht als Bild;
      oben eine Lichtkante, unten ein weiter, weicher Schatten. Kein Glas: bei 94 % Deckkraft ist
      der Weichzeichner eine Oberfläche, kein Effekt.

   ⛔ DIE MULDE (27.09.2026, D-182). Der Betreiber wollte die Leiste aus dem Codepen «Nice
      animated bottom menu» (vikassingh1111/rNGxXzB), geglättet nach «NotchNav» auf 21st.dev
      (21st.dev/@jatin-yadav05/components/notch-nav): das aktuelle Ziel sitzt in einem Kreis in
      der Hausfarbe, der über die Oberkante steigt, und die Leiste weicht ihm mit einer runden
      Mulde aus. Der Codepen fälscht die Mulde mit einem Rand in der Farbe des Seitengrunds; bei
      uns liegt die Leiste über Fotos und über hellen wie dunklen Seiten, also wird sie wirklich
      ausgeschnitten: die Fläche ist `::before` mit einer Maske, der Schatten ein `drop-shadow`
      auf der Leiste, der dem ausgeschnittenen Umriss samt Kreis folgt.

   ⚠️ DARUM KEIN WEICHZEICHNER MEHR. `filter` auf der Leiste macht sie zur Wurzel jedes
      `backdrop-filter` darin — die Fläche sähe nichts mehr hinter sich. Sie ist deckend. */
.mobilebar {
    position: fixed; z-index: 45; display: none;
    left: var(--leiste-abstand); right: var(--leiste-abstand);
    bottom: calc(var(--leiste-abstand) + env(safe-area-inset-bottom, 0px));
    max-width: 520px; margin-inline: auto;
    gap: 4px; padding: 6px;
    filter: var(--leiste-schatten);
}
/* DIE FLÄCHE MIT DER MULDE. Vier Masken-Ebenen, addiert:
   1. alles unterhalb der Schulterhöhe, ohne den Kreis der Mulde;
   2. der Streifen darüber links und rechts der Mulde;
   3. + 4. je ein kleiner Kreis, der die Kante zur Mulde abrundet (die «Schultern» — ohne sie
      stünden zwei spitze Ecken neben dem Kreis).
   Die Mitte der Mulde ist die Mitte des aktuellen Ziels, aus Platz und Zahl der Ziele gerechnet,
   also ohne Skript und im ersten Bild richtig (`--kuhle-i`, `--kuhle-n` weiter unten). */
.mobilebar::before {
    --kx: calc(6px + (var(--kuhle-i) + .5) * (100% - 12px - (var(--kuhle-n) - 1) * 4px) / var(--kuhle-n) + var(--kuhle-i) * 4px);
    --ks: calc(var(--kuhle-r) * .27);
    --kd: calc(var(--kuhle-r) + var(--ks));
    content: ""; position: absolute; inset: 0; z-index: -1;
    border-radius: var(--leiste-rundung);
    background: var(--leiste-flaeche);
    box-shadow: inset 0 0 0 1px var(--leiste-linie), inset 0 1px 0 rgba(255, 255, 255, .75);
    -webkit-mask:
        radial-gradient(circle var(--kuhle-r) at var(--kx) calc(4px - var(--ks)), transparent calc(100% - .5px), #000 100%) 0 var(--ks) / 100% calc(100% - var(--ks)) no-repeat,
        linear-gradient(90deg, #000 calc(var(--kx) - var(--kd)), transparent 0 calc(var(--kx) + var(--kd)), #000 0) 0 0 / 100% var(--ks) no-repeat,
        radial-gradient(circle var(--ks) at calc(var(--kx) - var(--kd)) var(--ks), #000 calc(100% - .5px), transparent 100%) 0 0 / 100% var(--ks) no-repeat,
        radial-gradient(circle var(--ks) at calc(var(--kx) + var(--kd)) var(--ks), #000 calc(100% - .5px), transparent 100%) 0 0 / 100% var(--ks) no-repeat;
    mask:
        radial-gradient(circle var(--kuhle-r) at var(--kx) calc(4px - var(--ks)), transparent calc(100% - .5px), #000 100%) 0 var(--ks) / 100% calc(100% - var(--ks)) no-repeat,
        linear-gradient(90deg, #000 calc(var(--kx) - var(--kd)), transparent 0 calc(var(--kx) + var(--kd)), #000 0) 0 0 / 100% var(--ks) no-repeat,
        radial-gradient(circle var(--ks) at calc(var(--kx) - var(--kd)) var(--ks), #000 calc(100% - .5px), transparent 100%) 0 0 / 100% var(--ks) no-repeat,
        radial-gradient(circle var(--ks) at calc(var(--kx) + var(--kd)) var(--ks), #000 calc(100% - .5px), transparent 100%) 0 0 / 100% var(--ks) no-repeat;
}
/* Das Ziel: drei (mit Warenkorb vier) gleich breite Spalten, Zeichen über Wort, 58 px hoch —
   weit über den 44 × 44, die ein Daumen braucht.

   `.mobilebar__korb` ist dieselbe Form als <button> (er öffnet die Schublade, er navigiert nicht). */
.mobilebar > a,
.mobilebar__korb {
    position: relative; flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    min-height: 58px; padding: 5px 4px 6px;
    border: 0; border-radius: calc(var(--leiste-rundung) - 6px);
    background: none; color: var(--leiste-still);
    font: 500 .75rem/1.2 var(--sans); letter-spacing: .005em;
    text-decoration: none; cursor: pointer;
    -webkit-tap-highlight-color: transparent; touch-action: manipulation;
    transition: transform .24s var(--leiste-kurve), color .25s var(--leiste-kurve);
}
/* ANTWORTET SOFORT, FEDERT WEICH ZURÜCK. Hinein in 110 ms auf .96, heraus in 240 ms auf der Kurve
   der Leiste — der Finger spürt eine Antwort, bevor die Seite überhaupt zu laden beginnt. (iOS
   setzt `:active` nur, wenn ein Berührungs-Lauscher hängt; den legt `site.js` an die Leiste.) */
.mobilebar > a:active,
.mobilebar__korb:active { transform: scale(.96); transition-duration: .11s; }
.mobilebar > a:focus-visible,
.mobilebar__korb:focus-visible { outline-offset: -2px; box-shadow: none; }

.mobilebar__wort {
    position: relative; z-index: 1; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* FÜNF ZIELE (D-182): bei 390px bleiben je Ziel 68px, und «Reservieren», «Speisekarte» und
   «Warenkorb» liefen in 12px über den Rand (gemessen: `scrollWidth > clientWidth`). Eine halbe
   Stufe kleiner, enger gesetzt und ohne Seitenpolster passen alle drei auch bei 360px. */
.mobilebar:has(> :nth-child(5)) > * { padding-inline: 0; font-size: .6875rem; letter-spacing: -.01em; }
/* Das Wort unter dem Kreis ist eine Stufe fester und damit breiter: «Reservieren» lief bei 360px
   genau dort über. Enger gesetzt statt dünner, damit es fest bleibt. */
.mobilebar:has(> :nth-child(5)) > a:has(> .mobilebar__pille) { letter-spacing: -.03em; }
/* Ein Raster, damit die Linien- und die Flächenfassung desselben Zeichens übereinander liegen
   und ineinander blenden können. Alle Zeichen stehen in derselben Kiste, also stehen alle
   Wörter auf derselben Linie — auch neben der Kapsel von «Reservieren». */
.mobilebar__glyph {
    position: relative; z-index: 1; display: grid; place-items: center;
    width: 44px; height: 30px;
}
/* An SVG inside a flex or grid cell has no intrinsic size to defend — the width and height are
   what stop it collapsing to a 0px sliver (the same failure documented on `.nav__social`). */
.mobilebar__ic {
    grid-area: 1 / 1; position: relative;
    width: 24px; height: 24px; flex: 0 0 auto;
    transition: opacity .2s var(--leiste-kurve), color .25s var(--leiste-kurve);
}
.mobilebar__ic--voll { opacity: 0; }

/* ── WO BIN ICH ── Zeichen in Fläche und Hausfarbe, Wort eine Stufe fester, dahinter die Pille:
   ein Hauch der Hausfarbe, eine Lichtkante und eine kaum sichtbare Erhebung. */
.mobilebar > a:has(> .mobilebar__pille) { color: var(--leiste-akzent-wort); font-weight: 600; }
.mobilebar > a:has(> .mobilebar__pille) .mobilebar__ic--voll { opacity: 1; }
.mobilebar > a:has(> .mobilebar__pille) .mobilebar__ic--linie { opacity: 0; }
/* ⛔ DIE PILLE LIEGT UNTER JEDEM WORT DER LEISTE, NICHT NUR UNTER DEM EIGENEN. Sie steckt im
      Ziel, zu dem sie gehört — und gleitet auf dem Weg dorthin über den Nachbarn. Ohne Ebenen
      zeichnete das spätere Ziel samt Pille über das frühere: bei 390px deckte sie beim Wechsel
      Reservieren → Speisekarte das «n» von «Reservieren» zu (Einzelbild bei verlangsamter Uhr).
      Pille auf Ebene 0, Zeichen und Wort auf 1 — und weil die Ziele selbst KEINEN Stapelkontext
      bilden (kein z-index, `transform` nur beim Drücken), gelten die Ebenen über die ganze Leiste. */
.mobilebar__pille {
    position: absolute; inset: 0; z-index: 0;
    border-radius: inherit; pointer-events: none;
}
/* ⚠️ DER KREIS IST DAS `::before` DER PILLE, NICHT DIE PILLE SELBST. Die Pille bleibt so gross wie
      ihr Ziel: `site.js` misst sie, um den Platz beim Gehen aufzuschreiben, und `pille-kommt`
      rechnet ihren Weg in Pillenbreiten (`100% + 4px`). Der Kreis steht mittig darüber, seine
      Mitte 4px unter der Oberkante der Leiste — dort, wo auch die Mulde ihre Mitte hat. */
.mobilebar__pille::before {
    content: ""; position: absolute;
    left: calc(50% - 24px); top: -26px;
    width: 48px; height: 48px; border-radius: 50%;
    background: var(--leiste-akzent);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22);
}
/* Das Zeichen steigt in den Kreis, das Wort rückt ihm eine Spur nach. `translate` statt
   `transform`: die Tipp-Gesten unten animieren `transform` und setzten es sonst zurück. */
.mobilebar__glyph,
.mobilebar__wort { transition: translate .32s var(--leiste-kurve); }
.mobilebar > a:has(> .mobilebar__pille) .mobilebar__glyph { translate: 0 -22px; }
.mobilebar > a:has(> .mobilebar__pille) .mobilebar__wort { translate: 0 -5px; }
/* Die Farbe sitzt am Rahmen des Zeichens, die Zeichen erben sie und blenden in ihren 250 ms hinüber:
   ein weisses Zeichen, das vor dem Kreis ankäme, stünde weiss auf weiss. */
.mobilebar > a:has(> .mobilebar__pille) .mobilebar__glyph { color: var(--leiste-auf-akzent); }

/* ── WAS SOLL ICH TUN ── Eine kleine erhabene Kapsel: heller als die Leiste, ein feiner Rand in
   der Hausfarbe, ein kurzer Schatten, das Zeichen in `--leiste-akzent-wort`. Ist Reservieren die
   aktuelle Seite, füllt sich die Kapsel mit der Hausfarbe und das Zeichen nimmt
   `--leiste-auf-akzent` (je Haus gerechnet). Das Wort bleibt Tinte, bis es aktiv ist: ein
   farbiges Wort ohne Pille hiesse «hier bist du». */
.mobilebar > a[data-ziel="reservieren"] { color: var(--leiste-tinte); }
.mobilebar > a[data-ziel="reservieren"]:has(> .mobilebar__pille) { color: var(--leiste-akzent-wort); }
.mobilebar > a[data-ziel="reservieren"] .mobilebar__glyph::before {
    content: ""; position: absolute; inset: 0;
    border-radius: 999px;
    background: var(--leiste-kapsel);
    box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--leiste-akzent) 26%, transparent),
                0 1px 1px rgba(30, 35, 32, .06),
                0 3px 8px -3px rgba(30, 35, 32, .20);
    transition: background-color .25s var(--leiste-kurve), box-shadow .25s var(--leiste-kurve);
}
/* Aktiv trägt der Kreis die Hausfarbe; die Kapsel darf nicht als zweiter Ring darin stehen. */
.mobilebar > a[data-ziel="reservieren"]:has(> .mobilebar__pille) .mobilebar__glyph::before {
    background: transparent;
    box-shadow: none;
}
.mobilebar > a[data-ziel="reservieren"] .mobilebar__ic {
    width: 21px; height: 21px; color: var(--leiste-akzent-wort);
}
.mobilebar > a[data-ziel="reservieren"]:has(> .mobilebar__pille) .mobilebar__ic { color: var(--leiste-auf-akzent); }

/* ── BEWEGUNG ── Jedes Zeichen antwortet auf das Tippen mit seiner eigenen kleinen Geste, einmal,
   nie in Schleife: das Telefon klingelt an (5°), der Kalender hebt sich, das Besteck steigt mit
   einer Spur Drehung. `site.js` setzt `.is-tipp` und nimmt es am Ende der Animation wieder ab. */
@media (prefers-reduced-motion: no-preference) {
    .mobilebar > .is-tipp[data-ziel="anrufen"] .mobilebar__ic { animation: leiste-klingeln .32s cubic-bezier(.33, 0, .2, 1); }
    .mobilebar > .is-tipp[data-ziel="reservieren"] .mobilebar__glyph { animation: leiste-heben .3s var(--leiste-kurve); }
    .mobilebar > .is-tipp[data-ziel="karte"] .mobilebar__ic { animation: leiste-steigen .3s var(--leiste-kurve); }
    .mobilebar__korb.is-tipp .mobilebar__ic { animation: leiste-heben .28s var(--leiste-kurve); }
}
/* Bei reduzierter Bewegung bleibt vom Druck nur ein Aufhellen — der Zustand wechselt trotzdem. */
@media (prefers-reduced-motion: reduce) {
    .mobilebar > a:active,
    .mobilebar__korb:active { transform: none; opacity: .7; }
}
/* ── ANKUNFT ── Kommt der Gast über die Leiste, gleitet die Pille auf der NEUEN Seite von dort
   herüber, wo sie beim Gehen stand (leiste-init.js setzt `--pille-von` und `.leiste-kommt`, nur
   wenn der Browser die Seitenüberblendung nicht selbst übernimmt). Der Weg ist in Plätzen gemessen:
   ein Platz ist die Breite der Pille plus die 4px Lücke der Leiste — dieselbe Rechnung wie das
   `transform` in site.js, nur ohne Messen, damit sie im ersten Bild schon stimmt. */
.mobilebar > :nth-child(1) { --pille-zu: 0; }
.mobilebar > :nth-child(2) { --pille-zu: 1; }
.mobilebar > :nth-child(3) { --pille-zu: 2; }
.mobilebar > :nth-child(4) { --pille-zu: 3; }
.mobilebar > :nth-child(5) { --pille-zu: 4; }
@media (prefers-reduced-motion: no-preference) {
    html.leiste-kommt:not(.leiste-neu) .mobilebar__pille { animation: pille-kommt .34s var(--leiste-kurve) both; }
    html.leiste-kommt.leiste-neu .mobilebar__pille { animation: pille-erscheint .3s var(--leiste-kurve) both; }
}
@keyframes pille-kommt {
    from { transform: translateX(calc((var(--pille-von, 0) - var(--pille-zu, 0)) * (100% + 4px))); }
}
@keyframes pille-erscheint {
    from { opacity: 0; transform: scale(.8); }
}
/* ── DIE MULDE WANDERT MIT ── Platz (`--kuhle-i`) und Zahl der Ziele (`--kuhle-n`) liest das
   Stylesheet aus der Leiste selbst: welches Kind die Pille trägt (nicht `aria-current`: auf der
   Startseite steht der Kreis an der Speisekarte, ohne dass sie die aktuelle Seite wäre), wie viele
   Kinder es gibt, und ob der Warenkorb-KNOPF sichtbar ist (`html.has-cart`, sonst `display: none`).
   Registriert, damit sie gleiten können: tippt der Gast, hängt `site.js` `aria-current` um, und
   die Mulde gleitet in denselben 320 ms und auf derselben Kurve wie die Pille. Ohne Ziel ist ihr
   Halbmesser 0; das kommt nur vor, wenn das Haus weder Karte noch Reservierung in der Leiste hat. */
@property --kuhle-i { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --kuhle-r { syntax: "<length>"; inherits: true; initial-value: 0px; }
.mobilebar { --kuhle-i: 0; --kuhle-r: 0px; --kuhle-n: calc(var(--kuhle-kinder, 1) - var(--kuhle-ohne-korb, 0)); }
.mobilebar:has(> :nth-child(2)) { --kuhle-kinder: 2; }
.mobilebar:has(> :nth-child(3)) { --kuhle-kinder: 3; }
.mobilebar:has(> :nth-child(4)) { --kuhle-kinder: 4; }
.mobilebar:has(> :nth-child(5)) { --kuhle-kinder: 5; }
html:not(.has-cart) .mobilebar:has(> button.mobilebar__korb) { --kuhle-ohne-korb: 1; }
.mobilebar:has(> * > .mobilebar__pille) { --kuhle-r: 30px; }
.mobilebar:has(> :nth-child(2) > .mobilebar__pille) { --kuhle-i: 1; }
.mobilebar:has(> :nth-child(3) > .mobilebar__pille) { --kuhle-i: 2; }
.mobilebar:has(> :nth-child(4) > .mobilebar__pille) { --kuhle-i: 3; }
.mobilebar:has(> :nth-child(5) > .mobilebar__pille) { --kuhle-i: 4; }
@media (prefers-reduced-motion: no-preference) {
    .mobilebar { transition: --kuhle-i .32s var(--leiste-kurve), --kuhle-r .3s var(--leiste-kurve); }
    /* Auf der neuen Seite kommt die Mulde von dort, wo die Pille ging (`leiste-kommt` aus
       leiste-init.js, auch unter einer Seitenüberblendung: siehe `daumenleiste` unten), oder sie öffnet sich, wenn vorher keine war. */
    html.leiste-kommt:not(.leiste-neu) .mobilebar::before { animation: kuhle-kommt .34s var(--leiste-kurve) both; }
    html.leiste-kommt.leiste-neu .mobilebar::before { animation: kuhle-oeffnet .3s var(--leiste-kurve) both; }
    html.leiste-kommt .mobilebar > a:has(> .mobilebar__pille) .mobilebar__glyph { animation: zeichen-steigt .34s var(--leiste-kurve) both; }
}
@keyframes kuhle-kommt { from { --kuhle-i: var(--pille-von, 0); } }
@keyframes kuhle-oeffnet { from { --kuhle-r: 0px; } }
@keyframes zeichen-steigt { from { translate: 0 0; color: var(--leiste-still); } }
@keyframes leiste-klingeln {
    0%, 100% { transform: none; }
    30% { transform: rotate(-5deg) scale(1.06); }
    65% { transform: rotate(3deg) scale(1.03); }
}
@keyframes leiste-heben {
    0%, 100% { transform: none; }
    40% { transform: translateY(-2px) scale(1.06); }
}
@keyframes leiste-steigen {
    0%, 100% { transform: none; }
    40% { transform: translateY(-2px) rotate(-5deg); }
}
/* ⛔ BEI OFFENEM MENÜ VERSCHWINDET DIE LEISTE, UND OHNE DIESE ZEILE LAG SIE DARÜBER.
      `.nav` ist zwar `position: fixed`, steht aber IM `.site-header`, und der ist
      `position: sticky; z-index: 40` — also ein eigener Stapelkontext. Das Panel kann auf
      Wurzelebene nie über 40 hinaus; `.mobilebar` liegt bei 45 direkt am `body`. Gemessen auf
      390 × 844 mit offenem Menü: das Element am unteren Bildrand gehört zur Leiste, nicht zum
      Panel — die untersten 62 px des Menüs, wo «Anrufen» und «WhatsApp» stehen, waren verdeckt.

      Die Leiste auszublenden ist die richtige Hälfte des Tauschs: sie bietet dieselben zwei
      Wege an, die das offene Menü ohnehin zeigt. Ein zweiter anklickbarer Navigationsweg hinter
      einem Menü, das sich als Überlagerung ausgibt, ist ausserdem genau das, was ein
      `aria-modal`-Panel nicht haben darf. */
body:has(.nav.is-open) .mobilebar { display: none; }
/* Die Zahl sitzt oben rechts am Symbol; leer (und `hidden`), solange der Korb leer ist, damit
   das Symbol nicht «0» trägt. Der Ring in der Farbe der Leiste löst sie vom Zeichen darunter. */
.mobilebar__badge {
    position: absolute; top: -3px; left: 50%; transform: translateX(5px);
    min-width: 17px; height: 17px; padding: 0 4px; box-sizing: border-box;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--leiste-akzent); color: var(--leiste-auf-akzent);
    box-shadow: 0 0 0 2px var(--leiste-flaeche);
    font-size: .64rem; font-weight: 700; line-height: 1;
    border-radius: 999px; font-variant-numeric: tabular-nums;
}
.mobilebar__badge[hidden] { display: none; }
@media (max-width: 860px) { .mobilebar { display: flex; } body { padding-bottom: var(--leiste-reserve); } }
@media (max-width: 860px) {
    /* AUF DEM TELEFON IST DER KORB DAS SYMBOL IN DER DAUMENLEISTE, nicht eine zweite feste Leiste
       darüber. Die volle `#cartbar` (Summe + «Bestellung ansehen») bleibt dem Breitbild vorbehalten,
       wo es keine Daumenleiste gibt; hier öffnet das Symbol dieselbe Schublade mit Summe und
       Absenden. So stapeln sich nie zwei feste Leisten (der Grund, aus dem `~ .mobilebar` die
       Leiste sonst versteckt), und der Korb ist trotzdem immer sichtbar. Nur die Speisekarte
       (`.page-menu`); `/bestellen` behält seine `#ladenbar` unberührt. `#cartbar` (id) schlägt die
       spätere `~ .mobilebar`-Regel in der Spezifität, unabhängig von der Reihenfolge. */
    .page-menu #cartbar { display: none; }
    .page-menu #cartbar ~ .mobilebar { display: flex; }
}

/* ---------- Speisekarte (menu page) ---------- */
/* Menu hero: a compact photo band so the table-QR landing feels premium at once.

   THE PHOTOGRAPH COMES FROM THE RESTAURANT, NOT FROM THIS FILE. It used to be
   `url("/assets/img/hero.webp")` — a path with no file behind it anywhere in this repository, so
   every Speisekarte load spent a request on a 404 before falling back to the dark plate; and had
   the file existed, twenty restaurants would have opened their card with the same photograph.
   `--hero-photo` is set once on <body> by the layout, from the restaurant's own upload. `none`
   is a valid background-image, so a restaurant with no photo requests nothing at all and still
   gets the finished dark plate — which is the state both demo restaurants are in today. */
.menu-hero {
    position: relative;
    display: flex; flex-direction: column; justify-content: flex-end;
    /* SCHLANKER als zuvor (war 210–320px). Der Kopf ist ein Bild-Band, kein halber Bildschirm —
       der Text darunter (Abholband, Filter) soll ohne langes Scrollen sichtbar sein. */
    min-height: clamp(168px, 24vh, 240px);
    color: var(--on-dark);
    padding: 0 0 clamp(16px, 3vw, 26px);
    overflow: hidden; isolation: isolate;
    /* Rückfall ohne Diashow: Hausfoto (`--hero-photo` vom `<body>`), sonst die dunkle Platte. */
    background: var(--hero-photo, none) center 42% / cover no-repeat, var(--dark-plate);
}
/* DIE DIASHOW liegt UNTER dem Schleier und dem Text. Die Bilder blenden über `.is-active`
   ineinander; ohne Skript trägt das erste `.is-active` und steht still — kein leerer Kopf. */
.menuhero__stage { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.menuhero__slide {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; opacity: 0; transition: opacity 1.1s ease;
}
.menuhero__slide.is-active { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .menuhero__slide { transition: none; } }
/* DER SCHLEIER ALS EIGENE SCHICHT (z-index 1), damit die Schrift auf JEDEM Bild lesbar bleibt.
   Früher lag er im Hintergrund der Box; ein Diashow-Bild darüber hätte ihn verdeckt. */
.menu-hero::after {
    content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background:
        linear-gradient(0deg, var(--scrim-86) 0%, var(--scrim-42) 48%, var(--scrim-08) 100%),
        linear-gradient(90deg, var(--scrim-64) 0%, var(--scrim-08) 56%, transparent 100%);
}
.menu-hero .hero__inner { position: relative; z-index: 2; }
.menu-hero .hero__title { color: var(--on-dark); text-shadow: 0 2px 22px rgba(0, 0, 0, .38); margin-bottom: 0; }
.menu-hero .eyebrow, .menu-hero .accent-script { color: var(--on-dark-accent); text-shadow: 0 1px 9px rgba(0, 0, 0, .4); }
/* Die eigenen Worte der Küche über der Karte — schlank und ruhig statt des grossen Absatzes, der
   früher im Kopf stand. Zentriert und schmal, damit sie als Auftakt liest, nicht als Fliesstext. */
.menu-lede {
    margin: clamp(16px, 3vw, 24px) auto 0; max-width: 46em; text-align: center;
    color: var(--muted); font-size: var(--fs-1); line-height: 1.55;
}
/* TAG/NACHT OBEN RECHTS IM KOPF, über dem Foto statt in der Filterleiste (die dadurch auf dem
   Telefon eine Zeile kürzer wird). Auf dem dunklen Bild braucht er eigene Farben: ein ruhiger,
   halbtransparenter Kreis mit hellem Rand und hellem Symbol. Über `.menu-hero .theme-toggle`,
   ohne eine zweite Klasse am Knopf — dessen `class`/`id` hält MenuTest fest. */
.menu-hero .theme-toggle {
    position: absolute; top: clamp(11px, 2.4vw, 18px); right: clamp(11px, 3vw, 20px); z-index: 2;
    width: 38px; height: 38px;
    background: color-mix(in oklab, #000 32%, transparent);
    border-color: color-mix(in oklab, #fff 32%, transparent);
    color: var(--on-dark);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.menu-hero .theme-toggle:hover { border-color: var(--on-dark); color: var(--on-dark); }
.menu-hero .theme-toggle svg { width: 17px; height: 17px; }
/* `.menu-dl`, `.menu-dl-foot` and `.menu-hero__dl` — a "Karte als PDF" button — are deleted.
   No template ever rendered them, and they should not be added: a PDF is a frozen copy of the
   one page on this platform where being out of date is a legal matter rather than an
   embarrassment, and it cannot be filtered by diet or by the allergens a guest is avoiding.
   The HTML card does both, and it is the one that is current. */

/* Elegant placeholder tile for dishes without a photo (serif monogram on warm stone). */
.ph-tile {
    display: flex; align-items: center; justify-content: center;
    background: var(--line-soft);
}
.ph-tile__mono { font-family: var(--serif); font-weight: 600; line-height: 1; color: color-mix(in srgb, var(--wine) 62%, var(--gold)); }
.mdish__photo.ph-tile .ph-tile__mono { font-size: 2.4rem; }
.dishcard__photo.ph-tile .ph-tile__mono { font-size: 3.2rem; }
/* Category drink icon inside the placeholder tile (drinks without a photo). */
.ph-tile__ic { width: 48%; height: 48%; color: color-mix(in srgb, var(--wine) 50%, var(--gold)); }
/*
 * DAS ZEICHEN EINES GERICHTS OHNE FOTO (D-229, partials/platzhalter): das goldene Zeichen auf
 * dunkler Fläche, darunter der Name des Hauses. Dunkel, weil die Zeichen golden sind und auf Weiss
 * ihre Lichter verlieren — und weil die Fläche zwischen Fotos stehen soll wie ein Foto, nicht wie
 * ein Loch. Die Grösse setzt der Aufrufer (`.mdish__photo`, `.beliebtkarte__foto`, der Teller …).
 *
 * ⚠️ DIE SCHRIFT MISST SICH AN DER FLÄCHE (`cqi`), und deshalb steht die Masseinheit nur an den
 *    KINDERN: ein Element ist nie sein eigener Container, `cqi` an `.platzhalter` selbst läse die
 *    Breite irgendeines äusseren Containers (auf der Speisekarte: die ganze Karte).
 * ⚠️ UNTER 64 PX KEIN NAME: im 44-px-Bildchen des Gastkontos wären es Pünktchen.
 * ⛔ KEINE VERSALIEN MIT SPERRUNG für den Namen (D-170): die Hausschrift, wie sie ist.
 */
.platzhalter {
    container-type: inline-size;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    overflow: hidden;
    background: #151413;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06);
    text-align: center;
}
.platzhalter__bild {
    display: block; flex: none;
    width: 62%; height: auto; max-height: 58%;
    object-fit: contain;
}
.platzhalter__name {
    max-width: 86%;
    margin-top: 5cqi;
    font-family: var(--serif); font-weight: 500;
    font-size: clamp(7px, 9.5cqi, 18px); line-height: 1.12;
    color: #f4c05a;
    overflow-wrap: anywhere; text-wrap: balance;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
/* Ein langer Name (über 16 Zeichen, partials/platzhalter) bekommt drei Zeilen und ein kleineres Zeichen:
   in der 96-px-Tafel stand sonst «Restaurant / Akropolis…», und der Betreiber will den Namen ganz. */
.platzhalter--lang .platzhalter__bild { width: 52%; max-height: 46%; }
.platzhalter--lang .platzhalter__name { font-size: clamp(7px, 8.4cqi, 17px); -webkit-line-clamp: 3; line-clamp: 3; }
@container (max-width: 63.9px) {
    .platzhalter__name { display: none; }
}
.dishcard__photo.platzhalter, .beliebtkarte__foto.platzhalter, .konto-fotos__bild.platzhalter, .konto-karte__foto.platzhalter { display: flex; }
/* On the menu page (table-QR target) the header scrolls away and ONLY a slim category
   bar stays sticky — so filters never eat the mobile screen. */
.page-menu .site-header { position: static; }
/* ---------- outer band + contained control card (editorial-menu-card) ---------- */
/* Schlanker: das Werkzeugband hält Suche, Diät und Nacht — es soll eine Leiste sein, kein Feld. */
.menu-tools { border-bottom: 1px solid var(--line-soft); padding: 11px 0 10px; }

.m-card {
    position: relative;
    display: grid;
    gap: 10px;
    background: var(--surface);
    border: 1px solid var(--line-soft);
    border-radius: var(--r);
    padding: 11px 14px 10px;
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
/* signature: hairline enamel-gold rule across the top edge */
.m-card::before {
    content: "";
    position: absolute; inset: 0 0 auto 0; height: 2px;
    background: linear-gradient(90deg,
        transparent 0,
        color-mix(in srgb, var(--gold) 70%, transparent) 18%,
        color-mix(in srgb, var(--gold) 70%, transparent) 82%,
        transparent 100%);
}
/* ---------- compact toolbar: search-icon · diet · theme-icon ---------- */
.m-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
/* shared round icon button (search + theme)
 *
 * ⚠️ 44 px UND NICHT MEHR 42 — die zwei Pixel sind genau der Satz, der im Bestellweg bei
 *    `.mdish__add` steht: «and that is not a rounding of 42». Zwei Knöpfe, die auf DEMSELBEN
 *    Bildschirm sitzen (Suche und Tag/Nacht in der Leiste der Speisekarte, der Warenkorb-Knopf
 *    im Gericht darunter), hatten zwei verschiedene Trefferflächen. Jetzt eine.
 *
 * ⚠️ DAS ZEICHEN BLEIBT BEI 19 px (`.iconbtn2 svg` weiter unten). Der Ring wird grösser, die
 *    Lupe nicht. */
.iconbtn2 { flex: 0 0 auto; min-width: 44px; min-height: 44px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 1px solid var(--line); background: var(--bg); color: var(--muted); cursor: pointer; transition: color var(--t), border-color var(--t); }
.iconbtn2:hover { border-color: var(--accent); color: var(--accent-ink); }
.iconbtn2:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* `flex: 0 0 auto` — `.iconbtn2` is an inline-flex box, so its SVG is a flex item with no
   intrinsic width and shrinks to nothing under pressure, leaving a bare ring. Same failure
   already documented on `.nav__social a svg` and `.wa-fab__btn svg`. */
.iconbtn2 svg { width: 19px; height: 19px; flex: 0 0 auto; }
/* The magnifier button. It shares `.iconbtn2`'s shape; what is its own is that it must not be
   squeezed when `.searchbox.is-open` hands the whole row to the input beside it. */
.searchbox__btn { flex: 0 0 auto; }
/* search: a magnifier that expands to a field on click */
.searchbox { flex: 0 0 auto; display: flex; align-items: center; min-width: 0; }
.searchbox__input { width: 0; min-width: 0; padding: 0; border: 1px solid transparent; border-radius: var(--r-sm); background: var(--bg); color: var(--text); font: inherit; font-size: .95rem; opacity: 0; transition: width var(--t), opacity .2s, padding var(--t), margin var(--t); }
.searchbox__input::placeholder { color: var(--muted); }
.searchbox.is-open { flex: 1 1 100%; order: -1; }
.searchbox.is-open .searchbox__input { flex: 1 1 auto; width: auto; opacity: 1; margin-left: 8px; padding: 11px 14px; border-color: var(--line); }
.searchbox.is-open .searchbox__input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent); }
/* theme toggle — icon only (sun/moon), pushed to the right edge of the bar */
.theme-toggle { margin-left: auto; }
.theme-toggle__ic { width: 19px; height: 19px; }
.theme-toggle__sun { display: none; }
:root[data-theme="dark"] .theme-toggle__moon { display: none; }
:root[data-theme="dark"] .theme-toggle__sun { display: inline; }

/* ---------- diet — quiet segmented control ---------- */
.m-diet { flex: 0 0 auto; }
.m-diet {
    display: inline-flex; gap: 4px; padding: 4px;
    background: color-mix(in srgb, var(--bg) 70%, var(--surface));
    border: 1px solid var(--line-soft); border-radius: 999px;
}
.m-diet .chip {
    font: inherit; font-family: var(--sans); font-size: .84rem;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 7px;
    border: 1px solid transparent; background: transparent; color: var(--muted);
    padding: 8px 16px; border-radius: 999px; white-space: nowrap;
    transition: color var(--t), background var(--t), border-color var(--t), box-shadow var(--t);
}
.m-diet .chip:hover { color: var(--text); }
.m-diet .chip.is-active {
    background: var(--surface); border-color: var(--line-soft);
    color: var(--accent-ink); font-weight: 600; box-shadow: var(--shadow-sm);
}

.m-diet .chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- (C) allergen ledger — collapsed by default ---------- */
.m-allergen { border-top: 1px solid var(--line-soft); padding-top: 11px; }
.m-allergen__toggle {
    list-style: none; cursor: pointer;
    display: flex; align-items: center; gap: 10px;
    font-family: var(--sans); font-weight: 600; font-size: .9rem; color: var(--link);
    padding: 5px 2px; border-radius: var(--r-sm);
}
.m-allergen__toggle::-webkit-details-marker { display: none; }
.m-allergen__toggle::marker { content: ""; }
.m-allergen__toggle:hover { color: var(--accent-ink); }
.m-allergen__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.m-allergen__mark { width: 17px; height: 17px; flex: 0 0 auto; color: var(--gold); }
.m-allergen__text { flex: 1 1 auto; }
.m-allergen__chev { width: 16px; height: 16px; flex: 0 0 auto; color: var(--muted); transition: transform var(--t); }
.m-allergen[open] .m-allergen__chev { transform: rotate(180deg); }
.m-allergen[open] .m-allergen__toggle { color: var(--accent-ink); }
.m-allergen__body { padding-top: 8px; }
/* Colour comes from the global `.muted` now; this keeps only what is particular to the ledger. */
.m-allergen__body .muted { margin: 0; font-size: .82rem; line-height: 1.5; max-width: var(--wrap-narrow); }

.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
/* ⛔ `min-height: 44px` — DIESE CHIPS GEHÖREN DEM GAST MIT DER ALLERGIE.
 *
 *    Gemessen waren es rund 31 px hoch: 2 × 7 px Polster, eine Zeile in .82rem und zwei
 *    Haarlinien. Das ist die kleinste Trefferfläche, die diese Seite einem Gast hinstellt —
 *    und sie liegt ausgerechnet an dem Bedienelement, mit dem jemand «Nüsse» aus der Karte
 *    nimmt, bevor er bestellt. Ein Fehlgriff hier ist nicht «Menü statt Konto», sondern eine
 *    Karte, die die falschen Gerichte zeigt.
 *
 * ⚠️ ÜBER DIE HÖHE, NICHT ÜBER DIE SCHRIFT. `min-height` lässt die Pille wachsen, ohne dass
 *    ein Zeichen grösser wird: dieselbe Schrift, dasselbe Kästchen (15 px), dieselbe Breite —
 *    die kommt vom Etikett («Hc · Walnüsse (Schalenfrüchte)») und war nie das Problem. Die
 *    Polsterwerte bleiben stehen, weil sie den Innenabstand LINKS und RECHTS setzen; oben und
 *    unten verteilt `align-items: center` den Rest. */
.ex-chip {
    display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
    min-height: 44px;
    font-family: var(--sans); font-size: .82rem; color: var(--muted);
    border: 1px solid var(--line); background: var(--bg);
    padding: 7px 12px 7px 10px; border-radius: 999px;
    transition: color var(--t), border-color var(--t), background var(--t);
}
.ex-chip:hover { color: var(--text); border-color: var(--accent); }
/* 20 px statt 15: das Kästchen selbst ist das Ziel, das ein Daumen trifft — gemessen als kleinstes
   Bedienelement der Karte (15×15) am 11.09.2026. */
.ex-chip .m-ex { width: 20px; height: 20px; margin: 0; flex: 0 0 auto; cursor: pointer; accent-color: var(--accent); }
/* `min-width: 0` is the overflow guard. The longest label on this control is "Hc · Walnüsse
   (Schalenfrüchte)"; a flex item's default `min-width: auto` refuses to shrink below its
   content, so at the 320px floor the chip pushed the row wider than the viewport and the whole
   page gained a horizontal scrollbar — from a checkbox label. */
.ex-chip__label { min-width: 0; }
.ex-chip:has(.m-ex:checked) {
    color: var(--accent-ink); font-weight: 600;
    border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, var(--surface));
}
.ex-chip:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Cereals and nuts have to be named individually (Aa Weizen, Hc Walnüsse), so those
   letters sit under their group name with an "alle" chip in front of them. */
.ex-grp { margin-top: 14px; }
/* ⛔ `--gold-ink` UND NICHT `--c-brass`: DAS HIER IST TEXT, UND ES IST DER DRITTE FUNDORT
   DESSELBEN FEHLERS.

   `tokens.css` schreibt die Regel aus — «--gold is 3.33:1 on the paper — correct for a rule, an
   underline or a border, where 3:1 is the bar, and NOT correct for text.» `.accent-script` und
   `.legend__grid h4` wurden umgestellt; diese Überschrift griff weiterhin auf die ROHE
   Markenfarbe zu, an `--gold` vorbei.

   Gemessen im Nachtmodus, wie die Speisekarte sich öffnet: #9A7B4F auf #1D2227 = 4,06:1,
   verlangt sind 4,5:1. Und es steht ausgerechnet über den Familienüberschriften des
   Allergenfilters — dem Bedienelement, das ein Gast mit einer Allergie benutzt. */
.ex-grp__hd { display: block; font-size: .8125rem; color: var(--gold-ink); }
.ex-grp .chips { margin-top: 7px; }

/* ---------- (D) sticky category rail — engraved index + pinned seam ---------- */
.catbar {
    position: sticky; top: 0; z-index: 35;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    -webkit-backdrop-filter: saturate(1.35) blur(10px);
            backdrop-filter: saturate(1.35) blur(10px);
    border-bottom: 1px solid color-mix(in srgb, var(--gold) 28%, var(--line-soft));
}
.catbar__inner { display: flex; align-items: stretch; gap: 12px; padding-top: 0; padding-bottom: 0; }
/* pinned, non-scrolling accent seam (survives after the toolbar scrolls away) */
.catbar__seam {
    flex: 0 0 auto; align-self: center;
    font-family: var(--serif); font-size: 1rem; letter-spacing: .02em;
    color: var(--gold);
    padding-right: 12px; border-right: 1px solid color-mix(in srgb, var(--gold) 26%, var(--line-soft));
}
.catnav {
    flex: 1 1 auto; min-width: 0;               /* correct horizontal-overflow guard */
    display: flex; gap: 2px; margin: 0; padding: 0;
    overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    /* pure-CSS "more to scroll" edge-fade hint */
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 16px), transparent 100%);
}
.catnav::-webkit-scrollbar { height: 0; }

a.chip--cat {
    position: relative; flex: 0 0 auto;
    padding: 13px 15px 12px; text-decoration: none; white-space: nowrap;
    font-family: var(--serif); font-size: .82rem; font-weight: 600; color: var(--muted);
    transition: color var(--t);
}
/* cloisonné cell-wall hairline between labels */
a.chip--cat + a.chip--cat::before {
    content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
    width: 1px; height: 16px; background: color-mix(in srgb, var(--gold) 40%, transparent);
}
a.chip--cat:hover { color: var(--text); }
a.chip--cat.is-active { color: var(--accent-ink); }
/* the one bold move: a thin gold rule that draws in under the active tab */
a.chip--cat::after {
    content: ""; position: absolute; left: 15px; right: 15px; bottom: 6px; height: 2px;
    background: var(--gold); border-radius: 2px;
    transform: scaleX(0); transform-origin: left center; transition: transform var(--t);
}
a.chip--cat.is-active::after { transform: scaleX(1); }
a.chip--cat:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; border-radius: var(--r-sm); }

/* tapped category headings clear the sticky bar (matches the bar height) */
[id^="cat-"] { scroll-margin-top: 66px; }

/* Desktop: show ALL categories at once (wrap instead of horizontal scroll) so none stay
   hidden off-screen; the phone keeps the compact single scrolling rail. */
@media (min-width: 861px) {
    .catbar__seam { display: none; }   /* reclaim width so all category chips fit in two rows */
    .catnav { flex-wrap: wrap; overflow-x: visible; -webkit-mask-image: none; mask-image: none; gap: 3px 4px; padding: 3px 0; }
    a.chip--cat + a.chip--cat::before { display: none; }
    a.chip--cat { padding: 6px 11px; font-size: .74rem; }
    .mcat, [id^="cat-"] { scroll-margin-top: 92px; }   /* clear the wrapped sticky category bar */
}

/* mobile — flawless down to 320px */
@media (max-width: 560px) {
    .menu-tools { padding: 8px 0 8px; }
    .m-card { padding: 9px 12px; gap: 8px; border-radius: var(--r-sm); }
    /* SCHLANKER: Tag/Nacht ist in den Kopf gewandert, also trägt die erste Zeile nur noch Suche
       UND Diät nebeneinander (nicht mehr die Diät auf einer eigenen, zentrierten Zeile). Passt
       die Diät nicht daneben, bricht `.m-bar` (flex-wrap) sie um — der Allergen-Ausschluss steht
       darunter. Zwei knappe Zeilen statt drei hoher. */
    .m-diet { flex: 0 1 auto; order: 0; justify-content: flex-start; }
    .m-diet .chip { padding: 8px 12px; }
    .catbar__inner { gap: 10px; }
}
@media (max-width: 360px) {
    .m-diet .chip { padding: 11px 10px; font-size: .8rem; }
    .ex-chip { font-size: .8rem; }
    .catbar__seam { display: none; }   /* reclaim horizontal rail room at the 320px floor */
}
@media (prefers-reduced-motion: reduce) {
    .m-search, .m-field__icon, .m-diet .chip, .m-allergen__chev, .m-allergen__toggle,
    .ex-chip, a.chip--cat, a.chip--cat::after { transition: none; }
}

.menu-list { padding: 24px 0 8px; }
.mcat { padding: 14px 0; scroll-margin-top: 66px; }
.mcat__title { font-size: clamp(1.5rem, 3vw, 2rem); padding-bottom: 8px; position: relative; margin-bottom: 6px; }
/* Kleiner als die Überschrift, damit das Bild die Rubrik begleitet statt sie anzuführen. */
.mcat__icon { font-size: .8em; margin-right: .35em; vertical-align: baseline; }
.mcat__title::after { content: ""; position: absolute; left: 0; bottom: 0; width: 44px; height: 3px; background: var(--gold); border-radius: 2px; }
/* Multi-column dish grid: the long card reads compact & organised, like a printed menu.
   1 column on phones, 2 on tablets, up to 3 on desktop (auto-fill). */
.mcat__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); column-gap: clamp(20px, 3.4vw, 46px); }
@media (max-width: 560px) { .mcat__grid { grid-template-columns: 1fr; } }
.mdish {
    display: flex; gap: 16px; align-items: flex-start; padding: 18px 2px;
    border-bottom: 1px solid var(--line-soft);
    /* THE SAME GUARD `.mdish__body` CARRIES, one level up — and the level that was missing.
       A grid item's default `min-width: auto` refuses to shrink below its content, so a card
       whose dish name is long ("Cantine San Marzano Primitivo Sessantanni", straight out of a
       real wine list) measured 372px inside a 316px track and pushed the whole document 34px
       sideways on a 375px phone. On the one page a guest opens at the table. */
    min-width: 0;
}
/* German compounds and Italian wine names both do this; neither is a mistake to design around
   with `hidden`, which would cut the name in half rather than wrap it. */
.mdish__name, .mdish__desc { overflow-wrap: anywhere; }
.mdish__photo { width: 84px; height: 84px; object-fit: cover; border-radius: 13px; flex: 0 0 auto; box-shadow: var(--shadow-sm); }
.mdish__body { flex: 1 1 auto; min-width: 0; }
.dishcard__photo { width: 100%; height: 168px; object-fit: cover; border-radius: 12px; margin-bottom: 14px; display: block; }
/* THE SIZING CLASS AND THE TILE ARE ON THE SAME ELEMENT, and the sizing class was winning.
   dishthumb.blade.php writes `class="dishcard__photo ph-tile"`; both selectors are one class
   deep, so the later `display: block` above beat `.ph-tile { display: flex }` and the tile
   stopped centring anything. Measured at 375px on the front page ("Empfehlungen des Hauses",
   four cards with no photograph — day one for every restaurant here): tile 289×168, computed
   display `block`, the monogram at offset 0 / −6 where centred is 127 / 58. The letter hung
   6px ABOVE the top edge of its own tile, with 168px of empty stone underneath it.
   `.mdish__photo` never showed it: that class declares no display, so flex survived there and
   the Speisekarte looked correct while the homepage did not. Compound selector rather than
   `!important`, and it belongs next to the rule it answers. */
.dishcard__photo.ph-tile { display: flex; }
.mdish.is-soldout { opacity: .58; }
/* name · · · · price on one baseline; price is flush-right on every card so the whole
   price column lines up cleanly, like a printed menu. */
.mdish__head { display: flex; align-items: baseline; gap: 6px; }
/* `hyphens: manual` HOLT DIE SILBENTRENNUNG AUS DEM NAMEN. Ererbt von `h1…h4 { hyphens: auto }`
   brach ein Name in einer schmalen Spalte silbenweise («Gebra-tene Au-bergi-nen»); der Name
   soll an Wortgrenzen umbrechen, nicht mitten im Wort. `overflow-wrap` (eine Zeile höher) bleibt
   als Überlauf-Sicherung für das eine Wort, das breiter ist als seine Spalte. */
.mdish__name { font-size: 1.24rem; font-family: var(--serif); margin: 0; hyphens: manual; }
.mdish__lead { flex: 1 1 auto; min-width: 16px; height: 0; border-bottom: 2px dotted var(--line); position: relative; top: -.26em; opacity: .7; }
.mdish__price { flex: 0 0 auto; font-family: var(--serif); font-weight: 600; color: var(--accent-ink); font-size: 1.16rem; text-align: right; white-space: nowrap; }
.mdish__var { display: block; font-size: .92rem; line-height: 1.45; }   /* each drink size on its own line so long variant prices never overflow the cell */
.soldout { font-family: var(--sans); font-size: .8125rem; background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent-ink); padding: 2px 8px; border-radius: 999px; margin-left: 8px; vertical-align: middle; }
.mdish__desc { color: var(--muted); font-size: .96rem; margin: 6px 0 0; line-height: 1.55; }
.mdish__tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 9px; }
/* `inline-block`, UND DAS WAR EIN GEMESSENER SCHÖNHEITSFEHLER MIT EINEM EINZIGEN WORT ALS
   URSACHE. Diese Regel wurde für ein `<span>` in der Zeile eines Gerichts geschrieben — dort
   umschliesst sie die Buchstaben. Vier Vorlagen schreiben sie aber als `<p>` (die Karte auf der
   Startseite, das Tagesangebot, die SEO-Seite): ein Blockelement, also ein gerahmter Kasten
   über die volle Kartenbreite mit zwei Buchstaben darin, der auf jedem Screenshot wie ein
   leeres Eingabefeld aussieht. Auf der Startseite steht er unter jedem Preis.
   Die `<span>`-Verwendungen sind bereits inline; für sie ändert sich nichts. */
.codes { display: inline-block; font-size: .72rem; color: var(--muted); border: 1px solid var(--line); padding: 2px 7px; border-radius: 6px; }
.codes--add { font-style: italic; }
@media (max-width: 560px) {
    /* ⛔ DAS FOTO IST DAS, WAS EIN GERICHT VERKAUFT, und es war das schwächste Element der
       Zeile. 92 statt 74 — bezahlt aus dem Abstand daneben (13 → 12) und aus dem Innenabstand
       (15 → 14), damit die Zeile davon NICHT höher wird. Nachgemessen: Medianhöhe 197px statt
       204px, und die längste Zeile fiel von 311px auf 245px. */
    .mdish__photo { width: 92px; height: 92px; }
    .mdish { gap: 12px; padding: 14px 2px; position: relative; }

    /* AUF DEM TELEFON GEHÖRT DEM NAMEN DIE ERSTE ZEILE. Zwischen Foto und Rand bleiben ~250px;
       Name, Führungspunkte, Preis UND der «+»-Knopf nebeneinander pressten den Namen wieder in
       eine Restspalte. Der Name nimmt jetzt die ganze Breite (`flex-basis: 100%` erzwingt den
       Umbruch), die Führungspunkte entfallen (bei vollbreitem Namen verbinden sie nichts). */
    .mdish__head { flex-wrap: wrap; align-items: center; row-gap: 2px; }
    .mdish__name { flex: 1 1 100%; }
    .mdish__lead { display: none; }

    /* ⛔ DER PREIS STEHT LINKS UNTER DEM NAMEN, NICHT MEHR RECHTS AM RAND.
       Hier stand `margin-left: auto`, und die Begründung dafür war die gedruckte Karte, in der
       eine Preisspalte fluchtet. Auf dem Telefon fluchtet aber nichts: es gibt nur EINE Spalte,
       der Name steht links, und der Preis sprang über die halbe Zeile ans andere Ende —
       gemessen 190px vom Namensanfang entfernt, direkt neben den «+»-Knopf, der damals oben
       rechts sass. Er las sich dadurch wie dessen Beschriftung.
       Unter dem Namen gehört er zu dem, was er kostet. */
    .mdish__price { margin-left: 0; text-align: left; }

    /* ⛔ DER KNOPF WIRD AUS DEM FLUSS GENOMMEN, UND DAS IST DER TEIL, DEN ICH ERST GEMESSEN
       HABE, NACHDEM ICH IHN FALSCH GEMACHT HATTE.
       Erster Entwurf: Knopf in den Kopf, Kopf umbrechen lassen. Der Name gewann eine Zeile
       (drei → zwei), aber der Knopf öffnete mit seinen 44px eine EIGENE Reihe. Nachher
       gemessen: die Zeile wuchs von 202px auf 214px, es passten 3,9 statt 4,1 Gerichte auf
       einen Schirm. Die Änderung war eine Verschlechterung, und die Zahl hat es gesagt, nicht
       das Auge. Absolut positioniert kostet er keine Höhe und sitzt unten rechts, auf Höhe der
       Abzeichen. `padding-right` auf den Abzeichen, damit sie nicht unter ihm durchlaufen. */
    .has-cart .mdish__add { position: absolute; right: 2px; bottom: 14px; margin: 0; }
    .mdish__tags { padding-right: 52px; }
}
/* Measured 1036px wide on the vegan page — a centred italic apology running the full width of
   `.wrap`, which is the one shape that makes a short sentence read as an error message. This
   is the state a restaurant is in on day one, on the homepage, the menu and the vegan page at
   once, so it earns a measure of its own. 46ch rather than 66: it is always a sentence or two,
   and centred text needs a shorter line than left-aligned text to keep its ragged edges calm. */
.m-empty { text-align: center; color: var(--muted); padding: 40px 0; font-style: italic; max-width: 46ch; margin-inline: auto; }

.legend { padding: 18px 0 40px; }
.legend details { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
.legend summary { cursor: pointer; padding: 14px 16px; font-weight: 600; }
.legend__grid { display: grid; grid-template-columns: 1fr; gap: 20px; padding: 4px 16px 18px; }
@media (min-width: 620px) { .legend__grid { grid-template-columns: 1fr 1fr; } }
/* ⛔ `--gold-ink` UND NICHT `--gold`: DIESE ZEILE IST TEXT.
   `tokens.css` schreibt es aus — «--gold is 3.33:1 on the paper — correct for a rule, an
   underline or a border, where 3:1 is the bar, and NOT correct for text. It was being used for
   both.» Gemessen auf `--surface`: #9A7B4F auf #FBF9F5 = 3,75:1, verlangt sind 4,5:1.
   `.accent-script` wurde damals umgestellt, diese Überschrift blieb stehen — und sie steht
   ausgerechnet über der Allergenlegende, also über dem Text, den ein Gast mit einer Allergie
   liest. Bei Nacht fiel es nicht auf: dort ist `--gold` helles Messing und besteht. */
.legend__grid h4 { font-size: .8rem; color: var(--gold-ink); margin-bottom: 8px; }
.legend__grid ul { list-style: none; margin: 0; padding: 0; font-size: .85rem; color: var(--muted); }
.legend__grid li { margin-bottom: 4px; }
.legend__grid b { color: var(--text); }
.legend__grp { color: var(--c-text); margin-bottom: 6px; }
.legend__grp > ul { margin-top: 3px; padding-left: 12px; border-left: 1px solid var(--c-line); }


/* ============================================================
   PHOTO PAGES — Galerie / Feiern-Catering / Home / Über uns
   (owner-supplied photography; classes namespaced .gal-/.cater-/.home-/.abt-)
   ============================================================ */

/* === Über uns — photo figures (prefix: .abt-) === */
.abt-figure {
    margin: 22px 0 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.abt-figure__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    object-position: center;
    border-radius: var(--r);
    border: 1px solid var(--line-soft);
    box-shadow: var(--shadow);
    background: var(--surface);
}
.abt-figure__cap {
    font-family: var(--serif);
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--muted);
}
.abt-figure__cap .accent-script {
    color: var(--gold-ink);
    font-style: normal;
}
@media (max-width: 760px) {
    .abt-figure {
        margin-top: 18px;
    }
    .abt-figure__img {
        aspect-ratio: 4 / 3;
    }
}

/* Lead photo under a text hero (Vegan, Kontakt, ...). */
.leadphoto { padding: clamp(20px, 4vw, 44px) 0 0; }
.leadphoto figure { margin: 0; }
.leadphoto__img { width: 100%; height: auto; display: block; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r); border: 1px solid var(--line-soft); box-shadow: var(--shadow); }
.leadphoto figcaption { margin-top: 11px; font-family: var(--serif); font-size: .92rem; color: var(--muted); }
.leadphoto figcaption .accent-script { color: var(--gold-ink); }
@media (max-width: 560px) { .leadphoto__img { aspect-ratio: 4 / 3; } }

/* `.brandsig` — the logo on a cream plate, as a section of its own — is deleted. It never had
   markup, and the header already carries the wordmark on every page; a second, larger copy of
   it mid-page is a band that says nothing a guest did not already know. */

/* ---- Feiern & Catering: photographic hero + gallery (.cater-) ---- */

/* Photographic hero band */
.cater-hero{
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.cater-hero__img{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 60%;
  z-index: 0;
}
/* THE SCRIM IS A CONTRAST GUARANTEE, NOT A MOOD. Its old shape was .42 at the top easing to
   .30 at 40% — lightest exactly where the H1 sits — and the H1 is pinned to #fff below. On a
   restaurant with no photograph at all, `.cater-hero` rendered with the paper background
   showing through and the title measured 1.14:1 against it in a browser. White on cream. The
   heading of the page with the highest basket value on the site was invisible.

   Two fixes, and the template carries the important one: `.cater-hero` is now only rendered
   when there IS a photograph, so the pinned white can never land on paper. This gradient is the
   second: its floor is .64, which is the alpha at which white still clears 4.5:1 against the
   worst case a guest can upload — a photograph that is pure white. Blended, .64 over #14100C
   gives #686866; white on that measures 5.5:1. Every darker photograph only improves it, so
   the guarantee does not depend on anybody's taste in pictures. */
.cater-hero__scrim{
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Über dem Inhalt und trotzdem stumm — siehe `.resband__schleier`. */
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(20,16,12,.68) 0%, rgba(20,16,12,.64) 45%, rgba(20,16,12,.82) 100%),
    linear-gradient(90deg, rgba(20,16,12,.34) 0%, rgba(20,16,12,0) 70%);
}
.cater-hero__inner{
  position: relative;
  z-index: 2;
}
/* Text stays legible over the photo (light, theme-independent) */
.cater-hero .eyebrow{ color: rgba(255,255,255,.86); }
.cater-hero .hero__title{ color: #fff; }
.cater-hero .hero__intro{ color: rgba(255,255,255,.90); }
.cater-hero .accent-script{ color: var(--gold); }
/* `.cater-hero__accent` is deleted. It was a `z-index` and a 10%-white colour with no position,
   no size and no font — the residue of a watermark whose other half never got written — applied
   to the accent word, which then rendered at 10% opacity on top of the scrim and was
   indistinguishable from nothing. The accent word now uses `.eyebrow` + `.accent-script` like
   it does on every other hero, where it is legible and where one rule governs all of them. */
/* Ghost button needs light treatment over the dark scrim */
.cater-hero .btn--ghost{
  color: #fff;
  border-color: rgba(255,255,255,.55);
  background: transparent;
}
.cater-hero .btn--ghost:hover{
  border-color: #fff;
  background: rgba(255,255,255,.10);
}

/* Celebration gallery */
.cater-gallery{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-flow: dense;
  gap: 14px;
}
.cater-shot{
  position: relative;
  margin: 0;
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--line-soft);
  background: var(--surface);
}
.cater-shot img{
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center;
}
.cater-shot--wide{ grid-column: span 2; }
.cater-shot--wide img{ aspect-ratio: 16 / 9; }
.cater-shot__cap{
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 34px 16px 14px;
  color: #fff;
  font-family: var(--serif);
  font-size: .98rem;
  line-height: 1.3;
  background: linear-gradient(180deg, rgba(20,12,10,0) 0%, rgba(20,12,10,.72) 78%, rgba(20,12,10,.82) 100%);
}
.cater-shot__eyebrow{
  display: block;
  margin-bottom: 3px;
  font-family: var(--sans);
  font-size: .8125rem;
  color: var(--gold);
}

@media (max-width: 860px){
  .cater-gallery{ grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px){
  .cater-gallery{ grid-template-columns: 1fr; }
  .cater-shot--wide{ grid-column: auto; }
  .cater-shot--wide img{ aspect-ratio: 4 / 3; }
}

/* `.scenery-band` — a full-bleed landscape with a headline over it — is deleted, and it is the
   deletion most likely to be argued with, so: it is a 480px-tall band whose entire content is a
   photograph. On a restaurant with one good picture of the room, spending that picture on
   decoration leaves the pages that need it — Über uns, the catering page — with nothing, and on
   a restaurant with none it is 480px of dark plate carrying a sentence. Both demo restaurants
   are in the second state today. It also hardcoded /assets/img/scenery.webp, a file this
   repository does not contain. A photograph earns its place next to something it explains. */

/* ===== Home: Feiern & Catering teaser ===== */
/* height:auto is a fix, not a tweak. The width/height attributes on an <img> map to CSS width
   and height as PRESENTATIONAL HINTS; setting only width in CSS leaves the height hint alive,
   where it outranks aspect-ratio and stretches the photo into a tall strip beside a short text
   column. Anywhere an <img> carries both attributes and the stylesheet sets width, set height. */
.home-feiern__figure { margin: 0; display: grid; gap: 12px; }
.home-feiern__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    object-position: center;
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
}
/* A second room photo is optional. When one is supplied the pair goes side by side in portrait,
   which fills the column height without any single image having to stretch; with only one
   photo the layout must stay a single 4:3 frame, hence :has() rather than a flat two-column. */
.home-feiern__img--sm { display: none; }
@media (min-width: 900px) {
    .home-feiern__figure:has(.home-feiern__img--sm) { grid-template-columns: 1fr 1fr; }
    .home-feiern__figure:has(.home-feiern__img--sm) .home-feiern__img { aspect-ratio: 3 / 4; }
    .home-feiern__img--sm { display: block; }
}

/* `.section--photo` is deleted, and it is a TRAP rather than merely unused. It was driven by
   `style="--bg:url('…')"`, and `--bg` is this design system's semantic name for the page
   background — tokens.css line 40, read by `body` and by every component that paints a surface.
   Setting it to a photograph on a section makes that photograph the background of everything
   nested inside: a `.dishcard` in that band would have inherited `--bg` and painted the picture
   inside the card. Nothing rendered it, so nobody ever saw that happen. A component that
   overwrites a semantic token cannot be fixed by using it carefully. */

/* `.home-intern` — a "Mitarbeiter-Login" strip at the foot of the homepage — is deleted along
   with `.header-login`. A guest deciding where to eat has no use for a staff door, and putting
   one on the front page is the single clearest signal that a site was built by somebody
   thinking about the software rather than about the restaurant. The panel is one hostname away
   and the people who need it have it bookmarked. */

/* Galerie (.gal-) */
/* `padding: 0` because this is a <section> and the element rule at the top of this file gives
   every section 44–88px. The band's own breathing room is on `.gal-hero__inner`; with both in
   force the photograph grew to 700px before its first line of type. */
.gal-hero{position:relative;overflow:hidden;isolation:isolate;min-height:clamp(320px,52vh,520px);display:flex;align-items:flex-end;padding:0;}
.gal-hero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 62%;z-index:-2;}
/* Measured, not eyeballed. `.gal-hero` is `align-items: flex-end`, so its text block starts at
   about 54% of the band's height — where the old stops (.28 → .52 at 58% → .80) put roughly .50
   of scrim. Against the demo photograph the title measured 14.3:1, but against the worst
   photograph a restaurant can upload — a near-white one — it was 4.91:1 at the title, and below
   the line at the eyebrow above it, which is set at 85% white to start with. Floor raised to .62
   across the text zone, the same guarantee `.cater-hero__scrim` carries; the top stop stays low
   so the photograph still reads as a photograph rather than as a tinted panel. */
.gal-hero__scrim{position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(24,12,14,.40) 0%,rgba(24,12,14,.62) 52%,rgba(24,12,14,.86) 100%);}
.gal-hero__accent{position:absolute;right:-.04em;bottom:-.22em;z-index:-1;font-family:var(--serif);font-size:clamp(5rem,20vw,15rem);line-height:.8;color:rgba(255,255,255,.10);pointer-events:none;user-select:none;white-space:nowrap;}
.gal-hero__inner{padding-block:clamp(2rem,6vw,4rem);}
.gal-hero .eyebrow{color:rgba(255,255,255,.85);}
.gal-hero .eyebrow .accent-script{color:var(--gold);}
.gal-hero__title{color:#fff;margin:.15em 0 .35em;}
.gal-hero__intro{color:rgba(255,255,255,.92);max-width:56ch;}
.gal-feature{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(1.4rem,4vw,3rem);align-items:center;}
.gal-feature__media{margin:0;border-radius:var(--r);overflow:hidden;box-shadow:var(--shadow);border:1px solid var(--line-soft);background:var(--surface);}
/* `height: 100%` MEASURED 2px. Its parent is a grid item under `align-items: center`, so the
   figure's height is content-driven — and the content is a lazily loaded <img> with no width or
   height attributes, which occupies nothing until it arrives. 100% of nothing is nothing: the
   whole band laid out 175px tall, the photograph appeared, and everything below it jumped.
   `aspect-ratio` reserves the box from the first paint. Every other photo component in this
   file already declares one; this was the one that did not. */
.gal-feature__media img{display:block;width:100%;height:auto;aspect-ratio:4 / 3;object-fit:cover;transition:transform var(--t) ease;}
.gal-feature__media:hover img{transform:scale(1.03);}
.gal-feature__text p:first-child{margin-top:0;}
.gal-masonry{columns:3 260px;column-gap:18px;}
.gal-figure{break-inside:avoid;-webkit-column-break-inside:avoid;margin:0 0 18px;border-radius:var(--r);overflow:hidden;background:var(--surface);border:1px solid var(--line-soft);box-shadow:var(--shadow-sm);}
.gal-figure img{display:block;width:100%;height:auto;transition:transform var(--t) ease;}
.gal-figure:hover img{transform:scale(1.035);}
.gal-figure figcaption{padding:.65rem .85rem .8rem;font-family:var(--sans);font-size:.86rem;line-height:1.45;color:var(--muted);}
.gal-figure figcaption b{display:block;margin-bottom:.12rem;font-family:var(--serif);font-weight:600;font-size:1rem;color:var(--text);}
.gal-figure figcaption .accent-script{color:var(--gold-ink);}
/* `.gal-cta` (a centred call-to-action band) and `.gal-feature--reverse` (alternating photo
   sides) are deleted. Neither had markup: the gallery promotes exactly ONE photograph into a
   feature block, so there is no second one to alternate with, and its call to action lives
   inside that block where the eye already is rather than in a band of its own. Both come back
   the day a restaurant has enough photographs to justify a second feature — with markup. */
@media (max-width:760px){.gal-feature{grid-template-columns:1fr;}}
@media (max-width:560px){.gal-masonry{columns:1;}}
@media (prefers-reduced-motion:reduce){.gal-figure img,.gal-feature__media img{transition:none;}.gal-figure:hover img,.gal-feature__media:hover img{transform:none;}}

/* ============================================================================
   HERO
   ----------------------------------------------------------------------------
   ONE first screen. The type set, the tonality and the restaurant's own colour
   are injected per restaurant by /assets/brand.css; everything here is shared,
   and that is the product decision: the same design at every restaurant, so an
   improvement made once is an improvement everywhere.

   `.hero` USED TO BE DECLARED TWICE — once here and once two hundred lines up,
   with different padding and only the earlier one carrying `overflow:hidden`.
   The later block won, so the watermark's overflow guard was silently not in
   effect. Merged.
   ========================================================================== */

.hero { position: relative; overflow: hidden; padding: clamp(56px, 9vw, 112px) 0; }
.hero__inner { display: flex; flex-direction: column; align-items: flex-start; gap: 18px; }
.hero__title { margin: 0; font-family: var(--serif); font-weight: 600; line-height: 1.02;
    font-size: clamp(2.4rem, 6vw, 4.2rem); letter-spacing: -.015em; }
/* `.hero__accent` and `.hero__tagline` deleted. Both are survivors of the three merged hero
   variants: the accent word is `.eyebrow > .accent-script` on every hero that renders, and the
   sentence under the title is `.hero__intro`. Two names for one element is how the wrong one
   ends up in a new template. */
.hero__status { margin: 4px 0 0; display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.hero__actions { margin: 10px 0 0; display: flex; gap: 12px; flex-wrap: wrap; }


/* -- The status word ------------------------------------------------------- */
.status { font-family: var(--sans); font-size: .82rem; font-weight: 600; }
/* MEASURED IN A BROWSER, ON A REAL RESTAURANT: «Jetzt geöffnet» came out at 1.39:1.
   It sits inside `.hero--foto`, i.e. on the near-black plate — and it was painted in the
   restaurant's OWN brand colour, tinted 14% of itself. Pinocchio's is #023d21, a very dark
   green, so the one sentence this component exists for was, in practice, not there. The
   CLOSED state used the light `--c-stone-2` and was the loud one: the badge was backwards.

   These two were the only rules on the whole guest side reading the RAW `--c-accent` instead
   of the semantic `--accent`, which is how they escaped the dark-hero treatment everything
   else in this block already had. Now they read the on-dark tokens like their neighbours.

   `--footer-open` is reused rather than a fourth green invented: it is the token that already
   answers «open, on a dark ground», and it computes to 9.4:1 here. */
.status--open {
    color: var(--footer-open); }
.status--closed {
    color: var(--on-dark-soft); }
.status__note { font-size: .88rem; color: var(--on-dark-soft); }

/* THE PREFERENCE COVERED FOUR BLOCKS AND MISSED THE MOST VISIBLE MOTION ON THE SITE: every
   card and every button lifted on hover, and the mobile panel slid in, regardless. A reader who
   has asked their operating system for less movement was getting all of it. */
@media (prefers-reduced-motion: reduce) {
    .hero * { transition: none !important; animation: none !important; }
    .btn:hover, .dishcard:hover, .rg-card:hover, .wa-fab__btn:hover { transform: none !important; }
    .nav, .nav-backdrop, .searchbox__input, body { transition: none !important; }
}

/* On a phone the fixed bar at the bottom already offers Anrufen and WhatsApp, so the hero's
   telephone button is the same affordance twice on one screen. The primary action stays. */
@media (max-width: 640px) {
    .hero__actions .btn--ghost { display: none; }
}

/* The accent word keeps its own treatment wherever it appears.
   `.eyebrow` uppercases its contents, which is right for a label like "SEIT 1998" and wrong
   for the one element carrying the restaurant's identity: Trattoria became TRATTORIA on the
   404 while staying Trattoria in the hero. Each typeface set decides how that word is set —
   Handwerk uppercases it deliberately, Klassik and Tafel do not — and a wrapper must not
   overrule the decision. */
.eyebrow .accent-script { text-transform: none; letter-spacing: inherit; }

/* ============================================================
   THE FIRST SCREEN — one variant, bounded height.

   What this replaces measured 1099px in a browser against the reference design's 533px: a
   variant carrying `padding-block: clamp(72px,13vw,168px)` under a title set at
   `clamp(3rem,11vw,7.5rem)`, so the height was whatever the content happened to add up to.
   `min-height` with a ceiling decides it now, and the content sits at the bottom of it.

   `min-height` and `justify-content:flex-end` HAVE TO ARRIVE TOGETHER. Either alone gives a
   tall box with the text stranded in the middle of it.
   ============================================================ */
.hero--foto {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    /*
     * ⛔ 74vh WAR AUF DEM TELEFON EIN GANZER BILDSCHIRM, und bei einem Haus ohne Foto ein
     *    ganzer Bildschirm dunkler Fläche. Gemessen an einem echten Haus mit zwei Standorten:
     *    oben die Standortwahl, darunter diese Platte — ein Gast musste rund 1100 px scrollen,
     *    bevor das erste Gericht kam. Die Zahl steht jetzt so, dass die Kante des nächsten
     *    Bandes am unteren Rand mitsieht; ein Bildschirm, dessen Boden man sieht, wird
     *    weitergescrollt, einer ohne Boden sieht aus wie die ganze Seite.
     *
     * ⚠️ DER DECKEL BLEIBT. `min-height` mit Obergrenze UND `justify-content: flex-end` gehören
     *    zusammen — das steht im Kopf dieses Blocks und gilt unverändert.
     */
    min-height: clamp(400px, 58vh, 560px);
    padding-block: clamp(40px, 6vw, 72px) clamp(30px, 5vw, 58px);
    /*
     * THE DAY-ONE STATE OF EVERY RESTAURANT ON THIS PLATFORM, and it was a flat near-black
     * rectangle up to 640px tall — the least designed surface on the site, shown to the customer
     * on the day they are deciding what they think of us. Most houses arrive with no usable
     * photograph; the fallback is not an edge case, it is the first impression.
     *
     * Two gradients and no image: a warm pool behind the type where the eye lands, and a cool
     * fall to the corner. Nothing moves, nothing loads.
     */
    /* 25.09.2026: ohne die zwei Lichthöfe in Haus- und Messingfarbe. Farbige Leuchtflecken hinter
       dem Namen sind der Hintergrund, den ein generierter Entwurf hinter jeden Titel legt; die
       dunkle Platte allein trägt den Namen. */
    background: var(--dark-plate);
    color: var(--on-dark);
}
/* The photograph arrives as a custom property from the template, never as a path written into
   this file: twenty restaurants sharing one hardcoded /assets/img/hero.webp is twenty
   restaurants with the same photograph. */
/* ⛔ DER SCHLEIER WAR SO DICHT, DASS DAS FOTO NICHT MEHR ZU SEHEN WAR.

   `--scrim-64` über `--scrim-86` lässt im Mittel rund ein Viertel des Bildes durch. Gemessen am
   ersten echten Hausfoto (mittlere Helligkeit 122 von 255) kommen davon etwa 30 an — ein
   schwarzes Rechteck. Der Kopf sah mit Foto genauso aus wie ohne, nur ohne das Wasserzeichen,
   das bei einem Haus ohne Foto an seiner Stelle steht.

   Jetzt ein eigener Verlauf: oben leicht, unten dicht. Der Titel steht unten links, also liegt
   die Deckung dort, wo Text ist, und das Bild bleibt oben sichtbar.

   ⛔ ALS EIGENE VARIABLE, WEIL ES DEN SCHLEIER ZWEIMAL GIBT. Ohne Skript malt ihn diese Regel;
      mit Skript wandert das Foto auf `::before` (man kann einen Hintergrund nicht
      transformieren) und der Schleier auf `::after`. Beim ersten Versuch habe ich nur die
      Regel hier geändert — und im Browser blieb alles schwarz, weil dort `.js-motion` gilt und
      `::after` weiter die alten Tokens trug. Eine Farbe, zwei Maler: eine Quelle. */
:root { --hero-schleier: linear-gradient(rgba(20, 24, 28, .34) 0%, rgba(20, 24, 28, .62) 55%, rgba(20, 24, 28, .82) 100%); }
.hero--foto.is-photo {
    background-image: var(--hero-schleier), var(--hero-photo);
    background-size: cover;
    background-position: center;
}
/* NO max-width HERE. Constraining the column to 34ch wrapped a restaurant's own name across
   three lines at 60px and pushed the two buttons onto a second row — 603px of content inside a
   533px frame. The measure belongs on the PARAGRAPH, which is the only thing that reads badly
   when it runs long; a title and a pair of buttons want the width they were given. */
.hero--foto .hero__inner { display: flex; flex-direction: column; gap: 16px; }
.hero--foto .hero__title { color: var(--on-dark); font-size: clamp(2.4rem, 5.4vw, 3.8rem); }
.hero--foto .hero__intro { color: var(--on-dark-soft); max-width: 46ch; }
.hero--foto .eyebrow,
.hero--foto .accent-script { color: var(--on-dark-accent); }
.hero--foto .btn--ghost { color: var(--on-dark); border-color: var(--on-dark-soft); }

/* ============================================================
   RESERVIEREN — the floating invitation, and the booking form.

   THE BUTTON CAME BACK. The reference design carries a WhatsApp action that was lost in the
   port: `.wa-fab` on wide screens and `.mobilebar__wa` in the thumb bar. For a German
   restaurant WhatsApp is not a nice extra — it is where the booking conversation actually
   happens, and a guest who wants a table at seven tonight will send a message long before
   they fill in a form.

   `svg { flex: 0 0 auto }` IS LOad-BEARING. Inside a flex row an SVG with no intrinsic width
   collapses to nothing, and the button renders as a green circle with an invisible icon.
   ============================================================ */
/* `.mobilebar__wa` — a brand-green WhatsApp glyph in the thumb bar — is deleted. The row it sat
   in is labelled "Reservieren", not "WhatsApp": the label names the errand, so a green mark from
   a different company beside it points at the wrong noun. The bar is one colour now, and the
   icon uses `.mobilebar__ic` like its neighbours. */

/* ONE DECLARATION, and it used to be three. The block above said "wide screens only", a bare
   `.wa-fab { display: none }` came next, and then a THIRD copy re-declared `display: flex`
   unconditionally — so the last one won and the floating button sat on top of the phone's own
   thumb bar, two WhatsApp actions on one 375px screen with the fixed bar underneath it. The
   comment above the rules described the behaviour the rules had stopped having; measured at
   375px, the green circle was there. Phones get the thumb bar, wide screens get this. */
.wa-fab { display: none; }
@media (min-width: 861px) {
    .wa-fab {
        position: fixed; right: 22px; bottom: 22px; z-index: 35;
        display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
    }
}
.wa-fab__note {
    margin: 0; max-width: 240px;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--line);
    /* square corner bottom-right: the bubble points at the button below it */
    border-radius: 16px 16px 4px 16px;
    padding: 10px 14px; font-size: .88rem; line-height: 1.35;
    box-shadow: 0 12px 32px rgba(20, 16, 12, .18);
    /* No entrance animation, deliberately. A delayed fade-in was tried both ways: `forwards`
       from opacity:0 leaves the text invisible forever if the animation never runs, and
       `backwards` does the same because it holds the hidden first frame for the whole delay —
       a stalled animation clock (throttled background tab, headless engine) never ends it.
       Both fail silently, and the invitation is the entire point of this component. It is a
       small quiet bubble; it does not need a reveal to earn its place. */
}
.wa-fab__btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 56px; height: 56px; border-radius: var(--r-tag);
    /* THE GREEN STAYS — a German guest recognises it and that recognition is the whole point of
       the button. What goes is WhatsApp's own drop-shadow: a coloured glow under a floating
       circle is a 2019 growth-hacking artefact, and it was the loudest object on a premium
       page. A neutral shadow lets it sit ON the page instead of hovering above it. */
    background: #25D366; box-shadow: 0 8px 22px color-mix(in oklab, #000 22%, transparent);
    transition: box-shadow var(--t-fast), filter var(--t-fast);
}
.wa-fab__btn svg { width: 30px; height: 30px; fill: #fff; flex: 0 0 auto; }
.wa-fab__btn:hover { box-shadow: 0 10px 28px color-mix(in oklab, #000 30%, transparent); filter: brightness(1.06); }

/* The booking form. Deliberately plain: native date, time and select controls, because the
   guest most likely to use this is on a pavement with one bar of signal and a form that needs
   a framework to boot is a form that sometimes does not. */
.resform { margin-top: 8px; }
.resform__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; }
.resform__field { display: flex; flex-direction: column; gap: 6px; margin: 0 0 16px; }
.resform__field label { font-size: .92rem; color: var(--muted); }
.resform__field input,
.resform__field select,
.resform__field textarea {
    font: inherit; color: var(--text); background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--r-sm);
    padding: 11px 12px; width: 100%;
}
.resform__field input:focus-visible,
.resform__field select:focus-visible,
.resform__field textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.resform__actions { display: flex; gap: 12px; flex-wrap: wrap; margin: 20px 0 12px; }
/* The invitation form reuses this family rather than owning a second one. Two things it needs
   that a booking form does not: a hint under a field, and a validation message.
   THE ERROR IS NOT COLOUR ALONE. `--wine` carries it, and so does the weight and the leading
   rule — colour on its own is invisible to a red-green colourblind owner, who is the exact
   person setting a password on the one page where getting it wrong locks them out. */
.resform__hint { font-size: .86rem; color: var(--muted); line-height: 1.45; }
/* DER WARTELISTEN-SATZ STEHT IM ABSAGEKASTEN, unter dem «wir sind ausgebucht». Er ist bewusst
   ruhiger als die Absage darüber — die Absage ist die Nachricht, das hier ist der Ausweg, und
   zwei fette Zeilen übereinander lesen sich wie zwei Probleme. Der Abstand nach unten trennt
   ihn vom Knopf, damit der Satz nicht wie dessen Beschriftung wirkt. */
.resform__warteliste { font-size: .92rem; color: var(--muted); line-height: 1.5; margin: 10px 0 14px; }
.resform__error {
    font-size: .88rem; font-weight: 600; color: var(--wine);
    border-left: 3px solid var(--wine); padding-left: 10px;
}

/* ZUSAMMENGEKLAPPT AUF DAS, WAS DER GAST GEWÄHLT HAT.
   `is-korb` setzt `cart.js`, nachdem es die Mengenfelder gefüllt hat. Die übrigen Zeilen bleiben
   im Formular und werden mit Menge 0 mitgeschickt — versteckt wird die ANZEIGE, nicht die Zeile.
   Ohne Skript trägt das Formular diese Klasse nie und die ganze Karte steht da.

   ⚠️ DIE SEITENLEISTE UND DER STREIFEN GEHEN MIT. Beide sind Werkzeuge zum AUSSUCHEN — eine
      Rubrikenliste über vier gewählten Gerichten wäre ein Wegweiser durch eine Karte, die gerade
      nicht da ist, und «Am beliebtesten» wäre eine Empfehlung an jemanden, der schon gewählt hat. */
.resform.is-korb .orderline:not(.is-gewaehlt) { display: none; }
.resform.is-korb .mcat:not(:has(.is-gewaehlt)) { display: none; }
.resform.is-korb .catbar,
.resform.is-korb .laden__seite,
.resform.is-korb .beliebt { display: none; }
/* ⛔ OHNE DIESE ZEILE LANDETE DIE KARTE IN DER 232-PX-SPALTE. Ab 861 px ist `.laden__raster` ein
   Zwei-Spalten-Raster «Leiste | Essen» (unten). Blendet `is-korb` die Leiste aus, bleibt ihre Spalte
   trotzdem stehen — das einzige Kind rückt in sie hinein: Karten von 230 px Breite links, zwei
   Drittel der Seite leer, und «Hauptgerichte» in einer 230-px-Spalte mit Silbentrennung mitten
   im Wort («Hauptgeri-chte»). Der Fehler stand genau auf dem Weg, den jeder Gast mit Warenkorb nimmt
   (Speisekarte → «Zum Bestellformular»).
   ⚠️ DIE SILBENTRENNUNG BLEIBT, wie für jede Überschrift (`h2 { hyphens: auto }`, `lang="de"`): sie war
      nicht die Ursache, sondern was eine zu schmale Spalte aus einem langen deutschen Wort macht.
      Eine Spalte, die breit genug ist, braucht sie nicht. */
.resform.is-korb .laden__raster { grid-template-columns: minmax(0, 1fr); }
.resform__mehr { margin: var(--s-3) 0; }

/* The honeypot. NOT `display:none` — bots have known about that for fifteen years. Off-screen,
   out of the tab order, and carrying a label that tells a screen reader to leave it alone. */
.resform__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* TOUCH TARGETS, MEASURED ON A 375px VIEWPORT.
   The menu button was 38 × 38, the menu-page controls 42 × 42 and the diet chips 42 tall — all
   under the 44 × 44 a thumb needs (WCAG 2.5.5). These are not decorative: the first is the ONLY
   way into navigation on a phone, and the others are the filters a guest with an allergy uses
   standing at a table. Applied here rather than on each rule so a new control inherits it.
   Desktop keeps the tighter sizes: a mouse is precise and 44px buttons look clumsy at 1280. */
@media (max-width: 860px) and (pointer: coarse), (max-width: 560px) {
    .iconbtn, .iconbtn2 { min-width: 44px; min-height: 44px; }
    .m-diet .chip, .chip--cat { min-height: 44px; }
    /* ⛔ `.ex-chip` FEHLTE HIER, und der Kommentar oben nennt genau diese Chips: «die anderen
       sind die Filter, die ein Gast mit einer Allergie benutzt, während er an einem Tisch
       steht». Gemessen 37,6px (13,12px × 1,65 Zeilenkasten + 14px padding + 2px Rahmen), bei
       360px sogar 37,1px — neben den Diät-Chips derselben Zeile, die 44px haben. */
    .ex-chip { min-height: 44px; }
    /* The wordmark is a link to the front page; 36px tall is a target you miss on a tram. */
    .brand { min-height: 44px; }

    .footer-links a, .footer-legal a, .footer-kontakt a, .breadcrumb a {
        display: inline-flex; align-items: center; min-height: 44px;
    }
    /* Mit 44px hohen Zeilen sitzt das Zeichen in der Mitte der Zeile, nicht an ihrer ersten Textzeile. */
    .footer-kontakt li { align-items: center; }
    .footer-kontakt svg { margin-top: 0; }
}


/* ============================================================
   THE 2026 PLATFORM LAYER — four browser features, no markup, no JavaScript.

   Every rule below is additive: an engine that does not know the feature ignores the block and
   the page is exactly what it was. That is the whole reason these are worth having on a site
   whose guests are on whatever phone they happen to own — the modern feel is free, and its
   absence costs nothing.

   NONE OF IT IS DECORATION FOR ITS OWN SAKE. Each one answers something the audit measured.
   ============================================================ */

/* -- 1 · Cross-document view transitions ------------------------------------
   A restaurant site is nine pages a guest walks through: Startseite → Speisekarte → Reservieren.
   Each of those was a white flash and a jump to the top. This is the single change that makes a
   server-rendered site feel like it was built this year, and it is four lines.

   The header and the name are named so they PERSIST across the navigation instead of fading —
   the masthead stays put and the page beneath it changes, which is what the guest expects to
   happen and what a full-page fade denies them. */
@view-transition { navigation: auto; }

::view-transition-old(root) { animation-duration: .18s; }
::view-transition-new(root) { animation-duration: .22s; }

.site-header { view-transition-name: masthead; }
.site-footer { view-transition-name: colophon; }
.brand__name { view-transition-name: house-name; }

/* DIE DAUMENLEISTE BLEIBT STEHEN.
   Unbenannt gehörte die Leiste zur Wurzel und blendete mit der ganzen Seite aus und wieder ein —
   ein Bedienteil, das bei jedem Tippen flackert. Benannt steht sie still.

   ⛔ NUR DIE NEUE LEISTE, UND SIE LEBT (D-182). Bis zur Mulde flog die Pille als eigenes benanntes
      Element hinüber. Mit Kreis und Mulde ging das nicht mehr auf: die Mulde steckt in der Fläche
      der Leiste, zwei Bilder der Leiste blendeten ineinander, und für eine Drittelsekunde standen
      zwei halbe Mulden nebeneinander; das weisse Zeichen im Kreis lag im Bild der Leiste UNTER der
      geflogenen Pille und war weg. Jetzt wird das alte Bild gar nicht gezeigt, und das neue ist
      die lebendige Seite (`::view-transition-new` ist kein Standbild) — Pille, Mulde und Zeichen
      gleiten dort mit derselben Ankunft wie ohne Überblendung (`leiste-kommt`, leiste-init.js).

   Nur bis 860px: darüber ist die Leiste `display: none` und wird ohnehin nicht erfasst. */
@media (max-width: 860px) {
    .mobilebar { view-transition-name: daumenleiste; }
}
::view-transition-old(daumenleiste) { display: none; }
::view-transition-new(daumenleiste) { animation: none; }
/* SCHNELL AUF DEM TELEFON. Die neue Seite steht praktisch sofort (96 %) und hebt sich die letzten
   vier Pixel an; die alte geht darunter weg. `normal` statt der voreingestellten Addition: zwei
   fast volle Bilder addiert ergäben einen hellen Blitz. Bei reduzierter Bewegung bleibt es bei
   der ruhigen Überblendung oben, und die Pille springt statt zu gleiten. */
@media (max-width: 860px) and (prefers-reduced-motion: no-preference) {
    ::view-transition-old(root) { animation: .14s linear both seite-weg; mix-blend-mode: normal; }
    ::view-transition-new(root) { animation: .2s cubic-bezier(.2, .8, .3, 1) both seite-an; mix-blend-mode: normal; }
}
@keyframes seite-weg { to { opacity: 0; } }
@keyframes seite-an { from { opacity: .96; transform: translateY(4px); } }

/* -- 2 · Container queries --------------------------------------------------
   THE SAME CARD IN THREE DIFFERENT SLOTS. A dish card sits in a four-column grid on the
   homepage, in a two-column band on the Stadt page, and full width on a phone — and it was
   sized by the VIEWPORT, which knows none of that. At 1280px in a narrow column it kept the
   wide-screen padding and the 168px photograph, and looked cramped for reasons no breakpoint
   could see.

   Container queries let the component ask its own slot. Baseline since 2023 and the correct
   tool for exactly this. */
.dish-grid, .rg-cards, .cater-gallery { container-type: inline-size; }

@container (max-width: 300px) {
    .dishcard { padding: var(--s-4); }
    .dishcard__photo { height: 132px; }
    .dishcard__name { font-size: var(--fs-3); }
}

/* -- 3 · A quiet arrival ----------------------------------------------------
   Scroll-driven, so it costs no JavaScript and no timer: the band lifts the last few pixels as
   it enters, once, and never again. `animation-range` stops it finishing at the very bottom of
   the viewport, where a guest would never see it complete.

   ⚠️ INSIDE the reduced-motion guard, not beside it. Four hover transforms were outside that
   guard for a year — a reader who asked their system for less movement got all of it. Motion
   added in 2026 does not get to repeat that. */
@media (prefers-reduced-motion: no-preference) {
    @supports (animation-timeline: view()) {
        main > section {
            animation: band-arrive linear both;
            animation-timeline: view();
            animation-range: entry 0% entry 32%;
        }

        /* The first band is already on screen when the page loads; animating it means the guest
           watches their own homepage assemble, which is the opposite of premium. */
        main > section:first-child { animation: none; }
    }
}

@keyframes band-arrive {
    from { opacity: .4; transform: translateY(10px); }
    to { opacity: 1; transform: none; }
}

/* -- 4 · Long menus stay cheap ---------------------------------------------
   A Speisekarte imported from a PDF runs to 119 dishes. `content-visibility` lets the browser
   skip layout and paint for the sections below the fold until they are needed; the intrinsic
   size keeps the scrollbar honest so the page does not jump as they come in.

   Measured shape rather than a guess: `.mcat` is a heading plus a grid of rows, and 640px is
   about a six-dish section. */
.mcat { content-visibility: auto; contain-intrinsic-size: auto 640px; }

/* -- Typography, restored where it belongs ----------------------------------
   These three were briefly in the base sheet, taken back out because they changed the look of
   every restaurant already live, and now come back DELIBERATELY as part of a design pass the
   operator asked for — rather than as a side effect of building something else.

   `hyphens: auto` is not a nicety in German: `overflow-wrap` breaks a compound WITHOUT drawing
   a hyphen, and «Allergenkennzeich nung» reads as a fault. `text-wrap: pretty` on running text
   kills the one-word last line; `balance` on headings keeps a two-word orphan off the second
   line of a hero. */
h1, h2, h3, h4 { hyphens: auto; text-wrap: balance; }
p, li, .hero__intro, .lede { text-wrap: pretty; }

/* AND A SIZE FOR BARE HEADINGS, which nothing gave them: only headings wearing `.section-head`,
   `.article__body` or a `__title` class were ever sized, so a bare <h2> fell through to the user
   agent's fixed 2em. Measured on the homepage: «Ihre Feier bei uns» at 24px, one band below a
   heading that scales to 40px. Same page, same level, two sizes, and nothing said so. */
h1 { font-size: var(--fs-6); }
h2 { font-size: var(--fs-5); }
h3 { font-size: var(--fs-4); }
h4 { font-size: var(--fs-3); }

/* NO OVERRIDE LIST IS NEEDED, and the first draft had one built on `revert-layer` — which
   would have been a real bug: this stylesheet uses no cascade layers, so outside a layer that
   keyword behaves like `revert` and would have dropped `.section-head h2` to the user agent's
   own size. It is unnecessary anyway. Every heading that was already sized deliberately carries
   a CLASS, and a class selector outranks a bare element selector. The rules above only reach
   the headings nothing had claimed. */

/* -- Gut zu wissen ----------------------------------------------------------
   Die Angaben, die ein Gast vor der Abfahrt braucht: Karte oder bar, Rampe oder Stufen, Hund,
   Terrasse, Hochstuhl, Parkplatz. Sie entscheiden, ob jemand überhaupt losfährt.

   ⛔ WAS HIER STAND, WAR EIN KARTENRASTER MIT PHOSPHOR-DOPPELTON, und es ist am 20.09.2026
      abgelöst worden — nicht umgefärbt, sondern ersetzt. Die Fassung darunter ist das Register
      mit der eigenen gezeichneten Zeichenfamilie, das seit dem 19.09. auf Bühne stand und jetzt
      in JEDEM Aufbau steht. Mit der Karte sind auch ihre Ausnahmen gegangen: die `--info-*`-
      Tokens von Kontor, das Einfliegen je Karte (`.js-motion .facts__item`), die Staffelung in
      Ofen. Ein Bauteil, das es nicht mehr gibt, braucht keine Sonderregeln.

   Die drei Regeln des Bands haben den Wechsel überlebt und stehen unverändert am Block darunter:
   keine Werbung, Nein nie im Ja-Grün, Nein nie rot. */

/* ══ GUT ZU WISSEN — ein Register mit eigenen Zeichen, für JEDEN Aufbau ═════════════════════
   Rubrikmarke, grosse Überschrift, ein Zähler, eine Haarlinie; darunter ein Raster aus Angaben,
   je eine Nummer mit Rubrik («01 · Bezahlen»), ein gezeichnetes Zeichen in einer Nische und der
   Satz. Keine Karten, keine Schatten, keine Kreise.

   ⛔ WARUM DAS HIER STEHT UND NICHT MEHR IN buehne.css. Diese Fassung wurde am 19.09. für Bühne
      gebaut und lag in dessen Blatt — Kontor, Ofen und Tatami bekamen weiter die alte Karte mit
      Phosphor-Doppelton. Der Betreiber am 20.09.: «o tasarım bütün temalara olması gerek.» Er hat
      recht, und der Grund ist nicht Geschmack: die Angaben hier entscheiden, ob jemand überhaupt
      losfährt (Karte, Rampe, Hund, Terrasse), und sie sind in jedem Aufbau dieselben Angaben. Ein
      Bauteil, das je Aufbau anders GEBAUT ist, driftet; eines, das je Aufbau anders AUSSIEHT,
      nicht. Also steht der Bau hier, und ein Aufbau darf Schrift und Ton daran ändern.

   ⚠️ DIE DREI REGELN DES BANDS GELTEN UNVERÄNDERT: keine Werbung (die Nische ist ein Hauch der
      Tinte, nie satt), Nein nie im Ja-Grün, Nein nie rot. Ja trägt --enamel, Nein --muted;
      `AuskunftszeichenTest` hält beides fest.

   ⚠️ `--az-grund` IST REGISTRIERT (@property), weil zwei Dinge dieselbe Farbe tragen und
      gemeinsam überblenden müssen: die Nische und die Flächen im Zeichen, die Dahinterliegendes
      abdecken (die Karte vor dem Schein). Unregistriert spränge die Fläche, während die Nische
      blendet.

   ⚠️ DIE SCHRIFT IST EINE VARIABLE, KEIN NAME. `--az-schrift` erbt vorgabemässig die Schrift der
      Seite; Bühne setzt dort seine Serife (buehne.css). So bleibt EIN Bau und jeder Aufbau
      behält seine Stimme. */
@property --az-grund {
    syntax: "<color>";
    inherits: true;
    initial-value: transparent;
}

.facts {
    --az-tinte: var(--enamel);
    --az-strich: 1.45;
    --az-kurve: cubic-bezier(.16, 1, .3, 1);
    --az-verzug: 0ms;
    --az-schrift: inherit;
    /* ⚠️ DAS PAPIER IST EINE VARIABLE. Die Nische und die Abdeckflächen IM Zeichen (die Karte vor
       dem Schein) werden aus der Tinte mit dem Grund gemischt — und der Grund ist je Aufbau ein
       anderer (Bühne `--bu-papier`, Tatami `--ta-grund`). Fest auf `--bg` gemischt sässe die
       Nische auf einem anderen Ton als das Band, in dem sie liegt. */
    --az-papier: var(--bg);
    padding: var(--s-7) 0;
}

.facts__kopf { margin-bottom: clamp(4px, .8vw, 10px); }
/* Die Rubrikmarke: eine kurze Linie und das Wort, klein und gesperrt. Bühne ersetzt sie durch
   seine eigene gezählte Marke; überall sonst ist dies die Marke. */
.facts__marke {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 clamp(14px, 1.6vw, 22px);
    font-size: .8125rem;
    font-weight: 600;
    color: var(--muted);
}

/* Das Feld für eine laufende Nummer. Leer im Markup und vorgabemässig ohne Inhalt — ein Aufbau,
   der seine Abschnitte zählt (Bühne), füllt es über `::before`; alle anderen zeigen nichts. */
.facts__nr { font-variant-numeric: lining-nums tabular-nums; }
.facts__kopfzeile {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 24px;
    padding-bottom: clamp(20px, 2.4vw, 32px);
}
.facts__h {
    margin: 0;
    padding: 0;
    border: 0;
    font-family: var(--az-schrift);
    font-size: clamp(2rem, 3.8vw, 3.4rem);
    font-weight: 400;
    line-height: 1;
    letter-spacing: -.02em;
    text-transform: none;
    color: var(--text);
}
.facts__h > span { display: block; }
.facts__zahl {
    flex: 0 0 auto;
    margin: 0 0 .3em;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--muted);
}
.facts__zahl span {
    font-family: var(--az-schrift);
    font-size: 1.7rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--text);
}
.facts__linie {
    display: block;
    height: 1px;
    background: var(--line);
    transform-origin: 0 50%;
}

.facts__raster {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: clamp(24px, 3.4vw, 56px);
    margin: 0;
    padding: 0;
    list-style: none;
}
/* DIE LETZTE ZEILE SCHLIESST. Sieben Angaben in drei Spalten lassen eine allein stehen, und ihre
   Linie hörte nach einem Drittel auf — das Register sah abgerissen aus. Die letzte Angabe nimmt
   die freien Spalten mit, ihre Linie läuft bis zum Rand; ihr Inhalt bleibt, wo er ist. */
.auskunft:last-child:nth-child(3n+1) { grid-column: 1 / -1; }
.auskunft:last-child:nth-child(3n+2) { grid-column: 2 / -1; }

/* Eine Angabe: Nische links, daneben Nummer mit Rubrik und der Satz. Die Haarlinie darunter
   trägt eine zweite, in der Tinte der Angabe, die beim Zeigen von links nachwächst. */
.auskunft {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(18px, 1.8vw, 26px);
    min-width: 0;
    padding: clamp(22px, 2.3vw, 30px) 0;
    border-bottom: 1px solid var(--line);
}
.auskunft::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 1px;
    background: color-mix(in oklab, var(--az-tinte) 60%, transparent);
    transform-origin: 0 50%;
    scale: 0 1;
}
.auskunft__nische {
    --az-grund: color-mix(in oklab, var(--az-tinte) 5%, var(--az-papier));
    display: grid;
    place-items: center;
    box-sizing: border-box;
    width: auto;
    height: auto;
    /* ⚠️ EIN BOGEN, KEIN KREIS. Der Betreiber: «keine Dashboard-Kreise». Oben rund, unten fast
       gerade — eine Mauernische, ein Fenster im Süden. */
    color: var(--az-tinte);
}
.auskunft__satz { display: grid; gap: 7px; min-width: 0; }
.auskunft__rubrik {
    display: flex;
    align-items: baseline;
    gap: 10px;
    font-size: .8125rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--muted);
}
.auskunft__text {
    font-family: var(--az-schrift);
    font-size: clamp(1.08rem, 1rem + .28vw, 1.28rem);
    font-weight: 400;
    line-height: 1.25;
    letter-spacing: -.005em;
    text-wrap: balance;
    color: var(--text);
}

/* NEIN: Zeichen, Nische und Satz grau — weder das Grün der Zusage noch ein Warnton. */
.auskunft--nein { --az-tinte: var(--muted); }
.auskunft--nein .auskunft__text { color: var(--muted); }

/* Das Zeichen: eine Stärke, Nebenlinien aus der Tinte gemischt, Abdeckflächen in der Farbe der
   Nische. `overflow: visible`, damit eine Geste (die Rute, die Sonne) nicht am Rand abreisst. */
.az {
    display: block;
    width: 58px;
    height: 58px;
    overflow: visible;
    stroke-width: var(--az-strich);
}
.az .az-b { stroke: color-mix(in oklab, currentColor 52%, var(--az-grund)); }
.az .az-f { fill: var(--az-grund); }
.az .az-aus { stroke: var(--az-grund); stroke-width: 5; }
.az .az-kreuz { stroke-width: 1.4; }
.az .az-m { transform-box: view-box; }
/* Jede Linie ist ein Strich der Länge 1 (pathLength) mit einer Lücke von 2: bei Versatz 0 ganz
   da, bei 1.05 ganz weg — so zieht sich jede Form mit denselben zwei Zahlen. */
.az :is(path, circle, rect) { stroke-dasharray: 1 2; }
.az .az-m--schwanz { transform-origin: 36px 32.4px; }
.az .az-m--lampe { transform-origin: 24px 3.5px; }

@media (max-width: 1023px) {
    .facts__raster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .auskunft:last-child:nth-child(n) { grid-column: auto; }
    .auskunft:last-child:nth-child(2n+1) { grid-column: 1 / -1; }
}
@media (max-width: 639px) {
    .facts { --az-strich: 1.55; }
    .facts__raster { grid-template-columns: minmax(0, 1fr); }
    .auskunft { padding: 18px 0; column-gap: 18px; }
    .auskunft__nische { width: auto; height: auto; }
    .az { width: 50px; height: 50px; }
    .facts__zahl span { font-size: 1.4rem; }
    .facts__h { font-size: clamp(1.8rem, 8vw, 2.4rem); }
}

@keyframes az-tinte {
    from { stroke-dashoffset: 1.05; }
    to { stroke-dashoffset: 0; }
}
@keyframes az-faellt {
    from { translate: 0 -4px; }
}
@keyframes az-schiebt {
    from { translate: 4px 0; }
}
@keyframes az-pendelt {
    30% { rotate: 5deg; }
    60% { rotate: -2.5deg; }
    82% { rotate: 1deg; }
}
@keyframes az-wedelt {
    20% { rotate: -12deg; }
    45% { rotate: 7deg; }
    70% { rotate: -6deg; }
}

/* ANTWORTEN — `ist-an` setzt site.js: mit der Maus, solange sie auf der Angabe liegt, mit dem
   Finger einmal für gut eine Sekunde. Kein `:hover` im Blatt — auf dem Telefon bliebe er nach
   dem Tippen kleben. Alle Angaben tun dasselbe Kleine (die Reihe rückt 3 px, die Nische wird
   eine Spur dichter, das Zeichen eine Spur grösser, der Satz nimmt die Tinte an, die Linie
   darunter wächst nach), und jedes Zeichen tut dazu SEINE Geste. Nichts federt, nichts springt;
   Antwort in 150–250 ms, Nachzügler bis 500 ms. Bei reduzierter Bewegung: nichts. */
@media (prefers-reduced-motion: no-preference) {
    .auskunft::after { transition: scale .6s var(--az-kurve); }
    .auskunft__nische {
        transition: --az-grund .4s var(--az-kurve), border-color .4s var(--az-kurve), translate .35s var(--az-kurve);
        width: auto;
        height: auto;
}
    .auskunft__satz { transition: translate .35s var(--az-kurve); }
    .auskunft__text { transition: color .35s var(--az-kurve); }
    .az { transition: scale .35s var(--az-kurve); }
    .az .az-m { transition: translate .45s var(--az-kurve); }

    .auskunft.ist-an::after { scale: 1 1; }
    .auskunft.ist-an .auskunft__nische {
        translate: 3px 0;
    }
    .auskunft.ist-an .auskunft__satz { translate: 3px 0; }
    .auskunft.ist-an .auskunft__text { color: color-mix(in oklab, var(--az-tinte) 55%, var(--text)); }
    .auskunft--nein.ist-an .auskunft__text { color: color-mix(in oklab, var(--muted) 70%, var(--text)); }
    .auskunft.ist-an .az { scale: 1.04; }

    /* Die Tinte zieht sich neu — nur die Teile, die dafür gezeichnet sind (az-z). */
    .auskunft.ist-an .az-z { animation: az-tinte .55s cubic-bezier(.45, 0, .2, 1) backwards; }

    /* Karte: die Karte rückt vor, der Schein dahinter hebt sich, kontaktlos zieht sich Welle für Welle. */
    .auskunft.ist-an [data-zeichen="karte"] .az-m--karte { translate: -1.5px .5px; }
    .auskunft.ist-an [data-zeichen="karte"] .az-m--schein { translate: 1.2px -1.4px; }
    .auskunft.ist-an [data-zeichen="karte"] .az-z:nth-of-type(2) { animation-delay: 70ms; }
    .auskunft.ist-an [data-zeichen="karte"] .az-z:nth-of-type(3) { animation-delay: 140ms; }
    .auskunft.ist-an [data-zeichen="karte"] .az-z:nth-of-type(4) { animation-delay: 210ms; }

    /* Bargeld: der Schein hebt sich, die oberste Münze fällt auf den Stapel. */
    .auskunft.ist-an [data-zeichen="bargeld"] .az-m--schein { translate: 0 -1px; }
    .auskunft.ist-an [data-zeichen="bargeld"] .az-m--muenze { animation: az-faellt .5s var(--az-kurve) backwards; }

    /* Rampe: der Rollstuhl rollt ein Stück die Rampe hinauf, die Rampe zieht sich unter ihm. */
    .auskunft.ist-an [data-zeichen="rampe"] .az-m--fahrer { translate: 1.8px -.25px; }
    .auskunft.ist-an [data-zeichen="rampe"] .az-z { animation-duration: .7s; }

    /* Stufen: die Treppe zieht sich von unten nach oben — man steigt sie mit dem Blick. */
    .auskunft.ist-an [data-zeichen="stufen"] .az-z { animation-duration: .8s; }

    /* WC: der Knopf gibt nach, das Wasser zieht sich durch das Becken. */
    .auskunft.ist-an [data-zeichen="waschraum"] .az-m--knopf,
    .auskunft.ist-an [data-zeichen="toilette"] .az-m--knopf { translate: 0 1.2px; }
    .auskunft.ist-an [data-zeichen="waschraum"] .az-z,
    .auskunft.ist-an [data-zeichen="toilette"] .az-z { animation-delay: 150ms; }

    /* Terrasse: der Schirm hebt sich, die Sonne kommt heraus. */
    .auskunft.ist-an [data-zeichen="terrasse"] .az-m--schirm { translate: 0 -1.6px; }
    .auskunft.ist-an [data-zeichen="terrasse"] .az-sonne .az-z:last-child { animation-delay: 160ms; }

    /* Drinnen: die Lampe pendelt einmal aus. */
    .auskunft.ist-an [data-zeichen="drinnen"] .az-m--lampe { animation: az-pendelt 1.1s var(--az-kurve); }

    /* Hund: die Rute wedelt. Keine Hunde: der Umriss zeichnet sich, dann legt sich der Strich darüber. */
    .auskunft.ist-an [data-zeichen="hund"] .az-m--schwanz { animation: az-wedelt .9s ease-in-out; }
    .auskunft.ist-an [data-zeichen="kein-hund"] .az-m > * { animation: az-tinte .7s cubic-bezier(.45, 0, .2, 1) backwards; }
    .auskunft.ist-an [data-zeichen="kein-hund"] .az-aus,
    .auskunft.ist-an [data-zeichen="kein-hund"] .az-kreuz { animation: az-tinte .45s cubic-bezier(.45, 0, .2, 1) .45s backwards; }

    /* Hochstuhl: das Tablett schiebt sich an seinen Platz. */
    .auskunft.ist-an [data-zeichen="hochstuhl"] .az-m--tablett { animation: az-schiebt .55s var(--az-kurve) backwards; }

    /* Parken: das Auto rollt in die Lücke, dann zeigt das Schild sein P. Ohne Parkplatz rollt es nur. */
    .auskunft.ist-an [data-zeichen="parken"] .az-m--auto,
    .auskunft.ist-an [data-zeichen="auto"] .az-m--auto { translate: 2.4px 0; }
    .auskunft.ist-an [data-zeichen="parken"] .az-z { animation-delay: .3s; }
}

/* Kontor setzt es als geführtes Register, so wie dieser Aufbau sonst einen Fakt stellt — die
   Regel dazu steht unten im Kontor-Block. */

/* -- Warenkorb --------------------------------------------------------------
   The add button and the bar. Both are hidden in the markup and revealed by cart.js, so a
   browser without JavaScript never sees a control that would do nothing — the order form at
   /bestellen remains the path that always works.

   THE BUTTON IS 44px, and that is not a rounding of 42: it is tapped one-handed by somebody
   holding a phone over a table, and it sits beside a price, which is the worst place on the
   page to miss by four pixels. */
.mdish__add { display: none; }

.has-cart .mdish__add {
    display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    min-width: 44px; min-height: 44px; padding: 0 var(--s-3);
    /* ⛔ `margin-left: var(--s-2)` UND NICHT MEHR `auto`. Der Knopf sitzt jetzt IM Kopf, hinter
       dem Preis; ein `auto` schöbe ihn von dort noch einmal weg — an den rechten Rand, also
       wieder fort von dem Preis, zu dem er gehört. Die Führungslinie `.mdish__lead` erledigt
       das Schieben bereits, und sie tut es zwischen NAME und Preis, wo es hingehört. */
    margin-left: var(--s-2); flex: 0 0 auto;
    border: 1px solid var(--line); border-radius: var(--r-btn);
    background: var(--surface); color: var(--text); cursor: pointer;
    font: inherit; font-size: var(--fs-1); font-variant-numeric: tabular-nums;
    transition: border-color var(--t-fast), background var(--t-fast), color var(--t-fast);
}
.has-cart .mdish__add:hover { border-color: var(--accent); color: var(--accent-ink); }

/* THE PER-SIZE BUTTON, and it sits inside the price line rather than after the dish. A Cola at
   two prices is two order lines, so it needs two buttons — one beside each price, where the
   choosing already happens. `margin-left` rather than `auto`, because inside `.mdish__var` there
   is no free row to push against. The 44px minimum stays: this is the smaller-looking control on
   the page and it is still a thumb target on a phone held over a table. */
.has-cart .mdish__add--var {
    margin-left: var(--s-2); padding: 0 var(--s-2); vertical-align: middle;
}
.mdish__add-plus { font-size: 1.15em; line-height: 1; }
/* Empty until something is in the basket, so the button does not read «0». */
.mdish__add-qty:empty { display: none; }
.mdish__add-qty { font-weight: 600; }

.cartbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
    background: color-mix(in oklab, var(--surface) 92%, transparent);
    backdrop-filter: saturate(1.2) blur(10px);
    border-top: 1px solid var(--line);
    padding: var(--s-3) 0;
}
.cartbar[hidden] { display: none; }
.cartbar__inner { display: flex; align-items: center; gap: var(--s-4); }
.cartbar__count { margin: 0; font-size: var(--fs-1); }
.cartbar__clear {
    background: none; border: 0; padding: var(--s-2); cursor: pointer;
    font: inherit; font-size: var(--fs-0); color: var(--muted); text-decoration: underline;
}
.cartbar__go { margin-left: auto; }
.cartbar__sum { margin-left: var(--s-2); color: var(--muted); font-variant-numeric: tabular-nums; }

/* THE LINE ON THE CARD THAT SAYS ORDERS ARE TAKEN — one of the two, never both. `has-cart` is
   set by cart.js, so a browser that never ran it reads the sentence with the link to the plain
   form instead of a sentence about buttons it cannot see. */
.menu-order { margin: var(--s-3) 0 0; font-size: var(--fs-1); }
.menu-order--js { display: none; }
.has-cart .menu-order--js { display: block; }
.has-cart .menu-order--nojs { display: none; }

/* ⛔ ZWEI BEDIENELEMENTE, DIE OHNE SKRIPT NICHTS TATEN UND TROTZDEM DASTANDEN.

   Die Regel steht zweimal im Projekt ausgeschrieben — «ohne Skript filtert es nichts, also darf
   es ohne Skript nicht da sein» und «ein Bedienelement, das nichts tut, ist schlimmer als
   keines: der Gast tippt darauf, nichts geschieht, und er glaubt, die Seite sei kaputt». Der
   zweite Satz nennt sogar ausdrücklich die Speisekarte. Angewandt war sie auf `/bestellen`
   (`.ladensuche` ist dort `hidden`), auf der Speisekarte nicht.

   · `.m-bar` — Suchfeld, Diät-Chips, Allergen-Auswahl. Ohne `menu.js` filtert nichts.
   · `.mobilebar__korb` — der Warenkorb-Knopf im Daumenband. Ohne `cart.js` öffnet er nichts.

   ⚠️ ÜBER DIE MARKE DES JEWEILS ZUSTÄNDIGEN SKRIPTS, nicht über eine gemeinsame: `cart.js` kann
      laufen, während `menu.js` scheitert. Eine Marke für beide hiesse, die Filterleiste zu
      zeigen, weil der Warenkorb funktioniert.

   ⚠️ DER WEG OHNE SKRIPT BLEIBT: `.menu-order--nojs` oben führt weiterhin auf `/bestellen`,
      wo dieselbe Karte ohne eine Zeile JavaScript bestellbar ist. */
html:not(.has-menufilter) .m-bar { display: none; }
/* Nur der KNOPF braucht cart.js (er öffnet die Schublade dieser Seite). Der Link auf den übrigen
   Seiten führt zur Speisekarte und funktioniert ohne Skript (D-182). */
html:not(.has-cart) .mobilebar__korb:not(a) { display: none; }

/* TWO CONTROLS, ONE VISIBLE AT A TIME. The button opens the basket and the order is placed
   there; the link goes to the plain form. `has-cart` is set by cart.js, so a browser that never
   ran it keeps the link — and a control that would do nothing is never on screen. */
.cartbar__go--nojs { margin-left: 0; }
.has-cart .cartbar__go--nojs { display: none; }
button.cartbar__go { display: none; }
.has-cart button.cartbar__go { display: inline-flex; }

/* THE THUMB BAR AND THE BASKET BAR CANNOT BOTH OWN THE BOTTOM OF THE SCREEN. The basket wins
   while it has something in it — a guest mid-order is doing the one thing the bar exists for —
   and the phone bar steps aside rather than stacking. */
.has-cart .cartbar:not([hidden]) ~ .mobilebar,
.cartbar:not([hidden]) ~ .mobilebar { display: none; }

/* ---- The basket panel ------------------------------------------------------------------
   A dialog over the card rather than a second page: choosing and ordering are one act, and
   sending somebody to a page that lists the whole menu again to do the second half was the
   shape this replaces. `/bestellen` stays exactly where it was, for the browser that never
   runs a script and for anybody who prefers one long page. */
.cartdrawer {
    position: fixed; inset: 0; z-index: 60;
    background: color-mix(in oklab, #000 46%, transparent);
    display: flex; align-items: flex-end; justify-content: center;
}
.cartdrawer[hidden] { display: none; }

/* ─── FAZ C · DER PRODUKTDIALOG ──────────────────────────────────────────────────────────
   Dieselbe Bottom-Sheet-Hülle wie der Warenkorb daneben, von cart.js aus dem `data-options`-Attribut
   des angetippten Gericht-Knopfs gefüllt. */
.proddialog {
    position: fixed; inset: 0; z-index: 70;
    background: color-mix(in oklab, #000 46%, transparent);
    display: flex; align-items: flex-end; justify-content: center;
}
.proddialog[hidden] { display: none; }
.proddialog__panel {
    background: var(--surface); color: var(--text);
    width: min(560px, 100%); max-height: min(90vh, 900px);
    display: flex; flex-direction: column;
    border-radius: var(--r) var(--r) 0 0;
    border: 1px solid var(--line); border-bottom: 0;
    box-shadow: 0 -18px 48px rgba(0, 0, 0, .28);
}
@media (min-width: 700px) {
    .proddialog { align-items: center; }
    .proddialog__panel { border-radius: var(--r); border-bottom: 1px solid var(--line); box-shadow: var(--shadow-xl); }
}
.proddialog__head {
    display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
    padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--line);
}
.proddialog__title { margin: 0; font-size: var(--fs-4); font-family: var(--serif); }
.proddialog__close {
    flex: 0 0 auto; inline-size: 40px; block-size: 40px; border-radius: 999px;
    border: 0; background: transparent; color: var(--muted); cursor: pointer;
    font-size: 1.5rem; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
}
.proddialog__close:hover { background: color-mix(in oklab, var(--text) 8%, transparent); color: var(--text); }
.proddialog__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: none; }

.proddialog__body { padding: var(--s-3) var(--s-5) var(--s-4); overflow-y: auto; display: flex; flex-direction: column; gap: var(--s-4); }
.pdgroup { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; }
.pdgroup__name { font-family: var(--sans); font-weight: 600; font-size: var(--fs-2); padding: var(--s-2) 0; border-bottom: 1px solid var(--line-soft); }
.pdgroup__hint { font-weight: 400; color: var(--muted); font-size: var(--fs-0); }
.pdopt {
    display: flex; align-items: center; gap: var(--s-3);
    padding: var(--s-3) 0; border-bottom: 1px solid var(--line-soft); cursor: pointer;
}
.pdopt__input { inline-size: 20px; block-size: 20px; accent-color: var(--accent); flex: 0 0 auto; }
.pdopt__text { flex: 1 1 auto; min-inline-size: 0; }
.pdopt__price { color: var(--muted); font-variant-numeric: tabular-nums; }

.proddialog__foot {
    display: flex; align-items: center; gap: var(--s-3);
    padding: var(--s-4) var(--s-5); border-top: 1px solid var(--line);
}
.proddialog__menge { display: inline-flex; align-items: center; gap: var(--s-3); }
.proddialog__step {
    inline-size: 44px; block-size: 44px; border-radius: 999px;
    border: 1px solid var(--line); background: var(--bg); color: var(--text);
    font-size: 1.25rem; cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
.proddialog__step--plus { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.proddialog__zahl { min-inline-size: 1.5em; text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; }
.proddialog__hinzu {
    flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: space-between; gap: var(--s-3);
    padding: 14px 20px; border: 0; border-radius: var(--r-md);
    background: var(--accent); color: var(--on-accent); font: inherit; font-weight: 600; font-size: var(--fs-2); cursor: pointer;
}
.proddialog__hinzu[disabled] { opacity: .5; cursor: not-allowed; }
.proddialog__hinzu-text { white-space: nowrap; }
.proddialog__total { font-variant-numeric: tabular-nums; }

/* Die gewählten Optionen unter einer Warenkorbzeile — «Kalb, Käse, ohne Zwiebel». */
.cartline__opts { display: block; color: var(--muted); font-size: var(--fs-0); margin-top: 2px; }

.cartdrawer__panel {
    background: var(--surface); color: var(--text);
    /* ⛔ 88 % DER HÖHE WAREN ZU WENIG. Die Abschlussleiste (Trinkgeld, Summe, Rechtssatz, Knopf) ist
       fest und nimmt rund 280 px; auf 1440×900 blieben der Liste samt Formular 395 px, auf dem Telefon
       (390×844) 330 — die Lieferadresse wurde durch ein Schlüsselloch ausgefüllt. 94 % von `dvh` (die
       Höhe OHNE die einfahrende Adressleiste; `vh` davor für Browser ohne) gibt dem Blatt, was der
       Bildschirm hergibt, und die Leiste unten ist schmaler gemacht (`.cartdrawer__foot`). */
    width: min(560px, 100%); max-height: min(94vh, 960px); max-height: min(94dvh, 960px);
    display: flex; flex-direction: column; overflow: hidden;
    /* `--r` (16px) statt `--r-btn` (8px): dieselbe weiche Rundung wie `.abschluss` auf
       `/bestellen` — die Vorlage, an der dieser Dialog gemessen wird. Ein Blatt aus 8-px-Ecken
       las sich neben den 13–16-px-Karten der Gastseite wie ein Systemdialog, nicht wie Teil des
       Ladens. Nur die beiden OBEREN Ecken, weil das Blatt am unteren Rand klebt. */
    border-radius: var(--r) var(--r) 0 0;
    border: 1px solid var(--line); border-bottom: 0;
    /* GERICHTETER SCHATTEN, mit Absicht kein `--shadow-*`-Token: ein Bottom-Sheet stösst unten an
       den Bildschirmrand, ein nach UNTEN fallender Token-Schatten läge dort ausserhalb und wäre
       unsichtbar. Der Aufwärts-Hub hebt das Blatt von der Karte darunter ab. */
    box-shadow: 0 -18px 48px rgba(0, 0, 0, .28);
}
/* Auf dem Telefon steht das Blatt fast randlos: ein Streifen Seite darüber (zehn Pixel) zeigt noch, dass es ein
   Blatt ist; jeder weitere Pixel gehört der Liste und dem Formular. */
@media (max-width: 699px) {
    .cartdrawer__panel { max-height: calc(100vh - 10px); max-height: calc(100dvh - 10px); }
    .cartdrawer .cartdrawer__head { padding-top: var(--s-3); padding-bottom: var(--s-3); }
}
@media (min-width: 700px) {
    .cartdrawer { align-items: center; }
    /* Auf breiten Schirmen steht das Blatt frei in der Mitte: rundum gerundet und ein
       symmetrischer Token-Schatten, weil hier kein Rand mehr eine Seite abschneidet. */
    .cartdrawer__panel { border-radius: var(--r); border-bottom: 1px solid var(--line); box-shadow: var(--shadow-xl); }
}

.cartdrawer__head {
    display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
    padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--line);
}
.cartdrawer__title { margin: 0; font-size: var(--fs-4); font-family: var(--serif); }
/* ⛔ IM SCREENSHOT WAR DAS X EIN «ORANGER KASTEN». Der Knopf trägt selbst keinen Rahmen — der
   Kasten war der GLOBALE `:focus-visible` (Akzent-Umriss + 5-px-Hof), und `cart.js` setzt den
   Fokus beim Öffnen genau auf diesen Knopf. Ein programmatischer Fokus zeigt in aktuellen
   Browsern `:focus-visible`, also empfing der erste Blick auf den Dialog den harten Kasten.
   Antwort: ein ruhiger runder Schliess-Knopf mit weichem Hover-Kreis und einem ENGEN Ring ohne
   Hof (`box-shadow: none`), der wie ein Knopf aussieht und nicht wie ein umrahmtes Feld. */
.cartdrawer__close {
    display: inline-flex; align-items: center; justify-content: center;
    /* A thumb target, on the control somebody reaches for first when they change their mind. */
    min-width: 44px; min-height: 44px; padding: 0;
    background: none; border: 0; border-radius: var(--r-tag);
    cursor: pointer; color: var(--muted); font-size: 1.7rem; line-height: 1;
    transition: background var(--t-fast), color var(--t-fast);
}
.cartdrawer__close:hover { background: color-mix(in oklab, var(--accent) 10%, transparent); color: var(--text); }
.cartdrawer__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: none; }

.cartdrawer__body { flex: 1 1 auto; min-height: 0; padding: var(--s-4) var(--s-5) var(--s-5); overflow-y: auto; }

.cartlines { list-style: none; margin: 0 0 var(--s-4); padding: 0; }
.cartline {
    display: grid; grid-template-columns: 1fr auto auto; align-items: center;
    gap: var(--s-2) var(--s-4); padding: var(--s-3) 0; border-bottom: 1px solid var(--line-soft);
}
.cartline:first-child { padding-top: 0; }
.cartline:last-child { border-bottom: 0; }
/* `align-items: flex-start` IST DER KERN DER KORREKTUR am Allergen-Etikett (siehe `.cartline .codes`
   unten): ohne sie streckt der Flex-Spalten-Standard `stretch` die `.codes`-Marke auf die volle
   Spaltenbreite, und mit ihrem umrandeten Grundstil sah sie dann aus wie ein leeres Eingabefeld. */
.cartline__what { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-1); min-width: 0; }
.cartline__name { font-weight: 600; font-size: var(--fs-2); line-height: 1.3; overflow-wrap: anywhere; }

/* ⛔ DIE KONKRETE BESCHWERDE: der Zusatzstoff-/Allergen-Code (LMIV Art. 21, MUSS bleiben) sah aus
   wie ein Eingabefeld — Rahmen, heller Grund, linksbündig, direkt über dem echten Mengenwähler.
   Ein Gast hielt das «Hc» für eine Eingabe.

   URSACHE, GEMESSEN AM MARKUP: `cart.js` erzeugt `<span class="codes">`; der Grundstil `.codes`
   (Zeile ~785) trägt `border: 1px solid var(--line)` + hellen Grund und ist auf der Speisekarte
   ein ruhiges Abzeichen, WEIL es dort inline zwischen anderen Tags steht. Im Dialog liegt es in
   einer Flex-SPALTE und wurde auf volle Breite gestreckt — dieselbe Form wie ein `<input>`.

   ⚠️ NUR DIE DARSTELLUNG ÄNDERT SICH, DER CODE BLEIBT. Nicht den globalen `.codes`-Stil anfassen
   (er ist auf Speisekarte und `/bestellen` richtig und wird von Tests geprüft), sondern hier
   scoped überschreiben: nicht mehr strecken (`width: max-content`), den umrandeten «Feld»-Look
   durch einen gefüllten, ruhigen Etikett-Grund ersetzen (`--line-soft`, Rahmen transparent). So
   liest es sich als Info-Abzeichen statt als Formularfeld. */
.cartline .codes {
    align-self: flex-start; width: max-content; max-width: 100%;
    border-color: transparent; background: var(--line-soft); color: var(--muted);
}

/* DER MENGENWÄHLER — auf das Niveau der `.orderline__step`-Knöpfe von `/bestellen` gebracht:
   runde Knöpfe (`--r-tag`), 44 px Trefferfläche, der «+» als gefüllte Haupthandlung mit `--shadow-xs`,
   der «−» als flache Gegenhandlung, und derselbe ENGE Fokusring (Versatz 1 px statt der globalen
   3 px samt Hof), der im gedrängten Cluster «− N +» nicht ans Nachbarfeld rückt. */
.cartline__steps { display: flex; align-items: center; gap: var(--s-1); }
.cartline__step {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px; padding: 0; flex: 0 0 auto; cursor: pointer;
    border: 1px solid var(--line); border-radius: var(--r-tag);
    background: var(--bg); color: var(--text); font: inherit; font-size: var(--fs-4); line-height: 1;
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.cartline__step:hover { border-color: var(--accent); color: var(--accent-ink); }
.cartline__step:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; box-shadow: none; }
.cartline__step--plus {
    background: var(--accent); border-color: var(--accent); color: var(--on-accent);
    box-shadow: var(--shadow-xs);
}
.cartline__step--plus:hover {
    background: var(--accent-strong); border-color: var(--accent-strong); color: var(--on-accent);
    box-shadow: var(--shadow-sm);
}
.cartline__qty { min-width: 2.5ch; text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; }
/* Der Zeilenpreis in der Preisschrift des Hauses, wie `.orderline__price` auf `/bestellen`: er ist
   die Zahl, auf die das Auge in der Zeile zielt. */
.cartline__money { font-variant-numeric: tabular-nums; white-space: nowrap; font-family: var(--serif); font-weight: 600; color: var(--accent-ink); }

/* Das Aktions-Etikett (D-216) in der Karte der Startseite. Bis D-248 (12.10.2026) standen seine
   Regeln nur in karte.css, und auf der Startseite fiel der runde Aufkleber als Text unter den Preis
   («−20 % AKTION»). Dieselbe Form wie auf der Speisekarte: rund, flach, in der Ecke des Fotos.
   ⛔ VOR DEM KONTOR-TEIL, nicht am Dateiende: ab der ersten `.layout-kontor`-Regel gehört jede Zeile dem
      Kontor (LayoutKontorTest) — genau da war dieser Block am 12.10. kurz gelandet. */
/* Das Signalrot des Etiketts, einmal benannt — karte.css setzt es an der Zeile, die Aufbauten lesen es. */
:root { --ak-rot: #c0392b; }
.dishcard { position: relative; }
.dishcard .aktion-etikett {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 2;
    margin: 0;
    display: grid;
    place-items: center;
    align-content: center;
    min-width: 50px;
    min-height: 50px;
    padding: 4px 6px;
    border-radius: 999px;
    background: var(--ak-rot, #c0392b);
    color: #fff;
    box-shadow: 0 0 0 2px var(--bg);
    text-align: center;
    pointer-events: none;
}
.dishcard .aktion-etikett--haus { background: var(--accent); }
.dishcard .aktion-etikett__zahl { font-weight: 700; font-size: 13px; line-height: 1.1; white-space: nowrap; }
.dishcard .aktion-etikett__wort {
    font-size: 8px;
    line-height: 1.15;
    letter-spacing: .06em;
    text-transform: uppercase;
    max-width: 8ch;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}

/* ⛔ DIESER BLOCK GEHÖRT VOR DEN KONTOR-TEIL — er stand einmal am Dateiende und war damit
      im zweiten Aufbau gelandet. Ab der ersten `.layout-kontor`-Regel bis zum Dateiende gehört
      jede Zeile dem Kontor-Aufbau und MUSS auf `.layout-kontor` lauten; `LayoutKontorTest` prüft
      genau das und hat den Fehler gefunden. Die Schublade ist beiden Aufbauten gemeinsam, also
      steht sie hier bei den übrigen `.cart*`-Regeln. */

/* ═══ «PASST GUT DAZU» IM WARENKORB ══════════════════════════════════════════════════════════
   Was zu dem zuletzt gewählten Gericht am häufigsten mit bestellt wurde. Die Liste kommt aus
   den Bestellungen dieses Hauses (`Menu::pairMap()`), nicht aus einer gepflegten Liste und
   nicht aus eingekaufter Werbung.

   ⚠️ SIE SIEHT NICHT AUS WIE EINE ANZEIGE. Kein Rahmen, keine Farbe, kein Ausrufezeichen —
      eine Zeile Text und drei flache Knöpfe. Ein Vorschlag, der wie Werbung aussieht, wird wie
      Werbung behandelt: übersehen. */
.cartdazu { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--line-soft); }
.cartdazu__titel { margin: 0 0 var(--s-3); font-family: var(--serif); font-size: var(--fs-2); font-weight: 600; }
.cartdazu__liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }

.cartdazu__knopf {
    display: flex; align-items: center; gap: var(--s-3); width: 100%;
    /* 56px, nicht 44: hier steht ein Bild neben dem Namen, und die Zeile ist die Trefferfläche.
       Der Daumen zielt auf die ganze Zeile, nicht auf das «+» am Ende. */
    min-height: 56px; padding: var(--s-2) var(--s-3);
    border: 1px solid var(--line); border-radius: var(--r-btn);
    background: var(--surface); color: var(--text); cursor: pointer; font: inherit; text-align: left;
    transition: border-color var(--t-fast), background var(--t-fast);
}
.cartdazu__knopf:hover { border-color: var(--accent); }
.cartdazu__foto { width: 44px; height: 44px; object-fit: cover; border-radius: var(--r-sm); flex: 0 0 auto; }
.cartdazu__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.cartdazu__name { overflow-wrap: anywhere; }
.cartdazu__preis { font-size: var(--fs-0); color: var(--muted); font-variant-numeric: tabular-nums; }
.cartdazu__plus { flex: 0 0 auto; font-size: 1.3em; line-height: 1; color: var(--accent-ink); }

/* SUMME — jetzt die Zahl der Abschlussleiste unten (`.cartdrawer__foot`), nicht mehr ein
   Zeilenende über dem Formular. In der Preisschrift und der Marken-/Akzentfarbe, gross genug,
   dass sie die Zahl ist, auf die das Auge am Absendeknopf trifft. */
.cartdrawer__sum {
    display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3);
    margin: 0; font-size: var(--fs-3);
}
.cartdrawer__sum span { color: var(--muted); letter-spacing: .01em; }
.cartdrawer__sum strong { font-size: var(--fs-5); font-family: var(--serif); font-weight: 600; color: var(--accent-ink); font-variant-numeric: tabular-nums; line-height: 1; }

/* ── TRINKGELD — freiwillig, fürs Team, an der Theke mitbezahlt ───────────────────────────
   Steht in der Abschlussleiste ÜBER der Summe: der Gast sieht Speisen, Trinkgeld und Summe in
   einer Bewegung, bevor er «Zahlungspflichtig bestellen» drückt. Kein Preis reist mit — nur
   `trinkgeld_cents`, den der Gast selbst bestimmt und der Server begrenzt.
   Chips statt Auswahlliste: vier Berührungen à 44 px, unter jedem Prozentsatz der gerechnete
   Betrag, damit «10 %» nicht abstrakt bleibt. «Eigener Betrag» steht allein in der zweiten
   Zeile, weil vier Wörter in einem Fünftel von 340 px nicht lesbar sind. Die Vorgabe ist «Kein»:
   ein voreingestelltes Trinkgeld wäre ein Betrag, den niemand gewählt hat. */
.trinkgeld { margin: 0; padding: 0; border: 0; min-width: 0; }
/* Die Zeile: Zeichen, Titel, Stand, Pfeil — ein Knopf über die ganze Breite, 44 px hoch, ohne
   eigenen Rahmen, damit er in der Leiste wie eine Zeile liegt und nicht wie ein zweiter Knopf
   neben «Zahlungspflichtig bestellen». Die erste Fassung war ein Block von 150 px; auf dem
   Telefon blieben der Bestellung darüber zwei Zeilen. */
.trinkgeld__kopf {
    display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px;
    margin: 0; padding: 4px 0; border: 0; background: transparent; color: var(--text);
    font: inherit; text-align: left; cursor: pointer;
}
.trinkgeld__icon { flex: 0 0 auto; color: var(--accent-ink); }
.trinkgeld__titel { font-weight: 600; font-size: var(--fs-1); }
.trinkgeld__stand { margin-left: auto; font-size: var(--fs-1); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.trinkgeld__stand.is-gewaehlt { color: var(--accent-ink); font-weight: 600; }
.trinkgeld__pfeil { flex: 0 0 auto; width: 8px; height: 8px; border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted); transform: translateY(-2px) rotate(45deg); transition: transform var(--t); }
.trinkgeld__kopf[aria-expanded="true"] .trinkgeld__pfeil { transform: translateY(2px) rotate(-135deg); }
.trinkgeld__kopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }
.trinkgeld__blatt { padding: 0 0 var(--s-2); }
.trinkgeld__hinweis { margin: 0 0 var(--s-2); font-size: var(--fs-0); color: var(--muted); }
.trinkgeld__wahl { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.trinkgeld__chip {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
    min-height: 44px; padding: 6px 4px; border-radius: var(--r-md);
    border: 1px solid var(--line); background: var(--surface); color: var(--text);
    font: inherit; font-size: var(--fs-1); font-weight: 600; line-height: 1.1; cursor: pointer;
    transition: border-color var(--t), background var(--t), color var(--t);
}
.trinkgeld__chip--eigen { grid-column: 1 / -1; flex-direction: row; gap: 8px; }
.trinkgeld__chip small { font-size: var(--fs-0); font-weight: 400; color: var(--muted); font-variant-numeric: tabular-nums; }
.trinkgeld__chip small:empty { display: none; }
.trinkgeld__chip:hover { border-color: var(--accent); }
.trinkgeld__chip.is-aktiv { border-color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, var(--surface)); color: var(--accent-ink); }
.trinkgeld__chip.is-aktiv small { color: var(--accent-ink); }
.trinkgeld__chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.trinkgeld__eigen { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin: var(--s-3) 0 0; font-size: var(--fs-1); }
.trinkgeld__eigen label { color: var(--muted); }
.trinkgeld__feld { display: inline-flex; align-items: center; gap: 6px; }
.trinkgeld__feld input {
    width: 6em; padding: 9px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
    background: var(--surface); color: var(--text); font: inherit; font-variant-numeric: tabular-nums; text-align: right;
}
.trinkgeld__feld input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent); }
/* Die zwei leisen Zeilen über der Summe — Speisen und Trinkgeld getrennt, damit die grosse Zahl
   darunter nicht behauptet, das Essen sei teurer geworden. */
.cartdrawer__zeile { display: flex; justify-content: space-between; gap: var(--s-3); margin: 0; font-size: var(--fs-1); color: var(--muted); font-variant-numeric: tabular-nums; }
.cartdrawer__empty { margin: var(--s-5) 0; color: var(--muted); text-align: center; }
/* ⛔ «WIR NEHMEN GERADE NICHTS AN» — im Blatt, vor dem Korb, nicht erst nach dem Absenden.
   Dieselbe Einfassung wie `.ladenmeldung` auf `/bestellen`, weil es dieselbe Art Auskunft ist:
   das Haus sagt etwas über sich, und der Gast soll es lesen, BEVOR er tippt. Die linke Kante
   trägt das Gewicht — ein voller Farbblock wäre ein Alarm, und ein Stopp ist keiner. */
.cartdrawer__stopp {
    margin: var(--s-4) 0 0;
    border: 1px solid color-mix(in oklab, var(--wine) 34%, var(--line));
    border-left-width: 4px;
    border-radius: var(--r-md);
    background: color-mix(in oklab, var(--wine) 6%, var(--surface));
    padding: var(--s-3) var(--s-4);
    font-size: var(--fs-1);
    line-height: 1.45;
}
/* Die Zusicherung mit einem ruhigen Info-Zeichen in Messing — kein Warnton, eine Auskunft. */
.cartdrawer__legal { display: flex; gap: var(--s-2); align-items: flex-start; font-size: var(--fs-0); line-height: 1.42; color: var(--muted); margin: 0; }
/* «Alle Preise inkl. MwSt.» unter dem Wort «Summe»: dieselbe Auskunft, ohne eine eigene Zeile in der festen Leiste. */
.cartdrawer__mwst { display: block; margin-top: 2px; font-size: var(--fs-0); line-height: 1.3; color: var(--muted); }
.cartdrawer__legalicon { flex: 0 0 auto; width: 15px; height: 15px; margin-top: 1px; color: var(--gold-ink); }
.cartdrawer__alt { font-size: var(--fs-0); margin: var(--s-4) 0 0; text-align: center; }
.cartdrawer__form { margin: 0; }
/* DIE FORMFELDER RUHIGER EINGEFASST. Die Felder liegen auf `--surface` (dem Panelgrund) und trugen
   selbst `--surface` — ihre Kante verschwand in der Fläche, auf der sie liegen. Wie im `.abschluss`
   auf `/bestellen` («die Felder liegen auf der Karte, also brauchen sie den Grund der SEITE»)
   bekommen sie hier den Seitengrund `--bg`, damit ihre Einfassung zu sehen ist; dazu eine
   einheitliche 44-px-Feldhöhe (Telefon) und ein kräftigeres Label. */
.cartdrawer__form .resform__field label { font-weight: 600; font-size: var(--fs-0); color: var(--muted); letter-spacing: .01em; }
.cartdrawer__form .resform__field input,
.cartdrawer__form .resform__field select,
.cartdrawer__form .resform__field textarea {
    background: var(--bg); min-height: 46px;
    border: 1px solid var(--line); border-radius: var(--r-sm);
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
/* Ein ruhiger, sichtbarer Fokus in der Marken-/Akzentfarbe (ersetzt den globalen Umriss im
   engen Formular durch einen weichen Hof, der nicht ans Nachbarfeld stösst). */
.cartdrawer__form .resform__field input:focus,
.cartdrawer__form .resform__field select:focus,
.cartdrawer__form .resform__field textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 20%, transparent);
    outline: none;
}
.cartdrawer__form .resform__field textarea { min-height: 68px; }

/* ═══ DER BESTELLZETTEL · PREMIUM-AUSSTATTUNG ════════════════════════════════════════════════
   Kopf mit Messing-Beiwort und Griff, ein gegliedertes Formular und eine festgeklebte
   Abschlussleiste (Summe · Zusicherung · Absenden). Alles über Token, damit das Blatt die
   Markenfarbe jedes Hauses trägt und in Tag wie Nacht gleich ruhig steht. */

/* Bottom-Sheet-Griff — nur, wo das Blatt am unteren Rand klebt (Schmalschirm; auf Breitschirmen
   steht der Dialog frei in der Mitte und der Griff ist weg, siehe Media-Query unten). */
.cartdrawer__grip {
    flex: 0 0 auto; width: 40px; height: 4px; border-radius: 999px;
    background: var(--line); margin: 10px auto 2px;
}

/* Kopf: Messing-Beiwort über dem Serifentitel. */
.cartdrawer__heading { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cartdrawer__eyebrow {
    margin: 0; font-family: var(--sans); font-weight: 600;
    font-size: .8125rem;
    color: var(--gold-ink);
}

/* Ein Abschnitt des Formulars — «Wann?» und «Wer?» je unter einer Überschrift mit Messing-Icon
   und weicher Trennlinie. Kein <fieldset>: dessen <legend> lässt sich nicht als Flexzeile setzen;
   die Gruppierung ist hier optisch, die Feld-Labels tragen die Semantik. */
.cartsec { margin: 0 0 var(--s-5); }
.cartsec:last-of-type { margin-bottom: 0; }
.cartsec__title {
    display: flex; align-items: center; gap: var(--s-2);
    margin: 0 0 var(--s-3); padding-bottom: var(--s-2);
    font-family: var(--sans); font-weight: 600; font-size: var(--fs-1); color: var(--text);
    border-bottom: 1px solid var(--line-soft);
}
.cartsec__icon { flex: 0 0 auto; width: 18px; height: 18px; color: var(--gold-ink); }

/* «Wann?» als leicht getöntes Kärtchen — die wichtigste Wahl bekommt einen eigenen Grund. */
.cartsec--wann {
    padding: var(--s-4); border: 1px solid var(--line-soft); border-radius: var(--r-md);
    background: color-mix(in oklab, var(--gold) 6%, transparent);
}
.cartsec--wann .cartsec__title { border-bottom-color: color-mix(in oklab, var(--gold) 24%, var(--line-soft)); }

/* ═══ ABHOLEN ODER LIEFERN (D-172) ═══════════════════════════════════════════════════════════
   Zwei echte Radioknöpfe im Kleid der Trinkgeld-Chips: dieselbe Kante, derselbe getönte Grund
   für die Wahl. Das Feld liegt unsichtbar über der ganzen Fläche, damit ein Tipp irgendwo auf
   den Kasten trifft; `:has()` malt die Wahl. Ein Browser ohne `:has()` zeigt beide gleich —
   und der Punkt des Radios ist dann eben weg, gewählt wird trotzdem. Hier ein <fieldset>, weil
   die zwei Knöpfe EINE Frage beantworten; die <legend> trägt nur Rand und Schrift, keine
   Flexzeile (siehe den Kopf über `.cartsec`). */
.artwahl { border: 0; margin-inline: 0; padding: 0; min-width: 0; }
/* ⚠️ `.cartsec:last-of-type` nimmt dem EINZIGEN <fieldset> im Blatt seinen Abstand — «last of
   type» zählt je Elementart. Ohne diese Zeile klebte «Wohin dürfen wir liefern?» an den Knöpfen. */
.cartsec.artwahl { margin-bottom: var(--s-5); }
.artwahl > .cartsec__title { width: 100%; padding-inline: 0; }
.artwahl__wahl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.artwahl__knopf {
    position: relative; display: flex; flex-direction: column; gap: 2px;
    min-height: 52px; padding: 10px 12px; border-radius: var(--r-md);
    border: 1px solid var(--line); background: var(--surface); color: var(--text);
    cursor: pointer; transition: border-color var(--t), background var(--t), color var(--t);
}
/* ⚠️ `appearance: none` UND NICHT `opacity: 0`: das Feld bleibt über der ganzen Fläche und im
   Tab-Weg, zeichnet nur seinen Punkt nicht mehr. `opacity: 0` ist auf dieser Seite der Bewegung
   vorbehalten (BewegungTest) — ein Radioknopf ist keine Einblendung, die noch laufen müsste. */
.artwahl__knopf input {
    position: absolute; inset: 0; margin: 0; border: 0; border-radius: inherit;
    appearance: none; -webkit-appearance: none; background: transparent; outline: none; cursor: pointer;
}
.artwahl__wort { font-weight: 600; font-size: var(--fs-1); line-height: 1.2; }
.artwahl__knopf small { font-size: var(--fs-0); color: var(--muted); }
.artwahl__knopf:hover { border-color: var(--accent); }
.artwahl__knopf:has(input:checked) { border-color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, var(--surface)); color: var(--accent-ink); }
.artwahl__knopf:has(input:checked) small { color: var(--accent-ink); }
.artwahl__knopf:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ═══ DAS KONTO IM WARENKORB (D-221) ═════════════════════════════════════════════════════════
   Gespeicherte Adressen und Gutscheine als Knöpfe im Kleid der Abhol/Liefer-Wahl darüber —
   dieselbe Kante, derselbe getönte Grund für die Wahl, damit das Blatt EINE Sprache spricht.
   Keine Radios: der Knopf füllt nur Felder, abgeschickt werden die Felder. */
.adresswahl,
.gutscheinwahl {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 6px;
    margin: 0 0 var(--s-3);
}
.adresswahl__knopf,
.gutscheinwahl__knopf {
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    min-height: 48px; padding: 9px 12px; border-radius: var(--r-md);
    border: 1px solid var(--line); background: var(--surface); color: var(--text);
    font: inherit; text-align: left; cursor: pointer;
    transition: border-color var(--t), background var(--t), color var(--t);
}
.adresswahl__knopf small,
.gutscheinwahl__knopf small {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: var(--fs-0); color: var(--muted);
}
.adresswahl__titel { font-weight: 600; font-size: var(--fs-1); line-height: 1.2; }
.gutscheinwahl__wert { font-weight: 600; font-size: var(--fs-1); font-variant-numeric: tabular-nums; }
.adresswahl__knopf:hover,
.gutscheinwahl__knopf:hover { border-color: var(--accent); }
.adresswahl__knopf.is-gewaehlt,
.gutscheinwahl__knopf.is-gewaehlt {
    border-color: var(--accent);
    background: color-mix(in oklab, var(--accent) 12%, var(--surface));
    color: var(--accent-ink);
}
.adresswahl__knopf.is-gewaehlt small,
.gutscheinwahl__knopf.is-gewaehlt small { color: var(--accent-ink); }
.adresswahl__knopf:focus-visible,
.gutscheinwahl__knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* «In meinem Konto speichern» — ein echtes Kästchen mit seinem Satz, keine Fläche. */
.cartcheck { margin: 0 0 var(--s-3); font-size: var(--fs-1); }
.cartcheck label { display: inline-flex; align-items: flex-start; gap: var(--s-2); cursor: pointer; }
.cartcheck input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--accent); flex: 0 0 auto; }

/* Der Weg ins Konto über den Kontaktfeldern, leise: ein Angebot, keine Hürde. */
.cartkonto { margin: 0 0 var(--s-3); font-size: var(--fs-0); color: var(--muted); }

/* Was «Nochmal bestellen» in den Korb gelegt hat — dieselbe Einfassung wie der Annahmestopp,
   aber mit der Farbe für «fertig, komm» statt der für «halt». */
.cartdrawer__nochmal {
    margin: var(--s-4) 0 0;
    border: 1px solid var(--line);
    border-left: 4px solid var(--enamel);
    border-radius: var(--r-md);
    padding: var(--s-3) var(--s-4);
    font-size: var(--fs-1);
    line-height: 1.45;
    color: var(--text);
}

/* Was für die getippte Postleitzahl gilt, und darunter die Gebiete des Hauses als leise Liste
   mit Haarlinien. Die Gebühr und der Mindestwert stehen da, BEVOR jemand tippt (PAngV). */
.liefergebiete__stand { margin: 0 0 var(--s-3); font-size: var(--fs-1); }
.liefergebiete__stand:empty { display: none; }
.liefergebiete__stand.is-fehlt { color: var(--wine); }
.liefergebiete { margin: 0; }
.liefergebiete__titel { margin: 0 0 var(--s-1); font-size: var(--fs-0); font-weight: 600; color: var(--muted); }
.liefergebiete__liste { list-style: none; margin: 0; padding: 0; font-size: var(--fs-0); color: var(--muted); }
.liefergebiete__liste li { display: flex; flex-wrap: wrap; gap: 2px 12px; padding: 6px 0; border-top: 1px solid var(--line-soft); font-variant-numeric: tabular-nums; }
.liefergebiete__liste li:first-child { border-top: 0; }
.liefergebiete__liste b { min-width: 3.6em; color: var(--text); font-weight: 600; }
/* Auf `/bestellen` ohne Skript: die Wahl über der Zeit, die Adresse darunter — und bei einer
   Abholung verschwindet die Adresse, ganz ohne JavaScript. */
.abholband__art { margin: 0 0 var(--s-3); }
.lieferfelder { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line-soft); }
.lieferfelder .liefergebiete { margin-top: var(--s-2); }
.lieferfelder > .abholband__hinweis { margin-bottom: var(--s-3); }
.abholband:has(input[name="art"][value="abholung"]:checked) .lieferfelder { display: none; }
/* Und umgekehrt: bei einer Lieferung sagen «Abholung im Haus» und der Satz zur Abholzeit nichts
   mehr — die Lieferfelder tragen ihren eigenen Satz zur Uhrzeit. */
.abholband:has(input[name="art"][value="lieferung"]:checked) > .abholband__was,
.abholband:has(input[name="art"][value="lieferung"]:checked) > .abholband__hinweis { display: none; }

/* Die Abschlussleiste: festgeklebt am Fuss, mit Kante und nach oben fallendem Schatten, der sie
   von der scrollenden Liste abhebt. Der iPhone-Sicherheitsrand wird unten mitgerechnet, damit der
   Knopf nicht unter dem Systembalken sitzt. `[hidden]` (global `!important`) blendet die ganze
   Leiste aus, solange der Korb leer ist. */
.cartdrawer__foot {
    /* Nicht mehr als die halbe Höhe des BILDSCHIRMS (Prozent der Blatthöhe gäbe es hier nicht: das Blatt
       hat nur eine Höchsthöhe), und scrollbar, wenn der Bildschirm so niedrig ist (Querformat): die
       Liste darüber behält immer ihren Teil, statt von der Leiste verdrängt zu werden. */
    flex: 0 0 auto; max-height: 50vh; max-height: 50dvh; overflow-y: auto; overscroll-behavior: contain;
    display: grid; gap: var(--s-2);
    padding: var(--s-3) var(--s-5);
    padding-bottom: calc(var(--s-3) + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--line);
    background: color-mix(in oklab, var(--gold) 4%, var(--surface));
    box-shadow: 0 -12px 30px rgba(0, 0, 0, .10);
}

/* Der Absendeknopf über die volle Breite — die Haupthandlung des Blattes. Erbt Grund, Schrift
   und Glanz von `.btn--primary`, also die Markenfarbe des Hauses. */
.cartdrawer__send {
    width: 100%; justify-content: center;
    padding: 15px 20px; border-radius: var(--r-md);
    font-size: var(--fs-2); font-weight: 600; letter-spacing: .01em;
}

/* Ein sanftes Auffahren des Blattes, der Hintergrund blendet auf. Auf Breitschirmen steht der
   Dialog mittig und blendet nur auf, statt hochzufahren. Bewegungsarm wird beides still. */
@keyframes cartdrawer-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cartdrawer-rise { from { transform: translateY(8%); } to { transform: translateY(0); } }
.cartdrawer:not([hidden]) { animation: cartdrawer-fade .2s ease both; }
.cartdrawer:not([hidden]) .cartdrawer__panel { animation: cartdrawer-rise .28s cubic-bezier(.22, .61, .36, 1) both; }
@media (min-width: 700px) {
    .cartdrawer__grip { display: none; }
    .cartdrawer:not([hidden]) .cartdrawer__panel { animation-name: cartdrawer-fade; }
}
@media (prefers-reduced-motion: reduce) {
    .cartdrawer:not([hidden]),
    .cartdrawer:not([hidden]) .cartdrawer__panel { animation: none; }
}

/* The page behind a modal must not scroll under the thumb. Beide Blätter — Warenkorb und
   Store-Details — teilen sich die Sperre. */
.cart-open, .cart-open body,
.sheet-open, .sheet-open body { overflow: hidden; }

/* ---------- Store-Details: Auslöser im Ladenkopf + Inhalt der Schublade ----------
   Die Schublade selbst trägt die `.cartdrawer`-Hülle (Rücken, Blatt, Kopf, Schliessen); hier
   steht nur, was ihr eigen ist. */
.ladenkopf__info {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px;
    min-height: 44px; padding: 0 14px;
    border: 1px solid var(--line); border-radius: var(--r-btn);
    background: var(--surface); color: var(--muted);
    font: inherit; font-size: var(--fs-1); cursor: pointer;
    transition: border-color var(--t-fast), color var(--t-fast);
}
.ladenkopf__info:hover { border-color: var(--accent); color: var(--accent-ink); }
.ladenkopf__info:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ladenkopf__info svg { width: 18px; height: 18px; flex: 0 0 auto; }

.storedetails__block { margin: 0 0 var(--s-5); }
.storedetails__block:last-child { margin-bottom: 0; }
.storedetails__h {
    display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2);
    margin: 0 0 var(--s-3); font-family: var(--serif); font-size: var(--fs-3);
}
.storedetails__addr { font-style: normal; color: var(--text); line-height: 1.55; font-size: var(--fs-2); }
.storedetails__maps {
    display: inline-flex; align-items: center; gap: 7px; margin-top: var(--s-3);
    color: var(--accent-ink); font-weight: 600; text-decoration: none;
}
.storedetails__maps svg { width: 18px; height: 18px; flex: 0 0 auto; }
.storedetails__maps:hover { text-decoration: underline; }
.storedetails__hint { margin: var(--s-2) 0 0; font-size: var(--fs-0); color: var(--muted); }
.storedetails__kontakt { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.storedetails__kontakt li { display: flex; align-items: center; gap: var(--s-3); }
.storedetails__kontakt svg { width: 19px; height: 19px; flex: 0 0 auto; color: var(--gold-ink); }
.storedetails__kontakt a { color: var(--text); text-decoration: none; }
.storedetails__kontakt a:hover { color: var(--accent-ink); text-decoration: underline; }
/* Die Zeitenliste im Blatt trägt keinen eigenen Rahmen — der Kopf trennt sie schon ab. */
.storedetails .hours-list { margin: 0; }

@media (max-width: 560px) {
    /* Auf dem Telefon schrumpft der Auslöser auf sein Symbol, wie der Hörer-Knopf daneben. */
    .ladenkopf__infotext { display: none; }
    .ladenkopf__info { padding: 0; min-width: 44px; justify-content: center; }
}


/* ============================================================
   LAYOUT: KONTOR — the second architecture.

   NOT A SECOND SET OF TEMPLATES. Everything below re-shapes the SAME markup the photographic
   layout renders, hung off one class on <body>. That is the whole reason this can exist: the
   version of this product that forked the templates per variation produced nine markup trees,
   the least-visited drifted first, and no section could be improved without checking the other
   eight. Here a section written tomorrow appears in both layouts because there is only one
   place it can be written.

   WHAT CHANGES, and none of it is colour or type — those stay the theme's job, and all three
   themes (Abend, Tafel, Markt) work with this layout exactly as they do with the other:

     · the masthead: name centred over a rule, navigation as a second row of small capitals
     · the opening: no full-bleed photograph anywhere. A stated plate with the photograph as an
       inset beside it, and the three specialised photo heroes brought onto paper too
     · the rhythm: hairlines and a left-hand label instead of alternating background bands
     · a dish: a ruled line with the price at the right margin, not a card with a photograph
     · the footer: paper rather than near-black
     · typography: sized headings, German hyphenation, balanced heading lines

   WHO IT IS FOR: the house whose photographs are its weakest asset. Measured across the
   restaurants onboarded so far that is most of them, and leading with a poor photograph of an
   empty dining room at eleven in the morning makes a good kitchen look worse than it is.

   ⛔ WHAT THIS BLOCK DELIBERATELY DOES NOT TOUCH, each for a reason written where it lives:
      the photo scrim arithmetic (`.cater-hero__scrim`, `.gal-hero__scrim` — the alpha floors
      that guarantee 4.5:1 over the worst photograph a customer can upload), `[hidden]` and its
      `!important` (the allergen filter; any `display` this block adds to `.mdish`/`.mcat` is
      the exact selector shape that once made ten hidden dishes stay on screen), the touch-target
      block, `.dishcard__photo.ph-tile { display: flex }`, `.legal-missing`, and the German
      wrap guards on headings.
   ============================================================ */

/* -- Masthead -------------------------------------------------------------- */
/* Two centred rows: the house's name, a rule, then the navigation as small capitals — the
   arrangement a printed Speisekarte has used for a century, and the one that survives a long
   German restaurant name without a burger menu.

   NOT STICKY, and that removes a whole class of problem rather than solving it. A two-row
   masthead that follows the reader down the page costs 96–184px of screen, and every sticky
   header on this site is coupled to `scroll-margin-top` values keyed to ITS height (:654, :663,
   :686). A printed card does not follow you; the phone already has the fixed bottom bar. */
/* ==========================================================================
   Startseiten-Bänder — die drei Komponenten, die dieses Stylesheet gelöscht
   hatte, und warum sie zurückkommen dürfen.

   Die Löschnotizen weiter oben (`.scenery-band`, `.section--photo`,
   `.map-card`) sagen dreimal dasselbe: es gab keinen Ort, an dem ein
   Restaurant sein eigenes Bild und seinen eigenen Satz hätte hinterlegen
   können, also hätten zwanzig Häuser denselben leeren Rahmen gerendert. Der
   Einwand war richtig. `App\Site\HomeBands` ist die fehlende Hälfte davon —
   pro Restaurant, im Panel unter «Startseite» zu füllen.

   Was NICHT zurückkommt, und das ist keine Nachlässigkeit:

     · `.section--photo` mit `style="--bg:url(…)"`. `--bg` ist der semantische
       Name des Seitenhintergrunds; ein Band, das ihn auf ein Foto setzt,
       vererbt dieses Foto in jede Karte darin. Die Fotobänder unten tragen
       ein echtes <img> plus Verlauf — wie `.gal-hero` es längst tut. Damit
       gibt es auch alt-Text und loading="lazy", die ein Hintergrundbild nicht
       haben kann.

     · `.home-intern`. Eine Mitarbeitertür auf der Startseite bleibt gelöscht.

     · Vier Stadtseiten in der Fußzeile. Diese Plattform hat genau EINE Stadt
       pro Restaurant (PublicController::localPage) — vier fast gleiche Seiten
       sind eine Doorway-Farm, und der Verzicht ist eine Entscheidung.
   ========================================================================== */

/* -- Fotoband (Herkunft, Vegan) -------------------------------------------- */
/* Ein Band mit Bild, Zeile, Überschrift und Text. Ohne Bild bleibt es ein
   ruhiges dunkles Band und sieht immer noch fertig aus — ein Restaurant ohne
   Landschaftsfoto soll keine leere Fläche bekommen. */
.band-photo {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: clamp(340px, 52vh, 480px);
    padding: clamp(34px, 6vw, 66px) 0;
    color: var(--on-dark, #FBF8F2);
    background: #1c1610;
}
.band-photo__img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; object-position: center;
    z-index: -2;
}
/* Zwei Verläufe, nicht einer: der waagerechte trägt die Schrift links, der
   senkrechte hält die Unterkante dunkel, wo das nächste Band anschließt. Bei
   einem einzigen Verlauf steht heller Text auf hellem Himmel, sobald jemand
   ein Foto mit Wolken hochlädt. */
.band-photo__scrim {
    position: absolute; inset: 0; z-index: -1; pointer-events: none;
    background:
        linear-gradient(90deg, rgba(18, 12, 7, .82) 0%, rgba(18, 12, 7, .54) 44%, rgba(18, 12, 7, .16) 76%, rgba(18, 12, 7, .04) 100%),
        linear-gradient(0deg, rgba(18, 12, 7, .74) 0%, rgba(18, 12, 7, .26) 38%, rgba(18, 12, 7, 0) 64%);
}
.band-photo__inner { max-width: 600px; }
.band-photo__title { color: #FBF8F2; margin: .14em 0 .32em; text-shadow: 0 2px 22px rgba(0, 0, 0, .42); }
.band-photo__text {
    color: rgba(251, 248, 242, .94);
    font-size: clamp(1.02rem, 2.1vw, 1.2rem);
    line-height: 1.55; max-width: 40em;
    text-shadow: 0 1px 12px rgba(0, 0, 0, .40);
}
.band-photo .eyebrow { color: #F1D79E; text-shadow: 0 1px 10px rgba(0, 0, 0, .45); }
.band-photo .btn--ghost { color: #fff; border-color: rgba(255, 255, 255, .6); }
.band-photo .btn--ghost:hover { color: #fff; border-color: #fff; background: rgba(255, 255, 255, .14); }
/* Das Zitat im Vegan-Band steht rechts neben dem Text, nicht darunter — sonst
   ist das Band auf dem Desktop eine sehr lange schmale Spalte. */
.band-photo__quote {
    font-family: var(--serif); font-style: italic;
    font-size: clamp(1.15rem, 2.4vw, 1.45rem); line-height: 1.4;
    color: rgba(251, 248, 242, .92); max-width: 18em;
    text-shadow: 0 1px 12px rgba(0, 0, 0, .4);
}
@media (min-width: 861px) {
    .band-photo--split .band-photo__inner { max-width: none; }
    .band-photo--split .split { align-items: end; }
}

/* -- Kartenkarte ----------------------------------------------------------- */
/* Ein STANDBILD hinter einem Link, nie ein eingebetteter Kartendienst: eine
   Einbettung wäre eine Fremdanfrage bei jedem Seitenaufruf, sie beendet das
   cookiefreie Versprechen und macht die gedruckte Datenschutzerklärung falsch.
   Das Bild lädt das Restaurant selbst hoch. */
.map-card {
    position: relative; display: block; margin-top: 36px;
    border-radius: var(--r); overflow: hidden;
    box-shadow: var(--shadow); border: 1px solid var(--line-soft);
    text-decoration: none;
}
.map-card__img { width: 100%; height: auto; display: block; aspect-ratio: 2 / 1; object-fit: cover; }
.map-card__overlay {
    position: absolute; left: 0; right: 0; bottom: 0;
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 12px; padding: 16px 18px;
    background: linear-gradient(0deg, rgba(19, 12, 7, .86), rgba(19, 12, 7, .12) 70%, transparent);
    color: #fff;
}
.map-card__addr { font-family: var(--serif); font-size: 1.08rem; }
.map-card__btn {
    flex: 0 0 auto; font-weight: 600; font-size: .9rem;
    background: var(--accent); color: var(--on-accent);
    padding: 9px 17px; border-radius: 999px;
    transition: background var(--t-fast);
}
.map-card:hover .map-card__btn { background: var(--accent-strong); }
.map-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.map-attrib { font-size: .74rem; color: var(--muted); margin: 10px 0 0; }


/* ============================================================
   DER LADEN — /bestellen

   ⛔ WAS HIER VORHER STAND: eine Bestellzeile, drei Rasterspalten, eine Trennlinie darunter.
      Gemessen am Laborrestaurant 81 solcher Zeilen in 15 Rubriken, ohne Bild, ohne Beschreibung,
      ohne Weg hindurch. Daneben lag die Seite eines Wettbewerbers, die aussieht wie ein Laden,
      und der Unterschied war nicht Geschmack: unsere Seite war eine PREISLISTE, und eine
      Preisliste verkauft nichts.

   ⚠️ EIN MARKUP-BAUM FÜR ALLE BREITEN (D-30). Es gibt keine zweite Vorlage fürs Telefon und
      keine zweite Rubrikenleiste. Die Seitenleiste ist unter 861px `display: contents` — ihre
      Kinder rutschen damit ins Raster, und die Rubrikenleiste klebt am oberen Rand statt in
      einem hundert Pixel hohen Kasten festzustecken. Darüber ist dieselbe Leiste die senkrechte
      Liste in einer klebenden Spalte.

   ⚠️ ALLE ABSTÄNDE, RUNDUNGEN UND SCHATTEN AUS DER LEITER in tokens.css. In diesem Block steht
      keine rohe Pixelzahl ausser den Trefferflächen (44px, WCAG 2.5.5) und den Bildkanten, die
      eine Rastergrösse sind und keine Abstandsentscheidung.
   ============================================================ */

/*
 * EINE ZAHL FÜR DREI DINGE, damit sie nicht auseinanderlaufen können: die Mindesthöhe des
 * Ladenkopfs, der Abstand, um den die Rubrikenleiste darunter klebt, und der `scroll-margin-top`
 * jedes Sprungziels. Stünde die Höhe dreimal da, verschwände beim nächsten Umbau eine
 * Rubriküberschrift unter der Leiste — und zwar nur auf einer der beiden Breiten.
 */
.page-laden {
    --ladenkopf-h: 58px;
    /* Telefon: Ladenkopf + klebende Rubrikenleiste. */
    --laden-sprung: calc(var(--ladenkopf-h) + 56px);
}

/*
 * ⛔ ZWEI KLEBENDE LEISTEN BEI `top: 0`, UND DIE UNTERE WAR UNSICHTBAR.
 *
 *    `.site-header` klebt mit z-index 40 und einem zu 88 % deckenden Grund; `.catbar` klebt
 *    ebenfalls bei `top: 0`, mit z-index 35. Die Rubrikenleiste lag also hinter dem Seitenkopf.
 *    Die Speisekarte hat für genau das `.page-menu .site-header { position: static }` — auf
 *    `/bestellen` fehlte die Klasse, weil die Leiste dort erst gestern dazukam.
 *
 *    Hier kommt der zweite Grund dazu: der Ladenkopf trägt Marke, Öffnungsstatus und
 *    Telefonnummer. Der Seitenkopf sagte daneben dasselbe ein zweites Mal.
 */
.page-laden .site-header { position: static; }

@media (min-width: 861px) {
    .page-laden {
        --ladenkopf-h: 74px;
        /* Auf dem Desktop klebt nur der Ladenkopf: die Rubriken stehen in der Seitenspalte. */
        --laden-sprung: calc(var(--ladenkopf-h) + var(--s-4));
    }
}

/* -- Der Ladenkopf ---------------------------------------------------------- */
.ladenkopf {
    position: sticky; top: 0; z-index: 40;
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    -webkit-backdrop-filter: saturate(1.3) blur(10px);
            backdrop-filter: saturate(1.3) blur(10px);
    border-bottom: 1px solid var(--line-soft);
}
.ladenkopf__inner {
    display: flex; align-items: center; gap: var(--s-3);
    min-height: var(--ladenkopf-h);
    padding-top: var(--s-2); padding-bottom: var(--s-2);
}
/* Dieselbe Regel wie bei `.brand__mark`: die Höhe gibt das Mass, die Breite folgt dem Bild. */
.ladenkopf__mark {
    height: 40px; width: auto; max-width: 150px; object-fit: contain; flex: 0 0 auto;
    background: none; padding: 0; border-radius: 0; box-shadow: none;
}
.ladenkopf__wer { flex: 1 1 auto; min-width: 0; }

/* ⛔ `.ladenkopf__name` ALLEIN REICHT NICHT, UND «GLEICHE SPEZIFITÄT, SPÄTERE QUELLE» AUCH NICHT.
      `.layout-kontor h1` ist (0,2,0) und schlägt eine einzelne Klasse; im Kontor-Aufbau wäre der
      Name hier 2,8rem gross und die Leiste doppelt so hoch, wie ihr eigenes Token behauptet —
      und damit zeigte jedes Sprungziel unter die Leiste.

      Der erste Entwurf löste das mit zwei Klassen und der Quellreihenfolge. Das hielt genau so
      lange, bis dieser Block VOR den Kontor-Block musste (`LayoutKontorTest` liest alles hinter
      der ersten `.layout-kontor`-Regel als dessen Block und verlangt, dass jede Regel darin
      gebunden ist). Eine Zusage, die von der Reihenfolge im File abhängt, ist keine — drei
      Klassen gewinnen, wo die Datei auch steht. */
.page-laden .ladenkopf .ladenkopf__name {
    margin: 0; font-size: var(--fs-3); line-height: 1.15; letter-spacing: 0;
    /* Bricht der Name um, wächst die Leiste über `--ladenkopf-h` hinaus — und dann zeigen alle
       Sprungziele auf eine Stelle, die unter ihr liegt. Ein langer Hausname darf die
       Rubrikenleiste nicht verschieben. */
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ladenkopf__meta {
    margin: 1px 0 0; font-family: var(--sans); font-size: var(--fs-0);
    color: var(--muted); line-height: 1.35;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ladenkopf__punkt { margin: 0 .4em; opacity: .55; }
.ladenkopf__abholung { color: var(--text); font-weight: 600; }

/* «· öffnet um 17:00» hinter «Gerade geschlossen» — die Auskunft, die aus einer Absage eine
   Verabredung macht. Ruhige Tinte: die Farbe gehört dem Zustand davor, nicht der Uhrzeit. */
.ladenkopf__auf { color: var(--muted); font-weight: 500; }

/* DIE FARBE TRÄGT DIE AUSSAGE NICHT ALLEIN. «Jetzt geöffnet» und «Gerade geschlossen» sagen es
   im Text; grün und weinrot sind die Verstärkung, nicht die Nachricht. Ein rotgrünblinder Gast
   erführe sonst nichts. `--enamel` ist die Farbe, mit der dieses Blatt seit jeher «ja» sagt
   (vegan, offen heute in der Zeitenliste), `--wine` die für die Gegenrichtung. */
.ladenstatus { font-weight: 700; }
.ladenstatus--offen { color: var(--enamel); }
.ladenstatus--zu { color: var(--wine); }

.ladenkopf__tel {
    flex: 0 0 auto; min-height: 44px;
    padding: var(--s-2) var(--s-4); border-radius: var(--r-tag);
}
.ladenkopf__tel svg { flex: 0 0 auto; }

@media (max-width: 560px) {
    /* Auf 375px muss die Zeile den Status tragen; die Adresse steht im Fussbereich und auf der
       Startseite und ist hier die entbehrlichere Hälfte. Die Ziffern der Telefonnummer ebenso:
       niemand tippt sie ab, `tel:` wählt. Der runde Hörer bleibt eine 44px-Trefferfläche. */
    .ladenkopf__ort, .ladenkopf__ort + .ladenkopf__punkt { display: none; }
    .ladenkopf__telnr { display: none; }
    .ladenkopf__tel { min-width: 44px; padding: 0; }
}

/* -- Das Band, der Fehlerkasten, die Hausnotiz ------------------------------ */
.laden { padding-bottom: var(--s-7); }

/* Das Foto des Hauses, aus `--hero-photo` — dieselbe Datei, die die Speisekarte schon geladen
   hat, also keine zweite Anfrage. Flach gedeckelt: das Vorbild nimmt hier eine halbe
   Bildschirmhöhe, und die zwei Abholfelder darunter sind die gemessen wichtigste Zeile. */
.ladenbanner {
    margin-top: var(--s-4);
    aspect-ratio: 21 / 7; max-height: 240px;
    border-radius: var(--r);
    background: var(--hero-photo, none) center 55% / cover no-repeat, var(--plate);
    box-shadow: var(--shadow-sm);
}

.ladenmeldung {
    margin-top: var(--s-4);
    border: 1px solid color-mix(in oklab, var(--wine) 34%, var(--line));
    border-left-width: 4px;
    border-radius: var(--r-md);
    background: color-mix(in oklab, var(--wine) 6%, var(--surface));
    padding: var(--s-3) var(--s-4);
}
.ladenmeldung p { margin: 0; }
.ladennotiz { margin-top: var(--s-4); color: var(--muted); font-size: var(--fs-1); }

/* -- Die Abholzeile --------------------------------------------------------- */
/* Sie sieht aus wie ein Band und ist trotzdem nur eine Formularzeile — dieselben zwei Felder,
   die vorher bei 95 % der Seite standen. Der Rahmen macht aus zwei verirrten Feldern über dem
   Essen eine AUSKUNFT: wo, und wann kann ich es holen. */
/* SCHLANK: eine Zeile «wo & wie lange», darunter eine Zeile «wie». Früher ein hohes Feld mit
   zwei Absätzen; jetzt ein flaches Band, das den Blick nicht vom Kopf zur Karte aufhält. */
.abholband {
    margin: var(--s-4) 0 var(--s-5);
    background: var(--surface);
    border: 1px solid var(--line-soft);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    padding: var(--s-3) var(--s-4);
}
.abholband__was {
    display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-1) var(--s-2);
    margin: 0; font-size: var(--fs-1); color: var(--muted);
}
.abholband__was b { color: var(--text); }
.abholband__ic { width: 18px; height: 18px; flex: 0 0 auto; color: var(--gold-ink); }
.abholband__punkt { margin: 0 .15em; opacity: .5; }
.abholband__hinweis { margin: var(--s-2) 0 0; font-size: var(--fs-0); color: var(--muted); }
.abholband__hinweis b { color: var(--text); }

/* Der Rahmen sitzt jetzt eine Ebene höher, am Band. Was diese Klasse noch tut, ist der Abstand
   zwischen den beiden Feldern — und die Randlosigkeit darunter, damit das Band nicht unten
   auseinanderfällt. */
.resform__row--wann { gap: var(--s-3); }
.resform__row--wann .resform__field { margin-bottom: 0; }

/* -- «Am beliebtesten» ------------------------------------------------------ */
/*
 * ⚠️ KEINE PFEILKNÖPFE, UND DAS IST BESSER ALS DIE VORLAGE. Sie bräuchten ein Skript, also
 *    müssten sie ohne Skript versteckt sein — und über 861px steht der ganze Streifen ohnehin
 *    auf einmal da, es gäbe also nichts zu blättern. Auf dem Telefon wischt man. Ein Knopf, der
 *    entweder unsichtbar oder überflüssig ist, ist kein Knopf.
 */
.beliebt { padding: 0; margin: 0 0 var(--s-6); }
.beliebt__kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-3); margin-bottom: var(--s-3); }
.page-laden .beliebt .beliebt__titel { margin: 0; font-size: var(--fs-4); }
.beliebt__quelle { margin: 0; font-size: var(--fs-0); color: var(--muted); }

.beliebt__spur {
    list-style: none; margin: 0; padding: 0 0 var(--s-3);
    display: grid; grid-auto-flow: column; grid-auto-columns: 44%;
    gap: var(--s-3);
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.beliebt__spur::-webkit-scrollbar { height: 0; }

.beliebtkarte { min-width: 0; scroll-snap-align: start; }
.beliebtkarte__link { display: block; text-decoration: none; color: var(--text); }
.beliebtkarte__bild { position: relative; display: block; }
.beliebtkarte__foto {
    width: 100%; aspect-ratio: 1 / 1; object-fit: cover;
    border-radius: var(--r-md); box-shadow: var(--shadow-sm);
    transition: box-shadow var(--t-fast);
}
.beliebtkarte__foto.ph-tile .ph-tile__mono { font-size: 2.6rem; }
/*
 * DIE ZAHL IST DIE BEHAUPTUNG, und sie ist gezählt: `Menu::mostOrderedDishes()` misst
 * Bestellungen der letzten dreissig Tage. Deshalb steht «#1» da und kein Pokal — eine
 * Auszeichnung behauptet ein Urteil, eine Rangzahl behauptet eine Zählung.
 */
.beliebtkarte__rang {
    position: absolute; left: var(--s-2); top: var(--s-2);
    font-family: var(--sans); font-size: var(--fs-0); font-weight: 700;
    background: color-mix(in oklab, var(--surface) 92%, transparent);
    color: var(--gold-ink);
    padding: 2px var(--s-2); border-radius: var(--r-tag);
    box-shadow: var(--shadow-xs);
}
.beliebtkarte__name {
    display: block; margin-top: var(--s-2);
    font-weight: 600; font-size: var(--fs-1); line-height: 1.3;
    overflow-wrap: anywhere;
    transition: color var(--t-fast);
}
.beliebtkarte__fuss {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--s-2); margin: var(--s-1) 0 0; min-height: 44px;
}
.beliebtkarte__preis { font-family: var(--serif); font-weight: 600; color: var(--accent-ink); }

/* Die Listenform des Streifens — wenn nicht jedes Gericht ein Foto hat. Rang, Name, Preis in
   einer Zeile; die Zeile ist der Verweis auf das Gericht weiter unten. Kein Bild, kein
   Monogramm: eine Liste ohne Bühne ist ehrlicher als eine Bühne ohne Bild. */
.beliebt__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.beliebtzeile { margin: 0; }
.beliebtzeile__link {
    display: grid; grid-template-columns: 1.6rem 1fr auto; align-items: baseline; gap: var(--s-2);
    padding: 10px 12px; border-radius: var(--r-sm); background: var(--surface);
    color: var(--text); text-decoration: none; min-height: 44px;
}
.beliebtzeile__link:hover { background: var(--line-soft); }
.beliebtzeile__rang { font-size: var(--fs-0); font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.beliebtzeile__name { font-weight: 500; }
.beliebtzeile__preis { font-weight: 600; color: var(--accent-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }

.beliebtkarte__plus {
    display: inline-flex; align-items: center; justify-content: center; gap: 3px;
    min-width: 44px; min-height: 44px; padding: 0 var(--s-2); flex: 0 0 auto;
    border: 1px solid var(--accent); border-radius: var(--r-tag);
    background: var(--accent); color: var(--on-accent); cursor: pointer;
    font: inherit; font-size: var(--fs-4); line-height: 1;
    font-variant-numeric: tabular-nums;
    box-shadow: var(--shadow-xs);
    transition: background var(--t-fast), box-shadow var(--t-fast);
}
.beliebtkarte__plus:hover { background: var(--accent-strong); box-shadow: var(--shadow-sm); }
/* DERSELBE ENGE FOKUSRING WIE AM MENGENFELD (`.orderline__qty`). Der globale `:focus-visible`
   (site.css :58) versetzt den Rand um 3px und legt einen 5px-Hof darum — richtig für ein Feld
   mit Luft ringsum, zu viel für einen 44px-Knopf in einem gedrängten Kartenfuss. Versatz 1px
   hält den Ring am Knopf. Beide «+» der Seite fokussieren damit gleich. */
.beliebtkarte__plus:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.beliebtkarte__zahl { font-size: var(--fs-1); font-weight: 700; }
.beliebtkarte__zahl:empty { display: none; }

/* ⛔ DIE EINZIGE KARTE DER SEITE, DIE AUF DEN ZEIGER NICHT ANTWORTETE. Die ganze Kachel ist ein
      Link, und Hover tat nichts — während die Gerichtkarte darunter sich längst hebt. Foto steigt
      eine Schattenstufe (`--shadow-md`, über der Ruhe-Stufe `--shadow-sm`), der Name nimmt den
      Akzent an. Dasselbe Vokabular wie bei `.orderline:hover`, nur ohne Rahmen: der Streifen hat
      keinen, seine Karten sind Bild und Wort. In beiden Modi getragen — `--accent`/`--shadow-md`
      sind Tokens, keine festen Farben. */
.beliebtkarte__link:hover .beliebtkarte__foto { box-shadow: var(--shadow-md); }
.beliebtkarte__link:hover .beliebtkarte__name { color: var(--accent-ink); }

@media (min-width: 861px) {
    /*
     * ⛔ ZURÜCK ZUM RASTER — ABER OHNE DEN FEHLER, DER ES DAMALS ZURÜCKGENOMMEN HAT.
     *
     *    Der 178px-Streifen von einst löste das «zu gross», schuf aber am Screenshot ein neues,
     *    gemessenes Problem: auf dem Desktop, wo ohnehin alle vier Karten ins Bild passen, klebten
     *    sie schmal am linken Rand, rechts blieb die halbe Breite leer, und jede Karte war ein
     *    schmales hohes Rechteck mit verrutschtem Preis. Ein waagerechter Scroll-Streifen ist auf
     *    dem Telefon richtig (dort wischt man) und auf dem Desktop verschenkte Fläche.
     *
     * ⚠️ DER BETREIBER WILL HIER EIN GLEICHMÄSSIGES RASTER. `repeat(4, 1fr)` verteilt die (auf VIER
     *    gedeckelten — `mostOrderedDishes(4)`) Karten über die volle Breite; sind es einmal weniger
     *    als vier, sitzen sie in den ersten Spalten statt schmal am Rand zu kleben. `grid-auto-flow:
     *    row` und `overflow-x: visible` heben den Streifen-Grundzustand (Spaltenfluss, Scroll) auf.
     *
     * ⛔ UND DAMIT NICHT WIEDER DAS MENÜ UNTER DEN FALZ RUTSCHT — GENAU DER GRUND DES DAMALIGEN
     *    RÜCKZUGS: das quadratische Foto war die Ursache, bei rund 249px Kartenbreite (Inhalt von
     *    `--wrap` 1080px, vier Spalten) wurde es 249px hoch. Auf dem Desktop bekommt es darum ein
     *    flacheres Seitenverhältnis (4:3 ≈ 187px statt 249px), und die Karte liest sich als Karte,
     *    nicht als Turm. Unter 861px bleibt das Quadrat (1:1) und der Scroll-Streifen (Telefon).
     *
     * ⚠️ NAME + PREIS SITZEN SAUBER: die Karte wird eine senkrechte Flex-Spalte, der Fuss mit dem
     *    Preis rutscht per `margin-top: auto` an den unteren Rand. Weil die Rasterzellen einer Reihe
     *    gleich hoch sind, stehen die Preise über alle vier Karten auf einer Linie — auch wenn ein
     *    Gerichtname zwei Zeilen braucht und der nächste eine.
     */
    .beliebt__spur {
        grid-auto-flow: row;
        grid-template-columns: repeat(4, 1fr);
        overflow-x: visible;
    }
    .beliebtkarte { display: flex; flex-direction: column; }
    .beliebtkarte__fuss { margin-top: auto; }
    .beliebtkarte__foto { aspect-ratio: 4 / 3; }
}

/* -- Das Raster: links der Weg, rechts das Essen ---------------------------- */
.laden__raster { display: block; }

/*
 * ⛔ `position: sticky` IN EINEM KURZEN ELTERNTEIL KLEBT NICHT. Ein klebendes Element wird von
 *    der Box seines Elternteils begrenzt; steckte die Rubrikenleiste auf dem Telefon in einer
 *    Seitenspalte, die nach hundert Pixeln endet, wäre sie nach hundert Pixeln wieder weg —
 *    also genau dann, wenn man sie braucht.
 *
 *    `display: contents` löst die Spalte auf: ihre Kinder werden zu Kindern des Rasters, dessen
 *    Box die ganze Karte umfasst. EIN Markup-Baum, zwei Anordnungen, kein zweites Element.
 */
.laden__seite { display: contents; }

.ladensuche {
    display: flex; align-items: center; gap: var(--s-2);
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-tag); padding: 0 var(--s-3);
    margin-bottom: var(--s-3);
}
.ladensuche:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}
.ladensuche__ic { width: 18px; height: 18px; flex: 0 0 auto; color: var(--muted); }
.ladensuche__feld {
    flex: 1 1 auto; min-width: 0; min-height: 44px;
    border: 0; background: none; color: var(--text); font: inherit; font-size: var(--fs-1);
}
.ladensuche__feld:focus { outline: none; }
.ladensuche__feld::placeholder { color: var(--muted); }

/* Die Rubrikenleiste klebt UNTER dem Ladenkopf statt hinter ihm. */
.page-laden .catbar { top: var(--ladenkopf-h); }
.page-laden .mcat { padding: var(--s-5) 0 0; }
.page-laden .mcat,
.page-laden [id^="best-"],
.page-laden [id^="gericht-"],
/*
 * ⛔ DAS ABHOLBAND WURDE OBEN VOM KLEBENDEN LADENKOPF ANGESCHNITTEN. Es ist das erste Feld unter
 *    dem klebenden Kopf, und bislang stand es nicht in dieser Liste. Beim Absenden springt der
 *    Browser zum ersten leeren Pflichtfeld — `pickup_date`/`pickup_time` liegen GENAU hier —, und
 *    dessen Oberkante landete unter der Leiste: die Sprechblase «Bitte ausfüllen» zeigte auf etwas
 *    Verdecktes. Auch «Am beliebtesten» steht direkt unter dem Kopf und bekommt denselben Rand.
 *    Ein eigener `scroll-margin`-Rand am FELD, weil der Browser das Feld ins Bild holt, nicht das
 *    Band um es herum.
 */
.page-laden .beliebt,
.page-laden .abholband,
.page-laden .abholband input,
.page-laden .abschluss { scroll-margin-top: var(--laden-sprung); }

.laden__karte {
    /* Die Gerichtkarte fragt IHRE Spalte, nicht den Bildschirm. Bei 1280px steht sie in einer
       800px breiten Spalte und soll zweispaltig sein; auf einem 800px breiten Tablet ohne
       Seitenspalte gilt dieselbe Rechnung. Ein Breakpoint auf die Fensterbreite kennt den
       Unterschied nicht. */
    container-type: inline-size;
}
.mcat__laden { display: grid; grid-template-columns: 1fr; gap: var(--s-3); }

@container (min-width: 620px) {
    .mcat__laden { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/*
 * ⛔ DIE SPEISEKARTE-IM-LADEN WAR ZWEISPALTIG UND QUETSCHTE DEN NAMEN. `.mcat__grid` verteilt
 *    `minmax(340px, 1fr)` — in der Ladenspalte (kein Seitenrand unter 861px, darüber neben der
 *    232px-Leiste) ergab das bei ~800px Ansichtsbreite zwei ~370px-Karten. In einer so schmalen
 *    Karte frass der Führungspunkt-Streifen (`flex: 1 1 auto`) den freien Platz, der Name schrumpfte
 *    auf seine min-content-Breite (~100px) und `hyphens` trennte jede Zeile silbenweise:
 *    «Gebra-tene Au-bergi-nen mit Walnüs-sen».
 *
 * ⚠️ EINE SPALTE, WIE EINE GEDRUCKTE KARTE. Volle Zeilenbreite heisst positiver Freiraum: der
 *    Name steht auf EINER Zeile, die Führungspunkte dehnen sich bis zum Preis, der Preis steht
 *    bündig rechts. Kein Umbruch, keine Trennung. Nur die Laden-Ansicht (`.laden__karte`); die
 *    gewöhnliche Speisekarte ohne Bestellen behält ihr `.mcat__grid` unangetastet.
 */
.laden__karte .mcat__grid { grid-template-columns: 1fr; }

@media (min-width: 861px) {
    .laden__raster {
        display: grid; grid-template-columns: 232px minmax(0, 1fr);
        gap: var(--s-6); align-items: start;
    }
    .laden__seite {
        display: block;
        position: sticky; top: calc(var(--ladenkopf-h) + var(--s-4));
        /* Fünfzehn Rubriken sind länger als mancher Bildschirm hoch ist. */
        max-height: calc(100vh - var(--ladenkopf-h) - var(--s-6));
        overflow-y: auto; scrollbar-width: thin;
    }

    /* Dieselbe Leiste, senkrecht. Die waagerechte Fassung bringt Rahmen, Weichzeichner,
       Randverlauf und Grossbuchstaben mit — in einer Spalte ist davon nichts richtig. */
    .page-laden .laden__seite .catbar {
        position: static; background: none; border: 0;
        -webkit-backdrop-filter: none; backdrop-filter: none;
    }
    .page-laden .laden__seite .catbar__inner { display: block; }
    .page-laden .laden__seite .catnav {
        flex-direction: column; flex-wrap: nowrap; gap: 1px; padding: 0;
        overflow: visible; -webkit-mask-image: none; mask-image: none;
    }
    .page-laden .laden__seite .catbar__seam { display: none; }
    .page-laden .laden__seite a.chip--cat {
        display: block; padding: var(--s-2) var(--s-3);
        font-family: var(--sans); font-size: var(--fs-1); font-weight: 500;
        text-transform: none; letter-spacing: 0;
        border-radius: var(--r-sm); color: var(--muted);
        transition: background var(--t-fast), color var(--t-fast);
    }
    .page-laden .laden__seite a.chip--cat::after { display: none; }
    .page-laden .laden__seite a.chip--cat + a.chip--cat::before { display: none; }
    .page-laden .laden__seite a.chip--cat:hover {
        background: color-mix(in oklab, var(--accent) 7%, transparent); color: var(--text);
    }
    .page-laden .laden__seite a.chip--cat.is-active {
        background: color-mix(in oklab, var(--accent) 12%, transparent);
        color: var(--accent-ink); font-weight: 600;
    }
}

/* -- Die Gerichtkarte -------------------------------------------------------- */
/*
 * ⛔ HIER STAND EINE ZEILE MIT EINER TRENNLINIE DARUNTER, und das war die Preislisten-Optik.
 *
 * ⚠️ DAS BILD SPANNT ZWEI ZEILEN, die Menge steht in der zweiten. Die naheliegende Fassung —
 *    Bild, Text und Menge nebeneinander — kostet in einer zweispaltigen Karte 84 + 152 Pixel,
 *    und vom Gerichtnamen bleiben in einer 300px-Spalte etwa sechzig übrig. Die Menge unter den
 *    Text zu legen gibt dem Namen die ganze Breite und dem Daumen trotzdem jedes Mal dieselbe
 *    Ecke.
 */
.orderline {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "text" "opts" "menge";
    column-gap: var(--s-3); row-gap: var(--s-2);
    padding: var(--s-4);
    background: var(--surface);
    border: 1px solid var(--line-soft);
    border-radius: var(--r);
    box-shadow: var(--shadow-xs);
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.orderline:hover {
    border-color: color-mix(in oklab, var(--gold) 44%, var(--line-soft));
    box-shadow: var(--shadow-sm);
}
/* Tastaturfokus hebt die Karte GENAUSO wie der Zeiger. Vorher wechselte nur der Rand die Farbe
   und die Karte blieb flach, während `:hover` sie mit `--shadow-sm` anhob — wer die Seite mit der
   Tabulatortaste bedient, bekam das schwächere Signal. Jetzt dieselbe Erhebung; der Rand bleibt
   `--accent` statt des Gold-Tons vom Hover, weil Fokus die stärkere Aussage ist. */
.orderline:focus-within { border-color: var(--accent); box-shadow: var(--shadow-sm); }

.orderline--foto {
    grid-template-columns: 84px minmax(0, 1fr);
    grid-template-areas: "foto text" "foto opts" "foto menge";
}
.orderline__foto {
    grid-area: foto; align-self: start;
    width: 84px; height: 84px; object-fit: cover;
    border-radius: var(--r-md);
    box-shadow: var(--shadow-xs);
}
.orderline__text { grid-area: text; min-width: 0; }

/* DIE OPTIONEN DES GERICHTS (Faz C) — zwischen Name und Menge, damit der Gast wählt, BEVOR er
   die Anzahl setzt. Ruhig gehalten: es ist ein Formular, kein zweiter Blickfang neben dem Preis. */
.orderline__opts { grid-area: opts; display: flex; flex-direction: column; gap: var(--s-2); }
.optgrp { display: flex; flex-direction: column; gap: 5px; border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.optgrp__name { font-family: var(--sans); font-size: var(--fs-0); font-weight: 600; color: var(--muted); }
.optgrp__hint { font-weight: 400; }
.optgrp__select {
    font: inherit; font-size: var(--fs-0);
    padding: 8px 12px; max-width: 22rem;
    color: var(--text); background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--r-md);
}
.optgrp--single { gap: 4px; }
.optgrp--multi { gap: 6px; }
.optchk { display: inline-flex; align-items: center; gap: 9px; font-size: var(--fs-0); cursor: pointer; }
.optchk input { inline-size: 17px; block-size: 17px; accent-color: var(--accent); flex: 0 0 auto; }
.optchk__text { min-inline-size: 0; }
.orderline__opts .codes { margin-left: 4px; }

.orderline__label { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2); cursor: pointer; }
.orderline__name { font-weight: 600; font-size: var(--fs-2); line-height: 1.3; overflow-wrap: anywhere; }
.orderline__var { color: var(--muted); font-size: var(--fs-0); }
.orderline__price {
    display: block; margin-top: 2px;
    font-family: var(--serif); font-weight: 600; font-size: var(--fs-3);
    color: var(--accent-ink); font-variant-numeric: tabular-nums;
}
/* ZWEI ZEILEN, ABGESCHNITTEN. Vollständig gesetzt wächst eine Karte mit einem langen Absatz auf
   das Dreifache ihrer Nachbarin und das Raster wird zum Flickenteppich. Der ganze Text steht auf
   der Speisekarte; was das Gesetz verlangt, sind die Buchstaben darunter, und die sind
   vollständig. */
.orderline__desc {
    margin: var(--s-2) 0 0; color: var(--muted); font-size: var(--fs-1); line-height: 1.45;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    overflow-wrap: anywhere;
}
.orderline__text .codes { display: inline-block; margin-top: var(--s-2); }

.orderline__menge {
    grid-area: menge; justify-self: end;
    display: flex; align-items: center; gap: var(--s-1);
}
.orderline__step {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px; padding: 0; flex: 0 0 auto;
    border: 1px solid var(--line); border-radius: var(--r-tag);
    background: var(--bg); color: var(--text); cursor: pointer;
    font: inherit; font-size: var(--fs-4); line-height: 1;
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.orderline__step:hover { border-color: var(--accent); color: var(--accent-ink); }
/* DERSELBE ENGE FOKUSRING WIE AM MENGENFELD, und aus einem greifbaren Grund: der globale
   `:focus-visible` versetzt den Rand um 3px, im gedrängten Cluster «− [Zahl] +»
   (`.orderline__menge` gap `--s-1`, 4–6px) rückt er damit fast ans Nachbarfeld. Versatz 1px
   hält den Ring am Knopf — genau die Fassung, die `.orderline__qty` daneben schon trägt, damit
   der ganze Cluster gleich fokussiert. */
.orderline__step:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.orderline__step--plus {
    background: var(--accent); border-color: var(--accent); color: var(--on-accent);
    /* Der akzentgefüllte «+» ist die Haupthandlung der Zeile und trug als einziger seiner Art
       keinen Schatten — sein Zwilling im Streifen (`.beliebtkarte__plus`) hat `--shadow-xs` seit
       jeher. Gleiche Rolle, gleiche Erhebung. Der «−» daneben bleibt bewusst flach: er ist die
       Gegenhandlung und kein gefüllter Knopf. */
    box-shadow: var(--shadow-xs);
}
.orderline__step--plus:hover {
    background: var(--accent-strong); border-color: var(--accent-strong); color: var(--on-accent);
    box-shadow: var(--shadow-sm);
}

/* 44px hoch, weil es mit dem Daumen auf dem Bürgersteig getroffen wird — dieselbe Untergrenze
   wie bei der mobilen Leiste. `tabular-nums`, damit 1 und 11 die Feldbreite nicht verschieben. */
.orderline__qty {
    width: 62px; min-height: 44px; text-align: center; flex: 0 0 auto;
    font: inherit; font-variant-numeric: tabular-nums;
    border: 1px solid var(--line); border-radius: var(--r-sm);
    background: var(--bg); color: var(--text); padding: 6px 2px;
}
.orderline__qty:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* -- «In den Warenkorb» an der Gerichtzeile --------------------------------- */
/*
 * DERSELBE KNOPF WIE `.mdish__add` AUF DER SPEISEKARTE, nur schreibt er hier in das Mengenfeld
 * daneben statt in `localStorage` — auf `/bestellen` IST das Formular der Korb. Wie dort ist er
 * ohne Skript `display:none` (nicht `hidden`-Attribut), damit ein Browser ohne `cart.js` nie
 * einen Knopf sieht, der nichts täte; der Weg ist dann das Mengenfeld.
 *
 * ⚠️ ER UND DER STEPPER TAUSCHEN SICH AUS, statt beide dazustehen. Solange nichts gewählt ist
 *    (`:not(.is-gewaehlt)`), steht der «In den Warenkorb»-Knopf da und Feld + Stepper treten
 *    zurück; sobald `cart.js` beim ersten Antippen `is-gewaehlt` setzt, greift die Regel nicht
 *    mehr, der Knopf fällt auf seinen `display:none`-Grundzustand zurück und der Stepper-Cluster
 *    ist wieder da. Das ist dieselbe Umschaltung, die der Warenkorb der Speisekarte im Panel
 *    macht — hier an Ort und Stelle, weil `/bestellen` kein zweites Panel hat.
 */
.orderline__add { display: none; }
.has-cart .orderline:not(.is-gewaehlt) .orderline__add {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--s-1);
    min-height: 44px; padding: 0 var(--s-4); flex: 0 0 auto;
    border: 1px solid var(--accent); border-radius: var(--r-tag);
    background: var(--accent); color: var(--on-accent); cursor: pointer;
    font: inherit; font-size: var(--fs-1); font-weight: 600;
    box-shadow: var(--shadow-xs);
    transition: background var(--t-fast), box-shadow var(--t-fast);
}
.has-cart .orderline:not(.is-gewaehlt) .orderline__add:hover {
    background: var(--accent-strong); box-shadow: var(--shadow-sm);
}
/* DERSELBE ENGE FOKUSRING WIE AM «+» daneben (`.orderline__step--plus`): der globale
   `:focus-visible` versetzt den Rand um 3px und legt einen Hof darum — zu viel für einen Knopf
   im gedrängten Mengen-Cluster. Versatz 1px hält den Ring am Knopf. */
.has-cart .orderline:not(.is-gewaehlt) .orderline__add:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 1px;
}
.orderline__add-plus { font-size: 1.15em; line-height: 1; }

/* Solange nichts gewählt ist, tritt der Mengen-Cluster hinter den Knopf zurück. Ist etwas
   gewählt, greift die Regel nicht mehr und Feld + Stepper stehen wieder da (der Stepper hatte sein
   `hidden`-Attribut da bereits von `cart.js` verloren). */
.has-cart .orderline:not(.is-gewaehlt) .orderline__qty,
.has-cart .orderline:not(.is-gewaehlt) .orderline__step { display: none; }

/* -- Der Abschluss ---------------------------------------------------------- */
/* Hier hört das Aussuchen auf und fängt das Bestellen an, und der Wechsel darf zu sehen sein. */
.abschluss {
    margin-top: var(--s-7);
    background: var(--surface);
    border: 1px solid var(--line-soft);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
    padding: var(--s-5);
}
.page-laden .abschluss .abschluss__titel { margin: 0 0 var(--s-4); font-size: var(--fs-4); }
/* Die Felder liegen auf der Karte, also brauchen sie den Grund der SEITE, sonst verschwindet
   ihre Kante in der Fläche, auf der sie liegen. */
.abschluss .resform__field input,
.abschluss .resform__field textarea { background: var(--bg); }
.abschluss__recht { font-size: var(--fs-0); color: var(--muted); line-height: 1.55; }
.abschluss__senden { padding: var(--s-3) var(--s-6); font-size: var(--fs-2); min-height: 48px; }

@media (max-width: 560px) {
    .orderline { padding: var(--s-3); }
    .orderline--foto { grid-template-columns: 68px minmax(0, 1fr); }
    .orderline__foto { width: 68px; height: 68px; }
    .abschluss { padding: var(--s-4); }

    /* ⛔ DER STREIFEN WAR DAS GRÖSSTE HINDERNIS ZWISCHEN GAST UND KARTE — gemessen, nicht
       vermutet. Auf einem 390×844-Gerät lag das erste Gericht bei 1437px, also 1,7 Schirme
       tief. Die Aufteilung darüber:

           Kopfleiste       61px
           Hero            203px
           Abholband       170px
           «Am beliebtesten» 526px   ← mehr als Hero und Abholband zusammen
           Suche/Filter     54px
           Rubrikenleiste   48px

       526px kamen aus EINEM Bild: die Karte war 360px breit, `aspect-ratio: 1/1` machte daraus
       360px Höhe. Ein Empfehlungsstreifen, dessen einzelne Kachel höher ist als der Hero, ist
       kein Streifen mehr, sondern eine zweite Startseite.

       ⚠️ 4:3 STATT 1:1, und schmaler: 52% statt 58%. Beides zusammen holt das erste Gericht
          deutlich näher — und die schmalere Kachel bringt den Nebeneffekt, der ohnehin gefehlt
          hat: die NÄCHSTE Karte lugt am Rand herein, und damit sieht ein Gast, dass sich hier
          etwas schieben lässt. Vorher endete die Kachel bündig mit dem Rand und der Streifen
          sah aus wie ein einzelnes Bild. */
    .beliebt__spur { grid-auto-columns: 52%; }

    /* ⚠️ `height: auto` GEHÖRT DAZU, SONST TUT `aspect-ratio` NICHTS. `dishthumb` schreibt
       `width`/`height` als ATTRIBUTE ins `<img>` — richtig so, sie reservieren den Platz und
       verhindern das Springen des Layouts beim Laden. Als Präsentations-Hinweis setzen sie aber
       eine feste Höhe, und `aspect-ratio` greift nur, wenn eine der beiden Achsen `auto` ist.
       Gemessen: Karte 180px breit, Bild trotzdem 360px hoch — die Regel war da und wirkte nicht. */
    .beliebtkarte__foto { aspect-ratio: 4 / 3; height: auto; }
}

@media (prefers-reduced-motion: reduce) {
    .orderline, .orderline__step, .beliebtkarte__plus,
    .beliebtkarte__foto, .beliebtkarte__name,
    .page-laden .laden__seite a.chip--cat { transition: none; }
    .beliebt__spur { scroll-snap-type: none; }
}

/* -- Die Ladenleiste am unteren Rand ---------------------------------------- */
/*
 * ⛔ DER ABSENDEKNOPF LAG HINTER 81 GERICHTEN, bei 96 % der Seite. Das Zusammenklappen greift
 *    nur bei jemandem, der MIT einem Korb von der Speisekarte kommt; wer direkt hier anfängt und
 *    vier Karten antippt, musste an der ganzen Karte vorbeiscrollen.
 *
 * ⚠️ SIE FÜHRT ZUM ABSCHLUSS UND SCHICKT NICHT AB. Ein Absendeknopf in einer schwebenden Leiste
 *    wirft den Gast an Pflichtfelder, die er nie gesehen hat.
 *
 * ⚠️ `env(safe-area-inset-bottom)` — auf einem iPhone liegt sonst die Hälfte der Leiste unter
 *    dem Home-Balken, also genau der Knopf.
 */
.ladenbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
    background: color-mix(in oklab, var(--surface) 94%, transparent);
    -webkit-backdrop-filter: saturate(1.2) blur(10px);
            backdrop-filter: saturate(1.2) blur(10px);
    border-top: 1px solid var(--line);
    box-shadow: var(--shadow-xl);
    padding: var(--s-3) 0 calc(var(--s-3) + env(safe-area-inset-bottom, 0px));
}
.ladenbar__inner { display: flex; align-items: center; gap: var(--s-3); }
.ladenbar__was { margin: 0; font-size: var(--fs-1); min-width: 0; }
.ladenbar__summe {
    margin-left: var(--s-2); font-family: var(--serif); font-weight: 600;
    color: var(--accent-ink); font-variant-numeric: tabular-nums;
}
/* Der Satz unter der Zahl: was in ihr steckt und was nicht. Eine eigene Zeile, damit die Zahl selbst nie
   umbricht; klein und ruhig, weil er Auskunft ist und kein zweiter Preis. */
.ladenbar__hinweis { display: block; margin-top: 2px; font-size: var(--fs-0); line-height: 1.35; color: var(--muted); }
.ladenbar__weiter { margin-left: auto; flex: 0 0 auto; min-height: 44px; }

/* ZWEI FESTE LEISTEN KÖNNEN NICHT BEIDE DEN UNTEREN RAND HABEN. Die Ladenleiste gewinnt,
   solange etwas gewählt ist — ein Gast mitten in einer Bestellung tut genau das, wofür sie da
   ist — und die Daumenleiste tritt ab, statt sich darüber zu stapeln. Dieselbe Regel wie beim
   Warenkorb der Speisekarte, und derselbe Geschwister-Kombinator: er kann nicht rückwärts
   schauen, also steht die Ladenleiste im Layout VOR `.mobilebar`. */
.ladenbar:not([hidden]) ~ .mobilebar { display: none; }

/* Platz, damit die Leiste den letzten Absatz nicht verdeckt — NUR WENN SIE STEHT. Vorher galt
   der Platz unbedingt: auf dem Rechner blieb unter der Rechtszeile ein leeres Band von 96px,
   obwohl die Leiste versteckt war (11.10.2026). Das Springen beim ersten «+» sieht niemand: wer
   wählt, steht in der Karte, nicht am Fuss der Seite. */
.page-laden:has(.ladenbar:not([hidden])) .footer-bar { padding-bottom: calc(var(--s-8) + env(safe-area-inset-bottom, 0px)); }

@media (max-width: 560px) {
    .ladenbar__weiter { padding: var(--s-2) var(--s-4); }
}


/* ============================================================
   RESERVIEREN — Titelbild und dunkle Fläche, in JEDEM Aufbau und JEDEM Thema (D-257, 14.10.2026)

   ⛔ EINE FORM FÜR ALLE. Der Betreiber, 14.10.2026: «reservierung tasarımı her temada böyle olması
      gerekiyor — bu kural artık, bu tasarım kalacak». Vorbild ist m2-burger.de/reservieren, das er
      selbst gezeigt hat. Kein Aufbau (Bühne, Kontor, Ofen, Tatami) und kein Thema setzt diese Seite
      anders; ihre Blätter tragen KEINE Regel für `.resv*`. Wer sie ändert, ändert sie hier, für alle.

   ⛔ VORHER: D-253 (zwei Hälften: links die Bühne klebend, rechts ein Fenster als Karte), davor das
      «Blatt», davor Bogen, Karte und Kästen. Alle drei hat der Betreiber abgelehnt.

   ⚠️ DIE FORM: oben das Hausfoto über die ganze Breite, gleichmässig verschleiert, darauf in der
      Mitte Name · Beiwort, der Titel, der eine wahre Satz, zwei Zusagen und drei Fakten mit
      Haarlinien. Darunter Graphit, das Formular als EINE Spalte von 640 px: vier Gruppen mit einer
      Beschriftung (die Ziffern stehen im Markup und treten zurück), Felder eine Stufe heller mit
      heller Linie, die Zeiten als Raster, die gewählte voll in der Hausfarbe, der Knopf in der
      Hausfarbe. Keine Karte, kein Rahmen, kein Schatten, keine Pille.

   ⚠️ DIE FLÄCHEN SIND FEST, NICHT VOM THEMA. Graphit und Nacht sind neutral (kein Papierton, kein
      Braun, D-155) und tragen jedes Thema, Tag wie Nacht. Die EINE Farbe mit Ton ist die des
      Hauses (`--accent`). Die gemeinsamen Namen (`--text`, `--muted`, `--line`, `--bg`) kippen
      lokal, damit die Regeln der Felder darin von selbst stimmen.

   ⚠️ PFEILE UND ZÄHLER NUR MIT SKRIPT. `html:not(.has-resv)` blendet sie aus, `reservation-times.js`
      setzt `has-resv` am `<html>`. Ohne Skript stehen die Radioknöpfe als Reihe; mit Skript
      übernimmt der Zähler und die Reihe tritt zurück (sie bleibt im Formular und wird mitgeschickt).

   ⚠️ `#main .resv` FÜR POLSTER UND KANTE: `section` trägt in jedem Aufbau ein Bandpolster und in
      Kontor eine Haarlinie oben; beides schlägt (0,1,1) eine Klasse.

   ⚠️ DIE FELDREGELN TRAGEN `.resv .resv__bogen` UND ZWEI `:not()`: Bühne setzt jedes
      `.resform input` mit zwei `:not()` auf ihre helle Fläche (0,4,1), und ihr Blatt lädt später.
   ============================================================ */

#main .resv { padding: 0; border-top: 0; }

.resv {
    --resv-nacht: #0B0C0E;
    --resv-flaeche: #17191C;
    --resv-feld: #212429;
    --resv-rand: rgba(255, 255, 255, .22);
    --resv-hell: #FFFFFF;
    --resv-hell-weich: rgba(255, 255, 255, .74);
    --resv-hell-linie: rgba(255, 255, 255, .2);
    --resv-akzent-hell: color-mix(in oklab, var(--accent) 58%, #FFFFFF);
    --text: var(--resv-hell);
    --muted: var(--resv-hell-weich);
    --line: var(--resv-rand);
    --line-soft: rgba(255, 255, 255, .12);
    --bg: var(--resv-feld);
    --link: var(--resv-akzent-hell);
    --accent-ink: var(--resv-akzent-hell);
    display: block;
    background: var(--resv-flaeche);
    color: var(--resv-hell);
}

.resv :focus-visible { outline-color: var(--resv-akzent-hell); }

/* ── Oben: das Titelbild ─────────────────────────────────────────────────────────────────── */

.resv__buehne {
    position: relative;
    min-width: 0;
    background: var(--resv-nacht);
    color: var(--resv-hell);
}

.resv__buehne-inhalt {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: clamp(22px, 3vw, 34px);
    min-height: clamp(400px, 58svh, 620px);
    padding: clamp(40px, 6vw, 80px) var(--wrap-rand) clamp(26px, 4vw, 44px);
    overflow: hidden;
    text-align: center;
}

/* Das Foto liegt hinter allem; der Schleier gleichmässig, denn der Titel steht in der Mitte. */
.resv__foto { position: absolute; inset: 0; margin: 0; pointer-events: none; }
.resv__bild { display: block; width: 100%; height: 100%; object-fit: cover; }
.resv__foto::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, rgba(11, 12, 14, .44) 0%, rgba(11, 12, 14, .56) 55%, rgba(11, 12, 14, .7) 100%);
}

.resv__haus,
.resv__kopf,
.resv__fakten { position: relative; }

.resv__haus {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 4px 0;
    margin: 0;
    font-family: var(--sans);
    font-size: .9rem;
    color: var(--resv-hell-weich);
}

.resv__haus-name { font-family: var(--serif); font-size: 1.1rem; color: var(--resv-hell); }
.resv__haus-zeile::before { content: "·"; margin: 0 10px; }

.resv__kopf {
    display: flex;
    flex-direction: column;
    align-items: center;
    max-width: 62ch;
}

/* (0,2,0): schlägt die Überschriften jedes Aufbaus (`.layout-x h1`, 0,1,1). */
.resv .resv__titel {
    max-width: 20ch;
    margin: 0 auto 16px;
    font-family: var(--serif);
    font-size: clamp(2.7rem, 6.4vw, 5.4rem);
    font-weight: 500;
    font-style: normal;
    line-height: .98;
    letter-spacing: -.02em;
    text-transform: none;
    color: var(--resv-hell);
}

.resv__satz {
    max-width: 52ch;
    margin: 0 auto;
    font-family: var(--sans);
    font-size: clamp(1.02rem, 1.3vw, 1.15rem);
    line-height: 1.55;
    color: var(--resv-hell-weich);
}

/* Zwei kurze Zusagen in einer Zeile, ein Punkt dazwischen — kein Zeichen, keine Pille. */
.resv__zusagen {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    margin: 14px 0 0;
    font-family: var(--sans);
    font-size: .92rem;
    line-height: 1.5;
    color: var(--resv-hell-weich);
}

.resv__zusagen span { white-space: nowrap; }   /* der Punkt bricht mit seinem Wort, nie allein an den Zeilenanfang */
.resv__zusagen span + span::before { content: "·"; margin: 0 10px; }

/* Drei Fakten als Zeile am Fuss des Bildes, mittig, Haarlinien dazwischen: heute, Telefon, Antwort. */
.resv__fakten {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    width: 100%;
    max-width: 760px;
    margin: 0 auto;
    padding: 18px 0 0;
    border-top: 1px solid var(--resv-hell-linie);
}

.resv__fakt { min-width: 0; padding: 2px 12px; text-align: center; }
.resv__fakt + .resv__fakt { border-left: 1px solid var(--resv-hell-linie); }
.resv__fakt dt { margin: 0 0 4px; font-family: var(--sans); font-size: .78rem; font-weight: 600; color: var(--resv-hell-weich); }
.resv__fakt dd {
    margin: 0;
    font-family: var(--serif);
    font-size: clamp(.98rem, 1.1vw, 1.1rem);
    line-height: 1.35;
    color: var(--resv-hell);
    overflow-wrap: anywhere;
}

.resv__anruf { color: inherit; text-decoration: none; }
.resv__anruf:hover,
.resv__anruf:focus-visible { text-decoration: underline; text-underline-offset: 4px; }

/* ── Unten: Graphit, das Formular als eine Spalte ────────────────────────────────────────── */

.resv__fenster {
    min-width: 0;
    padding: clamp(36px, 6vw, 72px) 16px clamp(48px, 6vw, 80px);
    background: var(--resv-flaeche);
    color: var(--resv-hell);
}

.resv__fenster-inhalt { max-width: 640px; margin: 0 auto; }

/* Die Absage steht ÜBER dem Formular, mit der Linie links (`.resform__error`). */
.resv__meldung { margin: 0 0 22px; max-width: 60ch; }
.resv .resform__error { color: var(--resv-hell); border-left-color: var(--resv-akzent-hell); }

/* Der Annahmestopp: ein ruhiger Kasten — er IST eine Unterbrechung. */
.resv__stopp {
    margin: 0 0 26px;
    padding: 16px 18px;
    border: 1px solid var(--resv-rand);
    border-radius: 6px;
    background: var(--resv-feld);
}

.resv__stopp p { margin: 0 0 12px; font-weight: 600; line-height: 1.5; }

.resv__bogen { margin: 0; }

/* Vier Gruppen, je eine Beschriftung; keine Haarlinie, keine Ziffer. */
.resv__schritt { margin: 0; padding: 0 0 clamp(24px, 3vw, 32px); border: 0; min-width: 0; }

/* ⛔ KEINE GEFLOATETE LEGENDE: sie schiebt jedes Raster danach in eine Spalte von null Breite. */
.resv__schritt-kopf {
    display: block;
    width: 100%;
    margin: 0 0 10px;
    padding: 0;
    font-family: var(--sans);
    font-size: 1rem;
    font-weight: 600;
    color: var(--resv-hell);
}

.resv .resv__nr { display: none; }

/* Felder: 52 px, Graphit eine Stufe heller, helle Linie, 6 px, der Fokus in der Hausfarbe. */
.resv .resform__field { gap: 7px; margin: 0; }

.resv .resform__field label {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    font-family: var(--sans);
    font-size: .9rem;
    font-weight: 600;
    color: var(--resv-hell);
}

.resv .resform__field label .muted { font-weight: 400; color: var(--resv-hell-weich); }

.resv .resv__bogen .resform__field input:not([type="radio"]):not([type="checkbox"]),
.resv .resv__bogen .resform__field textarea {
    min-height: 52px;
    padding: 12px 14px;
    font-family: var(--sans);
    font-size: 1rem;
    line-height: 1.4;
    color: var(--resv-hell);
    color-scheme: dark;
    background: var(--resv-feld);
    border: 1px solid var(--resv-rand);
    border-radius: 6px;
    box-shadow: none;
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.resv .resv__bogen .resform__field input:not([type="radio"]):not([type="checkbox"])::placeholder,
.resv .resv__bogen .resform__field textarea::placeholder { color: rgba(255, 255, 255, .42); }

.resv .resv__bogen .resform__field input:not([type="radio"]):not([type="checkbox"]):hover,
.resv .resv__bogen .resform__field textarea:hover { border-color: var(--resv-hell-weich); }

.resv .resv__bogen .resform__field input:not([type="radio"]):not([type="checkbox"]):focus,
.resv .resv__bogen .resform__field textarea:focus {
    outline: none;
    border-color: var(--resv-akzent-hell);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 28%, transparent);
}

.resv .resv__bogen .resform__field textarea { resize: vertical; }

/* Ein Zeichen vor dem Feld, nicht hinter dem Text: Name, Telefon, Post, Anmerkung. */
.resv__feld-rahmen { position: relative; display: block; }
.resv__feld-rahmen > svg {
    position: absolute;
    left: 14px;
    top: 17px;
    width: 18px;
    height: 18px;
    color: var(--resv-hell-weich);
    pointer-events: none;
}
.resv .resv__bogen .resv__feld-rahmen > input:not([type="radio"]):not([type="checkbox"]),
.resv .resv__bogen .resv__feld-rahmen > textarea { padding-left: 44px; }

/* Eine Beschriftung nur für die Vorlesestimme: die Gruppenzeile sagt es sehend schon. */
.resv__unsichtbar {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Tag: Pfeil, Datum, Pfeil über die ganze Spalte — und darunter der Wochentag als Wort. */
.resv__datum {
    display: grid;
    grid-template-columns: 52px minmax(0, 1fr) 52px;
    gap: 8px;
    align-items: center;
}

html:not(.has-resv) .resv__datum { grid-template-columns: minmax(0, 1fr); }
html:not(.has-resv) .resv__tag-knopf,
html:not(.has-resv) .resv__stepper { display: none; }
html.has-resv [data-res-personen] .resform__zahlen { display: none; }

.resv__tag-knopf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    padding: 0;
    color: var(--resv-hell);
    background: var(--resv-feld);
    border: 1px solid var(--resv-rand);
    border-radius: 6px;
    cursor: pointer;
    transition: border-color var(--t-fast), background var(--t-fast);
}
.resv__tag-knopf:hover { border-color: var(--resv-hell-weich); }
.resv__tag-knopf:focus-visible { outline: 2px solid var(--resv-akzent-hell); outline-offset: 2px; }
.resv__tag-knopf:disabled { opacity: .4; cursor: default; }
.resv__tag-knopf svg { width: 18px; height: 18px; }

.resv .resv__tag { margin: 0; }
.resv .resv__bogen .resv__tag input:not([type="radio"]):not([type="checkbox"]) {
    font-family: var(--serif);
    font-size: 1.12rem;
    font-weight: 500;
    text-align: center;
}

.resv__wochentag { margin: 10px 0 0; font-family: var(--sans); font-size: .95rem; font-weight: 500; text-align: center; color: var(--resv-hell-weich); }
.resv__wochentag:empty { display: none; }

/* Personen: der Zähler über die ganze Spalte, die Zahl in der Mitte, der Satz darunter. */
.resv__personen { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }

.resv__stepper {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) 56px;
    align-items: stretch;
    width: 100%;
    background: var(--resv-feld);
    border: 1px solid var(--resv-rand);
    border-radius: 6px;
    overflow: hidden;
}

.resv__stepper-knopf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 50px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--resv-hell);
    cursor: pointer;
    transition: background var(--t-fast);
}
.resv__stepper-knopf:hover { background: rgba(255, 255, 255, .08); }
.resv__stepper-knopf:focus-visible { outline: 2px solid var(--resv-akzent-hell); outline-offset: -3px; }
.resv__stepper-knopf:disabled { opacity: .35; cursor: default; }
.resv__stepper-knopf svg { width: 18px; height: 18px; }

.resv__stepper-wert {
    display: grid;
    place-content: center;
    font-family: var(--serif);
    font-size: 1.35rem;
    font-weight: 500;
    color: var(--resv-hell);
    border-inline: 1px solid rgba(255, 255, 255, .12);
}

.resv .resv__personen-hinweis { margin: 0; font-family: var(--sans); font-size: .88rem; color: var(--resv-hell-weich); }
.resv .resv__zahlfeld { margin: 0; }

/* ── Uhrzeit und Personenzahl ohne Skript: eine Auswahl, kein Aufklappmenü ─────────────────
 *
 * ⛔ EIN AUFKLAPPMENÜ VERBIRGT DAS ANGEBOT, bis jemand es antippt. Der Gast soll den Abend sehen
 *    und dann wählen, nicht wählen müssen, um ihn zu sehen.
 *
 * ⚠️ ES SIND GEWÖHNLICHE `input[type=radio]`, nur unsichtbar gemacht statt weggelassen. Tastatur,
 *    Screenreader, Pfeiltasten in der Gruppe und das Absenden ohne Skript bleiben, was der Browser
 *    ohnehin kann.
 *
 * ⛔ NICHT `opacity: 0` — `BewegungTest` verbietet jede Deckkraft-Null ausserhalb von `.js-motion`.
 *    Der Knopf ist einen Pixel gross und weggeschnitten; angetippt wird er über das `<label>`.
 *
 * ⚠️ DIE WAHL IST NICHT NUR FARBE: die gewählte Zeit ist gefüllt und eine Stufe schwerer — auch in
 *    Graustufen ist sie die einzige volle Zelle.
 */
/* 92 px auf dem Schreibtisch; auf dem Telefon drei je Zeile (unten), wie beim Vorbild. */
.resform__zeiten { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 10px; }
.resform__zahlen { display: flex; flex-wrap: wrap; gap: 8px; }

.resform__zeit,
.resform__zahl { position: relative; display: block; cursor: pointer; }

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

.resv .resform__zeit span,
.resv .resform__zahl span {
    display: grid;
    place-content: center;
    min-height: 50px;
    padding: 10px 8px;
    text-align: center;
    font-family: var(--serif);
    font-size: 1.08rem;
    font-weight: 500;
    font-variant-numeric: normal;
    color: var(--resv-hell);
    background: var(--resv-feld);
    border: 1px solid var(--resv-rand);
    border-radius: 6px;
    transition: border-color var(--t-fast), background var(--t-fast), color var(--t-fast);
}

.resv .resform__zahl span { min-width: 50px; padding: 10px 12px; }

/* Am `label`, nicht am Knopf: der Knopf ist einen Pixel gross und wird nie überfahren. */
.resv .resform__zeit:hover span,
.resv .resform__zahl:hover span { border-color: var(--resv-hell); }

.resv .resform__zeit input:focus-visible + span,
.resv .resform__zahl input:focus-visible + span { outline: 2px solid var(--resv-akzent-hell); outline-offset: 2px; }

.resv .resform__zeit input:checked + span,
.resv .resform__zahl input:checked + span {
    color: var(--on-accent);
    background: var(--accent);
    border-color: var(--accent);
    font-weight: 600;
}

/* Während das Skript die Zeiten eines anderen Tages holt: die alten treten zurück, nichts springt. */
.resform__zeiten[aria-busy="true"] { opacity: .5; pointer-events: none; }

.resv__zeitnote { display: block; margin: 10px 0 0; font-family: var(--sans); font-size: .9rem; line-height: 1.5; color: var(--resv-hell-weich); }
.resv__zeitnote:empty { display: none; }

/* Angaben: zwei Spalten, wo Platz ist. */
.resv__angaben { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }

@media (min-width: 640px) {
    .resv__angaben { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

.resv .resv__kontosatz { margin: 14px 0 0; color: var(--resv-hell-weich); }
.resv .resv__sicherung { margin: 0 0 18px; color: var(--resv-hell-weich); }

/* ── Der Schluss: der Knopf in der Hausfarbe, mittig; der Anruf, der Datenschutz, die Marke ── */

.resv__aktionen { display: flex; flex-direction: column; align-items: center; gap: 12px; margin: 8px 0 0; }

.resv .resv__aktionen .resv__senden {
    width: auto;
    min-width: min(100%, 320px);
    min-height: 58px;
    padding: 0 40px;
    gap: 10px;
    font-family: var(--sans);
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--on-accent);
    background: var(--accent);
    border: 0;
    border-radius: 6px;
    text-transform: none;
}

.resv .resv__aktionen .resv__senden:hover {
    color: var(--on-accent);
    background: var(--accent-strong);
    box-shadow: 0 14px 32px -14px color-mix(in oklab, var(--accent) 80%, transparent);
}

.resv__senden svg { width: 18px; height: 18px; flex: 0 0 auto; transition: transform var(--t-fast); }
.resv__senden:hover svg { transform: translateX(3px); }

/* Abgeschickt: der Knopf tritt zurück und nimmt keinen zweiten Klick an (`data-res-sendet`). */
.resv__bogen[data-res-sendet] .resv__senden { opacity: .6; pointer-events: none; cursor: progress; }

.resv__anruf-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 4px 8px;
    font-family: var(--sans);
    font-size: .92rem;
    color: var(--resv-hell-weich);
    text-decoration: none;
}
.resv__anruf-link:hover,
.resv__anruf-link:focus-visible { color: var(--resv-hell); text-decoration: underline; text-underline-offset: 4px; }

/* ⚠️ OHNE SCHILD UND OHNE KLEINGEDRUCKTES: der Satz ist die eine Zusage, die ein Gast liest. */
.resform__datenschutz {
    margin: 16px 0 0;
    font-family: var(--sans);
    font-size: .86rem;
    line-height: 1.5;
    text-align: center;
    color: var(--resv-hell-weich);
}

/* Die Marke unter dem Formular (D-227): eine Haarlinie, darunter mittig «Tischreservierung mit» und
   die Wortmarke, ruhig. Auf Graphit immer die WEISSE Schrift. */
.resform__marke {
    margin: 18px 0 0;
    padding-top: 12px;
    border-top: 1px solid rgba(255, 255, 255, .12);
    text-align: center;
}
.resform__marke-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 6px;
    color: var(--resv-hell-weich);
    font-size: .8125rem;
    text-decoration: none;
    opacity: .78;
    transition: opacity var(--t-fast);
}
.resform__marke-link:hover,
.resform__marke-link:focus-visible { opacity: 1; }
.resform__marke-wort { white-space: nowrap; }
.resform__marke-bild { display: block; width: auto; height: 20px; }
.resform__marke-bild--dunkel { display: none; }
.resform__marke-bild--hell { display: block; }

/* Telefon: das Bild etwas höher, drei Zeiten je Zeile wie beim Vorbild, der Knopf über die ganze Breite. */
@media (max-width: 639px) {
    .resv__buehne-inhalt { gap: 20px; min-height: clamp(380px, 64svh, 560px); padding: 36px 20px 24px; }
    .resv .resv__titel { margin-bottom: 12px; }
    .resv__fakten { padding-top: 14px; }
    .resv__fakt { padding: 2px 8px; }
    .resform__zeiten { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
    .resv .resv__aktionen .resv__senden { width: 100%; min-width: 0; padding: 0 24px; }
}

/* ── Bewegung: das Titelbild hebt sich an, dann die Spalte — einmal, kurz ─────────────────── */
.js-motion .resv__buehne-inhalt > .resv__haus { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) both; }
.js-motion .resv__buehne-inhalt > .resv__kopf { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) 80ms both; }
.js-motion .resv__buehne-inhalt > .resv__fakten { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) 160ms both; }
.js-motion .resv__fenster-inhalt { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) 200ms both; }

@media (prefers-reduced-motion: reduce) {
    .js-motion .resv__buehne-inhalt > *,
    .js-motion .resv__fenster-inhalt { animation: none; }
    .resv .resform__zeit span,
    .resv .resform__zahl span,
    .resv .resv__bogen .resform__field input:not([type="radio"]):not([type="checkbox"]),
    .resv .resv__bogen .resform__field textarea,
    .resv__tag-knopf,
    .resv__stepper-knopf,
    .resv__senden svg { transition: none; }
    .resv__senden:hover svg { transform: none; }
}

/* ============================================================
   BEWEGUNG — was ankommt, was antwortet, und was ausdrücklich still bleibt

   ⛔ DER RUHEZUSTAND IST SICHTBAR. Versteckt wird ausschliesslich unter `html.js-motion`, und
      diese Klasse setzt `site.js` erst, nachdem es einen IntersectionObserver gefunden UND
      festgestellt hat, dass der Gast keine reduzierte Bewegung wünscht. Ohne Skript, ohne
      Beobachter, mit reduzierter Bewegung oder bei angehaltener Animationsuhr steht die Seite
      vollständig da.

      Diese Datei trägt die Narbe dafür schon: `.wa-fab__note` bekam bewusst KEINE Einblendung,
      weil eine Animation ab `opacity: 0` den Text für immer unsichtbar lässt, sobald sie nicht
      läuft — «Both fail silently, and the invitation is the entire point of this component.»
      Derselbe Fehler, eine Seite weiter, wäre eine Speisekarte ohne Gerichte.

   ⛔ NUR `transform` UND `opacity`. Beide laufen auf der Grafikkarte; `top`, `height` oder
      `margin` zu animieren heisst, den Browser bei jedem Bild neu rechnen zu lassen — auf dem
      Telefon, auf dem diese Seite meistens geöffnet wird, ist das der Unterschied zwischen
      sechzig Bildern und Ruckeln.

   ⚠️ ZWEI AUFBAUTEN, ZWEI BEWEGUNGSSPRACHEN. Was hier steht, ist Bühnes Sprache: das Bild
      führt, also hebt sich eine Karte an und das Foto darin zieht leicht näher. Kontor sagt
      über sich selbst «square, and they do not lift» — dort wäre dieselbe Geste ein Widerspruch
      zum eigenen Charakter. Seine Fassung steht im Kontor-Block und arbeitet mit der Linie und
      der Farbe statt mit der Höhe.

   ⚠️ JEDE BEWEGUNG HIER HAT EINEN GRUND, und wo keiner steht, steht auch keine Bewegung.
      Ankommen führt das Auge eine lange Seite hinunter; Hover sagt «das hier antwortet»;
      der Druckpunkt bestätigt den Finger. Alles andere ist Zierat, der Aufmerksamkeit
      verlangt, statt sie zu lenken.
   ============================================================ */

/* ── Ankommen ──────────────────────────────────────────────────────────────────────────── */

.js-motion .section-head,
.js-motion .dishcard,
.js-motion .band-photo,
.js-motion .rg-card,
.js-motion .split__media,
.js-motion .split__text,
.js-motion .section-head.is-in,
.js-motion .dishcard.is-in,
.js-motion .band-photo.is-in,
.js-motion .rg-card.is-in,
.js-motion .split__media.is-in,
.js-motion .split__text.is-in {
    opacity: 1;
    transform: translate3d(0, 0, 0);
}

/*
 * ⚠️ DIE STAFFELUNG STEHT IM STYLESHEET UND NICHT IM SKRIPT. Der naheliegende Weg wäre, dem
 *    Beobachter je Element einen Verzögerungswert in `element.style` zu schreiben — und die
 *    Auslieferung dieser Seite verbietet Inline-Stile über die Content-Security-Policy, die am
 *    Webserver gesetzt wird und die der Anwendung übergeordnet ist. `:nth-child()` kann
 *    dasselbe, ohne dass irgendwo ein Stil aus JavaScript entsteht.
 *
 * ⚠️ VIER STUFEN UND DANN SCHLUSS. Bei zwölf Gerichten wäre die zwölfte Karte eine dreiviertel
 *    Sekunde nach der ersten dran, und der Gast wartet auf sein Essen statt es anzusehen.
 */
.js-motion .dish-grid > .dishcard:nth-child(2)  { transition-delay: 70ms; }
.js-motion .dish-grid > .dishcard:nth-child(3)  { transition-delay: 140ms; }
.js-motion .dish-grid > .dishcard:nth-child(n+4) { transition-delay: 210ms; }

/*
 * ── Der erste Bildschirm kommt an, statt dazustehen ──────────────────────────────────────
 *
 * ⚠️ EINE ANIMATION UND KEIN ÜBERGANG, weil hier kein Zustand wechselt: die Seite lädt, und
 *    der Aufmacher setzt sich. `backwards` hält den ersten Bildrahmen während der Verzögerung —
 *    ohne das blitzt die Zeile kurz an ihrer Endstelle auf, bevor sie zurückspringt.
 */
@keyframes bm-anheben {
    from { opacity: 0; transform: translate3d(0, 18px, 0); }
    to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

.js-motion .hero__inner > .eyebrow  { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) both; }
.js-motion .hero__inner > .hero__title { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) 80ms both; }
.js-motion .hero__inner > .hero__intro { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) 160ms both; }
.js-motion .hero__inner > .hero__status,
.js-motion .hero__inner > .hero__actions { animation: bm-anheben .62s cubic-bezier(.16, .84, .44, 1) 240ms both; }

/*
 * ── DER AUFMACHER ATMET ────────────────────────────────────────────────────────────────────
 *
 * ⛔ EIN STANDBILD IST DAS EINZIGE, WAS EIN RESTAURANT NICHT IST. Die langsame Zufahrt auf das
 *    Foto — sechsundzwanzig Sekunden von 1,00 auf 1,085 — ist die Geste, mit der jede
 *    Restaurantseite arbeitet, die man sich merkt. Sie ist so langsam, dass man sie nicht als
 *    Bewegung sieht, sondern nur merkt, dass der Raum lebt.
 *
 * ⚠️ SIE IST SICHER, UND ZWAR ANDERS ALS EINE EINBLENDUNG. Hält die Animationsuhr an, bleibt
 *    der ERSTE Rahmen stehen — `scale(1)`, also genau das Bild, das ohne jede Animation zu
 *    sehen wäre. Ein `opacity: 0` am Anfang wäre dagegen ein leerer Aufmacher; deshalb bewegt
 *    sich hier nur die Grösse und nie die Deckkraft.
 *
 * ⚠️ DAS FOTO WANDERT AUF EIN EIGENES BLATT, weil man einen Hintergrund nicht transformieren
 *    kann. `::before` trägt das Bild, `::after` den Schleier darüber, der Inhalt liegt auf
 *    z-index 1 und bleibt oben. Ohne `.js-motion` steht die ursprüngliche Regel unverändert da:
 *    ein Haus ohne JavaScript sieht exakt das, was es heute sieht.
 */
.hero--foto { position: relative; overflow: hidden; }

@keyframes bm-schwenk {
    from { transform: scale(1); }
    to   { transform: scale(1.085); }
}

.js-motion .hero--foto.is-photo { background-image: none; }

.js-motion .hero--foto.is-photo::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: var(--hero-photo);
    background-size: cover;
    background-position: center;
    transform-origin: 50% 58%;
    animation: bm-schwenk 26s cubic-bezier(.25, .5, .35, 1) both;
}

.js-motion .hero--foto.is-photo::after {
    content: '';
    position: absolute;
    inset: 0;
    /* Derselbe Schleier wie ohne Skript — siehe `--hero-schleier`. */
    background-image: var(--hero-schleier);
}

/*
 * ⚠️ UND DAS BAND SETZT SICH. Dieselbe Bewegung, kürzer und an das Ankommen gekoppelt: das
 *    Foto steht eine Spur zu gross da und findet seine Grösse, während das Band hereinkommt.
 */
.js-motion .band-photo__img {
    transform: scale(1.07);
    transition: transform 1.15s cubic-bezier(.16, .84, .44, 1);
}

.js-motion .band-photo.is-in .band-photo__img { transform: scale(1); }

/*
 * ── DER FORTSCHRITTSFADEN ──────────────────────────────────────────────────────────────────
 *
 * ⚠️ NUR WO ER OHNE SKRIPT GEHT. `animation-timeline: scroll()` bindet die Animation an den
 *    Rollbalken statt an die Uhr — kein Ereignis, kein `requestAnimationFrame`, keine Zeile
 *    JavaScript. `@supports` ist hier tragend: ohne die Abfrage liefe die Animation in älteren
 *    Browsern auf der Zeituhr mit Dauer null und stünde sofort auf voller Breite — ein Faden,
 *    der immer «fertig» sagt.
 */
@supports (animation-timeline: scroll()) {
    @keyframes bm-fortschritt {
        from { transform: scaleX(0); }
        to   { transform: scaleX(1); }
    }

    .js-motion body::before {
        content: '';
        position: fixed;
        inset: 0 0 auto 0;
        height: 3px;
        z-index: 60;
        pointer-events: none;
        transform-origin: 0 50%;
        background: linear-gradient(90deg, var(--accent), var(--gold));
        animation: bm-fortschritt linear both;
        animation-timeline: scroll(root block);
    }
}

/* ── Antworten: Hover und Druckpunkt ───────────────────────────────────────────────────── */

/*
 * ⚠️ DAS FOTO ZIEHT NÄHER, DIE KARTE HEBT SICH. Zusammen ergibt das die Bewegung, die ein
 *    Gedeck macht, wenn man sich darüber beugt — und sie gehört zum fotografischen Aufbau,
 *    dessen ganze These das Bild ist. `overflow: hidden` ist dafür tragend: ohne es wächst das
 *    Foto über die Kante der Karte hinaus.
 */
.dishcard { overflow: hidden; }

.dishcard__photo {
    transition: transform var(--t);
    will-change: auto;
}

@media (hover: hover) {
    .dishcard:hover { transform: translate3d(0, -6px, 0); }
    .dishcard:hover .dishcard__photo { transform: scale(1.07); }
}

/*
 * ⚠️ EIN GLANZ ÜBER DEN HAUPTKNOPF, und nur über diesen einen. «Zur Speisekarte» und «Tisch
 *    anfragen» sind die zwei Handlungen, für die es diese Seite gibt; ein Lichtstreifen, der
 *    beim Zeigen darüberläuft, sagt «hier lang», ohne ein Wort hinzuzufügen. Auf jedem Knopf
 *    wäre dieselbe Geste Kirmes.
 */
.btn--primary { position: relative; overflow: hidden; isolation: isolate; }

.btn--primary::after {
    content: '';
    position: absolute;
    top: 0;
    left: -140%;
    width: 55%;
    height: 100%;
    z-index: -1;
    background: linear-gradient(100deg, transparent, rgb(255 255 255 / .26), transparent);
    transform: skewX(-18deg);
    transition: left .6s cubic-bezier(.22, .61, .36, 1);
}

@media (hover: hover) {
    .btn--primary:hover::after { left: 150%; }
}

/*
 * ⚠️ DER STRICH UNTER DEM MENÜPUNKT ZIEHT SICH, statt zu erscheinen. `::before`, weil `::after`
 *    an dieser Stelle schon den Punkt der aktuellen Seite trägt (eine Regel weiter oben, im
 *    Breitbild-Block) — zwei Gesten auf einem Pseudoelement wären eine, die die andere
 *    überschreibt.
 */
.nav > a { position: relative; }

.nav > a::before {
    content: '';
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 3px;
    height: 1.5px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--t);
}

@media (hover: hover) {
    .nav > a:hover::before { transform: scaleX(1); }
}

/* Der Druckpunkt. Ein Knopf, der auf den Finger nicht reagiert, fühlt sich an, als hätte er
   nicht ausgelöst — und dann drückt man ihn ein zweites Mal. */
.btn:active { transform: translate3d(0, 1px, 0) scale(.988); }
.btn { transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast),
                   box-shadow var(--t-fast), transform var(--t-fast); }

/*
 * ⛔ UND HIER HÖRT ALLES AUF. Der Block gilt für jede Regel dieses Abschnitts, auch für die
 *    Kontor-Fassung weiter unten: wer reduzierte Bewegung eingestellt hat, hat das gesagt, weil
 *    Bewegung ihm körperlich unangenehm ist. `.js-motion` wird zwar ohnehin nicht gesetzt, aber
 *    diese Regel deckt auch den Fall ab, dass jemand die Einstellung ändert, während die Seite
 *    offen ist — dann fällt die Bewegung sofort weg, ohne Neuladen.
 */
@media (prefers-reduced-motion: reduce) {
    .js-motion .section-head,
    .js-motion .dishcard,
    .js-motion .band-photo,
    .js-motion .rg-card,
    .js-motion .split__media,
    .js-motion .split__text {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .js-motion .hero__inner > * { animation: none; }

    .dishcard,
    .dishcard__photo,
    .btn { transition: none; }

    .dishcard:hover,
    .dishcard:hover .dishcard__photo,
    .btn:active { transform: none; }

    .js-motion .hero--foto.is-photo::before { animation: none; }
    .js-motion .band-photo__img,
    .js-motion .band-photo.is-in .band-photo__img { transform: none; transition: none; }
    .js-motion body::before { display: none; }
    .btn--primary::after,
    .nav > a::before { transition: none; }
    .btn--primary:hover::after { left: -140%; }
    .nav > a:hover::before { transform: scaleX(0); }
}


/* ── Die Karte ────────────────────────────────────────────────────────────────────
 *
 * ⚠️ DER PLATZHALTER IST KEIN GRAUER KASTEN. Er trägt dieselbe Kante, denselben Radius und
 *    denselben Schatten wie die Kartenkarte darunter, dazu die Anschrift und eine Nadel — er
 *    sieht aus wie ein Teil der Seite und nicht wie etwas, das noch lädt. Ein Platzhalter, der
 *    nach Fehler aussieht, wird nicht angeklickt.
 *
 * ⚠️ UND ER HÄLT DIE HÖHE, DIE DIE KARTE GLEICH BRAUCHT. Ohne `aspect-ratio` springt die
 *    halbe Seite nach unten, sobald jemand den Knopf drückt — genau die Bewegung, die einen
 *    Klick auf etwas anderes auslöst, das gerade weggerutscht ist.
 */
.karte {
    margin: clamp(24px, 4vw, 40px) 0 0;
    border: 1px solid var(--line-soft);
    border-radius: var(--r);
    overflow: hidden;
    box-shadow: var(--shadow);
    background: var(--plate);
}

.karte__platzhalter {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    aspect-ratio: 2 / 1;
    min-height: 220px;
    padding: clamp(18px, 4vw, 32px);
    text-align: center;
}


/* Alles Inhaltliche liegt über dem Raster. */
.karte__nadel,
.karte__adresse,
.karte__knopf,
.karte__hinweis { position: relative; }

/*
 * ⚠️ DIE NADEL TRÄGT DIE AKZENTFARBE, und zwar als einziges Element hier. Auf einer Karte
 *    ist der Punkt das, was man sucht; in Grau wäre er ein Symbol neben einer Anschrift.
 */
.karte__nadel {
    width: 38px;
    height: 38px;
    color: var(--accent, var(--c-ink));
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .12));
}

.karte__adresse {
    margin: 0;
    font-family: var(--serif);
    font-size: 1.05rem;
    line-height: 1.45;
}

.karte__knopf { margin-top: 2px; }

.karte__hinweis {
    margin: 0;
    max-width: 42ch;
    font-size: .82rem;
    line-height: 1.5;
    color: var(--muted);
}

/* Das eingesetzte `iframe` erbt die Form des Platzhalters, den es ersetzt. */
.karte__rahmen {
    display: block;
    width: 100%;
    aspect-ratio: 2 / 1;
    min-height: 220px;
    border: 0;
}

.karte__quelle {
    padding: 8px 14px;
    font-size: .78rem;
    color: var(--muted);
    border-top: 1px solid var(--line-soft);
}

.karte__quelle a { color: inherit; }

.karte__nurlink { margin: clamp(20px, 3vw, 32px) 0 0; }

/* Im Laden-Schubfach ist weniger Platz: dort steht die Karte quadratischer und ohne Schatten. */
.storedetails .karte { margin-top: 12px; box-shadow: none; }
.storedetails .karte__platzhalter,
.storedetails .karte__rahmen { aspect-ratio: 4 / 3; min-height: 180px; }

/* ⚠️ UND DIESE DREI EBENFALLS — aus demselben Grund, eine Warnung weiter unten
      ausgeschrieben. Ans Dateiende angehängt lagen sie hinter der ersten
      `.layout-kontor`-Regel, waren dort ungebunden und trugen `[hidden]` mit sich:
      zwei rote Tests aus einer Zeilennummer, genau wie beim Urlaubsband vor ihnen.
      Die Falle erwischt jeden, der «unten anfügen» für neutral hält. */

/* ── Das Gästekonto ────────────────────────────────────────────────────────────
 *
 * ⚠️ EINE LISTE, KEINE TABELLE. Auf einem Telefon — und dort wird diese Seite geöffnet, weil
 *    der Link in der Fusszeile steht — zerfällt eine vierspaltige Tabelle in etwas, das man
 *    seitwärts schieben muss. Die Zeilen stapeln sich hier stattdessen.
 *
 * ⛔ KEINE EIGENE FARBWELT. Die Kontoseite ist Teil der Restaurantseite und erbt deren
 *    Schriften und Töne; ein Konto, das aussieht wie ein fremdes Portal, sieht aus wie eine
 *    Anmeldeseite, die jemand untergeschoben hat.
 */
/* Ein Knopf, der wie ein Link aussieht: die selteneren Handlungen einer Adresse. */
.linkknopf {
    display: inline;
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent-ink);
    font: inherit;
    font-size: .9rem;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.linkknopf--leise { color: var(--muted); }
summary.linkknopf { list-style: none; }
summary.linkknopf::-webkit-details-marker { display: none; }

.adressneu { margin: 0 0 8px; }
.adressneu > summary { list-style: none; display: inline-flex; }
.adressneu > summary::-webkit-details-marker { display: none; }
.adressneu[open] > summary { margin-bottom: 14px; }

.kontovorteile { margin: clamp(26px, 5vw, 40px) 0 0; padding-top: 18px; border-top: 1px solid var(--c-line); }
.kontovorteile__titel { margin: 0 0 6px; font-weight: 600; }
.kontovorteile__liste { margin: 0; padding: 0 0 0 1.1em; }
.kontovorteile__liste li { padding: 3px 0; }
.kontovorteile__fuss { margin: 10px 0 0; font-size: .88rem; }



/* ⚠️ DAS «ODER» ZWISCHEN DEN BEIDEN ANMELDEWEGEN. Eine Linie mit einem Wort darin: ohne sie
 *    stehen zwei Formulare untereinander und sehen aus wie ein einziges, dessen zweite Hälfte
 *    man auch noch ausfüllen soll. */
.konto-oder {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: clamp(22px, 4vw, 34px) 0;
    color: var(--muted);
    font-size: .9rem;
}

/* ⚠️ RECHTSBÜNDIG UND KLEIN: «Passwort vergessen?» gehört neben das Passwortfeld, aber es ist
 *    kein zweites Angebot — es ist der Ausweg für den, bei dem das erste nicht klappt. Grösser
 *    gesetzt sähe es aus, als sei das Vergessen der übliche Fall. */
.konto-vergessen {
    margin-top: -6px;
    text-align: right;
    font-size: .88rem;
}

.konto-oder::before,
.konto-oder::after {
    content: '';
    flex: 1 1 auto;
    /* ⚠️ EIN RAND, KEINE FLÄCHE. Als `height: 1px; background: var(--c-line)` gezeichnet, meldete
     *    `ThemeMarktTest` die Regel zu Recht als Fläche ohne eigene Schriftfarbe — die Wache kann
     *    nicht wissen, dass hier wegen `content: ''` nie ein Zeichen steht. Ein Strich ist ohnehin
     *    ein Rand und keine bemalte Fläche; so gesagt, stimmt die Form mit der Absicht überein. */
    border-top: 1px solid var(--c-line);
}


/* ══ Das Gästekonto (D-221, Rahmen D-224) ═══════════════════════════════════════
 *
 * ⛔ KEINE EIGENE FARBWELT. Die Kontoseite ist Teil der Restaurantseite und erbt deren
 *    Schriften und Töne; ein Konto, das aussieht wie ein fremdes Portal, sieht aus wie eine
 *    Anmeldeseite, die jemand untergeschoben hat. Alles hier liest die Token des Hauses.
 *
 * ⚠️ ZWEI SPALTEN, EINE LEISTE. Ab 900 px links die Bereiche (klebend), rechts der Inhalt;
 *    darunter wird die Leiste eine Zeile zum Schieben. Gemessen vorher: 720 px schmal, 5400 px
 *    hoch, mit halben Bildschirmen Papier zwischen den Abschnitten.
 *
 * ⚠️ KARTEN NUR, WO SIE GRUPPIEREN (Adressen, Gutscheine, was gerade läuft); Listen bleiben
 *    Haarlinien, Formulare stehen frei auf der Seite. Keine farbigen Punkte, keine Häkchen in
 *    Kreisen, kein Eyebrow (site/DESIGN.md §6). Form nach 21st.dev «Settings Sidebar Layout»
 *    (felipemenezes098/settings-2) und «Vertical Settings Tabs» (cnippet-dev/v-tabs-13).
 */
.konto { padding: var(--s-7) 0 var(--s-8); }

.konto__kopf {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--s-3) var(--s-5);
    margin: 0 0 var(--s-5);
    padding: 0 0 var(--s-4);
    border-bottom: 1px solid var(--line);
}
.konto .konto__titel { margin: 0 0 6px; font-size: var(--fs-7); line-height: 1.05; }
.konto__wer { margin: 0; color: var(--muted); }
.konto__wer strong { color: var(--text); font-weight: 600; }
.konto__abmelden { margin: 0; }
.konto__kopftext { min-width: 0; }

/* Das Band mit dem Hausfoto: derselbe Schleier wie die Aufmacher (`--hero-schleier`), das Foto vom
   <body> (`--hero-photo`), Titel und Zeile in Hell. Niedriger als ein Aufmacher — hier beginnt
   Verwaltung, nicht die Einladung. */
.konto__kopf--foto {
    min-height: clamp(200px, 26vw, 280px);
    padding: clamp(20px, 3vw, 32px) clamp(18px, 3vw, 32px);
    border: 0;
    border-radius: var(--r-md);
    background: var(--dark-plate);
    background-image: var(--hero-schleier), var(--hero-photo);
    background-size: cover;
    background-position: center;
    color: var(--on-dark);
}
.konto__kopf--foto .konto__titel { color: var(--on-dark); }
.konto__kopf--foto .konto__wer { color: var(--on-dark-soft); }
.konto__kopf--foto .konto__wer strong { color: var(--on-dark); }
/* Der Knopf auf dem Foto ist hell und gefüllt: ein Geisterknopf auf einem dunklen Bild war kaum zu sehen (gemessen). */
/* Drei Klassen: die Aufbauten setzen `.layout-… .btn--ghost` (0,2,0) nach diesem Blatt. */
.konto .konto__kopf--foto .btn--ghost { color: var(--dark-plate); border-color: var(--on-dark); background: var(--on-dark); }
.konto .konto__kopf--foto .btn--ghost:hover { background: var(--on-dark-soft); color: var(--dark-plate); border-color: var(--on-dark-soft); }

.konto-meldung {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0 0 var(--s-5);
    padding: 12px 16px;
    border: 1px solid color-mix(in srgb, var(--enamel) 45%, var(--line));
    border-left: 3px solid var(--enamel);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text);
}
.konto-meldung svg { flex: 0 0 auto; margin-top: 2px; color: var(--enamel); }

.konto__raster { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-5); align-items: start; }
.konto__inhalt { min-width: 0; }

/* ── Die Leiste ──────────────────────────────────────────────────────────────── */
.kontonav {
    display: flex;
    gap: 4px;
    margin: 0 calc(-1 * var(--wrap-rand));
    padding: 0 var(--wrap-rand) 10px;
    overflow-x: auto;
    scrollbar-width: none;
    border-bottom: 1px solid var(--line);
    -webkit-overflow-scrolling: touch;
}
.kontonav::-webkit-scrollbar { display: none; }

.kontonav__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    min-height: 44px;
    padding: 8px 14px;
    border-radius: var(--r-btn);
    color: var(--muted);
    font-size: var(--fs-1);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--t-fast), background var(--t-fast);
}
.kontonav__link svg { flex: 0 0 auto; }
.kontonav__link:hover { color: var(--text); background: color-mix(in oklab, var(--text) 5%, transparent); }
.kontonav__link[aria-current] { color: var(--accent-ink); background: color-mix(in oklab, var(--accent) 9%, transparent); }
.kontonav__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.kontonav__zahl {
    margin-left: 2px;
    padding: 1px 7px;
    border-radius: var(--r-tag);
    background: color-mix(in oklab, var(--text) 8%, transparent);
    font-size: .78rem;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
}
.kontonav__link[aria-current] .kontonav__zahl { background: color-mix(in oklab, var(--accent) 16%, transparent); color: var(--accent-ink); }

@media (min-width: 900px) {
    .konto__raster { grid-template-columns: 232px minmax(0, 1fr); gap: var(--s-7); }
    .kontonav {
        position: sticky;
        top: 96px;
        flex-direction: column;
        gap: 2px;
        margin: 0;
        padding: 0;
        overflow: visible;
        border-bottom: 0;
    }
    .kontonav__link { width: 100%; white-space: normal; }
    .kontonav__zahl { margin-left: auto; }
}
@media (min-width: 1200px) {
    .konto__raster { grid-template-columns: 260px minmax(0, 1fr); }
}

/* ── Die Abschnitte ──────────────────────────────────────────────────────────── */
/* `scroll-margin`, damit der Sprung aus der Leiste nicht unter dem klebenden Kopf landet. */
/* `padding: 0`: die Abschnitte sind <section>, und die Grundregel gibt jeder Section den Bandabstand
   der Startseite — hier wären das 96 px oben UND unten, je Abschnitt (gemessen: die alte Leere). */
.kontoteil { margin: 0 0 var(--s-7); padding: 0; scroll-margin-top: 96px; }
.kontoteil:last-child { margin-bottom: 0; }
.kontoteil__kopf {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-2) var(--s-4);
    margin: 0 0 var(--s-3);
}
/* Zwei Klassen: die Aufbauten setzen `.layout-… h2` (0,1,1) nach diesem Blatt, und eine Klasse allein verlöre. */
.konto .kontoteil__kopf h2 { display: flex; align-items: center; gap: 10px; margin: 0; font-size: var(--fs-5); line-height: 1.15; }
.kontoteil__ic { flex: 0 0 auto; color: var(--accent-ink); }
.kontoteil__kopf .btn { padding-block: 8px; }
.kontoteil__satz { margin: 0 0 var(--s-4); max-width: 62ch; color: var(--muted); }
.konto .kontoteil__h3 { margin: 0 0 var(--s-3); font-size: var(--fs-3); }

.konto .konto__gruss { margin: 0 0 6px; font-size: var(--fs-6); line-height: 1.1; }
.konto__untertitel { margin: 0 0 var(--s-4); max-width: 62ch; color: var(--muted); }

/* Die Kacheln der Übersicht: eine Zahl, ein Wort, ein Sprung. Haarlinien, keine Flächen. */
.konto-zahlen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 10px;
    margin: 0 0 var(--s-5);
    padding: 0;
    list-style: none;
}
/* Jede Kachel mit eigenem Rand: ein Raster mit Linienhintergrund liesse bei ungerader Zahl auf dem
   Telefon eine leere, dunkle Zelle stehen (gemessen auf Tatami, 390 px). */
.konto-zahl {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-height: 88px;
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    transition: background var(--t-fast);
}
.konto-zahl:hover { background: color-mix(in oklab, var(--accent) 6%, var(--surface)); }
.konto-zahl:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
.konto-zahl__ic { margin-bottom: 8px; color: var(--accent-ink); }
.konto-zahl__wert { font-family: var(--serif); font-size: var(--fs-6); line-height: 1; font-variant-numeric: tabular-nums; }
.konto-zahl__wort { font-size: var(--fs-1); color: var(--muted); }

/* ── Leerzustände: klein, mit Zeichen, Haarlinie statt Strichlinie (DESIGN §6), nie ein halber Bildschirm ──────────────── */
.konto-leer {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 16px 18px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: color-mix(in oklab, var(--text) 3%, transparent);
    color: var(--muted);
}
.konto-leer p { margin: 0; display: grid; gap: 2px; }
.konto-leer strong { color: var(--text); font-weight: 600; }
.konto-leer__ic { flex: 0 0 auto; margin-top: 1px; color: var(--accent-ink); }
.konto-leer--zeile { margin: 0; }
.konto-leer--zeile > span { display: block; }
.konto-leer--zeile a { color: var(--accent-ink); }

/* ── Listen: Haarlinien, Zustand als Wort am Ende ─────────────────────────────── */
.konto-liste { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.konto-liste__eintrag {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "wann status" "was summe" "zeilen zeilen" "tun tun";
    gap: 2px 14px;
    align-items: baseline;
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
}
.konto-liste__wann { grid-area: wann; font-weight: 600; }
.konto-liste__was { grid-area: was; color: var(--muted); font-size: var(--fs-1); }
/* Keine Tabellenziffern an Preisen: in der Gastschrift rückt das Komma dann als «19 , 00 €» auseinander
   (Fund 0e, D-226; a3 hat sie in D-225 aus demselben Grund entfernt). Ganze Zahlen (Kacheln) dürfen sie. */
.konto-liste__summe { grid-area: summe; justify-self: end; }
.konto-liste__eintrag .konto-status { grid-area: status; justify-self: end; }
/* Die Gerichte als Bilder: kleine Kacheln, leicht überlappend, mit dem Grund als Ring dazwischen. */
.konto-fotos { grid-area: zeilen; display: flex; margin: 8px 0 0; padding: 0; list-style: none; }
.konto-fotos li { margin-left: -10px; }
.konto-fotos li:first-child { margin-left: 0; }
.konto-fotos__bild {
    display: block;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    object-fit: cover;
    box-shadow: 0 0 0 2px var(--bg);
    background: var(--line-soft);
}
.konto-fotos__bild.ph-tile { display: flex; }
.konto-fotos__bild.ph-tile .ph-tile__mono { font-size: 1.2rem; }
.konto-fotos + ul.konto-liste__zeilen { margin-top: 6px; }
ul.konto-liste__zeilen { grid-area: zeilen; list-style: none; margin: 6px 0 0; padding: 0; font-size: var(--fs-1); color: var(--muted); }
.konto-liste__zeilen li { padding: 1px 0; }
.konto-liste__tun { grid-area: tun; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 10px 0 2px; }
.konto-liste__tun .muted { font-size: .86rem; }
.konto-frist { margin: calc(-1 * var(--s-5)) 0 var(--s-7); font-size: .88rem; color: var(--muted); max-width: 62ch; }

@media (min-width: 640px) {
    .konto-liste__eintrag {
        grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto;
        grid-template-areas: "wann was summe status" "zeilen zeilen zeilen zeilen" "tun tun tun tun";
    }
    .konto-liste__summe { min-width: 5.5em; text-align: right; }
}

/* Das Wort für den Zustand: Schrift und ein dünner Rand, keine farbige Fläche, kein Punkt. */
.konto-status {
    display: inline-block;
    padding: 3px 10px;
    border: 1px solid var(--line);
    border-radius: var(--r-tag);
    font-size: .8rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--muted);
    white-space: nowrap;
}
.konto-status--angenommen,
.konto-status--pending,
.konto-status--waitlisted { border-color: color-mix(in srgb, var(--accent) 50%, var(--line)); color: var(--accent-ink); }
.konto-status--fertig,
.konto-status--abgeholt,
.konto-status--confirmed { border-color: color-mix(in srgb, var(--enamel) 55%, var(--line)); color: var(--enamel); }
.konto-status--abgelehnt,
.konto-status--storniert,
.konto-status--nicht_abgeholt,
.konto-status--declined,
.konto-status--cancelled { color: var(--muted); text-decoration: line-through; text-decoration-thickness: 1px; }

/* ── Adressen als Karten ─────────────────────────────────────────────────────── */
.adresskarten {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
    gap: var(--s-3);
    margin: 0 0 var(--s-4);
    padding: 0;
    list-style: none;
}
.adresskarte {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 18px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text);
}
.adresskarte.is-standard { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); }
.adresskarte__text { flex: 1 1 auto; min-width: 0; }
.adresskarte__text p { margin: 0; }
.adresskarte__titel { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.adresskarte__ic { color: var(--accent-ink); }
.adresskarte__standard {
    padding: 2px 9px;
    border-radius: var(--r-tag);
    background: color-mix(in oklab, var(--accent) 12%, transparent);
    font-size: .78rem;
    font-weight: 600;
    color: var(--accent-ink);
}
.adresskarte__zeile { margin-top: 6px; }
.adresskarte__hinweis { font-size: .9rem; color: var(--muted); }
.adresskarte__gebiet { margin-top: 8px; font-size: .86rem; color: var(--muted); }
.adresskarte__gebiet.is-fehlt { color: var(--wine); }
.adresskarte__tun { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; padding-top: 10px; border-top: 1px solid var(--line-soft); }
.adresskarte__tun form { margin: 0; }
/* Geschlossen steht «Bearbeiten» in der Reihe der Handlungen; geöffnet rückt das Formular
   über die ganze Breite unter sie. */
.adresskarte__aendern[open] { flex-basis: 100%; order: 3; margin-top: 6px; }
.adresskarte__aendern .resform { margin-top: 10px; }

/* ── Gutscheine als Karten ───────────────────────────────────────────────────── */
.gutscheinkarten {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
    gap: var(--s-3);
    margin: 0 0 var(--s-4);
    padding: 0;
    list-style: none;
}
.gutscheinkarte {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    padding: 16px 18px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--surface);
}
/* Der Nachlass ist die Zahl, die der Gast sucht — gross, in der Hausschrift. */
.gutscheinkarte__wert {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 0 0 auto;
    min-width: 4.4em;
    padding: 10px 12px;
    border-radius: var(--r-sm);
    background: color-mix(in oklab, var(--accent) 11%, transparent);
    font-family: var(--serif, inherit);
    font-size: var(--fs-5);
    line-height: 1.1;
    color: var(--accent-ink);
}
.gutscheinkarte__ic { color: var(--accent-ink); }
.gutscheinkarte__text { min-width: 0; }
.gutscheinkarte__text p { margin: 0; }
.gutscheinkarte__name { font-weight: 600; }
.gutscheinkarte__code { margin-top: 2px; font-size: var(--fs-1); color: var(--muted); }
.gutscheinkarte__code b { color: var(--text); letter-spacing: .02em; }
.gutscheinkarte__bedingung { margin-top: 4px; font-size: .86rem; color: var(--muted); }

/* ── Eine allgemeine Karte für weitere Abschnitte (D-225: Favoriten, gemerkte Codes) ─────
   Titel, ein Satz, Linkknöpfe darunter; `--aus` für etwas, das heute nicht auf der Karte steht. */
.konto-karten {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
    gap: var(--s-3);
    margin: 0 0 var(--s-4);
    padding: 0;
    list-style: none;
}
.konto-karte {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px 18px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text);
}
.konto-karte p { margin: 0; }
/* Das Foto des Lieblingsgerichts: oben, randlos bis an den Kasten, 3:2. */
.konto-karte__foto {
    display: block;
    width: calc(100% + 36px);
    /* `height: auto` schlägt das height-Attribut des <img>, sonst gilt das Seitenverhältnis nicht. */
    height: auto;
    aspect-ratio: 3 / 2;
    margin: -16px -18px 4px;
    border-radius: var(--r-sm) var(--r-sm) 0 0;
    object-fit: cover;
    background: var(--line-soft);
}
.konto-karte__foto.ph-tile { display: flex; }
.konto-karte__foto.ph-tile .ph-tile__mono { font-size: 2.6rem; }
.konto-karte--aus .konto-karte__foto { opacity: .55; }
.konto-karte__titel { font-weight: 600; }
.konto-karte__satz { font-size: var(--fs-1); color: var(--muted); }
.konto-karte__tun { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line-soft); }
.konto-karte__tun form { margin: 0; }
/* Kein gestrichelter Rand (DESIGN §6): den Zustand sagt der Satz, der Titel tritt zurück. */
.konto-karte--aus { background: transparent; }
.konto-karte--aus .konto-karte__titel { color: var(--muted); }

/* ── Formulare und die Handlungen am Konto ───────────────────────────────────── */
.konto-form { max-width: 560px; }
.konto-form .resform__field input[readonly] { color: var(--muted); background: color-mix(in oklab, var(--text) 4%, transparent); }
.konto-aktionen {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 20px;
    margin: var(--s-6) 0 0;
    padding-top: var(--s-4);
    border-top: 1px solid var(--line);
}
.konto-aktionen form { margin: 0; }
.konto-aktionen__loeschen { font-size: .9rem; color: var(--muted); }
.konto-aktionen__loeschen:hover { color: var(--wine); }


/* ══ Gerade bei uns — was gerade läuft, im Konto ganz oben ═══════════════════════
 *
 * ⛔ DIE FARBEN SIND DIE DES HAUSES, keine neuen. `--accent` heißt «das Haus arbeitet daran»,
 *    `--enamel` heißt «fertig, komm», `--muted` heißt «noch nichts geschehen». Beide Paletten
 *    definieren alle drei — ein Token, das nur im Tagblock steht, ist genau der Fehler, den
 *    `ThemeMarktTest` seit dem Keksband jagt.
 *
 * ⚠️ SEMANTISCHE FARBE IST NICHT DER AKZENT DER SEITE. Dass «in der Küche» den Hausakzent
 *    trägt, ist kein Zufall, sondern die Aussage: an dieser Bestellung wird gerade gearbeitet.
 *    «Abholbereit» bekommt die zweite Farbe, weil es der einzige Zustand ist, bei dem der Gast
 *    aufstehen muss.
 */
.jetzt { margin: 0; display: flex; flex-direction: column; gap: 14px; }
.jetzt__titel { margin: 0 0 2px; font-size: var(--fs-3); }

.jetzt-karte {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: clamp(16px, 3.5vw, 24px);
    border: 1px solid var(--line);
    border-radius: var(--r-sm, 10px);
    background: var(--surface);
    color: var(--text);
}

/* ⚠️ DER STREIFEN SAGT DEN ZUSTAND, BEVOR EIN WORT GELESEN IST — und er sitzt links, weil
 *    dort das Auge auf einer Karte zuerst ankommt. `border-left` statt eines Pseudo-Elements:
 *    ein Rand verschiebt nichts und kann nicht über den abgerundeten Ecken hängen. */
.jetzt-karte--angenommen { border-left: 3px solid var(--accent); }
.jetzt-karte--fertig { border-left: 3px solid var(--enamel); }
.jetzt-karte--confirmed { border-left: 3px solid var(--enamel); }
.jetzt-karte--wartet,
.jetzt-karte--pending,
.jetzt-karte--waitlisted { border-left: 3px solid var(--line); }

.jetzt-karte__kopf {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 12px;
    margin: 0;
}

.jetzt-karte__art {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8125rem;
    color: var(--muted);
}
.jetzt-karte__art svg { color: var(--accent-ink); }

/* `tabular-nums`: Nummern, Uhrzeiten und Beträge stehen hier untereinander, und
 * proportionale Ziffern lassen die Spalte zappeln. */
.jetzt-karte__nr { font-variant-numeric: tabular-nums; }
.jetzt-karte__summe { margin-left: auto; color: var(--muted); }
.jetzt-karte__satz { margin: 0; }

/* ⚠️ AUF DEM TELEFON WIRD AUS «nach rechts» EIN GESTRANDETES WORT. `margin-left: auto`
 *    schiebt den Betrag an den rechten Rand — sobald die Zeile umbricht, steht er allein auf
 *    einer eigenen Zeile ganz rechts, weit weg von allem, wozu er gehört. Gemessen an
 *    «30.08.2026 um 12:30 Uhr» + «4 Personen» auf 390px: passt nicht nebeneinander, also
 *    bricht es, also stand «4 Personen» verloren rechts. Untereinander links gelesen ergibt
 *    dieselbe Angabe einen Satz. */
@media (max-width: 460px) {
    .jetzt-karte__summe { margin-left: 0; }
}

/* Das Zeichen für den Zustand eines Tisches — dort, wo bei der Bestellung die Stufen stehen. */
.jetzt-karte__marke {
    align-self: flex-start;
    margin: 0;
    padding: 4px 12px;
    border-radius: 999px;
    border: 1px solid var(--line);
    font-size: .82rem;
    color: var(--muted);
}

.jetzt-karte--confirmed .jetzt-karte__marke { border-color: var(--enamel); color: var(--enamel); }

/* ⚠️ `align-self`, SONST WIRD DER ABSAGEKNOPF SO BREIT WIE DIE KARTE. Die Karte ist ein
 *    Flex-Container in Spaltenrichtung; ein Formular darin streckt sich über die volle Breite
 *    und sieht damit aus wie der Hauptweg dieser Seite. Absagen ist der seltene Fall — er
 *    gehört sichtbar, aber nicht gross. `margin: 0`, weil das Formular sonst den Abstand der
 *    Karte (`gap: 14px`) verdoppelt. */
.jetzt-karte__tun { align-self: flex-start; margin: 0; }

/* ── Die Stufen einer Bestellung ───────────────────────────────────────
 *
 * ⚠️ DIE LINIE WIRD AUS DEM SCHRITT SELBST GEZOGEN, nicht aus einem Balken darunter: so
 *    bleibt sie bei jeder Anzahl von Stufen und in jeder Breite an den Punkten hängen. Der
 *    erste Schritt bekommt keine — sonst liefe sie ins Nichts links.
 */
.stufen {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.stufen__schritt {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    color: var(--muted);
    font-size: .78rem;
    line-height: 1.25;
}

.stufen__schritt::before {
    content: '';
    position: absolute;
    top: 6px;
    right: 50%;
    left: -50%;
    height: 2px;
    background: var(--line);
}

.stufen__schritt:first-child::before { content: none; }

.stufen__punkt {
    position: relative;
    z-index: 1;
    width: 14px;
    height: 14px;
    border-radius: 999px;
    border: 2px solid var(--line);
    background: var(--surface);
}

.stufen__wort { max-width: 10ch; }

/* Erledigt: die Linie davor und der Punkt tragen die Hausfarbe. */
.stufen__schritt.ist-vorbei { color: var(--text); }
.stufen__schritt.ist-vorbei::before { background: var(--accent); }
.stufen__schritt.ist-vorbei .stufen__punkt { border-color: var(--accent); background: var(--accent); }

/* ⚠️ HIER IST DAS ESSEN GERADE. Der Ring ist grösser als der Punkt und nicht nur farbig:
 *    wer Farben schlecht unterscheidet, sieht trotzdem, welche Stufe die aktuelle ist. */
.stufen__schritt.ist-jetzt { color: var(--text); font-weight: 600; }
.stufen__schritt.ist-jetzt::before { background: var(--accent); }
.stufen__schritt.ist-jetzt .stufen__punkt {
    border-color: var(--accent);
    background: var(--accent);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 24%, transparent);
}

/* «Abholbereit» ist der eine Zustand, bei dem der Gast aufstehen muss — er bekommt die
 * zweite semantische Farbe, nicht den Arbeitsakzent. */
.jetzt-karte--fertig .stufen__schritt.ist-jetzt .stufen__punkt {
    border-color: var(--enamel);
    background: var(--enamel);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--enamel) 24%, transparent);
}

.jetzt-karte--fertig .stufen__schritt.ist-vorbei::before,
.jetzt-karte--fertig .stufen__schritt.ist-jetzt::before { background: var(--enamel); }
.jetzt-karte--fertig .stufen__schritt.ist-vorbei .stufen__punkt { border-color: var(--enamel); background: var(--enamel); }

/* ⚠️ AUF SCHMALEN TELEFONEN wird aus vier Spalten à ~80px ein Silbenbrei. Unter 380px
 *    trägt nur noch die aktuelle Stufe ihr Wort; die Punkte bleiben alle stehen, damit der Weg
 *    als Ganzes sichtbar ist. */
@media (max-width: 380px) {
    .stufen__schritt:not(.ist-jetzt) .stufen__wort { display: none; }
    .stufen__schritt { gap: 0; }
}

/* Der Widerruf auf der Datenschutzseite — eine Einwilligung ohne Rückweg ist keine. */
.einwilligung-widerruf { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }

/* ── Privatsphäre-Einstellungen: der Link in der Fusszeile, das Fenster und die Tabelle ──────
 *
 * ⛔ EIN FENSTER, ZWEI EBENEN (D-236). Ebene 1 ist die Frage beim ersten Besuch: Titel in der
 *    Mitte, drei Absätze, zwei gleich grosse Knöpfe übereinander und der Weg nach Ebene 2. Ebene 2
 *    sind die Karten mit Schalter und Tabellen — dieselbe Ebene, die der Link in der Fusszeile
 *    öffnet; sie ist breiter, weil Tabellen darin stehen. Das Band am unteren Rand gibt es seit
 *    D-236 nicht mehr (hinter Leisten und Fusszeile verschwunden, 10.10.2026 gemessen 10 685 px
 *    tief): ein Fenster in der Mitte sieht jeder beim ersten Blick.
 *
 * ⛔ TOKENS, DIE ES IN BEIDEN PALETTEN GIBT: `--surface`, `--text`, `--line`, `--muted`, `--accent`.
 *    Das alte Band hatte an `--c-paper` ein Kontrastloch (hell auf hell, 1,07:1), weil der Rohwert
 *    nur in `:root` steht und im Nachtblock fehlt. Das Fenster öffnet auf der Speisekarte, die
 *    standardmässig dunkel startet — es darf nicht das Erste sein, was ein Gast dort nicht lesen kann.
 *
 * ⛔ «ALLE AKZEPTIEREN» UND «WEITER OHNE EINWILLIGUNG» SIND GLEICH GROSS: dieselbe Klasse
 *    `.keks-fenster__knopf` gibt beiden volle Breite, 48 px Höhe und dieselbe Schrift; der
 *    Unterschied ist allein die Füllung (Akzent gegen eine stille Fläche aus 8 % `--text`). Ein
 *    Ablehnen, das kleiner, blasser oder einen Klick tiefer liegt, ist die Bauform, die die
 *    Aufsichtsbehörden als Dark Pattern beanstanden — und die eine Einwilligung angreifbar macht.
 */
.footer-cookie, .footer-intern { display: inline-flex; align-items: center; gap: 6px; }
.footer-cookie svg, .footer-intern svg { flex: none; }

.keks-fenster {
    /* Ein natives <dialog> ohne eigenen Innenabstand: der Rahmen darin füllt es ganz aus, damit ein
       Klick auf den abgedunkelten Rand (Ziel = das Fenster selbst) von einem Klick darin zu unterscheiden ist. */
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-xl);
    inline-size: min(40rem, calc(100vw - 24px));
    max-block-size: calc(100dvh - 24px);
    /* Nur der Inhalt scrollt (siehe `.keks-fenster__inhalt`); das Fenster selbst nie — sonst zwei
       Rollbalken, einer am Fenster, einer am Inhalt. Der Rahmen darin ist `display: contents`, damit
       Kopf, Inhalt, Fuss und Rechtslinks direkt die Flex-Kinder des Fensters sind und der Inhalt den
       Rest der Höhe bekommt. `[open]` davor: die UA-Regel `dialog:not([open]) { display: none }`
       darf nicht von einem blossen `display: flex` überstimmt werden. */
    overflow: hidden;
}
.keks-fenster[open] { display: flex; flex-direction: column; }

/* Ebene 2 trägt Tabellen und drei Knöpfe nebeneinander: breiter. */
.keks-fenster[data-keks-ebene-aktiv="2"] { inline-size: min(54rem, calc(100vw - 24px)); }

.keks-fenster::backdrop { background: rgba(0, 0, 0, .55); }

/* VON UNTEN HERAUF, NACH UNTEN WEG (10.10.2026). `@starting-style` für den Anfang, `allow-discrete`
   hält `display` und die Deckschicht (`overlay`) bis zum Ende der Bewegung, damit sich das Fenster
   auch beim Schliessen noch bewegt. Auf dem Breitbild steigt es nur wenig und blendet ein; auf dem
   Telefon ist es ein Blatt am unteren Rand. Ohne diese Fähigkeit (ältere Browser) ein sofortiges
   Ein und Aus, nie ein kaputtes Fenster. */
.keks-fenster {
    opacity: 0;
    transform: translateY(24px);
    transition:
        transform .42s var(--leiste-kurve, cubic-bezier(.22, 1, .36, 1)),
        opacity .26s ease,
        overlay .42s allow-discrete,
        display .42s allow-discrete;
}
.keks-fenster[open] { opacity: 1; transform: none; }
.keks-fenster::backdrop {
    opacity: 0;
    transition: opacity .3s ease, overlay .42s allow-discrete, display .42s allow-discrete;
}
.keks-fenster[open]::backdrop { opacity: 1; }
@starting-style {
    .keks-fenster[open] { opacity: 0; transform: translateY(24px); }
    .keks-fenster[open]::backdrop { opacity: 0; }
}

@media (max-width: 640px) {
    .keks-fenster, .keks-fenster[data-keks-ebene-aktiv="2"] {
        inline-size: 100%;
        max-inline-size: 100%;
        margin: auto 0 0;
        max-block-size: calc(100dvh - 40px - env(safe-area-inset-top, 0px));
        border-inline: 0;
        border-bottom: 0;
        border-radius: 20px 20px 0 0;
        padding-bottom: env(safe-area-inset-bottom, 0px);
        transform: translateY(100%);
    }
    .keks-fenster[open] { transform: none; }
    @starting-style {
        .keks-fenster[open] { transform: translateY(100%); }
    }
}

.keks-fenster__rahmen { display: contents; }

/* Der Titel in der Mitte, das Kreuz rechts daneben — der Kopf reserviert beidseits Platz dafür,
   damit der Titel auch auf dem Telefon mittig bleibt und nie unter das Kreuz rutscht. */
.keks-fenster__kopf {
    position: relative;
    padding: var(--s-5) 56px var(--s-4);
    text-align: center;
    border-block-end: 1px solid var(--line);
}

.keks-fenster .keks-fenster__titel { margin: 0; padding: 0; border: 0; background: none; box-shadow: none; font-family: var(--sans); font-size: 1.375rem; font-weight: 700; line-height: 1.3; letter-spacing: 0; text-transform: none; }
.keks-fenster .keks-fenster__titel:focus { outline: none; }
/* ⚠️ `.keks-fenster` VORAN, damit die Regel gegen die Überschriften der Vorlagen gewinnt: eine
   Vorlage stellt `.layout-… h2` ein (Spezifität 0,1,1), und ein Fenster mit vierzig Pixel hohem
   Serifentitel wäre nur die Überschrift, nicht der Inhalt. */
/* Auf dem Telefon passt «Privatsphäre-Einstellungen» so auf eine Zeile zwischen Rand und Kreuz. Die
   Regel steht NACH der Grundregel: gleiche Spezifität, die spätere gewinnt. */
@media (max-width: 640px) {
    .keks-fenster .keks-fenster__titel { font-size: 1.125rem; }
}

.keks-fenster__zu {
    position: absolute; inset-block-start: 50%; inset-inline-end: var(--s-4); transform: translateY(-50%);
    display: inline-flex; align-items: center; justify-content: center;
    inline-size: 40px; block-size: 40px; padding: 0;
    border: 1px solid var(--line); border-radius: var(--r-sm);
    background: transparent; color: var(--text); cursor: pointer;
}
.keks-fenster__zu:hover { border-color: var(--text); }
.keks-fenster__zu:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.keks-fenster__inhalt { flex: 1 1 auto; min-block-size: 0; overflow-y: auto; padding: var(--s-5); font-size: var(--fs-1); line-height: 1.6; }
.keks-fenster__kopf, .keks-fenster__fuss, .keks-fenster__rechts { flex: none; }
/* Die Ebenen sind `<div>`, keine `<section>`: `section { padding: var(--s-8) 0 }` der Vorlagen hätte
   sonst eine Leerzeile von 64 px über den ersten Absatz gelegt. */
.keks-ebene { margin: 0; padding: 0; }
.keks-fenster__inhalt > .keks-ebene > p:first-child { margin-block-start: 0; }

/* Ebene 1 liest sich wie ein Brief: mittig, höchstens 60 Zeichen breit, drei Absätze. */
.keks-ebene--frage { text-align: center; }
.keks-ebene--frage p { margin: 0 auto var(--s-4); max-inline-size: 60ch; }
.keks-ebene--frage p:last-child { margin-block-end: 0; }
.keks-fenster__klein { color: var(--muted); font-size: var(--fs-0); line-height: 1.55; }
.keks-fenster__klein a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

.keks-fenster__fuss {
    padding: var(--s-4) var(--s-5);
    border-block-start: 1px solid var(--line);
}

/* Übereinander, volle Breite, alle gleich hoch — auf jeder Breite. Nur Ebene 2 stellt ihre drei
   Knöpfe auf dem Breitbild nebeneinander, weil dort Platz ist und die Tabellen das Fenster breit machen. */
.keks-fenster__knoepfe { display: flex; flex-direction: column; gap: var(--s-3); }
.keks-fenster__knopf {
    inline-size: 100%; min-block-size: 48px; justify-content: center;
    border-color: var(--line); background: transparent; color: var(--text);
}
.keks-fenster__knopf.btn--primary { border-color: transparent; background: var(--accent); color: var(--on-accent); }
.keks-fenster__knopf--still { border-color: transparent; background: color-mix(in srgb, var(--text) 8%, var(--surface)); color: var(--text); }
.keks-fenster__knopf--still:hover { background: color-mix(in srgb, var(--text) 13%, var(--surface)); }

/* Der Weg nach Ebene 2 — ein Knopf, der wie ein Link aussieht, weil er kein Ziel hat, sondern das
   Fenster umschaltet. `type="button"`, kein `href`: ohne Skript gäbe es keine Ebene 2 zu zeigen. */
.keks-fenster__link {
    align-self: center; margin: 0; padding: var(--s-2) var(--s-3);
    border: 0; background: none; font: inherit; font-size: var(--fs-1); font-weight: 500;
    color: var(--accent); text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
    min-block-size: 44px;
}
.keks-fenster__link:hover { color: var(--accent-strong, var(--accent)); }
.keks-fenster__link:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }

@media (min-width: 641px) {
    .keks-fenster__knoepfe--liste { flex-direction: row; justify-content: flex-end; }
    .keks-fenster__knoepfe--liste .keks-fenster__knopf { inline-size: auto; min-inline-size: 10em; }
}

/* Die Rechtslinks ganz unten, auf einer stillen Fläche — dieselben wie in der Fusszeile. */
.keks-fenster__rechts {
    display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: var(--s-2) var(--s-3);
    padding: var(--s-3) var(--s-5) calc(var(--s-3) + env(safe-area-inset-bottom, 0px));
    border-block-start: 1px solid var(--line);
    background: color-mix(in srgb, var(--text) 3%, var(--surface));
    font-size: var(--fs-0);
}
.keks-fenster__rechts a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.keks-fenster__rechts a:hover { color: var(--text); }
.keks-fenster__rechts a + a::before { content: '•'; margin-inline-end: var(--s-3); color: var(--muted); display: inline-block; }

/* Die Zeile «Ihre Auswahl»: was gilt, seit wann, bis wann (site.js füllt sie). */
.keks-gespeichert {
    margin: var(--s-3) 0 0; padding: var(--s-3) var(--s-4);
    border: 1px solid var(--line); border-radius: var(--r-sm);
    font-size: var(--fs-0); font-weight: 600; line-height: 1.5;
}
.keks-gespeichert:empty { display: none; }

.keks-liste .keks-liste__titel { margin: var(--s-5) 0 var(--s-2); font-family: var(--sans); font-size: 1rem; font-weight: 700; line-height: 1.35; letter-spacing: 0; }
.keks-liste__hinweis { margin: 0 0 var(--s-3); color: var(--muted); font-size: var(--fs-0); }

.keks-tabelle { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-0); margin-block-end: var(--s-4); }
.keks-tabelle th, .keks-tabelle td {
    text-align: start; vertical-align: top; font-weight: 400;
    padding: var(--s-3) var(--s-3) var(--s-3) 0;
    border-block-end: 1px solid var(--line-soft);
}
.keks-tabelle thead th { font-family: var(--sans); font-size: var(--fs-0); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--muted); background: transparent; border-block-end-color: var(--line); }
.keks-tabelle tbody th { font-weight: 500; inline-size: 30%; }
.keks-tabelle code { overflow-wrap: break-word; }
.keks-tabelle__art { display: block; margin-block-start: 2px; color: var(--muted); font-size: .8125rem; }

/* ⚠️ AUF DEM TELEFON WIRD AUS JEDER ZEILE EINE KARTE: vier Spalten in 360px wären ein
 *    waagerechter Scrollbereich, den niemand als solchen erkennt. Die Spaltenköpfe wandern als
 *    kleine Beschriftung (`data-label`) vor jeden Wert. */
@media (max-width: 640px) {
    .keks-tabelle thead { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); }
    .keks-tabelle, .keks-tabelle tbody, .keks-tabelle tr, .keks-tabelle th, .keks-tabelle td { display: block; }
    .keks-tabelle tr { padding-block: var(--s-3); border-block-end: 1px solid var(--line-soft); }
    .keks-tabelle th, .keks-tabelle td { padding: 2px 0; border: 0; }
    .keks-tabelle tbody th { inline-size: auto; }
    .keks-tabelle td::before { content: attr(data-label); display: block; color: var(--muted); font-size: .8125rem; }
}

/* ── Die Gruppen im Fenster: je eine Karte, rechts «Immer aktiv» oder der Schalter ────────── */
.keks-liste--fenster .keks-gruppe {
    margin-block-start: var(--s-4); padding: var(--s-4);
    border: 1px solid var(--line); border-radius: var(--r-md);
}
.keks-liste--fenster .keks-gruppe__kopf { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-4); }
.keks-liste--fenster .keks-gruppe__text { min-inline-size: 0; }
.keks-liste--fenster .keks-liste__titel { margin: 0 0 var(--s-2); }
.keks-liste--fenster .keks-liste__hinweis { margin-block-end: 0; }
.keks-gruppe__immer {
    flex: none; padding: 2px var(--s-3);
    border: 1px solid var(--line); border-radius: 999px;
    font-size: var(--fs-0); font-weight: 600; white-space: nowrap;
}
/* ⚠️ AUF DEM TELEFON STEHT «Immer aktiv» ÜBER DEM TITEL, nicht daneben: nebeneinander bliebe dem Text
 *    ein Streifen von hundert Pixeln, in dem jedes Wort allein in einer Zeile steht. */
@media (max-width: 640px) {
    .keks-liste--fenster .keks-gruppe { padding: var(--s-3); }
    .keks-liste--fenster .keks-gruppe__kopf { flex-direction: column-reverse; align-items: flex-start; gap: var(--s-2); }
}

/* «Einträge ansehen (n)»: die Tabelle liegt hinter einem Aufklappfeld, nicht im Weg. */
.keks-details { margin-block-start: var(--s-3); }
.keks-details > summary {
    display: flex; align-items: center; gap: var(--s-2);
    padding-block: var(--s-2); cursor: pointer; list-style: none;
    font-size: var(--fs-0); font-weight: 600;
}
.keks-details > summary::-webkit-details-marker { display: none; }
.keks-details > summary::before {
    content: ''; flex: none; inline-size: .5em; block-size: .5em;
    border-inline-end: 2px solid currentColor; border-block-end: 2px solid currentColor;
    transform: rotate(-45deg);
}
.keks-details[open] > summary::before { transform: rotate(45deg); }
.keks-details > summary:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }
.keks-details .keks-tabelle { margin-block-end: 0; }

/* ── Der Schalter: ein echter Schalter statt eines Kästchens ─────────────────────────────────
 *
 * ⚠️ DIE BEDIENUNG IST EIN `<input type="checkbox" role="switch">`: Tastatur, Fokus, Vorlesen und
 *    `:checked` bringt der Browser mit; hier ist nur das Aussehen. Der Rand trägt die Grenze (mehr als
 *    3:1 gegen die Fläche, in beiden Paletten), nicht die Füllung allein.
 * ⚠️ BEWEGUNG NUR, WENN ERWÜNSCHT: der Knopf gleitet nur ohne `prefers-reduced-motion`. */
.keks-schalter {
    display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
    margin-block-start: var(--s-3); padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--line-soft); cursor: pointer;
}
.keks-schalter__text { display: flex; flex-direction: column; gap: 2px; }
.keks-schalter__klein { color: var(--muted); font-size: var(--fs-0); }
.keks-schalter__kasten {
    appearance: none; -webkit-appearance: none;
    flex: none; position: relative; margin: 0; cursor: pointer;
    inline-size: 46px; block-size: 26px;
    border: 2px solid var(--muted); border-radius: 999px; background: transparent;
}
.keks-schalter__kasten::after {
    content: ''; position: absolute; inset-block-start: 3px; inset-inline-start: 3px;
    inline-size: 16px; block-size: 16px; border-radius: 50%; background: var(--muted);
}
.keks-schalter__kasten:checked { border-color: var(--accent); background: var(--accent); }
.keks-schalter__kasten:checked::after { inset-inline-start: 23px; background: var(--on-accent); }
.keks-schalter__kasten:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
    .keks-schalter__kasten, .keks-schalter__kasten::after { transition: inset-inline-start .15s ease-out, background-color .15s ease-out, border-color .15s ease-out; }
}
@media (forced-colors: active) {
    .keks-schalter__kasten:checked { border-color: Highlight; background: Highlight; }
    .keks-schalter__kasten::after { background: CanvasText; }
    .keks-schalter__kasten:checked::after { background: HighlightText; }
}

/* Wer Bewegung abgeschaltet hat, bekommt kein Gleiten: das Fenster ist einfach da oder weg. */
@media (prefers-reduced-motion: reduce) {
    .keks-fenster, .keks-fenster::backdrop { transition: none; }
}

/* Der Hinweis auf das Konto, auf dem Beleg. Ein Kasten, kein Knopf: er ist ein Angebot und
   kein Schritt, den der Gast noch vor sich hätte. */
.konto-einladung {
    margin: clamp(18px, 3vw, 28px) 0 0;
    padding: 14px 16px;
    border: 1px solid var(--c-line);
    border-radius: 3px;
    font-size: .95rem;
    line-height: 1.55;
}

/* ⚠️ DIESER BLOCK STEHT VOR DEM KONTOR-BLOCK, UND DAS IST KEINE GESCHMACKSFRAGE.
      `LayoutKontorTest` liest alles hinter der ersten `.layout-kontor`-Regel als dessen
      Block und verlangt, dass JEDE Regel darin an `.layout-kontor` gebunden ist. Ans
      Dateiende angehängt landete «.hinweis-band» dort — ungebunden — und nahm ausserdem
      `[hidden]` mit, das der zweite Wächter dort ebenfalls verbietet. Zwei rote Tests aus
      einer Zeilennummer. Dieselbe Falle steht weiter oben schon einmal beschrieben
      (`.ladenkopf__name`); sie erwischt jeden, der «unten anfügen» für neutral hält. */

/* ==========================================================================
   BETRIEBSFERIEN — das Band und das Türschild
   ==========================================================================

   ⛔ DAS SCHILD TRÄGT SEINE FARBEN SELBST, statt sie aus dem Tag/Nacht-Umschalter zu holen.
      Die Speisekarte läuft standardmässig dunkel, alle anderen Seiten hell — dasselbe Schild
      erschiene also auf zwei Seiten desselben Hauses in zwei Ausführungen. Ein Schild an einer
      Tür sieht abends aus wie morgens. Deshalb Papier, Messing und Tinte, direkt benannt.

   ⚠️ DAS BAND NIMMT NICHT DIE MARKENFARBE, und seit es auch die Ankündigungen trägt, gilt das
      für beide Sorten Hinweis. Die alte `.announce` stand in `--accent`, weil eine Neuigkeit
      dem Haus gehört. «Wir sind zu» gehört keinem — und in einem Haus mit grüner Marke wäre
      ausgerechnet die Schliessung die freundlichste Farbe auf der Seite gewesen. Ein Band, das
      je nach Anlass die Farbe wechselt, wäre ausserdem kein Band mehr, sondern zwei. */

.hinweis-band {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 2px var(--s-3);
    padding: 10px var(--s-4);
    background: var(--c-ink);
    color: var(--on-dark);
    font-size: var(--fs-1);
    line-height: 1.45;
    text-align: center;
    /* Der Messingstrich unten trennt das Band vom Kopf darunter, ohne eine zweite Linie zu
       zeichnen: ohne ihn schwimmen zwei dunkle Flächen ineinander, sobald ein Haus einen
       dunklen Kopf hat. */
    border-bottom: 2px solid var(--c-brass);
}

/* ⛔ DER LINK TRÄGT DIE FARBE DES BANDES, NICHT DIE DER SEITE. Ohne diese Zeile erbt eine
   Ankündigung mit Link das globale `a { color: var(--link) }` — Petrol auf Tinte, gemessen
   rund 2,5:1, und zwar in der obersten Zeile der Seite, an der Stelle, die zuerst gelesen
   wird. Der Kontor-Aufbau hatte die Regel längst; der Grundentwurf nicht. */
.hinweis-band a {
    color: var(--on-dark);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.hinweis-band__wort {
    font-weight: 700;
    letter-spacing: .01em;
}

.hinweis-band__satz {
    color: var(--on-dark-soft);
}

/* DAS DEMO-BAND (D-133) trägt Messing statt Tinte: es ist keine Nachricht des Hauses, sondern
   eine der Plattform, und es darf neben einem Urlaubs- oder Hinweisband stehen, ohne mit ihm
   zu einem Balken zu verschwimmen. Tinte auf Messing, gemessen rund 7:1. */
.hinweis-band--demo {
    background: var(--c-brass);
    color: var(--c-ink);
    border-bottom-color: var(--c-ink);
}

.hinweis-band--demo .hinweis-band__satz,
.hinweis-band--demo a {
    color: var(--c-ink);
}

/*
 * ⚠️ IM KOPF, ALSO GEGEN DESSEN DURCHSICHT. `.site-header` liegt bei 88 % Deckkraft mit
 *    `backdrop-filter` über der Seite; ein Band ohne eigene volle Deckkraft liesse den Text
 *    darunter durchscheinen, und «Wir machen Sommerpause» stünde über einem Foto. Deshalb
 *    `--c-ink` ohne Mischung — und der negative Rand, weil `.site-header` selbst keinen
 *    Innenabstand hat, seine Kinder aber im `.wrap` sitzen.
 */
.site-header > .hinweis-band {
    position: relative;
    z-index: 1;
}

/*
 * ⛔ AUF DEM TELEFON KOSTET EIN KLEBENDER HINWEIS ECHTEN PLATZ, und das ist die einzige Zahl,
 *    die hier zählt. Gemessen auf 390 × 844 mit dem vollen Satz: das Band brach auf DREI
 *    Zeilen, der Kopf wurde 157 px hoch — ein Fünftel des Bildschirms, dauerhaft, auf jeder
 *    Seite, während der Gast scrollt. Auf dem Schreibtisch sind es 109 px und niemand merkt es.
 *
 *    Deshalb wird auf schmalen Schirmen der Satz enger gesetzt statt weggelassen: kleinere
 *    Schrift, weniger Innenabstand, engere Zeilen. Die Auskunft bleibt vollständig — sie ist
 *    der Grund, warum das Band überhaupt klebt — sie nimmt nur weniger Raum ein.
 */
@media (max-width: 719px) {
    .hinweis-band {
        gap: 0 var(--s-2);
        padding: 7px var(--s-3);
        font-size: var(--fs-0);
        line-height: 1.35;
    }

    /* ⚠️ `balance` UND NICHT `pretty`, weil hier eine ganze ZEILE auf dem Spiel steht und nicht
          nur ihr Aussehen. Ohne das brach «… ab 17:00 Uhr» so um, dass in der dritten Zeile das
          Wort «Uhr» allein stand: 18 px Kopfhöhe für drei Buchstaben, dauerhaft klebend. */
    .hinweis-band__satz {
        text-wrap: balance;
    }
}

/* Der Trennpunkt erscheint nur, solange beide Teile in einer Zeile stehen. Auf dem Telefon
   brechen sie um, und ein Punkt am Zeilenende wäre ein Satzzeichen, das keines ist. */
@media (min-width: 720px) {
    .hinweis-band__satz::before {
        content: "·";
        margin-right: var(--s-3);
        color: var(--on-dark-accent);
    }
}

/* ---------- Das Schild ---------- */

/* Ohne diese Zeile ist `hidden` wirkungslos, sobald irgendeine Regel `display` setzt — und
   dann liegt ein unsichtbares, aber anklickbares Feld über der ganzen Seite. */
.urlaub[hidden] { display: none; }

.urlaub {
    position: fixed;
    inset: 0;
    z-index: 90;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: clamp(16px, 7vh, 76px) var(--s-4) var(--s-6);
    background: var(--scrim-74);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    /* Ein langes Schild auf einem kurzen Telefon muss scrollen können. */
    overflow-y: auto;
    overscroll-behavior: contain;
}

/*
 * DIE GANZE AUFHÄNGUNG SCHWINGT, nicht die Karte allein — und der Drehpunkt sitzt oben an der
 * Stange, weil ein Schild dort hängt. Mit `transform-origin: center` würde es sich um seine
 * eigene Mitte drehen, was kein Pendel ist, sondern ein Kreisel.
 */
.urlaub__haenge {
    position: relative;
    width: min(460px, 100%);
    padding-top: 54px;
    transform-origin: 50% 0;
    /* `will-change` nur hier: Motion bewegt `y` und `rotate` gleichzeitig auf diesem einen
       Element, und genau das ist die Stelle, an der ein Telefon sonst ruckelt. */
    will-change: transform;
}

.urlaub__seile {
    position: absolute;
    inset: 0 0 auto;
    height: 54px;
    pointer-events: none;
}

.urlaub__stange {
    position: absolute;
    top: 0;
    left: 50%;
    width: 128px;
    height: 3px;
    margin-left: -64px;
    border-radius: 2px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--c-brass) 55%, transparent),
        var(--c-brass) 22%,
        var(--c-brass) 78%,
        color-mix(in srgb, var(--c-brass) 55%, transparent));
}

.urlaub__seil {
    position: absolute;
    top: 3px;
    bottom: 0;
    width: 2px;
    /* Von oben nach unten wachsend, weil Motion `scaleY` von 0 aufzieht: mit dem
       Standard-Ursprung in der Mitte käme die Schnur aus ihrer eigenen Mitte heraus. */
    transform-origin: 50% 0;
    background: linear-gradient(180deg, var(--c-brass), color-mix(in srgb, var(--c-brass) 72%, var(--c-ink)));
}

.urlaub__seil--links  { left: calc(50% - 58px); }
.urlaub__seil--rechts { left: calc(50% + 56px); }

.urlaub__karte {
    position: relative;
    padding: var(--s-6) var(--s-5) var(--s-5);
    background: var(--c-ivory);
    border: 1px solid var(--c-stone);
    border-radius: var(--r-md);
    box-shadow: 0 26px 60px -18px rgba(20, 24, 28, .55), 0 3px 10px rgba(20, 24, 28, .18);
    text-align: center;
    color: var(--c-ink);
}

/* Die zweite, eingerückte Linie — der Doppelrahmen einer gedruckten Karte. Als Pseudoelement,
   damit dafür kein zweites <div> im Dokument steht, das nichts sagt. */
.urlaub__karte::before {
    content: "";
    position: absolute;
    inset: 7px;
    border: 1px solid color-mix(in srgb, var(--c-brass) 40%, transparent);
    border-radius: calc(var(--r-md) - 5px);
    pointer-events: none;
}

/* Die beiden Ösen, an denen die Schnüre sitzen. Ohne sie enden die Schnüre auf dem Papier,
   und das Schild wirkt aufgeklebt statt aufgehängt. */
.urlaub__karte::after {
    content: "";
    position: absolute;
    top: 9px;
    left: 50%;
    width: 6px;
    height: 6px;
    margin-left: -61px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--c-brass) 80%, var(--c-ink));
    box-shadow: 114px 0 0 color-mix(in srgb, var(--c-brass) 80%, var(--c-ink));
}

.urlaub__auge {
    margin: 0 0 var(--s-2);
    font-family: var(--sans);
    font-size: var(--fs-0);
    font-weight: 700;
    color: var(--c-brass);
}

.urlaub__titel {
    margin: 0 0 var(--s-4);
    font-family: var(--serif);
    font-size: var(--fs-5);
    line-height: 1.18;
    font-weight: 600;
    text-wrap: balance;
}

.urlaub__spanne {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    margin: 0 0 var(--s-4);
    font-family: var(--serif);
    font-size: var(--fs-3);
    line-height: 1.35;
}

.urlaub__bis {
    font-family: var(--sans);
    font-size: var(--fs-0);
    color: var(--c-muted);
}

/* «bis» steht zweimal im Dokument: einmal sichtbar als Zierschrift, einmal nur für die
   Vorlesesoftware. Ohne das läse sie entweder das Wort in seiner ganzen Sperrung vor oder,
   wäre es rein dekorativ, zwei Daten ohne jede Beziehung zueinander. */
.urlaub__nur-vorlesen {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.urlaub__rueck {
    display: inline-block;
    margin: 0;
    padding: 10px var(--s-4);
    border: 1px solid color-mix(in srgb, var(--c-brass) 55%, transparent);
    border-radius: var(--r-tag);
    background: color-mix(in srgb, var(--c-brass) 12%, var(--c-paper));
    font-size: var(--fs-2);
    font-weight: 600;
    line-height: 1.4;
    color: var(--gold-ink);
    text-wrap: balance;
}

.urlaub__rand,
.urlaub__gruss {
    margin: var(--s-3) 0 0;
    font-size: var(--fs-1);
    line-height: 1.55;
    color: var(--c-muted);
    text-wrap: pretty;
}

.urlaub__gruss {
    font-family: var(--serif);
    font-style: italic;
    font-size: var(--fs-2);
    color: var(--c-ink);
}

.urlaub__knopf {
    min-height: 44px;
    margin-top: var(--s-5);
    padding: 0 var(--s-5);
    border: 1px solid var(--c-accent);
    border-radius: var(--r-btn);
    background: var(--c-accent);
    /* ⛔ NICHT `--on-accent`, UND DAS WAR EIN ECHTER FEHLER IN DIESEM SCHILD. Der Wert dreht
       sich in der Nachtpalette (#FFFFFF → #12161A), die Fläche `--c-accent` aber nicht. Auf
       der Speisekarte, die standardmässig dunkel öffnet, wäre der Knopf «Verstanden» damit
       dunkler Schiefer mit fast schwarzer Schrift gewesen. Das Schild trägt seine Farben
       bewusst selbst — dann muss es BEIDE selbst tragen, nicht eine davon der Palette
       überlassen. */
    color: var(--on-dark);
    font-family: var(--sans);
    font-size: var(--fs-1);
    font-weight: 600;
    letter-spacing: .01em;
    cursor: pointer;
}

.urlaub__knopf:hover { background: var(--c-accent-2); border-color: var(--c-accent-2); }
.urlaub__knopf:focus-visible { outline: 3px solid var(--c-brass); outline-offset: 2px; }

/*
 * ⚠️ DIE SCHNÜRE VERSCHWINDEN BEI `reduce`, UND DAS IST KEINE SPARMASSNAHME. Ohne Bewegung
 *    hängt das Schild nicht, es liegt da — und zwei Schnüre, die aus dem Nichts an die
 *    Bildschirmkante stossen, sind dann kein Bild mehr, sondern zwei Striche. Motion setzt in
 *    diesem Fall alle Dauern auf null (siehe urlaub.js); hier fällt weg, was nur durch die
 *    Bewegung Sinn ergab.
 */
@media (prefers-reduced-motion: reduce) {
    .urlaub__seile { display: none; }
    .urlaub__haenge { padding-top: 0; }
    .urlaub__karte::after { display: none; }
}

@media (max-width: 480px) {
    .urlaub__karte { padding: var(--s-5) var(--s-4) var(--s-4); }
    .urlaub__stange { width: 96px; margin-left: -48px; }
    .urlaub__seil--links  { left: calc(50% - 42px); }
    .urlaub__seil--rechts { left: calc(50% + 40px); }
    .urlaub__karte::after { margin-left: -45px; box-shadow: 82px 0 0 color-mix(in srgb, var(--c-brass) 80%, var(--c-ink)); }
}

/* Die beiden Daten tragen das Gewicht, das «bis» dazwischen nicht — sonst liest sich die
   Spanne als drei gleichrangige Zeilen, und der Blick findet die Zahlen nicht. */
.urlaub__tag {
    font-weight: 600;
}

/* ==========================================================================
   ÜBER UNS — die Geschichte des Hauses
   ==========================================================================

   ⚠️ AUCH DIESER BLOCK STEHT VOR DEM KONTOR-BLOCK, aus dem Grund, der zwei Kästen weiter
      oben ausgeschrieben ist: alles hinter der ersten `.layout-kontor`-Regel gilt als
      dessen Block, und `LayoutKontorTest` verlangt dort jede Regel gebunden. «Unten
      anfügen» ist in dieser Datei die Falle, nicht die neutrale Wahl.

   ⛔ EINE SCHMALE SPALTE, UND DAS IST DER GANZE ENTWURF. Jedes andere Band der Startseite
      trägt ein bis zwei Sätze neben einem Bild; dies trägt Absätze. Fliesstext liest man
      auf 60 bis 70 Zeichen — `.split` hätte daraus eine halbe Spalte Prosa neben einem
      Foto gemacht, also genau die Form, in der niemand bis zum letzten Absatz kommt.

   ⚠️ DAS BILD STEHT UNTER DEM TEXT. Es bestätigt, was man gelesen hat — der Raum, die
      Familie, der Ofen — und konkurriert nicht mit dem ersten Satz um den Blick. Deshalb
      auch 16:9 und nicht hochkant: ein Porträt neben Prosa wäre wieder der Zweispalter.
   ========================================================================== */

.home-ueber .wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(20px, 3vw, 32px);
}

.home-ueber__kopf {
    max-width: 34em;
    text-align: center;
}

.home-ueber__kopf h2 { margin: .18em 0 0; }

/* 62 Zeichen, nicht 66 wie beim Fliesstext daneben: dieser Absatz steht mittig, und eine
   zentrierte Spalte darf schmaler sein, weil das Auge den Zeilenanfang nicht sucht. */
.home-ueber__text {
    max-width: 62ch;
}

.home-ueber__text > p + p { margin-top: 1em; }

.home-ueber__figur {
    margin: 0;
    width: 100%;
    max-width: 62rem;
}

.home-ueber__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: var(--r-sm);
    box-shadow: var(--shadow-sm);
}

/* ==========================================================================
   GOOGLE-BEWERTUNG — die Bitte am Fuss der Startseite
   ==========================================================================

   ⚠️ AUCH DIESER BLOCK STEHT VOR DEM KONTOR-BLOCK. Alles hinter der ersten
      `.layout-kontor`-Regel gilt als dessen Eigentum und muss dort gebunden sein; «unten
      anfügen» ist in dieser Datei die Falle. Die Kontor-Fassung dieses Bandes steht ganz
      am Ende der Datei, wo sie hingehört.

   ⛔ ZUERST GESTAPELT, AB 821px NEBENEINANDER — und die Richtung ist Absicht. Die
      Zweispalter dieser Datei sind meist andersherum geschrieben (`max-width`), und genau
      daran ist der Kontor-Block schon einmal hängengeblieben: `.layout-kontor .gbew__tat`
      ist (0,2,0) und schlägt ein `.gbew__tat` (0,1,0) auch innerhalb einer Medienabfrage.
      Was für den breiten Schirm gilt, steht deshalb hier UND dort in derselben Abfrage,
      und die schmale Ansicht ist für beide Aufbauten dieselbe.

   ⛔ DIE FÜNF STERNE SIND KEINE NOTE. Warum das Band keine `AggregateRating` ausgibt, steht
      im Partial — hier ist nur wichtig, dass sie golden sind, weil ein Stern golden ist,
      und nicht in der Hausfarbe: sie zitieren Google, nicht das Restaurant. Der Knopf
      darunter trägt die Hausfarbe (`.btn--primary`) und ist damit das einzige Element, das
      von Haus zu Haus wechselt — so wie auf jedem anderen Band dieser Seite.
   ========================================================================== */

/* ENGER ALS DIE BÄNDER DARÜBER, oben wie unten. Der Bandrhythmus dieser Seite ist `--s-8`
   auf jeder Seite, also rund 190px zwischen zwei Abschnitten — richtig für zwei Bänder, die
   beide etwas erzählen. Was hier steht, ist ein Nachsatz von vier Zeilen in einer Karte, und
   am Bildschirm gemessen schwamm sie zwischen der Karte darüber und dem dunklen Fuss
   darunter, statt den Abschluss zu machen. */
.gbew { padding: var(--s-7) 0; }

.gbew__karte {
    display: grid;
    gap: clamp(22px, 3vw, 40px);
    padding: clamp(22px, 3.2vw, 40px);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-sm);
}

.gbew__wort { display: flex; align-items: flex-start; gap: clamp(14px, 1.8vw, 22px); }

/* `line-height: 0` — sonst setzt die Zeilenhöhe des <span> unter dem G noch einmal ein
   Viertel Zeile Luft, und das Zeichen sitzt sichtbar zu hoch neben der Überschrift. */
.gbew__zeichen { flex: none; line-height: 0; }

/* HÖHE AUSGESCHRIEBEN, NICHT `auto`. Ein Inline-SVG mit viewBox rechnet sich seine Höhe
   zwar aus dem Seitenverhältnis, aber erst nachdem das Bild da ist — bis dahin steht die
   Zeile mit 150px Vorgabehöhe, und die Karte springt beim Aufbau. Beide Zeichen sind
   quadratisch, also ist die Zahl dieselbe wie die Breite. */
.gbew__zeichen svg { width: clamp(38px, 4vw, 52px); height: clamp(38px, 4vw, 52px); }

.gbew__satz { min-width: 0; }
.gbew__titel { font-size: clamp(1.3rem, 2.4vw, 1.85rem); margin: 0 0 .4em; }
/* 46 Zeichen: drei kurze Fragen hintereinander, und keine davon soll über die halbe Karte
   laufen, während rechts daneben der Knopf steht. */
.gbew__text { margin: 0; color: var(--muted); max-width: 46ch; }

.gbew__lead { margin: 0 0 var(--s-3); }

.gbew__sterne { display: flex; gap: 4px; margin: 0 0 var(--s-4); color: #FBBC05; }
.gbew__sterne svg { width: clamp(22px, 2.4vw, 28px); height: clamp(22px, 2.4vw, 28px); fill: currentColor; }

/* Auf dem Telefon über die volle Breite: der Knopf ist das Einzige, was auf diesem Band
   angeklickt werden kann, und ein Daumen trifft eine ganze Zeile besser als ein Wort. */
.gbew__knopf { width: 100%; }

@media (min-width: 821px) {
    .gbew__karte {
        grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
        align-items: center;
    }

    /* Die rechte Hälfte ist eine Handlung und keine Fortsetzung des Textes — mittig
       gesetzt liest sie sich als eigener Block, linksbündig als vierter Absatz. */
    .gbew__tat { text-align: center; }
    .gbew__sterne { justify-content: center; }
    .gbew__knopf { width: auto; }
}

/* ==========================================================================
   DIE STARTSEITE EINES HAUSES, DAS KEINE FOTOS HAT
   ==========================================================================

   ⛔ DER BEFUND, AN ZWEI ECHTEN HÄUSERN GEMESSEN. Das eine: 66 Fotos an 81 Gerichten,
      sechs von sechs Textbändern ausgefüllt — eine Startseite, die trägt. Das andere:
      195 Gerichte, NULL Fotos, NULL ausgefüllte Bänder. Dessen Seite bestand aus einer
      dunklen Platte, vier Monogrammkacheln und «So finden Sie uns».

      Bühne ist nicht kaputt; sie war gegen das erste Haus entworfen, und die Flotte steht
      am anderen Ende. Was hier steht, gestaltet die Zustände, die es bisher nur als
      Weglassung gab — die Aufbauten und die Grammatik bleiben, wie sie sind.

   ⚠️ UND ALLES HIER STEHT VOR DEM KONTOR-BLOCK, aus dem Grund, der weiter oben zweimal
      ausgeschrieben ist: alles hinter der ersten `.layout-kontor`-Regel gilt als dessen
      Eigentum und muss dort gebunden sein. Zusätzlich sind alle Regeln unten mit einer
      Klasse gewichtet — nie mit `:not(:has(…))` —, damit Kontors eigene Regeln
      (gleiche Spezifität, später in der Datei) sie weiter überstimmen. Ein `:has()` hätte
      die Spezifität um eins gehoben und Kontor still auf Bühnes Liste umgestellt: genau
      der Fehler, den D-91 beschreibt.
   ========================================================================== */

/* -- Beiwort UND Küche in einer Zeile -------------------------------------- */
/* `restaurant.cuisine` war an jedem Haus gepflegt und wurde ausschliesslich an Suchmaschinen
   ausgeliefert. Die beiden zusammen sind die billigste Antwort auf «jedes Haus soll nach sich
   selbst aussehen», die dieses Produkt hat. */
.eyebrow--zeile { display: flex; align-items: baseline; flex-wrap: wrap; gap: 9px; margin: 0; }
.eyebrow__punkt { opacity: .5; letter-spacing: 0; }
.eyebrow__kueche { }

/* -- Die gerechneten Hausfakten: seit dem 16.09.2026 nicht mehr gezeichnet (D-126) ------- */

/* -- Das Beiwort als Kontur auf der fotolosen Platte ----------------------- */
/*
 * `.hero__accent-watermark` liegt seit langem im Stylesheet und wurde von genau EINER Seite
 * geschrieben: der 404. Die Platte, für die es gedacht ist, hat es nie erreicht.
 *
 * ⚠️ NUR OHNE FOTO — die Vorlage rendert es gar nicht erst, wenn ein Bild da ist: dort ist das
 *    Bild der Grund, und eine Kontur darüber wäre eine zweite Geste auf derselben Fläche.
 * ⚠️ Die Kontur nimmt den hellen Akzentton des dunklen Grundes statt `--gold`; auf der Platte
 *    ist Gold die richtige Familie, aber `--gold` ist für dunkel gedacht zu tief.
 */
.hero--foto .hero__accent-watermark {
    right: -3%;
    -webkit-text-stroke: 1.5px color-mix(in oklab, var(--on-dark-accent) 30%, transparent);
    opacity: .85;
}

/*
 * ⚠️ AUF DEM TELEFON NIEDRIGER — ABER NUR OHNE FOTO. Der Inhalt sitzt am unteren Rand der
 *    Platte (`justify-content: flex-end`); bei 58vh lagen Zustand und die beiden Knöpfe unter
 *    der Kante, und über einem Haus mit zwei Filialen stand davor noch die Standortwahl.
 *    Gemessen bei 390 × 844: der ganze erste Bildschirm war belegt, ohne dass ein Knopf
 *    sichtbar war.
 *
 *    Ein Haus MIT Foto behält seine Höhe. Dort ist die Fläche das Bild, und ein Bild niedriger
 *    zu machen heisst, weniger davon zu zeigen — das ist bei diesen Häusern genau das
 *    Gegenteil dessen, was der Aufbau will.
 */
@media (max-width: 620px) {
    .hero--foto:not(.is-photo) { min-height: clamp(320px, 44vh, 420px); }
}

/* -- Vier Karten ohne ein einziges Foto ------------------------------------ */
/*
 * ⛔ SIE BLEIBEN KARTEN. Der naheliegende Griff wäre, sie zur Liste zu machen — und das wäre
 *    Kontor. Zwei Aufbauten, die im häufigsten Fall gleich aussehen, sind eine Entscheidung,
 *    für die der Betreiber zweimal bezahlt hat. Was verschwindet, ist die leere Bildfläche;
 *    was bleibt, ist Bühnes Grammatik: Fläche, Rundung, Kante.
 *
 * ⚠️ DIE ZEILE AUS NAME, PUNKTLINIE UND PREIS IST HIER ENTSTANDEN und steht inzwischen an
 *    `.dishcard` selbst — die Karte MIT Foto trägt sie seit demselben Durchgang. Alles, was
 *    davon hier stehen bliebe, wäre eine zweite Beschreibung derselben Sache; der eine echte
 *    Unterschied ist die Anzahl der Spalten.
 *
 * ⚠️ ZWEI SPALTEN, NICHT «so viele wie passen». `auto-fit` ergab bei vier Karten auf einem
 *    1280er Schirm drei oben und eine allein darunter — ein Raster, das aussieht, als sei
 *    etwas abgebrochen. Ohne Bild sind die Karten schmal genug für zwei, und zwei Spalten
 *    sind ausserdem, wie eine gedruckte Karte gesetzt wird.
 */
.dish-grid--ohne-foto { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 620px) { .dish-grid--ohne-foto { grid-template-columns: 1fr; } }

/*
 * ⚠️ HIER HAT DIE ZEILE PLATZ, und das ist der ganze Unterschied zur Karte mit Foto: zwei
 *    Spalten statt vier, also rund die doppelte Breite. Der Name bricht nicht auf drei Zeilen,
 *    und die Punktlinie ist eine Linie statt vier Punkten.
 *
 * ⚠️ DER PREIS STEHT AUF DER HÖHE DES NAMENS. `grid-row: 2` setzt ihn neben die Beschreibung —
 *    genau der Fehler, den D-91 auf der Kontor-Seite schon einmal gekostet hat; auf einer
 *    gedruckten Karte steht der Preis IMMER auf der Höhe des Gerichts, das er kostet.
 */
.dish-grid--ohne-foto .dishcard { grid-template-columns: 1fr auto; align-items: baseline; }

.dish-grid--ohne-foto .dishcard__name {
    grid-row: 1; grid-column: 1;
    display: flex; align-items: baseline; gap: 12px;
    margin: 0;
}

/* Dieselbe Geste wie `.mdish__lead` auf der Speisekarte — 2 px gepunktet, um ein Viertel
   Geviert angehoben. Eine dritte Schreibweise für dieselbe Linie wäre die Stelle, an der sie
   eines Tages verschieden aussehen. */
.dish-grid--ohne-foto .dishcard__name::after {
    content: '';
    flex: 1 1 auto;
    min-width: 18px;
    border-bottom: 2px dotted var(--line);
    transform: translateY(-.25em);
}

.dish-grid--ohne-foto .dishcard__price {
    grid-row: 1; grid-column: 2;
    align-self: baseline; margin-top: 0;
    white-space: nowrap;
}

.dish-grid--ohne-foto .dishcard__desc { grid-row: 2; grid-column: 1 / -1; }

.dish-grid--ohne-foto .dishcard__tags,
.dish-grid--ohne-foto .dishcard > .codes {
    grid-row: 3; grid-column: 1 / -1;
    justify-self: start; justify-content: flex-start;
    margin-top: 10px;
}


/* ==========================================================================
   BILDERLEISTE — die Galerie als gefahrene Reihe
   ==========================================================================

   ⛔ WAS SIE ERSETZT, WAR EIN MAUERWERK. `.gal-masonry` zeigte drei Spalten und alle Bilder
      gleichzeitig: bei acht Fotos knapp tausend Pixel Höhe, alles gleich gross, nichts betont.
      Ein Restaurant hat aber ein bestes Foto, und das soll gross sein. (Das Mauerwerk bleibt
      im Blatt und im Einsatz — die SEO-Seiten schreiben es weiter, und dort ist es richtig:
      ein Textdokument mit ein paar Bildern will keine Fahrt.)

   ⛔ DER GANZE MECHANISMUS IST EIN SCROLLBEREICH, KEIN KARUSSELL AUS SKRIPT. `scroll-snap`
      rastet das mittlere Bild ein, der Daumen wischt ohnehin, und ohne JavaScript bleibt alles
      erreichbar. Was Skript braucht, sind nur die Pfeile und der Balken; die tragen `hidden`
      im Markup und werden von `site.js` freigeschaltet.

   ⚠️ DIE VERGRÖSSERUNG DER MITTE KOMMT AUS DER STILVORLAGE UND NICHT AUS EINEM SKRIPT, das bei
      jedem Bild die Position ausrechnet. `animation-timeline: view()` bindet die Bewegung an
      die Sichtbarkeit des Bildes IM Scrollbereich — der Browser rechnet, nichts läuft in
      JavaScript, und ein Browser ohne diese Zeitachse zeigt schlicht alle Bilder gleich gross.
      Der Rückfall ist eine ordentliche Leiste, kein Bruch.

   ⚠️ UND KEINE DECKKRAFT NULL. Die Nachbarn gehen auf .55 herunter, nicht auf 0: was auf
      dieser Seite unsichtbar wird, muss unter `.js-motion` stehen und von einem Wachhund
      zurückgeholt werden können (BewegungTest). Ein Bild, das man halb sieht, ist eine
      Einladung; ein Bild, das verschwindet, ist ein Fehler.
   ========================================================================== */

/* Das Band ist der einzige Abschnitt der Seite, dessen Inhalt ÜBER den Satzspiegel hinausläuft.
   Der Kopf steht deshalb in seinem eigenen `.wrap`, und der Abschnitt selbst gibt seitlich
   nichts vor — sonst stünde die Leiste in einem 22-px-Rahmen und die Nachbarn ragten nicht mehr
   an den Rand. Unten etwas enger, weil eine gefahrene Reihe ihre eigene Luft mitbringt. */
.bleiste-band { overflow: hidden; padding-bottom: var(--s-7); }

.bleiste { position: relative; }

/* Die Breite EINES Bildes, und alles andere rechnet daraus: der seitliche Einzug der Spur
   zentriert damit das erste und das letzte Bild, ohne dass irgendwo eine zweite Zahl steht. */
.bleiste__spur {
    /* 58vw statt 78: bei 78 blieb links und rechts kaum ein Streifen des Nachbarn übrig, und
       eine Reihe, von der man nur EIN Bild sieht, ist keine Reihe. */
    --bleiste-breite: min(58vw, 620px);

    list-style: none;
    margin: 0;
    display: flex;
    gap: clamp(16px, 2.2vw, 30px);
    padding: 8px calc(50% - var(--bleiste-breite) / 2) 10px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
}

/* Der Balken darüber sagt bereits, wo man ist — eine zweite Leiste darunter wäre dieselbe
   Auskunft zweimal, und auf dem Telefon zeichnet sie ohnehin niemand. */
.bleiste__spur::-webkit-scrollbar { display: none; }

.bleiste__bild {
    flex: 0 0 var(--bleiste-breite);
    scroll-snap-align: center;
}

/* `position: relative` TRÄGT DIE BILDUNTERSCHRIFT, die jetzt AUF dem Bild liegt. Und keine
   Kante mehr: ein Rahmen um eine Fotografie, die ohnehin auf hellem Papier schwebt, ist die
   Linie zuviel — was sie vom Papier abhebt, ist der Schatten. */
.bleiste__figur {
    position: relative;
    margin: 0;
    border-radius: 14px;
    overflow: hidden;
    background: var(--surface);
    box-shadow: var(--shadow-xl);
}

/* 4:3 UND `object-fit`, WEIL DIE BILDER EINES HAUSES NIE DASSELBE FORMAT HABEN. Im Mauerwerk
   durfte jedes seine eigene Höhe behalten; in einer Reihe wäre das eine Zeile aus Treppen. Die
   Angaben `width`/`height` am Bild bleiben trotzdem stehen — sie reservieren den Platz, bevor
   die Datei da ist. */
.bleiste__foto {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

/*
 * ⛔ DIE BILDUNTERSCHRIFT LIEGT AUF DEM BILD, NICHT IN EINEM KASTEN DARUNTER. Der weisse
 *    Streifen unter jeder Fotografie brach das Rechteck und sah aus wie ein leeres
 *    Eingabefeld — am Bildschirm gesehen und genau so gemeldet. Auf dem Bild ist sie das, was
 *    sie ist: eine Beschriftung.
 *
 * ⚠️ DER VERLAUF IST DER ALPHA-BODEN, KEIN GESCHMACK. Die Fotografien kommen von den Häusern,
 *    und darunter ist eines, das an dieser Stelle fast weiss ist. `--scrim-74`/`--scrim-90`
 *    sind die Werte, die dieselbe Datei für ihre Foto-Aufmacher ausgerechnet hat; die oberen
 *    drei Viertel bleiben durchsichtig, damit das Bild ein Bild bleibt.
 */
.bleiste__text {
    position: absolute;
    inset: auto 0 0 0;
    padding: 3.2rem 1.15rem 1rem;
    font-family: var(--sans);
    font-size: .88rem;
    line-height: 1.4;
    color: var(--on-dark);
    background: linear-gradient(180deg, transparent 0%, var(--scrim-74) 62%, var(--scrim-90) 100%);
}

/* -- Die Mitte ist gross ---------------------------------------------------- */
/*
 * ⚠️ .76 UND .34, NICHT .88 UND .55. Der erste Versuch war so vorsichtig, dass der Nachbar
 *    nicht kleiner aussah, sondern unscharf — und die Reihe damit wie ein Bauteil, das nicht
 *    fertig geladen hat. Ein Abfall, den man nicht sieht, ist kein Abfall.
 *
 * ⚠️ UND WEITERHIN NICHT AUF NULL: was auf dieser Seite unsichtbar wird, muss unter
 *    `.js-motion` stehen und von einem Wachhund zurückgeholt werden können (BewegungTest).
 */
@supports (animation-timeline: view()) {
    .bleiste__figur {
        animation: bleiste-mitte linear both;
        animation-timeline: view(inline);
        animation-range: cover 6% cover 94%;
    }

    @keyframes bleiste-mitte {
        0%   { transform: scale(.76); opacity: .34; }
        50%  { transform: scale(1);   opacity: 1; }
        100% { transform: scale(.76); opacity: .34; }
    }
}

/* -- Balken und Pfeile: nur mit Skript -------------------------------------- */
/*
 * `[hidden]` STEHT SCHON IM MARKUP; diese Regeln beschreiben, wie die beiden aussehen, sobald
 * `site.js` das Attribut abnimmt. Die Marke am <html> ist zusätzlich da, weil ein Skript, das
 * zur Hälfte durchläuft, sonst einen Knopf ohne Wirkung stehen liesse — dieselbe Bauform wie
 * `html:not(.has-menufilter) .m-bar`.
 */
html:not(.has-bleiste) .bleiste__pfeil,
html:not(.has-bleiste) .bleiste__balken { display: none; }

/* ⛔ UNTER DER LEISTE, NICHT DARÜBER, UND DÜNN. Über den Bildern war er ein zweites Bauteil,
      das mit der Überschrift um dieselbe Zeile stritt; darunter ist er die Fusszeile der Reihe.
      Zwei Pixel statt fünf: er ist eine Auskunft am Rand und kein Anzeigeelement. */
.bleiste__balken {
    width: min(52%, 380px);
    height: 2px;
    margin: clamp(14px, 2vw, 22px) auto 0;
    border-radius: 999px;
    background: var(--line);
    overflow: hidden;
}

.bleiste__lauf {
    display: block;
    height: 100%;
    width: 100%;
    border-radius: inherit;
    /* DIE HAUSFARBE, NICHT DAS ZIERGOLD. Dies ist eine Auskunft — wo bin ich in der Reihe —
       und keine Verzierung; `--gold` trug auf hellem Papier ausserdem so wenig, dass der
       gefahrene Teil vom Rest kaum zu unterscheiden war. */
    background: var(--accent);
    transform-origin: left center;
    /* Von `site.js` gesetzt: 0 bis 1. Ohne Skript ist der Balken ohnehin nicht da. */
    transform: scaleX(var(--bleiste-lauf, .2));
    transition: transform var(--t-fast);
}

/* `calc(50% - 1.4rem)`: der Balken sitzt jetzt UNTER der Leiste und gehört zur Höhe dieses
   Kastens. Ohne die Korrektur stünden die Knöpfe um seine halbe Höhe zu tief — nicht viel, aber
   genug, dass sie nicht mehr auf der Mitte des Bildes liegen. */
.bleiste__pfeil {
    position: absolute;
    top: calc(50% - 1.4rem);
    transform: translateY(-50%);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    /* 48 px: dieselbe Daumengrösse wie jedes andere Bedienelement dieser Seite. */
    width: 48px;
    height: 48px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}

.bleiste__pfeil svg { width: 22px; height: 22px; }
.bleiste__pfeil--zurueck { left: clamp(10px, 3vw, 46px); }
.bleiste__pfeil--vor { right: clamp(10px, 3vw, 46px); }

@media (hover: hover) {
    .bleiste__pfeil:hover { border-color: var(--accent); color: var(--accent-ink); box-shadow: var(--shadow-md); }
}

/* Am Anfang und am Ende der Reihe zeigt der Pfeil nach nirgends. Er bleibt STEHEN und wird
   blass, statt zu verschwinden: ein Knopf, der springt, verschiebt das Bild darunter. */
.bleiste__pfeil[disabled] { opacity: .35; cursor: default; box-shadow: none; }

/*
 * ⛔ AUF DEM TELEFON KEINE PFEILE. Am Bildschirm gemessen bei 390 px: die beiden Knöpfe lagen
 *    mitten auf der Fotografie, der linke halb ausserhalb — und sie tun dort nichts, was der
 *    Daumen nicht besser kann. Ein Bedienelement, das ein Bild verdeckt, um eine Geste zu
 *    ersetzen, die es ohnehin gibt, ist eine Verschlechterung.
 *
 * ⚠️ DER BALKEN BLEIBT. Er verdeckt nichts und beantwortet die einzige Frage, die eine
 *    gefahrene Reihe aufwirft: wie viel kommt noch.
 */
@media (max-width: 860px) {
    .bleiste__pfeil { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .bleiste__spur { scroll-behavior: auto; }
    .bleiste__figur { animation: none; transform: none; opacity: 1; }
    .bleiste__lauf { transition: none; }
}

/* ==========================================================================
   KARTENSPIEGEL — das Inhaltsverzeichnis der Karte auf der Startseite
   ==========================================================================

   Die Begründung, warum es dieses Band gibt, steht im Partial. Hier zählt die Form: es ist
   ein VERZEICHNIS und keine zweite Speisekarte, also wird es wie eines gesetzt — Name in der
   Hausschrift, Zahl klein und rechts, eine Haarlinie je Zeile. Keine Pillen: eine Reihe
   Pillen liest sich als Filter, und hier ist nichts zu filtern.
   ========================================================================== */

/* OHNE EIGENEN ABSTAND NACH OBEN. Das Band gehört zu den vier Gerichten darüber — es sagt
   «und das ist die ganze Karte». Mit den vollen `--s-8` auf beiden Seiten stünde es als
   dritter, unverbundener Abschnitt da, und genau diese Löcher sind es, die eine Seite mit
   wenigen Bändern leer wirken lassen. */
/* ═══ DER KARTENDECKEL ═══════════════════════════════════════════════
   Hier lag der Kartenspiegel — ein Verzeichnis mit einer Zahl je Zeile. Es war richtig und es
   sah leer aus; ein Verzeichnis IST leer, es zählt auf, was woanders steht.

   ⛔ DIE FLÄCHE MUSS SELBST ETWAS SEIN. Eine grosse Schrift auf einer leeren Fläche wäre
      wieder «schlicht» — genau der Befund, der dieses Band ausgelöst hat. Ein gedruckter
      Kartendeckel trägt einen Rahmen, und die doppelte Haarlinie gibt es sonst NIRGENDS auf
      dieser Seite: sie sagt ohne ein Wort, dass hier die Karte beginnt. */
/* -- «So finden Sie uns»: zwei Spalten, die nicht gleich lang sind ---------- */
/* `.split` zentriert seine Spalten senkrecht, was für ein Bild neben einem Absatz richtig ist.
   Hier stehen links drei Zeilen Adresse und zwei Knöpfe gegen sieben Zeilen Öffnungszeiten:
   zentriert hängt die kurze Spalte in der Mitte und lässt oben und unten eine Fläche frei, die
   auf einer Seite ohne Texte die auffälligste des ganzen Dokuments ist. Beide beginnen jetzt
   oben, wie zwei Spalten eines Dokuments. */
.split--finden { align-items: start; }

/* ═══ DAS RESERVIERUNGSBAND — in JEDEM Aufbau und JEDEM Thema dieselbe Form (D-257, 14.10.2026) ═══
   Der Betreiber: «anasayfadaki Für wann dürfen wir eindecken? bölümü de her temada aynı tasarım
   kullanılacak». Dieselbe Form wie die Buchungsseite (Vorbild m2-burger.de/reservieren): oben das
   Foto über die ganze Breite, gleichmässig verschleiert, darauf Rubrik, Titel und Satz in der Mitte;
   darunter Graphit, das Formular als eine Spalte von 720 px, die Zeiten als Raster, der Knopf in
   der Hausfarbe. Kein Aufbau trägt eine Regel für `.resband*`; wer das Band ändert, ändert es hier.

   ⚠️ DIE FLÄCHEN SIND FEST UND NEUTRAL, die eine Farbe mit Ton ist die des Hauses (`--accent`).
   ⚠️ `#main .resband` FÜR POLSTER UND KANTE: `section` trägt in jedem Aufbau ein Bandpolster und
      in Kontor eine Haarlinie oben; beides schlägt (0,1,1) eine Klasse.
   ⚠️ ÜBERSCHRIFTEN (0,2,0): schlagen `.layout-x h2` (0,1,1) jedes Aufbaus. */
#main .resband,
.resband {
    --resband-nacht: #0B0C0E;
    --resband-flaeche: #17191C;
    --resband-feld: #212429;
    --resband-rand: rgba(255, 255, 255, .22);
    --resband-hell: #FFFFFF;
    --resband-hell-weich: rgba(255, 255, 255, .74);
    --resband-akzent-hell: color-mix(in oklab, var(--accent) 58%, #FFFFFF);
    --text: var(--resband-hell);
    --muted: var(--resband-hell-weich);
    --line: var(--resband-rand);
    position: relative;
    padding: 0;
    border: 0;
    background: var(--resband-flaeche);
    color: var(--resband-hell);
}

.resband :focus-visible { outline-color: var(--resband-akzent-hell); }

/* Oben: das Foto über die ganze Breite, die Schrift in der Mitte. */
.resband__buehne {
    position: relative;
    display: grid;
    place-items: center;
    min-height: clamp(300px, 40vw, 480px);
    background: var(--resband-nacht);
    overflow: hidden;
}

.resband:not(.resband--foto) .resband__buehne { min-height: 0; }

.resband__foto {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    pointer-events: none;
}

/* Der Schleier: Dekoration über dem Foto, aber stumm für die Maus — ohne `pointer-events: none`
   hat er einmal ein ganzes Band totgelegt (DesignSystemTest). Gleichmässig, denn der Titel steht
   in der Mitte; auf dem schmalen Schirm unten noch einmal ausdrücklich, ≥ 0,6 Deckung. */
.resband__schleier {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, rgba(11, 12, 14, .5) 0%, rgba(11, 12, 14, .6) 60%, rgba(11, 12, 14, .76) 100%);
    pointer-events: none;
}

@media (max-width: 700px) {
    .resband__schleier {
        background: linear-gradient(to bottom, rgba(11, 12, 14, .62) 0%, rgba(11, 12, 14, .66) 60%, rgba(11, 12, 14, .78) 100%);
    }
}

.resband__kopf {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-top: clamp(40px, 6vw, 72px);
    padding-bottom: clamp(36px, 5vw, 64px);
    text-align: center;
}

.resband .resband__ueber {
    margin: 0 0 14px;
    font-family: var(--serif);
    font-size: 1.05rem;
    font-style: italic;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--resband-hell-weich);
}

.resband .resband__titel {
    max-width: 18ch;
    margin: 0;
    font-family: var(--serif);
    font-size: clamp(2.3rem, 5.2vw, 4.4rem);
    font-style: normal;
    font-weight: 500;
    line-height: 1;
    letter-spacing: -.02em;
    text-transform: none;
    color: var(--resband-hell);
}

.resband__satz {
    max-width: 50ch;
    margin: 16px 0 0;
    font-family: var(--sans);
    font-size: clamp(1rem, 1.25vw, 1.1rem);
    line-height: 1.55;
    color: var(--resband-hell-weich);
}

/* Unten: Graphit, eine Spalte von 720 px in der Mitte. */
.resband__flaeche { padding-top: clamp(36px, 5vw, 64px); padding-bottom: clamp(56px, 6.5vw, 104px); }
.resband__spalte { max-width: 720px; margin: 0 auto; }

.resband__form { display: block; margin: 0; }

.resband__felder {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
}

.resband__feld {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    min-width: 0;
}

.resband__label {
    margin: 0;
    font-family: var(--sans);
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--resband-hell);
}

/* Felder: Graphit eine Stufe heller, helle Linie, 6 px, die Serife für Datum und Zahl. */
.resband .resband__eingabe {
    display: block;
    width: 100%;
    min-height: 54px;
    padding: 0 14px;
    font-family: var(--serif);
    font-size: 1.15rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--resband-hell);
    color-scheme: dark;
    background: var(--resband-feld);
    border: 1px solid var(--resband-rand);
    border-radius: 6px;
    box-shadow: none;
    appearance: none;
    -webkit-appearance: none;
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.resband .resband__eingabe:hover { border-color: var(--resband-hell-weich); }

.resband .resband__eingabe:focus {
    outline: none;
    border-color: var(--resband-akzent-hell);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 28%, transparent);
}

.resband__eingabe::-webkit-calendar-picker-indicator { opacity: .8; cursor: pointer; }
.resband__eingabe option { font-family: var(--sans); color: var(--resband-hell); background: var(--resband-feld); }
.resband select.resband__eingabe { padding-right: 40px; cursor: pointer; }

/* Der Pfeil der Auswahl ist ein Kind des Rahmens, kein Hintergrundbild. */
.resband__auswahl { position: relative; display: block; }
.resband__auswahl::after {
    content: "";
    position: absolute;
    right: 16px;
    top: calc(50% - 7px);
    width: 9px;
    height: 9px;
    border-right: 1.5px solid var(--resband-hell);
    border-bottom: 1.5px solid var(--resband-hell);
    rotate: 45deg;
    pointer-events: none;
}

/* Die Zeiten: ein Raster gleich breiter Felder; jede ist der Absendeknopf. */
.resband__zeiten-wort { margin-top: clamp(22px, 2.4vw, 30px); }

.resband__zeiten {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 10px;
    margin-top: 10px;
    transition: opacity .3s;
}

.resband__zeiten:empty { display: none; }
.resband__zeiten[aria-busy='true'] { opacity: .5; pointer-events: none; }

.resband .resband__zeit {
    min-height: 52px;
    padding: 0 8px;
    font-family: var(--serif);
    font-size: 1.1rem;
    font-weight: 500;
    font-variant-numeric: normal;
    color: var(--resband-hell);
    background: var(--resband-feld);
    border: 1px solid var(--resband-rand);
    border-radius: 6px;
    cursor: pointer;
    transition: color var(--t-fast), background-color var(--t-fast), border-color var(--t-fast);
}

.resband .resband__zeit:hover { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.resband .resband__zeit:active { background: var(--accent-strong); border-color: var(--accent-strong); }
.resband .resband__zeit:focus-visible { outline: 2px solid var(--resband-akzent-hell); outline-offset: 2px; }

/* Darunter: der Satz des Tages, dann der Weg zum ganzen Tag als Knopf in der Hausfarbe, mittig. */
.resband__fuss {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    margin-top: clamp(18px, 2vw, 26px);
}

.resband__note {
    align-self: stretch;
    margin: 0;
    font-family: var(--sans);
    font-size: .92rem;
    line-height: 1.55;
    color: var(--resband-hell-weich);
}

.resband__note:empty { display: none; }

.resband .resband__mehr {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: min(100%, 320px);
    min-height: 56px;
    margin: 0;
    padding: 0 36px;
    font-family: var(--sans);
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--on-accent);
    text-align: center;
    text-decoration: none;
    text-transform: none;
    background: var(--accent);
    border: 0;
    border-radius: 6px;
    cursor: pointer;
    transition: background-color var(--t-fast), box-shadow var(--t-fast);
}

.resband .resband__mehr:hover {
    color: var(--on-accent);
    background: var(--accent-strong);
    box-shadow: 0 14px 32px -14px color-mix(in oklab, var(--accent) 80%, transparent);
}

.resband .resband__mehr:focus-visible { outline: 2px solid var(--resband-akzent-hell); outline-offset: 3px; }

.resband__hinweis {
    margin: 22px auto 0;
    max-width: 56ch;
    font-family: var(--sans);
    font-size: .9rem;
    line-height: 1.55;
    text-align: center;
    color: var(--resband-hell-weich);
}

/* Telefon: das Foto etwas flacher, drei Zeiten je Zeile, der Knopf über die ganze Breite. */
@media (max-width: 639px) {
    .resband__buehne { min-height: clamp(260px, 72vw, 340px); }
    .resband__kopf { padding-top: 36px; padding-bottom: 32px; }
    .resband__felder { gap: 12px; }
    .resband .resband__eingabe { padding: 0 12px; font-size: 1.08rem; }
    .resband select.resband__eingabe { padding-right: 36px; }
    .resband__auswahl::after { right: 14px; }
    .resband__zeiten { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
    .resband .resband__mehr { width: 100%; min-width: 0; padding: 0 20px; }
}

@media (max-width: 359px) {
    .resband__felder { grid-template-columns: minmax(0, 1fr); }
}
/* ==========================================================================
   DIE KARTE ALS APP (D-222) — partials/startbildschirm, auf der Speisekarte und der Quittung.

   ⚠️ IM FLUSS, NICHT DARÜBER: eine ruhige Karte zwischen zwei Rubriken, Form aus 21st.dev
      «Announcement Banner» (cnippet-dev): Zeichen, Titel, ein Satz, eine Handlung, ein ×. Statt
      eines Schmuckzeichens steht links das Symbol, das der Gast gleich auf dem Telefon hat.
   ⚠️ `hidden` trägt die Regel ganz oben (`[hidden] { display: none !important }`); hier setzt
      niemand `display` auf ein Element, das das Skript verstecken muss, ohne dass sie gewinnt.
   ========================================================================== */
.startbild {
    position: relative;
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    gap: var(--s-4);
    align-items: start;
    margin: var(--s-6) 0;
    padding: var(--s-4);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface);
    color: var(--text);
}

.startbild--kurz { margin: var(--s-5) 0; }

.startbild__symbol {
    width: 56px;
    height: 56px;
    border-radius: 13px;
    background: #FFFFFF;
    box-shadow: 0 0 0 1px var(--line);
}

.startbild__text { min-width: 0; }

/* Rechts Platz für das ×, damit ein langer Titel nicht darunter läuft. Zwei Klassen, weil die
   Aufbauten Absätze und Überschriften mit `.layout-… p` setzen (0,1,1) und eine Klasse allein verlöre. */
.startbild .startbild__titel {
    margin: 0 0 4px;
    padding-right: 36px;
    font: 600 1.06rem/1.3 var(--sans);
    color: var(--text);
}

.startbild--kurz .startbild__titel { padding-right: 0; }

.startbild .startbild__satz { margin: 0; font-size: .94rem; line-height: 1.5; color: var(--muted); }

.startbild__weg {
    display: grid;
    gap: 10px;
    margin: var(--s-3) 0 0;
    padding: var(--s-3) 0 0;
    border-top: 1px solid var(--line-soft);
    list-style: none;
    font-size: .94rem;
    line-height: 1.45;
}

.startbild__weg li,
.startbild__fertig {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
}

.startbild__weg .startbild__fussnote { display: block; font-size: .86rem; color: var(--muted); }

.startbild__ic { margin-top: 2px; color: var(--accent-ink); }

.startbild__fertig { margin: var(--s-3) 0 0; font-weight: 600; }

.startbild__aktion { margin: var(--s-3) 0 0; }

.startbild__zu {
    position: absolute;
    top: 4px;
    right: 4px;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--muted);
    cursor: pointer;
}

.startbild__zu:hover { color: var(--text); }

.startbild__zu:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }

/* ═══ KONTOR ═════════════════════════════════════════════════════════════════════════════════
   Seit D-258 (13.10.2026) steht ALLES zu diesem Aufbau in kontor.css: der Block hier trug die
   gedruckte Karte (Kopf als Plakette, Papier, Punktlinie) und wäre unter dem schwarzen Aufbau nur
   noch eine Liste von Regeln, die kontor.css Zeile für Zeile zurücknimmt. Die eine Regel bleibt,
   damit LayoutKontorTest den Block weiterhin findet und «die erste Gestaltung bleibt vom zweiten
   Aufbau unberührt» prüfen kann: nichts hier darf eine Bühne-Seite berühren.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
.layout-kontor { color-scheme: dark; }
