/* pz: Basis des Redesigns — Design-Tokens aus dem Mockup, Grundtypografie,
   CI-Umfaerbung der NOVA-Gelb-Stellen, wiederverwendbare Bausteine.
   Quelle SOLL: Projektinformationen/mockup/mockup-*.html (:root-Tokens).
   Version: siehe Marker --pz-css-base unten (muss mit layout/header.tpl uebereinstimmen) */

:root {
  --pz-css-base: "20260821-36";

  /* ==========================================================================
     pz: SEKTIONS-SKALA — die EINZIGE Quelle fuer Abstaende an Sektionsgrenzen
     (FEHLERMUSTER.md Zeile 1, verschaerft: Ben hat "sinnlosen whitespace" 2x
     beanstandet, weil jede Luecke einen eigenen Pixelwert hatte).

     Die vier Stufen sind KEINE erfundenen Werte, sondern genau die vier
     Sektionsmasse, die in den abgenommenen Mockups vorkommen:
       126  mockup-startseite  `section{padding:126px 0}`
        96  mockup-kategorie   `.chead{padding:88px 0 96px}` / `footer{padding:96px 0 0}`
        76  mockup-kategorie   `.layout{padding:76px 0 0}`   (Band -> Inhalt)
        32  mockup-*           Brotkrumen-/Toolbar-Streifen
     Vereinheitlicht (bewusste Mockup-Abweichung, Klasse 6 dokumentiert):
     mockup-artikel `.desc/.care{110px}`, `.rel{120px}` und mockup-kategorie
     `.seo{110px}` laufen bei uns auf --pz-sek (126). Genau diese 110/120/126-
     Streuung IST die Beliebigkeit, die Ben beanstandet hat.

     REGEL, die jede Abnahme prueft:
     (1) Jede Sektion traegt ihr Mass selbst, ueber --pz-sek*, nie ueber einen
         Einzelwert und nie ueber ein Innen-Wrapper-Polster.
     (2) An jeder Grenze zieht GENAU EIN Skalenwert. Folgen zwei helle
         Sektionen aufeinander (kein oder nur schwacher Flaechenwechsel
         ivory<->ivory-2), setzt die ZWEITE ihr Kopfmass auf 0.
     (3) Ausnahme mit Ansage: an einer HARTEN Farbkante (hell -> ink) behaelt
         jede Seite ihr eigenes Mass — die Kante teilt den Raum sichtbar in
         zwei Zonen. So loest es auch das Mockup (`.setband`, `footer`).
     (4) NOVA-Zuschlaege (#content-wrapper padding, #content padding-bottom,
         Breadcrumb-Margin) werden HIER an der Basis neutralisiert, nie je
         Seite (Fehlerregister 17).
     ========================================================================== */
  --pz-sek: 126px;       /* Standard-Sektionsgrenze */
  --pz-sek-band: 96px;   /* Innenmass eines farbigen Vollbild-Bandes */
  --pz-sek-lead: 76px;   /* Anschluss Band -> Inhaltsbereich */
  --pz-sek-nav: 32px;    /* Brotkrumen-/Toolbar-Streifen */

  /* pz: HALBSTUFEN (Ben 20.08.: "Abstand halbieren" an drei Stellen —
     vor der Kachel-Sektion, nach dem Kachelgrid, unter dem Vor-Ort-Band,
     dazu der Fussbereich). Die Skala wird dafuer BEWUSST um benannte
     Halbstufen erweitert statt an vier Stellen einen freien Pixelwert zu
     setzen (Fehlerregister 3 / FEHLERMUSTER.md Zeile 1).
     Jede Halbstufe ist exakt die halbe Vollstufe, auf gerade Zahl gerundet;
     die responsiven Entsprechungen halbieren die jeweilige Mobilstufe.
     Benutzt wird eine Halbstufe NUR dort, wo die Vollstufe eine der oben
     genannten Grenzen bildet — nicht als zweite freie Wahlmoeglichkeit. */
  --pz-sek-halb: 64px;   /* halbe Sektionsgrenze  (126 / 2) */
  --pz-band-halb: 48px;  /* halbes Bandmass       (96 / 2)  */
  --pz-lead-halb: 38px;  /* halber Bandanschluss  (76 / 2)  */
  --pz-nav-halb: 16px;   /* halber Streifen       (32 / 2)  */

  /* pz: ZEILENHOEHE DER TOOLBAR (Ben 20.08./F4: "das ist immernoch nicht
     buendig nach oben"). Die Sidebar-Ueberschrift "KATEGORIEN" und die
     Toolbar-Zeile der rechten Spalte stehen nebeneinander, bekamen ihre
     Hoehe aber aus zwei Quellen — das Label aus seiner Textzeile (20px), die
     Toolbar aus den Knopfkaesten (38,5px gemessen). Das ist Fehlerregister
     11 ueber die Spaltengrenze hinweg: EINE Zeile, zwei Hoehen.
     Ab jetzt referenzieren beide Seiten DIESE Zahl.
     Sie ist nicht gegriffen, sondern gerundet: 38,5px misst der
     Sortier-Knopf im NOVA-Rohzustand, 40px ist der naechste Wert, der
     zugleich 2,5 x --pz-nav-halb ist — die Knoepfe wachsen also um 1,5px
     und die Skala bekommt keinen krummen Fremdkoerper.
     ⚠️ Bewusst NUR ab lg benutzt: unterhalb stehen die beiden Spalten
     nicht nebeneinander (die Sidebar rutscht unter die Liste, gemessen),
     und die Knoepfe tragen dort die 44px-Tap-Ziel-Hoehe. */
  --pz-toolbar-row: 40px;

  /* pz: STEUERELEMENT-HOEHEN — EINE Quelle fuer alles, was als Knopf/CTA
     nebeneinander oder untereinander steht (Fehlerregister 11 "Zwei Hoehen in
     einer Element-Gruppe"; Ben 20.08./A2+A3: "passend gleichgross nebeneinander"
     bzw. "gleichgross ueber containerbreite untereinander").

     ⚠️ Beide Zahlen sind GEMESSEN, nicht gegriffen:
       58px  ist die Hoehe, die .pz-btn heute schon hat (19px Polster oben +
             unten + 20px Zeilenkasten, im Browser gemessen 20.08. an Hero-,
             Beratungs- und Setband-Knopf). Genau EIN Knopf fiel mit 56px
             heraus (Setband-Fuss) — das ist die Streuung, die das Token
             beendet: die Hoehe steht ab jetzt EINMAL da und wird nicht mehr
             aus dem Polster gerechnet.
       46px  ist die bereits im Projekt gesetzte Hoehe der Formularfelder
             (weiter unten .form-control) und zugleich ueber dem 44px-Tap-Ziel.
             Der Karten-CTA teilt sie sich mit ihnen, statt eine dritte
             Knopfhoehe zu erfinden.
     Wer ein neues Bedienelement baut, greift eine dieser beiden Stufen. */
  --pz-ctl-h: 58px;      /* Primaer-/Sektions-CTA (.pz-btn, .pz-tlink) */
  --pz-ctl-h-sm: 46px;   /* Karten-CTA, Formularfelder */

  /* pz: ZWEI GROESSEN, DIE DER GANZE KAUFPFAD TEILT (Fixrunde 8, Abschnitt D).
     Ben hat den Bestellpfad als Ganzes beanstandet — er wird deshalb auch als
     Ganzes vermasst, nicht Station fuer Station.
     ⚠️ Sie standen bis Fixrunde 8b in pz-warenkorb.css und wurden von
     pz-checkout.css mitbenutzt. Das koppelte zwei Bereichsdateien an ihre
     LADEREIHENFOLGE im header.tpl: haette jemand 'warenkorb' hinter 'checkout'
     einsortiert, waeren die Werte im Checkout still undefiniert gewesen
     (CSS meldet das nicht, der Knopf faellt einfach auf seine Inhaltshoehe).
     Tokens gehoeren deshalb zu den anderen Tokens an die Basis, die als
     erste Bereichsdatei geladen wird.

     --pz-kaufpfad-img  Bildmass der Artikelzeile. FESTES Mass, kein `1fr`:
       FEHLERMUSTER #4 (Bens Thumb-Beanstandung) — die Datenmenge bestimmt
       Umbruch und Scroll, nie die Elementgroesse. Derselbe Artikel zeigt sein
       Foto auf der Zwischenseite UND in der Positionstabelle der
       Zusammenfassung damit gleich gross; vorher war es dort 397px und hier
       172px breit (20.08. gemessen). Mobil kleiner, weil daneben noch die
       Artikeldaten stehen muessen (390 - 2x16 Seite - 2x20 Karte - 16 Spalt
       = 262px Restbreite; mit 110px Bild bleiben 152px Text, mit 160px nur 102).
     --pz-kaufpfad-btn-h  EINE Hoehe fuer alle Button-Paare des Kaufpfads
       (Fehlerregister 11: in einer Gruppe wird die Hoehe EINMAL festgelegt).
       Gemessen 20.08. vorher: Zwischenseite 43 gegen 39px, Dropdown 35 gegen
       47px — vier Knoepfe, vier Hoehen. 48px ist kein neuer Wert, sondern
       genau die Hoehe, die pz-checkout.css seit dem 19.08. fuer das
       Zurueck/Weiter-Paar setzt; sie gilt ab jetzt fuer den ganzen Pfad. */
  --pz-kaufpfad-img: 160px;
  --pz-kaufpfad-btn-h: 48px;

  /* pz: KARTENPLATTE (Ben 20.08./K6: "man erkennt die eigentliche artikelkarte
     aktuell quasi nicht wirklich weil die hintergruende identisch sind — ein
     kleiner effekt hier waer sehr edel").
     Die Karte lag bis heute rahmen- und flaechenlos auf derselben Ivory-
     Grundflaeche wie die Seite; sichtbar war nur die Bildbuehne. Sie bekommt
     jetzt eine eigene, sehr leise Flaeche.
     ⚠️ KEINE frei gegriffenen Werte — alle drei Groessen sind abgeleitet:
       --pz-card-bg    exakter Mittelwert zwischen --pz-ivory (#f7f4ee) und
                       --pz-ivory-2 (#efeadf) = #f3efe6. Die Buehne (ivory-2)
                       bleibt damit einen Hauch dunkler als die Platte — die
                       Karte liest sich geschichtet statt flach.
       --pz-card-line  die halbe Deckkraft von --pz-line (.13 -> .065): eine
                       Kante, die die Karte begrenzt, ohne einen Kasten zu malen.
       --pz-card-pad   16px = die kleinste Stufe der KARTEN-eigenen Rhythmik aus
                       dem Mockup (.card .prices margin-top:16px). Bewusst NICHT
                       aus der Sektions-Skala gegriffen: die misst Sektions-
                       grenzen, nicht Kartenpolster (Fehlerregister 3).
     Weil das Polster auf ALLEN Seiten gleich ist, bleibt der im Mockup
     vereinbarte Bezug erhalten: Titel und Bildbuehne stehen weiter buendig
     zueinander (FEHLERMUSTER.md Zeile 2 / Fehlerregister 22). */
  --pz-card-bg: #f3efe6;
  --pz-card-bg-hover: #f8f5ef;
  --pz-card-line: rgba(18, 16, 13, .065);
  --pz-card-pad: 16px;

  /* pz: FREIRAUM UNTER DEM FIXEN CONSENT-WIDGET (Ben 20.08.: der
     Fingerabdruck-Knopf lag auf dem "Vertrag widerrufen"-Button;
     Fehlerregister 7 "Fixe Elemente ueberdecken Bedienelemente").
     Kein geschaetzter Wert: #consent-settings-btn ist fixed, 32x32, mit
     16px Abstand zur linken und unteren Viewportkante (gemessen 20.08. bei
     390) — er belegt also die unteren 48px. 12px Luft dazu. */
  --pz-consent-clear: 60px;

  /* Tokens 1:1 aus dem Mockup */
  --pz-ink: #12100d;
  --pz-ink-2: #1a1712;
  --pz-ink-3: #241f18;
  --pz-ivory: #f7f4ee;
  --pz-ivory-2: #efeadf;
  --pz-ivory-3: #e6e0d3;
  --pz-gold: #b98d4f;
  --pz-gold-lt: #d3ae74;
  /* pz: TEXT-GOLD (Ben-Entscheidung 21.08., impeccable-Audit).
     --pz-gold #b98d4f misst auf --pz-ivory #f7f4ee nur 2,45:1 — als
     FLAECHE (Buttons, Linien, Badges, Hover) ist das richtig, als
     SCHRIFT auf hellem Grund reisst es AA (4,5:1) klar.
     Deshalb ein zweiter Gold-Ton, ausschliesslich fuer TEXT auf hellen
     Flaechen (Eyebrow, <em>-Akzente in Headlines, Karten-Kicker).
     ⚠️ ABWEICHUNG VOM BRIEFING (bewusst, mit Messung): vorgegeben war
     #8a6428. Der misst auf --pz-ivory-2 #efeadf nur 4,45:1 und verfehlt
     damit das Ziel (>=4,5:1 auf ivory UND ivory-2) — und genau dort steht
     der Eyebrow "Beschreibung" auf der Artikelseite (gemessen 21.08.).
     #886225 ist der naechstdunklere Schritt, der ALLE drei hellen
     Flaechen traegt; der Farbunterschied ist mit blossem Auge nicht zu
     sehen. Ein Ton eine Stufe dunkler ist besser als eine Ausnahmeregel
     fuer eine einzelne Sektion (Fehlerregister 17).
     Im Browser nachgerechnet (21.08., WCAG-Formel):
       auf --pz-ivory   #f7f4ee = 5,01:1  (AA fuer Normaltext)
       auf --pz-card-bg #f3efe6 = 4,79:1  (AA)
       auf --pz-ivory-2 #efeadf = 4,58:1  (AA)
     ⛔ NICHT fuer Flaechen, Rahmen, Hover — dafuer bleibt --pz-gold.
     ⛔ NICHT auf dunklem Grund — dort bleibt --pz-gold-lt (.pz-eyebrow-d). */
  --pz-gold-text: #886225;
  --pz-rose: #e9d8cf;
  --pz-text: #221f1b;
  /* pz: KONTRAST VON --pz-muted, im Browser nachgerechnet.
     21.08. (Ben-Entscheidung, impeccable-Audit): Der Ton wird von
     #7b736a auf #726a61 abgedunkelt — der alte Wert kam auf --pz-ivory
     nur auf 4,25:1 und riss damit AA (4,5:1) fuer Normaltext, obwohl er
     genau dort steht, wo Nebentexte trotzdem gelesen werden muessen
     (Lead-Absaetze, MwSt-Zeilen, Merkmalslisten).
     ⚠️ ABWEICHUNG VOM BRIEFING (bewusst, mit Messung): vorgegeben war
     #726a61. Der misst auf --pz-ivory-2 #efeadf 4,43:1 — und genau dort
     steht das PDP-Label "Langbeschreibung" (gemessen 21.08.). #6f675e ist
     der naechstdunklere Schritt, der alle drei hellen Flaechen traegt.
     Gemessen mit dem neuen Wert (21.08., WCAG-Formel im Browser):
       auf --pz-ivory   #f7f4ee = 5,06:1  (AA)
       auf --pz-card-bg #f3efe6 = 4,84:1  (AA)
       auf --pz-ivory-2 #efeadf = 4,63:1  (AA)
     Damit gilt die alte Nutzungsbeschraenkung NICHT mehr — der Ton ist
     auf JEDER hellen Flaeche des Shops AA-tauglich.
     Historie: In pz-artikel.css stand dazu, der Kommentar in dieser Datei
     nenne fuer diese Paarung 5,51:1 und sei falsch. Das war eine
     Verwechslung — die 5,51:1 weiter unten gehoeren zu --pz-ok #4f6a42
     (nachgerechnet: stimmt), nicht zu --pz-muted. Beide Stellen sind
     jetzt richtig beschriftet. */
  --pz-muted: #6f675e;
  /* pz: ⚠️ NUR AUF DUNKLEM GRUND. Auf --pz-ivory misst der Ton 2,45:1 —
     er war bis 21.08. an acht Stellen auf HELLEM Grund im Einsatz
     (Streichpreise, PDP-Labels "Kurzbeschreibung/Langbeschreibung",
     Filter-Zaehler, Trennpunkte). Alle acht tragen jetzt --pz-muted
     (Fehlerregister 17: der Wert war nicht auf EINER Seite falsch,
     sondern ueberall auf hellem Grund).
     Auf --pz-ink #12100d misst er 7,06:1 — dafuer bleibt er stehen.
     Aktuell hat er keinen Nutzer mehr; er bleibt als benannter
     Dunkelgrund-Ton der Palette erhalten, damit die naechste dunkle
     Sektion nicht wieder einen freien Grauwert erfindet. */
  --pz-muted-d: #a79c90;
  /* pz: einziger Ton ausserhalb des Mockups — Verfuegbarkeits-Signal
     (Bootstrap-Gruen passte nicht in die warme Palette, Review R3). */
  --pz-ok: #4f6a42;
  --pz-line: rgba(18, 16, 13, .13);
  /* pz: 20.08. (Ben-Freigabe "jo mach"): Kontur-Ton fuer INTERAKTIVE
     Outline-Elemente (Ghost-Buttons, Form-Controls, Stepper, Chips) —
     WCAG 1.4.11 verlangt >=3:1 fuer Bedienelement-Konturen; der alte
     projektweite Wert rgba(18,16,13,.28) mass nur 1,88:1. Dieser hier:
     3,48:1 auf Seite #f7f4ee, 3,43:1 auf Platte #f3efe6 (im Browser
     gerechnet). Dekorative Trennlinien bleiben bewusst auf --pz-line —
     sie sind keine Bedienelemente. */
  --pz-ctl-line: rgba(18, 16, 13, .5);
  /* pz: FOKUSRING — ZWEIFARBIG (Ben-Freigabe 20.08., F5).
     NOVA setzt projektweit `outline: 2px solid rgb(214,188,152)` (#d6bc98)
     auf `:focus-visible`. Der Ton misst gegen die Seitenflaeche #f7f4ee nur
     1,66:1 — WCAG 2.4.13 (Focus Appearance) und 1.4.11 verlangen 3:1 gegen
     ALLE angrenzenden Flaechen. Auf hellen Seiten war der Ring damit
     praktisch unsichtbar, auf den dunklen Baendern (Hero, Set-Band, Fuss)
     ausgerechnet gut sichtbar — genau falsch herum.
     Ein einfarbiger Ersatz kann das nicht loesen: der Shop hat helle UND
     dunkle Flaechen, und jede Einzelfarbe versagt auf einer davon. Deshalb
     ZWEI Ringe aus den beiden Endpunkten der Palette — Kern innen dunkel,
     Halo aussen hell. Auf hellem Grund traegt der Kern, auf dunklem der
     Halo, und die beiden tragen sich immer gegenseitig.
     Beide Werte sind vorhandene Palettentokens, keine neuen Farben. */
  --pz-focus-core: var(--pz-ink);
  --pz-focus-halo: var(--pz-ivory);
  --pz-focus-w: 2px;        /* Breite des dunklen Kerns */
  --pz-focus-ring-w: 4px;   /* Kern + Halo zusammen, Halo also ebenfalls 2px */
  --pz-line-d: rgba(247, 244, 238, .16);
  --pz-serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --pz-sans: 'Inter', 'Helvetica Neue', Arial, sans-serif;
}

