/** Shopify CDN: Minification failed

Line 1412:3 Unexpected "="

**/
/* ── Globale Skalierung: Produktseiten ×1.18 ── */
/* ══════════════════════════════════════════════════════════════════════════
   ⛔ UMBRUCHPUNKT DER PRODUKTSEITEN: 1279 / 1280 px, NICHT 900 / 901
   ══════════════════════════════════════════════════════════════════════════
   Geaendert am 2026-08-08 (Auftraggeber: „auf iPad/Tablet-Groesse ist die
   Formatierung zerschossen").

   ⛔ DER PUNKT SASS AM FALSCHEN ENDE. Das Raster loeste sich erst UNTER
   901 px auf. Direkt darueber war die Kaufspalte gemessen **277 px** breit —
   schmaler als die 350 px, die ein Telefon bei 390 px bekommt. Die Seite war
   in diesem Band nicht „etwas eng", sie war enger als auf dem Handy.

   Gemessen am gerenderten Dokument, Innenbreite der Kaufspalte:

       901 px  →  277 px   H1 auf 5 Zeilen
      1024 px  →  333 px   H1 auf 4 Zeilen      ← iPad quer
      1180 px  →  403 px   H1 auf 3 Zeilen
      1366 px  →  487 px   H1 auf 2 Zeilen
      1440 px  →  520 px   ✅ der gezeichnete Wert

   Die Spalte erreicht ihre Sollbreite erst bei 1440. Der neue Punkt liegt
   bei 1280, weil die Spalte dort 448 px haelt — 86 % des Solls, H1 dreizeilig,
   und ein 1280er-Laptop behaelt damit das zweispaltige Layout.

   ⚠️ ES IST EINE ZAHL, NICHT ZWEI: Der Mobilblock traegt bereits alles, was
   der einspaltige Zustand braucht — auch die Deckelung des Galeriebilds auf
   421 px (Z. ~2418 im alten Stand). Ich hatte hier zuerst einen zweiten Fix
   fuer die Bildhoehe angekuendigt; das war ein Irrtum aus meiner Probe, die
   nur zwei der Regeln injiziert und die Deckelung nicht mitgenommen hatte.
   **Eine Probe, die einen Teil des Blocks nachstellt, misst nicht den Block.**

   ⛔ DIE DATEI WIRD NUR AUF PRODUKTSEITEN GELADEN (`layout/theme.liquid:857`,
   hinter `request.page_type == 'product'`). Deshalb ist die Umstellung ALLER
   900er-Queries dieser Datei vertretbar: Sie erreicht keine andere Seite.
   Gegengeprueft: Startseite, Collection, Warenkorb, Ueber uns, Versand,
   Kontakt, Suche und Buch zeigen bei 768 / 834 / 1024 px null Ueberlauf und
   sind unveraendert.
   ══════════════════════════════════════════════════════════════════════════ */

html { font-size: 118% !important; }
/* Mobil minimal groesser fuer bessere Lesbarkeit (auch aeltere Nutzer) */
@media (max-width: 749px) { html { font-size: 124% !important; } }

/* ══════════════════════════════════════════════════════════════════════════
   KEINE SERIF AUF PRODUKTSEITEN — 2026-08-07 (Auftraggeber)

   Auftrag: „das serif auf den PDPs wegnehmen und nur mit plain oder bold
   arbeiten." Gilt für die elf Einzelprodukte UND die Set-Seite (ausdrücklich
   nachgefragt); der Schnitt ist Outfit 600, aus einer Schriftprobe in den
   echten Graden gewählt (46 · 21 · 1,575rem · 2,625rem · 23 px).

   ⛔ ES SIND ZWEI ZEILEN UND KEINE 32, WEIL BEIDES ÜBER TOKEN LÄUFT.
   Jede Display-Regel im Theme sagt `var(--vbg-ff-display)` und seit heute
   `var(--vbg-fw-display)`. Hier werden nur die beiden Token umgehängt — die
   65 Regeln, die sie lesen, bleiben unangetastet. Wer statt dessen die Regeln
   einzeln überschreibt, muss die `!important` der Kaufspalte nachbauen und
   verpasst jede Regel, die später dazukommt.

   ⛔ DER GELTUNGSBEREICH IST `#MainContent`, NICHT `body` — und das ist der
   Punkt, an dem es schiefgehen würde: Kopfzeile, Fußzeile und der
   Warenkorb-Drawer stehen AUSSERHALB. Läge die Umstellung am `body`, trüge
   das Logo auf der Produktseite Outfit und auf jeder anderen Seite Cormorant.
   **Eine Marke, die je nach Seite anders heißt.**
   ✅ Die schwebende Kaufleiste wandert dagegen mit: Sie ist `position: fixed`,
   aber DOM-Kind der Kaufspalte — Vererbung folgt dem Baum, nicht dem Layout.
   (Dieselbe Eigenschaft, die am 2026-08-03 einen Defekt verursacht hat, ist
   hier genau das Gewünschte.)

   ⚠️ GESPIEGELT IM CRITICAL CSS (`layout/theme.liquid`). Ohne das zeigt der
   erste Paint die Serif und der Nachladeschritt die Groteske — ein Wechsel der
   Schriftart bei jedem Seitenaufruf, und die Zeilen brechen dabei anders um.

   📝 Zurückdrehen ist eine Zeile: den Block löschen. Die 32 umgehängten
   Regeln sind verhaltensneutral — `--vbg-fw-display` steht per Vorgabe auf
   `--vbg-fw-light`, also auf 300 wie vorher.
   ══════════════════════════════════════════════════════════════════════════ */
body.vbg-product-page #MainContent {
  --vbg-ff-display: var(--vbg-ff-body);
  --vbg-fw-display: var(--vbg-fw-semibold);
}

/* ============================================================
   VBG PRODUCT PAGE CSS
   Abhängigkeit: vbg-tokens.css + vbg-global.css
   Eingebunden in: layout/theme.liquid NACH vbg-global.css

   Inhalt:
   0.  Section Resets
   1.  Utility Classes
   2.  Preise & Varianten
   3.  Scroll Reveal
   4.  Vergleich (Vorher/Nachher + Kosten)
   5.  Listen
   6.  Zeitplan
   7.  Dosierung
   8.  Kräuter Animation (INGA v4)
   9.  Kombi-Produkte
   10. Kontakt
   11. Lightbox
   ============================================================ */

/* ============================================================
   0. SECTION RESETS
   Entkoppelt HTML-Tags innerhalb bestimmter Sections
   von den globalen Tag-Styles in vbg-global.css.
   Danach greifen nur noch die jeweiligen Klassen-Styles.
   ============================================================ */

/* ============================================================
   1. UTILITY CLASSES
   ============================================================ */

.vbg-text-center { text-align: center; }

.vbg-mb-16 { margin-bottom: 16px; }
.vbg-mb-40 { margin-bottom: 40px; }
.vbg-mb-48 { margin-bottom: 48px; }

.vbg-order-first { order: -1; }
.vbg-order-last  { order: 1; }

.vbg-stars {
  color: var(--vbg-gold);
  font-size: 1.155rem;  /* Skala B: war 1.1rem = 20.8 px */
  letter-spacing: 2px;
}

.vbg-img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--vbg-radius-lg);
}

/* ============================================================
   2. PREISE & VARIANTEN
   ============================================================ */

.vbg-price {
  font-family: var(--vbg-ff-display);
  font-weight: var(--vbg-fw-display);
  color: var(--vbg-forest);
}

/* ⛔ `.vbg-price-large` und `.vbg-price-strike` sind am 2026-08-03 mit der
   Preiszeile ueber dem Selektor gefallen. Auf Produktseiten hatten sie keinen
   Traeger mehr. Landing-Pages verwenden dieselben Namen, beziehen ihre Regeln
   aber gescopt aus `assets/vbg-lp.css:756-768` und laden diese Datei nicht. */


/* ══════════════════════════════════════════════════════════════
   MENGEN-SELEKTOR — senkrechte Liste
   Umgebaut am 2026-08-03 nach `Sari's Dental-Hygiene Spray PDP.html`
   Z. 1518-1538 (dekodiert). Vorher: Dreier-Kartenraster.

   ⛔ FESTE px, keine rem. `vbg-product-page.css:2` setzt
   `html{font-size:118%}` fuer alle Produktseiten — jeder rem-Wert laendet
   18 % ueber dem gezeichneten. Der Entwurf ist auf px gezeichnet.

   ⛔ Die Klasse `.vbg-variant-pill` heisst weiter so, obwohl es keine Pille
   mehr ist. `assets/vbg-product.js:5` ist der einzige Schreiber von
   `.vbg-variant-input`; ein neuer Name haette das Formular stumm auf die
   erste Variante festgenagelt.

   ⛔ HIER STANDEN 32 ZEILEN MOBILES GRID-LAYOUT, die zu 90 % wirkungslos
   waren: Die Media-Query stand VOR den Grundregeln derselben Datei, also
   gewann bei gleicher Spezifitaet die spaetere. Gemessen bei 390 px kam
   `display:flex` statt `grid` heraus, `padding 30/14/14` statt `28/16/14`,
   und `grid-template-areas` war damit inert. Von 32 Zeilen wirkten 4.
   Die neue Media-Query steht deshalb HINTER den Grundregeln.
   ══════════════════════════════════════════════════════════════ */
.vbg-variant-pills {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 24px;
}

.vbg-variant-pill {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  min-width: 0;
  padding: 18px 20px;
  border: 1px solid var(--vbg-sand);
  border-radius: 0;
  background: var(--vbg-white);
  font-family: var(--vbg-ff-body);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.vbg-variant-pill:hover {
  border-color: var(--vbg-ink);
}

/* ⛔ Die AUSWAHL laeuft ueber Rahmenfarbe und Flaeche: `2px solid moss` auf
   `cream` (Entwurf Z. 2269-2273). Das padding gleicht das eine Pixel aus,
   damit die Zeile beim Anklicken nicht springt — hier ist die Kompensation
   richtig, denn der Entwurf WILL die breitere Kante.
   ⛔ Die EMPFEHLUNG sitzt dagegen ausschliesslich am Badge. Zwei Rahmen mit
   zwei Bedeutungen an derselben Kante koennen nicht beide gewinnen, und die
   empfohlene Zeile ist oft genau die ausgewaehlte. */
.vbg-variant-pill.active {
  border-color: var(--vbg-moss);
  border-width: 2px;
  padding: 17px 19px;
  background: var(--vbg-cream);
}
.vbg-variant-pill.active:hover {
  border-color: var(--vbg-moss);
}
.vbg-variant-pill:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.vbg-variant-pill-radio {
  flex: none;
  width: 20px;
  height: 20px;
  border: 1px solid var(--vbg-sand);
  border-radius: 50%;
  background: var(--vbg-white);
  transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.vbg-variant-pill.active .vbg-variant-pill-radio {
  border-color: var(--vbg-moss);
  background: var(--vbg-moss);
  box-shadow: inset 0 0 0 3px var(--vbg-cream);
}

/* ── Mitte: Titel · Grundpreis und Reichweite · Eignung ── */
.vbg-variant-pill-main {
  flex: 1 1 auto;
  min-width: 0;
}
.vbg-variant-pill-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.vbg-variant-pill-qty {
  font-size: 18px;
  font-weight: var(--vbg-fw-normal, 400);
  color: var(--vbg-ink);
  line-height: 1.2;
}
/* ⛔ EIN Badge, und es hat eine Aussage: die Empfehlung. Vorher trug jede
   Zeile eines („Einzelpack", „Vorrat-Deal", „Mehrhunde" …) — wenn alle eines
   tragen, unterscheidet keines. Gold ist hier richtig und das einzige Gold
   in der Kaufspalte (Entwurf Z. 1525). */
.vbg-variant-pill-badge {
  flex: none;
  padding: 2px 8px;
  /* Der Rahmen bleibt `--vbg-gold`: Linie, nicht Text. */
  border: 1px solid var(--vbg-gold);
  border-radius: 0;
  background: none;
  /* ⛔ `--vbg-gold-dark` gemessen 2,84:1 auf Weiß und 2,50:1 auf Cream — das
     Badge steht in BEIDEN Zuständen, weil die ausgewählte Zeile cream gefüllt
     ist. `--vbg-gold-deep`: 4,64 auf Weiß, 4,09 auf Cream.
     ⚠️ Damit ist der ausgewählte Zustand weiterhin unter AA. Das Badge trägt
     die Empfehlung, also Information — es bleibt Gold (Entscheidung
     „Gold markiert die Empfehlung"), aber der Token müsste auf `#7d6608`
     nachdunkeln, damit beide Zustände tragen. Vorschlag liegt vor. */
  color: var(--vbg-gold-deep);
  font-size: 13px;
  font-weight: var(--vbg-fw-normal, 400);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.vbg-variant-pill-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
  font-size: 15px;
  color: var(--vbg-warm-gray);
  line-height: 1.3;
}
.vbg-variant-pill-sub {
  display: block;
  margin-top: 2px;
  font-size: 15px;
  color: var(--vbg-ink);
  line-height: 1.3;
}

/* ── Rechts: Endpreis · Ersparnis · Versand ── */
.vbg-variant-pill-side {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
}
.vbg-variant-pill-price {
  font-family: var(--vbg-ff-display);
  font-size: 23px;
  font-weight: var(--vbg-fw-display, 300);
  color: var(--vbg-ink);
  line-height: 1.1;
}
/* Ersparnis in Moos. Rot ist im Regelwerk die FEHLERfarbe; eine Ersparnis
   ist kein Fehler. Im Critical-Block stand sie bis heute auf `#c0392b` —
   die Farbe sprang beim Async-Load von Rot auf Gruen. */
.vbg-variant-pill-save {
  margin-top: 2px;
  font-size: 15px;
  color: var(--vbg-moss);
}
.vbg-variant-pill-ship {
  margin-top: 2px;
  font-size: 14px;
  color: var(--vbg-warm-gray);
}
.vbg-variant-pill-ship.is-free {
  color: var(--vbg-moss);
}

/* ⛔ HIER STAND `:nth-child(n+4){display:none}` — GEFALLEN AM 2026-08-10.
   Seit der Begrenzung in `vbg-zpp-kauf.liquid` (`for … limit: 3`) rendert
   die Seite nur noch drei Pillen; die Regel haette nichts mehr zu verbergen.

   ⛔ SIE IST NICHT NUR UEBERFLUESSIG, SIE WAERE GEFAEHRLICH. Wer das `limit`
   im Liquid spaeter anhebt, bekaeme die Plaetze ab vier weiterhin still
   ausgeblendet — und suchte den Fehler in der Schleife, nicht in einer
   CSS-Datei zwei Ordner weiter. Die Zahl steht jetzt an genau einer Stelle.
   📝 Kein Gegenstueck im Critical CSS zu entfernen: dort standen die
   Pillen-Regeln (Z. 832-834), diese Zeile nie. Gemessen, nicht angenommen. */

/* ⛔ AUSGEKLAPPT LEGEN SICH 6x/10x/20x AUF DIE PLAETZE VON 1x/2x/3x —
   2026-08-07 (Auftraggeber: „dass die Varianten 1x 2x und 3x durch die
   Varianten 6x 10x und 20x ersetzt werden, also praktisch dass die sich
   genau da drueber legen").

   Vorher wuchs die Liste beim Ausklappen von drei auf SECHS Zeilen und
   schob alles darunter — Rechner, Kaufknopf, Versandzeile — um rund
   300 px nach unten. Jetzt bleibt die Hoehe gleich, es tauscht nur der
   Inhalt. */
.vbg-variant-pills.is-expanded .vbg-variant-pill:nth-child(-n+3) {
  display: none;
}

/* ⛔⛔ DIE GEWAEHLTE OPTION BLEIBT IMMER SICHTBAR — und das ist keine
   Feinheit, sondern der Grund, warum der Tausch ueberhaupt gefahrlos ist.

   Ohne diese zwei Zeilen koennte der Kunde `2 x 150 ml` waehlen, ausklappen,
   und die gewaehlte Zeile waere WEG — waehrend das Formular sie weiter
   traegt und der Kaufknopf ihren Preis zeigt. Ein Preis, der zu einer
   nirgends sichtbaren Menge gehoert: exakt der Defekt, der am 2026-08-03
   an der schwebenden Kaufleiste gefunden wurde (`mirrorEl` zeigte
   „150 ml · 39,95", der Knopf legte etwas anderes in den Warenkorb).

   ⚠️ Die Spezifitaet MUSS 0,4,0 erreichen, sonst verliert die Regel gegen
   die zwei `nth-child`-Regeln darueber (ebenfalls 0,4,0, aber frueher).
   `.vbg-variant-pills .vbg-variant-pill.active` waere nur 0,3,0 und
   wirkungslos — sichtbar wuerde davon nichts, und der Fehler traete erst
   beim Kunden auf. */
.vbg-variant-pills.is-expanded .vbg-variant-pill.active,
.vbg-variant-pills:not(.is-expanded) .vbg-variant-pill.active {
  display: flex;
}

/* Das „+" dreht sich beim Ausklappen zum „x" — dieselbe Mechanik wie beim
   FAQ-Akkordeon (`assets/vbg-global.css`, `.vbg-faq-item.open .vbg-faq-icon`).
   ⛔ Kein zweites Zeichen im Markup: Ein ausgetauschtes Textzeichen springt,
   eine Drehung ist eine Bewegung — und sie sagt zugleich, dass derselbe Knopf
   wieder zurueckfuehrt. */
.vbg-variant-toggle__icon {
  display: inline-block;
  transition: transform 0.2s var(--vbg-ease-out);
}
.vbg-variant-toggle[aria-expanded='true'] .vbg-variant-toggle__icon {
  transform: rotate(45deg);
}

/* ── Umschalter: gerahmter Kasten mit „+" (Entwurf Z. 1545-1546) ── */
.vbg-variant-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  margin-top: 12px;
  padding: 14px 20px;
  border: 1px solid var(--vbg-parchment);
  border-radius: 0;
  background: none;
  font-family: var(--vbg-ff-body);
  font-size: 16px;
  font-weight: var(--vbg-fw-normal, 400);
  color: var(--vbg-ink);
  cursor: pointer;
  transition: border-color 0.2s;
}
.vbg-variant-toggle:hover,
.vbg-variant-toggle:focus-visible {
  border-color: var(--vbg-ink);
  outline: none;
}
/* ══════════════════════════════════════════════════════════════
   LESBARKEIT DES FLIESSTEXTS — zwei Massnahmen, eine davon gegen den Entwurf

   (1) Langkopie einheitlich auf 14 px / 1.7. DAS IST DER ENTWURFSWERT: er
       staffelt in drei Stufen — 16/1.5 fuer die Produktbeschreibung im Kopf
       (genau einmal), 14/1.7 fuer jede echte Langkopie (Spray PDP Z. 1569,
       1754, 1804), 12 px fuer Fussnoten. Die Zeilenhoehe ist der Hebel, den
       er selbst benutzt.

   (2) ⛔ ZEILENLAENGE BEGRENZT — ABWEICHUNG. Der Entwurf hat KEINE
       Begrenzung: null `max-width`, null `ch`, null `measure` in der ganzen
       Kaufspalte (ausgezaehlt ueber Z. 1462-1819; am 2026-08-04 gegen beide
       Entwurfsdateien nachgezaehlt, Ergebnis unveraendert). Die Zeilenlaenge
       ist dort schlicht die Spaltenbreite — 520 px, genau unsere.
       ⚠️ Er loest das Problem nicht, er HAT es nur nicht: seine Texte sind
       Platzhalter, unsere ein Vielfaches laenger.
       ⛔ Das laesst sich NICHT mit „steht so im Entwurf" begruenden. Es ist
       eine Entscheidung, und sie steht hier, damit sie beim naechsten
       Abgleich nicht als Abweichung zurueckgedreht wird.

       ⛔ KORREKTUR 2026-08-04: HIER STAND `62ch`, UND DAS HAT NIE GEGRIFFEN.
       Hier stand dazu „62ch bringt das in den lesbaren Bereich" — es hat den
       Bereich nie erreicht. `ch` ist der Vorschub der ZIFFER NULL, nicht die
       Breite eines Zeichens. Aus der Schriftdatei gemessen (fontTools,
       `hmtx`): Outfit `0` = **0,659 em**, also 9,23 px bei 14 px Schrift.
           62ch = 572 px  >  520 px Spaltenbreite
       Die Regel war damit auf JEDER Seite wirkungslos, und die Zeilen liefen
       weiter ueber die vollen 520 px. Das mittlere Zeichen desselben Textes
       misst 0,4398 em = 6,16 px, eine 520-px-Zeile fasst also rund
       **84 Zeichen** — die Zahl, die der Auftraggeber am Bildschirm auf „rund
       80" geschaetzt hat.
       ⚠️ Die Lehre ist aelter als der Fall: eine Einheit, deren Wert man
       nicht gemessen hat, ist eine Schaetzung mit Nachkommastelle. Und eine
       Begrenzung, die groesser ist als der Behaelter, sieht im Quelltext
       genauso aus wie eine, die greift.
       Jetzt in px, weil in der Kaufspalte ohnehin feste px gelten und die
       Regel die Schriftgroesse selbst setzt: 62 Zeichen × 0,4398 em × 14 px
       = 381 px → **380 px**. Die 62 bleibt, sie war als ZEICHEN gemeint.

   ⛔ WARM-GRAY BLEIBT. Der Entwurf setzt JEDEN laufenden Sachtext in
   warm-gray (12 Saetze); in Ink steht dort kein einziger Satz in der
   Body-Schrift — wo er lange Passagen in Ink stellt, wechselt er zugleich auf
   Display kursiv, und das sind Zitate. Ein Wechsel auf Ink kehrte die
   Farbhierarchie der Seite um. Gemessen traegt warm-gray auf Weiss 5,79:1
   und liegt damit ueber der AA-Schwelle.
   ══════════════════════════════════════════════════════════════ */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) p,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) li {
  font-size: 20px;
  line-height: 1.7;
  /* ⛔ HIER STAND `max-width: 464px` — 62 Zeichen x 0,4398 em x 17 px.
     GEFALLEN am 2026-08-08 auf Entscheidung des Auftraggebers, nach fuenf
     Bildern derselben Sache: Kostenvergleich, Herstellung, Zeitplan,
     Kombi-Sets, Kundenstimmen — ueberall stand der Text in einer schmalen
     Saeule, waehrend die Spalte daneben leer blieb.

     ⛔ DAS KEHRT EINE FESTLEGUNG UM, es korrigiert keinen Fehler. Die
     Rechnung war richtig und die Absicht auch. Was sich geaendert hat, ist
     ihre VORAUSSETZUNG: Sie wurde fuer die 520 px breite Spalte des
     Entwurfs (Artboard 1440) gerechnet. Gemessen waechst die Spalte
     darueber hinaus mit — 520 px bei 1440, **736 bei 1920, 1024 bei 2560**.
     Eine feste Zeichenzahl in einem wachsenden Behaelter ergibt nicht eine
     gute Zeile, sondern eine schmale Saeule mit Leerraum daneben.

     ⚠️ WAS ES KOSTET, damit es niemand suchen muss: Die Zeilen werden
     laenger, und zwar mit der Breite. Bei 1440 rund 70 statt 62 Zeichen
     (die Grenze griff auch dort — 464 in einer 520er Spalte). Bei 2560
     rund 137. Ueber 90 Zeichen gilt als schwer lesbar; der Auftraggeber
     hat die Zahlen vor der Entscheidung gesehen.

     🚩 Der eigentliche Hebel liegt woanders und ist NICHT gebaut: Der
     Entwurf setzt „Content max. 1180 px". Bekaeme die Seite eine
     Hoechstbreite, bliebe die Spalte ueberall ~520 px und die Frage
     stellte sich nicht. Vorgelegt und verworfen zugunsten dieses Wegs. */
}

/* ══════════════════════════════════════════════════════════════════
   ⛔ DIE REGEL IST GETEILT (2026-08-05) — und der Grund ist eine
   Entscheidung, nicht die Technik.

   Bis hierher galt EINE Regel fuer beides: die Abschnitte der rechten
   Spalte UND die Kaufspalte. Gemessen regierte sie 47 von 54 Absaetzen
   der Abschnitte und 10 von 16 in der Kaufspalte. Die shopweite
   Vergroesserung will die Abschnitte anheben; die Kaufspalte ist davon
   ausdruecklich ausgenommen (Entwurf auf feste Werte gezeichnet, Spalte
   520 px breit). Beides in einer Regel ist nicht moeglich.

   Oben stehen deshalb die Abschnitte: 14 -> 17 px, und die Breite MUSS
   mit. Sie ist aus der Schrift gerechnet, nicht gesetzt:
       62 Zeichen x 0,4398 em x 17 px = 463,6 -> 464 px
   Ohne die Breite fielen 62 Zeichen auf 51 — genau der Fehler, den die
   Zahl verhindern soll.

   Hier unten behaelt die Kaufspalte ihre gemessenen Werte. Ein Selektor
   mit einer Klasse mehr genuegt (0,4,1 gegen 0,3,1); es braucht kein
   `:not()` und kein `!important`.
   ⚠️ Wer diese zwei Bloecke je wieder zusammenlegt, muss vorher
   entscheiden, welche der beiden Zahlen gewinnt — sie widersprechen sich
   mit Absicht.
   ══════════════════════════════════════════════════════════════════ */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero--kauf p,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero--kauf li {
  /* Skala B 2026-08-05, zweiter Durchgang: die Kaufspalten-Ausnahme ist
     aufgehoben (Auftraggeber). 14 -> 16 px.
     ⛔ Die Breite MUSS mit: 380 px hielten 58 Zeichen bei 14 px, bei 16 px
     sind es 50. 437 px stellen die 58 wieder her. Gemessen nach dem Bau. */
  font-size: 16px;
  max-width: 437px;
}

