/* Neutrale Vorgaben (P0-7). Die Gastseite ueberschreibt --brand und --accent aus dem Betriebsdatensatz (_Branding.cshtml). */
:root { --accent: #9DB7D5; --ink: #F2EDE4; --black: #0B0D10; --brand: #1B2430; }
* { box-sizing: border-box; }
html { background: var(--black); color-scheme: dark; }
body {
  margin: 0; padding: 0 16px calc(24px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, var(--black), var(--brand));
  background-attachment: fixed; color: var(--ink);
  font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.head { text-align: center; padding: 20px 0 12px; border-bottom: 1px solid var(--accent); }
.head p { margin: 0; }
.wordmark { margin: 0; text-transform: uppercase; color: var(--accent); font-size: 1.5rem; letter-spacing: .25em; font-weight: 600; }
.logo { display: block; max-height: 64px; max-width: 80%; margin: 0 auto 8px; }
.operation { margin-top: 4px; font-size: .9rem; opacity: .85; }
.foot { text-align: center; margin: 32px 0 0; font-size: .75rem; opacity: .6; }
.foot a { color: inherit; }
.age { font-size: .85rem; opacity: .85; margin-top: 4px; }
.empty { text-align: center; margin: 40px 0; opacity: .85; }
.table { margin-top: 8px; font-weight: 600; }
main { max-width: 640px; margin: 0 auto; }
h2 { color: var(--accent); font-size: 1.15rem; letter-spacing: .08em; text-transform: uppercase; margin: 28px 0 8px; }
.items { list-style: none; margin: 0; padding: 0; }
.items li {
  display: grid; grid-template-columns: 1fr auto; column-gap: 12px;
  padding: 10px 0; border-bottom: 1px solid rgba(242, 237, 228, .12);
}
.price { color: var(--accent); white-space: nowrap; font-variant-numeric: tabular-nums; }
.desc, .notice, .tag { grid-column: 1 / -1; font-size: .85rem; opacity: .75; }
.soldout .name, .soldout .price { opacity: .45; text-decoration: line-through; }
.offline { margin: 8px 0 0; padding: 6px 10px; border: 1px solid var(--accent); border-radius: 6px; color: var(--accent); font-size: .9rem; }

/* ---- Bausteine: Karte, Feld, Schaltflaeche (02.10.2026) --------------------------------------
   Diese Regeln standen bis heute NUR in admin.css. Das Gast-Layout (_Layout) bindet admin.css aber
   nicht ein - deshalb waren die Gast-Kontoseiten (Register, Pending, Confirm, Resend) ohne jede
   Gestaltung: Beschriftung und Eingabefeld in einer Zeile, keine Abstaende, auf der ersten Seite,
   die ein Gast nach dem QR-Code sieht. Sie gehoeren hierher, weil Gast UND Verwaltung sie brauchen;
   admin.css laedt site.css ohnehin immer mit.
   Keine festen Farben: alles leitet sich aus --ink, --black, --brand und --accent ab, die der
   Betrieb ueber /branding.css setzt (P0-7). Nur "falsch" und "in Ordnung" sind eigene Variablen mit
   neutraler Vorgabe - ein Betrieb mit roter Marke soll seine Fehlermeldung trotzdem lesen koennen. */
:root { --bad: #ff9b8a; --good: #9ed9a0; --line: color-mix(in srgb, var(--ink) 15%, transparent); }
.card { border: 1px solid var(--line); border-radius: 10px; padding: 12px; margin: 10px 0;
  background: color-mix(in srgb, var(--black) 70%, transparent); }
.card h3 { margin: 0 0 8px; font-size: 1rem; }

/* Vom Telefon aus gedacht: ein Feld ist eine Zeile, Beschriftung ueber der Eingabe, Eingabe ueber
   die volle Breite. 48px Mindesthoehe ist die Tippflaeche am Tisch, 1rem Schriftgroesse verhindert
   das Hineinzoomen von iOS, und box-sizing (oben) haelt die Breite in der Spalte - also keine
   waagerechte Rollleiste. */
.field { display: block; margin: 10px 0; }
.field > span { display: block; font-size: .85rem; opacity: .8; margin-bottom: 4px; }
.field input[type=text], .field input[type=email], .field input[type=password],
.field input[type=number], .field select, .field textarea {
  width: 100%; min-height: 48px; padding: 10px 12px; font: inherit; font-size: 1rem; color: var(--ink);
  background: color-mix(in srgb, var(--brand) 55%, var(--black));
  border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); border-radius: 8px;
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible,
.check input:focus-visible, .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.check { display: flex; align-items: center; gap: 10px; min-height: 48px; }
.check input { flex: 0 0 auto; width: 24px; height: 24px; }
.btn { min-height: 48px; padding: 10px 18px; font: inherit; font-weight: 600; color: var(--black);
  background: var(--accent); border: 0; border-radius: 8px; cursor: pointer; }
.btn.ghost { background: transparent; color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); }
.btn.danger { background: color-mix(in srgb, var(--bad) 55%, var(--black)); color: var(--ink); }
/* Link im Schaltflaechen-Look; eigene Klasse statt style-Attribut, weil die Richtlinie
   style-src 'self' (P0-8) Inline-Stile sperrt. */
.btn-link { text-decoration: none; display: inline-block; }
.error, .field-validation-error, .validation-summary-errors { color: var(--bad); display: block; margin: 4px 0; }
.notice-ok { color: var(--good); margin: 8px 0; }
.muted { opacity: .7; font-size: .85rem; }
.hint { opacity: .8; font-size: .9rem; margin: 8px 0; }
.closed { margin: 8px 0; padding: 8px 10px; border: 1px solid var(--accent); border-radius: 8px; }

/* Der leere Aufzaehlungspunkt oben auf der Registrierung: asp-validation-summary schreibt die Liste
   IMMER mit und versteckt ihr Platzhalter-<li> per style-Attribut - genau das verwirft die
   Richtlinie style-src 'self' (P0-8). Also wird hier versteckt, was nichts sagt: die ganze Liste im
   gueltigen Zustand, das leere <li> auch im Fehlerzustand. Gilt fuer alle Formulare, nicht nur fuer
   die Registrierung (Login, Invite, Artikel, Kategorien, Betrieb anlegen, Betrieb). */
.validation-summary-valid, .field-validation-valid { display: none; }
.validation-summary-errors ul { margin: 0; padding-left: 1.1rem; }
.validation-summary-errors li:empty { display: none; }

/* Hinweisleiste des Testzugangs (P-4): ein Etikett, nicht ein Absatz. */
.trialnotice { display: inline-block; margin: 8px 0 0; padding: 2px 10px; border: 1px solid var(--accent);
  border-radius: 999px; color: var(--accent); font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; }

/* Zeilenteile des Gastes: Menge, Summe, Vorname, Nummer, Zustand. Bewusst NUR unter .guest, obwohl
   das Board dieselben Namen benutzt: "die Board-Regeln sind spezifischer" stimmt nur fuer
   Eigenschaften, die sie selbst setzen. .board .tile .state setzt keine Deckkraft - eine freie
   Regel .state { opacity: .75 } haette das Zustandswort auf der roten und der goldenen Kachel
   gedimmt, und fett fuer "bestaetigt" haette es von "neu" nicht mehr zu unterscheiden gemacht
   (B1-3). Das Board bleibt deshalb bei seinen Regeln in admin.css. */
.guest .qty { font-variant-numeric: tabular-nums; opacity: .85; }
.guest .sum { margin: 10px 0 0; font-weight: 600; font-size: 1.05rem; }
.guest .guestname { font-weight: 600; }
.guest .ordernumber { font-weight: 700; font-variant-numeric: tabular-nums; }
.guest .state { font-size: .85rem; opacity: .75; }
.guest .line.new .name, .guest .line.confirmed .name { font-weight: 600; }
.guest .line.delivered { opacity: .6; }
.guest .line.cancelled { opacity: .5; text-decoration: line-through; }

/* ---- Gast: Deckel und Bestellen (Karte) ------------------------------------------------------
   Nur unter .guest: dieselben Namen (tab, lines, cart) bedeuten auf dem Board an der Wand etwas
   anderes, und davon darf die Wand nichts mitbekommen. Die Klasse setzen _Layout und die Karte. */
.guest .tab, .guest .cart { margin: 16px 0; padding: 12px; border: 1px solid var(--line);
  border-radius: 10px; background: color-mix(in srgb, var(--black) 70%, transparent); }
.guest .tab h2, .guest .cart h2 { margin: 0 0 8px; }
.guest .lines { list-style: none; margin: 0; padding: 0; }
.guest .line { display: grid; grid-template-columns: auto 1fr auto; column-gap: 8px;
  align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--line); }
.guest .line .state, .guest .line .strike-reason { grid-column: 1 / -1; }
.guest .cart label { display: block; font-size: .85rem; opacity: .8; margin-bottom: 4px; }
.guest .cart input[type=text] { width: 100%; min-height: 48px; padding: 10px 12px; font: inherit;
  font-size: 1rem; color: var(--ink); background: color-mix(in srgb, var(--brand) 55%, var(--black));
  border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); border-radius: 8px; }
