/* ==========================================================================
   Breadtime Bakery — components.css
   Buttons, Icons, Karten, Badges, Formularfelder, WhatsApp-Button
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Icons
   -------------------------------------------------------------------------- */

.icon {
  display: inline-block;
  inline-size: 1.25em;
  block-size: 1.25em;
  vertical-align: -0.2em;
  flex-shrink: 0;
  fill: none;
}
.icon--sm { inline-size: 1em; block-size: 1em; }
.icon--lg { inline-size: 1.75rem; block-size: 1.75rem; }
.icon--xl { inline-size: 2.25rem; block-size: 2.25rem; }

/* --------------------------------------------------------------------------
   2. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-block-size: 2.875rem;
  padding: var(--sp-3) var(--sp-5);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  border: 1.5px solid transparent;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}
.btn .icon { inline-size: 1.125rem; block-size: 1.125rem; vertical-align: middle; }

/* Primär: Amber-Fläche mit brauner Schrift (Kontrast 5.2:1 — AA erfüllt).
   Amber niemals als Textfarbe auf hellem Grund verwenden. */
.btn--primary {
  background-color: var(--c-amber);
  color: var(--c-brown);
  box-shadow: var(--shadow-sm);
}
.btn--primary:hover {
  background-color: var(--c-amber-600);
  color: var(--c-brown);
  box-shadow: var(--shadow-md);
}

.btn--dark {
  background-color: var(--c-brown);
  color: var(--c-cream);
}
.btn--dark:hover {
  background-color: var(--c-brown-700);
  color: var(--c-cream);
}

.btn--outline {
  background-color: transparent;
  border-color: var(--c-brown);
  color: var(--c-brown);
}
.btn--outline:hover {
  background-color: var(--c-brown);
  color: var(--c-cream);
}

/* Für dunkle Sektionen */
.btn--ghost-light {
  background-color: transparent;
  border-color: rgba(237, 226, 209, 0.45);
  color: var(--c-cream);
}
.btn--ghost-light:hover {
  background-color: var(--c-cream);
  border-color: var(--c-cream);
  color: var(--c-brown);
}

/* WhatsApp: derselbe Grünton wie beim schwebenden Knopf — das gedeckte
   #0F7A46 statt des hellen Markengrüns. Weiße Schrift darauf erreicht 5,40:1
   und damit AA; auf dem Markengrün wären es 1,98:1. Siehe OFFENE-PUNKTE T8. */
.btn--whatsapp {
  background-color: var(--c-whatsapp);
  color: var(--c-white);
  box-shadow: var(--shadow-sm);
}
.btn--whatsapp:hover {
  background-color: var(--c-whatsapp-dark);
  color: var(--c-white);
  box-shadow: var(--shadow-md);
}
.btn--whatsapp:focus-visible { outline-color: var(--c-brown); }

.btn--sm { min-block-size: 2.375rem; padding: var(--sp-2) var(--sp-4); font-size: var(--fs-sm); }
.btn--lg { min-block-size: 3.375rem; padding: var(--sp-4) var(--sp-7); font-size: var(--fs-lg); }
.btn--block { inline-size: 100%; }

/* Textlink mit Pfeil, der bei Hover wandert */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 600;
  text-decoration: none;
  color: var(--c-brown);
}
.link-arrow .icon { transition: transform var(--dur) var(--ease); }
.link-arrow:hover { color: var(--c-amber-600); }
.link-arrow:hover .icon { transform: translateX(0.25rem); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.btn-row--center { justify-content: center; }

/* --------------------------------------------------------------------------
   2b. Hero-Carousel
   Jede Folie ist eine ganzflächige Bildfläche, der Text liegt darüber.
   Aufbau wie die Produktgalerie: eine scroll-snap-Leiste, die ohne JavaScript
   wisch- und scrollbar ist. carousel.js lässt sie von selbst weiterlaufen.
   Bedienelemente gibt es auf Kundenwunsch keine.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  /* Farbe, solange das Bild noch nicht da ist — nicht Weiß, sonst blitzt es */
  background-color: var(--c-brown-800);
  color: var(--text-on-dark);
  border-block-end: 1px solid var(--border);
}

.hero__track {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.hero__track::-webkit-scrollbar { display: none; }

/* isolation: Das Bild liegt mit z-index: -1 hinter dem Text, soll aber nicht
   hinter die Folie selbst rutschen — der eigene Stapelkontext hält es drin. */
.hero__slide {
  position: relative;
  isolation: isolate;
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: grid;
  align-items: center;
  min-block-size: 26rem;                        /* Rückfall ohne svh */
  min-block-size: clamp(26rem, 68svh, 34rem);
}
@media (min-width: 56em) {
  .hero__slide {
    min-block-size: 32rem;
    min-block-size: clamp(32rem, 74svh, 42rem);
  }
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}
.hero__bg-img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center;
}