/* ⛔ Ausnahme A — LISTEN, DIE ZEILEN SIND, KEINE KOPIE.
   Solange die Begrenzung wirkungslos war (572 px in einer 520-px-Spalte),
   war das folgenlos. Mit 380 px wird es sichtbar, und zwar doppelt: die
   Haarlinie unter der Zeile wuerde mitschrumpfen, und bei den beiden
   `space-between`-Listen liefe die rechte Spalte nach innen.
   Ausgezaehlt ueber `sections/vbg-zpp-*.liquid` — es sind genau diese drei. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero__usp li,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-kaufakk__dauer li,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-kv7-lines li {
  max-width: none;
}

/* ⛔ Ausnahme C — DIE ZUTATENDEKLARATION, 2026-08-08 (Auftraggeber:
   „Desktop: Nutze den Raum vollstaendig bis zum rechten Rand aus;
   Mobile: ist ok").

   Sie ist KEINE Langkopie, sondern eine Aufzaehlung ohne Satzbau: elf mit
   `·` getrennte Glieder, die der Leser ueberfliegt und nicht Zeile fuer
   Zeile liest. Die 58-Zeichen-Regel ist fuer Fliesstext gerechnet und
   erzeugt hier das Gegenteil ihres Zwecks — sie streckt die Liste auf
   sieben Zeilen, waehrend rechts daneben die halbe Spalte leer bleibt.

   ⛔ `min-width: 1280px` IST NICHT VORSICHT, SONDERN DER AUFTRAG.
   „Mobile ist ok" heisst: unterhalb des Umbruchpunkts aendert sich nichts.
   Ohne die Query bekaeme auch der gestapelte Bereich den Wegfall — die
   Spalte ist dort BREITER als 437 px, der Deckel bindet also und sein
   Wegfall waere sichtbar. Nur unter rund 437 px waere es folgenlos, und das
   ist nicht „mobil", das ist Telefon.
   📝 STAND HIER `901`, bis der Umbruchpunkt am 2026-08-08 auf 1280 ging.
   Die Zahl ist mitgewandert, weil sie DENSELBEN Punkt meint — nicht, weil
   sich an dieser Entscheidung etwas geaendert haette.

   📝 Nur die Deklaration, nicht der ganze Akkordeon-Inhalt: Die
   Anwendungstabelle darunter ist eine Tabelle und traegt den Deckel gar
   nicht; `.vbg-kaufakk__meta` („Ergaenzungsfuttermittel fuer Hunde") ist
   eine kurze Zeile, die ihn nie erreicht.

   ⛔ `.vbg-hero--kauf p.vbg-kaufakk__deklaration` — UND ZWAR VOLLSTAENDIG,
   nicht gekuerzt. Die erste Fassung hiess nur
   `… :has(…) .vbg-kaufakk__deklaration` und war WIRKUNGSLOS. Gemessen:
   437 px, unveraendert. Der Grund ist knapp und leicht zu uebersehen —

       Deckel   … .vbg-hero--kauf p                  (1,3,2)
       Ausnahme … .vbg-kaufakk__deklaration          (1,3,1)

   Gleiche id, gleiche Klassenzahl; der Deckel hat EIN ELEMENT MEHR im
   Selektor (`body` + `p` gegen nur `body`) und gewinnt damit. Ein
   Klassenselektor schlaegt einen Elementselektor eben NICHT, wenn alles
   davor gleich ist. Mit `.vbg-hero--kauf` und `p.` davor sind es (1,4,2).
   ⚠️ Wer diesen Selektor je kuerzt, macht die Ausnahme lautlos wirkungslos —
   es faellt nichts aus, der Text wird nur wieder schmal. */
@media (min-width: 1280px) {
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie)
    .vbg-hero--kauf p.vbg-kaufakk__deklaration {
    max-width: none;
  }
}

/* ⛔ AUSNAHME B IST AM 2026-08-07 ERSATZLOS GEFALLEN — mit ihrer Voraussetzung.

   Hier stand `margin-inline: auto` fuer `.vbg-ts2-video-lead` und
   `-caption`, mit dieser Begruendung:

   > „Eine Begrenzung ohne `margin-inline: auto` schiebt zentrierten Text
   > nach links: die Zeile bleibt in ihrer Box zentriert, die Box sitzt aber
   > am linken Rand."

   Die Begruendung war richtig — **solange die beiden Absaetze zentriert
   waren.** Am 2026-08-07 ist die Zentrierung gefallen (Auftraggeber: „Echte
   Stimmen vom Markt linksbuendig wie alles andere"), und damit dreht die
   Regel ihre Wirkung um: Sie zentriert jetzt die 437-px-BOX in der 520-px-
   Spalte, und der linksbuendige Text begaenne 41 px vom linken Rand — also
   sichtbar eingerueckt gegen alles darueber. **Die Regel wuerde exakt das
   verhindern, wofuer sie einmal gebaut wurde.**

   ⚠️ Und das ist der zweite Fall dieser Klasse an EINEM Tag; der erste war
   `border-top: none` an der mobilen Auswahlleiste (`vbg-homepage.css`).
   Beide Male: eine Hilfsregel, die zusammen mit ihrer Voraussetzung entstand,
   die Voraussetzung ueberlebte, und danach das Gegenteil tat. Keine Pruefung
   schlaegt dabei an — der Wert steht ja da und ist fuer sich richtig.

   > **Wer eine Ausrichtung aendert, sucht die Regeln, die AN ihr haengen.**
   > Sie nennen sie im Kommentar, nicht im Selektor. */

/* ⛔ Ausnahme C — DIE ZWEI KOMPONENTENLISTEN, DIE KEINE KOPIE SIND.
   Beide Regeln stehen HIER und nicht in ihrer Section, und das ist kein
   Versehen: die Langkopie-Regel oben traegt eine id im Selektor (1,2,1) und
   schlaegt damit JEDEN Klassenselektor der Section, egal wie spezifisch er
   dort aussieht. Wer den Grad in der Section sucht, findet ihn und misst
   trotzdem etwas anderes.

   1. Kopfbereich, USP-Zeilen: Begriff 14 px (eigene Regel in
      vbg-zpp-kauf.liquid), Erklaerung 13 px — die Werte des massgeblichen
      Entwurfs (Spray PDP Z. 1471-1483). Ueber die Langkopie-Regel standen
      beide auf 14 px / 1.7 und lasen als EIN Absatz.
   2. Komponentenzeile der Kombi-Karten: dritte Stufe der Kartenhierarchie,
      11 px. Ueber die Langkopie-Regel stand sie auf 14 px / 1.7 — also
      GROESSER als die 12-px-Beschreibung und optisch groesser als der Titel
      (14 px Cormorant = 11,8 px Outfit). Begruendung und Messung:
      sections/vbg-zpp-kombi.liquid, Block „HIERARCHIE DER KARTE". */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero__usp li {
  /* Skala B, zweiter Durchgang: 13 -> 15 px. Die zugehoerige Breite steht
     an den SPANS in vbg-zpp-kauf.liquid (360 -> 414). */
  font-size: 15px;
  line-height: var(--vbg-lh-normal);
}
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-col-fset-contents li {
  font-size: 13px;
  line-height: var(--vbg-lh-normal);
  max-width: none;
}
/* Ausgenommen: alles, was keine Langkopie ist. Ueberschriften, Fussnoten,
   Zitate und die Zeilen des Selektors tragen eigene Groessen — sie hier
   mitzuziehen hiesse, sechs bewusste Werte durch einen zu ersetzen. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) [class$="-headline"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) [class*="disclaimer"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) [class*="vorbehalt"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) [class*="hinweis"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-variant-pill p,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-testi-text,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-ts2-mehr-zitat {
  /* ⛔ `revert` WAR HIER FALSCH und ist am 2026-08-03 korrigiert.
     `revert` auf Autorenebene faellt auf das BROWSER-Stylesheet zurueck, nicht
     auf die vorige Autorenregel — es hat also nicht nur meine 14 px
     zurueckgenommen, sondern auch `.vbg-bedarf__vorbehalt { font-size:
     var(--vbg-text-xs) }` mit. Gemessen kamen 16 px heraus, die
     UA-Vorgabe, statt der gemeinten 12.
     ⚠️ Und der Fehler war nicht am Selektor zu sehen: Die Ausnahmeliste sah
     richtig aus, sie hat nur mehr ausgenommen als gemeint. Aufgefallen ist es
     erst beim Nachmessen am gerenderten Dokument — die Regel schien zu
     greifen, das Ergebnis war ein anderes.
     `unset` waere derselbe Fehler; `initial` auch. Die Ausnahme darf die
     Eigenschaft schlicht NICHT anfassen. */
  max-width: none;
}

/* Der Hinweis, wenn die Empfehlung den Zielzeitraum nicht traegt.
   Bewusst ruhig: keine Warnfarbe, kein Rahmen, keine Flaeche. Er ist eine
   Auskunft ueber die eigene Eingabe, keine Beanstandung — und Rot waere hier
   ohnehin die Fehlerfarbe des Regelwerks. */
.vbg-variant-hinweis {
  margin: 10px 0 0;
  font-family: var(--vbg-ff-body);
  font-size: 15px;
  line-height: 1.4;
  color: var(--vbg-warm-gray);
}
.vbg-variant-hinweis[hidden] { display: none; }

.vbg-variant-toggle__icon {
  flex: none;
  font-size: 21px;
  line-height: 1;
  color: var(--vbg-warm-gray);
}

/* ── Mobil. STEHT HINTER den Grundregeln, sonst wirkt sie nicht. ── */
@media (max-width: 600px) {
  .vbg-variant-pill        { gap: 12px; padding: 14px; }
  .vbg-variant-pill.active { padding: 13px; }
  .vbg-variant-pill-qty    { font-size: 15px; }
  .vbg-variant-pill-meta,
  .vbg-variant-pill-sub    { font-size: 12px; }
  .vbg-variant-pill-price  { font-size: 20px; }
  .vbg-variant-pill-badge  { font-size: 10px; padding: 1px 6px; }
}

.vbg-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ============================================================
   3. SCROLL REVEAL
   ============================================================ */

.vbg-reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.vbg-reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

.vbg-reveal-left {
  opacity: 0;
  transform: translateX(-32px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.vbg-reveal-left.visible {
  opacity: 1;
  transform: translateX(0);
}

.vbg-reveal-right {
  opacity: 0;
  transform: translateX(32px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.vbg-reveal-right.visible {
  opacity: 1;
  transform: translateX(0);
}

/* Staggered delays */
[data-delay="1"] { transition-delay: 0.05s; }
[data-delay="2"] { transition-delay: 0.10s; }
[data-delay="3"] { transition-delay: 0.15s; }
[data-delay="4"] { transition-delay: 0.20s; }
[data-delay="5"] { transition-delay: 0.25s; }
[data-delay="6"] { transition-delay: 0.30s; }

/* ============================================================
   4. VERGLEICH (Vorher/Nachher + Kosten)
   ============================================================ */

.vbg-comparison {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  align-items: start;
}

.vbg-comp-col {
  border-radius: var(--vbg-radius-xl);
  padding: 32px;
}

.vbg-comp-col-bad {
  background: #fff5f5;
  border: 1px solid #f5c6c6;
}

.vbg-comp-col-good {
  background: #f2f8f4;
  border: 1px solid #b8dfc4;
}

.vbg-comp-title {
  font-family: var(--vbg-ff-display);
  font-size: 1.47rem;  /* Skala B: war 1.4rem = 26.4 px */
  font-weight: var(--vbg-fw-display);
  color: var(--vbg-forest);
  margin-bottom: 16px;
}

@media (max-width: 1279px) {
  .vbg-comparison {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   5. LISTEN
   ============================================================ */

.vbg-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.vbg-list li {
  font-family: var(--vbg-ff-body);
  font-size: 1.0925rem;  /* Skala B: war 0.95rem = 17.9 px */
  font-weight: var(--vbg-fw-light);
  line-height: 1.5;
  padding-left: 28px;
  position: relative;
  color: var(--vbg-warm-gray);
}

.vbg-list li::before {
  position: absolute;
  left: 0;
  top: 0;
  font-size: 1.15rem;  /* Skala B: war 1rem = 18.9 px */
}

/* Checkmarks (grün) – .vbg-list-green ist ein Alias */
.vbg-list-check li::before,
.vbg-list-green li::before {
  content: '✓';
  color: var(--vbg-sage);
  font-weight: 700;
}

/* Rote X */
.vbg-list-red li::before {
  content: '✗';
  color: var(--vbg-red);
  font-weight: 700;
}

/* ============================================================
   6. ZEITPLAN
   ============================================================ */

/* Zeitplan-Styles leben jetzt vollständig in sections/vbg-zpp-zeitplan.liquid */

/* ============================================================
   7. DOSIERUNG
   ============================================================ */

.vbg-dosage-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-top: 32px;
}

.vbg-dosage-card {
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--vbg-radius-xl);
  padding: 24px 20px;
  cursor: pointer;
  transition: var(--vbg-transition-card);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.vbg-dosage-card:hover {
  background: rgba(255, 255, 255, 0.12);
  transform: translateY(-4px);
}

.vbg-dosage-card-highlight {
  border-color: var(--vbg-gold);
  background: rgba(201, 151, 58, 0.1);
}

.vbg-dosage-card-badge {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--vbg-gold);
  color: var(--vbg-forest);
  font-family: var(--vbg-ff-body);
  font-size: 0.7475rem;  /* Skala B: war 0.65rem = 12.3 px */
  font-weight: var(--vbg-fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 12px;
  border-radius: var(--vbg-radius-full);
  white-space: nowrap;
}

.vbg-dosage-weight {
  font-family: var(--vbg-ff-display);
  font-size: 1.26rem;  /* Skala B: war 1.2rem = 22.7 px */
  font-weight: var(--vbg-fw-display);
  color: var(--vbg-cream);
  line-height: 1.2;
}

.vbg-dosage-detail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--vbg-ff-body);
  font-size: 1.012rem;  /* Skala B: war 0.88rem = 16.6 px */
  color: var(--vbg-cream);
  font-weight: var(--vbg-fw-light);
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.vbg-dosage-detail span {
  font-size: 0.828rem;  /* Skala B: war 0.72rem = 13.6 px */
  font-weight: var(--vbg-fw-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--vbg-mint);
}

@media (max-width: 1279px) {
  .vbg-dosage-cards { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   8. KRÄUTER ANIMATION (INGA v4)
   ============================================================ */

/* Section-Wrapper */

/* Hintergrund-Gradient */

/* Dekor-Linien */

/* SVG Verbindungslinien */

/* Bühne */

/* Dimmer */

/* Nicht-fokussierte Karten abdunkeln */

/* --- Header --- */

/* --- Flasche --- */

@keyframes vbgBounce {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(-6px); }
}

/* --- Kräuter-Karten --- */

/* --- Footer CTA --- */

/* --- Inhaltsstoffe-Overlay --- */

/* --- Hybrid-List (Inhaltsstoffe) --- */

/* --- Mobile Bottom Sheet --- */

/* --- Responsive INGA --- */

/* ── Desktop: Carousel-Wrapper unsichtbar, Dots ausblenden ── */

/* ── Mobile: Linearer Flow + Karten-Carousel ── */
@media (max-width: 768px) {

  

  

  /* Hint über Flasche zentriert */

  /* ── 3D Cover-Flow Carousel ── */

  /* Glow-Verbindung von Flasche → aktive Karte */

  /* Goldener Glow-Pool unter der Flasche */

  @keyframes vbgGlowLine {
    0%, 100% { opacity: 0.3; height: 54px; }
    50%      { opacity: 0.9; height: 62px; }
  }

  @keyframes vbgGlowPulse {
    0%, 100% { transform: translateX(-50%) scale(1);   opacity: 0.5; }
    50%      { transform: translateX(-50%) scale(1.4); opacity: 0.9; }
  }

  

  

  /* Alle Infos immer sichtbar */

  

  /* Expand-Button nicht nötig */

  /* Inactive Karten: leichter Blur (Depth-of-Field) */

  /* Aktive Karte: Glow + Breathing */

  @keyframes vbgCardBreathe {
    0%, 100% { transform: scale(1);    filter: brightness(1); }
    50%      { transform: scale(1.01); filter: brightness(1.08); }
  }

  /* Aktive Karte: Emoji pulsiert */

  @keyframes vbgEmojiPop {
    0%   { transform: scale(1); }
    50%  { transform: scale(1.3); }
    100% { transform: scale(1.1); }
  }

  /* Dots — genug Abstand damit Karten nicht reinragen */

  

  /* Footer CTA — genug Abstand zum Carousel darüber */

  /* Dimmer: fixed für Sheet */

  /* Dekorative Linien verstecken */

  

  /* Overlay nur auf Desktop */
  
}

@media (min-width: 769px) {
  /* Sheet nur auf Mobile */
  
}

/* (alte 600px-Overrides für absolute Karten-Positionierung entfernt – Carousel löst das) */

/* ============================================================
   9. KOMBI-PRODUKTE
   ============================================================ */

.vbg-kombi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 28px;
}

.vbg-kombi-card {
  background: var(--vbg-white);
  border-radius: var(--vbg-radius-2xl);
  border: 1px solid var(--vbg-sand);
  overflow: hidden;
  transition: var(--vbg-transition-card);
  position: relative;
  box-shadow: var(--vbg-shadow-sm);
}

.vbg-kombi-card:hover {
  transform: translateY(-8px);
  box-shadow: var(--vbg-shadow-xl);
}

.vbg-kombi-card-highlight {
  border-color: var(--vbg-gold);
  box-shadow: 0 8px 24px rgba(201,151,58,0.15);
}

.vbg-kombi-bestseller {
  position: absolute;
  top: 20px;
  left: -30px;
  width: 128px;
  text-align: center;
  transform: rotate(-45deg);
  transform-origin: center center;
  background: var(--vbg-gold);
  color: var(--vbg-forest);
  font-family: var(--vbg-ff-body);
  font-size: 0.7475rem;  /* Skala B: war 0.65rem = 12.3 px */
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 0;
  box-shadow: 0 2px 8px rgba(201,151,58,0.35);
  z-index: 10;
}

/* ⛔ DER DREIFARBEN-VERLAUF IST GEFALLEN — 2026-08-07 (Auftraggeber).
   Hier stand `linear-gradient(150deg, #ddeee3 0%, #c8e2d0 60%, #b8d9c4 100%)`:
   drei Toene quer ueber die Flaeche, keiner davon aus dem Token-Satz.
   Jetzt eine Flaeche, und nur ihr RAND blendet nach Weiss
   (`--vbg-flaeche-weich` am `::after` darunter).
   📝 `--vbg-parchment` ist derselbe Ton wie die Galeriespalte und die
   Set-Komposition — die drei Produktflaechen des Shops tragen jetzt eine
   Farbe statt drei verschiedener Verlaeufe. */
.vbg-kombi-img-wrap {
  background: var(--vbg-parchment);
  height: 240px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  position: relative;
}

/* ⛔ WEICHE KANTE AUF ALLEN VIER SEITEN — vorher nur unten und nur zu 35 %.
   Der alte Streifen war ein Rest aus der Verlaufszeit: Er sollte den
   dunkelsten Punkt des Verlaufs abmildern und stand deshalb genau dort.
   Ohne den Verlauf hat er keine Stelle mehr, an der er richtig waere. */
.vbg-kombi-img-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--vbg-flaeche-weich);
  pointer-events: none;
}

.vbg-kombi-img {
  max-height: 200px;
  max-width: 82%;
  object-fit: contain;
  transition: transform 0.4s ease;
  position: relative;
  z-index: 1;
}

.vbg-kombi-card:hover .vbg-kombi-img {
  transform: scale(1.06);
}

.vbg-kombi-body {
  padding: 28px 28px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.vbg-kombi-title {
  font-family: var(--vbg-ff-display);
  font-size: 1.365rem;  /* Skala B: war 1.3rem = 24.5 px */
  font-weight: var(--vbg-fw-display);
  color: var(--vbg-forest);
  line-height: 1.25;
}

.vbg-kombi-desc {
  font-size: 1.012rem;  /* Skala B: war 0.88rem = 16.6 px */
  color: var(--vbg-warm-gray);
  line-height: 1.6;
  margin: 0;
}

.vbg-kombi-price {
  font-family: var(--vbg-ff-display);
  font-size: 1.68rem;  /* Skala B: war 1.6rem = 30.2 px */
  font-weight: var(--vbg-fw-display);
  color: var(--vbg-forest);
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--vbg-sand);
  margin-top: 4px;
}

@media (max-width: 1279px) {
  .vbg-kombi-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 600px) {
  .vbg-kombi-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   11. FIXES – Mobile & Allgemein
   ============================================================ */

/* Fix: Kombi Button Textfarbe explizit (globale a-Styles überschreiben) */
.vbg-kombi-card .vbg-btn-dark,
.vbg-kombi-card .vbg-btn-dark:visited,
.vbg-kombi-card .vbg-btn-dark:hover {
  color: var(--vbg-cream) !important;
  text-decoration: none !important;
}

/* Fix: Dosierung Hint lesbarer */
.vbg-dosage-hint {
  text-align: center;
  margin-top: 16px;
  font-size: 1.012rem;  /* Skala B: war 0.88rem = 16.6 px */
  color: rgba(255,255,255,0.65);
  letter-spacing: 0.03em;
}

/* Fix: Preisvergleich 3er-Grid auf Mobile umbrechen */
@media (max-width: 600px) {
  .vbg-kv-dogs-grid {
    grid-template-columns: 1fr !important;
    max-width: 280px;
    margin-left: auto;
    margin-right: auto;
  }
}

/* ── FIX: Bindestrich – kein Zeilenumbruch davor/danach ── */
/* Wörter können umbrechend, aber der Bindestrich bleibt an
   der vorherigen Zeile, da overflow-wrap ihn nicht trennt  */
@media (max-width: 600px) {
  .vbg-order-last h1 {
    overflow-wrap: break-word;
    hyphens: none;
    /* Verhindert Umbruch VOR einem Bindestrich:
       word-break:keep-all würde CJK-Zeichen ignorieren,
       stattdessen nutzen wir white-space-collapse normal +
       word-break normal + kein automatisches Trennen */
    word-break: normal;
  }
}

/* ── FIX: "In den Warenkorb" Button im Hero – Dawn setzt auf
   button[type="submit"] in Produktformularen eigene font-size/padding ── */
.vbg-page button[type="submit"].vbg-btn-cart,
.vbg-page button[type="submit"].vbg-btn-primary {
  font-size: 1.0062rem !important;  /* Skala B: war 0.875rem = 16.5 px */
  padding: 14px 20px !important;
  height: 52px !important;
  white-space: nowrap !important;
  line-height: 1 !important;
  box-sizing: border-box !important;
  letter-spacing: 0.08em !important;
}

@media (max-width: 480px) {
  .vbg-page button[type="submit"].vbg-btn-cart,
  .vbg-page button[type="submit"].vbg-btn-primary {
    font-size: 0.7rem !important;
  }
}

/* ══════════════════════════════════════════════════════════════
   KAUFKNOPF — zwei Farben, mit Absicht (2026-08-03)

   `.is-moss`  → Produktseite. `--vbg-moss` auf Weiss, mit dem Preis im Knopf.
   `.is-liquid-gold` → NUR NOCH die Set-Seite (`vbg-set-hero.liquid:1648`).

   ⛔ Die Trennung ist entschieden, nicht entstanden. Bis zum 2026-08-03 lief
   beides ueber `.is-liquid-gold`, und A12 stand auf „Moos ueberall — im Theme
   bereits so". Das war falsch gemessen: die Pruefung hatte Goldflaechen
   gezaehlt und den Kaufknopf nicht mitgezaehlt. Er war die ganze Zeit Gold.
   Die Entwuerfe verlangen Verschiedenes — PDP Moos (Spray PDP Z. 1552, 2208),
   Set-Seite Gold (`Set-Produktseite.dc.html:91, 251`) —, und das ist Absicht:
   die Set-Seite verkauft ein Buendel, die PDP ein Produkt.

   ⚠️ Wer daraus wieder EINE Regel macht, zieht die Set-Seite stumm mit.
   ══════════════════════════════════════════════════════════════ */
/* ⚠️ Ohne `button[type=submit]`-Praefix: die schwebende Leiste nutzt
   `type="button"`. Die alte Gold-Regel hat sie deshalb nie getroffen — ihre
   Farbe kam aus der Grundregel in `vbg-global.css:385`. */
.vbg-btn-primary.is-moss {
  background: var(--vbg-moss);
  color: var(--vbg-white);
  font-family: var(--vbg-ff-body);
  font-weight: var(--vbg-fw-semibold);
  letter-spacing: 0.04em;
  gap: 10px;
  border-radius: 0;
  box-shadow: none;
  transition: background 0.2s;
}
.vbg-btn-primary.is-moss:hover {
  background: var(--vbg-forest);
  color: var(--vbg-white);
  transform: none;
  box-shadow: none;
}
.vbg-btn-primary.is-moss:active {
  background: var(--vbg-forest);
  transform: none;
}
/* Der Preis im Knopf — er macht sichtbar, was der Klick kostet.
   Der Gedankenstrich ist nur Trennung und traegt keine Bedeutung. */
.vbg-atc-label { letter-spacing: inherit; }
.vbg-atc-sep   { opacity: 0.55; }
.vbg-atc-price { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ══════════════════════════════════════════════════════════════
   Liquid-Gold Add-to-Cart Conversion-Button — nur noch Set-Seite
   135°-Gold-Gradient + Hover-Glow + Icon-Nudging + Micro-Copy.
   Aktiviert auf jedem ATC-Button mit .is-liquid-gold.
   ══════════════════════════════════════════════════════════════ */
button[type="submit"].vbg-btn-primary.is-liquid-gold {
  /* ⛔ Flach. Vorher ein dreistufiger Verlauf mit drei rohen Hexwerten und
     vierlagigem Schatten. Der Entwurf setzt den Kauf-Button auf die volle
     Tokenfarbe, ohne Verlauf und ohne Schatten.
     ⚠️ Diese Regel ist mit der SET-SEITE geteilt (vbg-set-hero.liquid:1642).
     Sie wird dort mit flach -- der Set-Entwurf verlangt dasselbe. */
  background: var(--vbg-gold) !important;
  color: var(--vbg-forest) !important;
  font-family: var(--vbg-ff-body) !important;
  font-weight: var(--vbg-fw-semibold) !important;
  letter-spacing: 0.12em !important;
  gap: 12px !important;
  padding: 14px 26px !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  transition:
    filter 0.25s ease,
    transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1),
    box-shadow 0.25s ease !important;
  position: relative;
}
button[type="submit"].vbg-btn-primary.is-liquid-gold:hover {
  filter: brightness(1.08) saturate(1.05);
  transform: translateY(-1px) scale(1.015);
  box-shadow:
    0 6px 18px rgba(166, 124, 0, 0.38),
    0 14px 34px rgba(166, 124, 0, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.40),
    inset 0 0 0 1px rgba(212, 175, 55, 0.55) !important;
}
button[type="submit"].vbg-btn-primary.is-liquid-gold:active {
  transform: translateY(0) scale(1.005);
  filter: brightness(0.98);
}
.vbg-atc-icon {
  flex-shrink: 0;
  display: inline-block;
  vertical-align: middle;
}
.vbg-atc-icon--arrow {
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.vbg-btn-primary.is-liquid-gold:hover .vbg-atc-icon--arrow {
  transform: translateX(4px);
}

/* Micro-Copy unter dem Button — Variante A: Versand + Test-Garantie
   14px / Semi-Bold / Dunkelgrau (#444444) — outdoor-lesbar bei Sonnenlicht */
.vbg-atc-microcopy {
  font-family: var(--vbg-ff-body);
  font-size: 16px;
  color: #444444;
  font-weight: 600;
  text-align: center;
  margin: 12px 0 0;
  line-height: 1.5;
  letter-spacing: 0.01em;
}

/* ── FIX: Bestseller Ribbon – schräges Banner oben links: siehe Sektion 9 ── */

/* ── FIX: INGA Section – Texte schwarz statt weiß ──
   .vbg-page h2 { color: var(--vbg-forest) } hat Spezifität (0,1{ color: var(--vbg-white) } hat Spezifität (0,1{
  color: var(--vbg-white) !important;
}

/* Alle p-Tags in der INGA Section: weiß statt warm-gray */

/* Hint-Text unter der Flasche */

/* Footer CTA */

/* Bild-Lightbox */
.vbg-lightbox-trigger {
  cursor: zoom-in;
  position: relative;
}

.vbg-lightbox-trigger::after {
  content: '🔍';
  position: absolute;
  bottom: 8px;
  right: 8px;
  font-size: 1.26rem;  /* Skala B: war 1.2rem = 22.7 px */
  opacity: 0;
  transition: opacity 0.2s;
  pointer-events: none;
}

.vbg-lightbox-trigger:hover::after {
  opacity: 1;
}

.vbg-lightbox-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.9);
  z-index: 9999;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}

.vbg-lightbox-overlay.is-open {
  display: flex;
}

.vbg-lightbox-overlay img {
  max-width: 92vw;
  max-height: 88vh;
  object-fit: contain;
  border-radius: 8px;
}

.vbg-lightbox-close {
  position: absolute;
  top: 16px;
  right: 20px;
  color: white;
  font-size: 2.1rem;  /* Skala B: war 2rem = 37.8 px */
  cursor: pointer;
  line-height: 1;
  opacity: 0.8;
}

.vbg-lightbox-close:hover {
  opacity: 1;
}
   ============================================================ */

.vbg-contact-wrap {
  max-width: 560px;
  margin: 0 auto;
  text-align: center;
}

.vbg-founder-img {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  object-fit: cover;
  margin: 0 auto 24px;
  display: block;
  border: 3px solid var(--vbg-sand);
}

/* ============================================================
   11. LIGHTBOX
   ============================================================ */

#vbg-lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: rgba(0,0,0,0.9);
  align-items: center;
  justify-content: center;
  animation: vbgLbFade 0.25s ease;
}

#vbg-lightbox.is-active {
  display: flex;
}