/* Die beiden Knoepfe der Karte: "Bestellen" ueber die ganze Breite, "+" eine quadratische
   Tippflaeche rechts in der Artikelzeile. */
.guest .send { width: 100%; min-height: 52px; margin-top: 10px; font: inherit; font-weight: 600;
  color: var(--black); background: var(--accent); border: 0; border-radius: 8px; cursor: pointer; }
.guest .plus { grid-column: 2; justify-self: end; width: 48px; height: 48px; font: inherit;
  font-size: 1.5rem; line-height: 1; color: var(--accent); background: transparent;
  border: 1px solid var(--accent); border-radius: 8px; cursor: pointer; }
.guest .withdraw { color: var(--accent); display: inline-block; padding: 8px 0; min-height: 44px; }

/* ---- Kopf und Fuss der Gastseite (02.10.2026) ------------------------------------------------
   Der Befund des Betreibers: die Gastseite "sieht sehr schwach aus - ohne Logo, ohne Fussbereich".
   Das Logo liess sich nie fuellen, der Fuss trug nur die Marke des Hauses. Keine festen Farben:
   alles aus --accent, --ink und --line, die der Betrieb ueber /branding.css setzt (P0-7). Vom
   Telefon aus gedacht - eine Spalte, und jeder Verweis im Fuss hat 44px Tippflaeche. */
