/* baushop.com — Stylesheet. Nur lokale Assets, keine externen CDNs.
   Light/Dark über prefers-color-scheme + manueller Umschalter (data-theme).

   ── Woher das Design kommt ───────────────────────────────────────────
   Die Farben kommen aus der Wortmarke mit Dach (assets/baushop-logo.svg):
   Orange #EE5D00 und Anthrazit (12. 10. 2026 vom früheren Logo-Rot
   umgestellt; die Abstufungen für Knöpfe und Text stehen unten bei der
   Kontrastregel).

   1. Zwei Farben. Anthrazit #1E2A33 trägt Text und Struktur, Orange
      trägt die Marke. Die Eigenmarke Nuvax ist ebenfalls orange — sie
      unterscheidet sich vom Shop über Logo und dunkle Produktflächen,
      nicht über die Farbe.
   2. Der Doppelstrich. Haarlinie + Abstand + orange Linie ist
      --doppelstrich-unten/-oben und
      liegt an genau vier Stellen: Kopfkante, Fußkante, aktiver Navigations-
      punkt, erledigte Strecke der Kasse. Ein Motiv, kein Muster.
   3. Die Dachschräge. 45° ist die einzige erlaubte Diagonale (--ecke),
      an genau zwei Stellen (.dachschraege). Die Flächen sind seit dem
      Redesign weicher (--radius-s/-m/-l), die Signaturen bleiben scharf.
   4. Das 2x2-Fenster. Ruhige, quadratische Kacheln mit großzügiger Rinne —
      daher --space-5 als Rasterlücke statt --space-4.
   5. Eine Strichstärke. Das Logo kennt genau eine Linienbreite; deshalb
      gibt es hier --strich (1px) für JEDEN Rahmen und JEDE Trennlinie.
      Keine gemischten Haarlinien, keine gestrichelten Sonderrahmen.

   ── Kontrastregel (gilt unverändert weiter) ──────────────────────────
   Text erreicht mindestens 4,5:1 gegen jeden Untergrund, auf dem er
   vorkommt (--bg, --surface, --panel und die jeweilige Tint-Fläche);
   Flächen und Rahmen mindestens 3:1.

   Seit 10/2026 ist die Shop-Farbe das ORANGE der Wortmarke (#EE5D00).
   Geprüft: Als Fläche trägt es Weiß nur mit 3,39:1, als Textfarbe auf
   --bg nur 3,10:1 — beides reißt die Regel. Deshalb drei Rollen mit
   demselben Farbton, unterschiedlich hell:
     --marke        #EE5D00  das Logo-Orange: Linien, Doppelstrich (dekorativ)
     --marke-strong #C24C00  Fläche mit weißer Schrift (Knöpfe): 4,85:1
     --marke-text   #AE4400  Text, Links, Preise: ≥ 4,89:1 auf jedem Untergrund
   Der Fokusring nimmt --marke-strong (≥ 4,1:1), weil das Logo-Orange auf
   --panel nur 2,86:1 erreicht.

   Statusfarben sind bewusst NICHT die Markenfarbe: eine Sicherheits-
   warnung darf nicht aussehen wie ein Kaufen-Knopf. */

:root {
  /* Formularelemente und Scrollbalken folgen dem Theme mit */
  color-scheme: light;

  /* ── Shop-Marke: Orange + Anthrazit aus der Wortmarke ─────────────
     Zuständig für Kopf, Fuß, Navigation, primäre Aktionen, Fokusring
     und Struktur. */
  --marke:        #EE5D00;  /* Logo-Orange: Linien, Doppelstrich — nie Text, nie Fläche mit Schrift */
  --marke-strong: #C24C00;  /* Fläche, die --marke-on trägt (Knöpfe, Badges): Weiß 4,85:1 */
  --marke-hover:  #A33F00;  /* Weiß 6,43:1 */
  --marke-on:     #ffffff;  /* Beschriftung auf --marke-strong */
  --marke-text:   #AE4400;  /* Orange als Textfarbe (Links, Preise): ≥ 4,89:1 */
  --marke-dim:    #FDEFE5;  /* Orange-Tint als Fläche (Auswahl) */
  --anthrazit:    #1E2A33;  /* Logo-Anthrazit — Quelle von --text */

  /* ── Eigenmarke Nuvax: NUR für die Eigenmarke ─────────────────────
     Sortimentsbereich, Marken-Panel, Bild-Platzhalter der Produktkarte.
     Nie als globale Shop-Farbe.

     Seit der Shop selbst orange ist, trennt die FARBE die beiden Marken
     nicht mehr — das tun das Nuvax-Logo ("N"-Zeichen, Wortmarke) und die
     dunklen Produktflächen. Die Werte bleiben das Orange aus dem
     Nuvax-Logo (#D05E0E). Die Eigenmarke trägt nie eine Aktion: kein
     --nuvax-strong/-on/-hover. Handeln ist immer --marke-strong. */
  --nuvax:        #D05E0E;  /* Kante des Eigenmarken-Blocks */
  --nuvax-text:   #A0480B;  /* Orange als Textfarbe (Marken-Label) */
  --nuvax-dim:    #FBEDE2;  /* Orange-Tint als Fläche */

  /* ── Status ───────────────────────────────────────────────────────
     Nie allein farblich, immer mit Symbol UND Textlabel.

     Die Gefahrenfarbe muss sich von der Marke absetzen — sonst sieht eine
     Sicherheitswarnung aus wie ein Kaufen-Knopf. Sie tut das auf drei
     Wegen zugleich:
     1. Ton: --danger ist ein kühles, tiefes Karminrot (#93142B), die
        Marke ein warmes Orange (#C24C00) — verschiedene Farbtöne, dazu
        1,82 Stufen Helligkeitskontrast.
     2. Form: Gefahrenflächen sind IMMER getönte Kästen mit Umrandung,
        nie gefüllte Knöpfe mit weißer Beschriftung. Auch der
        Eskalationsknopf bleibt ein Umriss.
     3. Symbol und Text: jede Fläche trägt ⚠ und eine Beschriftung. */
  --danger:    #93142B;  /* Eskalation, Gefahrgut, Fehler */
  --danger-bg: #FBE9EC;
  --warn:      #7D5700;  /* Biozid, Vorsicht */
  --warn-bg:   #FDF3DC;
  --info:      #1A5FA8;  /* neutrale Hinweise */
  --info-bg:   #E8F1FB;
  --ok:        #226C29;  /* Erfolg */
  --ok-bg:     #E7F3E8;

  /* ── Flächen und Text ─────────────────────────────────────────────
     Die Graustufen sind aus dem Logo-Anthrazit entsättigt, nicht warm
     wie vorher — sonst steht ein warmes Beige neben einem kühlen
     Anthrazit und beide wirken schmutzig. */
  --bg:           #F4F5F6;
  --surface:      #ffffff;  /* Karte: die EINE erhobene Fläche */
  --panel:        #EAECEE;  /* Panel: die EINE ruhende Fläche */
  --border:       #D3D8DC;  /* dekorative Trennlinie */
  --border-stark: #79828A;  /* Rahmen, der Bedeutung trägt (Bedienelemente), 3,3:1 */
  --text:         var(--anthrazit);  /* das Anthrazit des Logos trägt den Text */
  --text-sec:     #4A575F;
  --text-dim:     #5C6971;  /* Untergrenze: PAngV-Grundpreis muss lesbar bleiben */

  /* Umgekehrte Fläche — trägt im Chat die eigene Nachricht. Bewusst
     nicht Orange: die Markenfarbe bleibt den Aktionen vorbehalten. */
  --kontrast:    var(--anthrazit);
  --kontrast-on: #ffffff;

  /* Abdeckung hinter Drawer und Modal */
  --abdeckung: rgba(15, 21, 26, 0.4);

  --fokus: var(--marke-strong);  /* hell: ≥ 4,1:1 auf jedem Untergrund; dunkel: siehe unten */

  /* System-Schriften, nichts wird geladen. Inter greift nur, wenn es auf
     dem Gerät installiert ist. */
  --font-body: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
               "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;

  /* ── Form-Token: Linie, Radius, Schräge ───────────────────────────
     Das Logo hat eine Strichstärke und genau eine Diagonale. Die Flächen
     sind seit dem Redesign weicher (drei Radien), die Signaturen bleiben
     scharf: Dachschräge und Doppelstrich werden nie gerundet. Keine
     Pillen, keine Kreise — das Logo kennt beides nicht. */
  --strich:        1px;  /* JEDER Rahmen, JEDE Trennlinie */
  --strich-marke:  3px;  /* die orange Linie des Doppelstrichs */
  --strich-luecke: 3px;  /* Abstand dazwischen — wie im Dach */
  --doppel-versatz: calc(var(--strich-marke) + var(--strich-luecke));
  --doppel-h:       calc(var(--doppel-versatz) + var(--strich));
  --radius-s:  6px;   /* Eingabefelder, Badges, Segmente, Hinweisflächen */
  --radius-m: 12px;   /* Knöpfe, Karten, Sprechblasen */
  --radius-l: 20px;   /* Hero-Visual, Modal, Drawer, Eigenmarken-Block */
  --radius:   var(--radius-s);  /* Alias für Altbestand */
  /* Dachschräge: Länge des 45°-Schnitts. Nur an zwei Stellen —
     Hero-Visual und Hauptbild der Produktseite, jeweils oben rechts. */
  --ecke: clamp(20px, 14.19px + 1.61vw, 40px);

  /* Schatten nur für Ebenen, die schweben. Ruhende Flächen tragen keinen. */
  --schatten-1: 0 1px 2px rgba(15, 21, 26, 0.06), 0 8px 24px rgba(15, 21, 26, 0.08);   /* Karte im Hover, aktives Segment */
  --schatten-2: 0 2px 6px rgba(15, 21, 26, 0.06), 0 18px 48px rgba(15, 21, 26, 0.14);  /* Sticky-Kaufbox, Drawer, Menü */
  --schatten-3: 0 24px 64px rgba(15, 21, 26, 0.24);                                    /* Modal */
  --schatten: var(--schatten-3);  /* Alias für Altbestand */

  /* ── Bewegung ─────────────────────────────────────────────────────
     Nur transform und opacity werden animiert. Bei prefers-reduced-motion
     fallen alle Dauern auf 0 (siehe Grundlagen). */
  --dauer-druck:    120ms;  /* Knopfdruck */
  --dauer-schnell:  200ms;  /* Hover, Schließen */
  --dauer-mittel:   360ms;  /* Drawer, Modal, Menü */
  --dauer-langsam:  600ms;  /* Einblenden beim Scrollen */
  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in:     cubic-bezier(0.4, 0, 1, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* Glas für Navigation und Leisten. 85 % ist der gerechnete Mindestwert:
     Bei 80 % fällt der Nebentext im Dunkelmodus über hellem Inhalt auf
     3,95:1, bei 85 % hält er 4,70:1. */
  --glas-deckung: 85%;
  --glas-blur: saturate(180%) blur(20px);

  /* Der Doppelstrich als fertige Hintergrund-Lagen. Unten: Haarlinie
     oben, orange Linie an der Kante. Oben: gespiegelt. */
  --doppelstrich-unten:
    linear-gradient(var(--border) 0 0) left 0 bottom var(--doppel-versatz) / 100% var(--strich) no-repeat,
    linear-gradient(var(--marke) 0 0)  left 0 bottom 0 / 100% var(--strich-marke) no-repeat;
  --doppelstrich-oben:
    linear-gradient(var(--border) 0 0) left 0 top var(--doppel-versatz) / 100% var(--strich) no-repeat,
    linear-gradient(var(--marke) 0 0)  left 0 top 0 / 100% var(--strich-marke) no-repeat;

  /* Logo-Höhen: stehen EINMAL hier, nie auf einer Seite */
  /* Wortmarke mit Dach (Seitenverhältnis 3,93:1). 40 px Höhe = 157 px
     Breite; kompakt (× 0,85) noch 134 px — über der Mindestbreite 96 px. */
  --logo-h:      40px;  /* Kopf, Desktop */
  --logo-h-klein: 30px; /* Kopf auf dem Telefon, Fuß: 118 px breit */
  --kopf-h:         76px;  /* Kopfleiste oben auf der Seite (inkl. Doppelstrich) */
  --kopf-h-kompakt: 64px;  /* nach dem ersten Scrollen — Logo behält seinen Schutzraum */

  /* ── Abstands-Token ───────────────────────────────────────────────
     Jede Stufe wächst stufenlos zwischen 360 px und 1600 px Viewport;
     darunter und darüber greifen die harten Grenzen der clamp(). Die
     Zwischenwerte sind gerechnet, nicht geschätzt:
     Wert = min + (max − min) × (100vw − 360px) / 1240px.
     Grund für die Skala: Abstände sind das, was ein Layout breit oder eng
     wirken lässt. Wurden sie fest gesetzt, sah dieselbe Seite auf 1440 px
     leer und auf 380 px gequetscht aus. */
  --space-1: clamp(4px,   3.42px + 0.16vw,  6px);   /* Symbol zu Text */
  --space-2: clamp(8px,   6.84px + 0.32vw, 12px);   /* Zeilen innerhalb eines Blocks */
  --space-3: clamp(12px, 10.26px + 0.48vw, 18px);   /* Innenabstand kleiner Flächen */
  --space-4: clamp(16px, 13.68px + 0.65vw, 24px);   /* Karten-Innenabstand */
  --space-5: clamp(24px, 19.35px + 1.29vw, 40px);   /* Blockabstand, Rasterlücke */
  --space-6: clamp(32px, 25.03px + 1.94vw, 56px);   /* Abstand zwischen Spalten */
  --space-7: clamp(48px, 38.71px + 2.58vw, 80px);   /* Blöcke innerhalb eines Abschnitts */
  --space-8: clamp(72px, 58.06px + 3.87vw, 128px);  /* Abschnitts-Rhythmus */
  --space-9: clamp(96px, 76.13px + 5.52vw, 176px);  /* Hero */

  /* ── Schrift-Token ────────────────────────────────────────────────
     Gleiche Rechenregel wie oben. */
  --fs-100: clamp(12px, 11.71px + 0.08vw, 13px);  /* Pflichtangaben, Fußzeile */
  --fs-200: clamp(13px, 12.71px + 0.08vw, 14px);  /* Navigation, Badges */
  --fs-300: clamp(14px, 13.42px + 0.16vw, 16px);  /* Nebentext, Formularhilfen */
  --fs-400: clamp(16px, 15.42px + 0.16vw, 18px);  /* Fließtext */
  --fs-500: clamp(19px, 18.13px + 0.24vw, 22px);  /* Einleitungstext */
  --fs-600: clamp(24px, 21.68px + 0.65vw, 32px);  /* Abschnittsüberschrift */
  --fs-700: clamp(36px, 30.19px + 1.61vw, 56px);  /* Seitentitel (h1) */

  /* Display-Stufen: großer Größenkontrast, enge Laufweite. */
  --fs-h3:      clamp(21px, 20.13px + 0.24vw, 24px);
  --fs-h2:      clamp(28px, 24.52px + 0.97vw, 40px);
  --fs-h1:      var(--fs-700);
  --fs-display: clamp(44px, 33.55px + 2.90vw, 80px);  /* Hero-Headline */
  --fs-lead:    clamp(19px, 17.55px + 0.40vw, 24px);  /* Einleitung unter Headlines */
  --ls-display: -0.025em;
  --ls-titel:   -0.015em;
  --lh-display: 1.05;
  --lh-titel:   1.12;

  /* ── Breiten-Token ────────────────────────────────────────────────
     --shell ist die EINE Kante, an der Kopf, Inhalt und Fuß ausgerichtet
     sind (siehe .container). Eine Seite verschiebt diese Kante, indem sie
     --shell überschreibt — nie, indem sie einzelne Bausteine breiter macht. */
  --maxw:      1280px;  /* Standardbreite aller Seiten */
  --maxw-text: 68ch;    /* Fließtext (Impressum, Datenschutz) */
  --maxw-wide: 1560px;  /* Katalog-Raster: mehr Spalten statt mehr Rand */
  --shell: var(--maxw);

  /* Dunkle Palette — die Werte stehen genau einmal hier und werden unten
     an beide Auslöser verteilt (manueller Umschalter + Systemeinstellung).
     So können die zwei Dark-Blöcke nicht auseinanderlaufen. */
  /* --marke-strong, --marke-hover und --marke-on stehen bewusst NICHT
     hier: Der Knopf #C24C00 trägt Weiß mit 4,85:1 und hebt sich mit
     3,35–3,68:1 von --d-bg/--d-surface ab. Der Kaufen-Knopf hat deshalb
     in beiden Themes dieselbe Farbe. Auf dunklem Grund trägt das reine
     Logo-Orange Linien und Fokusring (≥ 4,29:1). */
  --d-marke:        #EE5D00;  /* Logo-Orange: Linien und Fokusring auf dunklem Grund */
  --d-marke-text:   #FF9550;  /* ≥ 6,69:1 */
  --d-marke-dim:    #33200F;
  --d-nuvax:        #D05E0E;
  --d-nuvax-text:   #EF8544;
  --d-nuvax-dim:    #2E1B0C;
  --d-danger:        #FFA2B4;  /* kühles Rosé — hebt sich vom Orange --d-marke ab */
  --d-danger-bg:     #2E1218;
  --d-warn:          #F0B429;
  --d-warn-bg:       #2C2110;
  --d-info:          #7FB3F5;
  --d-info-bg:       #12202F;
  --d-ok:            #7BC97F;
  --d-ok-bg:         #13251A;
  --d-bg:            #14181B;
  --d-surface:       #1B2126;
  --d-panel:         #232A30;
  --d-border:        #333C43;
  --d-border-stark:  #6E7B84;
  --d-text:          #EDF1F3;
  --d-text-sec:      #A7B2BA;
  --d-text-dim:      #9AA6AE;
  --d-kontrast:      #E7EBEE;
  --d-kontrast-on:   #14181B;
  --d-abdeckung:     rgba(0, 0, 0, 0.6);
  --d-schatten-1:    0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.35);
  --d-schatten-2:    0 2px 6px rgba(0, 0, 0, 0.3), 0 18px 48px rgba(0, 0, 0, 0.5);
  --d-schatten-3:    0 24px 64px rgba(0, 0, 0, 0.6);
}