/* Der Schleier trägt die Lesbarkeit. Werte und Rechnung stehen bei den Tokens
   in base.css. Hochkant liegt der Text über der ganzen Breite, deshalb deckt
   der Schleier dort fast alles ab; ab 56em steht er links unter dem Text und
   gibt die rechte Seite dem Bild frei. */
.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    var(--hero-schleier-oben) 0%,
    var(--hero-schleier) 14%,
    var(--hero-schleier) 100%);
}
@media (min-width: 56em) {
  .hero__bg::after {
    background: linear-gradient(
      to right,
      var(--hero-schleier) 0%,
      var(--hero-schleier) 58%,
      var(--hero-schleier-weich) 90%,
      var(--hero-schleier-weich) 100%);
  }
}

.hero__inner {
  padding-block: clamp(2rem, 1.5rem + 3vw, 3.5rem);
}

.hero__text { max-inline-size: 34rem; }
.hero__text > * + * { margin-block-start: var(--sp-4); }
.hero__text .btn-row { margin-block-start: var(--sp-6); }

.hero h1,
.hero__title { color: var(--c-cream); }
/* Auch der Fließtext in voller Stärke, nicht gedämpft: Auf einem Foto ist der
   gedämpfte Ton der Grund, warum der Schleier dicht sein müsste — siehe die
   Rechnung bei den Tokens in base.css. In voller Stärke bleibt vom Bild
   deutlich mehr übrig. */
.hero__lead { color: var(--text-on-dark); }
/* Auf dunklem Grund muss der Fokusring hell sein, sonst ist er unsichtbar. */
.hero :focus-visible { outline-color: var(--c-amber); }

/* Folie 2 und 3 tragen statt <h1> einen Absatz: Auf einer Seite gehört genau
   eine erste Überschrift, und die soll nicht davon abhängen, welche Folie
   gerade sichtbar ist. Aussehen identisch zu h1 (base.css). */
.hero__title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: var(--fs-h1);
  font-weight: 600;
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.hero__lead {
  max-width: 40rem;
  font-size: var(--fs-lg);
}

/* --- Platzhalter, solange keine Hero-Aufnahmen da sind (I6) ---------------
   Statt eines Fotos eine warme CI-Fläche mit dem freigestellten Produktfoto
   rechts. Die Fläche ist hell, also kehren sich die Textfarben um und der
   Schleier entfällt — auf einer bekannten Farbe ist er nicht nötig, und über
   dem Freisteller wäre er sogar schädlich. Fällt beim Bildaustausch komplett
   weg: Modifikator aus dem Markup nehmen, dieser Block kann dann raus. */
.hero__slide--flaeche .hero__bg {
  background:
    radial-gradient(circle at 78% 50%,
      var(--c-amber-100) 0%,
      var(--c-cream-100) 55%,
      var(--c-cream-50) 100%);
}
.hero__slide--flaeche .hero__bg::after { content: none; }

/* Die Produktfotos liegen als JPEG auf reinem Weiß — als Freisteller taugen
   sie nur mit `multiply`: Weiß wird gegen den Untergrund gerechnet und
   verschwindet, das Gebäck bleibt stehen.

   Erst ab 62em, und auch dann auf 38 % der Breite begrenzt: Darunter reicht
   der Platz neben dem Text nicht, das Motiv liefe unter die Zeilen — und
   dunkler Text auf dem Gebäck ist nicht mehr verlässlich lesbar. Schmale
   Fenster bekommen deshalb nur die Fläche. Beim echten Hero-Foto stellt sich
   die Frage nicht: Das liegt hinter dem Schleier und trägt den Text überall. */
.hero__slide--flaeche .hero__bg-img { display: none; }
@media (min-width: 62em) {
  .hero__slide--flaeche .hero__bg-img {
    display: block;
    position: absolute;
    inset-block-end: 6%;
    inset-inline-end: 4%;
    inline-size: auto;
    max-inline-size: 38%;
    block-size: 78%;
    object-fit: contain;
    object-position: bottom right;
    mix-blend-mode: multiply;
  }
}

.hero__slide--flaeche h1,
.hero__slide--flaeche .hero__title { color: var(--text-strong); }
.hero__slide--flaeche .hero__lead { color: var(--text-muted); }
.hero__slide--flaeche :focus-visible { outline-color: var(--focus); }

/* --------------------------------------------------------------------------
   3. Karten
   -------------------------------------------------------------------------- */

.card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: var(--c-white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.card--interactive:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
/* Quadratisch: Brötchen, Ringe und Brote sind rundliche Motive, die im
   Quadrat besser sitzen als im Querformat. Quadratische Zulieferung ist
   außerdem die flexibelste — daraus lässt sich jedes andere Format
   beschneiden, umgekehrt nicht. */
.card__media {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background-color: var(--c-cream-100);
}
.card__media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease);
}
.card--interactive:hover .card__media img { transform: scale(1.05); }

.card__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-5);
}
.card__title { font-size: var(--fs-h4); }
.card__text { color: var(--text-muted); font-size: var(--fs-sm); line-height: var(--lh-snug); }
.card__footer { margin-block-start: auto; padding-block-start: var(--sp-3); }