/* Nur unter .guest: class="head" tragen auch Verwaltung, Board und Theke - deren Kopf soll sich
   durch den Auftritt des Kunden nicht verschieben. */
.guest .head { padding: 24px 0 14px; }
/* Das hochkante Logo (368x560) blieb bei 96px Hoehe nur rund 63px breit - als Kopfzeile eines
   Lokals zu zaghaft. 150px geben ihm Raum; max-width: 80% aus der Grundregel begrenzt es weiterhin
   zur Seite hin, und auf schmalen Geraeten nimmt es anteilig weniger (Regel am Ende des Blocks). */
.guest .logo { max-height: 150px; margin-bottom: 14px; }
.tagline { margin: 8px auto 0; max-width: 30em; font-size: .9rem; letter-spacing: .04em;
  text-transform: uppercase; opacity: .85; }
/* Ueber die Spezifitaet, nicht mit !important: .head p (0,1,1) ist spezifischer als .tagline
   (0,1,0) und hat deshalb deren `margin: 8px auto 0` ueberschrieben. Mit `margin: 0` fielen die
   auto-Raender weg - der Claim klebte in seinem 30em breiten Kasten am linken Rand, waehrend Logo
   und Name mittig standen. Auf der Produktion sichtbar, und es sah nach einem Layoutfehler aus,
   weil es einer war. Dieselbe Regel hat auch .age, .table und .trialnotice ihr margin-top
   genommen: im Kopf klebte alles aneinander.
   .guest .head .x (0,3,0) gewinnt gegen .head p und bleibt dabei auf die Gastseite begrenzt -
   class="guest" tragen nur _Layout und Menu/Index, also behalten Verwaltung, Board und Theke ihren
   Kopf unveraendert.
   Bewusst NICHT der kuerzere Weg ueber `.head :where(p)`: der zaehlt mit Spezifitaet 0 und haette
   den Abstand auch auf den Personalseiten wiederbelebt (.operation ueberall, .trialnotice im
   Testzugang) - vier Kopfzeilen, die hier niemand angefasst haben wollte. Dass deren margin-top
   dort weiterhin tot ist, ist damit bekannt und absichtlich stehen geblieben. */