/* Dunkle Abschnitte (.abschnitt--dunkel) lesen dieselbe Palette wie der
   Dunkelmodus — keine eigenen Farbwerte. Im Dunkelmodus setzt sich der
   Abschnitt über --surface gegen --bg ab. */
[data-theme="dark"],
.abschnitt--dunkel {
  color-scheme: dark;
  --marke:        var(--d-marke);
  --marke-text:   var(--d-marke-text);
  --marke-dim:    var(--d-marke-dim);
  --fokus:        var(--d-marke);
  --nuvax:        var(--d-nuvax);
  --nuvax-text:   var(--d-nuvax-text);
  --nuvax-dim:    var(--d-nuvax-dim);
  --danger:       var(--d-danger);
  --danger-bg:    var(--d-danger-bg);
  --warn:         var(--d-warn);
  --warn-bg:      var(--d-warn-bg);
  --info:         var(--d-info);
  --info-bg:      var(--d-info-bg);
  --ok:           var(--d-ok);
  --ok-bg:        var(--d-ok-bg);
  --bg:           var(--d-bg);
  --surface:      var(--d-surface);
  --panel:        var(--d-panel);
  --border:       var(--d-border);
  --border-stark: var(--d-border-stark);
  --text:         var(--d-text);
  --text-sec:     var(--d-text-sec);
  --text-dim:     var(--d-text-dim);
  --kontrast:     var(--d-kontrast);
  --kontrast-on:  var(--d-kontrast-on);
  --abdeckung:    var(--d-abdeckung);
  --schatten-1:   var(--d-schatten-1);
  --schatten-2:   var(--d-schatten-2);
  --schatten-3:   var(--d-schatten-3);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --marke:        var(--d-marke);
    --marke-text:   var(--d-marke-text);
    --marke-dim:    var(--d-marke-dim);
    --fokus:        var(--d-marke);
    --nuvax:        var(--d-nuvax);
    --nuvax-text:   var(--d-nuvax-text);
    --nuvax-dim:    var(--d-nuvax-dim);
    --danger:       var(--d-danger);
    --danger-bg:    var(--d-danger-bg);
    --warn:         var(--d-warn);
    --warn-bg:      var(--d-warn-bg);
    --info:         var(--d-info);
    --info-bg:      var(--d-info-bg);
    --ok:           var(--d-ok);
    --ok-bg:        var(--d-ok-bg);
    --bg:           var(--d-bg);
    --surface:      var(--d-surface);
    --panel:        var(--d-panel);
    --border:       var(--d-border);
    --border-stark: var(--d-border-stark);
    --text:         var(--d-text);
    --text-sec:     var(--d-text-sec);
    --text-dim:     var(--d-text-dim);
    --kontrast:     var(--d-kontrast);
    --kontrast-on:  var(--d-kontrast-on);
    --abdeckung:    var(--d-abdeckung);
  --schatten-1:   var(--d-schatten-1);
    --schatten-2:   var(--d-schatten-2);
    --schatten-3:   var(--d-schatten-3);
  }
}

/* ── Grundlagen ─────────────────────────────────────────── */

* { box-sizing: border-box; margin: 0; padding: 0; }

/* `hidden` muss jede display-Regel aus einer Klasse schlagen — sonst
   bleibt ein als hidden markierter Block sichtbar, weil die
   Browser-Vorgabe fuer [hidden] gegen jeden Klassenselektor verliert. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  /* Sprungziele landen unter der klebenden Kopfleiste, nicht dahinter */
  scroll-padding-top: calc(var(--kopf-h-kompakt) + var(--space-4));
  -webkit-text-size-adjust: 100%;
}

/* Reduzierte Bewegung: Alle Dauern fallen auf 0, jeder Zustand ist sofort
   erreicht. Die Token-Werte stehen hier, damit Skripte, die Dauern aus
   dem Stylesheet lesen, ebenfalls 0 bekommen. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dauer-druck: 0ms;
    --dauer-schnell: 0ms;
    --dauer-mittel: 0ms;
    --dauer-langsam: 0ms;
  }
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Platz für die feste Hinweis-Fußzeile */
  padding-bottom: 64px;
}

/* Überschriften: großer Größenkontrast, enge Laufweite. */
h1, h2, h3 { letter-spacing: var(--ls-titel); line-height: var(--lh-titel); text-wrap: balance; }
p { text-wrap: pretty; }

img { max-width: 100%; }

a { color: var(--marke-text); }

/* Ein Fokusring, eine Regel, jedes bedienbare Element. Dunkles Orange
   (--marke-strong) auf hellem, Logo-Orange auf dunklem Grund — beides
   über 3:1 gegen --bg, --surface und --panel. */
:where(a, button, input, select, textarea, summary, label, [tabindex]):focus-visible {
  outline: 3px solid var(--fokus);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  background: var(--marke-strong);
  color: var(--marke-on);
  padding: 10px 16px;
  z-index: 200;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ── Die drei Bausteine ─────────────────────────────────────────────
   Vorher hatte fast jeder Block seine eigene Fläche, seinen eigenen
   Rahmen und seine eigene Rundung. Jetzt gibt es genau zwei Flächen und
   eine Linienstärke; alles andere ist eine Wiederholung davon.

   Karte  = erhobene Fläche mit Rahmen (--surface + --strich)
   Panel  = ruhende Fläche ohne Rahmen (--panel)
   Linie  = --strich solid var(--border), überall gleich */
.shop-card,
.form-card,
.katalog-steuerung,
.kasse-uebersicht,
.chat-wrap {
  background: var(--surface);
  border: var(--strich) solid var(--border);
  border-radius: var(--radius-m);
}

.marken-panel,
.placeholder-note,
.chat-empfehlungen,
.chat-eskalation {
  background: var(--panel);
  border-radius: var(--radius-m);
}

/* ── Knöpfe: primär, sekundär, dezent — mehr gibt es nicht ──────────
   Die Beschriftung sitzt bei 16px/600 weit unter der Großtext-Schwelle,
   die AA-Large-Regel greift also nicht — geprüft wurde deshalb gegen die
   volle 4,5:1-Schwelle: Weiß auf --marke-strong (#C24C00) erreicht
   4,85:1 — das reine Logo-Orange (3,39:1) wäre zu hell. Gleiche Farbe in
   hell wie dunkel. Beim Hover dunkler (--marke-hover, 6,43:1). */
.btn {
  /* inline-flex statt inline-block: So lässt sich eine Mindesthöhe
     setzen (Touch-Ziel), ohne dass die Beschriftung oben klebt. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 48px;
  min-width: 44px;
  background: var(--marke-strong);
  color: var(--marke-on);
  border: var(--strich) solid transparent;
  border-radius: var(--radius-m);
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  padding: 12px 24px;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color var(--dauer-schnell) var(--ease-out),
    color var(--dauer-schnell) var(--ease-out),
    transform var(--dauer-druck) var(--ease-out);
}
.btn:hover { background: var(--marke-hover); }
/* Druck-Rückmeldung: der Knopf gibt kurz nach. Nur transform. */
.btn:active:not(:disabled) { transform: scale(0.97); }

.btn-secondary {
  background: transparent;
  color: var(--text);
  border-color: var(--border-stark);
}
.btn-secondary:hover { background: var(--panel); color: var(--text); }

/* Dezent: keine Fläche, kein Rahmen — für Nebenwege (Details, Abbrechen). */
.btn-dezent {
  background: transparent;
  color: var(--marke-text);
  border-color: transparent;
  padding-inline: var(--space-3);
}
.btn-dezent:hover { background: var(--marke-dim); color: var(--marke-text); }

.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn:disabled:hover { background: var(--marke-strong); }
.btn-secondary:disabled:hover,
.btn-dezent:disabled:hover { background: transparent; }

/* Größenvarianten — .btn-klein und .btn-small existieren beide im JavaScript. */
.btn-klein,
.btn-small { font-size: 15px; min-height: 44px; padding: 10px 18px; }
.btn-gross { font-size: 19px; min-height: 56px; padding: 14px 32px; }
.btn-block { width: 100%; }

/* Pfeil hinter dem Linktext („Mehr erfahren ›"), rückt im Hover nach. */
.link-pfeil {
  color: var(--marke-text);
  font-weight: 500;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: 0.25em;
}
.link-pfeil::after {
  content: "\203A";
  display: inline-block;
  transition: transform var(--dauer-schnell) var(--ease-out);
}
.link-pfeil:hover { text-decoration: underline; }
.link-pfeil:hover::after { transform: translateX(3px); }

/* ── Seitenraster ───────────────────────────────────────────────────
   EIN Container für Kopf, Inhalt und Fuß. Alle drei lesen dieselbe
   Variable --shell, deshalb liegen ihre Kanten übereinander — auch auf
   der breiten Katalogseite. */
.container {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

/* Inhaltsbereich einer Unterseite: nur der senkrechte Rhythmus. Die
   Breite kommt vom Container. */
.page-content { padding-block: var(--space-7); min-height: 50vh; }

/* Fließtext-Seiten: Die Zeilenlänge begrenzt der INHALT, nicht der
   Container — so bleibt die Kante dieselbe wie bei Kopf und Fuß. */
/* Rechtstexte: rein typografisch — ruhige Zeilenlänge, klare Stufen. */
.page-content--text { padding-block: var(--space-8); }
.page-content--text > * { max-width: var(--maxw-text); }
.page-content--text h1 {
  font-size: var(--fs-h1);
  font-weight: 700;
  letter-spacing: var(--ls-display);
  margin-bottom: var(--space-6);
}
.page-content--text h2 {
  font-size: var(--fs-h3);
  font-weight: 600;
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: var(--strich) solid var(--border);
}
.page-content--text h2:first-of-type { border-top: 0; padding-top: 0; }
.page-content--text p,
.page-content--text li { margin-top: var(--space-2); color: var(--text-sec); line-height: 1.65; }
.page-content--text ul { padding-left: 1.25em; }
.page-content--text strong { color: var(--text); }

/* Katalog: mehr Spalten statt mehr Rand. */
.page-content--wide { --shell: var(--maxw-wide); }
body.layout-wide { --shell: var(--maxw-wide); }

/* ── Header ─────────────────────────────────────────────────────────
   Schmale Glasleiste, die klebt. Die Unterkante ist der Doppelstrich aus
   dem Logo — als Hintergrund-Lagen, padding-bottom hält den Inhalt frei.

   Kompakt beim Scrollen, ohne die Höhe zu animieren (das kostet Layout
   in jedem Frame): Die Leiste rückt per transform um die Differenz nach
   oben, der Inhalt rückt um die halbe Differenz zurück und das Logo
   schrumpft. Sichtbar bleibt eine Leiste von --kopf-h-kompakt, der
   Doppelstrich bleibt an der Kante. ui.js setzt nur die Klasse. */
.site-header {
  --kopf-versatz: calc(var(--kopf-h) - var(--kopf-h-kompakt));
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--kopf-h);
  padding-bottom: var(--doppel-h);
  background: var(--doppelstrich-unten), var(--surface);
  transition: transform var(--dauer-mittel) var(--ease-out);
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header {
    background:
      var(--doppelstrich-unten),
      color-mix(in srgb, var(--surface) var(--glas-deckung), transparent);
    -webkit-backdrop-filter: var(--glas-blur);
    backdrop-filter: var(--glas-blur);
  }
}
.site-header.kompakt { transform: translateY(calc(var(--kopf-versatz) * -1)); }
.site-header.kompakt .header-inner { transform: translateY(calc(var(--kopf-versatz) / 2)); }
.site-header.kompakt .logo-bild--voll { transform: scale(0.85); }

/* Raster statt Flex-Umbruch: Logo, Navigation und Aktionen haben je
   ihren festen Platz. */
.header-inner {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  height: 100%;
  transition: transform var(--dauer-mittel) var(--ease-out);
}

/* ── Logo ───────────────────────────────────────────────────────────
   Der Kopf trägt die Wortmarke mit Dach (orange). Die Höhe steht in
   --logo-h / --logo-h-klein — nie auf einer Seite.

   Zwei Dateien statt einer: Die dunkle Schrift verschwindet auf dunklem
   Grund. Der Umschalter tauscht deshalb die Bilddatei, und zwar für
   BEIDE Auslöser — Systemeinstellung wie manueller Schalter — und
   zusätzlich in dunklen Abschnitten. */
.logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  /* Das Logo ist selbst das Tippziel — 44 px Mindesthöhe. */
  min-height: 44px;
  border-radius: var(--radius-s);
}
.logo-bild { display: block; width: auto; }
.logo-bild--voll {
  height: var(--logo-h);
  transform-origin: left center;
  transition: transform var(--dauer-mittel) var(--ease-out);
}

[data-theme="dark"] .logo-bild--voll,
.abschnitt--dunkel .logo-bild--voll    { content: url("../assets/baushop-logo-invers.svg"); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-bild--voll    { content: url("../assets/baushop-logo-invers.svg"); }
}

/* ── Navigation ─────────────────────────────────────────────────────
   Der aktive Punkt trägt den Doppelstrich — dieselbe Kante wie der Kopf,
   nur kürzer. Zusätzlich volle Textfarbe und Fettung: Farbe allein wäre
   kein zulässiger Bedeutungsträger (WCAG 1.4.1). */
.site-nav { display: flex; gap: var(--space-1); justify-content: center; }
.site-nav a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--text-sec);
  text-decoration: none;
  font-size: var(--fs-300);
  font-weight: 500;
  min-height: 44px;
  padding: 11px 12px;
  border-radius: var(--radius-s);
  transition: color var(--dauer-schnell) var(--ease-out), background-color var(--dauer-schnell) var(--ease-out);
}
.site-nav a:hover { color: var(--text); background: var(--panel); }
/* [aria-current] ohne Wertprüfung: "page" auf der Seite selbst, "true" auf
   einer Unterseite davon (Produktdetail gehört zum Katalog). */