/* Icon-Karte für USP-/Feature-Blöcke */
.feature {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  background-color: var(--c-white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.feature__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 3rem;
  block-size: 3rem;
  border-radius: var(--r-md);
  background-color: var(--c-amber-100);
  color: var(--c-brown);
}
.feature__icon .icon { inline-size: 1.5rem; block-size: 1.5rem; }
.feature p { color: var(--text-muted); font-size: var(--fs-sm); line-height: var(--lh-snug); }

.section--inverse .feature {
  background-color: rgba(237, 226, 209, 0.06);
  border-color: rgba(237, 226, 209, 0.16);
}
.section--inverse .feature__icon {
  background-color: rgba(251, 169, 24, 0.18);
  color: var(--c-amber);
}
.section--inverse .feature p { color: var(--text-on-dark-muted); }

/* --------------------------------------------------------------------------
   3b. Produktkachel mit Bildergalerie
   Aufbau bewusst so, dass ohne JavaScript alles Wesentliche funktioniert:
   die Galerie ist eine scroll-snap-Leiste (wischen und scrollen gehen nativ),
   die Variantenauswahl sind echte Radio-Buttons, deren Wirkung über :has()
   in CSS greift. JavaScript ergänzt nur Pfeile, Punkte und Tastaturbedienung.
   -------------------------------------------------------------------------- */

.product { position: relative; }

/* Das Radio steckt im Label. Dadurch braucht es kein for/id-Paar, der Klick
   aufs Chip schaltet nativ um, und der Fokusring lässt sich am Chip zeigen. */
.variant-input {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}

/* --- Galerie --- */

.gallery { display: none; block-size: 100%; }

/* Produkte ohne Varianten zeigen ihre einzige Galerie immer. */
.product:not(:has(.variant-input)) .gallery { display: block; }

/* Mit Varianten: die Galerie zur angehakten Variante. Die Kürzel sind ein
   fester, kleiner Satz (siehe docs/BILDER-SPEC.md), deshalb reichen
   statische Regeln — kein JavaScript nötig. */
.product:has(.variant-input[value="glatt"]:checked) .gallery[data-variant="glatt"],
.product:has(.variant-input[value="sesam"]:checked) .gallery[data-variant="sesam"],
.product:has(.variant-input[value="sesam-schwarzkuemmel"]:checked) .gallery[data-variant="sesam-schwarzkuemmel"],
.product:has(.variant-input[value="schwarzkuemmel"]:checked) .gallery[data-variant="schwarzkuemmel"],
.product:has(.variant-input[value="mehrkorn"]:checked) .gallery[data-variant="mehrkorn"],
.product:has(.variant-input[value="malz"]:checked) .gallery[data-variant="malz"],
.product:has(.variant-input[value="koerner"]:checked) .gallery[data-variant="koerner"] { display: block; }

.gallery__track {
  display: flex;
  block-size: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.gallery__track::-webkit-scrollbar { display: none; }

.gallery__slide {
  position: relative;
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}
.gallery__slide img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
}

/* Zoom-Knopf, den products.js um jedes Bild legt. Er ersetzt kein Layout —
   er erbt schlicht die Fläche der Folie, damit das Bild weiter passt. */
.gallery__zoom {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

/* Bilder mit freiem Hintergrund brauchen eine Kante, sonst franst das Foto
   im weißen Kartenraum aus. Freisteller haben sie nicht nötig. */
.gallery__slide--framed img {
  background-color: var(--c-cream-100);
  box-shadow: inset 0 0 0 1px var(--border);
}

/* --- Pfeile, erst per JS eingehängt --- */

.gallery__nav {
  position: absolute;
  inset-block-start: 50%;
  translate: 0 -50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  padding: 0;
  background-color: color-mix(in srgb, var(--c-white) 88%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  color: var(--c-brown);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), background-color var(--dur-fast) var(--ease);
}
@supports (backdrop-filter: blur(1px)) {
  .gallery__nav { backdrop-filter: blur(6px); }
}
.gallery__nav--prev { inset-inline-start: var(--sp-3); }
.gallery__nav--next { inset-inline-end: var(--sp-3); }
.gallery__nav:hover { background-color: var(--c-white); }
.gallery__nav[disabled] { opacity: 0 !important; pointer-events: none; }
.gallery__nav .icon { inline-size: 1.125rem; block-size: 1.125rem; }

/* Auf dem Touchscreen wird gewischt, da stören dauerhaft sichtbare Pfeile.
   Sie erscheinen bei Hover, Fokus innerhalb der Karte oder ohne Hover-Gerät. */
.card:hover .gallery__nav,
.card:focus-within .gallery__nav { opacity: 1; }
@media (hover: none) {
  .card:focus-within .gallery__nav { opacity: 1; }
}

/* --- Punkte --- */

.gallery__dots {
  position: absolute;
  inset-block-end: var(--sp-3);
  inset-inline: 0;
  display: flex;
  justify-content: center;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.gallery__dot {
  inline-size: 1.5rem;
  block-size: 1.5rem;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.gallery__dot::before {
  content: "";
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: 50%;
  background-color: var(--c-cream-400);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.7);
  transition: background-color var(--dur-fast) var(--ease),
              scale var(--dur-fast) var(--ease);
}
.gallery__dot[aria-current="true"]::before {
  background-color: var(--c-brown);
  scale: 1.25;
}

/* --- Kennzeichnung KI-generierter Bilder --- */

/* Kein position/inset hier: Die Platzierung übernimmt der jeweilige Ort —
   `.card__media .badge` an der Kachel, `.lightbox__badge` am großen Bild.
   Stünde inset-inline-end hier, zöge die Kachelregel mit ihrem
   inset-inline-start das Abzeichen auf die volle Kachelbreite auseinander. */
.badge--ai {
  background-color: color-mix(in srgb, var(--c-brown) 92%, transparent);
  border-color: transparent;
  color: var(--c-cream);
  letter-spacing: var(--tracking-wide);
  box-shadow: var(--shadow-sm);
}

/* --- Variantenauswahl --- */

/* fieldset bringt Rahmen, Innenabstand und Mindestbreite mit — alles weg.
   Das Element bleibt trotzdem ein fieldset, weil es die Chips für
   Screenreader als zusammengehörige Auswahl ausweist. */
.variant-picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-1) 0 0;
  padding: 0;
  border: 0;
  min-inline-size: 0;
}
.variant-picker__legend {
  inline-size: 100%;
  margin-block-end: var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.variant-chip {
  padding: 0.3rem var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.4;
  background-color: var(--c-cream-50);
  border: 1.5px solid var(--border);
  border-radius: var(--r-pill);
  color: var(--text-body);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.variant-chip:hover { border-color: var(--c-brown-400); }

.product:has(.variant-input[value="glatt"]:checked) .variant-chip[data-variant="glatt"],
.product:has(.variant-input[value="sesam"]:checked) .variant-chip[data-variant="sesam"],
.product:has(.variant-input[value="sesam-schwarzkuemmel"]:checked) .variant-chip[data-variant="sesam-schwarzkuemmel"],
.product:has(.variant-input[value="schwarzkuemmel"]:checked) .variant-chip[data-variant="schwarzkuemmel"],
.product:has(.variant-input[value="mehrkorn"]:checked) .variant-chip[data-variant="mehrkorn"],
.product:has(.variant-input[value="malz"]:checked) .variant-chip[data-variant="malz"],
.product:has(.variant-input[value="koerner"]:checked) .variant-chip[data-variant="koerner"] {
  background-color: var(--c-amber);
  border-color: var(--c-amber);
}

/* Fokusring am Chip, weil das Radio selbst unsichtbar ist */
.variant-chip:has(.variant-input:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* --- Kopfzeile der Kachel --- */

.product__title a {
  text-decoration: none;
  color: inherit;
}
.product__title a:hover { color: var(--c-amber-600); }
.product__note {
  margin-block-start: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   3c. Lightbox
   Natives <dialog>: Fokusfalle, Escape und Hintergrund kommen vom Browser.
   Der Dialog füllt den Viewport, damit ein Klick daneben schließen kann.
   -------------------------------------------------------------------------- */

.lightbox {
  inline-size: 100vw;
  max-inline-size: 100vw;
  block-size: 100dvh;
  max-block-size: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  /* Die Abdunklung liegt auf dem Dialog selbst, nicht nur auf ::backdrop:
     Der Dialog füllt ohnehin den ganzen Viewport, und ::backdrop wird nicht
     überall zuverlässig gezeichnet. Beide tragen denselben Ton. */
  background-color: rgba(38, 24, 20, 0.86);
}
/* Erst im geöffneten Zustand auf Flex schalten: Ein geschlossener <dialog>
   steht auf display:none, und das darf keine Regel überschreiben. */
.lightbox[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox::backdrop { background-color: rgba(38, 24, 20, 0.86); }

/* Das Abzeichen sitzt am Bild, nicht am Viewport — deshalb die Hülle. */
.lightbox__figur {
  position: relative;
  display: flex;
}
.lightbox__badge {
  position: absolute;
  inset-block-start: var(--sp-3);
  inset-inline-end: var(--sp-3);
}
.lightbox__badge[hidden] { display: none; }

.lightbox__img {
  display: block;
  inline-size: auto;
  block-size: auto;
  max-inline-size: min(92vw, 60rem);
  max-block-size: 88dvh;
  border-radius: var(--r-md);
  background-color: var(--c-white);
}

.lightbox__close,
.lightbox__nav {
  position: fixed;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  padding: 0;
  background-color: color-mix(in srgb, var(--c-white) 90%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  color: var(--c-brown);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover { background-color: var(--c-white); }
.lightbox__close[hidden],
.lightbox__nav[hidden] { display: none; }

.lightbox__close {
  inset-block-start: var(--sp-4);
  inset-inline-end: var(--sp-4);
}
/* Mobile-first: Auf schmalen Geräten sitzen die Pfeile unter dem Bild —
   zwischen Bildkante und Displayrand ist seitlich kein Platz. */
.lightbox__nav { inset-block-end: calc(var(--sp-8) + var(--sp-4)); }
.lightbox__nav--prev { inset-inline-start: var(--sp-3); }
.lightbox__nav--next { inset-inline-end: var(--sp-3); }
@media (min-width: 34em) {
  .lightbox__nav {
    inset-block-start: 50%;
    inset-block-end: auto;
    translate: 0 -50%;
  }
}
.lightbox__close .icon,
.lightbox__nav .icon { inline-size: 1.25rem; block-size: 1.25rem; }

/* Der WhatsApp-Knopf liegt auf dem Telefon genau dort, wo in der Lightbox der
   Vorwärtspfeil sitzt. Solange das Bild groß ist, hat er nichts zu suchen. */
body.has-lightbox-open .whatsapp-fab { display: none; }

.lightbox__count {
  position: fixed;
  inset-block-end: var(--sp-4);
  inset-inline: 0;
  margin: 0;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--c-cream);
}

/* --------------------------------------------------------------------------
   4. Badges & Tags
   -------------------------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 0.2rem var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: 0.03em;
  border-radius: var(--r-pill);
  background-color: var(--c-cream-100);
  color: var(--c-brown);
  border: 1px solid var(--border);
}
.badge--amber { background-color: var(--c-amber); border-color: var(--c-amber); }
.badge--vegan { background-color: #e3f0e5; border-color: #c2ddc7; color: #23522f; }
.badge--frozen { background-color: #e2edf5; border-color: #c3dbeb; color: #1f4c6b; }

/* Auf Bildern liegende Badges */
.card__media .badge {
  position: absolute;
  inset-block-start: var(--sp-3);
  inset-inline-start: var(--sp-3);
  box-shadow: var(--shadow-sm);
}

.tag-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* Segment-Kennzeichnung Markt / Fast-Food / Gastro */
.segment {
  --segment-color: var(--c-amber);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}
.segment::before {
  content: "";
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: 50%;
  background-color: var(--segment-color);
}
/* Zwei Segmente laut Produktliste des Kunden vom 11.08.2026 — vorher waren
   drei geplant (Markt / Fast Food / Gastro). Siehe docs/OFFENE-PUNKTE.md I16. */
.segment--supermarkt { --segment-color: #c8722a; }
.segment--gastro { --segment-color: #7a6d3f; }

/* --------------------------------------------------------------------------
   5. Formularfelder
   -------------------------------------------------------------------------- */

.field { display: grid; gap: var(--sp-2); }
.field__label { font-size: var(--fs-sm); font-weight: 600; }
.field__label .req { color: var(--c-error); }
.field__hint { font-size: var(--fs-xs); color: var(--text-muted); }

.input,
.textarea,
.select {
  inline-size: 100%;
  min-block-size: 2.875rem;
  padding: var(--sp-3) var(--sp-4);
  background-color: var(--c-white);
  border: 1.5px solid var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text-body);
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
/* Volle Deckkraft: mit opacity würde der Platzhaltertext unter AA rutschen. */
.input::placeholder, .textarea::placeholder { color: var(--c-brown-400); opacity: 1; }
.input:hover, .textarea:hover, .select:hover { border-color: var(--c-brown-400); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--c-brown);
  box-shadow: 0 0 0 3px rgba(251, 169, 24, 0.35);
}
.textarea { min-block-size: 8rem; resize: vertical; line-height: var(--lh-snug); }

.select {
  appearance: none;
  padding-inline-end: var(--sp-8);
  /* Pfeil als Data-URI, damit kein zusätzlicher Request nötig ist */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235a382f' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-4) center;
}

.input[aria-invalid="true"],
.textarea[aria-invalid="true"],
.select[aria-invalid="true"] { border-color: var(--c-error); }

.field__error {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--c-error);
}

/* Rückmeldung über dem Formular. Farbe trägt die Aussage nicht allein —
   der Text sagt dasselbe, und die Kante links markiert sie zusätzlich. */
.form-status {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border);
  border-inline-start: 4px solid var(--c-brown-400);
  border-radius: var(--r-md);
  background-color: var(--c-cream-100);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
}
.form-status--erfolg {
  border-inline-start-color: #2f7a45;
  background-color: #e3f0e5;
  color: #23522f;
}
.form-status--fehler {
  border-inline-start-color: var(--c-error);
  background-color: #fbe9e7;
  color: #8a2118;
}

.check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-3);
  align-items: start;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  cursor: pointer;
}
.check input[type="checkbox"],
.check input[type="radio"] {
  inline-size: 1.25rem;
  block-size: 1.25rem;
  margin-block-start: 0.1rem;
  accent-color: var(--c-brown);
  cursor: pointer;
}

/* Honeypot: für Menschen unsichtbar, für Bots ausfüllbar */
.hp-field {
  position: absolute !important;
  inline-size: 1px; block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Hervorgehobener Kontaktweg, z. B. WhatsApp über dem Kontaktformular.
   Drei Spalten ab Tablet: Symbol, Text, Knopf — darunter gestapelt. */
.contact-highlight {
  display: grid;
  gap: var(--sp-4);
  align-items: center;
  padding: var(--sp-6);
  background-color: var(--c-white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.contact-highlight__text { display: grid; gap: var(--sp-2); }
.contact-highlight p { color: var(--text-muted); font-size: var(--fs-sm); line-height: var(--lh-snug); }
@media (min-width: 48em) {
  .contact-highlight {
    grid-template-columns: auto 1fr auto;
    gap: var(--sp-5);
  }
}

/* --------------------------------------------------------------------------
   6. Floating WhatsApp-Button
   Mobil: Kreis. Ab Tablet: Pille, die bei Hover/Fokus den Text ausfährt.
   -------------------------------------------------------------------------- */

/* Eingeklappt exakt kreisrund: Höhe 3.5rem, Icon 1.625rem, also beidseitig
   0.9375rem Innenabstand und gap 0 — zusammen wieder 3.5rem Breite.
   Beim Ausklappen wachsen gap und Innenabstand mit, deshalb bleibt der
   Übergang rund und die Abstände symmetrisch. */
.whatsapp-fab {
  position: fixed;
  inset-block-end: clamp(1rem, 3vw, 1.75rem);
  inset-inline-end: clamp(1rem, 3vw, 1.75rem);
  z-index: var(--z-fab);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  block-size: 3.5rem;
  padding-inline: 0.9375rem;
  background-color: var(--c-whatsapp);
  color: var(--c-white);
  font-weight: 600;
  text-decoration: none;
  border-radius: var(--r-pill);
  box-shadow: 0 4px 12px rgba(47, 27, 20, 0.22), 0 12px 32px rgba(47, 27, 20, 0.18);
  transition: background-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              gap var(--dur-slow) var(--ease),
              padding-inline var(--dur-slow) var(--ease);
}
.whatsapp-fab .icon {
  inline-size: 1.625rem;
  block-size: 1.625rem;
  vertical-align: middle;
}
.whatsapp-fab:hover,
.whatsapp-fab:focus-visible {
  background-color: var(--c-whatsapp-dark);
  color: var(--c-white);
  transform: translateY(-2px);
}
.whatsapp-fab:focus-visible { outline-color: var(--c-brown); }

.whatsapp-fab__label {
  max-inline-size: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: max-inline-size var(--dur-slow) var(--ease),
              opacity var(--dur) var(--ease);
}
@media (min-width: 48em) {
  .whatsapp-fab:hover,
  .whatsapp-fab:focus-visible {
    gap: var(--sp-3);
    padding-inline: var(--sp-5);
  }
  .whatsapp-fab:hover .whatsapp-fab__label,
  .whatsapp-fab:focus-visible .whatsapp-fab__label {
    max-inline-size: 12rem;
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
   6b. Social-Media-Buttons
   Reine Textlinks zu den eigenen Profilen — keine eingebetteten Widgets,
   damit ohne Einwilligung nichts an Meta oder ByteDance geht.
   -------------------------------------------------------------------------- */

.social-row {
  display: flex;
  gap: var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.social-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border: 1.5px solid currentColor;
  border-radius: var(--r-pill);
  color: inherit;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.social-btn .icon { inline-size: 1.25rem; block-size: 1.25rem; }
.social-btn:hover {
  background-color: var(--c-amber);
  border-color: var(--c-amber);
  color: var(--c-brown);
  transform: translateY(-2px);
}

/* --------------------------------------------------------------------------
   6c. Fließtextseiten (Impressum, Datenschutz)
   -------------------------------------------------------------------------- */

/* Seitenkopf der Unterseiten — seit dem 28.09.2026 eine Fläche in Goldocker.
   Sie steht auf „Über uns", „Kontakt", „Impressum" und „Datenschutz"; die
   Startseite hat stattdessen den Hero, die Fehlerseite ihren eigenen Kopf.

   Die Trennlinie nach unten ist entfallen: Zwischen Goldocker und dem cremen
   Seitenhintergrund liegt ohnehin eine sichtbare Kante, eine zusätzliche
   Linie in Creme-300 wäre nur Unruhe.

   Kein Polsterwert über 6rem, aber auch nicht starr: 6rem oben und unten
   sind auf dem Telefon rund ein Drittel der Bildschirmhöhe, und darunter
   steht auf zwei der vier Seiten noch das Maskottchen. Der volle Wert wird
   ab etwa 1070 px erreicht, darunter läuft er auf 3,5rem herunter. */
.page-head {
  padding-block: clamp(3.5rem, 2rem + 6vw, 6rem);
  background-color: var(--c-gold);
  color: var(--text-on-gold);
}
/* Auf Goldocker trägt keiner der sonst üblichen Textwerte. Überschrift und
   Eyebrow gehen auf den tiefen Braunton, der Beschreibungsabsatz auf den
   normalen — er bleibt dadurch als zweite Ebene erkennbar, ohne unter AA zu
   fallen. Alles hier ist auf .page-head eingegrenzt: .eyebrow und
   .page-head__meta stehen auch im Sortimentskopf der Startseite, und der
   liegt auf Creme. */
.page-head h1,
.page-head .eyebrow { color: var(--text-on-gold); }
/* Der Strich vor der Eyebrow war Amber — auf Goldocker 1,07:1 und damit
   praktisch weg. Er läuft jetzt im selben Braunton wie die Schrift daneben. */
.page-head .eyebrow::before { background-color: var(--text-on-gold); }

.page-head__meta {
  margin-block-start: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.page-head .page-head__meta { color: var(--text-on-gold-muted); }

.prose {
  max-width: 68ch;
  padding-block: var(--sp-8);
}
.prose > * + * { margin-block-start: var(--sp-4); }

.prose h2 {
  margin-block-start: var(--sp-8);
  font-size: var(--fs-h3);
}
.prose h3 {
  margin-block-start: var(--sp-6);
  font-size: var(--fs-h4);
}
.prose h2 + *, .prose h3 + * { margin-block-start: var(--sp-3); }
.prose > :first-child { margin-block-start: 0; }

.prose ul, .prose ol {
  padding-inline-start: var(--sp-5);
  display: grid;
  gap: var(--sp-2);
}
.prose li { padding-inline-start: var(--sp-1); }
.prose li::marker { color: var(--c-amber-600); }

.prose address { font-style: normal; line-height: var(--lh-body); }

/* Beschriftete Angaben, z. B. im Impressum */
.data-list {
  display: grid;
  gap: var(--sp-3) var(--sp-5);
  margin: 0;
}
.data-list dt {
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}
.data-list dd { margin: 0; }
@media (min-width: 34em) {
  .data-list { grid-template-columns: minmax(9rem, auto) 1fr; align-items: baseline; }
  .data-list dt { text-align: start; }
}

/* Hervorgehobener Hinweiskasten im Fließtext */
.callout {
  padding: var(--sp-4) var(--sp-5);
  background-color: var(--c-cream-50);
  border-inline-start: 4px solid var(--c-amber);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
}
.callout > * + * { margin-block-start: var(--sp-2); }

/* Sprungmarken-Verzeichnis am Anfang langer Rechtstexte */
.toc {
  padding: var(--sp-5);
  background-color: var(--c-cream-50);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.toc ol {
  display: grid;
  gap: var(--sp-2);
  margin-block-start: var(--sp-3);
  padding-inline-start: var(--sp-5);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   6d. Fehlerseite
   -------------------------------------------------------------------------- */

.error-page { max-width: 44rem; }
.error-page__lead {
  margin-block-start: var(--sp-4);
  font-size: var(--fs-lg);
  color: var(--text-muted);
}

.error-page__links {
  display: grid;
  gap: var(--sp-3);
  margin-block-start: var(--sp-7);
  padding: 0;
  list-style: none;
}

.error-link {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--sp-4);
  align-items: center;
  padding: var(--sp-4) var(--sp-5);
  background-color: var(--c-white);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  text-decoration: none;
  color: var(--text-body);
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.error-link:hover {
  border-color: var(--c-amber);
  box-shadow: var(--shadow-md);
  transform: translateX(3px);
  color: var(--text-body);
}
.error-link > .icon { inline-size: 1.5rem; block-size: 1.5rem; color: var(--c-amber-600); }
.error-link span { display: grid; gap: 0.15rem; font-size: var(--fs-sm); color: var(--text-muted); }
.error-link strong { font-size: var(--fs-base); color: var(--text-strong); }
.error-link__arrow {
  inline-size: 1.125rem;
  block-size: 1.125rem;
  color: var(--text-muted);
  transition: transform var(--dur) var(--ease);
}
.error-link:hover .error-link__arrow { transform: translateX(0.25rem); }

/* --------------------------------------------------------------------------
   6e. Maskottchen (Toasti)

   Die Figur ist Beiwerk: Sie sagt nichts, was nicht schon in der Überschrift
   daneben steht. Deshalb überall leeres alt-Attribut — ein Screenreader
   würde sonst zweimal pro Seite dieselbe Bildbeschreibung vorlesen.

   Die Bilddateien entstehen aus _masters/Toasti/freigestellt/ über
   tools/prepare-mascot.py. Die Anzeigehöhen dort und die Höhen hier müssen
   zusammenpassen, sonst wird die Figur skaliert ausgegeben.
   -------------------------------------------------------------------------- */

/* Kopf-Maskottchen: steht neben Eyebrow, Überschrift und Einleitung.

   Unter 48em steht die Figur über dem Text. Daneben bliebe auf einem Telefon
   für die Überschrift keine Breite mehr übrig — bei 375 px wären es nach
   Figur und Abstand noch gut 220 px. */
.head-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-4);
}
@media (min-width: 48em) {
  .head-row {
    flex-direction: row;
    align-items: center;
    gap: var(--sp-6);
  }
}
/* Ohne min-inline-size: 0 bricht eine lange Überschrift den Flex-Kasten nicht
   um, sondern schiebt ihn über die Spaltenbreite hinaus. */
.head-row__text { min-inline-size: 0; }

/* Der Textteil soll weiter so breit werden dürfen wie ein Kopf ohne Figur.
   44rem (der Wert aus layout.css) plus Figur plus Abstand. */
.section__head.head-row { max-width: 58rem; }

.mascot--head {
  flex-shrink: 0;
  inline-size: auto;
  block-size: clamp(7rem, 4rem + 11vw, var(--mascot-h, 11.25rem));
}
/* Im Seitenkopf der Unterseiten und auf der Fehlerseite steht die Figur
   allein und darf etwas größer sein als im Sortimentskopf der Startseite. */
.page-head .mascot--head,
.error-page .mascot--head { --mascot-h: 12.5rem; }

/* Auf der Fehlerseite steht die Figur innerhalb von .error-page, und dessen
   44rem teilen sich Figur und Text. Etwas mehr Breite, damit die Überschrift
   daneben nicht auf halbe Zeilen fällt; die Linkkarten darunter wachsen dabei
   mit, das ist gewollt. Wo :has() fehlt, bleibt es bei 44rem — enger, aber
   heil. */
.error-page:has(.head-row) { max-width: 52rem; }

/* Footer-Maskottchen: steht mittig auf der Oberkante des Footers und ragt in
   den Bereich darüber hinein.

   Absolut positioniert, damit die Figur im Footer selbst keinen Platz belegt
   und der Abstand der Fußzeilenspalten unverändert bleibt. Der Platz nach
   oben kommt aus dem unteren Polster des letzten Abschnitts; deshalb tragen
   die Abschnitte über dem Footer .mascot-clearance.

   translate(-50%, -94%): die Hälfte der eigenen Breite zurück (mittig) und
   94 % der eigenen Höhe nach oben. Nicht 100 % — dann läge die Unterkante der
   Datei exakt auf der Footerkante und die Figur sähe aus, als schwebe sie
   davor. Mit den letzten 6 % stehen die Füße auf der Fläche darunter. Ändert
   sich das Motiv, ist der Wert nachzujustieren: Er hängt daran, wie viel
   Datei unter den Füßen liegt. */
.site-footer { position: relative; }
.site-footer__mascot {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 50%;
  transform: translate(-50%, -94%);
  inline-size: auto;
  block-size: var(--mascot-footer-h);
  /* Rein dekorativ: Die Figur soll keine Klicks auf das abfangen, was unter
     ihr im Abschnitt darüber liegt. */
  pointer-events: none;
}

/* Freiraum für die Figur im Abschnitt über dem Footer. Muss das untere
   Polster dieses Abschnitts ersetzen und nicht ergänzen — deshalb ein fester
   Grundwert plus Figurenhöhe statt eines Aufschlags auf --sp-section, das je
   nach Abschnittstyp (.section, .section--tight, .prose) anders ausfällt.
   Die Regel steht bewusst spät in der Datei: Sie soll die Polsterwerte aus
   layout.css und aus Abschnitt 6c schlagen, und alle wiegen gleich viel. */
.mascot-clearance { padding-block-end: calc(var(--sp-8) + var(--mascot-footer-h)); }

/* --------------------------------------------------------------------------
   6f. Foto in einer Textspalte

   Für Aufnahmen, die in einer .split-Spalte neben Fließtext stehen. Das Bild
   behält sein eigenes Seitenverhältnis — anders als bei den Produktkacheln
   gibt es hier kein festes Raster, in das es passen müsste. Rundung und
   Schatten wie bei den Kacheln, damit es im Seitenbild nicht fremd wirkt.
   -------------------------------------------------------------------------- */

.photo {
  display: block;
  inline-size: 100%;
  block-size: auto;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-md);
}

/* --------------------------------------------------------------------------
   7. Bild-Platzhalter (nur bis echte Fotos geliefert sind)
   TODO: entfernen, sobald alle Bilder vorliegen — siehe docs/OFFENE-PUNKTE.md
   -------------------------------------------------------------------------- */

.img-placeholder {
  display: grid;
  place-content: center;
  gap: var(--sp-2);
  justify-items: center;
  aspect-ratio: var(--ratio, 4 / 3);
  padding: var(--sp-5);
  text-align: center;
  background-color: var(--c-cream-100);
  background-image:
    repeating-linear-gradient(45deg,
      transparent 0 12px,
      rgba(90, 56, 47, 0.045) 12px 24px);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--r-lg);
  color: var(--c-brown-400);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.img-placeholder .icon { inline-size: 1.75rem; block-size: 1.75rem; opacity: 0.6; }