.guest .head .tagline { margin: 10px auto 0; }
.guest .head .age { margin-top: 12px; }
.guest .head .trialnotice { margin-top: 12px; }
.guest .head .table { margin-top: 10px; }
/* Schmales Geraet: das Logo nimmt anteilig weniger Hoehe, sonst schiebt es die Karte unter die
   Falz - die erste Seite nach dem QR-Code soll mit Artikeln beginnen, nicht mit Scrollen. */
@media (max-width: 420px) {
  .guest .logo { max-height: 112px; }
}
/* Der Fuss war mit .6 fast nicht zu lesen - mit Anschrift und Impressum darin ist er kein
   Kleingedrucktes mehr, sondern eine Angabe, die ein Gast finden soll. */
.foot { margin-top: 36px; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: .8rem; opacity: .8; }
.foot p { margin: 0 0 4px; }
.foot .contact { opacity: .9; }
.foot .legal a { display: inline-block; min-height: 44px; padding: 10px 6px; color: var(--accent); }

/* ==== GESTALTUNG-KARTE-2026-10-02 =============================================================
   Der Befund des Betreibers: "Die Seite sieht immer noch sehr schwach aus, kein besonderer Stil.
   Der Flyer sieht besser aus." Er hatte recht - die Karte war eine ununterbrochene Liste aus 81
   Zeilen in 10 Gruppen, alles in derselben Groesse, Gruppe und Artikel kaum zu unterscheiden.

   Was die gedruckte Karte besser macht und hier nachgebaut ist:
     - jede Gruppe steht in einem eigenen Feld mit feiner Linie und dunklerem Grund,
     - die Gruppenueberschrift haengt zwischen zwei Zierlinien und traegt eine Serifenschrift,
     - Name und Preis sind durch eine Punktlinie verbunden, der Preis steht rechts in Akzentfarbe,
     - es gibt eine Groessenstufung (Bereich > Gruppe > Name > Beschreibung) statt einer Groesse.

   Keine festen Farben: alles leitet sich ueber color-mix aus --brand, --accent, --ink, --black und
   --line ab, die der Betrieb ueber /branding.css setzt (P0-7). Die dritte, dunkelrote Farbe des
   Flyers gibt es im Modell nicht und sie wird deshalb NICHT erfunden - wo der Flyer sie benutzt,
   steht hier eine Abstufung von --brand. (Der Name dieser Farbe faellt hier bewusst nicht: er
   gehoert einem Kunden, und BrandingTests prueft genau das.)
   Keine fremde Schrift und kein CDN (style-src 'self', P0-8): die Serifenschrift ist ein Stapel
   aus Schriften, die auf dem Geraet schon liegen, und laedt nichts nach.
   Alles unter .guest - dieselben Namen gelten auf Board und Theke anders.
   Vom Telefon aus gedacht: eine Spalte, nichts rollt waagerecht, jede Tippflaeche misst 44px. */