.site-nav a[aria-current],
.kopf-korb[aria-current] {
  color: var(--text);
  font-weight: 700;
  background: var(--doppelstrich-unten);
  border-radius: 0;
}
.site-nav a[aria-current]:hover,
.kopf-korb[aria-current]:hover { background: var(--doppelstrich-unten), var(--panel); }

/* Rechte Gruppe: Farbschalter, Warenkorb, Menüknopf (nur mobil). */
.kopf-aktionen { display: flex; align-items: center; gap: var(--space-1); }

.theme-toggle,
.kopf-korb,
.menu-knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 44px;
  min-height: 44px;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-s);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-300);
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--dauer-schnell) var(--ease-out), transform var(--dauer-druck) var(--ease-out);
}
.theme-toggle:hover,
.kopf-korb:hover,
.menu-knopf:hover { background: var(--panel); }
.theme-toggle:active,
.kopf-korb:active,
.menu-knopf:active { transform: scale(0.94); }
.theme-toggle { color: var(--text-sec); font-size: 20px; line-height: 1; }

.kopf-korb svg,
.menu-knopf svg { width: 22px; height: 22px; display: block; }
.kopf-korb svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }

/* Menüknopf: zwei Striche, die sich zum ✕ drehen. Nur transform. */
.menu-knopf { display: none; }
.menu-knopf .strich {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform var(--dauer-mittel) var(--ease-out);
}
.menu-offen .menu-knopf .strich--oben { transform: translateY(3px) rotate(45deg); }
.menu-offen .menu-knopf .strich--unten { transform: translateY(-3px) rotate(-45deg); }

/* Warenkorb-Zähler: gefüllt, sobald etwas drin ist — im leeren Zustand
   nur ein Umriss. Die Zahl selbst bleibt der Bedeutungsträger. Ändert
   sie sich, springt das Badge kurz (Klasse .hüpft, von ui.js gesetzt). */
.warenkorb-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border: var(--strich) solid transparent;
  border-radius: var(--radius-s);
  background: var(--marke-strong);
  color: var(--marke-on);
  font-size: var(--fs-100);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.warenkorb-badge.leer {
  background: transparent;
  border-color: var(--border-stark);
  color: var(--text-dim);
  font-weight: 500;
}
.warenkorb-badge.huepft { animation: badge-huepfen var(--dauer-langsam) var(--ease-out); }
@keyframes badge-huepfen {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.35); }
  60%  { transform: scale(0.92); }
  100% { transform: scale(1); }
}

/* ── Mobil-Menü (bis 833 px) ────────────────────────────────────────
   Die Navigation wird zur Vollbild-Ebene unter der Kopfleiste. Sie ist
   immer im DOM (Links bleiben ohne JS über den Fuß erreichbar) und wird
   per visibility versteckt — so ist sie geschlossen weder sichtbar noch
   per Tab erreichbar. Öffnen und Schließen: opacity und transform,
   die Punkte laufen gestaffelt ein. */
@media (max-width: 833px) {
  :root { --kopf-h: 64px; --kopf-h-kompakt: 56px; }
  .header-inner { grid-template-columns: minmax(0, 1fr) auto; }
  .logo-bild--voll { height: var(--logo-h-klein); }
  .menu-knopf { display: inline-flex; }

  .site-nav {
    /* Die Kopfleiste ist durch backdrop-filter/transform der Bezugsrahmen
       für position: fixed. Deshalb von ihrer Unterkante aus messen statt
       vom Fenster. */
    position: fixed;
    top: 100%;
    left: 0;
    right: 0;
    height: calc(100dvh - var(--kopf-h));
    z-index: 99;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0;
    padding: var(--space-5) var(--space-4);
    background: var(--surface);
    overflow-y: auto;
    visibility: hidden;
    opacity: 0;
    transform: translateY(-8px);
    transition:
      opacity var(--dauer-schnell) var(--ease-in),
      transform var(--dauer-schnell) var(--ease-in),
      visibility 0s linear var(--dauer-schnell);
  }
  .menu-offen .site-nav {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition:
      opacity var(--dauer-mittel) var(--ease-out),
      transform var(--dauer-mittel) var(--ease-out),
      visibility 0s;
  }
  .site-nav a {
    font-size: var(--fs-h2);
    font-weight: 600;
    letter-spacing: var(--ls-titel);
    color: var(--text);
    padding: var(--space-2) 0;
    min-height: 56px;
    border-radius: 0;
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity var(--dauer-schnell) var(--ease-out), transform var(--dauer-schnell) var(--ease-out);
  }
  .site-nav a:hover { background: transparent; color: var(--marke-text); }
  .menu-offen .site-nav a {
    opacity: 1;
    transform: none;
    transition-duration: var(--dauer-mittel);
  }
  .menu-offen .site-nav a:nth-child(2) { transition-delay: 40ms; }
  .menu-offen .site-nav a:nth-child(3) { transition-delay: 80ms; }
  .menu-offen .site-nav a:nth-child(4) { transition-delay: 120ms; }
  .menu-offen .site-nav a:nth-child(5) { transition-delay: 160ms; }
  /* Der aktive Punkt behält den Doppelstrich, aber nur so breit wie das Wort. */
  .site-nav a[aria-current] { align-self: flex-start; }
  /* Solange das Menü offen ist, scrollt die Seite darunter nicht. */
  .menu-offen body { overflow: hidden; }
  .menu-offen .site-header { transform: none; }
  .menu-offen .site-header .header-inner { transform: none; }
}

/* ── Dachschräge ────────────────────────────────────────────────────
   Die einzige Diagonale: 45°-Schnitt oben rechts, die übrigen drei Ecken
   tragen --radius-l. Erlaubt an genau ZWEI Stellen — Hero-Visual der
   Startseite und Hauptbild der Produktseite. */
.dachschraege {
  border-radius: var(--radius-l);
  clip-path: polygon(
    0 0,
    calc(100% - var(--ecke)) 0,
    100% var(--ecke),
    100% 100%,
    0 100%);
}

/* ── Abschnitte ─────────────────────────────────────────────────────
   Ein Rhythmus (--space-7), eine Trennlinie (--strich). Keine
   Sonderabstände mehr. */
section { padding-block: var(--space-7); }
main > section + section { border-top: var(--strich) solid var(--border); }
section h2 {
  font-size: var(--fs-h2);
  font-weight: 700;
  margin-bottom: var(--space-2);
}
.page-content h1 { font-size: var(--fs-h1); font-weight: 700; margin-bottom: var(--space-3); }
.section-sub { color: var(--text-sec); font-size: var(--fs-lead); line-height: 1.45; margin-bottom: var(--space-6); max-width: 52ch; }

/* ── Abschnitte im Vollbild-Rhythmus ────────────────────────────────
   Eine Botschaft pro Abschnitt. Die Flächen wechseln sich ab, statt durch
   Linien getrennt zu werden:
     .abschnitt            --bg (Grundfläche)
     .abschnitt--flaeche   --surface
     .abschnitt--dunkel    dunkle Palette (setzt die --d-Werte lokal, siehe
                           oben) — im Dunkelmodus hebt er sich über
                           --surface gegen --bg ab. */
main > .abschnitt + .abschnitt { border-top: 0; }
.abschnitt { padding-block: var(--space-8); background: var(--bg); color: var(--text); }
.abschnitt--flaeche { background: var(--surface); }
.abschnitt--dunkel  { background: var(--surface); }
.abschnitt--mittig  { text-align: center; }
.abschnitt--mittig .section-sub,
.abschnitt--mittig .abschnitt-titel { margin-inline: auto; }

.eyebrow {
  font-size: var(--fs-300);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--marke-text);
  margin-bottom: var(--space-2);
}
.abschnitt-titel {
  font-size: var(--fs-h1);
  font-weight: 700;
  letter-spacing: var(--ls-display);
  line-height: var(--lh-titel);
  max-width: 20ch;
  margin-bottom: var(--space-3);
}
.display {
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: var(--ls-display);
  line-height: var(--lh-display);
  margin-bottom: var(--space-4);
}
.lead { font-size: var(--fs-lead); line-height: 1.45; color: var(--text-sec); max-width: 52ch; }

/* Der Eigenmarken-Block. Einzige Stelle, an der die Nuvax-Farbe eine
   Fläche trägt — sie markiert die Marke, nicht den Shop. */
.marken-panel {
  background: var(--nuvax-dim);
  border-radius: var(--radius-l);
  border-left: var(--strich-marke) solid var(--nuvax);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5);
  margin-top: var(--space-5);
}
/* Das Nuvax-Logo ist schwarz und hat keine helle Fassung. Es bekommt
   deshalb eine eigene weiße Platte — im Dunkelmodus wäre es sonst
   unsichtbar. Ein fremdes Markenzeichen färbt man nicht um. */
.marken-panel img {
  width: 180px;
  height: auto;
  background: #ffffff;
  border-radius: var(--radius);
  padding: var(--space-3);
}
.marken-panel p { color: var(--text); font-size: var(--fs-300); }
.marke-label {
  text-transform: uppercase;
  letter-spacing: 1.5px;
  font-size: var(--fs-100);
  font-weight: 700;
  color: var(--nuvax-text);
  margin-bottom: var(--space-1);
}
.marke-nuvax { color: var(--nuvax-text); }

/* ── Karten-Raster ──────────────────────────────────────────────────
   Intrinsisch statt an Breakpoints: Die Spaltenzahl ergibt sich aus der
   verfügbaren Breite, nicht aus dem Fenster.

   Die Deckelung liegt bewusst auf der KARTE, nicht auf der Spur: Ist die
   obere Grenze einer Spur eine feste Länge, rechnet auto-fit die
   Spaltenzahl mit dieser Länge — aus 5 möglichen Spalten wurden so 2.

   Rinne ist --space-5 statt --space-4: das 2x2-Fenster des Logos lebt von
   der Lücke zwischen den Kacheln. */
.product-grid {
  --karte-min: clamp(240px, 18vw, 280px);
  --karte-max: 420px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--karte-min)), 1fr));
  gap: var(--space-5);
}
.product-grid > * { max-width: var(--karte-max); }

/* ── Hinweisflächen ─────────────────────────────────────────────────
   Vier Rollen, vier Farben, jede zusätzlich mit einem Symbol markiert —
   Farbe ist nie der einzige Bedeutungsträger (WCAG 1.4.1). Die
   Variantenselektoren \FE0E erzwingen die Textdarstellung der Symbole,
   damit sie nicht als bunte Emoji erscheinen. */
.notice::before,
.abhol-hinweis::before,
.biozid-note::before,
.gefahrgut-hinweis::before,
.gefahrgut-note::before,
.msg-error::before,
.form-status.ok::before,
.form-status.error::before,
.feld-fehler-text::before {
  font-weight: 700;
  margin-right: 0.35em;
}

.notice {
  background: var(--info-bg);
  border: var(--strich) solid var(--border);
  border-left: var(--strich-marke) solid var(--info);
  border-radius: var(--radius);
  padding: 14px 18px;
  font-size: var(--fs-300);
  color: var(--text-sec);
  margin-top: var(--space-4);
}
.notice::before { content: "\2139\FE0E"; color: var(--info); }

/* ── Chat ───────────────────────────────────────────────────────────
   Angelehnt an Apples Nachrichten: große Radien, ruhige Flächen, eine
   durchscheinende Kopfzeile, Eingabe als Kapsel mit rundem Senden-Knopf.
   Die eigene Nachricht steht auf der umgekehrten Fläche (--kontrast), die
   Antwort auf dem Panel — ohne Rahmen. Orange bleibt Aktionen vorbehalten
   (Senden). Antworten sind Markdown (chat-markdown.js) und bekommen eine
   eigene, ruhige Typografie. */
.chat-wrap {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  border-radius: 24px;
}