#vbg-lightbox-img {
  width: auto;
  height: auto;
  max-width: 90vw;
  max-height: 88vh;
  object-fit: contain;
  border-radius: var(--vbg-radius-lg);
  animation: vbgLbZoom 0.25s ease;
}

#vbg-lightbox-close {
  position: fixed;
  top: 16px;
  right: 20px;
  background: rgba(255,255,255,0.12);
  border: none;
  color: #fff;
  font-size: 1.47rem;  /* Skala B: war 1.4rem = 26.4 px */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s ease;
}

#vbg-lightbox-close:hover {
  background: rgba(255,255,255,0.22);
}

/* ============================================================
   GLOBALE RESPONSIVE-OVERRIDES
   (nur für Utilities die keine eigene Sektion haben)
   ============================================================ */

@media (max-width: 1279px) {
  .vbg-order-first { order: 0; }
  .vbg-order-last  { order: 0; }
}

/* ============================================================
   PREFERS-REDUCED-MOTION
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .vbg-reveal, .vbg-reveal-left, .vbg-reveal-right {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  [data-delay] { transition-delay: 0s !important; }
}

/* ══════════════════════════════════════════════════════════════════════
   PDP-HERO — gemeinsame Wurzel der beiden Hälften
   ══════════════════════════════════════════════════════════════════════
   Angelegt am 2026-08-03 mit der Teilung von vbg-zpp-hero.liquid in
   vbg-zpp-galerie und vbg-zpp-kauf (Weg A, PDP-ZWEISPALTIG-WEGE.md).

   Beide Sections brauchen dieselbe Wurzel. Sie steht deshalb HIER und
   nicht doppelt in den beiden <style>-Blöcken — doppeltes CSS läuft
   auseinander, und genau daran ist der Kombi-Umbau schon einmal
   hängengeblieben.

   ⚠️ Die Fläche sitzt auf der `.shopify-section`, nicht auf `.vbg-hero`.
   Grund: Grid-Items strecken sich auf die Zeilenhöhe (`align-items:
   stretch`), ein Kind mit `height: auto` tut das nicht. Läge das Cream
   auf `.vbg-hero`, endete es unter der kürzeren der beiden Hälften und
   die Fläche bekäme eine Stufe.
   ────────────────────────────────────────────────────────────────────── */
.vbg-hero {
  /* Fläche liegt auf der .shopify-section, siehe oben. */
  background: none;
  /* ⛔ Das Offset-Polster ist mit Teilstück 2 an das Seitengrid gewandert
     (`#MainContent { padding-top }`). Läge es hier, bekäme JEDE der beiden
     Hälften den Header-Abstand — die rechte Spalte fängt aber nicht unter
     dem Header an, sie fängt unter den Breadcrumbs an. */
  padding: 0;
  /* Safety-Net gegen horizontalen Overflow (Pills, lange Eyebrow-Texte etc.) */
  overflow-x: clip;
  min-width: 0;
}
.vbg-hero__half { min-width: 0; }

/* ══════════════════════════════════════════════════════════════════════
   DAS SEITENGRID — Teilstück 2 von Punkt 4, 2026-08-03
   ══════════════════════════════════════════════════════════════════════
   Ersetzt den Zwischenstand aus Teilstück 1. Der Entwurf setzt einen
   Container über die GANZE Seite: links 55 % sticky auf Parchment, rechts
   45 % mit ALLEN Abschnitten, kein vollbreiter Inhaltsabschnitt außer dem
   Footer (ENTWURF-REFERENZ.md §1.1).

   Drei Regeln tragen das, plus die drei Token-Überschreibungen. Die
   zehn Section-Dateien bleiben unangetastet.

   ⛔ WÄCHTER: `:has(.vbg-hero--galerie)`, NICHT die Body-Klasse.
   `body.vbg-product-page` tragen auch product.set.json, product.json,
   das GemPages-Template und product.ARCHIV.gras-kot — keines davon hat
   eine Galeriespalte. Die Klasse `vbg-tpl-*` aus theme.liquid ist der
   Hook für den umgekehrten Fall: wenn die Set-Seite das Grid später
   ABSICHTLICH bekommt.
   ────────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) {
  display: grid;
  grid-template-columns: 55fr 45fr;
  align-items: start;
  /* ── Die obere Kante, EINMAL benannt ──────────────────────────────
     `--vbg-pdp-top` ist ein NEUER Name für eine neue Größe, nicht die
     Umwidmung eines bestehenden Tokens — der Unterschied ist der Grund,
     warum das hier in Ordnung ist und die drei Token-Überschreibungen
     oben nicht waren.

     Gebraucht wird sie zweimal: als Flusspolster hier und als Anschlag
     des Bildpanels. Standen die beiden Ausdrücke getrennt da, liefen sie
     auseinander — genau das war der Fall: das Polster rechnete den
     40 px hohen USP-Streifen mit, der Anschlag nicht, und das Panel
     ragte 8 px unter die Falz.

     ⚠️ Der Streifen ist am 2026-08-03 entfallen und `--vbg-usp-banner-h`
     mit ihm. Die Groesse bleibt trotzdem benannt: sie hat zwei Leser
     (Flusspolster und Anschlag), und die duerfen nicht wieder getrennt
     dastehen. Kommt je eine zweite Leiste, wird sie HIER addiert. */
  --vbg-pdp-top: var(--vbg-offset, 108px);
  padding-top: var(--vbg-pdp-top);
}

/* ══════════════════════════════════════════════════════════════════════
   ABSCHNITTSFLÄCHEN DER RECHTEN SPALTE — Zuordnung V2
   ══════════════════════════════════════════════════════════════════════
   ⛔ ABWEICHUNG VOM ENTWURF, entschieden vom Auftraggeber am 2026-08-05.
   Beide PDP-Entwürfe geben den Abschnitten KEINE Fläche; `CLAUDE.md` A8
   führte „PDP · Set-Seite — kein Rhythmus". Beides ist überstimmt, die
   Begründung steht in A8: **Neun Abschnitte in derselben Fläche lesen als
   eine lange Spalte; der Entwurf zeichnet sie kürzer, als sie im Theme
   geworden sind.**

   ⛔ DIE GRUPPIERUNG IST GEMESSEN, NICHT GERATEN. Wer hier einen
   Abschnitt einfügt, entfernt oder verschiebt, ändert den Rhythmus —
   deshalb stehen die Zahlen hier und nicht in einem Bericht.

   Gemessen am 2026-08-05 am gerenderten Dokument, 1440 px, nach der
   Schriftvergrößerung:

     kauf              1728 px   bleibt WEISS (Kaufspalte)
     kostenvergleich    592 px   ▓ Fläche
     testimonials      1197 px   ░ weiss
     herstellung        260 px   ▓ Fläche  ┐ zusammen EIN Band
     zeitplan           977 px   ▓ Fläche  ┘ 1317 px (mit den 80 px dazwischen)
     kombi              575 px   ░ weiss
     faq                123 px   ▓ Fläche  ┐ zusammen EIN Band
     kontakt            303 px   ▓ Fläche  ┘  506 px (mit den 80 px dazwischen)

   Daraus fünf Bänder: ▓592 ░1197 ▓1317 ░575 ▓506

   ⛔ NACHGEMESSEN nach den 80 Abstandsstellen (senkrechte Abstände × 1,25)
   — und diesmal BEIDE Breiten:

     1440 px   ▓630 ░1269 ▓1382 ░588  ▓541   Faktor 2,55, niedrigstes 541
      390 px   ▓769 ░1150 ▓1673 ░1176 ▓564   Faktor 2,97, niedrigstes 564

   ⛔ ZUORDNUNG V2 SEIT DEM 2026-08-05 — sechs Bänder, gemessen als
   SICHTBARE Bänder (die Ränder zählen zum weissen Nachbarn):

     ▓ kostenvergleich  750 / 818     ░ testimonials  1429 / 1213
     ▓ herstellung      393 / 352     ░ zeitplan      1189 / 1353
     ▓ kombi            708 / 1224    ░ faq+kontakt    621 /  596
                                        (1440 px / 390 px)
     Faktor 3,64 / 3,84 · kleinstes Band 393 / 352

   Der Auftraggeber wollte den Farbwechsel zwischen `herstellung` und
   `zeitplan`. V2 liefert ihn, ohne dass `zeitplan` und `kombi` zu einem
   weissen Doppelblock verschmelzen — das wäre die naheliegende Variante
   gewesen und hätte 1857 px (Desktop) bzw. 2561 px (mobil) Weiss am Stück
   ergeben, gut drei Bildschirmhöhen ohne Wechsel.

   ══════════════════════════════════════════════════════════════════════
   ⛔ DIE GRENZEN SIND ANHALTSPUNKTE, KEIN TOR — zurückgestuft am 2026-08-05
   ══════════════════════════════════════════════════════════════════════
   Hier stand `Faktor < 3` und `kein Band < 400 px` als **Abnahmekriterium**.
   Beide Zahlen waren gegen einen Zustand gebildet, **den es nicht mehr
   gibt** — vor Zwischenstufe und Polster. Dieselbe `herstellung`, die
   damals als 273-px-Streifen galt, misst heute **393 px** und trägt am
   Bild als eigenes Band, bei 1440 und bei 390 px geprüft.

   > **Gehen Auge und Zahl auseinander und das Auge sagt dreimal dasselbe,
   > hat die Zahl unrecht.** (Auftraggeber, 2026-08-05)

   Neue Werte, hergeleitet statt gegriffen:

       Faktor    <  4,5    Ist-Stand 3,64 / 3,84 — knapper Abstand nach
                           oben, damit eine echte Verschlechterung noch
                           auffällt.
       Band      >= 300 px Eingeklammert von zwei Beobachtungen: 393 px
                           trägt am Bild, 144 px (`faq` im strengen
                           Wechsel) trägt nicht.

   ⛔ Sie **verbieten nichts**. Wer sie reisst, sieht sich das Bild an und
   entscheidet dort. ⚠️ Und die Lehre, die teurer war als die Zahl: Die
   alte 400 hat einen richtigen Entwurf zweimal blockiert, weil sie gegen
   eine frühere Ausstattung gemessen war. **Eine Schwelle altert mit dem,
   wogegen sie gebildet wurde** — wer sie setzt, schreibt den Zustand dazu.

   📝 Werkzeug: `node scripts/pdp-baender.mjs` — misst beide Breiten als
   sichtbare Bänder und meldet, wenn ein Anhaltspunkt fällt.

   ⛔ DER FAKTOR ALLEIN BELEGT NICHTS. Er ist ein Verhältnis ZWEIER Bänder
   und blind für alles dazwischen. **Diesmal ist er nur zufällig stabil
   geblieben:** Bei der Abstandsvergrösserung sind grösstes und kleinstes
   Band ähnlich gewachsen — 1317 → 1382 (× 1,05) und 506 → 541 (× 1,07) —,
   deshalb bewegte sich 2,60 kaum auf 2,55. Wer beim nächsten Eingriff nur
   den Faktor prüft und ihn stabil findet, hat **keinen Beleg für die
   Zuordnung**, sondern nur dafür, dass sich die zwei Extreme proportional
   bewegt haben. Genau deshalb stehen oben die fünf Höhen.

   ⛔ UND DER TREIBER IST NICHT `kombi`. Hier stand, kombi sei der Treiber,
   weil es mobil von 588 auf 1176 px wächst. Die Zahl ist gemessen richtig
   und **für den Faktor bedeutungslos**: 1176 liegt bei 390 px MITTEN im
   Feld zwischen kleinstem (564) und grösstem Band (1673) und geht in
   max/min gar nicht ein. Den Faktor setzen auf beiden Breiten
   `herstellung + zeitplan` gegen `faq + kontakt`.
   ⚠️ Nah an der Grenze steht kombi auf dem **Desktop**: 588 px gegen das
   kleinste Band mit 541. Schrumpft es dort um 8 %, ist es selbst das
   kleinste Band. Die Warnung war richtig — sie stand an der falschen
   Breite.

   ⛔ `faq` TRÄGT NUR IM VERBUND MIT `kontakt` — allein misst es **145 px**
   (1440) bzw. 123 px (390). Die 400-px-Grenze hält erst das Paar (541 /
   564). Wer die beiden je trennt — ein Abschnitt dazwischen, oder einer
   von beiden bekommt eine eigene Fläche —, hat kein 541-px-Band mehr,
   sondern einen 145-px-Streifen: **genau den Defekt, gegen den B gewählt
   wurde** (siehe „WARUM NICHT JEDER ZWEITE" unten). Die Zuordnung ist dann
   neu zu rechnen, nicht nachzujustieren.

   ⛔ DIE PAARBILDUNG IST KEINE KOSMETIK — SIE HÄLT DIE GRENZE. Jeder
   Abschnitt einzeln gemessen (1440 / 390 px), Grenze 400:

     kostenvergleich   630 /  769   ✅
     testimonials     1269 / 1150   ✅
     herstellung       273 /  304   ⛔ unter 400 auf BEIDEN Breiten
     zeitplan         1109 / 1369   ✅
     kombi             588 / 1176   ✅
     faq               145 /  123   ⛔ unter 400 auf BEIDEN Breiten
     kontakt           396 /  441   ⛔ unter 400 bei 1440, um 4 px

   **Drei der sieben Abschnitte tragen allein nicht**, und es sind genau
   drei der vier Glieder der beiden Paare — nur `zeitplan` trüge für sich.
   Erst im Verbund kommen sie auf 1382 / 1673 und 541 / 564.

   ⚠️ `kontakt` mit 396 ist der lehrreiche Fall: **4 px unter der Grenze.**
   Wer die Paare auflöst, verliert nicht nur den 145-px-Streifen, den man
   sieht — er verliert auch einen Abschnitt, der auf den ersten Blick
   ausreichend aussieht. Die Grenze prüft man nicht am Augenmass.

   ⛔ NACHGEMESSEN AM 2026-08-05, UND DIE ZEILE DARÜBER STIMMTE NICHT:
   Jeder Abschnitt trägt `margin-top: 80px`, und `#MainContent` ist ein
   Grid — in Grid-Items fällt kein Rand zusammen. Zwischen `herstellung`
   und `zeitplan` und zwischen `faq` und `kontakt` standen also **80 px
   Weiss**. Die beiden „Bänder" waren keine; sichtbar lagen sieben
   Blöcke, darunter der **123-px-Streifen `faq`** — genau der Defekt,
   gegen den B gewählt worden war. Die Zahlen 1237 und 426 waren
   gerechnet, nicht gemessen.
   ✅ Behoben unten: das zweite Glied jedes Paares tauscht seine 80 px
   Rand gegen 80 px Polster. Die Höhe bleibt auf den Pixel gleich, der
   Zwischenraum liegt jetzt IM Band statt daneben.

   ⛔ WARUM NICHT „JEDER ZWEITE" — BEGRÜNDUNG KORRIGIERT AM 2026-08-05,
   nach einer Probe mit gleicher Ausstattung (Ton, Zwischenstufe, Polster):

     Zuordnung B   1440: 2,56 / min 588 ✅    390: 2,82 / min 611 ✅
     gemischt      1440: 3,34 / min 380 ⛔    390: 3,66 / min 352 ⛔
     streng        1440: 8,81 / min 144 ⛔    390: 10,57 / min 122 ⛔

   ⛔ **Hier stand „die 260-px-Herstellung liegt als Streifen". Das gilt
   nicht mehr.** Am Bild gemessen trägt `herstellung` als eigenes Band
   ohne weiteres — denn die 273 px waren nie die ganze Zahl: Mit
   Zwischenstufe (2 × 24) und Polster (24 + 48) wird daraus ein Band von
   **393 px**. Die Ausstattung hebt genau die kleinen Abschnitte über die
   Grenze; die alte Begründung war gegen einen Zustand gebildet, den es
   nicht mehr gibt.

   ✅ **Die richtige Begründung ist der ABSTAND, nicht die Grösse:** Auch
   die Zwischenform, die nur `herstellung`/`zeitplan` trennt und
   `faq`+`kontakt` zusammenlässt, reisst das Kriterium (3,34 / 3,66).

   > **B funktioniert nicht, weil es kleine Abschnitte versteckt, sondern
   > weil es kleine mit grossen PAART.** Jede Trennung löst die Paarung
   > auf, und der Abstand zwischen grösstem und kleinstem Band wächst —
   > unabhängig davon, wie gut das kleine Band für sich aussieht.

   ⚠️ `faq` bleibt der Sonderfall: Im strengen Wechsel ist es **weiss**,
   bekommt also weder Stufe noch Polster, und steht als Überschrift mit
   einem `+` in einem hellen Loch zwischen zwei Flächen. **Weisse Bänder
   tragen im System nichts — ihre Nachbarn tragen für sie.**

   📝 Wer den strengen Wechsel je will, setzt **oben** an, nicht unten:
   `testimonials` 1269 und `zeitplan` 1029 px. `OFFEN.md` 53.
   Vollständige Probe: `BERICHTE/2026-08-05-strenger-wechsel-probe.md`.

   ✅ Die Gruppen sind auch inhaltlich stimmig: Herstellung und Zeitplan
   sind beide Prozess, FAQ und Kontakt beide Service am Seitenende.

   ⚠️ UND SIE IST ROBUSTER. Wächst auf der PDP noch etwas — die
   Schriftvergrößerung lief gerade —, kippt der strenge Wechsel zuerst,
   weil dort zwei Bänder nahe an der Grenze liegen. In B liegt keines.
   ⚠️ Auf dem Desktop. Bei 390 px trägt B nur noch knapp — siehe die
   Schwelle oben.

   ⛔ WÄCHTER: dieselbe Bedingung wie beim Grid darüber,
   `:has(.vbg-hero--galerie)`. `body.vbg-product-page` allein trifft auch
   product.set.json, product.json, das GemPages-Template und
   product.ARCHIV.gras-kot — keines davon hat diese Spaltenaufteilung.

   ⚠️ Der Ton ist `--vbg-section-alt`, NICHT cream: Die Galeriespalte
   links trägt cream (ΔE 0,0 — es wäre dieselbe Farbe). Dass sie es tut,
   ist selbst eine unentschiedene Abweichung, `OFFEN.md` 50.
   ⛔ Der Wert steht seit dem 2026-08-05 auf **#ebf0ec** (vorher #e3ebe5),
   gesenkt auf Entscheidung des Auftraggebers — der Ton las als eigene
   Farbe statt als Nuance. **Nicht hier ändern, sondern am Token**; die
   Begründung, beide ΔE-Verfahren und der gemessene Textkontrast stehen in
   `assets/vbg-tokens.css` beim Token selbst.
   ══════════════════════════════════════════════════════════════════════ */