.guest {
  /* Serifen aus dem Bestand des Geraets, in dieser Reihenfolge: Windows/macOS, Windows, Linux. */
  --display: Georgia, "Times New Roman", "Noto Serif", "Liberation Serif", serif;
  /* Die Zierlinie und der Feldrand: Akzent, aber zurueckgenommen - sonst rahmt die Karte sich
     selbst zu Tode. */
  --rule: color-mix(in srgb, var(--accent) 32%, transparent);
  /* Der Grund eines Feldes, zwei Stufen: oben fast schwarz, unten ein Hauch der Hausfarbe. Genau
     dieser Verlauf laesst das gedruckte Feld des Flyers plastisch wirken. */
  --panel-top: color-mix(in srgb, var(--black) 72%, transparent);
  --panel-bottom: color-mix(in srgb, var(--brand) 40%, transparent);
}

/* ---- Sprungleiste ---------------------------------------------------------------------------
   Umbrechend statt rollend: eine waagerechte Rollleiste ist auf der Gastkarte verboten, und zehn
   haftende Marken fraessen drei Reihen Bildschirm. Deshalb bricht sie um und haftet nicht. */
.guest .jump {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
  margin: 16px 0 24px; padding: 0; list-style: none;
}
.guest .jumpitem {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px;
  border: 1px solid var(--rule); border-radius: 999px;
  background: color-mix(in srgb, var(--black) 55%, transparent);
  color: var(--accent); text-decoration: none;
  font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
}
.guest .jumpitem:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- Oberbereich: "Getränke & Küche" und "Shisha" --------------------------------------------
   Zwei Linien ueber und unter dem Wort - die ruhigste Art, einen Teil der Karte als eigenen Teil
   zu zeigen, ohne eine dritte Farbe zu erfinden. */
.guest .areahead {
  margin: 40px 0 18px; padding: 10px 0;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  font-family: var(--display); font-size: 1.5rem; font-weight: 400;
  letter-spacing: .22em; text-transform: uppercase; text-align: center;
  color: var(--accent);
}
.guest .areahead span { display: block; }

/* ---- Gruppe: ein Feld wie auf dem Flyer ------------------------------------------------------ */
.guest .group {
  margin: 0 0 18px; padding: 16px 14px 8px;
  border: 1px solid var(--rule); border-radius: 14px;
  background: linear-gradient(180deg, var(--panel-top), var(--panel-bottom));
  box-shadow: 0 14px 28px -22px var(--black);
  /* Damit ein Sprungziel nicht am obersten Bildpunkt klebt. */
  scroll-margin-top: 14px;
}
/* Die Gruppenueberschrift haengt zwischen zwei Zierlinien (::before / ::after) - kein Bild, kein
   Zeichen aus einer fremden Schrift, nur zwei Linien, die den Rest der Zeile fuellen. */
.guest .grouphead {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 12px; font-family: var(--display); font-size: 1.25rem; font-weight: 400;
  letter-spacing: .08em; color: var(--accent); text-align: center;
}
.guest .grouphead::before, .guest .grouphead::after {
  content: ""; flex: 1 1 auto; height: 0; border-top: 1px solid var(--rule);
}
.guest .groupname { flex: 0 1 auto; }

/* ---- Artikelzeile ---------------------------------------------------------------------------
   Zwei Spalten: links die ganze Angabe, rechts der "+"-Knopf neben der ersten Zeile. Der Abstand
   steckt im Knopf und nicht im column-gap, sonst bliebe ohne Knopf rechts totes Land.
   Der Knopf steht ausdruecklich in `grid-row: 1` und NICHT in `1 / -1`: ohne grid-template-rows
   zeigt die Linie -1 auf dieselbe Linie 1, der Knopf haette also ohnehin nur die erste Zeile
   belegt - sie dabei aber auf seine 48px aufgezogen. Die Punktlinienzeile daneben wird gestreckt,
   und der Name haengt oben in einer 48px hohen Zeile mit einer Luecke zur Beschreibung. Deshalb
   zusaetzlich align-self an der Zeile selbst. */
.guest .items .item {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 0;
  padding: 9px 0; border-bottom: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
}
.guest .items .item:last-child { border-bottom: 0; }
.guest .items .item .plus { grid-row: 1; align-self: center; margin-left: 12px; }