/* Kopfzeile: durchscheinend wie eine Titelleiste */
.chat-kopf {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 12px var(--space-4);
  border-bottom: var(--strich) solid var(--border);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  position: relative;
  z-index: 3;
}
.chat-avatar {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--panel);
  display: grid;
  place-items: center;
}
.chat-avatar,
.chat-empty-zeichen { background: var(--kontrast); color: var(--kontrast-on); }
.chat-avatar svg,
.chat-empty-zeichen svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.chat-avatar svg { width: 22px; height: 22px; }
.chat-kopf-text { flex: 1; min-width: 0; }
.chat-kopf-titel { font-weight: 600; line-height: 1.3; letter-spacing: -0.01em; }
.chat-kopf-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-100);
  color: var(--text-sec);
}
.chat-status-punkt {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 0 3px var(--ok-bg);
}
.chat-neu {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--marke-text);
  font: inherit;
  font-size: var(--fs-200);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--dauer-schnell) var(--ease-out);
}
.chat-neu:hover { background: var(--panel); }
.chat-neu { display: inline-flex; align-items: center; gap: 6px; }
.chat-neu[hidden] { display: none; }
.chat-neu svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.chat-kopf-titel,
.chat-kopf-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Telefon: Kopfzeile einzeilig halten — Untertitel kürzer, "Neu beginnen" nur als Symbol */
@media (max-width: 480px) {
  .chat-kopf { padding: 10px var(--space-3); gap: 10px; }
  .chat-avatar { width: 36px; height: 36px; }
  .chat-neu { width: 44px; padding: 0; justify-content: center; }
  .chat-neu span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .chat-input-row { padding-inline: 10px; }
  .chat-attach { width: 44px; height: 44px; }
  .chat-nach-unten { bottom: 80px; }
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-padding-bottom: var(--space-4);
  padding: var(--space-4) var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Leerer Zustand: Begrüßung und Einstiege */
.chat-empty {
  margin: auto;
  max-width: 640px;
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  text-align: center;
  padding: var(--space-3) 0;
}
.chat-empty-zeichen {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  margin-bottom: var(--space-1);
}
.chat-empty-zeichen svg { width: 24px; height: 24px; }
.chat-empty-titel { font-size: var(--fs-500); font-weight: 600; letter-spacing: -0.015em; }
.chat-empty-text { color: var(--text-sec); font-size: var(--fs-300); max-width: 420px; }
/* Alle Einstiege auf einen Blick: festes Raster statt umbrechender Reihe,
   damit kein Knopf unter den Rand rutscht und man erst scrollen muss. */
.chat-vorschlaege {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
  width: 100%;
  margin-top: var(--space-2);
}
.chat-vorschlag {
  min-height: 44px;
  padding: 8px 14px;
  line-height: 1.3;
  border: var(--strich) solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-300);
  cursor: pointer;
  transition: background var(--dauer-schnell) var(--ease-out),
              border-color var(--dauer-schnell) var(--ease-out),
              transform var(--dauer-druck) var(--ease-out);
}
.chat-vorschlag:hover { background: var(--panel); border-color: var(--border-stark); }
.chat-vorschlag:active { transform: scale(0.97); }

/* Nachrichten */
.msg {
  max-width: min(82%, 640px);
  display: flex;
  flex-direction: column;
  animation: einlaufen var(--dauer-mittel) var(--ease-out) both;
}
.msg-user { align-self: flex-end; align-items: flex-end; transform-origin: right bottom; }
.msg-bot  { align-self: flex-start; align-items: flex-start; transform-origin: left bottom; }
@keyframes einlaufen {
  from { opacity: 0; transform: translateY(10px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
.bubble {
  padding: 10px 15px;
  border-radius: 20px;
  font-size: var(--fs-400);
  line-height: 1.45;
  letter-spacing: -0.005em;
  overflow-wrap: break-word;
}
.msg-user .bubble {
  background: var(--kontrast);
  color: var(--kontrast-on);
  border-bottom-right-radius: 6px;
  white-space: pre-wrap;
}
.msg-bot .bubble {
  background: var(--panel);
  color: var(--text);
  border-bottom-left-radius: 6px;
}

/* Typografie der Antworten (Markdown) */
.bubble--md { padding: 12px 16px; }
/* :where() hält die Rücksetzung ohne Spezifität — sonst schlüge sie den
   Abstand zwischen den Blöcken darunter. */
.bubble--md :where(p, ul, ol, blockquote, hr) { margin: 0; }
.bubble--md > * + * { margin-top: 0.65em; }
.bubble--md strong { font-weight: 650; }
.bubble--md ul,
.bubble--md ol { padding-left: 1.3em; }
/* Ein Absatz, der mit Doppelpunkt eine Liste einleitet, gehört eng zu ihr. */
.bubble--md p + :is(ul, ol) { margin-top: 0.3em; }
.bubble--md li + li { margin-top: 0.3em; }
.bubble--md li { padding-left: 0.15em; }
.bubble--md ul li::marker { color: var(--text-dim); }
.bubble--md ol li::marker { color: var(--text-sec); font-weight: 600; font-variant-numeric: tabular-nums; }
.bubble--md .md-titel { font-weight: 650; letter-spacing: -0.01em; }
.bubble--md .md-titel:not(:first-child) { margin-top: 0.9em; }
.bubble--md blockquote {
  margin: 0;
  padding: 2px 0 2px 12px;
  border-left: 3px solid var(--border-stark);
  color: var(--text-sec);
}
.bubble--md code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.88em;
  background: var(--surface);
  border-radius: 5px;
  padding: 1px 5px;
}
.bubble--md a { color: var(--marke-text); text-underline-offset: 2px; }
.bubble--md hr { border: 0; border-top: var(--strich) solid var(--border); margin: 0.9em 0; }

/* Absätze und Listen einer neuen Antwort laufen nacheinander ein */
.bubble--einlauf > * { animation: block-ein 420ms var(--ease-out) both; }
.bubble--einlauf > :nth-child(2) { animation-delay: 70ms; }
.bubble--einlauf > :nth-child(3) { animation-delay: 140ms; }
.bubble--einlauf > :nth-child(4) { animation-delay: 210ms; }
.bubble--einlauf > :nth-child(5) { animation-delay: 280ms; }
.bubble--einlauf > :nth-child(n+6) { animation-delay: 350ms; }
@keyframes block-ein {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Unter der Blase: Absender, Zeit, Kopieren */
.msg-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-100);
  color: var(--text-dim);
  margin-top: 4px;
  padding-inline: 6px;
}
.msg-aktion {
  /* 44 px Tippfläche, optisch aber nur eine Textzeile */
  min-height: 44px;
  margin-block: -14px;
  padding: 0 8px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-sec);
  font: inherit;
  cursor: pointer;
}
.msg-aktion:hover { color: var(--text); text-decoration: underline; }

/* Feste Fußzeile an JEDER KI-Antwort (SYSTEM.md §5.3/§5.4). Nicht
   wegklappbar, nicht ausblendbar — sie gehört zur Antwort. */
.msg-fuss {
  margin-top: var(--space-1);
  padding: 0 6px;
  font-size: var(--fs-100);
  line-height: 1.45;
  color: var(--text-sec);
}
.msg-fuss strong { color: var(--text); font-weight: 600; }

.msg-error {
  align-self: flex-start;
  background: var(--danger-bg);
  border: var(--strich) solid var(--danger);
  border-radius: 16px;
  padding: 10px 14px;
  font-size: var(--fs-300);
  color: var(--text);
  max-width: min(82%, 640px);
}
.msg-error::before { content: "\26A0\FE0E  "; color: var(--danger); }

/* Tipp-Indikator: drei Punkte in der Antwortblase */
.typing { display: inline-flex; gap: 5px; padding: 14px 16px; }
.typing i {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--text-dim);
  animation: tippen 1.2s var(--ease-in-out) infinite;
}
.typing i:nth-child(2) { animation-delay: 0.15s; }
.typing i:nth-child(3) { animation-delay: 0.3s; }
@keyframes tippen {
  0%, 70%, 100% { opacity: 0.35; transform: translateY(0) scale(0.85); }
  35%           { opacity: 1;    transform: translateY(-3px) scale(1); }
}

/* "Zur neuesten Nachricht" — erscheint, wenn man nach oben gescrollt hat */
.chat-nach-unten {
  position: absolute;
  left: 50%;
  bottom: 88px;
  z-index: 5;
  width: 44px;
  height: 44px;
  margin-left: -22px;
  border-radius: 50%;
  border: var(--strich) solid var(--border);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--schatten-1);
  display: grid;
  place-items: center;
  cursor: pointer;
  animation: einlaufen var(--dauer-schnell) var(--ease-out) both;
}
.chat-nach-unten[hidden] { display: none; }

/* Eingabe: Plus-Knopf, Kapsel mit rundem Senden-Knopf */
.chat-input-row {
  border-top: var(--strich) solid var(--border);
  padding: 10px var(--space-3) 12px;
  display: flex;
  gap: var(--space-2);
  align-items: flex-end;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
}
.chat-input-row svg,
.chat-nach-unten svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.chat-eingabe {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  gap: 6px;
  padding: 4px 4px 4px 16px;
  background: var(--surface);
  border: var(--strich) solid var(--border-stark);
  border-radius: 23px;
  transition: border-color var(--dauer-schnell) var(--ease-out),
              box-shadow var(--dauer-schnell) var(--ease-out);
}
.chat-eingabe:focus-within {
  border-color: var(--marke);
  box-shadow: 0 0 0 3px var(--marke-dim);
}
.chat-eingabe textarea {
  flex: 1;
  min-width: 0;
  min-height: 36px;
  max-height: 140px;
  padding: 7px 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-400);
  line-height: 1.4;
  resize: none;
}
.chat-eingabe textarea:focus { outline: none; }
.chat-eingabe textarea::placeholder { color: var(--text-dim); }
.chat-senden {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 0;
  background: var(--marke-strong);
  color: var(--marke-on);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background var(--dauer-schnell) var(--ease-out),
              transform var(--dauer-druck) var(--ease-out),
              opacity var(--dauer-schnell) var(--ease-out);
}
.chat-senden:hover:not(:disabled) { background: var(--marke-hover); }
.chat-senden:active:not(:disabled) { transform: scale(0.9); }
.chat-senden:disabled { background: var(--border-stark); opacity: 0.45; cursor: default; }
/* Die Kapsel ist 46 px hoch — die Tippfläche des runden Knopfs wird nach
   außen auf 44 px erweitert, ohne dass er größer aussieht. */
.chat-senden { position: relative; }
.chat-senden::after { content: ""; position: absolute; inset: -4px; }

.chat-attach {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  background: var(--panel);
  color: var(--text);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: background var(--dauer-schnell) var(--ease-out),
              transform var(--dauer-druck) var(--ease-out);
}
.chat-attach:hover:not(:disabled) { background: var(--border); }
.chat-attach:active:not(:disabled) { transform: scale(0.92); }
.chat-attach:disabled { opacity: 0.45; cursor: not-allowed; }
.chat-attach.hat-bild { background: var(--marke-dim); color: var(--marke-text); }

/* Vorschaustreifen über der Eingabe: Thumbnail + Dateiname + Entfernen. */
.chat-bild-vorschau {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-3);
  border-top: var(--strich) solid var(--border);
  background: var(--surface);
}
.chat-bild-vorschau img {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 10px;
  flex: 0 0 auto;
}
.chat-bild-vorschau .cbv-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.cbv-name {
  font-size: var(--fs-300);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cbv-groesse { font-size: var(--fs-100); color: var(--text-dim); }
.cbv-entfernen {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  border-radius: 999px;
  color: var(--marke-text);
  font-family: var(--font-body);
  font-size: var(--fs-200);
  font-weight: 600;
  min-height: 44px;
  padding: 0 12px;
  cursor: pointer;
}
.cbv-entfernen:hover { background: var(--panel); }

/* Hinweis an der eigenen Nachricht, dass ein Foto mitgeschickt wurde. */
.msg-foto-note {
  font-size: var(--fs-100);
  color: var(--text-dim);
  margin-top: 4px;
  padding-inline: 6px;
}

/* Drag-and-Drop-Fläche: liegt über dem Chat und wird nur eingeblendet,
   während eine Datei über das Fenster gezogen wird. */
.chat-dropzone {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  backdrop-filter: blur(6px);
}
.chat-dropzone span {
  border: 2px dashed var(--marke);
  border-radius: 20px;
  color: var(--text);
  font-size: var(--fs-400);
  font-weight: 600;
  padding: 28px 40px;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .msg, .bubble--einlauf > *, .chat-nach-unten, .typing i { animation: none; }
}

/* ── Formular ───────────────────────────────────────────────────────
   Beschriftung immer ÜBER dem Feld, nie daneben und nie im Feld: Ein
   Platzhalter verschwindet beim Tippen, ein Label bleibt stehen. */
.form-card { padding: var(--space-5); max-width: var(--maxw-text); border-radius: var(--radius-l); }
/* Felder, die nebeneinander in einer Zeile stehen, sind selbst Zeilen —
   so trägt jedes seine eigene Meldung. Der Abstand kommt von außen. */
.form-row .form-row { margin-bottom: 0; }
.form-card h2 { font-size: var(--fs-500); margin-bottom: var(--space-3); }
.form-card h2 + .fulfillment-wahl { margin-top: 0; }
.form-card h3 { font-size: var(--fs-400); margin: var(--space-4) 0 var(--space-2); }
.form-row { margin-bottom: var(--space-4); }
.form-row label {
  display: block;
  font-size: var(--fs-300);
  font-weight: 600;
  margin-bottom: var(--space-1);
}
.form-row label .optional { font-weight: 400; color: var(--text-dim); }
.form-row input,
.form-row textarea,
.form-row select {
  width: 100%;
  background: var(--surface);
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius-m);
  color: var(--text);
  font-family: var(--font-body);
  /* 17 px: verhindert zudem das automatische Zoomen von iOS (< 16 px) */
  font-size: 17px;
  /* 52 px: groß und ruhig — ein Eingabefeld ist ein Tippziel */
  min-height: 52px;
  padding: 13px 16px;
  transition: border-color var(--dauer-schnell) var(--ease-out), box-shadow var(--dauer-schnell) var(--ease-out);
}
.form-row input:hover, .form-row textarea:hover { border-color: var(--text-sec); }
.form-row input:focus, .form-row textarea:focus { border-color: var(--marke); }

/* Inline-Validierung: Nach dem Verlassen eines Feldes zeigt ui.js ein ✓
   (gültig) oder die vorhandene .feld-fehler-Meldung. Das Häkchen ist
   zusätzlich zum Text — Farbe allein trägt nie die Aussage. */