/* pz: Die Skala schrumpft an EINER Stelle — dadurch braucht KEINE Sektion in
   irgendeiner Bereichsdatei noch eine eigene Media-Query fuer Abstaende.
   (Vorher stand `padding: 72px 0` handverlesen in vier Dateien.) */
@media (max-width: 991.98px) {
  :root {
    --pz-sek: 72px; --pz-sek-band: 56px; --pz-sek-lead: 48px; --pz-sek-nav: 24px;
    --pz-sek-halb: 36px; --pz-band-halb: 28px; --pz-lead-halb: 24px; --pz-nav-halb: 12px;
  }
}
@media (max-width: 575.98px) {
  :root {
    --pz-sek: 48px; --pz-sek-band: 40px; --pz-sek-lead: 32px; --pz-sek-nav: 20px;
    --pz-sek-halb: 24px; --pz-band-halb: 20px; --pz-lead-halb: 16px; --pz-nav-halb: 10px;
    /* Karte: Polster folgt der Mobilstufe derselben Kartenrhythmik */
    --pz-card-pad: 12px;
    /* Kaufpfad-Bild: mobil kleiner (Rechnung siehe Token-Kommentar oben) */
    --pz-kaufpfad-img: 110px;
  }
}

/* ============================================================================
   pz: NOVA-Zuschlaege an der BASIS neutralisieren (Skalen-Regel 4).
   Gemessen 19.08. (1440): #content-wrapper padding-top 64, #content
   padding-bottom 48, .breadcrumb-wrapper margin-bottom 32 — drei Werte, die
   sich auf JEDER Seite zu den Sektionsmassen dazuaddierten. Der 48px-Rest
   unter dem letzten Band war der "Ivory-Streifen" vor dem dunklen Footer
   (Reviewer F9).
   Nur dort abgeschaltet, wo eine pz-Sektion das Mass selbst traegt — auf
   Konto-/CMS-/Checkout-Seiten bleibt NOVAs Polster unangetastet. */
/* Die drei von uns gestalteten Seitengattungen, ueber ein Merkmal ihres
   EIGENEN Markups adressiert (nie ueber #result-wrapper allein — den benutzt
   NOVA auch im Bestellvorgang, Lehre I.5). */
/* ⚠️ Das ist die NEUTRALISIERUNG von NOVAs 64px, nicht das Endmass. Wo eine
   Seitengattung an dieser Grenze bewusst ein Skalenmass traegt, setzt sie es in
   ihrer Bereichsdatei (Artikelliste: --pz-sek-lead in pz-kategorie.css, Ben/K2).
   Wer hier misst und dort nicht nachsieht, haelt die Stelle faelschlich fuer
   erklaert (Fehlerregister 17). */
#content-wrapper:has(> #content > .pz-section),          /* Startseite */
#content-wrapper.is-item-list,                            /* Artikelliste */
#content-wrapper:has(#result-wrapper > .pz-care) {        /* Artikeldetail */
  padding-top: 0;
}
#content-wrapper:has(> #content > .pz-section) > #content,
#content-wrapper.is-item-list > #content,
#content-wrapper:has(#result-wrapper > .pz-care) > #content {
  padding-bottom: 0;
}

/* Brotkrumen-Streifen: EIN Skalenwert oben wie unten (statt 64 oben / 32 unten) */
#content-wrapper.is-item-list .breadcrumb-container,
#content-wrapper:has(#result-wrapper > .pz-care) .breadcrumb-container { padding-top: var(--pz-sek-nav); }
#content-wrapper.is-item-list .breadcrumb-wrapper,
#content-wrapper:has(#result-wrapper > .pz-care) .breadcrumb-wrapper { margin-bottom: var(--pz-sek-nav); }

/* --- Grundtypografie (Mockup: Inter 15px/1.65, Headlines Cormorant) --- */
/* pz: Reviewer M1 — NOVA legt #main-wrapper auf Weiss und laesst 4 Seiten-
   gattungen als weisse Bloecke im Sand stehen. Grundflaeche an der BASIS
   setzen (Lehre I.6: nie seitenweise scopen). */
#main-wrapper { background: var(--pz-ivory); }