/* Name - Punktlinie - Preis in einer Zeile. Die Punktlinie ist ein leeres Feld, das den Rest der
   Breite nimmt; sie fuehrt das Auge ueber die Luecke wie auf der gedruckten Karte. */
.guest .itemline { display: flex; align-items: baseline; gap: 8px; align-self: center; }
.guest .itemline .name { flex: 0 1 auto; font-size: 1rem; font-weight: 600; letter-spacing: .01em; }
.guest .dots {
  flex: 1 1 24px; min-width: 18px; align-self: center; height: 0;
  border-bottom: 1px dotted color-mix(in srgb, var(--accent) 45%, transparent);
}
/* Der Preis bleibt bewusst bei der Grundschrift: Georgia setzt Mediaevalziffern, bei denen 3, 4, 5
   und 9 unter die Grundlinie reichen - eine Preisspalte wird damit unruhig. Die Zier steckt in den
   Ueberschriften, die Preisspalte soll ruhig sein. */
.guest .itemline .price {
  flex: 0 0 auto; font-size: 1.05rem; font-weight: 600;
  color: var(--accent); font-variant-numeric: tabular-nums;
}

/* Die leisere Stufe: Beschreibung und Hinweis ("hausgemacht") stehen unter dem Namen, nicht
   daneben - und deutlich kleiner, damit der Name die Zeile fuehrt. */
.guest .items .desc, .guest .items .notice, .guest .items .tag {
  grid-column: 1; margin: 3px 0 0; font-size: .82rem; line-height: 1.35; opacity: .72;
}
.guest .items .notice { font-style: italic; color: color-mix(in srgb, var(--accent) 75%, var(--ink)); opacity: .9; }

/* 18+ als kleines Schild - an der Gruppe, wenn jeder Artikel darin 18+ ist, sonst an der Zeile.
   Die Farbe ist eine Abstufung von --accent in Richtung --brand, kein drittes Farbfeld. */
.guest .agemark {
  display: inline-block; margin: 4px 0 0; padding: 1px 8px;
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent); border-radius: 999px;
  background: color-mix(in srgb, var(--brand) 55%, transparent);
  color: color-mix(in srgb, var(--accent) 85%, var(--ink));
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: .68rem; font-weight: 600; letter-spacing: .08em; vertical-align: middle;
}
.guest .grouphead .agemark { margin: 0; flex: 0 0 auto; }
/* In der Artikelzeile ausdruecklich in Spalte 1 und auf Inhaltsbreite: ohne grid-column wuerde die
   automatische Platzierung das Schild hinter einer Beschreibung in die Knopfspalte schieben, und
   ohne justify-self zoege es sich als randvolle Pille ueber die ganze Breite. */
.guest .items .agemark { grid-column: 1; justify-self: start; }

/* "aus" statt "gestrichen": der Artikel bleibt lesbar, tritt aber sichtbar zurueck. Durchstrich und
   Deckkraft kommen aus der Grundregel (.soldout .name/.price) und bleiben dort - eine zweite
   Deckkraft an der Zeile haette sich mit ihr multipliziert und Name und Preis auf etwa .25
   heruntergezogen. Hier bleibt nur die Punktlinie, die mitredet. */
.guest .items .soldout .dots { border-bottom-style: dashed; }
.guest .items .tag { text-transform: uppercase; letter-spacing: .08em; font-size: .72rem; }

/* Sanftes Springen nur, wenn niemand darum gebeten hat, es zu lassen. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
/* Schmales Geraet: etwas weniger Rand im Feld, damit die Zeile nicht umbricht, und die Marken der
   Sprungleiste ruecken enger zusammen. Die Tippflaeche von 44px bleibt. */
@media (max-width: 420px) {
  .guest .group { padding: 14px 11px 6px; }
  .guest .areahead { font-size: 1.3rem; letter-spacing: .16em; }
  .guest .grouphead { font-size: 1.12rem; gap: 9px; }
  .guest .jump { gap: 6px; }
  .guest .jumpitem { padding: 0 11px; font-size: .74rem; }
}