.feld-ok { position: relative; }
.feld-ok > input { border-color: var(--ok); padding-right: 44px; }
.feld-ok::after {
  content: "\2713\FE0E";
  position: absolute;
  right: 16px;
  bottom: 14px;
  color: var(--ok);
  font-weight: 700;
  pointer-events: none;
  animation: abdeckung-auf var(--dauer-schnell) var(--ease-out);
}
.form-hint { font-size: var(--fs-200); color: var(--text-dim); margin-top: var(--space-3); }
/* Die Rückmeldung ist eine Fläche, kein bloß eingefärbter Satz: Ein
   grüner oder roter Text allein wird auf dem Telefon leicht überlesen —
   und Farbe darf ohnehin nicht der einzige Bedeutungsträger sein. Symbol,
   Wortlaut und Fläche tragen die Aussage gemeinsam. Ohne Text nimmt die
   Zeile keinen Platz ein. */
.form-status {
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  background: var(--panel);
  border-left: var(--strich-marke) solid var(--border-stark);
  font-size: var(--fs-300);
  font-weight: 600;
}
.form-status:empty { display: none; }
.form-status.ok {
  color: var(--ok);
  background: var(--ok-bg);
  border-left-color: var(--ok);
}
.form-status.ok::before { content: "\2713\FE0E"; }
.form-status.error {
  color: var(--danger);
  background: var(--danger-bg);
  border-left-color: var(--danger);
}
.form-status.error::before { content: "\2716\FE0E"; }

/* Fehlerhaftes Feld: Der Text sagt, was fehlt — die Farbe verstärkt ihn
   nur. Die Kante wird über einen inneren Schein kräftiger, nicht über
   eine zweite Linienstärke. */
.feld-fehler input {
  border-color: var(--danger);
  box-shadow: inset 0 0 0 var(--strich) var(--danger);
}
.feld-fehler-text {
  color: var(--danger);
  font-size: var(--fs-200);
  font-weight: 600;
  margin-top: var(--space-1);
}
.feld-fehler-text::before { content: "\2716\FE0E"; }

/* ── Footer ─────────────────────────────────────────────────────────
   Gespiegelte Kopfkante: derselbe Doppelstrich, orange nach oben. Ruhig,
   klein, vier Spalten — auf dem Telefon zwei. */
.site-footer {
  background: var(--doppelstrich-oben), var(--bg);
  padding-top: calc(var(--space-7) + var(--doppel-h));
  padding-bottom: var(--space-5);
  font-size: var(--fs-200);
  color: var(--text-sec);
}
.footer-raster {
  display: grid;
  grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  padding-bottom: var(--space-5);
  border-bottom: var(--strich) solid var(--border);
}
.footer-marke { display: grid; gap: var(--space-3); align-content: start; }
.footer-marke .logo-bild--voll { height: var(--logo-h-klein); width: auto; align-self: start; }
.footer-marke p { line-height: 1.6; }
.footer-spalte { display: grid; align-content: start; }
.footer-titel { font-weight: 600; color: var(--text); margin-bottom: var(--space-1); }
.footer-spalte a {
  color: var(--text-sec);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.footer-spalte a:hover { color: var(--text); text-decoration: underline; }
/* § 356a BGB: Die Widerrufsfunktion muss gut lesbar und hervorgehoben sein. */
.footer-spalte a.footer-link--widerruf { color: var(--text); font-weight: 600; text-decoration: underline; }
.footer-unten {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2);
  padding-top: var(--space-4);
  font-size: var(--fs-100);
}
@media (max-width: 833px) {
  .footer-raster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-marke { grid-column: 1 / -1; }
}

/* Feste Hinweis-Fußzeile: Biozid-Pflichtsatz + keine Fachberatung (§5.3/§5.4) */
.legal-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 90;
  background: var(--panel);
  border-top: var(--strich) solid var(--border);
  padding: var(--space-1) var(--space-4);
  font-size: var(--fs-100);
  line-height: 1.45;
  color: var(--text-sec);
  text-align: center;
}
.legal-bar strong { color: var(--text); font-weight: 600; }
/* Glas wie die Kopfleiste: 85 % Deckung hält den Nebentext über jedem
   Untergrund bei mindestens 4,7:1 (gerechnet für beide Themes). */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .legal-bar {
    background: color-mix(in srgb, var(--surface) var(--glas-deckung), transparent);
    -webkit-backdrop-filter: var(--glas-blur);
    backdrop-filter: var(--glas-blur);
  }
}

/* ── Shop: Katalog / Warenkorb / Kasse ──────────────────────────────
   Die Karte ist ihr eigener Bezugsrahmen (container-type). Sie steht mal
   in einer 240-px- und mal in einer 420-px-Spalte — was sie zeigt, hängt
   also von IHRER Breite ab, nicht von der des Fensters. */
.shop-card {
  container: karte / inline-size;
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  transition: transform var(--dauer-mittel) var(--ease-out), box-shadow var(--dauer-mittel) var(--ease-out);
}
/* Hover hebt die Karte an — nur wo ein Zeiger schweben kann. */
@media (hover: hover) {
  .shop-card:not(.skelett):hover { transform: translateY(-4px); box-shadow: var(--schatten-1); }
}
.shop-card h3 { font-size: var(--fs-400); line-height: 1.4; }
.shop-card h3 a { color: var(--text); text-decoration: none; }
.shop-card h3 a:hover { text-decoration: underline; }

/* Preis und Aktion stehen auf JEDER Karte an derselben Stelle: unten.
   Das Skript baut sie in der Mitte ein (Bild, Name, Preis, Texte,
   Kennzeichen, Knopf) — die Reihenfolge wird hier gedreht, nicht dort.
   So bleibt die Logik unangetastet und der Blick findet den Preis beim
   Überfliegen immer auf derselben Höhe. */
.shop-card > *        { order: 5; }
.shop-card > .shop-bild        { order: 0; }
.shop-card > .marke-logo       { order: 1; align-self: flex-start; }
.shop-card > .shop-kategorie   { order: 1; }
.shop-card > h3                { order: 2; }
.shop-card > .karte-badges     { order: 6; }
.shop-card > .biozid-note      { order: 7; }
.shop-card > .karte-dokument   { order: 8; }
.shop-card > .preis-zeile      { order: 9; margin-top: auto; padding-top: var(--space-2); }
.shop-card > .grundpreis       { order: 10; }
.shop-card > .karte-aktionen   { order: 11; }

/* 4:3 wie die Produktbilder selbst. Das Bild steht frei auf der ruhenden
   Fläche (contain, nie beschnitten) und wächst im Hover leicht. */
.shop-bild {
  margin: calc(var(--space-4) * -1) calc(var(--space-4) * -1) var(--space-1);
  border-radius: var(--radius-m) var(--radius-m) 0 0;
  overflow: hidden;
  background: var(--panel);
  aspect-ratio: 4 / 3;
}
.shop-bild img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  transition: transform var(--dauer-langsam) var(--ease-out);
}
@media (hover: hover) {
  .shop-card:hover .shop-bild img { transform: scale(1.04); }
}
.shop-bild-leer { position: relative; }
/* Das Nuvax-Logo hat schwarze Buchstaben und keine helle Fassung: eigene
   weiße Platte, auch im Dunkelmodus. Ein fremdes Zeichen färbt man nicht um. */
.shop-bild-leer::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 62%;
  aspect-ratio: 3 / 1;
  transform: translate(-50%, -50%);
  background: #ffffff url("/assets/nuvax-logo.svg") center / 82% auto no-repeat;
  border-radius: var(--radius-m);
}
/* Ohne Bild trägt nur die Eigenmarke das Nuvax-Logo — Handelsware
   anderer Hersteller bekommt einen neutralen Platzhalter. */
.shop-card--fremd .shop-bild-leer::after,
.pd-fremd .shop-bild-leer::after {
  content: "Kein Bild";
  inset: 0;
  width: auto;
  aspect-ratio: auto;
  transform: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border-radius: 0;
  color: var(--text-dim);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  font-size: var(--fs-200);
}
.shop-kategorie {
  font-size: var(--fs-100);
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
}
/* Nuvax-Logo über dem Produktnamen (Karte und Produktseite) — auf weißer
   Platte, sonst verschwinden die schwarzen Buchstaben im Dunkelmodus. */
.marke-logo {
  display: block;
  flex: none;
  height: 21px;
  width: auto;
  box-sizing: content-box;
  padding: 3px 6px;
  background: #ffffff;
  border-radius: var(--radius);
}
.pd-kaufbereich .marke-logo { height: 28px; margin-bottom: var(--space-2); }
.preis-zeile { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.preis { font-size: 20px; font-weight: 700; color: var(--marke-text); }
.preis-alt { color: var(--text-dim); font-size: var(--fs-300); }
/* Grundpreis ist PAngV-Pflichtangabe — eine Stufe kräftiger als --text-dim,
   damit die Pflichtangabe nicht die schwächste Zeile der Karte ist. */
.grundpreis { font-size: var(--fs-100); color: var(--text-sec); }
/* Biozid-Pflichtsatz (§5.3): Vorsicht, kein Fehler → --warn. */
.biozid-note {
  font-size: var(--fs-100);
  color: var(--text);
  background: var(--warn-bg);
  border-left: var(--strich-marke) solid var(--warn);
  border-radius: var(--radius);
  padding: 8px 10px;
  line-height: 1.5;
}
.biozid-note::before { content: "\26A0\FE0E"; color: var(--warn); }

.korb-zeile {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: var(--strich) solid var(--border);
  flex-wrap: wrap;
}
.korb-name { font-weight: 600; }
.korb-preis { font-size: var(--fs-300); color: var(--text-sec); }
.menge-steuerung { display: flex; align-items: center; gap: var(--space-2); }
.menge-knopf {
  width: 44px; height: 44px;
  background: transparent;
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius-m);
  transition: background-color var(--dauer-schnell) var(--ease-out), transform var(--dauer-druck) var(--ease-out);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-400);
  cursor: pointer;
}
.menge-knopf:hover { background: var(--panel); }
.menge-knopf:active { transform: scale(0.94); }
/* Entfernen ist destruktiv → --danger. Das Symbol ✕ und aria-label
   „Artikel entfernen" tragen die Bedeutung unabhängig von der Farbe. */
.menge-knopf.entfernen { color: var(--danger); margin-left: var(--space-2); }
.menge-anzahl { min-width: 32px; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.korb-summe {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--fs-500);
  font-weight: 700;
  padding: var(--space-3) 0;
  border-top: var(--strich) solid var(--border);
  margin-top: var(--space-2);
}
.summen-hinweis { font-size: var(--fs-200); color: var(--text-dim); margin-bottom: var(--space-4); }

/* Zwei Spalten, solange beide mindestens 320 px bekommen — sonst eine.
   Braucht keinen Breakpoint: Das Raster entscheidet selbst. */
.kasse-grid { gap: var(--space-5); }
.kasse-uebersicht { padding: var(--space-5); }
.kasse-uebersicht h2 { font-size: var(--fs-500); margin-bottom: var(--space-3); }
.kasse-uebersicht ul {
  list-style: none;
  margin: var(--space-3) 0;
  display: grid;
  gap: var(--space-2);
  font-size: var(--fs-300);
}
.summen-zeile {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  font-size: var(--fs-300);
  color: var(--text-sec);
  padding: var(--space-1) 0;
}

.fulfillment-wahl {
  border: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: var(--space-3);
}
/* Das Tippziel ist das LABEL, nicht das 13-px-Kästchen im Browserstandard.
   Beide bekommen deshalb 44 px Mindesthöhe, und das Kästchen selbst wächst
   auf 20 px — sonst trifft man am Rand daneben. */
.fulfillment-option {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  min-height: 44px;
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius-m);
  transition: border-color var(--dauer-schnell) var(--ease-out), background-color var(--dauer-schnell) var(--ease-out);
  padding: var(--space-3);
  cursor: pointer;
  font-size: var(--fs-300);
}
/* Ausgewählt: kräftige Kante in Markenorange auf ruhiger Panel-Fläche.
   Bewusst NICHT der Orange-Tint --marke-dim: Direkt darüber steht auf dieser
   Seite der Gefahrgut-Hinweis auf seinem eigenen rosé Untergrund — zwei
   blassorange Kästen nebeneinander wären nicht mehr auseinanderzuhalten.
   Den Zustand trägt ohnehin zuerst der Radioknopf selbst. */
.fulfillment-option:has(input:checked) {
  border-color: var(--marke);
  background: var(--panel);
}
.fulfillment-option input,
.form-row-checkbox input {
  flex: none;
  width: 20px;
  height: 20px;
  accent-color: var(--marke-strong);
}
.form-row-checkbox label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  font-weight: 400;
  cursor: pointer;
}
/* Abholadresse ist eine reine Sachinformation → --info, nicht Marke. */
.abhol-hinweis {
  background: var(--info-bg);
  border: var(--strich) solid var(--border);
  border-left: var(--strich-marke) solid var(--info);
  border-radius: var(--radius);
  padding: 14px 16px;
  font-size: var(--fs-300);
  line-height: 1.6;
  margin-bottom: var(--space-4);
}
.abhol-hinweis::before { content: "\2139\FE0E"; color: var(--info); }

/* Gefahrgut/Sperrgut: harte Einschränkung → --danger. Diese Fläche darf
   nie dieselbe Farbe tragen wie der Kaufen-Knopf. */
.gefahrgut-hinweis {
  background: var(--danger-bg);
  border: var(--strich) solid var(--danger);
  border-left: var(--strich-marke) solid var(--danger);
  border-radius: var(--radius);
  padding: 14px 16px;
  font-size: var(--fs-300);
  line-height: 1.6;
  margin-bottom: var(--space-4);
}
.gefahrgut-hinweis::before { content: "\26A0\FE0E"; color: var(--danger); }
/* Links in Statusflächen tragen die Farbe der Fläche, nicht die Marke —
   sonst steht ein Kauf-Orange mitten in einer Sicherheitswarnung.
   Unterstreichung bleibt der Träger der Link-Bedeutung. */
.gefahrgut-hinweis a,
.gefahrgut-note a { color: var(--danger); text-decoration: underline; }
.gefahrgut-hinweis a { font-weight: 600; }
.gefahrgut-note {
  font-size: var(--fs-100);
  color: var(--text);
  background: var(--danger-bg);
  border-left: var(--strich-marke) solid var(--danger);
  border-radius: var(--radius);
  padding: 8px 10px;
  line-height: 1.5;
}
.gefahrgut-note::before { content: "\26A0\FE0E"; color: var(--danger); }

/* ── Katalog: Suche, Filter, Sortierung ─────────────────────────────
   Die Leiste ist bewusst ruhig gehalten: Sie soll zum Katalog führen,
   nicht mit ihm konkurrieren. */