/* ⛔ `*=` UND NICHT `$=` — 2026-08-07. Ursache und Nachtrag in einem:

   Die elf Produktvorlagen benannten ihre Abschnitte in ZWEI Schreibweisen —
   `dental` und `gras-kot` kurz (`kostenvergleich`), die uebrigen NEUN lang
   (`vbg_zpp_kostenvergleich`). Shopify baut daraus
   `id="shopify-section-template--<id>__<schluessel>"`, und die Regel stand
   auf `[id$="__kostenvergleich"]`: Sie traf nur die kurze Schreibweise, und
   auf NEUN von elf Produktseiten hat der Flaechenwechsel nie stattgefunden.

   ⚠️ Unbemerkt blieb es, weil `dental` das Produkt ist, an dem hier fast
   alles gemessen wird — dort hat die Regel funktioniert. Dieselbe Klasse wie
   „richtig gemessener Ausschnitt, falsch verallgemeinerte Aussage", nur an
   einem Selektor.

   ✅ SEIT DEM 2026-08-07 SIND DIE SCHLUESSEL VEREINHEITLICHT (kurze Form, in
   allen elf Vorlagen; `OFFEN.md` 123 erledigt). `$=` wuerde also wieder
   treffen.

   ⛔ Es bleibt trotzdem bei `*=`, und das ist eine Entscheidung, keine
   Nachlaessigkeit: Ein Suffix-Vergleich auf einen Section-Schluessel bricht
   lautlos, sobald jemand eine Vorlage anders benennt — und genau das ist
   einmal passiert, ohne dass es jemand gemerkt hat. `*=` ueberlebt das.
   📝 Gegengeprueft ueber alle elf Vorlagen: kein anderer Abschnitt traegt
   eines der drei Woerter im Schluessel. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id*="kostenvergleich"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id*="herstellung"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id*="kombi"] {
  background: var(--vbg-section-alt);
}

/* ══════════════════════════════════════════════════════════════════════
   ⛔ MUSTER FÜR JEDES WEITERE BAND IM THEME: 50 + 50, NICHT 100

   Steht hier, weil hier gesucht wird — die PDP ist die erste Seite mit
   Flächenwechsel. **Sie selbst braucht das Muster nicht** (die Abschnitte
   sind Grid-Items und tragen den Ton direkt); jede Seite mit einem
   VOLLBREITEN Träger braucht es. Erstmals gebaut auf Über uns:
   `templates/page.ueber-uns.liquid`, `.vbg-mk-band`.

   Der Fall: Ein Band ist breiter als der Inhalt, also braucht es einen
   Träger. Die Abschnitte darin tragen ihren Abstand meist selbst
   (`margin-top: 100px`).

   ⛔ ZWEI FEHLER LIEGEN DANN NAHE, und beide sehen im Code richtig aus:

   1. **Träger ohne `padding`, Kind behält `margin-top`.** Die Marge
      **kollabiert durch den Träger hindurch** und wirkt AUSSERHALB — die
      Farbkante sitzt 100 px zu hoch, der Text steht am oberen Rand des
      Bandes. Nichts schlägt fehl, es sieht nur falsch aus.
   2. **Träger mit `padding: 100px`, Kind behält seine 100.** Kein
      Collapsing mehr, dafür addieren sie sich: 200 px zwischen zwei
      Texten, wo überall sonst 100 stehen.

   ✅ DIE FASSUNG, die beides löst:

       .band       { margin-top: 50px; padding-block: 50px; }
       .band > :first-child { margin-top: 0; }

   Der Gesamtabstand bleibt bei 100 — und die Farbkante sitzt **mittig im
   vorhandenen Weissraum** statt direkt am Text. Das ist der eigentliche
   Gewinn: Ein Band, dessen Kante am Text klebt, liest als Kasten; eines
   mit Luft auf beiden Seiten liest als Fläche.

   ⚠️ Die 50 sind die Hälfte des seitenüblichen Abstands, nicht der Wert
   selbst. Steht die Seite auf 80er-Abständen, sind es 40 + 40.

   ⚠️ Nur das ERSTE Kind verliert `margin-top`. Ein zweites Kind im selben
   Band behält seine Marge — das ist der Abstand INNERHALB des Bandes und
   soll bleiben (auf Über uns: Zeitleiste und Dreierreihe im selben Band).
   ══════════════════════════════════════════════════════════════════════ */

/* ⛔ UND DIE INNERE FLÄCHE MUSS WEG, sonst sieht man nur die Ränder.
   Vier der fünf Abschnitte tragen innen ein `section.vbg-section-white`,
   das 520 px breit ist und WEISS malt. Die Hülle darunter ist 648 px —
   sichtbar blieb der Ton dadurch nur als **zwei 64-px-Streifen links und
   rechts**, in der Mitte weiss. Der fünfte (`kontakt`) hat kein weisses
   Innen und zeigte den Ton über die volle Breite; die fünf sahen deshalb
   auch untereinander verschieden aus.

   ⚠️ DAS IST GENAU DIE STAPELUNG AUS `OFFEN.md` 50 — dieselbe, die eine
   Stunde vorher an der Galeriespalte gemessen und dort aufgeschrieben
   worden war: Hülle setzt einen Ton, ein Kind malt darüber, und wer nur
   das äussere Element prüft, sieht „Ton gesetzt, alles richtig".
   Die Regel dagegen stand schon da — **bei Flächen die KETTE messen,
   nicht das Element** — und die Gegenprobe beim Einbau hat trotzdem nur
   `getComputedStyle(section).backgroundColor` gelesen.
   ✅ Seither prüft `scripts/flaeche.mjs` die Kette; der Nachweis für
   diesen Block läuft darüber (`flaechenKette`, `pruefeFlaeche`).
   ⚠️ Und das Urteil fällt über das BAND, nicht über den Mittelpunkt:
   bei `kontakt` liegt dort die 520 px breite `.vbg-kt2-box` und meldet
   cream. Das ist die Messstelle, kein Defekt — geprüft wird deshalb an
   den beiden Aussenpunkten plus „kein Kind über die volle Breite".

   `transparent` statt derselbe Ton noch einmal: So gibt es weiterhin
   EINE Farbquelle (die Hülle) und keinen zweiten Wert, der auseinander
   laufen kann. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kostenvergleich"] > section,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__herstellung"] > section,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kombi"] > section {
  background: transparent;
}

/* ── Das verbliebene Paar der Zuordnung V2 ist EIN Band ───────────────
   `zeitplan` und `kontakt` sind die zweiten Glieder. Sie tauschen ihre
   80 px Rand gegen 80 px Polster: Gesamthöhe unverändert, aber der
   Zwischenraum wird von der Hülle mitgefärbt statt weiss zu bleiben.
   ⚠️ Nur diese beiden — bei jedem anderen Abschnitt IST der Weissraum
   die Trennung und soll bleiben.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kontakt"] {
  margin-top: 0;
  padding-top: 80px;
}

/* ── Die Haarlinie IM Band: faq | kontakt ─────────────────────────────
   ⛔ MEHR ABSTAND IST WIDERLEGT, NICHT NUR UNGÜNSTIG. Gemessen am
   2026-08-05 am gerenderten Dokument:

     sichtbare Fuge IM Band (letzte Zeile herstellung → „So startest du")   98 px
     Weissraum ZWISCHEN zwei Bändern (kombi → faq)                          80 px

   Die Fuge im Band ist **schon 18 px grösser** als der Abstand, an dem
   zwei Bänder sauber auseinanderfallen — und sie verschmilzt trotzdem.
   **Was dort trennt, ist der Wechsel, nicht die Entfernung.** Die Probe
   mit 140 px bestätigte es: ein grösseres Loch in derselben Fläche, zwei
   Überschriften ohne Grenze.
   ⚠️ Und Abstand kostet doppelt: 60 px mehr gehen direkt in das grösste
   Band (1382 → 1442) und drücken den Faktor nach oben — bei 390 px, wo
   2,97 gegen die 3 steht, ist das der falsche Hebel.

   ✅ DIE LINIE KOSTET FAST NICHTS. 40 px Polster an der Hülle, Linie am
   inneren `section`, 40 px darunter — statt der bisherigen 80 px am
   Stück. **Das Band wächst um genau 1 px**, die Breite der Linie selbst
   (1382 → 1383 bei 1440 px, 1673 → 1674 bei 390 px); der Faktor geht von
   2,55 auf 2,56, mobil bleibt er bei 2,97.
   ⚠️ Hier stand zuerst „bleibt auf den Pixel gleich" — **das war
   gerechnet, nicht gemessen.** Ein `border-top` liegt ausserhalb des
   Polsters, nicht darin. Nachgemessen mit `node scripts/pdp-baender.mjs`.

   ⚠️ Die Linie ist **520 px breit, nicht 648** — sie sitzt auf der
   Textspalte, nicht über das ganze Band. Genau so führt der Entwurf
   **alle** seine Haarlinien (79 Stück, sämtlich an Bauteilen auf der
   Textbreite). Eine Linie über die volle Bandbreite würde das Band
   zerschneiden statt es zu gliedern.

   ⛔ `--vbg-sand`, nicht `--vbg-parchment`: parchment ist auf dem Ton zu
   leise, beide am Bild verglichen. Die Drops-Datei des Entwurfs führt an
   ihren zwei Abschnittslinien ebenfalls `sand`.

   ⛔ `!important` IST HIER NÖTIG, nicht Bequemlichkeit: Die erste Probe
   ohne war **wirkungslos** — eine bestehende `border-top: 0`-Regel
   gewinnt —, und das Bild sah exakt aus wie der Ist-Zustand. Wer diese
   Zeile „aufräumt", entfernt die Linie, ohne dass sich sonst etwas ändert.

   ⛔ ES GIBT NUR NOCH EINE NAHT — die zwischen `herstellung` und
   `zeitplan` ist am 2026-08-05 GEFALLEN, und zwar ersatzlos.

   Sie trennte **innerhalb eines Bandes**. Seit V2 sind die beiden
   verschiedene Flächen; der Farbwechsel trennt dort, und eine Linie
   zusätzlich wäre eine zweite Trennung an derselben Stelle.
   ⚠️ **Das ist kein Fehler von damals.** Solange die zwei ein Band waren,
   war die Linie die einzige Trennung, die es gab — die Messung dazu
   (98 px Fuge, die trotzdem verschmilzt) steht oben und gilt weiter. Was
   sich geändert hat, ist nicht die Messung, sondern die Zuordnung.

   ✅ `faq` | `kontakt` bleibt ein Band und behält die Naht. **Der
   Rangunterschied spricht dafür, nicht dagegen:** `faq` ist mit 144 px
   der kleinste Abschnitt der Seite und `kontakt` mit 397 px fast dreimal
   so gross. Ohne die Naht liest der kleine Teil als Vorspann des grossen
   statt als eigener Abschnitt.

   ⚠️ Das Paar ist seit V2 **weiss**. Die Sand-Linie steht damit auf Weiss
   statt auf dem Ton — sie bleibt sichtbar (sand gegen weiss ist der
   grössere Abstand von beiden), aber wer sie prüft, prüft sie dort.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kontakt"] {
  padding-top: 40px;
}
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kontakt"] > section {
  border-top: 1px solid var(--vbg-sand) !important;
  padding-top: 40px;
}

/* ── Anlauf und Auslauf im Band ───────────────────────────────────────
   Der Übergang zwischen den Bändern soll weicher wirken (Auftraggeber).
   Schritt 2 von dreien; Schritt 1 war der gesenkte Ton.

   ⛔ DER GRUND IST GEMESSEN, nicht Geschmack. Abstand von der Bandkante
   zum ersten bzw. letzten Text, vorher:

     kostenvergleich        oben 28   unten   0
     herstellung+zeitplan   oben 28   unten   0
     faq+kontakt            oben 60   unten 110

   **Bei zwei von drei Bändern endet der letzte Text exakt auf der
   Unterkante.** Hart wirkt also nicht der Farbsprung, sondern dass er
   unmittelbar an einer Textzeile stattfindet. Nachher 52 / 48.

   ⚠️ `faq+kontakt` hatte beides schon — deshalb steht hier kein fester
   Zielabstand, sondern ein Zuschlag. Wer daraus einen Zielwert macht,
   muss die Bänder einzeln pflegen.

   ⛔ SEIT V2 sind Bandanfang und Bandende DIESELBEN DREI Abschnitte —
   jeder getönte Abschnitt ist sein eigenes Band, also oben und unten
   Kante. `faq`+`kontakt` ist weiss und bekommt deshalb weder Polster noch
   Stufe: **Weisse Bänder tragen im System nichts, ihre Nachbarn tragen
   für sie.**

   ══════════════════════════════════════════════════════════════════════
   ⛔ NUR DESKTOP — UND DAS IST DER TEURE TEIL DER ENTSCHEIDUNG
   ══════════════════════════════════════════════════════════════════════
   Dasselbe Polster bei 390 px reisst das Abnahmekriterium der Zuordnung:

     390 px   jetzt 2,97 ✅   ·   +24/+48 → 3,15 ⛔   ·   +40/+64 → 3,03 ⛔

   ⛔ Und es ist kein Wertproblem: `faq+kontakt` gewinnt fast nichts dazu
   (563 → 555), weil seine 104 px unten ein **Rand** sind, der heute aus
   der Section herausläuft — ein `padding-bottom` fängt ihn ein, statt
   etwas hinzuzufügen. Die zwei grossen Bänder wachsen voll. Der Abstand
   zwischen grösstem und kleinstem Band nimmt also ZU.
   Gerechnet: Bei unverändertem kleinstem Band bliebe für Anlauf **und**
   Auslauf zusammen `x < 15 px`. Das ist kein Polster.

   ⚠️ **`min-width`, nicht `max-width`.** Ein Desktop-Wert mit mobilem
   Gegenstück wäre dieselbe Wirkung — aber das Gegenstück kann man
   vergessen, und genau das ist im Theme schon fünfmal passiert
   (`CLAUDE.md`, Mobilblock-Regel). Was konstruktiv nicht greift, kann
   man nicht vergessen.

   🚩 Bei 390 px kleben die zwei grossen Bänder damit weiter an der Kante.
   **Benannte Auslassung, kein Versehen** — `OFFEN.md`. Der Weg dorthin
   führt über die Höhe von `herstellung+zeitplan`, nicht über Polster.

   ✅ Gemessen NACH dem Einbau: **1440 px Faktor 2,58** · 390 px unverändert
   2,97, beide unter 3 (`node scripts/pdp-baender.mjs`).

   ⚠️ Die Probe hatte 2,73 vorhergesagt — sie war **pessimistisch**, weil
   sie `zeitplan` und `kontakt` ihr Polster per `!important` festhielt und
   damit verhinderte, dass das kleinste Band mitwächst. Im Einbau wächst
   `faq+kontakt` von 540 auf 564, und der Faktor bleibt praktisch stehen
   (2,56 → 2,58) statt zu steigen.
   ⛔ **Eine Probe, die Werte festhält, misst nicht die Änderung, sondern
   die Fesselung.** Die Zahl aus der Probe ist eine Schätzung; die Zahl
   nach dem Einbau ist die Messung.
   ──────────────────────────────────────────────────────────────────── */
@media (min-width: 1280px) {
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kostenvergleich"],
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__herstellung"],
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kombi"] {
    padding-top: 24px;
    padding-bottom: 48px;
  }
}

/* ── Die Zwischenstufe an der Bandkante ───────────────────────────────
   Schritt 3 und letzter: Der Sprung Weiss → Band wird in zwei Stufen
   geteilt. Variante B aus `BERICHTE/2026-08-05-banduebergang-varianten.md`.

   ⛔ WARUM NICHT DAS POLSTER DARÜBER GEREICHT HAT. Es war Variante A, und
   es ändert die Kante um **null**: gemessen ΔE 6,29 vorher wie nachher.
   Polster verschiebt den INHALT von der Kante weg — der Farbsprung bleibt
   an derselben Stelle derselbe. **„Luftiger" und „weicher" sind zwei
   Grössen**, und A beantwortet nur die erste. Beide werden gebraucht,
   deshalb steht A weiter oben und wird nicht ersetzt.

   ⛔ KEIN VERLAUF (Variante C). Er löst die Kante zwar vollständig auf
   (59 Stufen à ΔE 0,67), aber ein Verlauf an neun Bandkanten holt genau
   die Bauform zurück, die im Redesign entfernt wurde — `CLAUDE.md`,
   Visuelle Sprache: „Verläufe: keine".

   Gemessen, CIE76:

     heute       Weiss → Band                      ΔE 6,29   ein Sprung
     mit Stufe   Weiss → #f5f7f5 → Band       3,22 + 3,09   zwei fast gleiche

   ✅ Der Zwischenton hält die Untergrenze dort, wo sie gilt: **4,46 zu
   cream** und **8,63 zu parchment** (CIEDE2000 4,07 / 6,69). Das ist keine
   Formalie — auf dem Band liegt bei `kontakt` eine 520 px breite cream-Box,
   die Stufe steht also direkt daneben.
   ⛔ Die Regel „≥ 5,0 zu Weiss" gilt für sie NICHT und darf nicht auf sie
   angewandt werden: Die Regel sichert, dass ein BAND sichtbar ist. Eine
   Zwischenstufe soll dazwischenliegen; ihr Massstab ist „> 2, also
   sichtbar" und „kleiner als der Bandabstand". 3,22 erfüllt beides.

   ⚠️ `border`, nicht `linear-gradient` mit harten Stopps. Beides ergibt
   dasselbe Bild, aber ein Rahmen ist ein Rahmen — die Vokabel des
   Entwurfs — und niemand muss später prüfen, ob der Verlauf wirklich
   keiner ist.

   ✅ Die 24 px gehen in die Bandhöhe ein, und zwar bei JEDEM Band gleich.
   Ein konstanter Zuschlag auf alle Bänder **verkleinert** das Verhältnis
   zwischen grösstem und kleinstem — anders als das Polster, das nur zwei
   Bänder traf. Deshalb gilt die Stufe auf beiden Breiten, ohne Query.
   Gemessen nach dem Einbau: siehe unten am Ende des Blocks.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kostenvergleich"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__herstellung"],
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section[id$="__kombi"] {
  border-top: 24px solid var(--vbg-section-alt-step);
  border-bottom: 24px solid var(--vbg-section-alt-step);
}

/* ── Standard: rechte Spalte ──────────────────────────────────────────
   Neue Sections landen von selbst rechts — es gibt nichts nachzutragen.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > * {
  grid-column: 2;
  min-width: 0;
  padding-inline: 64px;
}

/* ── §3a und §3d aus PDP-45-PROZENT.md ───────────────────────────────
   ⛔ HIER STANDEN BIS ZUM 2026-08-03 DREI TOKEN-ÜBERSCHREIBUNGEN
   (`--vbg-section-padding: 0px`, `--vbg-container-padding: 0px`,
   `--vbg-container-max: none`). Sie waren kürzer, aber sie haben einen
   Defekt erzeugt, und zwar lautlos:

   `.vbg-hero__sticky-inner` in vbg-zpp-kauf.liquid liest
   `var(--vbg-container-max, 1200px)`. Die schwebende Kaufleiste ist
   `position: fixed`, bleibt aber DOM-Kind der Kaufspalte — sie erbt die
   Überschreibung. Gemessen: `max-width: none`, Inhalt auf **1408 px**
   statt zentriert bei 1200.

   Die Lehre ist allgemeiner als der Fall: Ein Token umzuwidmen wirkt auf
   JEDEN Leser im Teilbaum, auch auf den, den man nicht kennt — und
   `position: fixed` führt aus dem Layout heraus, nicht aus der Vererbung.
   Deshalb stehen die Polster jetzt an ihren zwei Verbrauchern statt am
   Token. Zwei Regeln statt drei Zeilen, aber greppbar und ohne Fernwirkung.
   ──────────────────────────────────────────────────────────────────── */
/* Die Wurzel jeder Section verliert ihr Sektionspolster. Selbe Form wie
   die Haarlinien-Regel in vbg-global.css — die Wurzeln sind direkte
   Kinder der .shopify-section, ausser bei den zwei Hero-Haelften, die
   eine .vbg-page dazwischen haben und ohnehin `padding: 0` tragen. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section > section,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section > .vbg-vn3,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section > .vbg-kv2-wrap {
  padding-block: 0;
}
/* Der Container polstert nicht länger GEGEN die Spaltenpolsterung:
   vorher 64 px Spalte + 48 px Container = 112 px je Seite von 648 px. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section .vbg-container {
  max-width: none;
  padding-inline: 0;
}
/* ── Abschnittsabstand ────────────────────────────────────────────────
   ⛔ 80 px statt der 48 des Entwurfs. BEWUSSTE ABWEICHUNG, 2026-08-03.

   Nachgezaehlt: der Entwurf gliedert seine neun Abschnittsbloecke
   ausschliesslich ueber `margin-top: 48px` — null Linien, null Flaechen.
   Genau das stand hier. Es traegt bei uns trotzdem nicht, und der Grund ist
   messbar: Die Bloecke des Entwurfs sind kurz, unsere sind 462 bis 1233 px
   hoch. Bei einem 200-px-Block sind 48 px ein Viertel der Blockhoehe; bei
   1233 px sind es vier Prozent. Derselbe absolute Wert leistet nicht
   dasselbe, wenn der Inhalt dreimal so hoch ist.

   ⛔ KEINE LINIEN. Die Messung „9 Bloecke, 0 Haarlinien" ist am 2026-08-03
   gegen die maszgebliche Datei gefuehrt worden und hat einen als „offen"
   notierten Mangel als Messfehler entlarvt. Sie wird nicht gegen einen
   ersten Eindruck aufgegeben. Reicht der Abstand nicht, ist die Linie eine
   ausdrueckliche Entscheidung — nicht der naechstliegende Griff. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section {
  margin-top: 80px;
}
/* Ueberschrift -> Inhalt: 24 px, an einer Stelle fuer alle sechs Abschnitte.
   ⚠️ Die sechs Ueberschriften heissen verschieden (`vbg-kv7-headline`,
   `vbg-vn3-headline`, `vbg-hs3-headline`, `vbg-ts2-headline`,
   `vbg-zeitplan-headline`, `vbg-kb3-headline`) und tragen ALLE
   `margin-bottom: 0` — der Abstand kam bisher vom Folgeelement, also aus
   sechs verschiedenen Regeln. Der Endungs-Selektor fasst sie zusammen; die
   zweite Zeile nimmt dem Nachbarn seinen Vorabstand, sonst addieren sich
   beide. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) [class$="-headline"] {
  margin-bottom: 24px;
}
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) [class$="-headline"] + * {
  margin-top: 0;
}
/* Erster Block der Spalte: kein Vorabstand. */
/* -- Feste Schriftgrade in der PDP-Spalte -----------------------------
   ENTSCHIEDEN 2026-08-03. `html { font-size: 118% }` (:2) vergroessert jeden
   `rem`-Wert um 18 %, mobil um 24 %. Der Entwurf ist aber auf FESTE px
   gezeichnet und rechnet gegen 16 px. Gemessen ueber vier Sections:

     Token            Sollwert   auf der PDP gerendert
     --vbg-text-xs      12 px         14,16 px
     --vbg-text-sm      14 px         16,52 px
     --vbg-text-base    16 px         18,88 px
     --vbg-text-2xl     32 px         37,76 px

   Jeder Wert exakt Faktor 1,18 - kein Einzelfehler, ein Systemfehler.

   Behoben durch Umdefinition der TOKEN in der Spalte, nicht durch das
   Umschreiben Hunderter Einzelwerte.

   WICHTIG - das ist NICHT die verbotene Token-Umwidmung vom 2026-08-03:
   dort bekam ein Token eine ZWEITE BEDEUTUNG (--vbg-section-padding: 0),
   hier behaelt es seine Bedeutung ("Schriftgrad sm") und nur die Einheit
   wechselt von rem auf px, damit die Root-Skalierung nicht durchschlaegt.
   Die Werte sind die Nennwerte der Skala aus vbg-tokens.css:70-77.

   Die 118 % bleiben unangetastet und gelten fuer alle uebrigen Seiten. Nur
   die PDP-Spalte rechnet fest - sie hat mit 520 px eine feste Breite, und
   eine viewport-abhaengige Vergroesserung gehoert dort nicht hin.

   Wer hier ein Token ergaenzt, ergaenzt es auch in vbg-tokens.css. Diese
   Liste ist eine Umrechnung, keine zweite Quelle. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) {
  --vbg-text-xs:   12px;
  --vbg-text-sm:   14px;
  --vbg-text-base: 16px;
  --vbg-text-md:   18px;
  --vbg-text-lg:   20px;
  --vbg-text-xl:   24px;
  --vbg-text-2xl:  32px;
  --vbg-text-3xl:  40px;
}

/* Dawns Ueberschriften-Regel blutete durch: base.css setzt
   `h1,h2,h3,h4,h5 { letter-spacing: calc(var(--font-heading-scale)*0.06rem) }`
   - gemessen 1,307 px an jeder vbg-zpp-Ueberschrift, weil keine der Sections
   `letter-spacing` selbst deklariert. Der Entwurf setzt dort nichts.
   Eine Regel an einer Stelle statt in acht Sections. */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) h1,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) h2,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) h3,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) h4,
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) h5 {
  letter-spacing: normal;
}

body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--kauf) {
  margin-top: 0;
  padding-top: 8px;
}
/* ⛔ Die Kaufspalte ist WEISS. Der Entwurf faerbt genau EINE Spalte, und das
   ist die Galerie links in `parchment` — die rechte ist weiss wie alle
   Abschnitte darunter.

   Gemessen am 2026-08-03, und der Befund war praeziser als die Vermutung: Es
   waren NICHT dieselben Farben. `.vbg-page` trug `cream` (rgb 245,240,232),
   die Galeriespalte `parchment` (rgb 237,231,217) — zwei benachbarte Toene.
   Genau deshalb ist es aufgefallen und nicht als Fehler zu sehen gewesen: Die
   Flaechen lesen als eine, die 55/45-Teilung verliert ihre Wirkung, und kein
   Test schlaegt an. Zwei fast gleiche Flaechen sind schlimmer als zwei
   gleiche — bei gleichen faellt sofort auf, dass eine zu viel ist.

   Die Cremeflaeche stammt aus `.vbg-page`, dem alten Hero-Grund. Sie hier
   abzuschalten trifft nur die Kaufspalte: der Selektor haengt an
   `:has(.vbg-hero--kauf)`, und die uebrigen `.vbg-page`-Wrapper im Theme
   bleiben unberuehrt. */
body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--kauf) > .vbg-page,
body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--kauf) .vbg-hero--kauf {
  background: var(--vbg-white);
}
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section:last-of-type {
  padding-bottom: 80px;
}
/* ⛔ Hier stand eine Ausnahme fuer `.vbg-kt2`, weil die Section ihr Polster
   hart per clamp() schrieb. Sie ist am 2026-08-03 mit dem Umbau entfallen:
   `.vbg-kt2` traegt jetzt `padding: 0` und der Kasten seinen Abstand als
   `margin-top`, wie jeder andere Abschnitt der Spalte.
   ⚠️ Die Ausnahme haette sonst als toter Selektor stehenbleiben koennen —
   `theme check` sieht so etwas nicht. Deshalb faellt sie im selben Schritt. */