/* pz: Reviewer M11 — NOVAs kaltes Blaugrau (#F5F7FA, bootstrap bg-light) in
   Filterpanels/Warenkorb-Uebersicht passt nicht zur warmen Palette. */
.bg-light { background-color: var(--pz-ivory-2) !important; }

body {
  background: var(--pz-ivory);
  color: var(--pz-text);
  font-family: var(--pz-sans);
  font-size: 15px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* pz: `.modal-title` mit aufgenommen (Review R3/B4-Klasse "Fremdschrift"):
   der Titel des mobilen Filter-Dialogs rendert sonst in Montserrat —
   gemessen 20.08. beim Nachzaehlen der letzten Montserrat-Elemente. */
h1, h2, h3, h4,
.h1, .h2, .h3, .h4,
.modal-title {
  font-family: var(--pz-serif);
  font-weight: 500;
  letter-spacing: -.005em;
  line-height: 1.04;
  color: var(--pz-text);
}

/* pz: 21.08. — Text-Gold statt Flaechen-Gold (siehe Token-Kommentar
   --pz-gold-text). Die <em>-Akzente stehen in h1/h2 auf heller Seite;
   mit --pz-gold waren sie 2,74:1. h1/h2 sind zwar Grosstext (>=24px, dort
   genuegt 3:1) — auch das war gerissen. Jetzt 5,01:1 auf --pz-ivory.
   ⚠️ AUF DUNKLEN BAENDERN DREHT SICH DAS UM: dort misst Text-Gold nur
   3,46:1, Flaechen-Gold dagegen 6,32:1. Die dunklen Baender holen den
   Flaechen-Ton deshalb selbst zurueck — gemessen 21.08. und einzeln
   gesetzt in .pz-hero h1 em und .pz-setband h2 em (pz-startseite.css)
   sowie .pz-care h2 em (pz-artikel.css). Kommt ein weiteres dunkles Band
   mit <em>-Akzent dazu, gehoert dieselbe Zeile dorthin. */
h1 em, h2 em {
  font-style: italic;
  color: var(--pz-gold-text);
}

/* --- NOVA-Gelb (#F8BF00) an allen bekannten Stellen auf CI-Gold ziehen
       (NOVA-LIVE-LEHREN C.1–C.5; !important dort, wo die Lehre es verlangt) --- */

/* C.5 globaler Link-Hover (trifft auch Megamenu-/Dropdown-Ebene) */
a:hover { color: var(--pz-gold); }
#mainNavigation .dropdown-menu a:hover,
.dropdown-menu .dropdown-item:hover { color: var(--pz-gold) !important; }

/* C.1 Nav-Hover */
.navbar-light .navbar-nav .nav-link:hover { color: var(--pz-gold) !important; }

/* C.2 Aktiv-/Hover-Marker der Hauptnav: den 6px-gelben ::before in JEDEM
   Zustand killen (sonst blitzt er beim Un-hovern gelb auf) */
#mainNavigation .nav-item > .nav-link::before { border-bottom: 0 !important; }

/* C.3 Aktiv-Marker Sidebar-Kategorie */
.box-categories .nav-link.active { border-bottom-color: var(--pz-gold) !important; }

/* C.4 Preis-Slider-Handle */
.noUi-handle {
  background: var(--pz-gold) !important;
  box-shadow: none !important;
}
.noUi-connect { background: var(--pz-gold-lt) !important; }

/* --- Wiederverwendbare Bausteine (Markup, das WIR setzen) --- */
.pz-eyebrow {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .24em;
  text-transform: uppercase;
  /* pz: 21.08. — 11px Normaltext auf heller Seite: --pz-gold war 2,74:1,
     --pz-gold-text ist 5,01:1 (AA). Siehe Token-Kommentar. */
  color: var(--pz-gold-text);
}
/* pz: die dunkle Fassung bleibt auf --pz-gold-lt — auf --pz-ink 7,4:1. */
.pz-eyebrow-d { color: var(--pz-gold-lt); }

.pz-lead {
  font-size: 16.5px;
  line-height: 1.75;
  color: var(--pz-muted);
  max-width: 52ch;
}
.pz-lead-d { color: #b9ada0; }

.pz-btn {
  text-decoration: none; /* pz: Reviewer m1 - NOVA unterstreicht a im Ruhezustand */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  /* pz: 20.08. — die Hoehe kommt aus dem Token, nicht mehr aus dem Polster
     (Fehlerregister 11). Optisch identisch (gemessen 58px vorher wie nachher),
     aber ein gestreckter Knopf (Mobil-Raster A2/A3) behaelt die Hoehe seiner
     Gruppe, statt sie aus seinem eigenen Textumbruch zu ziehen.
     `justify-content` wirkt nur im gestreckten Fall — inhaltsbreit bleibt
     alles wie bisher. */
  min-height: var(--pz-ctl-h);
  padding: 0 30px;
  white-space: nowrap;
  border: 0;
  cursor: pointer;
}
.pz-btn svg { width: 15px; height: 15px; }
.pz-btn-gold { background: var(--pz-gold); color: #14110c; }
.pz-btn-gold:hover { background: var(--pz-gold-lt); color: #14110c; }
.pz-btn-ghost { border: 1px solid var(--pz-ctl-line); color: var(--pz-text); background: transparent; }
.pz-btn-ghost:hover { border-color: var(--pz-gold); color: var(--pz-text); }
.pz-btn-ghost-d { border: 1px solid rgba(247, 244, 238, .3); color: #f2ede4; background: transparent; }
.pz-btn-ghost-d:hover { border-color: var(--pz-gold-lt); color: #fff; }

/* ============================================================================
   pz: SEKTIONSLINK ("Alle Kategorien" / "Alle Perlenketten") — NEUBAU 20.08.
   (Ben/A1, Desktop UND Mobil beanstandet: "schön machen … der unterstrichene
   Sperrsatz-Link wirkt billig").

   BEFUND, gemessen 20.08. (1440, Startseite): der Baustein war 158x26px und
   trug ZWEI Linien uebereinander — unsere goldene `border-bottom` UND NOVAs
   `text-decoration: underline`, das auf `a` im Ruhezustand steht und hier nie
   abgeschaltet wurde (bei .pz-btn schon). Ein doppelt unterstrichener
   11px-Sperrsatz in einer 60px-Luecke neben einer 50px-Ueberschrift: genau der
   "billige" Eindruck.

   SOLL: ein eigenstaendiger, ruhiger CTA aus Bausteinen, die es im Projekt
   schon gibt — kein neues Formvokabular:
     Rahmen + Versalien-Label  = .pz-btn-ghost (Ghost-Knopf des Shops)
     abgesetztes Pfeilquadrat  = .pz-cat-arw (Kategorie-Kacheln, gleiche Seite)
   Die Hoehe kommt aus --pz-ctl-h, also aus derselben Quelle wie die
   Hero-/Beratungs-Knoepfe (Fehlerregister 11); die Pfeilzelle ist quadratisch,
   weil sie diese Hoehe als Breite referenziert — nicht als eigener Pixelwert.
   Der Gold-Akzent wandert von der Unterstreichung in die Pfeilzelle: im Hover
   fuellt sie sich, statt dass eine Linie die Farbe wechselt.

   EINE Loesung fuer Desktop und Mobil (Ben: "gleich hässlich wie aufm desktop"):
   unter 576px streckt sich derselbe Baustein auf die Containerbreite
   (Fehlerregister 3b — allein stehend in einer Spalte fuellt er seine Zeile),
   Aufbau und Masse bleiben identisch.
   Markup: layout/header.tpl + page/index.tpl (beide Instanzen, Register 13). */
.pz-tlink {
  display: inline-flex;
  align-items: stretch;
  min-height: var(--pz-ctl-h);
  border: 1px solid var(--pz-ctl-line);
  background: transparent;
  color: var(--pz-ink);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color .3s ease, background-color .3s ease, color .3s ease;
}
.pz-tlink-t {
  display: flex;
  align-items: center;
  padding: 0 24px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
}
.pz-tlink-a {
  flex: none;
  /* quadratisch: die Zelle ist so breit wie die INNENhoehe des Rahmens
     (gemessen 20.08.: 58px Aussenhoehe - 2x1px Rahmen = 56px). Mit dem vollen
     Token waere sie 58x56 gewesen — 2px daneben, und genau solche Ungenauigkeit
     nimmt einem edlen Baustein die Praezision. */
  width: calc(var(--pz-ctl-h) - 2px);
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 1px solid var(--pz-ctl-line);
  /* Ruhezustand schon warm getoent, damit der Baustein als CTA und nicht als
     Formularfeld liest — der Ton ist --pz-gold mit 10 % Deckkraft, also kein
     neuer Farbwert. Im Hover fuellt dieselbe Farbe voll durch. */
  background: rgba(185, 141, 79, .1);
  color: var(--pz-gold);
  transition: inherit;
}
.pz-tlink svg { width: 15px; height: 15px; }
.pz-tlink:hover { border-color: var(--pz-gold); color: var(--pz-ink); }
.pz-tlink:hover .pz-tlink-a {
  background: var(--pz-gold);
  border-left-color: var(--pz-gold);
  color: #14110c;
}
/* pz: Die dunkle Fassung `.pz-tlink-d` (4 Regeln) stand hier als Vorrat fuer
   einen Band-Kopf auf dunklem Grund. Gegen die Templates geprueft (Fixrunde
   8b): keine einzige Instanz im ganzen Child. Toter Selektor — er faellt
   nicht auf, weil nichts kaputt aussieht (Lehre N.13), kostet aber jeden
   Leser eine falsche Annahme darueber, was der Baustein kann. Entfernt;
   wer eine dunkle Fassung braucht, baut sie mit dem dann echten Markup. */
/* Telefon: derselbe Baustein ueber die Containerbreite (Fehlerregister 3b) —
   das Label nimmt den Rest, die Pfeilzelle behaelt ihr Quadrat. */
@media (max-width: 575.98px) {
  .pz-tlink { display: flex; width: 100%; }
  .pz-tlink-t { flex: 1 1 auto; min-width: 0; }
}

/* --- Produktkarte — GRUNDZUSTAND, ueberall (Reviewer M3/M8: der Titel liegt
       in .productbox-title, nicht .productbox-caption — die alte Regel griff
       nie; Scope generisch auf .productbox, damit ALLE Instanzen matchen:
       Kategorie, Suche, Startseiten-Grid UND .recommendations). --- */
.productbox .productbox-title a,
.productbox a.text-clamp-2 {
  font-family: var(--pz-serif);
  font-size: 20.5px;
  line-height: 1.25;
  font-weight: 500;
  color: var(--pz-ink);
  text-decoration: none;
}
.productbox .productbox-title a:hover,
.productbox a.text-clamp-2:hover { color: var(--pz-gold); }
.productbox .price {
  font-size: 19px;
  font-weight: 600;
  color: var(--pz-ink);
}
.productbox .price_wrapper .strike,
.productbox .price_wrapper del { font-size: 13px; color: var(--pz-muted); } /* pz: 21.08. heller Grund -> --pz-muted (muted-d misst hier 2,45:1) */
/* "NEU"-Badge als ruhiges Gold-Rechteck statt grauer Sprechblase */
.productbox .badge-new, .productbox .signal-new {
  background: var(--pz-gold);
  color: #14110c;
  border-radius: 0;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
}

/* --- Sektions-Rhythmus (Skalen-Regel 1 + 2) ---------------------------------
   NOVAs pauschales main-section-Padding wird ersetzt, nicht ergaenzt.
   Jede pz-Sektion traegt ihr FUSSMASS selbst (--pz-sek); das Kopfmass liegt
   bei 0, weil die Vorgaengersektion die Grenze bereits gezogen hat — so kann
   an keiner Grenze etwas stapeln. Eine Sektion, die als ERSTE nach einem
   dunklen Band steht, bekommt zusaetzlich .pz-section-lead.
   !important, weil NOVA das Padding per `main section` (0,0,2) setzt und wir
   sonst je Bereichsdatei nachziehen muessten (Lehre B.1). */
main section.pz-section {
  padding-top: 0 !important;
  padding-bottom: var(--pz-sek) !important;
}
main section.pz-section.pz-section-lead { padding-top: var(--pz-sek-lead) !important; }
/* pz: Halbstufen-Modifier (Ben 20.08.). .pz-section-halb halbiert das
   FUSSMASS der Sektion, .pz-section-halb-top gibt einer farbigen Sektion ein
   halbes KOPFMASS — beides nur ueber die benannten Tokens. */
main section.pz-section.pz-section-halb { padding-bottom: var(--pz-sek-halb) !important; }
main section.pz-section.pz-section-halb-top { padding-top: var(--pz-sek-halb) !important; }

/* Mockup-Raster: Inhalt boxed auf 1280px */
.pz-wrap {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 40px;
}
@media (max-width: 767.98px) {
  .pz-wrap { padding: 0 20px; }
}

/* ============================================================================
   pz: Produktkarte — WEISSE VOLLFLAECHE ABSCHALTEN (Ben 19.08.: "der text
   klebt direkt am rand", FEHLERMUSTER.md Zeile 2).
   Ursache war NICHT .productbox{background} (das stand schon auf transparent),
   sondern NOVAs Pseudo-Element: _productbox.scss Zeile 5 legt
   `.productbox.productbox-hover .productbox-inner::before` als weisse
   $card-bg-Flaeche ueber die GANZE Karte (nur >=md). Gemessen 19.08. per
   elementsFromPoint: getComputedStyle(inner,'::before').backgroundColor
   = rgb(255,255,255), Pixelprobe im Screenshot 255,255,255 bis zur CTA-Zeile.
   SOLL (mockup-startseite.html .card): Karte transparent auf Ivory, nur die
   Bildbuehne ist eine Flaeche.
   Gleiche Spezifitaet wie NOVA (0,3,0) -> Quellreihenfolge entscheidet,
   pz-base laedt nach my-nova.css. Der Hover-Zustand wird MITGENOMMEN
   (Fehlerregister 2/14): NOVA zieht das ::before on-hover um 1rem nach
   aussen und legt einen Schatten darunter. Beides aus. */
.productbox.productbox-hover .productbox-inner::before,
.productbox.productbox-hover:hover .productbox-inner::before,
.productbox.productbox-hover:focus .productbox-inner::before,
.productbox.productbox-hover.focus .productbox-inner::before,
.productbox.productbox-hover:focus-within .productbox-inner::before {
  background-color: transparent;
  box-shadow: none;
  outline: 0;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

/* ============================================================================
   pz: KARTENPLATTE (Ben 20.08./K6).
   Traeger ist die AEUSSERE Karte (.productbox-column), NICHT .productbox-images
   und NICHT .productbox-inner::before — Fehlerregister 1: eine Flaeche auf dem
   gemeinsamen Container der beiden Bild-Wrapper (first/second) verdeckt das
   erste Bild. Die Platte liegt eine Ebene darueber und kann das nicht.
   Das Polster ist auf ALLEN vier Seiten gleich, damit die im Mockup
   vereinbarte Buendigkeit Titel<->Bildbuehne erhalten bleibt: beide ruecken um
   denselben Betrag ein (Fehlerregister 22 / FEHLERMUSTER.md Zeile 2).
   Generisch an der Basis, weil die Karte auf Startseite, Kategorie, Suche und
   Merkzettel dieselbe ist (Fehlerregister 17 — nicht wieder nur eine Instanz).
   ⚠️ Der Hover fasst AUSSCHLIESSLICH Flaeche, Kante und Schatten der Platte an —
   kein transform, kein Bildwechsel, keine Verschiebung von Fahne oder Overlay
   (Fehlerregister 2 "Hover verreisst Karten/Overlays"; Lehre F.4). */
.productbox.productbox-column {
  padding: var(--pz-card-pad);
  background-color: var(--pz-card-bg);
  border: 1px solid var(--pz-card-line);
  transition: background-color .35s ease, border-color .35s ease, box-shadow .35s ease;
}
.productbox.productbox-column:hover,
.productbox.productbox-column:focus-within {
  background-color: var(--pz-card-bg-hover);
  border-color: var(--pz-line);
  box-shadow: 0 14px 34px -18px rgba(18, 16, 13, .38);
}
/* Die Listenansicht traegt NOVAs eigene Kartenflaeche (das ::before des
   .productbox-inner, oben pauschal abgeschaltet). Sie kommt hier in CI-Ton
   zurueck, statt sie halb abgeschaltet stehen zu lassen — das ist Bens
   Default-Loesung fuer Zweitansichten: NOVA-Standard, nur die Farbgebung auf CI
   (Fehlerregister 23 / FEHLERMUSTER.md Zeile 3). */
.productbox.productbox-row .productbox-inner::before,
.productbox.productbox-row.productbox-hover:hover .productbox-inner::before,
.productbox.productbox-row.productbox-hover:focus .productbox-inner::before,
.productbox.productbox-row.productbox-hover.focus .productbox-inner::before,
.productbox.productbox-row.productbox-hover:focus-within .productbox-inner::before {
  background-color: var(--pz-card-bg);
  border: 1px solid var(--pz-card-line);
}

/* ============================================================================
   pz: LABEL/WERT-ZEILEN DER PRODUKTKARTE — EINE FASSUNG FUER ALLE INSTANZEN
   (Audit L5, Fehlerregister 13 + 17).
   JTL rendert "Artikelnummer: PZ-P026" als `dl.form-row` mit `dt.col-6` und
   `dd.col-6` — ein fester 50/50-Split, der nie stimmen kann, weil die
   Labelbreite vom Wort abhaengt.
   Der Fix stand bis heute NUR in pz-kategorie.css, gescopet auf
   `.product-list.layout-list .productlist-item-detail`. Genau daneben lag
   dieselbe Mechanik ungefixt: das WARENKORB-MODAL rendert seine Artikelzeile
   ebenfalls als Produktbox (gemessen 20.08., 1440: dt bei x546 (358 breit),
   dd bei x905 — 355px Luecke zwischen "Artikelnummer:" und dem Wert).
   Fehlerregister 17: der Wert ist nicht auf der Liste falsch, sondern
   ueberall -> die Korrektur gehoert an die Basis, in EINER Fassung.
   Anker ist `.productbox-inner` (gemessene gemeinsame Huelle beider
   Instanzen), nicht die seitenspezifische Listenklasse.
   Label bekommt Inhaltsbreite, der Wert den Rest. */
.productbox-inner dl.form-row { flex-wrap: nowrap; }
.productbox-inner dl.form-row > dt {
  flex: 0 0 auto;
  width: auto;
  max-width: none;
  padding-right: 8px;
}
.productbox-inner dl.form-row > dd {
  flex: 1 1 auto;
  width: auto;
  max-width: none;
  min-width: 0; /* Fehlerregister 15 */
}

/* ============================================================================
   pz: Bootstrap-Graublau (#f5f7fa = $light) auf die warme Palette ziehen.
   ⚠️ Korrektur der Review-Diagnose: Der Inline-Block setzt zwar
   `:root{--light:#f5f7fa}`, aber KEINE einzige Regel benutzt `var(--light)`
   (19.08. gemessen: styleSheets-Scan ueber alle 5.5k Regeln -> 0 Treffer).
   Die Farbe steckt als KOMPILIERTES Hex in ~154 Bootstrap-Regeln. Ein
   :root-Override waere wirkungslos gewesen - deshalb hier per Selektor.
   Nur die Regeln, die im Shop wirklich Flaeche zeigen. */
.card-gray,
.stepper,
.card-header,
.card-footer,
.progress,
.badge-light,
.badge-gray-light,
.box-categories .dropdown .collapse,
.box-linkgroup .dropdown .collapse,
.config-table .accent-bg,
.list-group-wrapper.disabled .list-group-item,
.swatches-text.active,
.comparelist .table tbody td:first-child,
.product-matrix .matrix-list-wrapper > .matrix-list:nth-of-type(odd),
.table-striped tbody tr:nth-of-type(even) { background-color: var(--pz-ivory-2); }

.alert-info,
.bg-info { background-color: var(--pz-ivory-2) !important; }

/* Der Stepper-Pfeil ist ein Border-Dreieck in derselben Farbe (sonst bleibt
   ein graublauer Keil zwischen den Schritten stehen). */
.stepper .step::after { border-left-color: var(--pz-ivory-2); }

.card { border-color: var(--pz-line); }
.card-header { border-bottom-color: var(--pz-line); }
.card-footer { border-top-color: var(--pz-line); }
.alert-info { border-color: var(--pz-line); color: var(--pz-text); }
.bubble { border-color: var(--pz-ivory-2); }
.new-shipping-address,
.select-shipping-address .dataTables_wrapper { border-color: var(--pz-line); }
.text-truncate-fade::after {
  background: linear-gradient(to right, rgba(247, 244, 238, 0), var(--pz-ivory) 50%);
}

/* ============================================================================
   pz: Bootstrap-Grau (#525252 = $body-color/$dark/$info) auf Palette ziehen.
   Gleiche Korrektur wie oben - `var(--dark)`/`var(--info)` wird nirgends
   benutzt, die Farbe steht kompiliert in den Regeln. */
.form-control,
.custom-select,
.input-group-text,
.form-control-plaintext { color: var(--pz-text); }
.page-link,
.dropdown-item,
.dropdown-menu,
.dropdown-item-text,
.list-group-item-action,
.breadcrumb-item.active { color: var(--pz-text); }
.text-body { color: var(--pz-text) !important; }
/* ============================================================================
   pz: "NEU"-FAHNE — CI-TON STATT SCHWARZ (Ben 20.08./K5, Nachtrag: "mach die
   schwarzen overlays bei den artikeln bitte in einem angenehmeren CI ton ...
   das is zu heftig ... (barrierefreiheit beachten)").
   Vorher: NOVAs `.ribbon-3` ist Bootstrap-Grau, von uns auf --pz-ink (#12100d)
   gezogen — ein harter schwarzer Block auf dem Foto.
   Jetzt: --pz-gold auf --pz-ink-Schrift. Das ist KEIN neuer Ton, sondern exakt
   die Behandlung, die `.badge-new` in diesem Stylesheet schon hat — der Shop
   bekommt damit EINE Badge-Sprache statt zweier.
   Barrierefreiheit GEMESSEN (nicht geschaetzt), WCAG 2.1 Kontrastformel auf den
   computed values: #b98d4f gegen #14110c = 6.26:1. Das ist AA (>=4.5:1) auch
   fuer die kleine 9,5px-Versalienschrift, und sogar AAA-Niveau fuer Grossschrift.
   Der Wert wird im Browser nachgerechnet (siehe Messprotokoll der Fixrunde). */
.ribbon-3 {
  background-color: var(--pz-gold);
  color: #14110c;
}

/* ============================================================================
   pz: .btn-primary GENERISCH auf CI (Reviewer F2).
   Der Fix hing bisher an #product-offer (pz-artikel.css) - ausserhalb der
   Artikelseite blieb NOVAs `.btn-primary{color:#525252}` auf Gold stehen:
   Kontrast 2,7:1 und keine CI-Typo. Lehre I.6/Fehlerregister 17: der Wert ist
   nicht auf der PDP falsch, sondern ueberall -> Korrektur an die Basis.
   Die PDP-Regel bleibt bestehen (dort zusaetzlich Hoehe 58px). */
.btn-primary,
.btn-primary:disabled,
.btn-primary.disabled {
  background-color: var(--pz-gold);
  border-color: var(--pz-gold);
  color: #14110c;
  border-radius: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary.focus,
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.show > .btn-primary.dropdown-toggle {
  background-color: var(--pz-gold-lt);
  border-color: var(--pz-gold-lt);
  color: #14110c;
  box-shadow: none;
}

/* pz: Sekundaer-Buttons (Kategorie-Filterleiste, "Zurueck", "Aendern") in der
   gleichen CI-Typo - ohne Gold-Flaeche (Reviewer m14/m8). */
.btn-outline-secondary,
.btn-outline-secondary:disabled {
  color: var(--pz-ink);
  border-color: var(--pz-ctl-line);
  border-radius: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  background-color: transparent;
}
/* ⚠️ NACHTRAG 20.08. (B2, am offenen Dropdown gemessen): Ein GEOEFFNETER
   Toggle bekam von Bootstrap `background-color: rgb(235,235,235)` — ein kaltes
   Grau mitten in der warmen Palette. Die Regel dafuer heisst
   `.show > .btn-outline-secondary.dropdown-toggle` (0,3,0) bzw. trägt `.active`;
   unsere alte Kette kannte nur `:active` (den gedrueckten Moment) und verlor
   deshalb genau im Dauerzustand "Menue offen".
   Betrifft JEDEN Dropdown-Knopf des Shops (Sortierung, Artikel pro Seite,
   Seitenwahl) — Fehlerregister 14 + 17: Zustand nie ausgeloest, Wert ueberall
   falsch, Korrektur an der Basis. */
.btn-outline-secondary:hover,
.btn-outline-secondary:focus,
.btn-outline-secondary:not(:disabled):not(.disabled):active,
.btn-outline-secondary:not(:disabled):not(.disabled).active,
.show > .btn-outline-secondary.dropdown-toggle {
  background-color: transparent;
  border-color: var(--pz-gold);
  color: var(--pz-ink);
  box-shadow: none;
}

/* pz: `.btn-outline-primary` war projektweit UNGESTALTET (Ben 20.08./D1:
   Buttons der Warenkorb-Zwischenseite "katastrophal BUGGY").
   Befund 20.08.: gestylt war bisher nur `.btn-outline-secondary` — NOVA
   benutzt auf dem gesamten Kaufpfad aber `.btn-outline-primary` als
   Gegenstueck zum Gold-Button: "Weiter einkaufen" (Zwischenseite),
   "Zur Kasse" (Warenkorb-Dropdown), "Warenkorb aendern" (Zusammenfassung).
   Er stand dort in NOVAs Blaugrau neben unserem Gold-Button — zwei Buttons
   aus zwei Welten in EINER Gruppe.
   Fehlerregister 17: der Wert ist nicht auf der Zwischenseite falsch,
   sondern ueberall -> an die Basis, in exakt derselben Optik wie
   `.btn-outline-secondary` (EIN Ghost-Button im Projekt, nicht zwei). */
.btn-outline-primary,
.btn-outline-primary:disabled {
  color: var(--pz-ink);
  border-color: var(--pz-ctl-line);
  border-radius: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  background-color: transparent;
}
.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:not(:disabled):not(.disabled):active,
.btn-outline-primary:not(:disabled):not(.disabled).active,
.show > .btn-outline-primary.dropdown-toggle {
  background-color: transparent;
  border-color: var(--pz-gold);
  color: var(--pz-ink);
  box-shadow: none;
}

/* pz: KEIN UNTERSTRICHENER TEXT IN BUTTONS (Ben 20.08./D1).
   Gemessen auf der Zwischenseite: beide Knoepfe `text-decoration: underline`
   — sie sind `<a class="btn">` (Smarty `{link class="btn …"}`), und NOVA
   unterstreicht `a` im Ruhezustand. Betroffen ist damit JEDER als Link
   gerenderte Button im Shop, nicht nur diese Seite (Fehlerregister 17).
   `.btn-link` bleibt ausgenommen: der IST ein Textlink ("Aendern" in den
   Kartenkoepfen der Zusammenfassung) und soll unterstrichen bleiben.
   Spezifitaet 0,2,0 schlaegt NOVAs `a` (0,0,1) und `.alert a` (0,1,1) —
   kein !important noetig (Fehlerregister 16). */
.btn:not(.btn-link),
.btn:not(.btn-link):hover,
.btn:not(.btn-link):focus { text-decoration: none; }

/* pz: D8 — EXPRESS-ZAHLARTEN-RASTER DARF NIE UEBER SEINE KARTENKANTE RAGEN
   (Ben 20.08.; NOVA-LIVE-LEHREN O.5, bei spanl @390 gemessen: 356px Raster
   in 324px Inhaltsbreite).
   Ursache: die Plugins liefern ihre Buttons in einer eigenen Bootstrap-`.row`
   (`.lpa-button-content.row` bei AmazonPay). Eine `.row` bringt die
   Gutter-Negativraender mit, ihre Kinder aber kein ausgleichendes Polster —
   das Raster steht dann links und rechts je 15px ueber dem Kasten, in dem es
   sitzt.
   Warum an der Basis und nicht in pz-artikel.css: dieselben Plugins rendern
   auf der Artikelseite, im Warenkorb UND im Bestellvorgang. Der Wert ist
   nicht auf einer Seite falsch, sondern ueberall (Fehlerregister 17).
   Die Regel steht bewusst schon jetzt da, obwohl noch keine Express-Zahlart
   aktiv ist: sie kostet nichts und greift in dem Moment, in dem der Kunde
   eine einschaltet — genau der Fall, den O.5 beschreibt.

   ⚠️ FIXRUNDE 8b / N6: Die Regel hing bis dahin nur an den AmazonPay-Klassen
   (`.lpa-*`). Die zweite Plugin-Bauart hat sie damit nicht erwischt — PayPal
   liefert sein Funding-Paar als schlichte `.row > .col-sm-6` OHNE eigene
   Plugin-Klasse (O.5). Gegengemessen mit einer Probe in Plugin-Massen: je
   16px Ueberstand ueber `#add-to-cart` bei 390. Fehlerregister 17 in
   Reinform — nicht der AmazonPay-Fall war falsch, sondern der Scope.
   Deshalb jetzt an den EINHAENGEPUNKTEN der Sperrliste (O.5) statt an den
   Plugin-Klassen: was auch immer ein Plugin dort hineinhaengt, kann seine
   Gutter nicht mehr ueber die Kante schieben.
   ⚠️ Bewusst NUR die Plugin-Einhaengepunkte, nicht `.row` global:
   NOVAs eigenes Grid RECHNET mit den Negativraendern (die Spalten gleichen
   sie mit ihrem Polster aus). Eine globale Neutralisierung rueckt jede
   Zeile des Shops um 15px ein.
   ⚠️ GENAU DAS IST MIR HIER PASSIERT und wurde in derselben Runde wieder
   zurueckgenommen: `.cart-summary .row` stand kurzzeitig mit in der Liste
   (aus dem Briefing uebernommen). Gemessen auf /Warenkorb kostete das die
   Fluchtlinie der Bestelluebersicht — Kartenkopf und Coupon-Hinweis bei
   944…1329, die Betragszeilen und "Zur Kasse" danach bei 968…1305.
   Nutzen null: die Zahlarten-Plugins haengen sich im Warenkorb NICHT in eine
   nackte `.cart-summary .row`, sondern in ihre eigenen Container
   (`#ppc-paypal-button-cart…`, `.lpa-*`) — die stehen unten schon drin.
   Ein Fix, der eine Fluchtlinie kaputtmacht, um einen Fall abzudecken, den
   es nicht gibt, ist teurer als der Befund (Fehlerregister 11: gemeinsame
   Kanten pruefen, nicht nur "kein Overflow"). */
.lpa-button-content.row,
.lpa-button-context-payDetail > .row,
#add-to-cart .row,
[id^="ppc-"] .row {
  margin-left: 0;
  margin-right: 0;
}

/* ============================================================================
   pz: Produktkarte — BILDBUEHNE + ABSTANDSKETTE, generisch fuer JEDE
   .productbox-Instanz (Startseite, Kategorie, Suche, Merkzettel).
   Fehlerregister 17: der Wert ist nicht auf einer Seite falsch, sondern
   ueberall - deshalb an der Basis und nicht je Bereichsdatei.
   SOLL = mockup-startseite.html .card:
     .imgbox  aspect-ratio 4/3
     h3       margin-top 24px, min-height 52px
     .prices  margin-top 16px
     .vat     margin-top 5px
     .tlink   margin-top 20px
   ⚠️ KORREKTUR 20.08. (Review R3, Fehlerregister 19 "Metrik pruefen, nicht
   nur den Wert"): Die frueher hier stehende Begruendung fuer eine WEISSE
   Buehne mit `object-fit:contain` stimmte fuer das Rendering, nicht fuer den
   Blick — mit contain stand jedes Foto als Briefmarke in einer grossen
   weissen Flaeche (gemessen /Perlenketten 1440: Buehne 430x323, Bild darin
   in Naturhoehe, oben/unten Weissbaender). SOLL laut Mockup .card .imgbox:
   Buehne ivory-2, Bild formatfuellend. Die Fotokante verschwindet damit
   nicht, sie wird weggeschnitten — genau das will `cover`.
   An der BASIS, damit Startseite, Kategorie, Suche, Merkzettel und der
   PDP-Slider dieselbe Buehne haben (Fehlerregister 17: nicht wieder nur
   eine Instanz).
   ⚠️ SCOPE-KORREKTUR 20.08. (Ben/K4, Fehlerregister 23): Dieser Block ist
   GEOMETRIE, kein Farbwert — und er traf bisher auch NOVAs Listenansicht
   (`.productbox-row` benutzt dieselbe .productbox-Klasse). Dort stand die
   Bildspalte nur ~110px breit, das erzwungene 4/3 machte daraus eine 84x63-
   Briefmarke. Deshalb ab hier `:not(.productbox-row)`: die Kachelkarte
   bekommt die Mockup-Buehne, die Listenansicht behaelt NOVAs Standardmasse
   und bekommt NUR Farbe/Schrift (Bens Default fuer Zweitansichten).
   Die FARB- und SCHRIFT-Regeln der Karte (Titel-Serif, Preis-Familie,
   Fahne, Verfuegbarkeits-Ton) bleiben bewusst ungescoped — genau die sollen
   in beiden Ansichten gelten. */
.productbox:not(.productbox-row) .productbox-images {
  background: var(--pz-ivory-2);
  border: 1px solid var(--pz-line);
}
/* 4/3 statt NOVAs Quadrat: `.square::before{padding-bottom:100%}` erzeugt das
   Seitenverhaeltnis (base_crit.scss) - 75% = 4/3. Ben 19.08.: die quadratische
   Buehne war eine ~290px hohe fast leere Weissflaeche. */
.productbox:not(.productbox-row) .productbox-images .square::before { padding-bottom: 75%; }
/* Bild fuellt die Buehne FORMATFUELLEND aus (cover statt contain, Review R3).
   ⚠️ Beide Wrapper: NOVA legt das Hover-Zweitbild in .second-wrapper — eine
   Regel nur auf .first-wrapper haette dort wieder eine Briefmarke gelassen
   (Fehlerregister 13: jede Instanz des Bausteins). */
.productbox:not(.productbox-row) .productbox-images .square-image .inner img,
.productbox:not(.productbox-row) .productbox-images .first-wrapper img,
.productbox:not(.productbox-row) .productbox-images .second-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.productbox:not(.productbox-row) .productbox-title {
  top: 0; /* NOVA versetzt den Titel per position-top um 8px */
  margin-top: 24px;
  min-height: 52px; /* Mockup .card h3 - haelt Preiszeilen ueber die Reihe buendig */
}
.productbox:not(.productbox-row) .price_wrapper { margin-top: 16px; margin-bottom: 0; }
.productbox .price-note:empty { display: none; }
/* pz: Ausnahme fuer JTLs "kein Bild"-Platzhalter (gfx/keinBild.gif, 130px):
   hochskaliert wuerde daraus eine formatfuellende graue Kamera. Er bleibt
   in Naturgroesse und ist durch die 4/3-Buehne trotzdem deutlich besser
   ausgefuellt als vorher (130/209 = 62 % statt 130/278 = 47 % Buehnenhoehe).
   Sobald die Wawi Artikelbilder liefert, greift die Regel darueber wieder. */
.productbox:not(.productbox-row) .productbox-images .square-image .inner img[src*="keinBild"] {
  width: auto;
  height: auto;
  object-fit: contain;
}

/* ============================================================================
   pz: "NEU"-FAHNE FLACH INS BILDECK (Review R3, Fehlerregister 2 "Hover
   verreisst Badges").
   Gemessen 19./20.08. (/Perlenketten, 1440): Ruhezustand `top:1rem;
   left:-0.5rem` (Fahne ragt 8px links aus der Buehne), im Hover springt NOVA
   auf `top:-0.5rem; left:-1.5rem` — die Fahne steht dann frei NEBEN der
   Karte. Dazu ein Sprechblasen-Zipfel aus ::before/::after und ein Schatten.
   SOLL: flach im Bildeck, in JEDEM Zustand identisch.
   ⚠️ Die Selektorkette ist bewusst 1:1 die von NOVA (0,5,0 im Hover-Fall) —
   eine kuerzere Kette mit !important haette den Hover-Sprung NICHT geschlagen
   (Fehlerregister 16: innerhalb der important-Ebene entscheidet weiter die
   Spezifitaet). pz-base laedt nach my-nova.css, also gewinnt Gleichstand.

   ⚠️ KORREKTUR 20.08. (Ben/K5): Der Flush-Stand 0/0 von heute frueh war zu
   hart — "die overlays muessen mehr nach innen eingedrueckt werden, von oben
   und von links / sonst sieht der uebergang zum rand hier scheisse aus".
   Die Fahne rueckt deshalb um --pz-nav-halb (16px, benannte Skalenstufe, kein
   freier Wert) in die Buehne hinein, oben wie links gleich viel. Der Wert zieht
   responsiv mit (12 / 10px) und gilt fuer JEDE Instanz der Fahne — Kachel- wie
   Listenansicht, Startseite, Kategorie und Suche (Fehlerregister 17). */
.productbox .productbox-ribbon.ribbon,
.productbox.productbox-hover:hover .productbox-ribbon.ribbon,
.productbox.productbox-hover:focus .productbox-ribbon.ribbon,
.productbox.productbox-hover.focus .productbox-ribbon.ribbon,
.productbox.productbox-hover:focus-within .productbox-ribbon.ribbon {
  top: var(--pz-nav-halb);
  left: var(--pz-nav-halb);
  border-radius: 0;
  box-shadow: none;
  font-family: var(--pz-sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .18em;
  padding: 6px 12px;
}
/* Der Zipfel ist reine Sprechblasen-Deko und passt nicht zur flachen Ecke. */
.productbox .productbox-ribbon.ribbon::before,
.productbox .productbox-ribbon.ribbon::after { content: none; }
/* Schriftfarbe der Fahne: siehe .ribbon-3 weiter oben (Gold-Flaeche, Ink-Text,
   gemessen 6.26:1). Frueher stand hier --pz-ivory auf schwarzer Flaeche. */
.productbox .productbox-ribbon.ribbon-3 { color: #14110c; }

/* ============================================================================
   pz: FREMDSCHRIFT MONTSERRAT IN DER PREISZEILE (Review R3).
   Gemessen 20.08. (/Perlenketten, 1440): `.price.productbox-price`, das
   innere <span> und `.footnote-reference` rendern in Montserrat 19px —
   NOVAs Kompilat setzt die Preis-Schrift ueber eine eigene Familie, und die
   Startseiten-Instanz sah nur deshalb richtig aus, weil dort eine
   .pz-prodgrid-Regel die Familie mitgab (Fehlerregister 13: eine Instanz
   gefixt, die anderen nicht). Deshalb generisch an der Basis. */
.productbox .price,
.productbox .price span,
.productbox .price .footnote-reference,
.productbox .price_wrapper .strike,
.productbox .price_wrapper del,
.x-related .item-slider-price .price,
.x-related .item-slider-price .price span,
.x-related .item-slider-price .footnote-reference { font-family: var(--pz-sans); }

/* ============================================================================
   pz: VERFUEGBARKEITS-GRUEN AUF DIE PALETTE (Review R3).
   Gemessen: Bootstraps `rgb(28,135,30)` ("Sofort verfuegbar") ist der einzige
   Signalton der Seite, der nicht aus der warmen Palette kommt.
   Das Mockup kennt keinen Verfuegbarkeitston — deshalb EIN benanntes Token
   statt eines freien Hex an drei Stellen; Wert ist ein entsaettigtes,
   waermeres Gruen mit >=4.5:1 auf ivory (#f7f4ee) — Token --pz-ok oben.

   ⚠️ Die Klassen sind GEMESSEN, nicht geraten: ein Scan ueber alle Elemente
   nach `rgb(28,135,30)` lieferte genau `span.status.status-2` (der Text) und
   `span.status-icon` (das LKW-Symbol) — `.text-success` allein hatte keinen
   einzigen Treffer (Fehlerregister 13/16).

   ⚠️ Bewusst NUR `status-2` (= verfuegbar), nicht `.status` pauschal: NOVA
   benutzt dieselbe Klasse mit status-1/-3 fuer "nicht verfuegbar" und
   "in Kuerze" — ein pauschaler Gruenton haette ausgerechnet die
   Nicht-Verfuegbarkeit gruen gefaerbt. Die anderen Zustaende bleiben
   unangetastet (im Bestand kein Artikel damit; als offener Punkt gemeldet).

   ⚠️ NACHTRAG 20.08. (Audit L3, Fehlerregister 13 "Regel trifft nur eine von
   mehreren Instanzen"): Die Artikelseite rendert `span.status.status-2`, die
   KATEGORIE-LISTENANSICHT dagegen `div.signal_image.status-2` (gemessen
   /Perlencolliers?ed=1, 1440: color rgb(28,135,30) = Bootstrap-Gruen,
   Kontrast 4,04:1 auf der Kartenplatte #f3efe6 — unter AA). Die Regel oben
   traf diese zweite Huelle nie. Zwei Markups, eine Aussage -> beide an
   denselben Ton.
   KONTRAST GEMESSEN (WCAG 2.1 auf den computed values, im Browser
   nachgerechnet): --pz-ok #4f6a42 auf --pz-card-bg #f3efe6 = 5,27:1 (AA),
   auf --pz-ivory #f7f4ee = 5,51:1. Der Token-Wert bleibt deshalb unveraendert
   — er traegt beide Untergruende. */
.text-success,
.status.status-2,
.signal_image.status-2,
.stock-information li:has(.status-2) .status-icon,
.delivery-status .text-success { color: var(--pz-ok) !important; }
.text-success .fas, .text-success .far, .text-success svg { color: inherit; }

/* ============================================================================
   pz: Formularfelder — EINE Hoehe, EIN Rahmenton (Reviewer m9,
   Fehlerregister 11). Gemessen 19.08. im Bestellvorgang:
   input  h 43.0  border 1px #707070      radius 2px
   select h 39.3  border 1px pz-line      radius 0
   Beides an denselben Wert: 46px (>= 44px Tap-Ziel, m13) und der
   Rahmenton der uebrigen CI-Elemente (Stepper, Ghost-Buttons).
   `min-height` statt `height`, damit gesetzte Sonderhoehen (Suchfeld im
   Kopf, Stepper der Kaufzeile) weiterhin gewinnen. */
.form-control,
.custom-select,
select.form-control,
textarea.form-control {
  /* pz: 20.08. — derselbe Wert wie bisher, jetzt aus dem Token (siehe
     --pz-ctl-h-sm oben): Formularfeld und Karten-CTA teilen sich EINE
     Steuerelement-Hoehe statt zweier gleich grosser Einzelwerte. */
  min-height: var(--pz-ctl-h-sm);
  max-height: none; /* Lehre I.6: NOVA deckelt Form-Controls per max-height */
  border: 1px solid var(--pz-ctl-line);
  border-radius: 0;
}
textarea.form-control { min-height: 110px; }
.form-control:focus,
.custom-select:focus {
  border-color: var(--pz-gold);
  box-shadow: none;
}
/* Die Zahl im Mengen-Stepper zieht ihre Hoehe aus der Gruppe (pz-artikel/
   pz-warenkorb) - min-height darf sie nicht auseinanderdruecken. */
.form-counter .form-control { min-height: 0; }

/* ============================================================================
   pz: FOKUSRING PROJEKTWEIT (Ben-Freigabe 20.08., F5). Tokens und die
   Begruendung fuer die Zweifarbigkeit stehen oben im :root-Block.

   AUFBAU (zwei Ringe aus EINEM Elementrand heraus, beide layoutneutral):
     0…2px  outline    --pz-focus-core (Ink)   — traegt auf hellem Grund
     2…4px  box-shadow --pz-focus-halo (Ivory) — traegt auf dunklem Grund
   Der `box-shadow`-Spann laeuft von 0…4px; die outline wird DARUEBER
   gezeichnet und deckt seine inneren 2px ab. Das Ergebnis sind zwei saubere
   2px-Baender, ohne dass ein zweites Element noetig waere.
   `outline-offset: 0` statt NOVAs 1px: mit Versatz entstuenden drei Baender
   (Halo / Kern / Halo) und der Ring franste optisch aus.
   `border-radius` bleibt bewusst unangetastet — die Ringe folgen der
   jeweiligen Elementform, und der Shop ist ohnehin durchgehend eckig.

   ⚠️ NUR `:focus-visible` (plus Bootstraps `.focus`, das NOVA in derselben
   Regel bedient): Mausklicks bleiben unberuehrt, der Ring erscheint bei
   Tastaturbedienung.

   ⚠️ WARUM `!important` — die Gegenspieler wurden gesucht, nicht geraten
   (Fehlerregister 16). Es sind DREI eigene Regeln aus frueheren Runden, die
   Bootstraps blauen Fokus-Schein abschalten sollten und dafuer pauschal
   `box-shadow: none` auf `:focus` setzen:
     .btn-primary:focus / .focus            (0,2,0)  — oben in dieser Datei
     .btn-outline-secondary:focus           (0,2,0)  — oben in dieser Datei
     .form-control:focus, .custom-select:focus (0,2,0) — oben in dieser Datei
   Sie sind spezifischer als `:focus-visible` (0,1,0) und wuerden den Halo
   still wegnehmen. Sie umzuschreiben waere der sauberere Weg, sie sollen
   aber genau das weiter tun, was sie tun (Maus-Fokus ohne Schein) — der
   Ring ist der Sonderfall und setzt sich deshalb hier durch.
   ⚠️ Die Kette enthaelt `.btn:focus-visible` mit, weil NOVAs Originalregel
   genau so heisst (0,2,0) und eine kuerzere Kette den Button-Fall NICHT
   geschlagen haette. */
:focus-visible,
.btn:focus-visible,
.form-control:focus-visible,
.custom-select:focus-visible,
.focus {
  outline: var(--pz-focus-w) solid var(--pz-focus-core) !important;
  outline-offset: 0 !important;
  box-shadow: 0 0 0 var(--pz-focus-ring-w) var(--pz-focus-halo) !important;
}

/* ============================================================================
   pz: Tap-Ziele mobil (Reviewer m13). Gemessen: Checkout-Buttons 43px,
   "Aendern" 32-35px, "Vertrag widerrufen" 39px - alle unter den 44px, die
   auf dem Telefon sicher treffbar sind. */
@media (max-width: 991.98px) {
  .btn,
  button.btn,
  a.btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* Ausgenommen: Elemente, deren Hoehe eine Gruppe traegt (Stepper) */
  .form-counter .btn { min-height: 0; }
}

/* ============================================================================
   pz: input-group-Anhaenge auf EINE Hoehe (Reviewer F4, Fehlerregister 11).
   Gemessen 19.08. (Kategorie, Preisspanne): .form-control 46px, der
   angehaengte .input-group-text ("EUR") 31px und 7,5px hoeher sitzend —
   dieselbe Klasse von Fehler wie das hr-kom-Suchfeld. Die Hoehe wird deshalb
   EINMAL an der Gruppe festgelegt und von beiden Teilen referenziert.
   Ausgenommen: der Mengen-Stepper (.form-counter), dessen Gruppenhoehe die
   Kaufzeile vorgibt (pz-artikel.css / pz-warenkorb.css). */
.input-group:not(.form-counter) { align-items: stretch; }
.input-group:not(.form-counter) > .input-group-prepend,
.input-group:not(.form-counter) > .input-group-append {
  display: flex;
  align-items: stretch;
}
.input-group:not(.form-counter) .input-group-text {
  min-height: 46px;
  display: flex;
  align-items: center;
  border: 1px solid var(--pz-ctl-line);
  border-radius: 0;
  background-color: var(--pz-ivory-2);
  color: var(--pz-text);
  font-size: 12px;
  letter-spacing: .06em;
}
/* ⚠️ KORREKTUR 20.08. (Ben/K7: "beim rechten Eingabefeld ist der rechte Rahmen
   abgeschnitten").
   Hier stand bis heute `> .input-group-prepend .input-group-text{border-right:0}`
   — also die Annahme, "prepend" heisse "steht links". Beim Preisspannen-Filter
   stimmt das NICHT: JTLs Markup haengt das EUR-Kaestchen zwar hinter das Feld,
   verpackt es aber in `.input-group-prepend` (gemessen 20.08. per Regel-Scan:
   parent=input-group-prepend, borderRightWidth=0px bei x=305.9-349.0, also
   genau an der Sidebar-Kante). Ergebnis: dem RECHTEN Kaestchen fehlte die
   rechte Kante — der Rahmen sah abgeschnitten aus.
   Die Kante wird deshalb nicht mehr nach dem Klassennamen entschieden, sondern
   nach der tatsaechlichen DOM-Position: verschwinden soll immer nur die Kante,
   die auf einem Nachbarn LIEGT. Das ist unabhaengig davon, wie das jeweilige
   Smarty-Snippet die Huelle nennt (Fehlerregister 13/16: erst messen, welche
   Instanz wirklich rendert). */
.input-group:not(.form-counter) > :not(:first-child) .input-group-text { border-left: 0; }
.input-group:not(.form-counter) > :not(:last-child) .input-group-text { border-right: 0; }
.input-group:not(.form-counter) .btn { border-radius: 0; }

/* ============================================================================
   pz: Meldungs-Toene auf CI (Reviewer F3 — die 404-Seite zeigte Bootstraps
   Rot/Blau/Gruen mitten in der warmen Palette). Generisch in pz-base, weil
   Alerts auf JEDER Seitengattung auftauchen koennen (Fehlerregister 17:
   der Wert ist nicht auf der 404 falsch, sondern ueberall).
   Die Semantik bleibt unterscheidbar: Gold = Hinweis/Warnung, Ink = Fehler,
   Ivory-2 = neutrale Information.

   ⚠️ FIXRUNDE 8b / N14 — DER LINKE 2px-AKZENTBALKEN IST GANZ WEG.
   Bens Beanstandung D1 galt der Erfolgsmeldung auf der Warenkorb-Zwischen-
   seite; der Fix stand danach als Ausnahme fuer `.card-header.alert-*` da —
   und auf /404 (Alert-Danger, freistehend) stand der Balken weiter. Genau
   Fehlerregister 17: der Wert war nicht auf EINER Seite falsch, sondern
   ueberall. Der Balken faellt deshalb an der Basis, nicht in einer zweiten
   Sonderregel.
   Die Semantik traegt jetzt die UMLAUFENDE Rahmenfarbe: Ink = Fehler,
   Gold = Hinweis/Erfolg, Linie = neutrale Information. Ein Ton, eine Kante,
   ueberall gleich — kein Balken, der auf einer Kartenkante doppelt. */
.alert {
  border-radius: 0;
  border: 1px solid var(--pz-line);
  background-color: var(--pz-ivory-2);
  color: var(--pz-text);
  font-size: 14px;
}
/* ⚠️ background-color bleibt an JEDER Variante stehen: Bootstraps
   `.alert-danger`/`-warning`/`-success` haben dieselbe Spezifitaet (0,1,0)
   wie unser `.alert` — die Kurzform oben gewinnt nur ueber die Reihenfolge.
   Ein spaeter geladenes Sheet wuerde das still kippen. */
.alert-danger {
  background-color: var(--pz-ivory-2);
  border-color: var(--pz-ink);
  color: var(--pz-ink);
}
.alert-warning,
.alert-success {
  background-color: var(--pz-ivory-2);
  border-color: var(--pz-gold);
  color: var(--pz-text);
}
.alert a, .alert .alert-link { color: var(--pz-ink); text-decoration: underline; }
.alert .close { color: var(--pz-muted); text-shadow: none; opacity: 1; }

/* pz: FIXRUNDE 8b / N12 — DIE 404-SEITE SAGT ES ZWEIMAL.
   Gemessen 20.08. (1440, /gibtesnicht-xyz): oben ein 1218x49-Alert
   "Entschuldigung, diese Seite wurde leider nicht gefunden.", 130px
   darunter die H1 "Seite nicht gefunden" mit demselben Inhalt und dem
   erklaerenden Fliesstext, den der Alert nicht hat.
   Die Ueberschrift ist die staerkere und vollstaendigere Aussage — der
   Alert ist eine Dopplung im Framework-Ton, die dem Kunden nichts sagt,
   was er nicht schon liest.
   ⚠️ Gezielt ueber `data-key`, NICHT ueber `#alert-list`: der Container
   traegt auf anderen Seiten echte Meldungen (Formularfehler, Hinweise), und
   ein Alert, den der Kunde braucht, darf nicht mit verschwinden. Das
   `data-key`-Attribut bleibt im Markup — es ist Einhaengepunkt der
   Zahlarten-Plugins (NOVA-LIVE-LEHREN O.5). */
.alert[data-key="pageNotFound"] { display: none; }

/* pz: Alert ALS KARTENKOPF (NOVA `productdetails/pushed_success.tpl`:
   `<div class="card alert …">` + `<div class="card-header alert-success">`).
   Hier traegt schon die Karte die Begrenzung — der Kopf darf keine zweite
   Aussenkante danebensetzen. Der Balken ist seit dem Basis-Fix oben ohnehin
   weg; was bleibt, ist das Abraeumen der drei Kanten, die auf der Kartenkante
   liegen wuerden, plus der Bootstrap-Alert-Abstand.
   Spezifitaet 0,2,0 schlaegt die .alert-*-Regeln (0,1,0) ohne !important. */
.card-header.alert-success,
.card-header.alert-info,
.card-header.alert-warning,
.card-header.alert-danger {
  border-top: 0;
  border-left: 0;
  border-right: 0;
  margin-bottom: 0;
}

/* ============================================================================
   pz: Kategorie-Kicker der Produktkarte (Mockup .card .cat-lbl).
   Markup: productlist/item_box.tpl — dort steht auch, warum er nur auf
   Artikellisten erscheint (keine Kategoriedaten im Listen-Artikel ohne
   eine SQL-Abfrage je Karte).
   Er ersetzt den oberen Teil des Titel-Abstands: das Mockup gibt der
   .cat-lbl `margin:24px 0 11px` und der h3 kein eigenes margin-top — die
   24px der Kette bleiben damit erhalten, egal ob der Kicker da ist. */
.productbox .pz-cat-lbl {
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  /* pz: 21.08. — 9,5px auf der Kartenflaeche --pz-card-bg #f3efe6:
     --pz-gold war 2,62:1, --pz-gold-text ist 4,79:1 (AA). */
  color: var(--pz-gold-text);
  /* Mockup .card .cat-lbl: margin 24px 0 11px — die 24px der Kette liegen
     jetzt am Kicker, nicht mehr am Titel. */
  margin: 24px 0 11px;
}
/* ⚠️ Der Kicker ist GESCHWISTER des Titels, nicht sein Kind (gemessen
   19.08.: parent .col.col-12) — eine :has()-Regel am Titel griff deshalb nie
   und der Kicker klebte mit 0px an der Bildunterkante. */
.productbox .pz-cat-lbl + .productbox-title { margin-top: 0; }

/* ============================================================================
   pz: KARTEN-CTA "ZUM ARTIKEL" (Ben 20.08./E1, Grundsatz-Entscheidung:
   "In den Warenkorb auf Produktkarten ergibt bei Schmuck keinen Sinn" —
   der CTA fuehrt jetzt auf die Artikelseite und soll "klar und deutlich /
   schön abbilden").

   ZWEI Aenderungen an einem Baustein:
   (1) Ziel. Aus dem Submit-Knopf des Kaufformulars wird ein Link auf
       $Artikel->cURLFull (Markup: productlist/item_box.tpl und die
       Set-Karten in page/index.tpl — beide Instanzen, Fehlerregister 13).
   (2) Form. Er war ein 11px-Textlink mit goldener Unterlinie — dieselbe
       Machart, die Ben am Sektionslink als "billig" beanstandet hat. Jetzt
       ein flaechiger Ghost-CTA ueber die volle Kartenbreite: die Karte
       bekommt einen sichtbaren Abschluss, der CTA ein Klickziel ueber die
       ganze Zeile statt 170px Text (Fehlerregister 3b).

   ⚠️ Der Baustein steht hier an der BASIS und nicht mehr in pz-startseite.css
   (Fehlerregister 17): dieselbe Karte rendert auf Startseite, Kategorie,
   Suche und Merkzettel. Hoehe aus --pz-ctl-h-sm (46px) — dieselbe Quelle wie
   die Formularfelder, und ueber dem 44px-Tap-Ziel; die frueher noetige
   Mobil-Sonderregel (min-height 44 + eigene Polster) entfaellt damit
   ersatzlos, statt neben dem Token stehen zu bleiben. */
.pz-cardcta-row { margin-top: 20px; }
.pz-cardcta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: var(--pz-ctl-h-sm);
  padding: 0 16px; /* = --pz-card-pad-Rhythmik der Karte */
  border: 1px solid var(--pz-ctl-line);
  background: transparent;
  color: var(--pz-ink);
  font-family: var(--pz-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: border-color .3s ease, background-color .3s ease, color .3s ease;
}
.pz-cardcta svg { width: 14px; height: 14px; flex: none; color: var(--pz-gold); }
.pz-cardcta:hover {
  border-color: var(--pz-gold);
  background: var(--pz-ivory);
  color: var(--pz-ink);
}
/* Dunkle Fassung (Set-Band, page/index.tpl) */
.pz-cardcta-d {
  border-color: rgba(247, 244, 238, .3);
  color: #f2ede4;
}
.pz-cardcta-d svg { color: var(--pz-gold-lt); }
.pz-cardcta-d:hover {
  border-color: var(--pz-gold-lt);
  background: rgba(247, 244, 238, .07);
  color: #fff;
}

/* ============================================================================
   pz: 404-Seitenkopf (Reviewer F3, Markup page/404.tpl). Bewusst in pz-base
   und nicht in einer Bereichsdatei: die 404 ist keiner der drei gestalteten
   Bereiche und laedt sonst kein passendes Stylesheet. */
/* pz: FIXRUNDE 8b / N12 — SITEMAP-LINKKASTEN FUELLT SEINE ZEILE NICHT.
   Markup: NOVA `page/sitemap.tpl` -> `.card.sitemap-group > .row` mit
   SIEBEN `col-lg-3`-Spalten, von denen nur die ersten drei eine gefuellte
   `ul.nav` tragen. Gemessen 20.08. (1440, 404-Seite): Spalten je 302px,
   Spalte 4 leer (302px), Spalten 5-7 mit Hoehe 0 — rechts neben den Links
   blieben rund 500px Weiss stehen, das wie ein vergessener Block aussieht
   (Fehlerregister 3b, Auspraegung "Navigation/Link-Listen").
   Die Spaltenzahl ist im Parent fest verdrahtet; sie folgt hier also nicht
   dem Inhalt. Statt sie nachzurechnen: leere Spalten fallen weg, und die
   verbliebenen wachsen auf die Zeile.
   ⚠️ Am BAUSTEIN `.sitemap-group` gescopet, nicht an `#page-not-found`:
   dieselbe Karte rendert auch auf der Seitenuebersicht (/Sitemap) — der
   Befund ist nicht der der 404-Seite, sondern der der Karte
   (Fehlerregister 17).
   ⚠️ `flex: 1 1 220px` statt `grid auto-fit`: 220px ist gegen den laengsten
   Linktext geprueft ("Batteriegesetzhinweise"); mit flex-grow fuellt auch
   eine unvollstaendige letzte Zeile die Breite, waehrend auto-fit dort eine
   leere Spur behielte — also genau den Befund reproduziert haette. */
.sitemap-group .row > [class*="col"] {
  flex: 1 1 220px;
  max-width: none;
}
.sitemap-group .row > [class*="col"]:not(:has(li)) { display: none; }

/* ============================================================================
   pz: FIXRUNDE 8b / N13 — LOGIN-SEITE UND LEERE SUCHE IN DIE CI-BASIS
   (Fehlerregister 25: Seiten ohne Mockup laufen im Roh-Framework mit; das
   Muster ist das des leeren Warenkorbs aus D7 — Lesebreite, ruhige
   Anordnung, keine Totflaeche. KEIN Neubau: Markup und Reihenfolge bleiben).

   (a) LOGIN-BLOCK — dieselbe Huelle fuer Wunschzettel, Mein Konto und
   Vergleichsliste (gemessen 20.08.: /Wunschliste und /Mein-Konto liefern
   BEIDE `#account.row > .col-12 > h1 + .alert + .row.login-form`, also ein
   Baustein in mehreren Huellen — Fehlerregister 13).
   IST (1440): H1 und Hinweis-Alert ueber die vollen 1218px, das Formular
   darunter als `col-lg-6` mit 625px — daneben 625px Weiss. Drei Elemente,
   zwei Fluchtbreiten, ein halbleerer Schirm.
   SOLL: ein zusammenhaengender Block in Lesebreite, mittig.
   ⚠️ Die 640px sind KEIN gegriffener Wert: es ist die Breite, die das
   Formular bereits hatte (col-lg-6 = 625px + 2x8px Gutter). Der Block
   schrumpft also nicht, er wird nur um seine eigene Kante zentriert.
   ⚠️ `:has(> .col-12 > .row.login-form)`: `#account` traegt AUCH die
   Kontouebersicht des eingeloggten Kunden — die darf nicht auf 640px
   gedrueckt werden. Die Regel greift nur, solange ein Login-Formular
   drinsteht. (`#account` selbst bleibt unangetastet — Einhaengepunkt der
   Zahlarten-Plugins, NOVA-LIVE-LEHREN O.5.) */
#account:has(> .col-12 > .row.login-form) > .col-12 {
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}
#account:has(> .col-12 > .row.login-form) .row.login-form > [class*="col"] {
  flex: 0 0 100%;
  max-width: 100%;
}

/* (b) LEERE SUCHE — NOVAs "nichts gefunden" plus Wiederholungs-Formular.
   IST gemessen 20.08. (1440, /suche?qs=zzzznixgibts): Alert und Feld je
   892px breit, der Knopf darunter 154x39 — das Feld ist 46px hoch.
   Wieder zwei Hoehen in einer Bedienungsgruppe (Fehlerregister 11), und der
   Block laeuft ueber die volle Spaltenbreite, waehrend sein Inhalt aus zwei
   Zeilen besteht.
   Beides wie beim leeren Warenkorb: Lesebreite, gemeinsame Hoehenquelle. */
/* ⚠️ Der Anker fuer den Alert ist bewusst der ELTERN-agnostische
   `:has(> form#suche2) > .alert`: gemessen liegt das Paar unter
   `#result-wrapper`, nicht in einer Bootstrap-Spalte — ein `[class*="col"]`
   davor hat beim ersten Versuch nichts getroffen (der Alert blieb 892px,
   waehrend das Formular schon 640px mass; genau die Diskrepanz, die
   Fehlerregister 4/16 meinen: erst messen, welcher Selektor wirklich
   matcht). */
:has(> form#suche2) > .alert,
#content form#suche2 {
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}
#content form#suche2 .btn {
  height: var(--pz-ctl-h-sm);
  max-height: none; /* ⚠️ Lehre I.6: NOVA deckelt Buttons per max-height */
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.pz-404-head {
  padding-top: var(--pz-sek-lead);
  padding-bottom: var(--pz-sek-lead);
}
.pz-404-head .pz-eyebrow { display: block; margin-bottom: 18px; }
.pz-404-head h1 { font-size: 50px; margin: 0 0 20px; }
.pz-404-head .pz-lead { margin: 0; }
@media (max-width: 767.98px) {
  .pz-404-head h1 { font-size: 32px; }
}

/* ============================================================================
   pz: SITEMAP (page/sitemap.tpl, 21.08. — Ben: "klarer und schoener, keine
   Bilder, muss frei mitskalieren"). Keine Bootstrap-Karten mehr: Sektionskopf
   wie auf der Startseite (Eyebrow + Serif-h2, Hairline darunter), dann ein
   auto-fill-Raster — jede Hauptkategorie / jede Linkgruppe ein Block mit
   Serif-Titel, goldener Kurzlinie und ruhiger Liste. Neue Kategorien fuellen
   das Raster von selbst (minmax 220px). Werte aus der Skala: .pz-eyebrow,
   --pz-serif, --pz-sek-*, 12er-Raster. Hover: Goldton + 4px Schub (wie
   .pz-tlink), reduced-motion respektiert. */
.pz-smap { padding-bottom: var(--pz-sek-halb); }
.pz-smap-head {
  display: flex;
  align-items: baseline;
  gap: 24px;
  padding-bottom: 16px;
  margin-bottom: 40px;
  border-bottom: 1px solid var(--pz-line);
}
.pz-smap-head .pz-eyebrow { order: 2; }
.pz-smap-head h2 { font-size: 34px; margin: 0; }
.pz-smap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 44px 40px;
}
.pz-smap-block { min-width: 0; }
.pz-smap-title {
  display: block;
  position: relative;
  font-family: var(--pz-serif);
  font-size: 24px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--pz-ink);
  text-decoration: none;
  padding-bottom: 14px;
  margin-bottom: 14px;
}
.pz-smap-title::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 1px;
  background: var(--pz-gold);
  /* pz: scaleX statt width — Layout-Eigenschaften nicht animieren (impeccable) */
  transform: scaleX(.5);
  transform-origin: left;
  transition: transform .3s ease;
}
a.pz-smap-title:hover,
a.pz-smap-title:focus-visible { color: var(--pz-gold); text-decoration: none; }
a.pz-smap-title:hover::after { transform: scaleX(1); }
.pz-smap-list { list-style: none; margin: 0; padding: 0; }
.pz-smap-list li { margin: 0 0 10px; }
.pz-smap-list a {
  display: inline-block;
  font-size: 15px;
  line-height: 1.5;
  color: var(--pz-muted);
  text-decoration: none;
  transition: color .2s ease, transform .2s ease;
}
.pz-smap-list a:hover,
.pz-smap-list a:focus-visible { color: var(--pz-gold); transform: translateX(4px); }
.pz-smap-list-sub { margin: 8px 0 4px 14px; border-left: 1px solid var(--pz-line); padding-left: 12px; }
.pz-smap-list-sub a { font-size: 14px; }
@media (max-width: 767.98px) {
  .pz-smap-head { flex-direction: column; gap: 10px; margin-bottom: 28px; }
  .pz-smap-head .pz-eyebrow { order: 0; }
  .pz-smap-head h2 { font-size: 28px; }
  .pz-smap-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 32px 24px; }
  .pz-smap-title { font-size: 21px; }
  /* Tap-Ziele (Fehlerregister 7): 22,5px Textzeile + 11px Polster oben/unten
     = 44,5px, der Listenabstand wandert dafuer ins Polster. */
  .pz-smap-list li { margin: 0; }
  .pz-smap-list a { display: block; padding: 11px 0; }
  /* Unterkategorien: 14px * 1,5 = 21px Textzeile, also 11,5px Polster fuer 44px. */
  .pz-smap-list-sub a { padding: 11.5px 0; }
}
@media (prefers-reduced-motion: reduce) {
  .pz-smap-title::after, .pz-smap-list a { transition: none; }
  .pz-smap-list a:hover { transform: none; }
}

/* ============================================================================
   pz: VERGLEICHSLISTE WIRD UNTER 576px NICHT ANGEBOTEN (Gate-Befund 20.08.).

   BEFUND (gemessen 390, Desktop-UA, Artikel real auf die Liste gelegt):
     Vergleichsliste leer   #shop-nav 4 Icons, scrollWidth 390 = clientWidth
     Vergleichsliste gefuellt  5 Icons, #shop-nav x233,4…403,4
                               -> scrollWidth 404 gegen clientWidth 390
   NOVA blendet `#shop-nav-compare` nur solange aus, wie die Liste LEER ist
   (`{if $productCount === 0}d-none{/if}`) — der Kunde erzeugt das fuenfte
   Icon also selbst, mit einem Klick, den er auf der Artikelseite auch mobil
   findet. Der bisherige Kopf war auf VIER Icons hin vermessen (siehe
   pz-header.css, Block "Kollisionszone Marke <-> Icons"); der fuenfte Fall
   war nie eingerechnet.

   WARUM AUSBLENDEN UND NICHT ENGER SETZEN: Das Budget der Reihe bei 390 ist
   140,6px (Wortmarke endet 233,4, rechter Rand 16px wie beim Burger). Fuenf
   Icons brauchen 170px. Die fehlenden 29,4px liessen sich nur ueber die
   Icon-Polster holen — 6px je Seite sind aber schon der Mindestwert von
   heute frueh, und die Trefferflaechen laegen danach bei ~26px Breite.
   Enger setzen hiesse also, einen Ueberlauf gegen zu kleine Tap-Ziele zu
   tauschen (Fehlerregister 7/11).

   BELEGT AN NOVAs EIGENEM VERHALTEN: mit echter Mobil-UA (Pixel 10, 360px,
   playwright) rendert NOVA nur DREI Icons — Suche, Konto, Warenkorb; weder
   Vergleich noch Wunschzettel (`{if !$isMobile}`). Unter 576px keine
   Vergleichsliste anzubieten ist damit exakt das, was das Framework auf
   einem echten Telefon ohnehin tut, und keine eigene Erfindung.

   ⚠️ BEIDE SEITEN, sonst entsteht eine Sackgasse (Fehlerregister 8/14):
   Nur das Icon zu verstecken wuerde den Zugang zu einer Liste kappen, die
   der Kunde weiter fuellen kann — der Knopf steht auf der Artikelseite auch
   bei 390 sichtbar da (gemessen 44x44). Genau diese Sackgasse liefert NOVA
   auf echten Telefonen aus; wir bauen sie nicht nach. Unter 576px
   verschwindet deshalb der EINSTIEG mit: kein Knopf, kein Icon, kein
   halboffener Zustand. Ab 576px ist alles unveraendert.
   `button[name=…]`, nicht `[name=…]`: auf der Vergleichsseite selbst tragen
   Formularfelder denselben Namen. */
@media (max-width: 575.98px) {
  #shop-nav-compare,
  button[name="Vergleichsliste"] { display: none !important; }
}