.katalog-steuerung {
  display: grid;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  padding: var(--space-4);
}
.katalog-zeile {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: var(--space-3);
}
/* Das Suchfeld darf mehr Platz beanspruchen als die Sortierung — sobald
   nebeneinander Platz ist. */
.katalog-feld--suche { grid-column: span 2; }
@media (max-width: 640px) { .katalog-feld--suche { grid-column: auto; } }

.katalog-feld { display: grid; gap: var(--space-1); }
.katalog-feld label {
  font-size: var(--fs-200);
  font-weight: 600;
  color: var(--text-sec);
}
.katalog-feld input,
.katalog-feld select {
  width: 100%;
  background: var(--surface);
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius-m);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  min-height: 48px;
  padding: 11px 16px;
}
.katalog-feld input:focus,
.katalog-feld select:focus { border-color: var(--marke); }

.filter-zeile {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.filter-titel {
  font-size: var(--fs-200);
  font-weight: 600;
  color: var(--text-sec);
  min-width: 5.5em;
}
.filter-gruppe { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* ── Segmented Control ──────────────────────────────────────────────
   Die Filtergruppe ist eine ruhende Schiene (--panel), jedes Segment ein
   Umschalter (aria-pressed — Mehrfachauswahl bleibt möglich). Das aktive
   Segment hebt sich als Fläche ab und trägt zusätzlich Fettung und ein
   Häkchen: Farbe allein wäre kein zulässiger Bedeutungsträger.
   Bewusst NICHT orange — ein gesetzter Filter ist ein Zustand, keine
   Aktion. Passt die Schiene nicht in die Breite, scrollt sie in sich. */
.filter-gruppe {
  display: inline-flex;
  /* nowrap: Die Regel weiter oben setzt "wrap" — dann brach die Schiene auf
     dem Telefon in drei Zeilen um, statt wie gedacht in sich zu scrollen. */
  flex-wrap: nowrap;
  gap: 2px;
  max-width: 100%;
  padding: 3px;
  background: var(--panel);
  border-radius: var(--radius-m);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.filter-gruppe::-webkit-scrollbar { display: none; }

.chip {
  flex: none;
  background: transparent;
  border: var(--strich) solid transparent;
  border-radius: calc(var(--radius-m) - 3px);
  color: var(--text-sec);
  font-family: var(--font-body);
  font-size: var(--fs-300);
  font-weight: 500;
  white-space: nowrap;
  min-height: 44px;
  padding: 9px 16px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color var(--dauer-schnell) var(--ease-out),
    color var(--dauer-schnell) var(--ease-out),
    box-shadow var(--dauer-schnell) var(--ease-out),
    transform var(--dauer-druck) var(--ease-out);
}
.chip:hover { color: var(--text); }
.chip:active { transform: scale(0.97); }
.chip[aria-pressed="true"] {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
  font-weight: 600;
  box-shadow: var(--schatten-1);
}
.chip[aria-pressed="true"]::before { content: "\2713\FE0E"; margin-right: 0.4em; color: var(--marke-text); }
.chip:focus-visible { outline-offset: -1px; }

.katalog-treffer {
  font-size: var(--fs-300);
  color: var(--text-sec);
  margin-bottom: var(--space-3);
}
.katalog-leer { display: grid; gap: var(--space-3); justify-items: start; }

/* ── Ladezustand: Skelettkarten ─────────────────────────────────────
   Gleiche Form wie die spätere Karte, damit beim Eintreffen der Daten
   nichts springt. Die Animation entfällt bei prefers-reduced-motion. */
.skelett { pointer-events: none; }
/* Schimmer statt Pulsieren: Ein heller Streifen wandert per transform
   über die Platzhalter — kein Neuzeichnen, 60 fps. */
.skelett-block,
.skelett-zeile,
.skelett-knopf {
  position: relative;
  overflow: hidden;
  background: var(--panel);
  border-radius: var(--radius-s);
}
.skelett-block::after,
.skelett-zeile::after,
.skelett-knopf::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    transparent 0%,
    color-mix(in srgb, var(--surface) 60%, transparent) 50%,
    transparent 100%);
  transform: translateX(-100%);
  animation: schimmern 1.6s var(--ease-in-out) infinite;
}
.skelett-zeile { height: 12px; }
.skelett-zeile--kurz { width: 55%; }
.skelett-knopf { height: 48px; width: 60%; margin-top: auto; border-radius: var(--radius-m); }
@keyframes schimmern { to { transform: translateX(100%); } }

/* ── Produktkarte: Kennzeichen ──────────────────────────────────────
   Reihenfolge auf der Karte: Bild, Kategorie, Name, Kennzeichen,
   Datenblatt — und ganz unten Preis und Kaufen. "Wofür / Wofür nicht"
   steht nur auf der Detailseite. */

.karte-badges { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.karte-badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius);
  font-size: var(--fs-100);
  font-weight: 600;
  padding: 4px 10px;
  border: var(--strich) solid;
}
.karte-badge::before { margin-right: 0.35em; }
.badge-abholung {
  background: var(--danger-bg);
  border-color: var(--danger);
  color: var(--text);
}
.badge-abholung::before { content: "\26A0\FE0E"; color: var(--danger); }
.badge-biozid {
  background: var(--warn-bg);
  border-color: var(--warn);
  color: var(--text);
}
.badge-biozid::before { content: "\2623\FE0E"; color: var(--warn); }
.badge-marke {
  background: var(--surface);
  border-color: var(--marke-strong);
  color: var(--text);
}
.badge-marke::before { content: "\2605\FE0E"; color: var(--marke-strong); }

/* Handelsware anderer Hersteller: ruhiger Rahmen statt Markenauftritt. */
.shop-card--fremd { border-style: dashed; }
.shop-card--fremd .shop-kategorie { color: var(--text-sec); }

.karte-dokument { font-size: var(--fs-200); }
/* Der Preis steht, aber es ist noch keiner: andere Größe als .preis,
   damit ein Hinweistext nie wie ein Betrag gelesen wird. */
.preis-offen { font-size: var(--fs-400); color: var(--text-sec); font-weight: 600; }

.karte-aktionen {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.karte-aktionen .btn { flex: 1 1 auto; }
.karte-details {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--space-2);
  font-size: var(--fs-200);
}

/* Ist die Karte selbst schmal (nicht das Fenster!), rutschen Knopf und
   Detaillink untereinander und das Bild wird flacher. Container-Query,
   weil dieselbe Karte je nach Spaltenzahl mal 240 und mal 420 px breit
   ist — das Fenster weiß davon nichts. */
@container karte (max-width: 280px) {
  .karte-aktionen { flex-direction: column; align-items: stretch; }
  .karte-details { justify-content: center; }
  .shop-bild { aspect-ratio: 3 / 2; }
}
/* Rückfall für Browser ohne Container-Queries: dieselbe Anpassung an
   der Handy-Schwelle, wo die Karten am schmalsten sind. */
@supports not (container-type: inline-size) {
  @media (max-width: 640px) {
    .karte-aktionen { flex-direction: column; align-items: stretch; }
    .shop-bild { aspect-ratio: 3 / 2; }
  }
}

/* ── Unterseiten (Impressum/Datenschutz) ────────────────── */
.placeholder-note {
  border-radius: var(--radius-m);
  padding: var(--space-4);
  color: var(--text-sec);
  margin-top: var(--space-5);
}

/* Adressfelder nebeneinander: Straße/Hausnummer und PLZ/Ort. Steht
   bewusst VOR den Schwellen — sonst schlägt die Grundregel die
   Handy-Regel. */
.form-row-strasse,
.form-row-ort,
.form-row-name { display: grid; gap: var(--space-3); align-items: start; }
.form-row-name { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.form-row-strasse { grid-template-columns: minmax(0, 3fr) minmax(0, 1fr); }
.form-row-ort { grid-template-columns: minmax(0, 1fr) minmax(0, 3fr); }

/* ── Produktempfehlungen im Chat ────────────────────────────────────
   Der Server wählt die Artikel; der Kunde legt sie direkt in den Korb. */
.chat-empfehlungen {
  margin: var(--space-1) 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
}
.chat-empfehlungen-titel {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-200);
  font-weight: 700;
  color: var(--text-sec);
  letter-spacing: .02em;
}
.chat-empfehlung {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px var(--space-3);
  align-items: center;
  padding: var(--space-2) 0;
  border-top: var(--strich) solid var(--border);
}
.chat-empfehlung:first-of-type { border-top: none; }
.ce-name { font-weight: 600; }
.ce-preis { font-weight: 700; color: var(--marke-text); white-space: nowrap; }
/* Kein Betrag, sondern ein Hinweis — andere Farbe und kein Fettdruck, damit
   er nicht als Preis gelesen wird. */
.ce-preis-offen { color: var(--text-sec); font-weight: 600; white-space: normal; }
.ce-grundpreis,
.ce-hinweis {
  grid-column: 1 / -1;
  font-size: var(--fs-100);
  color: var(--text-sec);
  line-height: 1.4;
}
.chat-empfehlung .btn-small {
  grid-column: 1 / -1;
  justify-self: start;
  margin-top: var(--space-2);
}
.chat-empfehlung .btn-small:disabled { opacity: .6; cursor: default; }

/* ── Belege unter der Antwort ───────────────────────────────────────
   Der Beleg soll nachlesbar sein, nicht dominant. Deshalb zugeklappt,
   kleiner Text und kein Rahmen. */
.chat-quellen {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-200);
  color: var(--text-sec);
}
.chat-quellen summary {
  cursor: pointer;
  /* 44 px Touch-Ziel, auch wenn der Text klein ist */
  padding: 11px 4px;
  font-weight: 600;
}
.chat-quellen ul { margin: 0 0 var(--space-2); padding-left: 22px; }
.chat-quellen li { margin-bottom: var(--space-1); line-height: 1.5; }
.quelle-stand { color: var(--text-dim); }

/* ── Kasse: genau ein Schritt sichtbar ──────────────────────────────
   Sichtbarkeit über Klassen statt Inline-Stile. Vorteil: Der Zustand
   steht im Stylesheet, nicht verstreut im JavaScript — und selbst wenn
   das Skript nicht lädt, ist nur das Formular sichtbar. */
.kasse-schritt { display: none; }
.kasse-schritt.aktiv { display: block; }
.kasse-schritt p { margin-bottom: var(--space-2); }
.kasse-schritt .btn { margin-top: var(--space-3); }

/* ── Eskalationshinweis im Chat ─────────────────────────────────────
   Erscheint, wenn der Fall persönlich beurteilt werden muss (Befall über
   0,5 m² oder Gesundheitsthema).

   Nutzt AUSSCHLIESSLICH --danger und --danger-bg aus der Palette oben.
   Bewusst kein gefüllter Knopf: Im Dunkelmodus ist --danger hell —
   weiße Schrift darauf wäre unlesbar. Die Umrandung funktioniert in
   beiden Themes und hält den Hinweis optisch vom Kaufen-Knopf getrennt. */
.chat-eskalation {
  margin: var(--space-1) 0 var(--space-4);
  padding: var(--space-4);
  background: var(--danger-bg);
  border-left: var(--strich-marke) solid var(--danger);
}

.esk-titel {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-400);
  font-weight: 700;
  color: var(--danger);
}

.esk-text { margin: 0 0 var(--space-3); font-size: var(--fs-300); line-height: 1.55; }

/* Einwilligung: sichtbar, aktiv zu setzen, nie vorausgewählt (§6). */
.esk-einwilligung {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  font-size: var(--fs-200);
  line-height: 1.45;
  color: var(--text-sec);
  cursor: pointer;
}

.esk-einwilligung input {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  accent-color: var(--danger);
  cursor: pointer;
}

.esk-btn {
  background: transparent;
  color: var(--danger);
  border: var(--strich) solid var(--danger);
  box-shadow: inset 0 0 0 var(--strich) var(--danger);
}
.esk-btn:hover:not(:disabled) { background: var(--danger-bg); color: var(--danger); }
.esk-btn:disabled { opacity: .5; cursor: not-allowed; }
.esk-fussnote { font-size: var(--fs-100); color: var(--text-dim); margin-top: var(--space-2); }

/* ══ Neue Bausteine des Redesigns ══════════════════════════════════ */

/* ── Einblenden beim Scrollen ───────────────────────────────────────
   Nur wenn ui.js läuft (Klasse .js am <html>) — ohne Skript ist alles
   sofort sichtbar. Verzögerung für gestaffelte Gruppen setzt ui.js aus
   data-verzoegerung (Inline-Stile verbietet die CSP). */
.js .einblenden {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--dauer-langsam) var(--ease-out),
    transform var(--dauer-langsam) var(--ease-out);
}
.js .einblenden.sichtbar { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .einblenden { opacity: 1; transform: none; }
}

/* Parallax: ui.js verschiebt [data-parallax] per transform. */
[data-parallax] { will-change: transform; }

/* ── Ebenen: Drawer und Modal ───────────────────────────────────────
   Ein gemeinsames Muster. Geschlossen: hidden (nicht im Fokus-Pfad).
   Öffnen: ui.js entfernt hidden und setzt im nächsten Frame .offen, damit
   der Übergang läuft. Schließen: .offen weg, nach --dauer-schnell hidden.
   Fokus-Falle, Esc und Klick auf die Abdeckung regelt ui.js. */
.ebene {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
}
.ebene-abdeckung {
  position: absolute;
  inset: 0;
  background: var(--abdeckung);
  opacity: 0;
  transition: opacity var(--dauer-schnell) var(--ease-in);
}
.ebene.offen .ebene-abdeckung {
  opacity: 1;
  transition: opacity var(--dauer-mittel) var(--ease-out);
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ebene-abdeckung { -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
}
.ebene-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--schatten-2);
  outline: none;
}
.ebene-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--strich) solid var(--border);
}
.ebene-kopf h2 { font-size: var(--fs-h3); font-weight: 700; margin: 0; }
.ebene-inhalt { flex: 1; overflow-y: auto; padding: var(--space-4); overscroll-behavior: contain; }
.ebene-inhalt > p + p { margin-top: var(--space-2); }
.korb-leer { display: grid; gap: var(--space-3); justify-items: start; color: var(--text-sec); }
.ebene-fuss {
  padding: var(--space-4);
  border-top: var(--strich) solid var(--border);
  display: grid;
  gap: var(--space-2);
}
.ebene-zu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--panel);
  border: 0;
  border-radius: var(--radius-m);
  color: var(--text);
  font-size: 18px;
  cursor: pointer;
  transition: transform var(--dauer-druck) var(--ease-out);
}
.ebene-zu:active { transform: scale(0.94); }