/* ── Linke Spalte: die Galerie, sticky mit Anschlag ───────────────────
   ⛔ `grid-row: 1 / -1` greift hier NICHT. Negative Linien zählen nur im
   EXPLIZITEN Grid; alle Zeilen dieses Grids sind implizit, `-1` zeigt
   deshalb auf das Ende von Zeile 1. Das ist die Falle, an der die
   naheliegende Fassung scheitert.

   `span 24` überdeckt die 13 Zeilen der elf Templates mit Reserve. Die
   überzähligen Zeilen sind leer und `auto` hoch, also 0 px. Reißt es
   jemals, hört das Panel SICHTBAR auf zu spannen — kein stiller Fehler.
   `pdp-smoketest.mjs` wacht über die Sectionzahl.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--galerie) {
  grid-column: 1;
  grid-row: 1 / span 24;
  align-self: stretch;
  /* Der Entwurf hat GENAU EINE große Fläche, und das ist diese Spalte.
     Bis Teilstück 1 lag Parchment nur um das Bildpanel und darum herum
     ein Cream-Band über beide Hälften. Das Band fällt hier: der Entwurf
     kennt es nicht, und über die volle Seitenhöhe wäre es die falsche
     Fläche an der falschen Stelle (PDP-45-PROZENT.md §3b). */
  background: var(--vbg-parchment);
  padding-inline: 0;
  margin-top: 0;
  /* ⛔ Die Streckkette. `position: sticky` braucht einen Elternteil, der
     höher ist als das Element selbst — sonst ist der Klebeweg null und
     das Panel wandert mit. Zwischen Grid-Item und Panel liegen DREI
     Ebenen (`.vbg-page`, `.vbg-hero--galerie`, `.vbg-hero__half`), und
     jede muss die Höhe weitergeben. Flex statt `height: 100%`: eine
     Prozenthöhe zeigt auf die Padding-Box und verschiebt den Klebeweg um
     Kopf- und Fußpolster. */
  display: flex;
  flex-direction: column;
}
body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--galerie) > .vbg-page,
body.vbg-product-page #MainContent .vbg-hero--galerie {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
body.vbg-product-page #MainContent .vbg-hero__half--galerie {
  flex: 1 1 auto;
  min-height: 0;
}

/* ── Das Bildpanel ───────────────────────────────────────────────────
   Der Entwurf gibt der Spalte `height: 856px` FEST — bei 1440×920 ist das
   etwa Viewporthöhe. Eine feste Pixelhöhe ins Theme zu übernehmen wäre
   der falsche Teil der Vorgabe: sie stimmt nur für dieses Artboard.
   Übernommen wird ihre ABSICHT — das Panel bleibt in den sichtbaren
   Bereich eingepasst:

     max-height = Viewport − Header-Offset − 2 × 16 px Luft

   Ohne den Anschlag ragt das 1028 px hohe Panel auf kleineren Schirmen
   unten heraus, und weil `top` es oben festhält, wäre der untere Teil —
   Thumbnails und Beratungsbox — NIE erreichbar. Das ist der Fehler, den
   der Anschlag verhindert; er ist keine Feinjustierung.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__col-left {
  /* Die Fläche ist jetzt die Spalte, nicht das Panel. */
  background: none;
  position: sticky;
  /* ⚠️ `top` rechnet OHNE den USP-Streifen, der Anschlag darunter MIT —
     und das ist Absicht, nicht die Drift von vorhin. Gemessen: die feste
     Kopfzone endet bei 112 px (USP-Streifen 0–40 `fixed`, Navigation
     40–112). `--vbg-offset` ist 100 px, weil es eine 28 px hohe
     Ankündigungsleiste mitzählt, die derzeit nicht über der Navigation
     im Fluss steht. `offset + 16` = 116 setzt das Panel damit 4 px unter
     die Kopfzone — richtig. `--vbg-pdp-top + 16` wären 156 und damit ein
     sichtbarer 44-px-Spalt.
     ⛔ Das ist eine Folge der offenen Frage zum USP-Streifen
     (OFFEN.md 15d). Wird sie entschieden, gehören die beiden Zeilen
     zusammengeführt — bis dahin steht hier der gemessene Wert und nicht
     der rechnerisch schönere. */
  top: calc(var(--vbg-offset, 108px) + 16px);
  /* ── Der Anschlag ────────────────────────────────────────────────
     Rechnet gegen die volle Kopfzone, damit das Panel auch in seiner
     Ruhelage (y = --vbg-pdp-top) nicht unter die Falz ragt.

     ⛔ `height`, NICHT `max-height`. Zwei Gründe, und der zweite ist der
     technische:
       1. Der Entwurf gibt der Spalte ebenfalls eine feste Höhe (856 px).
       2. `max-height` allein macht die Höhe NICHT definit — und ohne
          definite Elternhöhe fällt jede Prozentangabe der Kinder auf
          `none` zurück. Genau daran ist `max-height: min(600px, 100%)`
          am Bild gescheitert: das Bild blieb bei 712 px in einer 472 px
          hohen Fläche. Erst eine definite Höhe macht die Rechnung im
          Inneren möglich.
     Preis: Bei Produkten ohne Thumbnails bleibt unten etwas Parchment
     frei. Der Entwurf nimmt denselben Preis in Kauf. */
  /* ⛔ Nach OBEN gedeckelt, seit 2026-08-03. Vorher wuchs das Panel unbegrenzt
     mit dem Viewport — und genau daraus entstand der gemeldete Leerraum.

     Der Mechanismus, gemessen an vier Fensterhoehen:

       Viewport   Panel   Bildflaeche   Bild   senkrechte Luft
       1440x700    568       252        252         0
       1440x920    788       472        472         0
       1440x1200  1068       752        600       152
       1512x1600  1468      1152        600       552

     Das Bild traegt `max-height: min(600px, 100%)`. Die 600 stammen aus dem
     Entwurf — dort ist das Panel FEST 856 px, die Bildflaeche also 568, und der
     Deckel greift NIE. Bei uns waechst die Flaeche mit dem Fenster; ab rund
     888 px Panelhoehe faengt der Deckel an zu binden, und alles darueber wird
     Leerraum. **Ein Sicherheitswert des Entwurfs ist zur wirksamen Schranke
     geworden, weil die Hoehenregel drumherum eine andere ist.**

     ⚠️ Auf 920 und 700 px war davon nichts zu sehen — beide Male 0 px Luft.
     Der Befund kam aus einem Screenshot, und er war richtig: bei 1512x1600
     misst das Panel 1468 px und die Luft 552. Wer nur zwei kurze Fensterhoehen
     prueft, prueft die Frage nicht.

     ⛔ Die 856 sind hier eine OBERGRENZE, nicht die feste Hoehe des Entwurfs.
     Das ist der Unterschied zu der Entscheidung, sie nicht zu uebernehmen: als
     feste Hoehe stimmt sie nur fuer das Artboard 1440x920, als Obergrenze sagt
     sie „nicht groesser werden, als der Entwurf zeigt". Damit ist die
     Bildflaeche hoechstens 568 px und der 600er-Deckel bindet wieder nie. */
  /* ⛔ DER 856-DECKEL IST GEFALLEN (2026-08-03). Er war der Entwurfswert
     fuer dessen Artboard 1440x920 und band ab 1080 px Fensterhoehe.
     Gemessen ueber vier Hoehen: bei 920 blieben 40 px unter der
     Beratungsbox, bei 1080 schon 132, bei 1200 252 und bei 1400
     **452 px** — rund ein Drittel der sichtbaren Spalte stand leer,
     waehrend das Bild darueber auf 572 px eingeschnuert blieb.
     ⚠️ Bei 920 war NICHTS zu sehen (Rest exakt 0). Eine Messung an einer
     Fensterhoehe ist hier keine Messung — der Defekt beginnt oberhalb. */
  /* ⛔ DIE SCHWEBENDE KAUFLEISTE WIRD ABGEZOGEN (2026-08-03).
     Befund des Auftraggebers: „Die Beratungsbox liegt teilweise unter der
     schwebenden Kaufleiste." Nachgemessen am gerenderten Dokument, an einer
     Scrollposition, an der die Leiste WIRKLICH ausgefahren ist
     (`translateY` ≈ 0 — bei y = 1200 ist sie noch um 75 px weggeschoben,
     dort misst man 0 Überdeckung und hält den Befund für falsch):

       Leiste          position: fixed, 69 px hoch, bündig am Fensterboden
       Beratungsbox    Unterkante 860 bei 900 px Fensterhöhe
       Leistenoberkante 831
       ------------------------------------------------------------
       Überdeckung     29 px — bei 900 UND bei 700 px Fensterhöhe gleich

     Die 32 px waren als Bodenabstand gedacht, aber die Leiste ist 69 hoch —
     der Abstand war nie für sie berechnet. Jetzt: Leistenhöhe + 32 px Luft.

     ⚠️ Die Höhe steht NICHT fest im Code. `--vbg-stickybar-h` wird von der
     Leisten-Logik in `vbg-zpp-kauf.liquid` aus `offsetHeight` gesetzt und bei
     `resize` nachgeführt. Grund: die Leiste wächst mit ihrem Inhalt — die
     anstehende Anhebung der Schriftgrade um 20 % macht sie höher, und ein
     hartkodiertes 69 wäre danach still falsch. Der Rückfallwert ist der
     gemessene Wert, damit die Regel auch ohne JS stimmt.

     ⚠️ Reserviert wird DAUERHAFT, nicht erst wenn die Leiste erscheint. Sie
     nur im eingeblendeten Zustand abzuziehen wäre sparsamer und würde beim
     Einblenden die halbe Spalte umbrechen — CLS an genau der Stelle, an der
     der Kunde liest.

     🚩 Dieselbe Bauform steht auf der Set-Seite (`.vbg-set__composition`,
     Zeile ~1769) neben `.vbg-set__bar`. Nicht mitgeändert — Phase 8. */
  height: calc(100vh - var(--vbg-pdp-top, 140px) - var(--vbg-stickybar-h, 69px) - 32px);
  min-height: 0;
}
/* ── Aufteilung INNERHALB des Anschlags, wie im Entwurf ───────────────
   Der Entwurf verteilt so: Bildfläche `flex:1; min-height:0`, Bild
   `max-height:600px; object-fit:contain`, darunter Thumbnails (72 px,
   `margin-top:24px`) und Beratungsbox (`margin-top:24px`).
   Nur die BILDFLÄCHE gibt nach. Thumbnails und Beratungsbox behalten
   ihre Höhe — sie sind der Grund, warum es den Anschlag gibt. */
body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img-el {
  /* ⛔ `max-height: 600px` allein war falsch. Der Entwurf kommt damit aus,
     weil seine Spalte 856 px hoch ist; mit dem Anschlag schrumpft die
     Bildfläche aber auf 472 px (bei 920 Viewport) oder 252 px (bei 700) —
     und ein 600 px hohes Bild ragte dann 128 px darüber hinaus.
     Gefunden von scripts/pdp-layout-check.mjs beim ersten Lauf, nicht vom
     Auge: im Screenshot sah der Stapel richtig aus, weil das Bild über den
     Thumbnails lag statt sie zu verschieben.
     `min(600px, 100%)` behält die Obergrenze des Entwurfs für große
     Schirme UND fügt sich in die geschrumpfte Fläche. */
  /* ⛔ Die 600 px des Entwurfs sind gefallen (2026-08-03) — derselbe Grund
     wie beim 856-Deckel der Spalte: Artboard-Werte, nicht unsere Geometrie.
     Solange die Spalte gedeckelt war, band die 600 nie. Ohne den Deckel
     haette sie das Bild bei jeder Fensterhoehe ueber 1080 kuenstlich klein
     gehalten, waehrend darunter Flaeche frei steht.
     `100%` genuegt: die Bildflaeche traegt `flex:1; min-height:0`, das Bild
     `object-fit: contain` — es fuellt die Hoehe und behaelt sein
     Verhaeltnis. */
  /* ⛔⛔ `width/height: auto` MIT Obergrenzen SKALIERT NIE HOCH — 2026-08-10,
     Auftraggeber: „Bekommen wir es auf dem Desktop hin, die Quadrate ausser
     der Flasche groesser darzustellen, dass sie genauso gross wie die
     Flasche sind?"

     Bei `auto` rendert ein Bild in seiner EIGENGROESSE; `max-width` und
     `max-height` koennen es nur verkleinern. Gemessen bei 1440 x 1200,
     Kasten 744 x 706:

         Flasche   Datei 640x1137  ->  zu hoch, max-height bindet  ->  397x706  ✅ fuellt
         Quadrate  Datei 640x 640  ->  passt hinein, nichts bindet ->  640x640  ⛔ 66 px Luft

     ⚠️ Die Ungleichheit haengt also NICHT am Rahmen und nicht am
     Seitenverhaeltnis, sondern daran, dass die eine Datei ZU GROSS und die
     andere ZU KLEIN fuer den Kasten ist. Ein Rahmen, den nur das groessere
     Bild ausfuellt, sieht aus wie zwei verschiedene Rahmen.

     Mit `100%/100%` fuellt das ELEMENT den Kasten und `object-fit: contain`
     macht die Passung — dieselbe Loesung wie mobil, aus demselben Grund. */
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: contain;
}
body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__thumbs,
body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__extras {
  flex: 0 0 auto;
}

/* Mobil hebt der Anschlag sich auf — dort ist nichts sticky, und ein
   eingepasstes Panel wäre nur eine Höhenbegrenzung ohne Zweck. */
@media (max-width: 1279px) {
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__col-left {
    position: static;
    /* Beide zurücksetzen. `height` ist mobil zwar wirkungslos, solange die
       Spalte `display: contents` trägt — aber ein Rücksetzer, der nur
       zufällig nicht gebraucht wird, ist keiner. */
    height: auto;
    max-height: none;
  }
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img {
    /* Seit dem 2026-08-06 die rechte Haelfte des Bildbands, nicht mehr das
       Band selbst. `flex: 1` statt `0 0 auto`, damit sie den Rest neben der
       Thumbnail-Spalte nimmt; `min-width: 0` gegen den Min-Content-Boden. */
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    /* ⛔ FESTE HOEHE, sonst SPRINGT DIE BILDFLAECHE BEIM DURCHKLICKEN.
       2026-08-09, Auftraggeber: „Bekommen wir die Slider-Bilder auf der PDP
       im Hero alle auf die gleiche Groesse, dass es nicht hin und her
       springt?"

       Gemessen bei 390 px, je Slide — der Kasten schrumpfte auf sein Bild:

           Freisteller  9:16   Bild 237x421   Kasten 342x421
           Maulpflege   1:1    Bild 342x342   Kasten 342x**342**
           Vorher-Nachher 4:5  Bild 337x421   Kasten 342x421
           Anwendung    1:1    Bild 342x342   Kasten 342x**342**

       **79 px Sprung**, je nachdem welche Slide gerade steht — und weil
       darunter die Kaufspalte folgt, wandert die halbe Seite mit.

       Die 421 sind nicht gegriffen: Es ist genau die Hoehe der senkrechten
       Thumbnail-Spalte daneben (33 + 5x68 + 4x12), die schon am `img-el`
       als `max-height` steht. Beide Haelften des Bandes sind damit gleich
       hoch, und zwar immer.

       ⚠️ AUF DEM DESKTOP IST NICHTS ZU TUN — dort misst der Kasten bereits
       bei JEDER Slide 744 x 506. Gemessen, nicht angenommen. Was dort
       wechselt, ist allein die Breite des Bildes IM Kasten (285 / 405 /
       506) — und das ist keine Layoutfrage, sondern eine der
       Seitenverhaeltnisse in den Dateien.

       ⛔ `min-height`, NICHT `height` — und das ist kein Geschmack, sondern
       gemessen: Der Kasten ist Flex-Item einer SPALTE und traegt `flex: 1`,
       also `flex-basis: 0%`. Auf der Hauptachse schlaegt die Flex-Basis
       jede `height`; mit `height: 421px` blieb der Kasten bei den
       quadratischen Slides weiter auf 342. Erst die Untergrenze bindet.

       📝 Und der Messfehler, der mich dabei fast in die falsche Richtung
       geschickt haette, gehoert dazu: Mein Pruefskript griff die
       Thumbnails mit `[class*="thumb"]` ab — das trifft auch den CONTAINER
       `.vbg-hero__thumbs`. Dadurch war die Zaehlung um eins verschoben, das
       Skript meldete sechs Thumbnails statt fuenf, und die Einzelmessung
       lag jedes Mal eine Slide daneben. Exakter Selektor, sonst misst man
       eine andere Slide als die, ueber die man urteilt. */
    min-height: 421px;
  }
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img-el {
    /* ⛔ 421 statt der bisherigen 300 — und die Zahl ist GERECHNET, nicht
       gegriffen: Sie ist die Hoehe, die die senkrechte Thumbnail-Spalte
       daneben braucht (33 Badge-Reserve + 5x68 + 4x12 = 421). Bild und
       Spalte sind gleich hoch, weil sie dieselbe Bandhoehe fuellen.
       Wer die Thumbnailgroesse aendert, zieht diesen Wert mit. */
    max-height: 421px;
    margin: 0 auto;
  }
}

/* ── Container Queries: der Boden dafür ──────────────────────────────
   Die zehn Abschnitte stehen jetzt in 45 % Breite, ihre
   Zusammenbruchregeln hängen aber an `@media` — und das misst den
   VIEWPORT, nicht die Spalte. Bei 1440 px greift keine einzige davon
   (PDP-45-PROZENT.md §1).

   `container-type: inline-size` macht jede rechte Section zu einem
   Abfragecontainer. Die Umstellung `@media` → `@container` geschieht
   je Section beim jeweiligen Umbau — sie ist NICHT mechanisch: der
   Entwurf hält `kraeuter` und `testimonials` bei 520 px ausdrücklich
   dreispaltig, ein blindes Umstellen würde sie einspaltig machen.

   ⛔ NICHT auf die zwei Hero-Hälften. `container-type` macht das
   Element zum Containing Block für `position: fixed` — die schwebende
   Kaufleiste (`.vbg-hero__sticky`, `position: fixed`) und die Lightbox
   hingen dann an der Section statt am Viewport.
   ──────────────────────────────────────────────────────────────────── */
body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section {
  container-type: inline-size;
  container-name: vbg-kaufspalte;
}
body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--galerie),
body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--kauf) {
  container-type: normal;
}

/* ══════════════════════════════════════════════════════════════════════
   Mobil — einspaltig, Bildband oben, Beratungsbox nach hinten
   ══════════════════════════════════════════════════════════════════════
   Der Entwurf hat für 390 px eine eigene Fassung: Bildband auf Parchment
   mit 24 px Polster und 300 px Bildhöhe, NICHT sticky, danach ein
   Textcontainer mit 24/20/40 px. Die Beratungsbox steht dort HINTER den
   Zahlungs-Pills („Drops PDP.dc.html:563"), nicht vor der Kaufspalte.

   Damit `order` sie dorthin bringen kann, muss sie ein Geschwister der
   Kaufspalte sein. Die vier Ebenen darüber lösen sich deshalb mobil per
   `display: contents` auf — was hier NICHTS kostet: Fläche und Sticky
   der Spalte will der Entwurf mobil ohnehin nicht. Genau deshalb ist es
   mobil das richtige Werkzeug und am Desktop das falsche.
   ────────────────────────────────────────────────────────────────────── */