/* Drawer: fährt von rechts ein, auf dem Telefon über die volle Breite. */
.ebene--drawer { justify-content: flex-end; }
.ebene--drawer .ebene-panel {
  width: min(440px, 100%);
  height: 100%;
  border-radius: var(--radius-l) 0 0 var(--radius-l);
  transform: translateX(100%);
  transition: transform var(--dauer-schnell) var(--ease-in);
}
.ebene--drawer.offen .ebene-panel {
  transform: none;
  transition: transform var(--dauer-mittel) var(--ease-out);
}
@media (max-width: 640px) {
  .ebene--drawer .ebene-panel { border-radius: 0; }
}

/* Modal: mittig, wächst aus 96 % auf. */
.ebene--modal { align-items: center; justify-content: center; padding: var(--space-4); }
.ebene--modal .ebene-panel {
  width: min(520px, 100%);
  max-height: calc(100dvh - 2 * var(--space-4));
  border-radius: var(--radius-l);
  box-shadow: var(--schatten-3);
  opacity: 0;
  transform: translateY(8px) scale(0.96);
  transition: opacity var(--dauer-schnell) var(--ease-in), transform var(--dauer-schnell) var(--ease-in);
}
.ebene--modal.offen .ebene-panel {
  opacity: 1;
  transform: none;
  transition: opacity var(--dauer-mittel) var(--ease-out), transform var(--dauer-mittel) var(--ease-out);
}

/* Solange eine Ebene offen ist, scrollt die Seite darunter nicht. */
.ebene-aktiv body { overflow: hidden; }

/* ── Karussell ──────────────────────────────────────────────────────
   Natives Scrollen mit Snap — Wischen, Trackpad und Tastatur funktionieren
   ohne Skript. ui.js ergänzt Pfeilknöpfe, Pfeiltasten und die Ansage der
   Position. Die Spur läuft randlos bis an den Fensterrand, die erste
   Karte steht trotzdem an der Kante des Containers. */
.karussell { position: relative; }
.karussell-spur {
  --rand: max(var(--space-4), calc((100vw - var(--shell)) / 2 + var(--space-4)));
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(260px, 78vw, 360px);
  gap: var(--space-4);
  margin: 0;
  padding: var(--space-2) var(--rand) var(--space-5);
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--rand);
  scroll-behavior: smooth;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.karussell-spur::-webkit-scrollbar { display: none; }
.karussell-spur:focus-visible { outline-offset: -3px; }
.karussell-element { scroll-snap-align: start; display: flex; }
.karussell-element > * { flex: 1; }
.karussell-steuerung {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}
.karussell-knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--panel);
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius-m);
  color: var(--text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dauer-schnell) var(--ease-out), opacity var(--dauer-schnell) var(--ease-out), transform var(--dauer-druck) var(--ease-out);
}
.karussell-knopf:hover:not(:disabled) { background: var(--surface); }
.karussell-knopf:active:not(:disabled) { transform: scale(0.94); }
.karussell-knopf:disabled { opacity: 0.35; cursor: default; }

/* Ab Tablet-Breite alle Pakete als Raster nebeneinander — nichts wandert
   seitlich weg, keine Pfeile. Wischen bleibt nur auf dem Handy. */
@media (min-width: 900px) {
  .karussell-spur {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    max-width: var(--shell);
    margin-inline: auto;
    padding: var(--space-2) var(--space-4) var(--space-5);
    overflow: visible;
    scroll-snap-type: none;
  }
  .karussell-steuerung { display: none; }
}

/* Set-Karte im Karussell: großes Bild, eine Zeile Nutzen, Preis, Aktion. */
.set-karte {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--surface);
  border: var(--strich) solid var(--border);
  border-radius: var(--radius-l);
  transition: transform var(--dauer-mittel) var(--ease-out), box-shadow var(--dauer-mittel) var(--ease-out);
}
@media (hover: hover) {
  .set-karte:hover { transform: translateY(-4px); box-shadow: var(--schatten-1); }
}
.set-karte .shop-bild { margin: calc(var(--space-4) * -1) calc(var(--space-4) * -1) var(--space-2); border-radius: var(--radius-l) var(--radius-l) 0 0; }
.set-karte h3 { font-size: var(--fs-h3); font-weight: 700; }
.set-karte h3 a { color: var(--text); text-decoration: none; }
.set-karte h3 a:hover { text-decoration: underline; }
.set-karte p { color: var(--text-sec); font-size: var(--fs-300); }
.set-karte .preis-zeile { margin-top: auto; padding-top: var(--space-2); }

/* ── Erzählung: Problem → Ursache → Lösungs-Set ────────────────────
   Links eine klebende Bühne, rechts die Schritte. Der Schritt in der
   Bildmitte ist aktiv (ui.js setzt .aktiv), die passende Bühnen-Ebene
   blendet über. Unter 834 px und bei reduzierter Bewegung: eine ruhige
   Liste, jeder Schritt trägt sein Bild selbst. */
.erzaehlung {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-7);
}
.erzaehlung-buehne {
  position: sticky;
  top: calc(var(--kopf-h-kompakt) + var(--space-5));
  align-self: start;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-l);
  background: var(--panel);
  overflow: hidden;
}
.erzaehlung-ebene {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--space-6);
  opacity: 0;
  transform: scale(0.97);
  transition: opacity var(--dauer-langsam) var(--ease-out), transform var(--dauer-langsam) var(--ease-out);
}
.erzaehlung-ebene.aktiv { opacity: 1; transform: none; }
/* Inaktive Schritte werden bewusst NICHT abgeblendet: Bei 35 % Deckkraft
   fällt der Text auf rund 2:1, erst ab 80 % hielte er 4,5:1 in beiden
   Themes. Den Wechsel zeigt die Bühne. */
.erzaehlung-schritt {
  min-height: 70vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.erzaehlung-schritt h3 {
  font-size: var(--fs-h2);
  font-weight: 700;
  letter-spacing: var(--ls-display);
  margin-bottom: var(--space-3);
}
.erzaehlung-schritt p { font-size: var(--fs-lead); color: var(--text-sec); line-height: 1.45; max-width: 36ch; }
.erzaehlung-schritt .schritt-bild { display: none; }
.schritt-nr {
  font-size: var(--fs-300);
  font-weight: 600;
  color: var(--marke-text);
  margin-bottom: var(--space-2);
}
@media (max-width: 833px), (prefers-reduced-motion: reduce) {
  .erzaehlung { grid-template-columns: 1fr; gap: var(--space-6); }
  .erzaehlung-buehne { display: none; }
  .erzaehlung-schritt { min-height: 0; }
  .erzaehlung-schritt .schritt-bild {
    display: grid;
    place-items: center;
    aspect-ratio: 4 / 3;
    margin-bottom: var(--space-4);
    padding: var(--space-5);
    border-radius: var(--radius-l);
    background: var(--panel);
  }
}

/* ── Fortschrittsanzeige (Kasse) ────────────────────────────────────
   Die vierte und letzte Stelle des Doppelstrichs: Die erledigte Strecke
   IST der Doppelstrich. Er wächst per transform (scaleX, Anteil in
   --anteil, von shop.js gesetzt), die Schritte
   tragen Nummer, Namen und aria-current — die Linie ist Zierde, der
   Text die Aussage. */
.fortschritt {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--schritte, 3), minmax(0, 1fr));
  margin: 0 0 var(--space-6);
  padding: 0 0 calc(var(--doppel-h) + var(--space-2));
  list-style: none;
  counter-reset: schritt;
}
.fortschritt::before,
.fortschritt::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--doppel-h);
}
.fortschritt::before { background: linear-gradient(var(--border-stark) 0 0) left 0 bottom 0 / 100% var(--strich) no-repeat; }
.fortschritt::after {
  background: var(--doppelstrich-unten);
  transform-origin: left center;
  transform: scaleX(var(--anteil, 0));
  transition: transform var(--dauer-langsam) var(--ease-out);
}
.fortschritt li {
  counter-increment: schritt;
  font-size: var(--fs-300);
  color: var(--text-sec);
  padding-bottom: var(--space-1);
}
.fortschritt li::before {
  content: counter(schritt) " ";
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  margin-right: 0.35em;
}
.fortschritt li[aria-current="step"] { color: var(--text); font-weight: 700; }
.fortschritt li.erledigt::before { content: "\2713\FE0E "; color: var(--ok); }

/* ══ Seiten ═══════════════════════════════════════════════════════ */

/* ── Startseite: Hero ───────────────────────────────────────────────
   Eine Botschaft, zwei Wege, dann die Produkte. Die Bühne trägt die
   Dachschräge (Stelle 1 von 2) und drei Pakete, die beim Scrollen
   leicht gegeneinander laufen. */
.hero { overflow: hidden; }
.hero-kopf { display: grid; justify-items: center; text-align: center; }
.hero .display { max-width: 16ch; }
/* Großtext (ab 44 px, fett) — 3:1 genügt, deshalb das reine Logo-Orange (3,10:1 auf --bg). */
.hero .display em { font-style: normal; color: var(--marke); }
.hero .lead { margin: 0 auto var(--space-5); }
.hero-aktionen { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }
.hero-buehne {
  position: relative;
  margin-top: var(--space-7);
  aspect-ratio: 16 / 7;
  background: var(--panel);
  overflow: hidden;
}
.hero-produkt {
  position: absolute;
  height: auto;
  border-radius: var(--radius-m);
  box-shadow: var(--schatten-2);
}
.hero-produkt--mitte  { width: 40%; left: 30%; top: 16%; z-index: 2; }
.hero-produkt--links  { width: 27%; left: 5%;  top: 38%; }
.hero-produkt--rechts { width: 27%; right: 5%; top: 30%; }
@media (max-width: 640px) {
  .hero-buehne { aspect-ratio: 4 / 3; }
  .hero-produkt--mitte  { width: 64%; left: 18%; top: 22%; }
  .hero-produkt--links  { width: 42%; left: -6%; top: 50%; }
  .hero-produkt--rechts { width: 42%; right: -6%; top: 8%; }
}

/* ── Startseite: Bildmotive der Erzählung ───────────────────────────
   Gezeichnet mit den Token des umgebenden Abschnitts — im dunklen
   Abschnitt also automatisch dunkel. */
.motive { position: absolute; width: 0; height: 0; overflow: hidden; }
.motiv { display: block; width: 100%; max-width: 420px; aspect-ratio: 1 / 1; height: auto; }
.m-flaeche { fill: var(--surface); }
.m-linie   { fill: none; stroke: var(--border-stark); stroke-width: 2; }
.m-befall  { fill: var(--text-sec); }
.m-rahmen  { fill: none; stroke: var(--text-sec); stroke-width: 6; }
.m-tropfen { fill: var(--text-sec); }
.m-anzeige { fill: var(--text-sec); }
.m-karton  { fill: var(--panel); stroke: var(--border-stark); stroke-width: 2; }
.m-nuvax   { fill: var(--nuvax); }
.schritt-aktion { margin-top: var(--space-5); }

/* ── Abschnittsköpfe ────────────────────────────────────────────── */
.abschnitt-kopf { margin-bottom: var(--space-6); }
.abschnitt-kopf .section-sub { margin-bottom: 0; }
.abschnitt-kopf-zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  margin-bottom: var(--space-3);
}
.abschnitt-kopf-zeile .abschnitt-titel { margin-bottom: 0; }

/* ── Startseite: Chat-Panel ─────────────────────────────────────── */
.chat-wrap {
  height: min(640px, 78vh);
  max-width: 880px;
  margin-inline: auto;
}
/* Einstieg über der gesperrten Eingabe — verschwindet nach dem Hinweis. */
.chat-start {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-4);
  background: var(--surface);
  border-top: var(--strich) solid var(--border);
  text-align: center;
}
.chat-start p { font-size: var(--fs-200); color: var(--text-sec); }

/* ── Startseite: Eigenmarke ─────────────────────────────────────────
   Die EINZIGE große Fläche in Nuvax-Farbe — sie markiert die Marke.
   Der Link darin ist eine Aktion und trägt deshalb die Shop-Farbe. */
.nuvax-block {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  align-items: center;
  gap: var(--space-7);
  padding: var(--space-7);
  background: var(--nuvax-dim);
  border-radius: var(--radius-l);
}
/* Das Nuvax-Logo ist schwarz und hat keine helle Fassung: eigene weiße
   Platte, auch im Dunkelmodus. Ein fremdes Zeichen färbt man nicht um. */
.nuvax-logo {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  padding: var(--space-6);
  background: #ffffff;
  border-radius: var(--radius-l);
}
.nuvax-logo img { width: 100%; height: auto; max-width: 320px; }
.nuvax-block .lead { color: var(--text); margin-bottom: var(--space-3); }
@media (max-width: 833px) {
  .nuvax-block { grid-template-columns: 1fr; padding: var(--space-5); gap: var(--space-5); }
}

/* ── Startseite: Vertrauen ──────────────────────────────────────── */
.vertrauen-raster {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: var(--space-6) var(--space-5);
  margin-top: var(--space-6);
}
.vertrauen-punkt svg {
  width: 36px;
  height: 36px;
  margin-bottom: var(--space-3);
  fill: none;
  stroke: var(--text);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.vertrauen-punkt h3 { font-size: var(--fs-h3); margin-bottom: var(--space-1); }
.vertrauen-punkt p { color: var(--text-sec); }

/* ── Startseite: Anfrage ────────────────────────────────────────── */
.anfrage-raster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
  gap: var(--space-7);
  align-items: start;
}
.anfrage-raster .form-card { max-width: none; }

/* ── Seitenkopf der Unterseiten ─────────────────────────────────── */
.seitenkopf { padding-bottom: var(--space-6); }
.seitenkopf .display { margin-bottom: var(--space-3); }

/* ── Katalog ────────────────────────────────────────────────────────
   Ruhig: Suche und Filter liegen frei auf der Fläche, keine Karte drum. */
.katalog-bereich { padding-top: var(--space-6); }
.katalog-steuerung {
  background: none;
  border: 0;
  padding: 0;
  margin-bottom: var(--space-5);
  gap: var(--space-4);
}
.filter-zeile { align-items: center; }
.filter-zeile .filter-gruppe { min-width: 0; flex: 0 1 auto; }
/* Grid-Kinder sind sonst mindestens so breit wie ihr Inhalt — eine nicht
   umbrechende Filterschiene drückte dann die ganze Seite in die Breite. */
.katalog-steuerung { grid-template-columns: minmax(0, 1fr); }
.katalog-steuerung > * { min-width: 0; }
@media (max-width: 640px) {
  .filter-zeile { gap: var(--space-1); }
  .filter-titel { flex-basis: 100%; }
  /* Weicher rechter Rand: zeigt, dass die Schiene weitergeht. */
  .filter-gruppe {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    padding-right: 28px;
  }
}

/* ── Warenkorb (Seite und Drawer) ───────────────────────────────── */
.korb-raster {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(300px, 1fr);
  gap: var(--space-7);
  align-items: start;
}
.korb-uebersicht {
  position: sticky;
  top: calc(var(--kopf-h-kompakt) + var(--space-4));
  display: grid;
  gap: var(--space-2);
  padding: var(--space-5);
  background: var(--surface);
  border: var(--strich) solid var(--border);
  border-radius: var(--radius-l);
}
.korb-uebersicht h2 { font-size: var(--fs-h3); margin-bottom: var(--space-2); }
.korb-uebersicht .summen-hinweis { margin-bottom: var(--space-2); }
@media (max-width: 900px) {
  .korb-raster { grid-template-columns: 1fr; gap: var(--space-5); }
  .korb-uebersicht { position: static; }
}
/* Zeile: Bild, Name + Preis, Menge. */
.korb-zeile { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; }
.korb-zeile:not(:has(.korb-bild)) { grid-template-columns: minmax(0, 1fr) auto; }
.korb-bild {
  width: 72px;
  height: 54px;
  object-fit: contain;
  background: var(--panel);
  border-radius: var(--radius-s);
}
.korb-name { color: var(--text); text-decoration: none; display: block; }
a.korb-name:hover { text-decoration: underline; }
.ebene-inhalt .korb-zeile { grid-template-columns: auto minmax(0, 1fr); }
.ebene-inhalt .korb-zeile .menge-steuerung { grid-column: 2; }
.ebene-inhalt .biozid-note { margin-top: var(--space-3); }
@media (max-width: 640px) {
  .korb-zeile { grid-template-columns: auto minmax(0, 1fr); }
  .korb-zeile .menge-steuerung { grid-column: 2; }
}

/* ── Kasse ──────────────────────────────────────────────────────── */
.kasse-seite { padding-block: var(--space-6) var(--space-8); }
.kasse-titel {
  font-size: var(--fs-h1);
  font-weight: 700;
  letter-spacing: var(--ls-display);
  margin-bottom: var(--space-5);
}
#kasse-bereich.kasse-schritt.aktiv {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(300px, 1fr);
  gap: 0 var(--space-7);
  align-items: start;
}
#kasse-bereich .fortschritt { grid-column: 1 / -1; }
#kasse-form { max-width: none; }
.kasse-teil { animation: schritt-auf var(--dauer-mittel) var(--ease-out); }
@keyframes schritt-auf {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: none; }
}
.kasse-teil h2 { font-size: var(--fs-h3); margin-bottom: var(--space-4); }
.kasse-teil h2:focus { outline: none; }
.kasse-teil h2:focus-visible { outline: 3px solid var(--fokus); outline-offset: 4px; }
.kasse-navigation {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}
.kasse-navigation .btn:only-child { margin-left: auto; }
.kasse-schritt .kasse-navigation .btn { margin-top: 0; }
.kasse-pruefung {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-5);
  padding: var(--space-4);
  background: var(--panel);
  border-radius: var(--radius-m);
  font-size: var(--fs-300);
}
.kasse-pruefung dt { color: var(--text-sec); }
.kasse-pruefung dd { margin: 0; overflow-wrap: anywhere; }
.kasse-uebersicht {
  position: sticky;
  top: calc(var(--kopf-h-kompakt) + var(--space-4));
  border-radius: var(--radius-l);
}
.kasse-ergebnis { max-width: 640px; margin-inline: auto; text-align: center; padding-block: var(--space-6); }
.kasse-ergebnis h2 { font-size: var(--fs-h1); letter-spacing: var(--ls-display); margin-bottom: var(--space-3); }
.kasse-ergebnis-zeichen {
  display: inline-grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin-bottom: var(--space-4);
  background: var(--ok-bg);
  border: var(--strich) solid var(--ok);
  border-radius: var(--radius-l);
  color: var(--ok);
  font-size: 32px;
  font-weight: 700;
  animation: modal-auf var(--dauer-langsam) var(--ease-out);
}
@media (max-width: 900px) {
  #kasse-bereich.kasse-schritt.aktiv { grid-template-columns: 1fr; gap: var(--space-5); }
  .kasse-uebersicht { position: static; }
}
@media (max-width: 640px) {
  .kasse-navigation { flex-direction: column-reverse; align-items: stretch; }
  .kasse-navigation .btn { width: 100%; }
  .kasse-pruefung { grid-template-columns: 1fr; gap: 0; }
  .kasse-pruefung dd { margin-bottom: var(--space-2); }
}

/* ── Die Schwellen ──────────────────────────────────────────────────
   Abstände, Schriftgrößen und Raster regeln sich oben von selbst. Übrig
   bleiben die Stellen, an denen sich die STRUKTUR ändert:

   Desktop (ab 1025 px)  Ausgangszustand ohne Query.
   Tablet  (bis 1024 px) Der Hero bricht um.
   Menü    (bis 833 px)  Navigation wird zum Vollbild-Menü (oben beim
                         Kopf definiert). Der Kopf klebt weiter — er ist
                         jetzt nur noch eine Zeile hoch.
   Handy   (bis 640 px)  Einspaltige Formulare, gestapelte Aktionen; die
                         feste Hinweis-Fußzeile braucht eine zweite Zeile. */

/* Tablet */
@media (max-width: 1024px) {
  .marken-panel { grid-template-columns: 1fr; text-align: center; justify-items: center; }
}

/* Handy */
@media (max-width: 640px) {
  .hero-aktionen { flex-direction: column; align-items: stretch; }
  .hero-aktionen .btn { width: 100%; }
  .msg, .msg-error { max-width: 92%; }
  .chat-messages { padding-inline: var(--space-3); }
  .chat-vorschlag { font-size: var(--fs-200); }
  .chat-wrap { height: min(560px, 80vh); }
  .form-row-strasse,
  .form-row-ort,
  .form-row-name { grid-template-columns: 1fr; }
  body { padding-bottom: 84px; }
}

/* Honigtopf-Feld gegen Formular-Bots: aus dem sichtbaren Bereich geschoben
   statt display:none — manche Bots überspringen versteckte Felder gezielt. */
.honigtopf {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── Ratgeber (erzeugt von scripts/seo_build.py) ───────────────────── */
.ratgeber .brotkrumen { margin-bottom: var(--space-2); font-size: var(--fs-200); }
.ratgeber .brotkrumen a { color: var(--text-sec); }
.ratgeber h1 { margin-bottom: var(--space-2); }
.ratgeber h2 { margin-top: var(--space-6); }
.ratgeber h3 { margin-top: var(--space-4); font-size: var(--fs-500); }
.ratgeber ol,
.ratgeber ul { padding-left: 1.3em; }
.ratgeber li + li { margin-top: var(--space-1); }
.ratgeber .hinweis-box {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--panel);
  border-left: var(--strich-marke) solid var(--marke);
  border-radius: var(--radius-s);
  color: var(--text);
}
.ratgeber .biozid-note { margin-top: var(--space-6); }
.ratgeber-weiter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-5);
}
.ratgeber-liste {
  list-style: none;
  padding: 0 !important;
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-5);
}
.ratgeber-liste li { margin: 0 !important; }
.ratgeber-liste a {
  display: grid;
  gap: 4px;
  padding: var(--space-4);
  background: var(--surface);
  border: var(--strich) solid var(--border);
  border-radius: var(--radius-m);
  color: var(--text);
  text-decoration: none;
  transition: border-color var(--dauer-schnell) var(--ease-out),
              transform var(--dauer-schnell) var(--ease-out);
}
.ratgeber-liste a:hover { border-color: var(--border-stark); transform: translateY(-2px); }
.ratgeber-liste a span { color: var(--text-sec); font-size: var(--fs-300); }
.ratgeber-liste em { font-size: var(--fs-100); color: var(--text-dim); }

/* ── Lange deutsche Wörter auf schmalen Bildschirmen ──────────────────
   "Geschäftsbedingungen" passt in 36 px nicht in 343 px Breite. Silben-
   trennung nur auf dem Telefon (lang="de" ist gesetzt); lange Zeichenketten
   ohne Trennstelle (Unterstrich-Linien im Muster-Formular) dürfen brechen. */
@media (max-width: 640px) {
  h1, h2, h3 { hyphens: auto; -webkit-hyphens: auto; overflow-wrap: break-word; }
}
.page-content--text p,
.page-content--text li { overflow-wrap: break-word; }

/* ── Produktseite: Gefahrstoffkennzeichnung (CLP Art. 48) ─────────────
   Piktogramme behalten ihre Pflichtfarben (roter Rand, weißer Grund) —
   auch im dunklen Modus, darum keine Filter. */
.clp-piktogramme { display: flex; gap: 8px; margin: 4px 0 8px; }
.clp-piktogramme img { width: 64px; height: 64px; }
.clp-titel { font-weight: 600; margin: 12px 0 4px; }
.clp-saetze { list-style: none; padding: 0; margin: 0 0 8px; }
.clp-saetze li { padding: 2px 0; line-height: 1.5; }
.clp-code { font-weight: 600; font-variant-numeric: tabular-nums; margin-right: 4px; }

/* ── Versandseite: Staffel aus der Warenwirtschaft ────────────────────── */
.versand-staffel table { border-collapse: collapse; margin-block: var(--space-2); }
.versand-staffel th,
.versand-staffel td { text-align: left; padding: 6px 16px 6px 0; border-bottom: var(--strich) solid var(--border); }
.versand-staffel td:last-child { font-variant-numeric: tabular-nums; }

/* ── Auswahl von Größe und Variante (Katalogkarte und Produktseite) ───── */
/* Die Hülle der Familienkarte verhält sich im Raster wie eine Karte. */
.shop-card-familie { display: flex; min-width: 0; }
.shop-card-familie > .shop-card { flex: 1; min-width: 0; }
.shop-card > .karte-auswahl { order: 3; }
.karte-auswahl,
.pd-auswahl { display: flex; flex-direction: column; gap: var(--space-2); }
.pd-auswahl { margin-block: var(--space-3); }
.karte-auswahl-gruppe,
.pd-wahl-liste { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pd-wahl-gruppe { display: flex; flex-direction: column; gap: 6px; }
.karte-auswahl-titel {
  flex-basis: 100%;
  font-size: var(--fs-100);
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.pd-wahl-titel { font-size: var(--fs-200); color: var(--text-sec); }
.pd-wahl-titel strong { color: var(--text); }
.chip--wahl,
.pd-wahl {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 4px 12px;
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-200);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.chip--wahl:hover,
.pd-wahl:hover { border-color: var(--marke-strong); }
.chip--wahl[aria-pressed="true"],
.pd-wahl--aktiv {
  border-color: var(--marke-strong);
  box-shadow: inset 0 0 0 1px var(--marke-strong);
  background: var(--surface);
}
.pd-hersteller { font-size: var(--fs-200); color: var(--text-sec); }

/* ── Setinhalt: auf der Karte, im Warenkorb und auf der Produktseite ──── */
.shop-card > .karte-setinhalt { order: 5; }
.karte-setinhalt,
.korb-setinhalt { font-size: var(--fs-100); color: var(--text-sec); line-height: 1.45; }
.karte-setinhalt ul,
.korb-setinhalt ul { list-style: none; margin: 2px 0 0; padding: 0; }
.korb-setinhalt { margin-top: 4px; }
.pd-menge { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ── Weitere Produktfotos ─────────────────────────────────────────
   Karte: kleine Punkte unten im Bild. Produktseite: Vorschaubilder unter
   dem Hauptbild. Das gewählte Foto trägt den Markenstrich. */
.shop-bild { position: relative; }
.bild-punkte {
  position: absolute;
  left: 50%;
  bottom: var(--space-2);
  transform: translateX(-50%);
  display: flex;
  gap: 2px;
}
.bild-punkt {
  /* 24px Trefferfläche, sichtbar ein 8px-Punkt */
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.bild-punkt::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.25);
  box-shadow: 0 0 0 1.5px #fff;
}
.bild-punkt[aria-pressed="true"]::before { background: var(--marke-strong); }
.bild-punkt:focus-visible { outline: 2px solid var(--marke-strong); outline-offset: -2px; border-radius: 50%; }

.pd-vorschau {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.pd-vorschau button {
  width: 72px;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--radius-s, 6px);
  background: var(--panel);
  overflow: hidden;
  cursor: pointer;
}
.pd-vorschau button[aria-pressed="true"] { border-color: var(--marke-strong); }
.pd-vorschau button:focus-visible { outline: 2px solid var(--marke-strong); outline-offset: 2px; }
.pd-vorschau img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Überschrift über einer Auswahl im Raster (z. B. „Sie kaufen als“) */
.zahlart-titel {
  float: left; /* nimmt die Legende in das Raster des Fieldsets */
  width: 100%;
  grid-column: 1 / -1;
  padding: 0;
  font-weight: 600;
  font-size: var(--fs-300);
}

/* Gefahrenhinweis auf Katalog- und Chat-Karte (CLP Art. 48) */
.karte-gefahr, .ce-gefahr {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-100, 0.8125rem);
  line-height: 1.35;
  color: var(--text);
}
.karte-gefahr img, .ce-gefahr img { width: 28px; height: 28px; flex: none; }
.karte-gefahr span, .ce-gefahr span { flex: 1 1 12rem; }

/* ── Katalog: alle Karten gleich hoch ─────────────────────────────
   Jede Reihe so hoch wie die höchste Karte im Katalog; Preis und Knopf
   stehen dank margin-top:auto immer unten. Namen höchstens zwei Zeilen. */
/* Gleich hoch je Reihe (Raster streckt die Karten); Preis und Knopf
   stehen unten. Über den ganzen Katalog gleich hoch hieße: einfache Karten
   mit 400 px Leerraum. */
.product-grid > .shop-card,
.product-grid > .shop-card-familie { height: 100%; }
.shop-card .karte-auswahl-gruppe { margin-bottom: var(--space-1); }
.shop-card h3 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(2 * 1.4em);
}
.karte-auswahl-liste {
  min-height: 44px;
  width: 100%;
  padding: 0 var(--space-3);
  border: var(--strich) solid var(--border-stark);
  border-radius: var(--radius-m);
  background: var(--surface);
  color: var(--text);
  font: inherit;
}
.shop-card .karte-gefahr { font-size: 0.75rem; color: var(--text-sec); }
.shop-card .karte-gefahr img { width: 24px; height: 24px; }

/* Startseite: echte Produktfotos auf heller Fläche, Format 4:3 */
.hero-produkt { aspect-ratio: 4 / 3; object-fit: cover; background: var(--panel); }