@media (max-width: 1279px) {
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) {
    display: flex;
    flex-direction: column;
    /* ⛔ ZURÜCKSETZEN NICHT VERGESSEN. `align-items: start` steht in der
       Desktop-Regel und gilt hier weiter — im Grid heißt das „oben
       ausrichten", im Spalten-Flex aber „auf Inhaltsbreite schrumpfen".
       Folge: Die Abschnitte fielen auf nahezu null Breite zusammen
       (gemessen `grid-template-columns: 0px` bei faq und kombi, die
       Herstellungs-Stationen bei 12 px).

       ⚠️ Das war seit Teilstück 2 so und ist erst hier aufgefallen, weil
       meine Mobilprobe y-POSITIONEN gemessen hat und keine Breiten. Die
       Reihenfolge war richtig, die Höhen plausibel, der Überlauf null —
       und die Seite trotzdem unbenutzbar. Wer mobil prüft, misst
       Breiten. */
    align-items: stretch;
  }
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > *,
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .shopify-section {
    padding-inline: 20px;
    margin-top: 32px;
    /* ⚠️ Standard-Rang 4. `order: 1` allein reichte NICHT: es schob die
       Beratungsbox hinter JEDEN order-0-Kasten, also hinter alle zehn
       Abschnitte statt nur hinter die Kaufspalte (gemessen Beratung@33637
       am Seitenende). Der Entwurf hat sie direkt hinter den
       Zahlungs-Pills — dafür braucht es fünf Ränge, nicht zwei. */
    order: 4;
  }
  /* 0 Breadcrumbs · 1 Bild und Thumbnails · 2 Kaufspalte · 3 Beratung ·
     4 alle Abschnitte */
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) > .vbg-breadcrumbs {
    order: 0;
    /* ⛔ Kein Vorabstand am ERSTEN Element. Die 32 px aus der Regel darüber
       addierten sich mobil auf das Seitenpolster und rissen ein 80 px hohes
       Loch zwischen Kopfzone (Unterkante 92 px) und Breadcrumbs (172 px).
       Im Screenshot war es die auffälligste Stelle der ganzen Seite. */
    margin-top: 0;
  }
  body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--kauf) {
    order: 2;
  }
  /* ⛔ FÜNF Ebenen, nicht vier. Der erste Versuch übersprang `.vbg-page`
     zwischen `.shopify-section` und `.vbg-hero--galerie` — die Kette riss
     dort, die Kinder blieben Enkel, und `order` war folgenlos: die
     Beratungsbox stand weiter vor der Kaufspalte (gemessen Beratung@858
     vor Eyebrow@1036). `display: contents` muss LÜCKENLOS sein, eine
     einzige übersprungene Ebene macht die ganze Kette wirkungslos. */
  body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--galerie),
  body.vbg-product-page #MainContent > .shopify-section:has(.vbg-hero--galerie) > .vbg-page,
  body.vbg-product-page #MainContent .vbg-hero--galerie,
  body.vbg-product-page #MainContent .vbg-hero--galerie > .vbg-hero__half--galerie,
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__col-left {
    display: contents;
  }
  /* ⚠️ Diese Regeln brauchen den ID-Selektor. Ohne ihn gewinnt
     `#MainContent:has(…) > *` mit seiner höheren Spezifität und legt
     20 px Innenabstand über das Bildband. */

  /* ── Bildband: Thumbnails WIEDER UNTER DEM BILD (2026-08-07) ─────────
     Auftraggeber: „die Bilder statt links vertikal unter dem Bild
     horizontal, aber kleiner dass sie nicht so viel Platz wegnehmen. Aber
     alles noch in der Creme Sektion. Das Hauptbild soll wieder mittig
     zentral sitzen nicht wie jetzt leicht rechts."

     ⛔ DIE SEITENSTELLUNG VOM 2026-08-06 IST DAMIT ZURÜCKGENOMMEN — und der
     Grund, aus dem sie entstand, ist mit einer Zahl gelöst statt mit einer
     Anordnung. Damals: fünf Kacheln à 72 px brauchten 5×72 + 4×12 = **408 px**
     bei 350 verfügbaren, die Reihe brach also zweizeilig um. Deshalb ging
     sie nach links.

     Jetzt: Kachel **56 px**, Fuge 10 → 5×56 + 4×10 = **320 px** bei
     342 verfügbaren (390 − 2×24 Bandpolster). Es passt, mit 22 px Luft.
     ⚠️ SECHS Kacheln bräuchten 6×56 + 5×10 = 386 und passen NICHT — die
     Schleife lässt `limit: 6` zu. Deshalb ist die Reihe waagerecht
     scrollbar statt umbrechend: Ein Umbruch verdoppelte die Höhe still,
     ein Scrollbereich zeigt seine Grenze. Heute hat nur das Dental-Spray
     mehr als ein Medium, aber ein Produktbild mehr wäre sonst ein Defekt
     ohne Warnung — derselbe Satz stand schon am alten `max-height`.

     ✅ DAS HAUPTBILD STEHT DAMIT VON SELBST MITTIG. Es sass „leicht rechts",
     weil die 68-px-Thumbnailspalte links Platz nahm und das Bild den Rest
     füllte. Es war kein Zentrierungsfehler, sondern die Folge der
     Seitenstellung — deshalb braucht es hier keine eigene Regel.

     ⛔ DIE FLÄCHE BLEIBT PARCHMENT und umschliesst weiterhin BEIDES
     („alles noch in der Creme Sektion"). Die Entscheidung vom 2026-08-06,
     dass die Thumbnails IM Band stehen statt darunter auf Weiss, gilt
     unverändert — sie hing nie an der Richtung der Leiste. */
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__bildband {
    display: flex;
    flex-direction: column;
    gap: 16px;
    align-items: stretch;
    background: var(--vbg-parchment);
    /* ⛔ 24 → 52 px OBEN, 2026-08-10 (Auftraggeber: „dass das bestseller Label
       dort überlappt ist nicht ganz so schön").

       ══ WARUM ES ÜBERLAPPTE ══════════════════════════════════════════
       Das Schild ist `position: absolute` und steht unten auf `top: 12px`
       im Bezugsrahmen dieses Bandes. Seine eigene Höhe ist aber grösser
       als die 12 px Vorlauf plus die 24 px Bandpolster:

         bis 768 px   Schild 23 px hoch  ->  Unterkante bei 35
         ab  769 px   Schild 31 px hoch  ->  Unterkante bei 43
         Bildoberkante lag beidemal bei  24

       Es ragte damit 11 bzw. 19 px in das Bild — und ausgerechnet die
       Vorher-Nachher-Tafeln tragen dort ihre Überschrift.

       ⛔ DIE KOPFRESERVE STAND SCHON EINMAL IM CODE. Der Kommentar zwei
       Blöcke tiefer nennt sie ausdrücklich („Die Spalte bekommt 33 px
       Kopfreserve, 25 Label + 8 Luft"). Sie ist beim Umbau vom 2026-08-07
       gefallen, als die Thumbnails unter das Bild wanderten und die Spalte
       auf `display: contents` ging — der Kommentar blieb, die Zahl nicht.
       **Ein Kommentar ohne die Regel, die er erklärt, ist eine Fussnote auf
       eine gelöschte Seite.**

       52 = 12 Vorlauf + 31 Schildhöhe + 9 Luft. Der grössere der beiden
       Fälle bestimmt den Wert; unter 768 px bleiben dadurch 17 px Luft
       statt 9. Eine zweite Zahl für den kleinen Fall wäre genauer und
       müsste bei jeder Schriftänderung mitgezogen werden. */
    padding: 52px 24px 24px;
    margin: 0 0 0;
    order: 1;
    /* ⛔ Bezugsrahmen für das BESTSELLER-Label, siehe unten. */
    position: relative;
  }
  /* ⛔ DAS LABEL IST ABSOLUT UND NIMMT KEINEN PLATZ IM FLUSS. Es stünde
     deshalb nicht ÜBER der neuen Spalte, sondern LÄGE DARAUF: gemessen
     94,7 × 25 px bei x 12–106,7 / y 108–133, die Spalte beginnt bei
     x 24 und y 120.

     Zwei Eingriffe, beide nötig:
     (1) Der Bezugsrahmen wandert von `.vbg-hero__img` auf das Band.
         Ohne das setzt `left: 12` das Label an den linken Rand der
         BILDHÄLFTE — also neben das Bild statt über die Spalte.
     (2) Die Spalte bekommt 33 px Kopfreserve (25 Label + 8 Luft). */
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img {
    background: none;
    padding: 0;
    margin: 0;
    position: static;
  }
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__badge {
    top: 12px;
    /* ⛔ 12 → 24 px, damit das Schild mit der LINKEN BILDKANTE fluchtet.
       Bei 12 stand es 12 px weiter links als das Bild darunter — im
       Bandpolster, aber ohne Bezug zu irgendetwas. Am Desktop steht es auf
       `left: 0` relativ zum Bild, also bündig; 24 ist hier dasselbe, nur
       gegen den anderen Bezugsrahmen gerechnet. */
    left: 24px;
  }
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__thumbs {
    /* `order` gefallen: Die Leiste steht wieder an ihrer Markup-Stelle,
       also UNTER dem Bild. Eine Umsortierung, die die Markup-Reihenfolge
       wiederherstellt, ist keine Umsortierung — sie ist eine Zeile, die
       beim nächsten Lesen nach Absicht aussieht. */
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    width: auto;
    gap: 10px;
    padding: 0;
    margin: 0;
    /* ⛔ Waagerecht scrollbar statt umbrechend — Begründung am Bildband
       darüber: Ein Umbruch verdoppelt die Höhe still, ein Scrollbereich
       zeigt seine Grenze. Die Leiste selbst bleibt unsichtbar. */
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* ⚠️ `justify-content: center` und `overflow-x` schliessen sich aus,
       sobald der Inhalt überläuft: Zentrierter Überlauf ist links NICHT
       erreichbar (der Anfang liegt vor scrollLeft 0). `safe center` löst
       genau das — es zentriert nur, solange Platz ist, und fällt sonst auf
       `start` zurück. Ohne das wären bei sechs Bildern die ersten Kacheln
       unerreichbar. */
    justify-content: safe center;
  }
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__thumbs::-webkit-scrollbar {
    display: none;
  }
  /* ⛔ 68 → 56 px. Die Zahl ist gerechnet, nicht gerundet: verfügbar sind
     342 px (390 − 2×24 Bandpolster), fünf Kacheln mit vier Fugen à 10 px
     ergeben 5×56 + 4×10 = 320. Bei 60 px wären es 340 — rechnerisch noch
     drin und praktisch ohne Luft; bei 64 px läuft es mit 356 über.
     ⚠️ Das Polster fällt von 6 auf 4 px mit: Bei 56 px Kante blieben sonst
     44 px für das Bild, und ein Freisteller mit viel Weissraum wäre darin
     kaum noch zu erkennen. */
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__thumb {
    width: 56px;
    height: 56px;
    padding: 4px;
    flex: 0 0 56px;
  }
  /* Hinter die Kaufspalte, wie im Entwurf. */
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__extras {
    order: 3;
    padding-inline: 20px;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   MOBIL — die Bildflaeche ist QUADRATISCH
   ══════════════════════════════════════════════════════════════════════
   2026-08-10, Auftraggeber: „Ich will auf mobil die Bildgroesse quadratisch
   verwenden wie Bild 2 und 5 bereits sind, und dass dann fuer alle" —
   nachgeschoben: „aber nur auf mobil, auf Desktop ist das nicht so strikt."

   Ausgangslage, bei 390 px je Slide gemessen (Dental-Spray, fuenf Slides):

       1  Freisteller     585x1040  0,563   Bild 237x421
       2  Maulpflege      585x 585  1,000   Bild 342x342   ← quadratisch
       3  Vorher-Nachher  585x 731  0,800   Bild 337x421
       4  Anwendung       585x 731  0,800   Bild 337x421
       5  Anwendung 03    585x 585  1,000   Bild 342x342   ← quadratisch

   Der KASTEN stand seit dem 2026-08-09 fest auf 342x421 und sprang nicht
   mehr; ungleich waren die BILDER darin. Zwei von fuenf fuellen die Flaeche,
   drei stehen als hoher Streifen darin.

   ⛔ `object-fit: contain` bleibt — es wird NICHT beschnitten. Der Kasten
   wird quadratisch, das Bild behaelt sein Verhaeltnis. Ein `cover` haette
   alle fuenf Bilder formatfuellend gemacht und dabei den Freisteller
   (9:16) auf sein mittleres Drittel beschnitten: von der Flasche waere
   weder Kopf noch Boden zu sehen. Uniformitaet ist das Ziel, nicht der
   Beschnitt.

   ⛔ `flex: 0 0 auto` ist Pflicht, nicht Stil. Der Kasten ist Flex-Item
   einer SPALTE und trug `flex: 1`, also `flex-basis: 0%`. Auf der
   Hauptachse — hier die Hoehe — schlaegt die Flex-Basis jede aus
   `aspect-ratio` abgeleitete Groesse; die Regel waere still wirkungslos
   geblieben. Derselbe Bau wie beim `height: 421px`, das am 2026-08-09
   nicht griff und durch `min-height` ersetzt werden musste.

   ⚠️ Die Obergrenze 421 px ist der Ruecksetzer nach oben: Bei 768 px waere
   das Band 720 px breit und ein Quadrat damit 720 px hoch. Die Grenze
   haelt den Kasten dort auf der bisherigen Hoehe — genau das „auf Desktop
   nicht so strikt". Bei 390 px bindet sie nicht (342 < 421).

   ⛔⛔ DEFINITE LAENGE, NICHT `aspect-ratio` — und das ist eine Korrektur,
   keine Vorliebe. Die erste Fassung stand auf

       .vbg-hero__img    { aspect-ratio: 1 / 1; max-height: 421px }
       .vbg-hero__img-el { width: auto; height: auto;
                           max-width: 100%; max-height: 100% }

   und war in Chromium nachweislich richtig: Kasten 342x342, Bild 192x342.
   Der Auftraggeber sah am Telefon eine Flasche, die „fast aus der Sektion
   raus" ragt.

   Der Grund ist die Kette aus zwei Prozentwerten: Die Hoehe des Kastens
   entsteht erst aus `aspect-ratio`, und `max-height: 100%` am Bild muss
   sich gegen genau diese abgeleitete Hoehe aufloesen. Wo eine Maschine das
   als UNBESTIMMT behandelt, faellt die Obergrenze weg — dann bindet nur
   noch `max-width: 100%`, das Bild wird 342 breit und bei 0,563 satte
   608 px hoch, und weil der Kasten `align-items: center` traegt, haengt es
   oben UND unten heraus.

   ⛔ Und das ist der Beleg, dass es diese Kette ist und nicht etwas
   anderes: BETROFFEN WAERE NUR SLIDE 1. Die vier quadratischen Dateien
   rechnen bei `max-width: 100%` auf 342 x 342 und passen zufaellig genau —
   sie koennen gar nicht ueberlaufen. Beanstandet wurde genau die eine
   Slide, die nicht quadratisch ist.

   ⚠️ Nachgemessen werden konnte es hier NICHT: In dieser Umgebung liegt
   nur Chromium, kein WebKit. Die Fassung unten ist deshalb so gebaut, dass
   sie UNABHAENGIG von der Ursache nicht ueberlaufen kann — die Hoehe ist
   eine ausgerechnete Laenge, und das Bild fuellt den Kasten mit
   `object-fit: contain` statt ueber Obergrenzen.

   📝 Die 48 px sind das Bandpolster (2 x 24 aus `.vbg-hero__bildband`),
   nachgeprueft: keine feinere Query aendert es. Wer das Polster anfasst,
   zieht diesen Wert mit.
   ────────────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img {
    flex: 0 0 auto;
    min-height: 0;
    height: min(calc(100vw - 48px), 421px);
  }
  body.vbg-product-page #MainContent .vbg-hero--galerie .vbg-hero__img-el {
    /* Kasten voll ausfuellen und das Verhaeltnis `contain` ueberlassen.
       ⛔ Die zwei Obergrenzen sind ausdruecklich zurueckgesetzt: Sie waren
       der Weg, auf dem der Ueberlauf entstehen konnte. */
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    object-fit: contain;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   SET-SEITE — das Seitengrid (Phase 8, Teilstück 1, 2026-08-03)
   ══════════════════════════════════════════════════════════════════════
   Der Entwurf `design-reference/Set-Produktseite.dc.html` Z. 31–49 setzt
   denselben 55/45-Aufbau wie die PDP (Entscheidung A2): links 55 % sticky
   auf Parchment mit der Set-Komposition, rechts 45 % mit ALLEN Abschnitten.

   ⛔ ZWEITER WÄCHTER, NICHT VERALLGEMEINERTER.
   Die PDP-Regeln oben wachen über `:has(.vbg-hero--galerie)`. Dieser Block
   wacht über `body.vbg-tpl-set` — die Klasse, die `layout/theme.liquid:808`
   aus `template.suffix` bildet. Beides nebeneinander ist Absicht:
   `body.vbg-product-page` tragen AUCH `product.json`, das GemPages-Template
   und `product.ARCHIV.gras-kot`, und keines von beiden hat zwei Spalten zu
   füllen. Wer die zwei Wächter zu einem verallgemeinert, bricht drei
   Templates auf einmal (SET-HERO-BESTAND-2026-08-03.md §3.a, Folgerung 3).

   ⚠️ ANDERS ALS DIE PDP BRAUCHT DIE SET-SEITE KEINE TEILUNG.
   Die PDP musste in `vbg-zpp-galerie` und `vbg-zpp-kauf` zerlegt werden,
   weil ihre Abschnitte GESCHWISTER-Sections sind und erst als solche
   Grid-Items werden. Die Set-Seite besteht aus EINER Section — das Grid
   sitzt deshalb auf ihrer eigenen Wurzel, und `#MainContent` bleibt
   unangetastet. Kein `display: contents`, keine Streckkette.
   ────────────────────────────────────────────────────────────────────── */
body.vbg-tpl-set .vbg-set {
  display: grid;
  grid-template-columns: 55fr 45fr;
  align-items: start;
  /* Dieselbe Größe wie auf der PDP, derselbe Grund: sie hat zwei Leser
     (Flusspolster hier, Anschlag der linken Spalte unten) und die dürfen
     nicht getrennt dastehen. */
  --vbg-pdp-top: var(--vbg-offset, 108px);
  /* ⛔ KEIN Abstand oben und unten (2026-08-05, `OFFEN.md` 69).
     Gemessen standen dort **je 100 px Weiss**: oben aus `padding-top` hier,
     unten aus `.vbg-section-white` in `vbg-global.css` (die trägt
     `padding: var(--vbg-section-padding) 0`). Die Fläche begann deshalb
     sichtbar unter der Kopfzeile und endete vor dem Seitenende.

     ⚠️ **Die Kaufspalte rutscht damit 100 px nach oben, und das ist der
     eigentliche Inhalt der Entscheidung** — nicht ein Nebeneffekt. Sie
     startet jetzt mit ihren eigenen 56 px unter der festen Kopfzone.
     Ausdrücklich so gewollt (Auftraggeber).

     ⛔ `padding-block` überschreibt hier LOKAL. `vbg-global.css` bleibt
     unangetastet: Dieselbe Regel trägt jede weisse Section im Theme; wer
     sie dort ändert, ändert den Rhythmus des ganzen Shops. Spezifität
     0,2,1 gegen 0,1,0 — die lokale gewinnt ohne `!important`. */
  padding-block: 0;
}
/* ⚠️ `1fr` ist `minmax(auto, 1fr)` und weicht dem Min-Content aus. In einer
   festbreiten Spalte erzeugt das ungleiche Spuren — auf der PDP gemessen
   (kraeuter 175/196/176 statt 3× 165,3). Gilt für JEDES Raster hier drin. */
body.vbg-tpl-set .vbg-set > * { min-width: 0; }

/* ── Linke Spalte: die Komposition ──────────────────────────────────────
   ⛔ UMGEBAUT AM 2026-08-05 — die Fläche läuft jetzt DURCH, und das Kleben
   ist eine Ebene tiefer gewandert (`OFFEN.md` 61 Weg A, 68, 69 in einem
   Schritt).

   **Der Zustand davor und warum er nicht zu retten war:** Fläche und
   klebendes Element waren dasselbe Div. Es endete nach 768 px, während die
   Kaufspalte 1620 px lang ist — darunter standen **852 px leeres Weiss**.
   Die Fläche zu verlängern hätte das Kleben aufgehoben (nichts mehr, was
   sich verschieben kann), das Kleben zu behalten hätte die Leere gelassen.
   **Durchlaufen und Kleben schliessen sich aus — solange es EIN Element
   ist.** Zwei Elemente lösen es ohne Zielkonflikt.

   ⛔ MITGEFALLEN, beides bewusst:

   `max-height: 856px` — **war ein toter Wert** (`OFFEN.md` 68). `min-height`
   schlägt `max-height`; bei 1440 × 1080 war die Fläche gemessen **948 px**
   hoch, also 92 über dem angeblichen Deckel. Ab rund 988 px Viewporthöhe
   hat die Zeile nie gewirkt. ⚠️ Sie **dokumentierte** die Absicht („die
   feste Höhe des Entwurfs nicht erben") und **setzte sie nicht durch** —
   gefährlicher als eine fehlende Zeile, weil man ihr glaubt.

   `min-height: calc(100vh …)` — hatte nur Sinn, solange die Fläche selbst
   klebte. Jetzt ergibt sich ihre Höhe aus der Grid-Zeile.

   ⚠️ `align-self: stretch` ist nicht Kosmetik: Das Grid trägt
   `align-items: start` (weiter oben, für die Kaufspalte richtig). Ohne die
   Ausnahme bliebe die Fläche auf Inhaltshöhe und der ganze Umbau wäre
   wirkungslos — dieselbe Falle wie beim mobilen Zusammenfall der PDP. */
body.vbg-tpl-set .vbg-set__composition {
  background: var(--vbg-parchment);
  align-self: stretch;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}
/* Das klebende Element — trägt KEINE Fläche, nur die Produkte.
   `top` wie zuvor die Fläche: `--vbg-offset` zählt eine Ankündigungsleiste
   mit, die nicht im Fluss über der Navigation steht; `offset + 16` setzt es
   4 px unter die feste Kopfzone.
   ⛔ Der Rand sitzt HIER, nicht an der Fläche: Er soll die Produkte von der
   Kopfzone abrücken, nicht die Fläche von der Section — die soll ja
   randlos durchlaufen. 40 → 24 px (Auftraggeber), damit die Bilder mehr
   Breite bekommen. **Rand 0 ausdrücklich nicht**: der eingebrannte
   Schlagschatten rückte sonst an die Kante (`OFFEN.md` 62). */
body.vbg-tpl-set .vbg-set__compo-sticky {
  position: sticky;
  top: calc(var(--vbg-offset, 108px) + 16px);
  padding: 24px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* ⛔ `min-height` UND `max-height` auf denselben Wert — beide nötig, aus
     zwei verschiedenen Gründen, und das eine ohne das andere ist falsch:

     `max-height` hält das Klebende im Viewport. Ohne sie klebte ein Element,
     dessen Unterkante nie erreicht wird — die unteren Produkte blieben bei
     kleinen Bildschirmen unsichtbar.

     `min-height` ist es, die die Produkte MITTIG stellt. Ohne sie ist das
     Element nur so hoch wie sein Inhalt, `justify-content: center` hat
     nichts zu zentrieren, und die Komposition klebt am oberen Rand der
     Fläche — bei 1620 px Flächenhöhe sass sie ganz oben und darunter
     standen 900 px leere Fläche. Der Entwurf zeigt sie in der MITTE.
     ⚠️ Genau das war am ersten Messlauf nach dem Umbau zu sehen und an den
     Zahlen NICHT: Fläche 792 × 1620, Überlauf 0, Weissraum 0 — alle drei
     Werte richtig, und das Bild trotzdem falsch. */
  min-height: calc(100vh - var(--vbg-offset, 108px) - 32px);
  max-height: calc(100vh - var(--vbg-offset, 108px) - 32px);
}
/* ⛔ KEIN `container-type` auf dieser Spalte. Es macht das Element zum
   Containing Block für `position: fixed` — die schwebende Kaufleiste hinge
   dann an der Section statt am Viewport. Auf der PDP gemessen. */

/* ⛔ ZUR LEEREN FLÄCHE — SIE IST DIE KOMPOSITION DES ENTWURFS.
   Gemessen am 2026-08-05, weil „die Komposition nutzt ihre Fläche nicht"
   als Mangel gemeldet war:

     Entwurf   zwei Produkte à 280 + gap 24 + Plus ≈ 614 × 390
               in 712 × 776 Innenraum          →  rund 43 % belegt
     Theme     dieselbe Anordnung              →       44 % belegt

   **Der Entwurf füllt seine Fläche selbst nicht.** Die grosse, ruhige
   parchment-Fläche mit einer kleinen zentrierten Komposition darin IST der
   gezeichnete Zustand — kein Umsetzungsfehler und keine Lücke.

   ⛔ Wer sie später „behebt", entscheidet damit GEGEN den Entwurf. Das ist
   erlaubt (der Flächenwechsel der PDP war genau so eine Entscheidung), aber
   es ist eine Entscheidung und keine Korrektur — und sie gehört als solche
   aufgeschrieben, sonst gilt sie beim nächsten Entwurfsabgleich als Fehler
   und wird zurückgedreht.

   ⚠️ Voraussetzung dafür ist ausserdem Bildarbeit, nicht CSS: Die Beutel
   tragen einen eingebrannten Schlagschatten (18 % halbtransparente Fläche,
   rgb(5,4,3)), das Spray nutzt 40 % seiner Dateibreite. Vergrössern
   skaliert beides mit. `OFFEN.md` 62.
   ──────────────────────────────────────────────────────────────────── */

/* ── Die Komposition: NEBENEINANDER, wie im Entwurf ──────────────────
   ⛔ Die Kinder der Komposition hatten bis zum 2026-08-05 GAR KEIN CSS.
   `.vbg-set__compo-row` war damit ein `display: block`, und die Produkte
   standen untereinander — bei zwei Produkten 812 px hoch in einer Spalte
   mit 688 px Innenraum, also 22 px sichtbarer Überstand.

   Der Entwurf führt dort (Set-Produktseite.dc.html):

     <div style="display:flex;align-items:center;justify-content:center;gap:24px">
       <div style="text-align:center;width:280px">  …Produkt…
       <div style="…font-size:44px;color:var(--vbg-warm-gray);flex:none">+
       <div style="text-align:center;width:280px">  …Produkt…

   ⛔ Das `+` war deshalb keine eigene Baustelle, sondern eine Folge: Als
   Kind eines Blocks nahm es die volle Spaltenbreite (712 px) ein und stand
   als eigene Zeile zwischen den Bildern statt zwischen ihnen. **Erst die
   Reihe erklärt das Zeichen** — im Entwurf ist es ein 44-px-Display-Plus
   in warm-gray, das zwei nebeneinanderstehende Produkte verbindet.

   ⚠️ `flex: 0 1 280px` statt `width: 280px`: Der Entwurf zeigt zwei
   Produkte, das Theme hat auch Sets mit DREI (`aktiv-gesund-komplett-set`).
   Bei drei festen 280ern wären es 840 px + Lücken in 712 px Innenraum —
   sie müssen schrumpfen dürfen. `min-width: 0` dazu, sonst weicht ein
   Flex-Item dem Min-Content aus (dieselbe Falle wie beim PDP-Raster).

   ⚠️ `height: auto` am Bild ist Pflicht, nicht Kosmetik: Das `<img>` trägt
   `width="280" height="340"` als Attribute. Ohne `height: auto` zieht das
   Attribut es auf feste Pixelhöhe, sobald `max-width` greift. */
body.vbg-tpl-set .vbg-set__compo-row {
  display: flex;
  /* ⛔ `stretch`, NICHT `center` — geändert am 2026-08-05.
     Mit `align-items: center` wird jedes Produkt als GANZES zentriert. Weil
     die Freisteller verschiedene Seitenverhältnisse haben (Spray 1080×1920,
     Beutel 1414×2000), landeten die Bildunterschriften auf verschiedenen
     Höhen — im Zweier- wie im Dreier-Set sichtbar.
     ⚠️ Der Entwurf führt dasselbe `align-items:center`, aber Bilder
     ähnlicher Höhe. **Dieselbe Regel, andere Bilder, anderes Ergebnis** —
     die Vorgabe ist nicht falsch abgeschrieben, ihre Voraussetzung fehlt.

     ⛔ ÜBERHOLT am 2026-08-05, als die Unterschriften fielen: Die Begründung
     oben nennt die Unterschriften als Grund — **die gibt es nicht mehr**.
     Es steht jetzt `flex-end`, und die Grundlinie liegt HIER statt am
     Bildfeld. Warum an dieser Stelle und nicht dort, steht beim Bildfeld.
     ⚠️ Die Maße in der Begründung waren ausserdem die 680er-Rendition, nicht
     die Datei — mitkorrigiert, `OFFEN.md` 62. */
  align-items: flex-end;
  justify-content: center;
  gap: 24px;
  width: 100%;
}
body.vbg-tpl-set .vbg-set__compo-item {
  /* 280 → 400 (2026-08-05). Der alte Wert war der Entwurfswert und zugleich
     das Attribut am `<img>`; beide sind gefallen. `0 1` heisst weiterhin:
     nicht wachsen, aber schrumpfen dürfen — bei drei Produkten bindet die
     Breite, und ohne Schrumpfen liefe die Reihe über. */
  flex: 0 1 400px;
  min-width: 0;
  text-align: center;
}
body.vbg-tpl-set .vbg-set__compo-item {
  display: flex;
  flex-direction: column;
}
/* ⛔ DIE FESTE BILDFELDHÖHE IST GEFALLEN (2026-08-05) — `height: 340px`.
   Sie war der Wert des Entwurfs und brachte die Bildunterschriften auf eine
   Linie. Die Unterschriften sind weg; damit hatte die Höhe keine Aufgabe
   mehr — **aber sie richtete weiter aus**, und zwar falsch:

   Bei 390 px ist das Bild 223 px hoch. In einem Feld von 340 blieben oben
   117 px leer, das Bild schlug unten an, und das Verbindungszeichen stand
   auf FELDmitte — also 59 px über den Produkten, sichtbar neben der
   Spraykappe statt zwischen den Produkten. Auf dem Desktop-Dreier
   dieselbe Bauform, kleiner: 24 bis 53 px.

   ⚠️ Die Falle war, dass die Höhe im Zweier UNAUFFÄLLIG ist: Dort füllen
   beide Bilder das Feld exakt aus (340 von 340), Zeichen- und Bildmitte
   fallen auf denselben Wert. Der Fehler zeigt sich nur, wo die BREITE
   bindet — also mobil und im Dreier. **Eine Messung am Zweier allein hätte
   ihn nie gefunden.**

   ✅ Die Obergrenze gehört ans Bild (`max-height`), die Grundlinie an die
   REIHE (`align-items: flex-end` oben). Dann ist das Feld so hoch wie sein
   Bild, die Bilder stehen auf einer Kante, und `align-self: center` am
   Zeichen trifft die Bildmitte statt einer leeren Feldmitte.

   ⚠️ ABER — DER PUNKT, DER NICHT ALS ERLEDIGT GELESEN WERDEN DARF:
   `flex-end` richtet die BILDER aus, nicht die PRODUKTE. Der Schlagschatten
   steckt in der Datei und ragt beim Beutel 20,5 % der Dateihöhe unter das
   Produkt, beim Spray 2,1 % (`OFFEN.md` 62). Die Dateiunterkante ist nicht
   die Produktunterkante. Am Dreier gemessen, Versatz in px:

                        Bildkanten   PRODUKTkanten
       center (vorher)      29            71
       flex-end (jetzt)      0            42     ← besser, nicht gelöst

   ⛔ Die 0 in der ersten Spalte ist genau die Zahl, die eine Fertigmeldung
   nahelegt — und sie beantwortet die falsche Frage. Die Reihe steht
   ausgerichtet, wenn man die Dateien misst, und um 42 px versetzt, wenn man
   die Produkte misst. **Vollständig gelöst ist es erst, wenn der Schatten
   aus den Dateien ist.**
   ✅ Der Zweier steht bei 0/0 — beide Beutel teilen dieselbe
   Datei-Geometrie. Der Befund betrifft nur gemischte Sets. */
body.vbg-tpl-set .vbg-set__compo-figure {
  flex: none;
  display: flex;
  justify-content: center;
}
/* ⛔ `width: 100%` STATT `max-width: 100%` — das ist der eigentliche Eingriff
   am 2026-08-05, und er sieht nach nichts aus.

   Mit `max-width` und `height: auto` ist die VERWENDETE Breite die
   intrinsische, und die kam aus dem Attribut `width="280"`. Das Bild wurde
   deshalb **nie breiter als 280 px**, gleichgültig wie viel Platz da war.
   ⚠️ Kein CSS hat das je aufgehoben, weil es kein CSS war — eine Probe, die
   nur `max-height` hob, mass viermal denselben Wert und liess mich glauben,
   Rand und Fuge brächten nichts.

   `max-width: 400px` ist der ERSATZ für den weggefallenen Schutz, nicht
   Zierde: Die Spalten sind ungedeckelt (`OFFEN.md` 60), das Bild wüchse auf
   breiten Schirmen sonst unbegrenzt weiter — und über die 800er Rendition
   hinaus. 400 × 2 = 800 ist genau die Deckung bei DPR 2.

   `max-height` hält das klebende Element im Viewport: Bei 100 vh Kopfzone
   ab bleibt für die Reihe rund 70 vh; ein höheres Bild schöbe die
   Unterkante aus dem Bild. */
/* ⛔ GLEICHE KASTENHÖHE, NICHT GLEICHE BREITE (2026-08-05, Auftraggeber).
   Vorher band die Regel die BREITE, also entschied das Seitenverhältnis der
   Datei über die Höhe — der Beutel bekam einen niedrigeren Kasten als das
   Spray und wirkte dadurch kleiner. Jetzt ist die Höhe der gemeinsame Wert.

   ⛔ Der Rest des Grössenunterschieds ist KEINE Layoutfrage und wird hier
   NICHT ausgeglichen. Grund, Messung und die Begründung gegen einen
   Ausgleichsfaktor: **`OFFEN.md` 62, Befund 4**. Dort steht die Zahl, hier
   nur der Verweis — zwei Fassungen desselben Befunds laufen auseinander. */
body.vbg-tpl-set .vbg-set__compo-img {
  height: 100%;
  max-height: 70vh;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}
body.vbg-tpl-set .vbg-set__compo-figure {
  /* Der gemeinsame Wert. Vorher ergab sich die Höhe je Bild aus der Breite;
     jetzt gibt die Figur sie vor und beide Bilder teilen sie. */
  height: 547px;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Mengenangabe unter dem Bild — Quelle ist der Variantentitel, kein eigenes
   Setting (Begründung am Markup in vbg-set-hero.liquid). */
body.vbg-tpl-set .vbg-set__compo-size {
  margin-top: var(--vbg-space-3);
  text-align: center;
  font-family: var(--vbg-ff-body);
  font-size: 15px;
  letter-spacing: var(--vbg-ls-wide);
  color: var(--vbg-warm-gray);
}
/* ⛔ DAS VERBINDUNGSZEICHEN „&" IST AM 2026-08-05 GEFALLEN (Auftraggeber).

   Hier standen rund 50 Zeilen Begruendung fuer seine Groesse — zuletzt
   116 px, ausdruecklich NICHT aus Skala B, sondern aus der Bildgeometrie
   (Bildhoehe 340 → 449 px, derselbe Faktor 1,32, Verhaeltnis 0,266
   gehalten). Die Begruendung war richtig und ist mit dem Zeichen
   gegenstandslos geworden; sie steht in der Historie
   (`git show 5e5f2c8:assets/vbg-product-page.css`) und in OFFEN.md 62/70.

   ⚠️ Der Satz dahinter gilt weiter und gehoert nicht mit geloescht:
   **Skala B ist fuer Textgrade gebaut. Was in einer Reihe mit BILDERN
   steht, folgt der Bildgeometrie, nicht der Textskala.** Er steht in
   CLAUDE.md und betrifft jeden weiteren Wert dieser Art. */

/* ⛔ AUSFALLFALL: Fehlt die Komposition, darf die erste Spur nicht leer
   stehenbleiben. Das Grid führt `55fr 45fr` — ohne linke Spalte läge die
   Kaufspalte in Spur 2 und die halbe Seite wäre leer. */
body.vbg-tpl-set .vbg-set:not(:has(.vbg-set__composition)) {
  grid-template-columns: 1fr;
}

/* ── Kundenstimmen (Set-Seite) ────────────────────────────────────────
   Werte aus `Set-Produktseite.dc.html` Z. 121–140. Flach: 1px parchment,
   keine Rundung, kein Schatten.
   ⛔ Es gibt heute KEINE gepflegte Stimme — der Abschnitt rendert nicht.
   Diese Regeln stehen trotzdem, damit der erste eingetragene Eintrag
   sofort richtig aussieht statt erst nach einem zweiten Schritt.
   ⚠️ Nicht befüllen, solange `RECHTSPRUEFUNG.md` 000 offen ist. */
body.vbg-tpl-set .vbg-set__voices {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}
body.vbg-tpl-set .vbg-set__voice {
  border: 1px solid var(--vbg-parchment);
  padding: 16px;
}
body.vbg-tpl-set .vbg-set__voice-stars {
  color: var(--vbg-sand);
  font-size: 18px;
  letter-spacing: 2px;
}
body.vbg-tpl-set .vbg-set__voice-quote {
  font-family: var(--vbg-ff-display);
  font-style: italic;
  font-size: 21px;
  line-height: 1.5;
  color: var(--vbg-ink);
  margin: 8px 0 0;
}
body.vbg-tpl-set .vbg-set__voice-author {
  font-size: 16px;
  color: var(--vbg-warm-gray);
  margin-top: 10px;
}
/* Der Knopf steht im Entwurf als Textlink unter den Karten, nicht als
   Schaltflaeche — deshalb ohne Rahmen und ohne Flaeche. */
body.vbg-tpl-set .vbg-set__voice-cta {
  display: inline-block;
  margin-top: 12px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--vbg-ff-body);
  font-size: 18px;
  color: var(--vbg-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* ⛔ Steht der Knopf ALLEIN — keine gepflegte Stimme, aber die
   Bewertungsfunktion an —, dann ist er das erste Kind des Abschnitts. Die
   12 px sind der Abstand zu den Karten darüber; ohne Karten wären sie ein
   Versatz gegen nichts. Der Abschnitt bringt seine 44 px selbst mit. */
body.vbg-tpl-set .vbg-set__voice-cta:first-child { margin-top: 0; }

/* ── Rechte Spalte: die Kaufspalte ──────────────────────────────────── */
body.vbg-tpl-set .vbg-set__buy {
  /* Der Entwurf: `padding:56px 64px 80px` bei 45 % von 1440 = 648 px
     → Innenbreite 520 px, derselbe Wert wie in der PDP-Kaufspalte. */
  padding: 56px 64px 80px;
  box-sizing: border-box;
}
/* ⛔ FESTE px, KEINE rem — `vbg-product-page.css:2` setzt
   `html { font-size: 118% }`, und das gilt auf der Set-Seite ebenso
   (SET-HERO-BESTAND-2026-08-03.md §3.e). Ein rem-Wert landet hier 18 %
   über dem gezeichneten. Ebenso verdächtig ist jedes `vw`: es misst den
   Viewport (1440), nicht die Spalte (520). */

/* ── Mobil: einspaltig, Komposition oben, nicht sticky ──────────────── */
@media (max-width: 1279px) {
  body.vbg-tpl-set .vbg-set {
    grid-template-columns: 1fr;
    padding-top: 0;
  }
  /* ⚠️ Mobil war die Fläche schon vor dem 2026-08-05 `static` — der ganze
     Sticky-Umbau betrifft nur den Desktop. Die Regel bleibt trotzdem
     stehen: Sie hebt jetzt nicht mehr die eigene `position: sticky` auf
     (die ist weg), sondern die des **neuen Inneren**. Ohne sie klebte
     mobil ein Element in einer einspaltigen Seite, in der es nichts zu
     kleben gibt. */
  body.vbg-tpl-set .vbg-set__composition {
    padding: 0;
  }
  body.vbg-tpl-set .vbg-set__compo-sticky {
    position: static;
    max-height: none;
    /* ⛔ `min-height: 0` — NACHGETRAGEN am 2026-08-09, und es ist der
       eigentliche Grund fuer das „riesige" Hero auf dem Telefon.

       Der Block hier schaltete `position` und `max-height` ab und liess
       `min-height` stehen. Die steht oben auf
       `calc(100vh - var(--vbg-offset) - 32px)` und ergibt bei 844 px
       Viewport **704 px** — die Flaeche wurde also mobil auf fast
       Bildschirmhoehe aufgeblasen, obwohl das Bild darin nur 245 px misst.
       Gemessen: Bereich 716 px, H1 der Kaufspalte bei y = 862, also unter
       der Falz. Zum Vergleich die Produktseite: y = 745.

       ⚠️ Auf dem Desktop ist die `min-height` richtig und bleibt: Sie ist
       es, die die Komposition in der hohen Flaeche MITTIG haelt
       (Begruendung oben bei der Regel). Mobil gibt es keine hohe Flaeche
       und damit nichts zu zentrieren.

       📝 Lehrbuchfall aus `CLAUDE.md`: Was der Mobilblock nicht nennt,
       erbt den Desktop-Wert. Hier stand die eine Haelfte eines Paares
       (`max-height`) und die andere fehlte — und die Regel darueber sagt
       ausdruecklich, dass die beiden zusammengehoeren. */
    min-height: 0;
    padding: 24px 16px;
  }
  body.vbg-tpl-set .vbg-set__buy { padding: 24px 20px 40px; }
  /* ⛔ 56 px STATT DER 28 DES ENTWURFS (2026-08-05, Auftraggeber).
     Das ist eine AUSNAHME von der Regel „Desktop-Eingriff, mobiles
     Gegenstück auf dem alten Wert" — und zwar aus demselben Grund, aus dem
     die feste Bildfeldhöhe darüber gefallen ist:

     **Ein Entwurfswert, dessen Aufgabe entfallen ist, ist keine Vorgabe
     mehr, sondern eine Annahme.** Die 28 galt für eine Reihe MIT
     Bildunterschriften. Dort war das Zeichen Beiwerk; seit dem Wegfall der
     Unterschriften ist es der einzige Anker der Reihe — mobil genauso wie
     am Desktop. Bei 28 gegen 88 wäre das Verhältnis auf 0,32 gefallen.
     56/88 = 0,64 ist exakt das Verhältnis, das vorher galt (28/44).

     ⚠️ ES IST NICHT UMSONST, und das gehört dazu: Das Zeichen wird 19 → 39
     px breit, und die Reihe hat bei 390 px nur 358 zu verteilen. Gemessen,
     Bildbreite je Produkt:

         Zeichen    Zweier      Dreier
           28 px    157 px      90 px
           48 px    150         81
           56 px    148 px      77 px   ← gewählt, −6 % / −14 %
           64 px    145         74

     ✅ Überlauf ist bei keiner der vier Größen entstanden (`scrollWidth`
     gegen `clientWidth`, beide Sets). Die Reihe wird enger, nicht kaputt.
     ⛔ Der Dreier zahlt doppelt so viel wie der Zweier — dort bindet die
     Breite ohnehin (`OFFEN.md` 62). Wer das Zeichen weiter vergrössert,
     nimmt es aus den Bildern, nicht aus dem Leerraum. */
  /* `.vbg-set__plus` ist am 2026-08-05 gefallen — die mobile Groesse mit. */
  body.vbg-tpl-set .vbg-set__compo-item { flex: 1 1 0; }
  body.vbg-tpl-set .vbg-set__compo-row { gap: 12px; }

  /* ⛔ DIE FESTE KASTENHOEHE VON 547 px IST EIN DESKTOP-WERT — 2026-08-09.
     Auftraggeber: „Auf mobil ist das Set-Hero irgendwie riesig, man sieht
     den Titel unten drunter gar nicht."

     Gemessen bei 390 px, je Produktkachel:

         Kasten          173 x 547
         Bild darin      173 x 245   ← die BREITE bindet, nicht die Hoehe
         leer oben       151 px
         leer unten      151 px

     **302 der 547 px sind Leerraum.** Der Kasten stand auf dem Wert, der
     auf 1440 px richtig ist; mobil kann das Bild ihn gar nicht fuellen,
     weil drei bzw. zwei Kacheln sich 358 px teilen. Folge: Die H1 der
     Kaufspalte lag bei **y = 862** — bei einem Viewport von 844 also
     vollstaendig unter der Falz. Zum Vergleich die Produktseite: y = 745,
     sichtbar.

     ⛔ `height: auto` allein reicht NICHT, und der Grund ist die Grenze
     dieser Query: Sie gilt bis 1279 px. Dort ist die Seite ebenfalls
     einspaltig, die Kachel aber rund 450 px breit — ohne Deckel waere das
     Bild 636 px hoch und der Hero WUECHSE, statt zu schrumpfen. Der Deckel
     von 420 px entspricht dem der PDP-Galerie (421). */
  body.vbg-tpl-set .vbg-set__compo-figure { height: auto; }
  body.vbg-tpl-set .vbg-set__compo-img    { max-height: 420px; }
}

/* ══════════════════════════════════════════════════════════════════════
   SET-SEITE — Kaufspalte (Phase 8, Teilstück 2, 2026-08-03)
   ══════════════════════════════════════════════════════════════════════
   Maße aus `design-reference/Set-Produktseite.dc.html` Z. 50–92.

   ⛔ FESTE px, KEINE rem. `vbg-product-page.css:2` setzt
   `html { font-size: 118% }`, und das gilt auf der Set-Seite ebenso
   (SET-HERO-BESTAND-2026-08-03.md §3.e). Ein rem-Wert landet hier 18 %
   über dem gezeichneten. Jedes `vw` ist ebenso verdächtig — es misst den
   Viewport (1440), nicht die Spalte (520).

   ⚠️ Warum hier und nicht im `<style>`-Block der Section: das inline-CSS
   der Section ist der Bestand, der zurückgebaut wird. Neues daneben zu
   legen hieße, beide Stände parallel zu pflegen — daran ist der
   Kombi-Umbau schon einmal hängengeblieben. Alles hier ist über
   `body.vbg-tpl-set` gescopt und wirkt auf keiner anderen Seite.
   ────────────────────────────────────────────────────────────────────── */
/* ⛔ GOLD STATT WARM-GRAU — 2026-08-09, Auftraggeber: „Der Hero auf der
   Set-Seite gefällt mir immer noch nicht zu 100 %, da fehlt ein bisschen
   Farbe, evtl. goldene Akzente."

   ⚠️ DAS GEHT ÜBER DEN ENTWURF HINAUS und steht deshalb ausdrücklich hier:
   `Set-Produktseite.dc.html` kennt Gold an GENAU ZWEI Stellen — dem
   Kauf-Knopf und dem Link-Hover. Der Eyebrow steht dort in warm-grau. Wer
   diese Zeile beim nächsten Entwurfsabgleich findet, darf sie nicht als
   Abweichung zurückdrehen; sie ist eine Entscheidung.

   ⛔ `--vbg-gold-deep`, NICHT `--vbg-gold` oder `--vbg-gold-dark`: Der
   Eyebrow ist laufender Text auf Weiss, und dafuer gibt es genau einen
   zulaessigen Ton (5,56 gegen Weiss). `--vbg-gold` traegt dort 2,17 und
   `--vbg-gold-dark` 2,83 — beide unter der 4,5-Grenze. Die Begruendung
   steht am Token selbst in `vbg-tokens.css`. */
body.vbg-tpl-set .vbg-set__eyebrow {
  font-size: 14px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--vbg-gold-deep);
  margin: 0;
}
body.vbg-tpl-set .vbg-set__claim {
  font-family: var(--vbg-ff-display);
  font-style: italic;
  font-size: 21px;
  color: var(--vbg-warm-gray);
  margin: 12px 0 0;
}
body.vbg-tpl-set .vbg-set__proof {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
}
body.vbg-tpl-set .vbg-set__stars {
  color: var(--vbg-sand);
  font-size: 14px;
  letter-spacing: 1.5px;
}
body.vbg-tpl-set .vbg-set__rating {
  font-size: 14px;
  color: var(--vbg-warm-gray);
}
body.vbg-tpl-set .vbg-set__title {
  font-family: var(--vbg-ff-display);
  font-weight: var(--vbg-fw-display);
  /* ⛔ Fester Wert, kein clamp mit vw. Auf der PDP kam eine H1 mit
     `clamp(…, 4.4vw, …)` bei 40,6 px statt 44 heraus, weil vw den
     Viewport misst und nicht die 520 px breite Spalte. */
  font-size: 44px;
  line-height: var(--vbg-lh-tight);
  color: var(--vbg-ink);
  margin: 8px 0 0;
}
body.vbg-tpl-set .vbg-set__lead {
  font-size: 18px;
  color: var(--vbg-warm-gray);
  line-height: var(--vbg-lh-normal);
  margin: 12px 0 0;
}

/* ── Zweizeiler — seit 2026-08-09 die KOPFZEILE des Ersparnis-Kastens ──
   Er stand vorher als eigener Kasten darueber, mit `border-top` UND
   `border-bottom` in `--vbg-parchment`, 20 px ueber einem Kasten in
   `--vbg-sand`. Zwei Rahmen, zwei Toene, dieselbe Aussage.

   Jetzt sitzt er INNEN und traegt nur noch die untere Haarlinie — dieselbe
   Rolle wie die Linie ueber dem Set-Preis. Der einzige Rahmen ist der des
   Kastens.

   ⛔ Die negativen Seitenraender sind kein Kniff, sondern der Zweck: Der
   Kasten polstert 24 px, und eine Kopfzeile, deren Trennlinie 24 px vor der
   Kante endet, sieht aus wie ein vergessener Rand. Sie zieht sich damit auf
   die volle Kastenbreite, das Polster wandert in die Zelle. */
body.vbg-tpl-set .vbg-set__facts {
  display: grid;
  /* ⚠️ `minmax(0, 1fr)`, NICHT `1fr`. `1fr` ist `minmax(auto, 1fr)` und
     weicht dem Min-Content aus — in einer festbreiten Spalte ergibt das
     ungleiche Spuren. Auf der PDP gemessen. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  margin: -20px -24px 12px;
  padding: 0 24px;
  border-bottom: 1px solid var(--vbg-parchment);
}
/* Fehlt der Produktvorteil, trägt die Versandzeile die Reihe allein. */
body.vbg-tpl-set .vbg-set__facts--single { grid-template-columns: minmax(0, 1fr); }
body.vbg-tpl-set .vbg-set__fact {
  padding: 12px 12px 12px 0;
  font-size: 16px;
  color: var(--vbg-moss);
}
body.vbg-tpl-set .vbg-set__fact + .vbg-set__fact {
  padding: 12px 0 12px 12px;
  border-left: 1px solid var(--vbg-parchment);
}

/* ── Ersparnis-Block ────────────────────────────────────────────────── */
/* ⛔ GOLDENE OBERKANTE — 2026-08-09, dieselbe Weisung wie beim Eyebrow.
   2 px `--vbg-gold` als Kopfkante des Kastens; die uebrigen drei Seiten
   bleiben die Haarlinie in `--vbg-sand`.

   ⚠️ HIER `--vbg-gold` und NICHT `--vbg-gold-deep`: Es ist eine LINIE, kein
   Text. Der Ton am Token ist ausdruecklich so aufgeteilt — „nur fuer
   laufenden Text … Flaechen und Linien bleiben bei gold/gold-dark". Die
   Kontrastgrenze von 4,5 gilt fuer Text, nicht fuer Zierlinien.

   ⛔ Und der Grund, warum es die OBERkante ist und keine Flaeche: Der Kasten
   ist das einzige Bauteil der Spalte, das etwas verspricht. Eine
   durchgefaerbte Flaeche wuerde ihn zur Werbeanzeige machen; eine Kante
   markiert ihn, ohne den Text zu verfaerben. */
body.vbg-tpl-set .vbg-set__savings {
  border: 1px solid var(--vbg-sand);
  border-top: 2px solid var(--vbg-gold);
  margin-top: 20px;
  padding: 20px 24px;
}
body.vbg-tpl-set .vbg-set__srow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 7px 0;
  font-size: 16px;
}
body.vbg-tpl-set .vbg-set__slabel { color: var(--vbg-warm-gray); }
body.vbg-tpl-set .vbg-set__sval   { color: var(--vbg-ink); }
body.vbg-tpl-set .vbg-set__srow--gain .vbg-set__slabel,
body.vbg-tpl-set .vbg-set__srow--gain .vbg-set__sval { color: var(--vbg-moss); }

/* ⛔ Die Linie sitzt ÜBER dem Set-Preis, nicht unter der Versandzeile.
   Der Entwurf setzt sie unter „Versand gespart" und zieht damit eine
   Summenlinie unter eine Kette, die nicht aufgeht (78,90 − 7,00 − 5,95
   = 65,95, angezeigt 71,90). Hier schließt die Linie genau die Zeilen ab,
   die zum Set-Preis führen. */
body.vbg-tpl-set .vbg-set__srow--total {
  border-top: 1px solid var(--vbg-parchment);
  padding-top: 12px;
  margin-top: 5px;
}
body.vbg-tpl-set .vbg-set__srow--total .vbg-set__slabel {
  font-weight: var(--vbg-fw-semibold);
  color: var(--vbg-ink);
}
body.vbg-tpl-set .vbg-set__stotal {
  font-family: var(--vbg-ff-display);
  font-size: 32px;
  line-height: 1;
  color: var(--vbg-ink);
}
/* ⛔ ÜBERHOLT AM 2026-08-05: Hier stand „Der Versandvorteil steht UNTER dem
   Set-Preis — gesondert ausgewiesen, nicht in der Subtraktionskette
   (2026-08-03)". Der Auftraggeber hat am 2026-08-05 auf die Form von `main`
   umgestellt: Der Versand wird auf den VERGLEICHSPREIS aufgeschlagen und
   steht als Zusatz an „Einzeln zusammen". Die Zeile `--extra` hat damit
   keinen Leser mehr; die Regel bleibt vorerst stehen, weil `--gain` sie
   nicht ersetzt und ein Rückbau der Darstellung sie sofort wieder braucht.
   Begründung und Vorbehalt: RECHTSPRUEFUNG.md 00b. */
body.vbg-tpl-set .vbg-set__srow--extra { padding-top: 10px; }
/* „inkl. 5,95 € Versand" — zweite Zeile im Label von „Einzeln zusammen".
   Eigene Zeile, damit die Beträge rechts auf einer Kante bleiben. */
body.vbg-tpl-set .vbg-set__snote-inline {
  display: block;
  font-size: 13px;
  color: var(--vbg-warm-gray);
  margin-top: 2px;
}
body.vbg-tpl-set .vbg-set__snote {
  font-size: 14px;
  color: var(--vbg-warm-gray);
  text-align: right;
  margin: 2px 0 0;
}

/* ── Kaufknopf ──────────────────────────────────────────────────────── */
/* ⛔ GOLD, nicht Moos. Entscheidung A12 vom 2026-08-03 trennt die beiden
   Seiten ausdrücklich: Set-Seite Gold, PDP Moos. Die Set-Seite verkauft
   ein Bündel, die PDP ein Produkt.
   ⚠️ Eigene Klasse statt `.vbg-btn-primary.is-liquid-gold` — die geteilte
   Regel (`vbg-product-page.css:897–938`, Gold-Verlauf mit vierlagigem
   Schatten und drei festen Hex, alles `!important`) gehört beiden Seiten,
   und der Entwurf will den Knopf FLACH. Wer sie hier flach macht, ändert
   die PDP mit. */
body.vbg-tpl-set .vbg-set__atc {
  display: block;
  width: 100%;
  margin-top: 20px;
  padding: 18px;
  /* ⛔ Die FLAECHE bleibt Gold — das ist A12 und eine Entscheidung des
     Auftraggebers (Set = Gold, PDP = Moos). Geaendert wird nur die SCHRIFT
     darauf: weiss auf `--vbg-gold` misst 2,63:1 und war nie mitentschieden.
     `--vbg-forest` traegt 4,56:1 und ist bereits die Hausantwort — dieselbe
     Paarung steht 11 × im Shop (Badges „Spare 29,90 €", `herb-effect-badge`).
     ⚠️ Gefunden erst am 2026-08-05, weil `kontrast-check.mjs` die Set-Seite
     GAR NICHT angefahren hat: Der Seitentyp mit dem einzigen goldenen
     Kaufknopf stand nicht in `ZIELE`. `OFFEN.md` 74/76. */
  background: var(--vbg-gold);
  color: var(--vbg-forest);
  border: none;
  cursor: pointer;
  font-family: var(--vbg-ff-body);
  font-size: 18px;
  letter-spacing: 0.04em;
  transition: filter 0.2s ease;
}
body.vbg-tpl-set .vbg-set__atc:hover { filter: brightness(1.08); }
body.vbg-tpl-set .vbg-set__atc[disabled] {
  background: var(--vbg-sand);
  cursor: not-allowed;
}
body.vbg-tpl-set .vbg-set__reassure {
  font-size: 15px;
  color: var(--vbg-warm-gray);
  margin: 10px 0 0;
  text-align: center;
}

/* ──────────────────────────────────────────────────────────────────────
   SET-SEITE — Textabschnitte der Kaufspalte (Phase 8, Teilstück 4)
   Entwurf `Set-Produktseite.dc.html` Z. 94-119: "Über dieses Set" und
   "Warum dieses Set" stehen IN der Kaufspalte, nicht in einem vollbreiten
   Band darunter. Getrennt werden sie allein durch `margin-top` — der
   Entwurf kennt hier keine Haarlinien und keine Flächen.

   ⛔ Feste px, keine rem: `html { font-size: 118% }` gilt auf der
   Set-Seite ebenso wie auf der PDP (sie haengt an `request.page_type`,
   nicht am Template). Ein rem-Wert landet 18 % ueber dem gezeichneten.
   ────────────────────────────────────────────────────────────────────── */
body.vbg-tpl-set .vbg-set__sec { margin-top: 44px; }
body.vbg-tpl-set .vbg-set__sec + .vbg-set__sec { margin-top: 40px; }
body.vbg-tpl-set .vbg-set__sec-title {
  font-family: var(--vbg-ff-display);
  font-weight: var(--vbg-fw-display);
  font-size: 27px;
  line-height: var(--vbg-lh-snug);
  color: var(--vbg-ink);
}
body.vbg-tpl-set .vbg-set__prose,
body.vbg-tpl-set .vbg-set__prose p {
  font-size: 20px;
  line-height: 1.8;
  color: var(--vbg-warm-gray);
}
body.vbg-tpl-set .vbg-set__prose p { margin: 12px 0 0; }
body.vbg-tpl-set .vbg-set__prose strong,
body.vbg-tpl-set .vbg-set__prose b {
  font-weight: var(--vbg-fw-semibold);
  color: var(--vbg-ink);
}

/* ⚠️ `minmax(0, 1fr)`, nicht `1fr`. `1fr` ist `minmax(auto, 1fr)` und weicht
   dem Min-Content aus — in der 520-px-Spalte ergab das an anderer Stelle
   ungleiche Spuren (175/196/176 statt 3x 165,3). Gilt fuer jedes Raster hier.

   ⛔ `auto-fit` statt fester Dreispaltigkeit ist Absicht: 33 von 34 Sets haben
   GENAU EINEN gepflegten Why-Eintrag. Ein Dreispalter mit einem gefuellten
   Feld ist schlechter als eine Zeile — entschieden am 2026-08-03. Sobald die
   Inhalte da sind, fuellt dieselbe Regel drei Spalten, ohne Umbau. */
/* ⛔ AUS DEM RASTER WIRD EINE LISTE — 2026-08-07 (Auftraggeber: die Punkte
   gehoeren unter „Ueber dieses Set", die Beschreibung darueber).

   Der Wrapper heisst jetzt `.vbg-set__punkte`; die Kinder behalten ihre Namen
   (`__why-item/-title/-desc`), weil sie weiter aus `custom.set_why_items`
   kommen — die Herkunft steht im Klassennamen und soll dort stehen bleiben.

   ⛔ KEIN `auto-fit`-Raster mehr. Der alte Dreispalter war fuer einen eigenen
   Abschnitt gedacht; unter einem Fliesstext liest eine Spaltenreihe wie ein
   zweiter Textblock. Als Zeilenliste mit Haarlinie ist es dieselbe Bauform,
   die die Produktseite fuer ihre USP-Zeilen benutzt (Begriff halbfett,
   Erklaerung darunter, `1px parchment` dazwischen) — die Hausform fuer genau
   diese Aufgabe.
   📝 Die alte Begruendung „33 von 34 Sets haben genau EINEN Eintrag" faellt
   damit weg: Eine Liste sieht mit einem Eintrag nicht falsch aus, ein
   Dreispalter schon. */
/* ⛔ EIGENE FLAECHE — 2026-08-09, Auftraggeber: „Die USPs hier unten müssen
   wir noch etwas abheben vom Rest."

   Gemessen war der Befund eindeutig: Der Block hatte AUSSER einer Haarlinie
   nichts Eigenes. Kein Grund, kein Rahmen, keine eigene Schrift — Titel
   20 px semibold ink, Text 18 px warm-grau, also exakt die Werte des
   Fliesstextes zwei Absaetze darueber. Was gleich aussieht, liest sich
   gleich; die Merkmale gingen im Beschreibungstext unter.

   Jetzt: Flaeche in `--vbg-cream` mit einer 2-px-Oberkante in `--vbg-gold`.

   ⛔ DIE GOLDKANTE IST NICHT ZIERDE, SONDERN DIESELBE SPRACHE wie beim
   Ersparnis-Kasten oben: Auf dieser Seite markiert Gold die Bloecke, die
   ein Versprechen tragen — was das Set kostet und was es kann. Zwei
   Bauteile, ein Zeichen.

   ⚠️ `cream` und NICHT `parchment`: Die Galeriespalte links traegt bereits
   parchment. Zwei gleiche Flaechen nebeneinander lesen als eine; cream
   setzt sich vom Weiss ab, ohne mit der Spalte zu konkurrieren.

   📝 Die Haarlinien BLEIBEN — sie trennen jetzt innerhalb der Flaeche, wie
   im Ersparnis-Kasten auch. Nur die letzte faellt: eine Linie direkt ueber
   der Flaechenkante ist ein doppelter Abschluss. */
body.vbg-tpl-set .vbg-set__punkte {
  margin-top: 18px;
  background: var(--vbg-cream);
  border-top: 2px solid var(--vbg-gold);
  padding: 4px 24px 6px;
}
body.vbg-tpl-set .vbg-set__punkte .vbg-set__why-item {
  min-width: 0;
  padding: 14px 0;
  border-bottom: 1px solid var(--vbg-parchment);
}
body.vbg-tpl-set .vbg-set__punkte .vbg-set__why-item:last-child { border-bottom: 0; }
body.vbg-tpl-set .vbg-set__punkte .vbg-set__why-desc { margin: 3px 0 0; }
/* Die Breitenklammer des Einzelfalls entfaellt: in einer Liste ist ein
   Eintrag ueber die volle Breite richtig. */
body.vbg-tpl-set .vbg-set__punkte .vbg-set__why-item:only-child .vbg-set__why-desc { max-width: none; }

/* ⛔ HIER STAND DER `auto-fit`-DREISPALTER FUER `.vbg-set__why` — GEFALLEN am
   2026-08-07. Den Wrapper gibt es im Markup nicht mehr; er heisst seit dem
   Zusammenlegen mit „Ueber dieses Set" `.vbg-set__punkte` (oben).
   ⚠️ Die KINDER behalten ihre Namen (`__why-item/-title/-desc`) und ihre
   Regeln — die Herkunft aus `custom.set_why_items` steht im Klassennamen und
   soll dort stehen bleiben. Nur die Wrapper-Regel war tot.
   📝 Selbst verursacht und selbst aufgeraeumt: Eine Regel ohne Element ist
   keine Reserve, sondern Ballast — beim naechsten Umbau sucht jemand das
   Element dazu (dieselbe Begruendung wie bei `.vbg-hero__tagline`). */
body.vbg-tpl-set .vbg-set__why-item { min-width: 0; }
body.vbg-tpl-set .vbg-set__why-title {
  font-size: 20px;
  font-weight: var(--vbg-fw-semibold);
  color: var(--vbg-ink);
}
body.vbg-tpl-set .vbg-set__why-desc {
  font-size: 18px;
  line-height: 1.7;
  color: var(--vbg-warm-gray);
  margin: 6px 0 0;
}
/* Ein einzelner Eintrag laeuft sonst ueber die volle Spaltenbreite und liest
   sich als Fliesstext statt als Merkmal. */
body.vbg-tpl-set .vbg-set__why-item:only-child .vbg-set__why-desc { max-width: 62ch; }

/* ── "Im Set enthalten" — Karten (Teilstück 5, Entwurf Z. 120-142) ───────
   Aus der Zeilenliste werden zwei Kartenspalten: Bildflaeche 150 px auf
   parchment, darunter Name, Groesse/Preis und ein Textlink. Rahmen
   1px parchment, scharfkantig — die Bildsprache kennt nur Kreise und Pills
   als runde Formen. */
body.vbg-tpl-set .vbg-set__incl {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: 16px;
}
body.vbg-tpl-set .vbg-set__incl-card {
  border: 1px solid var(--vbg-parchment);
  box-sizing: border-box;
  min-width: 0;
}
body.vbg-tpl-set .vbg-set__incl-img {
  height: 150px;
  background: var(--vbg-parchment);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  box-sizing: border-box;
}
/* ⚠️ `width:auto; height:auto` ist Pflicht, nicht Kosmetik: das Bild traegt
   `width`/`height`-Attribute (gegen CLS und gegen die theme-check-Regel), und
   ohne diese beiden Zeilen zieht das height-Attribut es auf feste Pixelhoehe.
   Genau die Falle aus `CLAUDE.md` — deshalb hier zusammen mit den Attributen. */
body.vbg-tpl-set .vbg-set__incl-img img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
body.vbg-tpl-set .vbg-set__incl-body { padding: 14px 16px 16px; }
body.vbg-tpl-set .vbg-set__incl-name {
  font-family: var(--vbg-ff-display);
  font-size: 23px;
  line-height: var(--vbg-lh-snug);
  color: var(--vbg-ink);
}
body.vbg-tpl-set .vbg-set__incl-meta {
  font-size: 16px;
  color: var(--vbg-warm-gray);
  margin-top: 2px;
}
body.vbg-tpl-set .vbg-set__incl-link {
  font-size: 18px;
  display: inline-block;
  margin-top: 8px;
  color: var(--vbg-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
body.vbg-tpl-set .vbg-set__incl-link:hover { color: var(--vbg-gold-dark); }
/* Der FAQ-Verweis unter den Karten (`OFFEN.md` 63 B). Er ist ein Hinweis,
   keine Überschrift: derselbe Grad wie die Kartenlinks darüber, aber in
   warm-gray, damit er nicht als weiterer Link liest.
   ⛔ NACHGETRAGEN am selben Tag: Hier stand „kein mobiles Gegenstück — diese
   Zeile hat kein Vorher". Das war richtig, solange sie auf 13 px stand.
   Seit der Vergrößerung (`OFFEN.md` 48) steht sie auf 16, und damit HAT sie
   ein Vorher — das Gegenstück liegt am Dateiende.
   ⚠️ Die Lehre ist allgemeiner als der Fall: Eine Begründung, die auf dem
   aktuellen Wert fusst, verfaellt mit dem naechsten Wert. */
body.vbg-tpl-set .vbg-set__incl-note {
  font-size: 18px;
  line-height: var(--vbg-lh-normal);
  color: var(--vbg-warm-gray);
  margin: 14px 0 0;
}

/* ── Schwebende Leiste (Teilstück 7, Entwurf Z. 176-181) ─────────────────
   Oben, weiss, Haarlinie nach unten, faehrt ueber `transform` herein.

   ⛔ `position: fixed` und KEIN `container-type`, `transform` oder
   `backdrop-filter` an einem Vorfahren: beides macht das Element zum
   Containing Block und die Leiste haengt dann an der Section statt am
   Viewport. Auf der PDP ist genau das schon einmal passiert.

   ⚠️ Spezifitaet 0,2,1 (`body` + zwei Klassen) — sie muss das Inline-CSS der
   Section schlagen, das spaeter im Dokument steht und bei gleicher
   Spezifitaet gewinnen wuerde. */
body.vbg-tpl-set .vbg-set__bar {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  z-index: 60;
  background: var(--vbg-white);
  border-bottom: 1px solid var(--vbg-sand);
  transform: translateY(-100%);
  transition: transform 0.22s ease;
}
body.vbg-tpl-set .vbg-set__bar.is-visible { transform: translateY(0); }
body.vbg-tpl-set .vbg-set__bar-inner {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 48px;
}
body.vbg-tpl-set .vbg-set__bar-img {
  height: 36px;
  width: auto;
  object-fit: contain;
  flex: none;
}
body.vbg-tpl-set .vbg-set__bar-name {
  font-family: var(--vbg-ff-display);
  font-size: 21px;
  color: var(--vbg-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
body.vbg-tpl-set .vbg-set__bar-prices {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex: none;
}
body.vbg-tpl-set .vbg-set__bar-compare {
  font-size: 16px;
  color: var(--vbg-warm-gray);
  text-decoration: line-through;
}
body.vbg-tpl-set .vbg-set__bar-now {
  font-family: var(--vbg-ff-display);
  font-size: 21px;
  color: var(--vbg-ink);
}
body.vbg-tpl-set .vbg-set__bar form { flex: none; margin: 0; }
body.vbg-tpl-set .vbg-set__bar-btn {
  flex: none;
  padding: 10px 22px;
  /* ⛔ Wie am Hauptknopf: Flaeche Gold, Schrift `--vbg-forest` statt weiss —
     2,63 → 4,56. ⚠️ DIE SCHWEBENDE LEISTE IST DER STRENGERE FALL: 15 px
     sind normaler Text (Schwelle 4,5), der Hauptknopf mit 18 px ebenfalls
     („large" braucht 24 px, oder 18,66 px UND fett). Beide reissen also die
     harte Schwelle, nicht nur die milde. */
  background: var(--vbg-gold);
  color: var(--vbg-forest);
  border: none;
  cursor: pointer;
  font-family: var(--vbg-ff-body);
  font-size: 15px;
  letter-spacing: 0.04em;
  transition: filter 0.2s ease;
}
body.vbg-tpl-set .vbg-set__bar-btn:hover { filter: brightness(1.08); }

/* ── Mobil ──────────────────────────────────────────────────────────── */
@media (max-width: 1279px) {
  /* ⛔ Die Leiste kehrt sich um: unten statt oben. Dort ist der Daumen, und
     oben steht bereits die Kopfzone. Der Entwurf zeigt sie mobil ebenfalls
     unten (Z. 330, „fixierte Kaufleiste"). */
  body.vbg-tpl-set .vbg-set__bar {
    top: auto;
    bottom: 0;
    border-bottom: none;
    border-top: 1px solid var(--vbg-sand);
    transform: translateY(100%);
  }
  body.vbg-tpl-set .vbg-set__bar-inner { padding: 10px 16px; gap: 10px; }
  /* Bild und Name fallen: bei 390 px konkurrieren vier Elemente um die Breite,
     und Preis plus Knopf sind die beiden, die etwas entscheiden. */
  body.vbg-tpl-set .vbg-set__bar-img,
  body.vbg-tpl-set .vbg-set__bar-name { display: none; }
  body.vbg-tpl-set .vbg-set__bar-prices { margin-left: 0; }
  body.vbg-tpl-set .vbg-set__bar-btn { margin-left: auto; padding: 12px 20px; }

  /* Zwei Spalten bleiben — bei 390 px sind das rund 165 px je Karte, und die
     Bildflaeche faellt mit. Eine einspaltige Liste waere hier laenger als der
     halbe Bildschirm je Produkt. */
  body.vbg-tpl-set .vbg-set__incl { gap: 12px; }
  body.vbg-tpl-set .vbg-set__incl-img { height: 120px; }
  body.vbg-tpl-set .vbg-set__incl-body { padding: 12px 12px 14px; }
  body.vbg-tpl-set .vbg-set__incl-name { font-size: 16px; }
  body.vbg-tpl-set .vbg-set__sec { margin-top: 32px; }
  body.vbg-tpl-set .vbg-set__sec + .vbg-set__sec { margin-top: 28px; }
  body.vbg-tpl-set .vbg-set__sec-title { font-size: 21px; }
  /* `.vbg-set__why` gap: mit dem Wrapper gefallen, siehe oben. */
  body.vbg-tpl-set .vbg-set__title { font-size: 30px; }
  body.vbg-tpl-set .vbg-set__claim { font-size: 16px; }
  body.vbg-tpl-set .vbg-set__lead  { font-size: 14px; }
  body.vbg-tpl-set .vbg-set__savings { margin-top: 16px; padding: 16px 18px; }
  /* ⛔ GEGENSTUECK zum Umzug des Zweizeilers in den Kasten (2026-08-09).
     Die negativen Raender muessen das Polster des Kastens SPIEGELN, und das
     ist hier 16/18 statt 20/24. Ohne diese Zeile stuende die Kopfzeile
     4 px ueber der Oberkante und 6 px je Seite ueber den Rand hinaus —
     genau die Klasse Fehler, vor der der Mobilblock-Abschnitt in CLAUDE.md
     warnt: Was der Mobilblock nicht nennt, erbt den Desktop-Wert. */
  body.vbg-tpl-set .vbg-set__facts   { margin: -16px -18px 10px; padding: 0 18px; }
  body.vbg-tpl-set .vbg-set__stotal  { font-size: 26px; }
  body.vbg-tpl-set .vbg-set__atc     { margin-top: 16px; padding: 16px; font-size: 14px; }
}

/* ══════════════════════════════════════════════════════════════════════
   MOBILE GEGENSTUECKE zur Desktop-Schriftvergroesserung vom 2026-08-05
   (689fb8a), je auf dem Wert von VOR der Aenderung. Gemessen bei 390 px
   standen 110 Textelemente der Produktseite groesser als vorher — der
   Mobilblock hatte fuer keine der geaenderten Deklarationen ein Gegenstueck.
   Geprueft, dass keiner der Selektoren in einer Query unter 900 px eine
   font-size traegt. Verfahren: CLAUDE.md, Abschnitt Mobilblock.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1279px) {
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) p, body.vbg-product-page #MainContent:has(.vbg-hero--galerie) li { font-size: 14px; }
}

/* ══════════════════════════════════════════════════════════════════════
   MOBILE GEGENSTUECKE zur Vergroesserung der SET-SEITE vom 2026-08-05
   (`OFFEN.md` 48, Weg A), je auf dem Wert von VOR der Aenderung.

   ⛔ Vergroessert wurden NUR die zwoelf Abschnitts-Regeln. Kaufblock,
   schwebende Leiste und linke Komposition bleiben auf den gezeichneten
   Werten — dieselbe Ausnahme wie bei der PDP-Kaufspalte (`CLAUDE.md`:
   Entwurf auf feste px gezeichnet, Spalte 520 px breit). Die Zuordnung ist
   am DOM gemessen, nicht am Selektornamen geraten.

   ✅ ZWEI der zwoelf brauchen hier nichts: `.vbg-set__sec-title` (21) und
   `.vbg-set__incl-name` (16) haben oben im Block ab Z. 2940 laengst ein
   Gegenstueck. Die Liste hier ist deshalb zehn Zeilen lang, nicht zwoelf —
   das ist kein Versaeumnis, sondern die Gegenprobe.

   Geprueft, dass keiner der zehn Selektoren in einer feineren Query unter
   dem Umbruchpunkt eine `font-size` traegt: der einzige weitere Set-Block
   ist die Umbruch-Query (seit 2026-08-08 `max-width: 1279px`, davor 900)
   und setzte nur `.vbg-set__plus` — das
   Zeichen ist am 2026-08-05 gefallen, die Query traegt dort seither GAR
   keine `font-size` mehr. Der Befund gilt damit erst recht. Deshalb
   darf dieser Block ans Dateiende — vgl. `CLAUDE.md`, wo genau diese
   Platzierung schon einmal elf fremde Kartentexte verstellt hat.

   ⚠️ VIER der Regeln haben heute kein Element (`prose`, `voice-quote`,
   `voice-stars`, `voice-author`) — leere Beschreibungen, gesperrte
   Kundenstimmen. Sie stehen trotzdem hier: sonst faellt beim ersten
   gepflegten Eintrag mobil ein Grad an, den niemand entschieden hat.
   ⛔ Sie sind damit auch die vier, die die 390-px-Messung NICHT belegen
   kann. Wer die Stimmen fuellt, misst sie nach.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 1279px) {
  body.vbg-tpl-set .vbg-set__prose,
  body.vbg-tpl-set .vbg-set__prose p  { font-size: 14px; }
  body.vbg-tpl-set .vbg-set__why-title  { font-size: 14px; }
  body.vbg-tpl-set .vbg-set__why-desc   { font-size: 13px; }
  /* ⛔ Gegenstueck zur neuen Flaeche (2026-08-09): Das Seitenpolster von
     24 px ist der Desktop-Wert. Bei 390 px misst die Spalte 350 — 48 px
     Polster waeren 14 % der Bildschirmbreite, und die Seite hat dort
     ohnehin schon zu viel Rand (`OFFEN.md` 114). */
  body.vbg-tpl-set .vbg-set__punkte     { padding-left: 16px; padding-right: 16px; }
  body.vbg-tpl-set .vbg-set__incl-meta  { font-size: 12px; }
  body.vbg-tpl-set .vbg-set__incl-link  { font-size: 13px; }
  body.vbg-tpl-set .vbg-set__incl-note  { font-size: 13px; }
  body.vbg-tpl-set .vbg-set__voice-stars  { font-size: 13px; }
  body.vbg-tpl-set .vbg-set__voice-quote  { font-size: 15px; }
  body.vbg-tpl-set .vbg-set__voice-author { font-size: 12px; }
  body.vbg-tpl-set .vbg-set__voice-cta    { font-size: 13px; }
}

/* ══════════════════════════════════════════════════════════════════
   ⛔ SKALA B, 2026-08-05 — Gegenstuecke zur Desktop-Vergroesserung.
   Je auf dem Wert von VOR der Aenderung; mobil bleibt alles, wie es war.
   Eingesetzt am Dateiende: hinter der letzten geaenderten Desktop-Regel
   (Z.3021), vor der naechsten feineren Query. Ans Dateiende
   gestellt wuerde der Block feinere Regeln ueberholen, an den Anfang
   gestellt waere er wirkungslos.
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1279px) {
  .vbg-stars                                                                           { font-size: 1.1rem; }
  .vbg-variant-pill-save                                                               { font-size: 13px; }
  .vbg-variant-pill-ship                                                               { font-size: 12px; }
  .vbg-variant-toggle                                                                  { font-size: 14px; }
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-col-fset-contents li { font-size: 11px; }
  .vbg-variant-hinweis                                                                 { font-size: 13px; }
  .vbg-variant-toggle__icon                                                            { font-size: 18px; }
  .vbg-comp-title                                                                      { font-size: 1.4rem; }
  .vbg-list li                                                                         { font-size: 0.95rem; }
  .vbg-list li::before                                                                 { font-size: 1rem; }
  .vbg-dosage-card-badge                                                               { font-size: 0.65rem; }
  .vbg-dosage-weight                                                                   { font-size: 1.2rem; }
  .vbg-dosage-detail                                                                   { font-size: 0.88rem; }
  .vbg-dosage-detail span                                                              { font-size: 0.72rem; }
  .vbg-kombi-bestseller                                                                { font-size: 0.65rem; }
  .vbg-kombi-title                                                                     { font-size: 1.3rem; }
  .vbg-kombi-desc                                                                      { font-size: 0.88rem; }
  .vbg-kombi-price                                                                     { font-size: 1.6rem; }
  .vbg-dosage-hint                                                                     { font-size: 0.88rem; }
  .vbg-atc-microcopy                                                                   { font-size: 14px; }
  .vbg-lightbox-trigger::after                                                         { font-size: 1.2rem; }
  .vbg-lightbox-close                                                                  { font-size: 2rem; }
  #vbg-lightbox-close                                                                  { font-size: 1.4rem; }
  body.vbg-tpl-set .vbg-set__eyebrow                                                   { font-size: 12px; }
  body.vbg-tpl-set .vbg-set__stars                                                     { font-size: 12px; }
  body.vbg-tpl-set .vbg-set__rating                                                    { font-size: 12px; }
  body.vbg-tpl-set .vbg-set__fact                                                      { font-size: 14px; }
  body.vbg-tpl-set .vbg-set__srow                                                      { font-size: 14px; }
  body.vbg-tpl-set .vbg-set__snote                                                     { font-size: 12px; }
  body.vbg-tpl-set .vbg-set__reassure                                                  { font-size: 13px; }
  body.vbg-tpl-set .vbg-set__bar-name                                                  { font-size: 18px; }
  body.vbg-tpl-set .vbg-set__bar-compare                                               { font-size: 14px; }
  body.vbg-tpl-set .vbg-set__bar-now                                                   { font-size: 18px; }
  body.vbg-tpl-set .vbg-set__bar-btn                                                   { font-size: 13px; }
}

/* ══════════════════════════════════════════════════════════════════
   ⛔ SKALA B, 2026-08-05 — Gegenstuecke zur Desktop-Vergroesserung.
   Je auf dem Wert von VOR der Aenderung; mobil bleibt alles, wie es war.
   Eingesetzt am Dateiende: hinter der letzten geaenderten Desktop-Regel
   (Z.1592), vor der naechsten feineren Query. Ans Dateiende
   gestellt wuerde der Block feinere Regeln ueberholen, an den Anfang
   gestellt waere er wirkungslos.
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1279px) {
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero--kauf p, body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero--kauf li { font-size: 14px; }
  body.vbg-product-page #MainContent:has(.vbg-hero--galerie) .vbg-hero__usp li                                                                                { font-size: 13px; }
}
