/** Shopify CDN: Minification failed

Line 1552:1 Unexpected "}"

**/
/* ==========================================================================
   PRESCH — globales Custom-CSS
   Eingebunden über snippets/custom.globals.liquid (via theme.liquid).

   Regeln:
   - Keine Vendor-Datei per !important überschreiben. Horizon ist vollständig
     über CSS-Variablen und Theme-Settings steuerbar — Marken-Tokens (Farben,
     Radien, Typo-Skala) gehören in config/settings_data.json, NICHT hierher.
   - Hier nur, was sich über Settings nicht ausdrücken lässt: Interaktions-
     Feedback, eigene Komponenten-Styles.
   - Komponenten-CSS, das nur eine Section betrifft, gehört in den
     {% stylesheet %}-Block der jeweiligen custom.*-Datei.
   - Nur transform und opacity animieren (GPU, kein Layout/Paint).
   - Jede Animation braucht einen Grund. Shop-UI wird täglich benutzt —
     Deko-Animationen machen sie auf Dauer langsam, nicht schöner.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Easing-Tokens
   Horizon liefert keine. Die CSS-Standardkurven sind zu schwach — sie wirken
   beliebig. Diese Kurven starten schnell und geben sofortiges Feedback.
   ease-in wird bewusst NICHT definiert: es startet langsam und lässt jede
   Interaktion träge wirken, genau im Moment der höchsten Aufmerksamkeit.
   -------------------------------------------------------------------------- */
:root {
  --custom-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --custom-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --custom-duration-press: 140ms;

  /* PRESCH-Dunkelton der Marken-Bänder. Steht als Literal in den
     Section-Settings der Startseite (background_color) und ist deshalb in
     keiner Theme-Variable greifbar — hier einmal benannt, statt ihn in
     Komponenten zu wiederholen. */
  --custom-color-dark: #253746;

  /* Platte hinter den Award-Logos. Weiß, weil die freigestellten Originale
     dunkle Schrift tragen („GERMAN DESIGN AWARD" ist schwarz) und auf dunklem
     Grund sonst unlesbar wären. Nur dort nötig — auf hellem Grund verschmelzen
     die freigestellten Logos ohne Platte. */
  --custom-color-award-plate: #ffffff;

  /* Ruhige Kartenfläche für Vorteils-Karten. Bewusst ein kühler Grauton und
     kein warmes Beige wie in der Vorlage: Die PRESCH-Palette ist auf das Navy
     #253746 gebaut, ein warmer Ton daneben wirkt schmutzig. */
  --custom-color-surface: #f2f4f6;
}

/* --------------------------------------------------------------------------
   2. Press-Feedback auf Buttons
   Grund: Feedback. „In den Warenkorb" ist die wichtigste Interaktion im Shop.
   Ohne Press-State fühlt sich der Klick an, als wäre er ins Leere gegangen —
   besonders auf Touch, wo kein Hover existiert. scale bleibt subtil (0.97),
   nur transform wird animiert.
   -------------------------------------------------------------------------- */
.button,
.button-secondary,
button.shopify-payment-button__button--unbranded {
  transition: transform var(--custom-duration-press) var(--custom-ease-out);
}

.button:active,
.button-secondary:active,
button.shopify-payment-button__button--unbranded:active {
  transform: scale(0.97);
}

/* Mengen-Stepper: kleinere Fläche, deshalb kräftigeres Feedback.
   Diese Buttons werden mehrfach hintereinander gedrückt — Transition statt
   Keyframes, damit schnelle Wiederholung sauber unterbrochen wird. */
.quantity-selector .button-unstyled {
  transition: transform var(--custom-duration-press) var(--custom-ease-out);
}

.quantity-selector .button-unstyled:active {
  transform: scale(0.92);
}

/* --------------------------------------------------------------------------
   3. Steuerhinweis unter dem Preis (snippets/custom.price.liquid)
   Text kommt aus den Locales, nie aus dem Markup.
   -------------------------------------------------------------------------- */
.custom-price__tax-note {
  display: block;
  margin-block-start: 0.25rem;
  color: rgb(var(--color-foreground-rgb) / var(--opacity-muted-text));
  font-size: var(--font-size--xs);
}

/* --------------------------------------------------------------------------
   4. Reduced Motion
   Bewegung raus, Farb-/Opacity-Übergänge bleiben — sie helfen beim Verstehen.
   Reduced Motion heißt weniger und sanfter, nicht null.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .button,
  .button-secondary,
  button.shopify-payment-button__button--unbranded,
  .quantity-selector .button-unstyled {
    transition: none;
  }

  .button:active,
  .button-secondary:active,
  button.shopify-payment-button__button--unbranded:active,
  .quantity-selector .button-unstyled:active {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   B2B-Layer (später): Netto-/Staffelpreis-Darstellung, Mengenregel-Hinweise.
   Platzhalter bewusst leer — hier ergänzen, nicht in Vendor-Dateien.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   5. Kategorie-Kacheln: runde Ecken
   Die Kacheln der collection-list werden über `resource-list` gerendert und
   haben deshalb kein eigenes border_radius-Setting im Template. Radius hier,
   passend zur Karten-Rundung aus den Theme-Settings (12px).
   -------------------------------------------------------------------------- */
.collection-card {
  border-radius: 12px;
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   6. Artikelnummer-Treffer in der Suche (custom.js)
   Erscheint nur, wenn die Eingabe eine echte SKU ist. Bewusst kräftig
   abgesetzt: wer eine Artikelnummer tippt, will genau dieses eine Produkt.
   -------------------------------------------------------------------------- */
.custom-sku-hit {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-block-start: 8px;
  padding: 10px 12px;
  border: 1px solid var(--color-primary-button-background, #fc4c02);
  border-radius: 8px;
  text-decoration: none;
  color: inherit;
  transition: transform var(--custom-duration-press) var(--custom-ease-out);
}

.custom-sku-hit:active {
  transform: scale(0.99);
}

.custom-sku-hit__label {
  font-size: var(--font-size--xs);
  color: var(--color-primary-button-background, #fc4c02);
}

.custom-sku-hit__title {
  font-size: var(--font-size--sm);
}

/* --------------------------------------------------------------------------
   7. „Meintest du …?" (custom.js)
   Erscheint nur, wenn Shopify keine Treffer liefert. Zurückhaltender als der
   Artikelnummer-Treffer: es ist ein Vorschlag, keine Gewissheit.
   -------------------------------------------------------------------------- */
.custom-did-you-mean {
  display: block;
  width: 100%;
  margin-block-start: 8px;
  padding: 8px 12px;
  border: 1px solid var(--color-border, #d6dde3);
  border-radius: 8px;
  background: none;
  text-align: left;
  font-size: var(--font-size--sm);
  color: inherit;
  cursor: pointer;
  transition: transform var(--custom-duration-press) var(--custom-ease-out);
}

.custom-did-you-mean:active {
  transform: scale(0.99);
}

/* ==========================================================================
   8. Markenschrift Malva (Harbor Type)
   ==========================================================================
   Die PRESCH-CI schreibt Malva vor, ausdrücklich als Webfont für
   Online-Anwendungen. Horizon lief bis hier auf Inter — das war der größte
   verbleibende Marken-Bruch.

   Warum hier und nicht über die Theme-Settings: Shopifys `font_picker` kennt
   nur Schriften aus der Shopify-Bibliothek. Malva ist lizenziert und wird
   selbst gehostet, deshalb werden die vier `--font-*--family`-Variablen
   überschrieben. custom.css wird NACH Horizons CSS geladen, gleiche
   Spezifität gewinnt also — kein !important nötig.

   Relative url(): Shopify liefert Assets aus demselben CDN-Verzeichnis wie
   diese Datei, deshalb lösen die Pfade ohne Liquid korrekt auf.

   font-display: swap — Text ist sofort lesbar, die Schrift tauscht nach.
   Bei 70 % Mobile-Anteil wichtiger als ein unsichtbarer Erstaufbau.
   ========================================================================== */

@font-face {
  font-family: 'Malva';
  src: url('custom.malva-light.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

/* ACHTUNG, hier steckt eine bewusste Entscheidung:
   Weight 400 zeigt auf malva-MEDIUM, nicht auf malva-book.

   Gemessen am 2026-08-10 über die Farbdeckung einer identischen Textzeile bei
   16px (Canvas, Summe der Tintendeckung geteilt durch die Laufweite):
     Malva Book 400   → 0,750 der Deckung von Helvetica Regular
     Malva Medium 500 → 1,035
   Die Laufweite war in beiden Fällen gleich (477px), es liegt also rein an der
   Strichstärke: Malvas „Book" ist ein LICHTER Schnitt, kein normaler Regular.
   25 % weniger Farbe im Fließtext liest ausgewaschen — der Kunde hat den Text
   als schwer lesbar gemeldet, und das ist die Ursache. Nicht die Schriftgröße:
   Malvas x-Höhe liegt bei 0,500 gegen 0,523 bei Helvetica, also nur 4 %
   darunter, und Größe, Zeilenhöhe (1,6), Laufweite (0em) sowie Kontrast
   (12,3:1) sind alle unauffällig.

   Book bleibt unter 350 verfügbar, falls er für großen Displaytext gebraucht
   wird — dort ist ein lichter Schnitt richtig. Ein nicht benutztes @font-face
   lädt nichts nach. */
@font-face {
  font-family: 'Malva';
  src: url('custom.malva-book.woff2') format('woff2');
  font-weight: 350;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Malva';
  src: url('custom.malva-medium.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Malva';
  src: url('custom.malva-book-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Malva';
  src: url('custom.malva-medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Malva';
  src: url('custom.malva-bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Black (900) fuer die Display-Headlines der Produkt-Landingpages
   (SPOTIX-PDP, Design-Handoff 2026-08-21). Die CI nennt Light/Book/Bold als
   Textschnitte -- Black ist der Plakat-Schnitt aus dem PRESCH Design System
   (Malva-Black.otf aus dem Handoff, Lizenz Harbor Type). Wird nur geladen,
   wo font-weight 900 tatsaechlich vorkommt. */
@font-face {
  font-family: 'Malva';
  src: url('custom.malva-black.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* EIN Orange im Shop. Vorher liefen drei Werte parallel: #fc4c02 als
     Aktionspreis-Ton aus einer frueheren Runde, #FC4C02 aus der
     Theme-Einstellung fuer Knoepfe und #eb6012 im Design-System. Gemessen
     stand der Kartenpreis dadurch in #fc4c02, Eyebrow und Menuekante aber in
     #FC4C02. Maßgeblich ist die Theme-Einstellung, weil ihr die Knoepfe
     folgen. */
  --presch-orange: #fc4c02;

  /* Heller Orange-Ton fuer Text AUF Bildern. Das Markenorange erreicht dort die
     Kontrastschwelle nicht: Es hat fast dieselbe Helligkeit wie ein
     halbabgedunkeltes Foto mit orangefarbenen Produkten — gemessen im
     Startseiten-Hero 2,26:1 gegen die hellste Stelle unter der Zeile (0,087),
     noetig sind 3:1 fuer 20px fett. Auch ein dichterer Schleier hilft nicht,
     die Grenze liegt in der Farbe. #ff8f4d traegt dort 3,40:1 und liest sich
     weiter als PRESCH-Orange. Auf weissem Grund bleibt ueberall das
     Markenorange. */
  --presch-orange-auf-bild: #ff8f4d;

  /* Aktionspreis-Ton = Markenorange. Die Variable wurde bislang nur BENUTZT,
     nie definiert — es rendert dann der Ersatzwert im Aufruf, und der stand
     auf #fc4c02. Genau daran hing der abweichende Kartenpreis. */
  --custom-color-sale: var(--presch-orange);

  --font-body--family: 'Malva', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-heading--family: 'Malva', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-subheading--family: 'Malva', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-accent--family: 'Malva', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* ==========================================================================
   9. Trust-Reihe (snippets/custom.trust-row.liquid, custom.trust-item.liquid)
   ==========================================================================
   Mobil eine wischbare Reihe, ab 750px ein Raster. Begründung steht im
   {% doc %}-Block des Snippets; hier nur die Umsetzung.

   grid statt flex, weil `grid-auto-columns` allen Karten dieselbe Breite gibt.
   Mit flex müsste jede Karte `flex: 0 0 78%` selbst tragen, und ungleich lange
   Texte würden die Breiten auseinanderziehen.
   -------------------------------------------------------------------------- */
.custom-trust-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 78%;
  /* Aus demselben Grund wie bei .custom-awards: In Horizons zentrierter
     Flex-Spalte wäre die Liste shrink-to-fit, und `78%` bezöge sich auf eine
     inhaltsabhängige Breite. */
  width: 100%;
  gap: var(--gap-lg);
  margin: 0;
  /* Platz für den Scrollbalken, damit er nicht über den Text läuft. */
  padding: 0 0 var(--padding-xs);
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Verhindert, dass die Wischbewegung die ganze Seite mitzieht. */
  overscroll-behavior-x: contain;
}

.custom-trust-row > .custom-trust-item {
  scroll-snap-align: start;
}

/* Variante 'grid': auch mobil alles sichtbar, zwei Spalten. Für Abschnitte,
   in denen die Reihe der Hauptinhalt ist und nichts übersehen werden darf. */
.custom-trust-row--grid {
  grid-auto-flow: row;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-columns: auto;
  overflow-x: visible;
  scroll-snap-type: none;
}

/* Im Grid-Modus steht das Icon mobil ÜBER dem Text, nicht daneben.
   Gemessen bei 375px Viewport: zwei Spalten lassen je ~168px, davon frisst
   das Icon samt Abstand 40px — der Text bekommt 130px und bricht nach zwei
   bis drei Wörtern. Untereinander steht die volle Spaltenbreite zur
   Verfügung. Ab 750px greift die Regel weiter unten und stellt das Icon
   wieder neben den Text. */
@media screen and (max-width: 749px) {
  .custom-trust-row--grid .custom-trust-item {
    flex-direction: column;
    gap: var(--gap-2xs);
  }

  .custom-trust-row--grid .custom-trust-item__media {
    margin-block-start: 0;
    margin-block-end: var(--gap-2xs);
  }
}

@media screen and (min-width: 750px) {
  .custom-trust-row,
  .custom-trust-row--grid {
    grid-auto-flow: row;
    /* auto-fit statt fester Spaltenzahl: die Reihe funktioniert mit drei wie
       mit vier Elementen, ohne dass der Aufrufer etwas mitteilen muss. */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    grid-auto-columns: auto;
    padding-block-end: 0;
    overflow-x: visible;
    scroll-snap-type: none;
  }
}

.custom-trust-item {
  display: flex;
  gap: var(--gap-md);
  align-items: flex-start;
}

.custom-trust-item__media {
  flex: 0 0 auto;
  /* Optischer Ausgleich: Das Icon soll auf der Mittellinie der ersten
     Textzeile sitzen, nicht an deren Oberkante. */
  margin-block-start: 0.1em;
}

.custom-trust-item__title {
  margin: 0;
  font-size: var(--font-size--md);
  line-height: 1.3;
}

.custom-trust-item__text {
  margin-block-start: var(--gap-2xs);
  font-size: var(--font-size--sm);
  color: rgb(var(--color-foreground-rgb) / var(--opacity-muted-text));
}

/* Rich-Text-Settings liefern <p>-Umbrüche mit. Der Abstand wird oben schon
   gesetzt, deshalb hier den Eigenabstand des ersten/letzten Absatzes weg. */
.custom-trust-item__text > :first-child {
  margin-block-start: 0;
}

.custom-trust-item__text > :last-child {
  margin-block-end: 0;
}

/* 44px Mindesthöhe über padding, nicht über min-height allein: so bleibt der
   Link im Textfluss und die Fläche wächst um die Schrift herum. */
.custom-trust-item__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: var(--padding-2xs);
  font-size: var(--font-size--sm);
}

/* ==========================================================================
   10. Auszeichnungen (snippets/custom.awards.liquid, custom.award-badge.liquid)
   ==========================================================================
   Die Logos sind freigestellt und tragen dunkle Schrift. Auf hellem Grund
   verschmelzen sie ohne Platte; auf dunklem Grund brauchen sie eine weiße
   Platte, sonst verschwindet die schwarze GDA-Schrift.
   Siehe {% doc %}-Block in custom.award-badge.liquid.
   -------------------------------------------------------------------------- */
/* Zwei gemessene Zwänge, die das Layout bestimmen:

   1. Mobil müssen die Kacheln NEBENEINANDER bleiben. Mit fester Breite von
      160px plus Platten-Innenabstand ist eine Kachel 192px breit; zwei davon
      brauchen 400px, auf einem 375px-Gerät stehen 335px zur Verfügung. Sie
      kippen also untereinander und werden dabei bildschirmfüllend groß — zwei
      übergroße Award-Kacheln im Einspalter wirken wie Eigenlob und kosten eine
      halbe Bildschirmhöhe.
   2. Auf dem Desktop müssen sie ZUSAMMENSTEHEN. Ein `repeat(auto-fit,
      minmax(140px, 1fr))`-Raster gab bei 1280px zwei Spalten à 572px und damit
      einen halben Meter Luft zwischen den Logos — sie lasen dann wie zwei
      unabhängige Bilder, nicht wie eine Auszeichnungsreihe.

   Deshalb flex mit prozentualer Basis: `calc(50% - gap)` sind mobil verlässlich
   zwei pro Zeile, und `max-width` bremst das Wachstum auf breiten Schirmen, wo
   `justify-content: center` die Kacheln als Gruppe zusammenhält.

   Prozent, nicht vw: Die Basis muss sich am Container orientieren. Horizons
   Seitenrand ändert sich mit dem `page_width`-Setting und mit der Section, in
   der die Reihe steht — eine vw-Rechnung wäre genau dann falsch. */
.custom-awards {
  display: flex;
  flex-wrap: wrap;
  /* PFLICHT, nicht Kosmetik: Horizons generische `section` legt ihre Blöcke als
     Flex-Spalte mit `align-items: center` aus. Ohne Breitenangabe ist diese
     Liste dort shrink-to-fit — die Flex-Basis `calc(50% - gap)` bezöge sich
     dann auf eine Breite, die selbst vom Inhalt abhängt, und kollabiert. Im
     Theme waren die Kacheln dadurch auf wenige Pixel geschrumpft.
     Im normalen Blockfluss ändert `width: 100%` nichts. */
  width: 100%;
  gap: var(--gap-lg);
  /* stretch, nicht center: Die beiden Logos haben unterschiedliche
     Seitenverhältnisse (400×194 und 400×228) und ergäben sonst zwei
     verschieden hohe Kacheln. Als Auszeichnungs-SET gelesen wirkt das
     unaufgeräumt; gleiche Höhe macht daraus eine Reihe. Das Logo selbst
     bleibt in seiner Kachel zentriert. */
  align-items: stretch;
  justify-content: center;
  margin: 0;
  padding: 0;
  list-style: none;
}

.custom-award-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 calc(50% - var(--gap-lg));
  min-width: 0;
  /* Deckel, damit die Logos auf breiten Schirmen nicht mitwachsen. */
  max-width: var(--custom-award-width, 160px);
}

.custom-award-badge--plate {
  padding: var(--padding-md) var(--padding-lg);
  border-radius: var(--style-border-radius-md, 0.8rem);
  background-color: var(--custom-color-award-plate);
  /* Die Platte trägt die Logobreite plus ihren Innenabstand. */
  max-width: calc(var(--custom-award-width, 160px) + 2 * var(--padding-lg));
}

.custom-award-badge__image {
  display: block;
  width: 100%;
  height: auto;
}

/* ==========================================================================
   11. Kategorie-Kacheln (snippets/custom.collection-card.liquid)
   ==========================================================================
   Bild als Fläche, darauf ein weißes Label-Kärtchen unten mittig.

   Die bisherigen Kacheln (weiße Piktogramme auf Navy) trugen keinen sichtbaren
   Titel — der Name stand nur als versteckter Text für Screenreader in Horizons
   Karte. Wer das Piktogramm nicht deutet, wusste nicht, wohin er klickt. Das
   Label ist hier also Funktion, nicht Dekor.
   -------------------------------------------------------------------------- */
/* Das Seitenverhältnis sitzt auf der KACHEL, nicht auf dem Bild. Grund ist ein
   im Theme aufgetretener Fehler: Lag es auf dem Bild und fehlte das Bild (kein
   Collection-Bild, kein Produktbild, nicht aufgelöste Referenz), hatte die
   Kachel keine Höhe — das Label rutschte als nackter Text ins Raster und die
   Zelle blieb leer. So hält die Kachel ihren Platz in jedem Fall, und der
   graue Grund zeigt beim Einrichten sofort, dass ein Bild fehlt. */
.custom-collection-card {
  display: block;
  position: relative;
  aspect-ratio: var(--custom-collection-card-ratio, 4 / 5);
  /* Die Kachel ist ihr eigener Container, damit das Label auf die KACHELBREITE
     reagieren kann und nicht auf die Fensterbreite. Nötig, weil die Breite hier
     von der Spaltenzahl abhängt: Eine Kachel bei fünf Spalten auf dem Desktop
     ist schmaler als eine bei zwei Spalten auf dem Telefon. Eine
     Viewport-Abfrage würde genau den Fall verfehlen. */
  container-type: inline-size;
  border-radius: 12px;
  /* Sicherung, damit kein Bild über die runden Ecken hinausragt, egal welches
     Format hereinkommt. Zunächst weggelassen mit der Begründung, der Fokusring
     der Kachel würde beschnitten — das war falsch: Ein Outline wird am Element
     selbst gezeichnet und von dessen eigenem overflow nicht beschnitten. */
  overflow: hidden;
  background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10, 0.1));
  color: inherit;
  text-decoration: none;
}

/* Statisch im Fluss, nicht absolut positioniert: Die Kachel trägt das
   Seitenverhältnis, das Bild füllt sie einfach aus. Ein absolut positioniertes
   Bild wurde im Theme geladen (HTTP 200) und trotzdem nicht dargestellt —
   ohne den Umweg tritt das nicht auf, und die Struktur ist einfacher. */
.custom-collection-card__image {
  display: block;
  width: 100%;
  height: 100%;
  /* cover, weil Produkt- und Anwendungsfotos in jedem Format hereinkommen.
     Ohne cover verzerrt oder briefmarkt das Motiv. */
  object-fit: cover;
  border-radius: 12px;
}

.custom-collection-card__label {
  position: absolute;
  /* 12px Abstand zum Rand: nimmt den Kachelradius auf, ohne dass das Label
     die Ecke berührt. */
  inset-block-end: 12px;
  inset-inline-start: 50%;
  translate: -50% 0;

  display: flex;
  align-items: center;
  justify-content: center;
  /* Breite nicht fix: In der Vorlage nimmt das Label rund 58 % ein. Bei
     „Bohrer" neben „Schrauben & Fixieren" würde eine feste Breite den langen
     Namen abschneiden. fit-content mit Mindestbreite gibt kurzen Namen Statur
     und lässt lange wachsen — abgesetzt bleiben sie durch max-width. */
  width: fit-content;
  /* Schmale Kachel: KEIN Mindestmaß und mehr Platz in der Breite. Bei zwei
     Spalten auf 375px ist die Kachel rund 170px breit, bei fünf Spalten auf
     1280px rund 225px. Mit Mindestbreite und großzügigem Innenabstand brach
     „Feilen & Formen" dort auf drei Zeilen und das Label verdeckte halb die
     Kachel. */
  max-width: calc(100% - 16px);
  min-height: 44px;
  padding: var(--padding-xs) var(--padding-md);
  box-sizing: border-box;

  background-color: #fff;
  /* Haarlinie, weil die PRESCH-Produktfotos auf WEISS freigestellt sind: Ohne
     Rand verschwindet das weiße Kärtchen darin und übrig bleibt schwebender
     Text — im Theme genau so gesehen. Der Rand macht daraus in jedem Fall eine
     Karte, auch auf einem hellen Motiv. Bewusst eine Linie und kein Schatten:
     Das Design ist flach. */
  border: 1px solid rgb(var(--color-foreground-rgb) / 0.12);
  border-radius: 8px;
  color: var(--custom-color-dark);
  font-size: var(--font-size--sm);
  line-height: 1.2;
  text-align: center;
  /* Kein text-wrap: balance — bei zwei bis drei Wörtern stellt es das „&"
     allein in eine Zeile. Der normale Umbruch liest hier besser. */
}

/* Statur erst ab einer Kachelbreite, bei der der längste Kategoriename
   („Schrauben & Fixieren") in zwei Zeilen passt. Container-Abfrage, nicht
   Viewport: Entscheidend ist, wie breit DIESE Kachel ist. In der Vorlage nimmt
   das Label rund 58 % ein — deshalb hier das Mindestmaß, damit kurze Namen wie
   „Bohrer" nicht als schmale Pille stehen. */
@container (min-width: 280px) {
  .custom-collection-card__label {
    min-width: 55%;
    max-width: calc(100% - 24px);
    padding: var(--padding-xs) var(--padding-xl);
    font-size: var(--font-size--md);
  }
}

/* Das Label reagiert mit, obwohl die ganze Kachel der Link ist: Auf dem Desktop
   ist es die Stelle, auf die der Blick fällt, und ein Hover-Zustand irgendwo
   sonst würde nicht gesehen. Nur transform, kein Layout. */
.custom-collection-card__label {
  transition: transform var(--custom-duration-press) var(--custom-ease-out);
}

.custom-collection-card:active .custom-collection-card__label {
  transform: translateY(1px);
}

@media (prefers-reduced-motion: reduce) {
  .custom-collection-card__label {
    transition: none;
  }

  .custom-collection-card:active .custom-collection-card__label {
    transform: none;
  }
}

/* ==========================================================================
   12. Vorteils-Karten (snippets/custom.benefit-card.liquid)
   ==========================================================================
   Illustration halb über der Kartenkante. Umgesetzt über absolute Positionierung
   plus reservierten Platz an der Karte selbst — so bleibt die Reihe gleich hoch
   und der Aufrufer muss nichts ausrechnen.
   -------------------------------------------------------------------------- */
.custom-benefit {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;

  /* Außen die halbe Bildhöhe, damit das überstehende Motiv nicht in den
     Abschnitt darüber ragt; innen dieselbe halbe Höhe plus Abstand, damit die
     Überschrift nicht unter das Motiv rutscht. Beides aus derselben Variablen,
     die das Snippet setzt — eine andere Bildgröße verschiebt also nichts. */
  margin-block-start: calc(var(--custom-benefit-media, 88px) / 2);
  padding-block-start: calc(var(--custom-benefit-media, 88px) / 2 + var(--padding-xl));
  padding-block-end: var(--padding-4xl);
  padding-inline: var(--padding-2xl);

  background-color: var(--custom-color-surface);
  border-radius: 16px;
  text-align: center;
}

.custom-benefit__media {
  position: absolute;
  inset-block-start: calc(-1 * var(--custom-benefit-media, 88px) / 2);
  inset-inline-start: 50%;
  translate: -50% 0;
  width: var(--custom-benefit-media, 88px);
  height: auto;
}

.custom-benefit__title {
  margin: 0;
  font-size: var(--font-size--lg);
  line-height: 1.25;
  /* balance ist hier richtig, anders als beim kurzen Kachel-Label: Diese
     Überschriften sind ganze Halbsätze über zwei bis drei Zeilen, und da
     verhindert es die einsame Restzeile. */
  text-wrap: balance;
}

.custom-benefit__text {
  margin-block-start: var(--gap-md);
  font-size: var(--font-size--sm);
  color: rgb(var(--color-foreground-rgb) / var(--opacity-muted-text));
}

.custom-benefit__text > :first-child {
  margin-block-start: 0;
}

.custom-benefit__text > :last-child {
  margin-block-end: 0;
}

/* Icon-Variante: weiße Scheibe, damit das Symbol wie ein Medaillon über der
   Karte liegt und nicht als nacktes Piktogramm in der Luft hängt. PRESCH hat
   keine Illustrationen wie die Vorlage — so ist der Abschnitt ohne neue Assets
   brauchbar. */
.custom-benefit__media--icon {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--custom-benefit-media, 88px);
  background-color: #fff;
  /* Haarlinie wie beim Kachel-Label und aus demselben Grund: Die obere Hälfte
     der Scheibe liegt auf dem weißen Seitenhintergrund und verschwand darin —
     übrig blieb ein frei schwebendes Symbol. Der Rand macht daraus in jedem
     Fall ein Medaillon. */
  border: 1px solid rgb(var(--color-foreground-rgb) / 0.12);
  border-radius: 50%;
  color: var(--custom-color-dark);
}

.custom-benefit__media--icon svg {
  /* Halbe Scheibengröße: Ein randfüllendes Symbol wirkt gedrängt. */
  width: 50%;
  height: 50%;
}

/* Ohne Bild und ohne Symbol darf die Karte keinen Platz für ein Motiv
   reservieren — sonst klafft oben eine Lücke. Im Theme genau so aufgefallen. */
.custom-benefit:not(:has(.custom-benefit__media)) {
  margin-block-start: 0;
  padding-block-start: var(--padding-4xl);
}

/* ==========================================================================
   13. Preis, Steuerhinweis und Lagerstatus auf der Produktseite
   ==========================================================================
   -------------------------------------------------------------------------- */

/* Steuerhinweis kleiner. Horizon setzt ihn per `.tax-note.tax-note.tax-note`
   auf `min(0.85em, --font-paragraph--size)`, also faktisch 16px — genauso groß
   wie der Fließtext und damit zu präsent neben einem 32px-Preis. Dieselbe
   dreifache Klasse hier, um die Spezifität zu treffen; custom.css lädt nach
   Horizons CSS, gleiche Spezifität gewinnt also ohne !important.

   Bewusst 14px und nicht kleiner: Der Hinweis auf enthaltene Steuern und
   Versandkosten ist in Deutschland nach Preisangabenverordnung Pflichtangabe
   und muss klar lesbar bleiben. Kleinergedrucktes wäre hier kein Design,
   sondern ein Risiko. */
.tax-note.tax-note.tax-note {
  font-size: var(--font-size--sm);
}

/* Pulsierender Lagerpunkt, wie im alten Live-Theme. Grund: „Auf Lager" plus
   Lieferzeit ist an dieser Stelle die letzte offene Frage vor dem Klick — ein
   leises Lebenszeichen zieht den Blick genau dorthin.

   Umsetzung anders als live: Das Live-Theme animierte `box-shadow`, das malt in
   jedem Frame neu. Hier pulsiert ein Ring aus `::after` über `transform` und
   `opacity` — beides auf der GPU, kein Layout und kein Paint. So hält sich der
   Effekt an Regel 4 dieser Datei.

   3s Zyklus wie live: langsam genug, dass es nicht flackert, schnell genug,
   dass man es bemerkt. */
.product-inventory__icon-in_stock {
  position: relative;
}

.product-inventory__icon-in_stock::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 2px currentcolor;
  animation: custom-stock-pulse 3s var(--custom-ease-out) infinite;
  pointer-events: none;
}

@keyframes custom-stock-pulse {
  0% {
    transform: scale(0.6);
    opacity: 0.55;
  }

  70% {
    transform: scale(1.6);
    opacity: 0;
  }

  100% {
    transform: scale(1.6);
    opacity: 0;
  }
}

/* Lieferhinweis unter dem Lagerstatus.
   Sichtbar NUR, wenn der Lagerpunkt „auf Lager" zeigt — über den
   Geschwister-Selektor, nicht über Liquid. Grund: Horizons
   `<product-inventory>` tauscht beim Variantenwechsel seine Statusklasse
   selbst aus, CSS folgt damit ohne eigenes JavaScript. Ein Liquid-`if` würde
   beim Wechsel auf eine ausverkaufte Variante stehen bleiben und eine
   Lieferzeit für etwas versprechen, das nicht lieferbar ist. */
.custom-delivery-hint {
  display: none;
  margin-block-start: var(--gap-2xs);
  font-size: var(--font-size--sm);
  font-weight: 500;
  color: var(--color-instock);
}

product-inventory:has(.product-inventory__icon-in_stock) ~ .custom-delivery-hint {
  display: block;
}

@media (prefers-reduced-motion: reduce) {
  .product-inventory__icon-in_stock::after {
    animation: none;
    opacity: 0;
  }
}

/* Strichpreis deutlich kleiner als der aktuelle Preis. Horizon lässt ihn die
   Größe des Preises erben — bei 24px Preis stehen dann zwei 24px-Zahlen
   nebeneinander und konkurrieren, obwohl die durchgestrichene die
   nachrangige Information ist.

   Bewusst 1rem und nicht kleiner: Der Vergleichspreis begründet den Nachlass,
   er muss lesbar bleiben. 16px gegen 24px ist ein klarer Unterschied, ohne ihn
   zur Fußnote zu machen.

   Gezielt über `product-price.custom-typography`, also nur dort, wo der
   Preis-Block ein eigenes Typo-Preset trägt — das ist unsere Produktseite.
   Produktkarten erben ihre Preisgröße aus der Karte und bleiben unberührt. */
product-price.custom-typography .compare-at-price {
  font-size: 1rem;
}

/* Zahlarten-Auswahl unter dem Kaufbutton (blocks/custom-payment-icons.liquid).
   Höhe über eine Variable, damit sie im Editor einstellbar bleibt; Breite
   automatisch, weil die Shopify-SVGs unterschiedliche Seitenverhältnisse haben
   und feste Breiten sie verzerren würden. */
.custom-payment-icons__list {
  display: flex;
  align-items: center;
  justify-content: var(--custom-payment-align, flex-start);
  flex-wrap: wrap;
  gap: var(--gap-xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

.custom-payment-icons__list svg,
.custom-payment-icons__list img {
  display: block;
  height: var(--custom-payment-height, 26px);
  width: auto;
}

/* ==========================================================================
   14. Kundenstimmen (Sterne und Zitatkarten)
   ==========================================================================
   -------------------------------------------------------------------------- */

/* Sternereihe. Zwei deckungsgleiche Reihen liegen im Grid übereinander, die
   obere wird per clip-path auf den Anteil beschnitten. Deshalb Grid und nicht
   `position: absolute`: So bestimmt die untere Reihe die Größe, und die obere
   kann nicht aus dem Fluss fallen — bei absoluter Positionierung hätte die
   Reihe keine eigene Höhe und Text daneben würde daran vorbeirutschen. */
.custom-stars {
  display: inline-grid;
  grid-template-areas: 'stars';
  line-height: 0;
}

.custom-stars__row {
  grid-area: stars;
  display: flex;
  gap: 0.1em;
}

.custom-stars__icon {
  width: var(--custom-stars-size, 16px);
  height: var(--custom-stars-size, 16px);
  flex: none;
}

/* Die leere Skala bleibt sichtbar, damit erkennbar ist, worauf sich die Note
   bezieht — 4 von 5 sieht ohne Skala aus wie „vier Sterne insgesamt". */
.custom-stars__row--empty .custom-stars__icon {
  fill: var(--custom-color-dark, #253746);
  opacity: 0.18;
}

.custom-stars__row--full {
  clip-path: inset(0 calc(100% - var(--custom-stars-fill, 0%)) 0 0);
}

/* Sterne in der Markenfarbe. Zur Projektregel „Orange ist die CTA-Farbe":
   Eine Bewertung ist ein Zustand, kein Angebot, und in diesem Abschnitt steht
   kein Button, mit dem sie konkurrieren könnte. Bewusst hier und nicht global. */
.custom-stars__row--full .custom-stars__icon {
  fill: var(--color-primary-button-background, #fc4c02);
}

/* Zitatkarte. Flex-Spalte mit `margin-block-start: auto` an der Fußzeile: So
   sitzt die Herkunft in einer Reihe gleich hoher Karten immer unten, egal wie
   lang das Zitat ist. */
.custom-review {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm, 0.75rem);
  height: 100%;
  margin: 0;
  padding: var(--padding-lg, 1.5rem);
  background-color: var(--custom-color-surface, #f2f4f6);
  border-radius: var(--style-border-radius-blocks, 8px);
}

/* Das Zitat ist der Inhalt, also größer als die Herkunft daneben — ein
   14px-Zitat neben großen Sternen ist der häufigste Fehler in solchen
   Abschnitten. Die lockere Zeilenhöhe kommt aus den Theme-Tokens. */
.custom-review__quote {
  margin: 0;
  font-size: 1.125rem;
  line-height: var(--line-height--body-loose, 1.6);
}

.custom-review__quote p {
  margin: 0;
}

/* Herkunft in eigenen Zeilen: Name, Produkt, Kennzeichnungen. Erster Versuch
   war eine Zeile mit Mittelpunkt als Trenner — in einer 319px breiten Karte
   bricht die Zeile aber, und der Trenner landet am Zeilenanfang, wo er wie ein
   Aufzählungspunkt liest. Eine Spalte bricht nie falsch, unabhängig von der
   Kartenbreite und von der Länge der Produktnamen in anderen Sprachen. */
.custom-review__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
  margin-block-start: auto;
  font-size: var(--font-size--sm, 0.875rem);
}

/* Die Kennzeichnungen bleiben untereinander in einer Reihe, weil sie zusammen
   gehören: beide sagen etwas über die Herkunft der Bewertung. */
.custom-review__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-xs, 0.5rem);
  margin-block-start: 0.15rem;
}

.custom-review__name {
  font-weight: 500;
}

.custom-review__product,
.custom-review__verified {
  opacity: 0.7;
}

.custom-review__verified {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
}

.custom-review__check {
  width: 1em;
  height: 1em;
  flex: none;
  fill: currentcolor;
}



/* Im Karussell steht eine Karte pro Folie und muss die Folienhöhe füllen,
   sonst schwebt sie in der Mitte. */
.custom-reviews__slide .custom-review {
  height: 100%;
}

/* Hinweis auf eine Gegenleistung. Bewusst als eigene, kleine Auszeichnung mit
   Umriss statt als weiterer grauer Text: Er muss erkennbar sein, sonst erfüllt
   er seinen Zweck nicht — aber er soll das Zitat nicht überstimmen. */
.custom-review__incentive {
  font-size: var(--font-size--xs, 0.75rem);
  padding: 0.1em 0.5em;
  border: 1px solid currentcolor;
  border-radius: 999px;
  opacity: 0.6;
}

/* ==========================================================================
   15. Aktionspreis, Ersparnis-Badge und Textbadges
   ==========================================================================
   -------------------------------------------------------------------------- */

/* Aktionspreis in der Aktionsfarbe, wie im alten Theme. Der Selektor greift
   über `:has()` am Container: Der Preis wird nur dann umgefärbt, wenn wirklich
   ein Streichpreis daneben steht. So bleibt jeder normale Preis unberührt, ohne
   dass Liquid eine zweite Klasse ausgeben muss — und es funktioniert auch nach
   einem Variantenwechsel, bei dem product-price.js den Container neu füllt.

   Zur Projektregel „Orange ist die CTA-Farbe": Hier ist es ausdrücklich so
   gewünscht (Vorgabe altes Theme). Der Kaufen-Button bleibt der einzige orange
   FLÄCHIGE Baustein auf der Produktseite; ein farbiger Preis konkurriert damit
   weniger als ein zweiter Button. */
[ref='priceContainer']:has(.compare-at-price) .price {
  color: var(--custom-color-sale, #fc4c02);
}

/* Streichpreis bleibt gedeckt: Er ist die Bezugsgröße, nicht das Angebot. */
[ref='priceContainer'] .compare-at-price {
  color: color-mix(in srgb, var(--color-foreground) 55%, transparent);
  text-decoration: line-through;
}

/* Ersparnis-Badge auf der Produktseite. Gleiche Form und Farbe wie das Badge
   über dem Kartenbild, damit Karte und Produktseite als dasselbe System lesen.
   `align-self: center` hält es auf der optischen Mittellinie der Preiszeile,
   die durch die große Preisziffer bestimmt wird. */
.custom-savings-badge {
  display: inline-block;
  align-self: center;
  padding: 0.25em 0.7em;
  border-radius: var(--style-border-radius-badge, 6px);
  background-color: var(--custom-color-sale, #fc4c02);
  color: #fff;
  font-size: var(--font-size--sm, 0.875rem);
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
}

/* Textbadges („Bestseller") tragen ihre Farben inline aus den globalen
   Einstellungen; hier nur, was Form und Abstand betrifft. */
.product-badges__badge.custom-badge--label {
  font-weight: 500;
}

/* ==========================================================================
   16. Produkt-Varianten als eigene Produkte, Badges auf der Produktseite
   ==========================================================================
   -------------------------------------------------------------------------- */

/* Geschwisterprodukte. Aussehen bewusst identisch zu Horizons
   Variantenschaltflächen (dieselben Tokens für Rahmen, Radius, Polsterung und
   Mindesthöhe), damit die zwei Variantenansichten auf einer Seite als EIN
   Bedienelement lesen und nicht als zwei verschiedene Systeme. */
.custom-variations {
  display: flex;
  flex-direction: column;
  gap: var(--margin-xs, 0.5rem);
  margin: 0;
  padding: 0;
  border: none;
  width: 100%;
}

.custom-variations__legend {
  padding: 0;
  color: var(--variant-option-label-color, var(--color-foreground));
}

/* Doppelpunkt als CSS-Dekoration: Satzzeichen, das nicht vorgelesen werden
   muss, und in anderen Sprachen anders gesetzt wird. */
.custom-variations__label::after {
  content: ':';
}

.custom-variations__current {
  padding-inline-start: var(--padding-xs);
  color: var(--variant-option-label-color-subdued, var(--color-foreground-subdued));
}

.custom-variations__options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-sm);
}

.custom-variations__option {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3.25em;
  padding-block: var(--padding-sm);
  padding-inline: var(--padding-lg);
  border: var(--options-border-width, 1px) solid var(--color-variant-border);
  border-radius: var(--options-border-radius);
  background-color: var(--color-variant-background);
  color: var(--color-variant-text);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--animation-speed) var(--animation-easing),
    border-color var(--animation-speed) var(--animation-easing),
    color var(--animation-speed) var(--animation-easing);
}

.custom-variations__option:hover {
  background-color: var(--color-variant-hover-background);
  border-color: var(--color-variant-hover-border);
  color: var(--color-variant-hover-text);
}

/* Aktueller Zustand über `aria-current`, nicht über eine Extraklasse allein:
   Damit ist die Auszeichnung im Markup dieselbe, die auch Vorlesesoftware
   nutzt — die Optik kann nicht behaupten, was der Baum nicht sagt. */
.custom-variations__option[aria-current='page'] {
  border-color: var(--color-selected-variant-border);
  border-width: calc(var(--options-border-width, 1px) * 2);
  font-weight: 500;
}

/* Badges auf der Produktseite: dieselbe Form wie über dem Kartenbild, aber im
   Textfluss unter dem Titel statt über einem Bild. */
.custom-pdp-badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-xs, 0.5rem);
}

.custom-pdp-badges__badge {
  display: inline-block;
  padding: 0.25em 0.7em;
  border-radius: var(--badge-border-radius, 8px);
  background-color: var(--custom-color-dark, #253746);
  color: #fff;
  font-size: var(--font-size--sm, 0.875rem);
  font-weight: 500;
  line-height: 1.3;
}

/* Sternebewertung unter dem Produkttitel. Als Link ausgezeichnet, deshalb
   bewusst ohne Unterstreichung, aber mit Unterstreichung beim Hover: Die
   Sterne tragen die Erkennbarkeit, der Sprung zum Beweis ist der Bonus. */
.custom-product-rating {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-xs, 0.5rem);
  text-decoration: none;
  color: inherit;
  font-size: var(--font-size--sm, 0.875rem);
}

.custom-product-rating:hover .custom-product-rating__count {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.custom-product-rating__value {
  font-weight: 500;
}

.custom-product-rating__count {
  opacity: 0.7;
}

/* Zweites Kopfleisten-Menü (Bestseller/Angebote) neben dem Logo. Übernimmt die
   Typografie der Hauptnavigation, damit die Kopfleiste eine Schrift spricht;
   abgesetzt wird über die Zeile, nicht über Farbe oder Größe. */
.custom-header-secondary__list {
  display: flex;
  align-items: center;
  gap: var(--gap-lg, 1.25rem);
  margin: 0;
  padding: 0;
}

/* Farbe über `--color-foreground` und NICHT über `color: inherit`.

   Horizon schaltet den transparenten Header um, indem es auf `.header__row`
   die Variable neu belegt: `--color-foreground: var(--color-transparent-text)`.
   Custom Properties werden aber dort aufgelöst, wo sie BENUTZT werden. Ein
   `color: inherit` erbt die bereits aufgelöste Farbe eines Vorfahren, der die
   Variable früher gelesen hat — also die dunkle. Gemessen: Kategorielinks
   `rgb(255,255,255)`, meine Links `rgb(37,55,70)`, und zwar durch die ganze
   Kette bis `header-component`.

   Wer die Variable selbst liest, schaltet mit: über dem Hero weiß, auf weißem
   Grund und im Sticky-Zustand dunkel. Genau so machen es Horizons eigene
   Kopfleisten-Bausteine. */
.custom-header-secondary__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
  color: var(--color-foreground);
  /* 1rem statt 0.875rem: „Bestseller" und „Angebote" sind die zwei
     wichtigsten Direkteinstiege der Kopfleiste und standen kleiner als das
     Hauptmenue darunter.

     Versalien mit derselben Sperrung wie das Hauptmenue (0,04em): Gemischte
     Schreibweise direkt ueber einer Versalienzeile las sich wie zwei
     verschiedene Menues. Die Groesse bleibt bei 16px gegen 14px unten — die
     Direkteinstiege duerfen praesenter sein als die Kategorien. */
  font-size: 1rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.custom-header-secondary__link:hover {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* Aktueller Eintrag: Auszeichnung über das Attribut, das auch Vorlesesoftware
   nutzt — keine reine Optik-Klasse. */
.custom-header-secondary__link[aria-current='page'] {
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* Auf schmalen Viewports übernimmt die Schublade die Navigation; die zwei Links
   würden dort mit Logo und Icons um dieselbe Zeile konkurrieren.

   Bis 989px statt 749px (Feedbackliste 2026-08-27, Mehmet): Zwischen 750 und
   ~950px läuft die Rechnung nicht mehr auf — das Raster der Kopfzeile ist
   `1fr auto 1fr`, die Seitenspalten teilen sich also (Viewport − Suchfeld) / 2.
   Gemessen bei 768px: Logo (161) + Abstand + Versalien (213) brauchen ~385px,
   die Spalte bekommt aber nur (768 − 190) / 2 = 289px — das Suchfeld schob
   sich über „BESTSELLER". Die Kategoriezeile darunter bleibt in diesem Band
   vollständig, nur die zwei Merchandising-Links weichen. */
@media screen and (max-width: 989px) {
  .custom-header-secondary {
    display: none;
  }
}

/* ==========================================================================
   17. Luft in der zweizeiligen Kopfleiste
   ==========================================================================
   -------------------------------------------------------------------------- */

/* Gemessener Ausgangszustand bei 1440px: obere Zeile 57px, untere 32px, beide
   mit `padding: 0` (Horizon setzt `header--collapse-row-paddings`, sobald beide
   Zeilen gleichfarbig sind und keine Trennlinie haben). Die Klickflächen der
   Kategorien lagen mit 0px Abstand aneinander, die Linkhöhe betrug 23px — unter
   den 44px, die ein Tap-Target braucht.

   Die Trennlinie ist in den Section-Settings gesetzt und hebt den Kollaps auf.
   Hier kommt dazu, was Settings nicht hergeben: Höhe der Navigationszeile und
   Abstand zwischen den Einträgen. */
#header-component .header__row--bottom .header__columns {
  padding-block: var(--padding-sm);
}

/* Menüpunkte weiter auseinander — und zwar an EINER Variable.

   Der Abstand zwischen den Wörtern kommt bei Horizon nicht aus
   `--menu-horizontal-gap`, sondern aus einer eigenen Regel am Titel:
   `.menu-list__link-title { padding-inline: calc(var(--gap-xl) / 2) }`, also
   10px je Seite. Nur `--menu-horizontal-gap` zu erhöhen bleibt deshalb wirkungslos
   — gemessen: Variable 2rem, Textabstand weiter 20px.

   Wichtig ist die Kopplung: `.overflow-menu::part(list)` zieht die Liste mit
   `margin-inline: calc(-1 * var(--menu-horizontal-gap) / 2)` wieder auf die
   Seitenkante, damit der erste Eintrag bündig sitzt. Wer nur die Polsterung
   erhöht, verschiebt die ganze Zeile um die Differenz. Deshalb liest die
   Polsterung hier dieselbe Variable wie die Kompensation. */
#header-component .header__row--bottom .menu-list {
  --menu-horizontal-gap: 2rem;
}

#header-component .header__row--bottom .menu-list__link-title {
  padding-inline: calc(var(--menu-horizontal-gap) / 2);
}

/* Tap-Target: Die Zeilenhöhe allein macht die Linkfläche nicht größer, weil die
   Höhe aus der Zeilenhöhe der Schrift kommt. */
#header-component .header__row--bottom .menu-list__link {
  min-height: 40px;
}

/* Abstand Logo → Bestseller/Angebote. Vorher 20px, das klebte am Logo. */
.custom-header-secondary {
  margin-inline-start: var(--gap-xl, 1.25rem);
}

/* Suche in der Kopfleiste: Feld plus Klappfläche darunter.

   Die Klappfläche hängt an `:focus-within` — Klick ins Feld öffnet, Klick
   daneben schließt. Bewusst ohne JavaScript: Die erste Fassung dieses Feldes
   öffnete Horizons Modal per Skript und hörte dabei auf `focusin`. Beim
   Schließen gibt der Browser den Fokus an das auslösende Element zurück, das
   Modal ging sofort wieder auf, und die Suche ließ sich nicht mehr schließen.
   Ein Zustand, den CSS selbst kennt, kann nicht hängen bleiben. */
.custom-search-inline {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-width: 12rem;
  max-width: 32rem;
}

.custom-search-inline__form {
  width: 100%;
}

.custom-search-inline__field {
  position: relative;
  display: flex;
  align-items: center;
}

.custom-search-inline__icon {
  position: absolute;
  inset-inline-start: var(--padding-sm, 0.75rem);
  display: flex;
  pointer-events: none;
  opacity: 0.6;
}

.custom-search-inline__icon svg {
  width: 1rem;
  height: 1rem;
}

/* Der Wrapper traegt `color-custom-popover`, damit Feld und Loeschen
   verlaessliche Farbvariablen haben: Ueber dem transparenten Header setzt die
   Kopfleiste `--color-foreground` auf Weiss, und das Feld waere weiss auf
   weiss. Malen darf der Wrapper nicht — sonst steht wieder eine eckige Platte
   hinter dem gerundeten Feld (derselbe Fehler wie zuvor an der Komponente). */
.custom-search-inline__field {
  background-color: transparent;
}

.custom-search-inline__input {
  width: 100%;
  min-height: 44px;
  padding-block: var(--padding-xs);
  padding-inline: calc(var(--padding-sm) * 2 + 1rem) var(--padding-md);
  border: var(--style-border-width-inputs, 1px) solid var(--color-border);
  border-radius: var(--style-border-radius-inputs, 8px);
  background-color: var(--color-background);
  color: var(--color-foreground);
  /* 1rem: Das Feld ist deckend und soll lesbar sein; unter 16px zoomt iOS beim
     Fokus zusaetzlich die ganze Seite. */
  font-size: 1rem;
}

.custom-search-inline__input::placeholder {
  color: color-mix(in srgb, var(--color-foreground) 60%, var(--color-background));
}

/* „Loeschen" in der Markenfarbe statt in der geerbten Textfarbe: Geerbt war es
   ueber dem Hero weiss und auf dem jetzt deckend hellen Feld unlesbar.

   Die Farbe kommt als eigene Variable aus den Theme-Einstellungen, NICHT aus
   `--color-primary-button-background`: Die ist schemaabhaengig und loest im
   Popover-Schema auf #ffffff auf — gemessen stand „Loeschen" damit weiss auf
   weissem Feld. Orange auf Weiss liegt bei ~4,6:1 und ist als Aktion erkennbar. */
.custom-search-inline__reset {
  position: absolute;
  inset-inline-end: var(--padding-sm, 0.75rem);
  color: var(--custom-search-reset-color, #fc4c02);
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: underline;
}

/* Ohne diese Regel steht „Loeschen" dauerhaft ueber dem Platzhalter: Horizons
   `.button-unstyled` setzt `display: block` und sticht damit das
   `hidden`-Attribut aus, das die Komponente zum Verbergen nutzt. Gemessen:
   hidden gesetzt, trotzdem sichtbar, 48px Ueberdeckung des Platzhalters. */
.custom-search-inline__reset[hidden] {
  display: none;
}

/* Ist „Loeschen" sichtbar, braucht der Text rechts Platz — sonst laeuft eine
   lange Eingabe darunter. */
.custom-search-inline__field:has(.custom-search-inline__reset:not([hidden])) .custom-search-inline__input {
  padding-inline-end: 5rem;
}

/* Keine Sonderbehandlung mehr ueber dem transparenten Header: Das Feld ist in
   beiden Zustaenden deckend hell mit dunklem Text. Die frueher halbtransparente
   Fassung liess das Hero-Bild durch — gemessen rgba(255,255,255,0.12), und der
   Nutzer konnte weder Platzhalter noch „Loeschen" lesen. */

/* Die Klappfläche. `position: fixed` und nicht `absolute`: Sie soll über die
   Breite der Seite gehen und nicht in der Spaltenbreite des Feldes kleben — und
   die Kopfleiste ist sticky, ein absolut positioniertes Panel würde beim
   Scrollen mitwandern und dabei aus dem sichtbaren Bereich laufen.
   Die Farben kommen aus der Popover-Palette, damit die Fläche auch über dem
   transparenten Header deckend ist. */
.custom-search-inline__panel {
  display: none;
  position: fixed;
  inset-inline: 0;
  top: var(--header-bottom, 133px);
  z-index: var(--layer-popover, 20);
  max-height: min(70vh, 40rem);
  overflow-y: auto;
  padding: var(--padding-lg) var(--page-margin, 2.5rem);
  border-block-start: 1px solid var(--color-border);
  box-shadow: var(--shadow-popover);
}

/* Farben kommen aus `color-custom-popover` an der Komponente (siehe Snippet),
   nicht von hier — sonst erbt die Fläche die Kopfleistenfarben und über dem
   Hero wird der Text weiß auf weiß. */
.custom-search-inline__panel {
  background-color: var(--color-background);
  color: var(--color-foreground);
}

/* Die Komponente selbst darf KEINEN Grund malen.

   Zwei Regeln geben ihr einen: Horizons eigene `predictive-search-component`
   und die Palettenklasse `.color-custom-popover`, beide mit
   `background-color: var(--color-background)`. Gemessen ergab das eine deckend
   weisse Platte von 299×44px mit `border-radius: 0` — genau in Feldgrösse.

   Das Feld darauf ist mit 8px gerundet, aber die eckige Platte füllt die vier
   Ecken wieder auf. Ergebnis: Die Rundung ist da und sieht trotzdem gerade aus.
   Über dem weissen Kopfleistenrand fällt es nicht auf, über dem transparenten
   Header auf der Startseite steht ein weisses Rechteck im Bild.

   Die Palettenklasse bleibt an der Komponente, denn sie liefert die Variablen
   für die Klappfläche. Nur das Malen wird abgeschaltet; die Fläche setzt ihren
   Grund oben selbst. */
.custom-search-inline {
  background-color: transparent;
  /* Die Mittelspalte der Kopfleiste ist `auto` und richtet sich nach dem
     Inhalt — gemessen blieben davon 224px, zu wenig fuer ein Suchfeld.
     `min-width` und NICHT `width`: `width: min(420px, 100%)` half nicht, weil
     `100%` sich auf genau diese 224px breite Spalte bezieht und damit auf 224px
     zurueckfiel. Eine Mindestbreite laesst die Spalte dagegen wachsen.

     Die Breite ist gestaffelt und nicht per `vw` gerechnet, weil das Raster
     `1fr auto 1fr` ist: Links und rechts sind immer gleich breit, also kostet
     jeder Pixel Mitte zwei Pixel Seitenspalte. Gemessen braucht die linke
     Spalte 364px fuer Logo plus „Bestseller/Angebote"; mit 32vw kollidierte es
     bei 1024px (Spalte 283px, Inhalt bis 404px, Zeile scrollte). Unter 1200px
     bleibt es deshalb bei Horizons Inhaltsbreite. */
}

/* Kein deckender Grund am Feld: Über dem weissen Kopfleistenrand ergibt der
   durchscheinende Ton des Themes ein ruhiges Hellgrau, und über dem Hero greift
   die Regel weiter unten mit der Vordergrundfarbe der transparenten
   Kopfleiste — jetzt tatsächlich Weiss, weil die Palettenklasse nicht mehr an
   der Komponente hängt und `--color-foreground` dort nicht mehr überschreibt. */

/* Untere Ecken gerundet, und zwar genau wie im Theme.

   Horizons eigene Ergebnisfläche macht es in `snippets/search-modal.liquid`
   so: `border-radius: 0 0 var(--search-border-radius) var(--search-border-radius)`,
   ab 750px, mobil 0. Oben bleibt es eckig, weil die Fläche an der Kopfleiste
   klebt — gerundet wären es dort zwei Ecken gegen eine gerade Kante.

   Gemessen war meine Fläche 0px, während `--style-border-radius-popover` im
   Theme 12px trägt und alle Nachbarn dieser Zahl folgen: Produktbilder 12px,
   Kollektionskarte 12px, das Bild darin 8px aus `calc(12px - padding/2)`. Die
   Fläche war der einzige Ausreißer.

   Der Wert kommt direkt aus `--style-border-radius-popover` und nicht aus
   `--search-border-radius`: Letztere ist auf `.search-modal` definiert, und die
   Klasse trägt diese Fläche nicht — die Variable wäre hier leer.

   Mobil bleibt es eckig wie im Theme: Dort füllt die Fläche die Breite bis an
   den Bildschirmrand, gerundete Ecken sähen nach abgeschnitten aus. */
@media screen and (min-width: 750px) {
  .custom-search-inline__panel {
    border-end-start-radius: var(--style-border-radius-popover, 0);
    border-end-end-radius: var(--style-border-radius-popover, 0);
  }
}

/* Unter 1200px muss das Feld schmal bleiben, sonst beschneidet die Mittelspalte
   die linke: Gemessen bei 1024px stand „Angebote" unter dem Suchfeld, weil die
   linke Spalte 364px braucht und nur 283px bekam. Mit 200px Mitte bleiben ihr
   372px. */
@media screen and (max-width: 1199px) {
  /* min-width UND max-width: Bei Konflikt gewinnt in CSS die Mindestbreite.
     Ein max-width allein war hier wirkungslos — das Feld blieb bei gemessenen
     192px, weil die Grundregel 12rem Mindestbreite setzt. */
  .custom-search-inline {
    min-width: 180px;
    max-width: 180px;
  }

  /* Auch der Abstand zwischen Logo und Zweitmenue gibt hier nach — 20px sind
     im schmalen Band Luxus. */
  .custom-header-secondary {
    margin-inline-start: var(--gap-sm, 0.75rem);
  }

  /* Versalien machen „BESTSELLER ANGEBOTE" rund 51px breiter als gemischte
     Schreibweise — gemessen 213px statt 147px. Bei 1024px reichte das, um
     wieder in die Mittelspalte zu laufen (Linkende 454, Spaltenbeginn 407).
     Das Raster ist `1fr auto 1fr`, jeder Pixel Mitte kostet zwei Pixel
     Seitenspalte, also muss hier die Schrift nachgeben statt das Feld.
     13px Versalien lesen sich noch klar und passen mit Luft. */
  .custom-header-secondary__link {
    font-size: 0.8125rem;
    letter-spacing: 0.03em;
  }
}

/* Zwischenstufe. Bei genau 1200px lag die Grenze falsch: Das Feld sprang auf
   360px, waehrend die Versalien schon wieder 16px gross waren — gemessen 40px
   Ueberlappung. Das Raster ist `1fr auto 1fr`, die linke Spalte bekommt also
   nur die Haelfte dessen, was die Mitte uebrig laesst, braucht aber Logo (161)
   + Abstand + Versalien (213) = 394px. Bei 1200px reicht das erst mit einer
   Mitte um 260px. */
@media screen and (min-width: 1200px) {
  .custom-search-inline {
    min-width: 260px;
  }
}

@media screen and (min-width: 1320px) {
  .custom-search-inline {
    min-width: 360px;
  }
}

@media screen and (min-width: 1440px) {
  .custom-search-inline {
    min-width: 420px;
  }
}

/* Sichtbar erst, wenn wirklich getippt wurde: `:focus-within` allein reichte
   nicht. Gemessen bei frischem Seitenaufruf: `document.activeElement` war das
   Suchfeld, die Klappfläche also sofort offen. `:placeholder-shown` ist genau so
   lange wahr, wie das Feld leer ist — die Fläche öffnet damit beim ersten
   Zeichen und schließt, wenn man den Text wieder löscht. Das entspricht auch der
   Vorlage, die erst bei Eingabe aufklappt. */
.custom-search-inline:focus-within:has(.custom-search-inline__input:not(:placeholder-shown))
  .custom-search-inline__panel {
  display: block;
}

.custom-search-inline__footer {
  display: flex;
  justify-content: center;
  margin-block-start: var(--margin-md);
}

/* Auf Mobilgeräten übernimmt das Symbol in der Schublade; ein Feld würde dort
   dem Logo die Zeile nehmen. */
@media screen and (max-width: 749px) {
  .custom-search-inline {
    display: none;
  }
}}

/* Kartengröße in der Klappfläche.

   Horizons Ergebnisliste ist ein Raster, dessen Spaltenbreite sich aus dem
   Container ergibt. Im Modal ist der 66 % des Fensters breit, in einer Leiste
   über die volle Seitenbreite werden daraus vier Karten à 313px und Bilder mit
   391px Höhe — die Klappfläche verdeckt dann die halbe Seite. Gemessen genau so,
   bevor die folgenden zwei Regeln dazukamen.

   Deshalb: mehr, kleinere Spalten und eine Deckelung der Bildhöhe. `contain`
   statt `cover`, weil die Produktfotos freigestellt sind und beim Beschneiden
   Werkzeugspitzen verlieren würden. */
.custom-search-inline__panel .predictive-search-results__list {
  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
  gap: var(--gap-md, 1rem);
}

.custom-search-inline__panel .predictive-search-results__list img {
  max-height: 8rem;
  object-fit: contain;
}

/* Inhalt mittig begrenzen: Eine Zeile mit 1300px Lauflänge liest niemand, und
   die Suchvorschläge stehen sonst am linken Rand allein. */
.custom-search-inline__panel .predictive-search-dropdown {
  max-width: var(--normal-content-width, 1400px);
  margin-inline: auto;
}

/* Zwei Spalten in der Klappfläche: links Suchvorschläge und Kollektionen,
   rechts die Produkte — wie in der Vorlage.

   Umgesetzt über explizite Rasterplatzierung und nicht über `order`: Die
   Reihenfolge im Markup ist Produkte → Kollektionen, und die soll so bleiben.
   Ein Screenreader liest damit weiter zuerst die Treffer, die der Nutzer
   gesucht hat, während das Auge links die Einstiege findet.

   Zwei Dinge, die beim ersten Versuch schiefgingen und die Regeln unten erklären:

   1. **Die linke Spalte darf nicht leer reserviert werden.** Ohne Kollektionen
      und ohne Suchvorschläge stand links eine 15rem breite Leerfläche und die
      Produkte drängten sich rechts. Deshalb hängt das Raster an `:has()` — es
      greift nur, wenn es für die linke Spalte auch Inhalt gibt.

   2. **Die Breite muss erzwungen werden.** `.predictive-search-results__inner`
      ist Flex-Kind von `.predictive-search-dropdown`, bekommt seine Breite also
      vom Inhalt. Mit `1fr` in der zweiten Spalte fiel das auf Inhaltsbreite
      zusammen: gemessen 412px statt 1334px, vier Karten à 90px. */
/* Horizon deckelt die Ergebnisfläche auf 672px — sinnvoll in einem Modal, das
   66 % des Fensters einnimmt, zu schmal für eine Leiste über die Seitenbreite.
   Gemessen: `max-width: 672px` plus `margin: 338px auto`, dadurch zwei Spalten
   à 240px und 412px statt der verfügbaren 1349px.

   Der Selektor trägt die ID der Kopfleiste, weil die Vendor-Regel mit gleicher
   Klassen-Spezifität später eingebunden wird — ohne die ID gewinnt sie. Kein
   `!important`, das verbietet die Projektregel. */
#header-component .custom-search-inline__panel .predictive-search-dropdown,
#header-component .custom-search-inline__panel .predictive-search-results__inner {
  width: 100%;
  max-width: none;
  margin-inline: 0;
}

@media screen and (min-width: 990px) {
  .custom-search-inline__panel
    .predictive-search-results__inner:has(
      .predictive-search-results__collections,
      .predictive-search-results__wrapper-queries
    ) {
    display: grid;
    grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr);
    gap: var(--gap-xl);
    align-items: start;

    .predictive-search-results__wrapper-queries {
      grid-column: 1;
      grid-row: 1;
      flex-direction: column;
      align-items: start;
    }

    .predictive-search-results__collections {
      grid-column: 1;
      grid-row: 2;
    }

    /* Produkte über beide Zeilen der linken Spalte hinweg */
    .predictive-search-results__products {
      grid-column: 2;
      grid-row: 1 / span 2;
    }

    /* In der linken Spalte ist kein Platz für vier Karten nebeneinander —
       Kollektionen stehen dort untereinander. */
    .predictive-search-results__collections .predictive-search-results__list {
      grid-template-columns: minmax(0, 1fr);
    }
  }
}

/* Suche und Mega-Menü schließen sich aus.

   Im Screenshot lagen beide Flächen übereinander: die Ergebnisse der Suche und
   die Spalten des gehoverten Menüs im selben Band. An der Stapelung liegt es
   nicht — gemessen Panel z-index 20, Submenü 12, beide im selben Stapelkontext
   der Kopfleiste. Zwei gleichzeitig offene Überlagerungen sind aber ohnehin ein
   Bedienfehler, egal welche oben liegt: Der Nutzer hat eine Absicht, nicht zwei.

   Also Vorrang für die Suche, solange sie offen ist. Die Bedingung ist
   absichtlich dieselbe wie für die Klappfläche selbst (Fokus im Feld UND Text
   darin) — sonst bliebe das Menü auch dann gesperrt, wenn nur noch ein alter
   Suchbegriff im Feld steht. */
#header-component:has(
    .custom-search-inline:focus-within .custom-search-inline__input:not(:placeholder-shown)
  )
  .menu-list__submenu {
  display: none;
}

/* Und die Klappfläche über alles andere in der Kopfleiste legen, damit auch ein
   verzögert schließendes Menü nicht durchscheint. */
#header-component .custom-search-inline__panel {
  z-index: 30;
}

/* Kollektionskarte füllt die linke Spalte. Der Karussell-Baustein bemisst seine
   Folien über `--slide-width`; ohne Vorgabe blieb die Karte bei rund 80px in
   einer 240px breiten Spalte stehen. */
#header-component .custom-search-inline__panel .predictive-search-results__collections {
  --slide-width: 100%;
}

#header-component
  .custom-search-inline__panel
  .predictive-search-results__collections
  .predictive-search-results__card {
  width: 100%;
  max-width: none;
}

/* Kollektionen in der linken Spalte stapeln, nicht schieben.

   Ursache im Quellcode: `<slideshow-slides>` ist ein horizontaler Flex-Scroller
   (`display: flex; overflow-x: scroll; scroll-snap-type: x mandatory`), und
   `<slideshow-slide>` trägt `flex-shrink: 0`. In einer 240px breiten Spalte
   laufen die Karten damit nach rechts aus dem Bild — genau das war zu sehen.

   `content-visibility: visible` ist kein Zierrat: Horizon setzt an den Folien
   `content-visibility: auto`, damit ein Karussell nur den sichtbaren Ausschnitt
   rendert. In einer gestapelten Spalte hätten die unteren Karten damit keine
   gemessene Höhe. */
#header-component .custom-search-inline__panel .predictive-search-results__collections slideshow-slides {
  flex-direction: column;
  overflow: visible;
  scroll-snap-type: none;
  gap: var(--gap-sm, 0.75rem);
}

#header-component .custom-search-inline__panel .predictive-search-results__collections slideshow-slide {
  width: 100%;
  scroll-snap-align: none;
  content-visibility: visible;
}

/* Die Pfeile steuern horizontales Blättern und haben in einer Spalte keine
   Aufgabe mehr. */
#header-component .custom-search-inline__panel .predictive-search-results__collections .slideshow-controls,
#header-component .custom-search-inline__panel .predictive-search-results__collections slideshow-arrows {
  display: none;
}

/* Karten im Gewerke-Abschnitt. Bewusst schlicht: Sie sind ein Einstieg, der zur
   Produktseite führt, keine Kaufoberfläche. Warum nicht Horizons Produktkarte,
   steht im doc-Block von blocks/_custom-audience-tab.liquid. */
/* Angleichung an die Standard-Produktkarte (Vereinheitlichung 2026-08-28):
   gleicher Rahmen, gleiche Radien, Innenabstand fuer den Textbereich —
   vorher schwebten die Gewerke-Karten rahmenlos und sahen als einzige
   Produktkarten anders aus als Collection/Startseite. */
.custom-audience__item {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs, 0.5rem);
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--color-border, #e5e7eb);
  border-radius: 12px;
  background: var(--color-background, #fff);
  overflow: hidden;
  padding-block-end: var(--padding-md, 1rem);
}

.custom-audience__item > :not(.custom-audience__media) {
  margin-inline: var(--padding-md, 1rem);
}

.custom-audience__media {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  /* Weiss wie die Standard-Kartengalerie — der graue Grund liess die
     Gewerke-Karten als einzige getoent wirken. */
  background-color: var(--color-background, #fff);
}

/* Titel traegt den Link und streckt ihn ueber die ganze Karte (das div hat
   position: relative). Schnellkauf und Badges liegen per z-index darueber. */
.custom-audience__item {
  position: relative;
}

.custom-audience__title {
  text-decoration: none;
  color: inherit;
}

.custom-audience__title::after {
  content: '';
  position: absolute;
  inset: 0;
}

/* Die Positions-Variablen der Standard-Kartengalerie existieren im
   Gewerke-Kontext nicht (gemessen: Badge stand bei bottom −22.8px unter dem
   Bild, vom overflow abgeschnitten; der Schnellkauf lag 162px gross im
   Fluss). Deshalb hier explizit in die Bildecken gesetzt. */
/* Der .quick-add-Wrapper bleibt beim Original (absolute, inset: 0) — nur die
   Variablen seiner inset-Formel fehlen ausserhalb der product-card und werden
   hier gesetzt, sonst rechnet max()/calc() mit undefinierten Werten. */
.custom-audience__media .quick-add {
  --quick-add-offset: var(--padding-sm, 12px);
  --padding-inline-end: 0px;
  --padding-block-end: 0px;
  --border-radius: 0px;
  z-index: 2;
}

/* Desktop-Einblendung wie product-card:hover, nur mit unserem Karten-Element */
@media screen and (min-width: 750px) {
  .custom-audience__item:is(:hover, :focus-within) .quick-add__button {
    opacity: 1;
  }
}

.custom-audience__media .product-badges {
  inset-block-end: var(--padding-xs, 8px);
  inset-block-start: auto;
  inset-inline-start: var(--padding-xs, 8px);
  z-index: 2;
}

.custom-audience__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.custom-audience__badge {
  position: absolute;
  inset-block-start: var(--padding-xs);
  inset-inline-start: var(--padding-xs);
  padding: 0.2em 0.6em;
  border-radius: var(--badge-border-radius, 8px);
  background-color: var(--custom-color-sale, #fc4c02);
  color: #fff;
  font-size: var(--font-size--xs, 0.75rem);
  font-weight: 500;
}

.custom-audience__title {
  font-size: var(--font-size--md, 1rem);
  line-height: 1.35;
}

.custom-audience__item:hover .custom-audience__title {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

/* Bewertung auf der Gewerke-Karte: Sterne plus Anzahl, klein. Reihenfolge
   Titel → Bewertung → Preis, weil die Bewertung die Entscheidung stützt und der
   Preis sie abschließt. */
.custom-audience__rating {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
  font-size: var(--font-size--sm, 0.875rem);
}

/* Dunkle Sterne wie der review-Block der Standardkarte — die orangen Sterne
   des Bewertungs-Abschnitts bleiben dort unberuehrt (der Override gilt nur
   auf den Gewerke-Karten). */
.custom-audience__rating .custom-stars__row--full .custom-stars__icon {
  fill: var(--custom-color-dark, #253746);
}

.custom-audience__rating-count {
  opacity: 0.7;
}

/* ==========================================================================
   18. Hinweis auf einen korrigierten Suchbegriff
   ==========================================================================

   Läuft eine Eingabe leer, prüft `assets/custom.search-typo.js` Kandidaten
   gegen die Suche und zeigt die Ergebnisse des ersten Begriffs, der wirklich
   Treffer liefert. Diese Zeile sagt, dass das passiert ist.

   Sie steht über der Ergebnisfläche und außerhalb davon, weil die Fläche bei
   jedem Tastendruck neu gemorpht wird. */
.custom-search-inline__typo-slot[hidden] {
  display: none;
}

.custom-search-inline__typo {
  margin: 0 0 var(--gap-md);
  padding-block-end: var(--gap-sm);
  border-block-end: 1px solid var(--color-border);
  font-size: var(--font-size--sm, 0.875rem);
  line-height: 1.4;
}

/* Die getippte Fassung tritt zurück, der geprüfte Begriff steht vorn — er ist
   das, was die Ergebnisse darunter erklärt. */
.custom-search-inline__typo-original {
  color: var(--color-foreground-subdued, currentcolor);
}

.custom-search-inline__typo strong {
  font-weight: 500;
}

/* Derselbe Hinweis auf der Ergebnisseite. Dort trägt er einen Link statt
   nachgeladener Karten: Die Adresse bleibt teilbar, und der Kunde entscheidet,
   ob er dem Vorschlag folgt. */
.custom-search-typo-page-slot[hidden] {
  display: none;
}

.custom-search-typo-page {
  margin-block: var(--gap-sm) 0;
  font-size: var(--font-size--md, 1rem);
}

.custom-search-typo-page a {
  color: inherit;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

/* ==========================================================================
   19. Silbentrennung in Produktkarten
   ==========================================================================

   Deutsche Komposita sind länger als jede Kartenspalte. Gemessen bei 375px in
   der Collection `innensechskantschlussel`: das Wort „Innensechskantschlüssel"
   ist 184px breit, die Kartenspalte 166px. Horizon bricht dann irgendwo — auf
   dem Bildschirm stand „Innensechskantschlüs / sel Set HX 13tlg.".

   `hyphens: auto` trennt stattdessen nach Sprachregeln („Innensechskant-
   schlüssel"). Es greift nur, wenn ein Wort ohnehin nicht in die Zeile passt,
   Preise und kurze Titel bleiben also unberührt. Die Sprachangabe steht im
   `<html lang="de">` — ohne sie täte die Regel nichts.

   Angesetzt an der Karte und nicht global: Im Fließtext soll Trennung eine
   Entscheidung bleiben, hier verhindert sie einen sichtbaren Fehler. */
.product-grid__item {
  hyphens: auto;
}

/* ==========================================================================
   20. Trefferfläche der Slideshow-Punkte
   ==========================================================================

   Horizons Folienpunkte sind 18px-Schaltflächen im 19px-Raster — unter den
   24px, die WCAG 2.5.8 verlangt, und die Abstandsausnahme greift bei 19px
   Mittenabstand auch nicht. Der sichtbare Punkt ist ein festes 9px-::after,
   die Schaltfläche lässt sich also vergrößern, ohne dass sich optisch etwas
   ändert — nur die Reihe wird ein paar Pixel breiter. */
.slideshow-control.button-unstyled {
  min-width: 24px;
  min-height: 24px;
}

/* ====== 21. „Passt dazu" in der Warenkorb-Schublade ====== */
.custom-cart-upsell {
  display: block;
  margin: var(--gap-md, 0.75rem) 0 0;
  padding: var(--padding-md, 0.75rem);
  border-radius: 12px;
  background-color: rgb(var(--color-foreground-rgb, 37 55 70) / 0.04);
}
.custom-cart-upsell__titel { margin: 0 0 var(--gap-xs, 0.5rem); font-weight: 600; font-size: var(--font-size--sm, 0.875rem); }
.custom-cart-upsell__karte { display: flex; align-items: center; gap: var(--gap-sm, 0.75rem); padding-block: var(--gap-2xs, 0.25rem); }
/* width/height explizit, nicht nur flex-basis: Die Schublade setzt auf ihre
   Bilder width:100%, das ueberstimmt Flex-Basis UND HTML-Attribute — gemessen
   stand der Vorschlag mit 348x348px in der Karte. */
.custom-cart-upsell__karte img {
  flex: 0 0 48px;
  width: 48px;
  height: 48px;
  border-radius: 8px;
  object-fit: contain;
  background: var(--color-background);
}
.custom-cart-upsell__name { flex: 1; min-width: 0; font-size: var(--font-size--sm, 0.875rem); color: inherit; text-decoration: none; }
.custom-cart-upsell__name:hover { text-decoration: underline; }
.custom-cart-upsell__preis { font-size: var(--font-size--sm, 0.875rem); font-variant-numeric: tabular-nums; white-space: nowrap; }
.custom-cart-upsell__plus { display: grid; place-items: center; width: 32px; height: 32px; flex: 0 0 auto;
  border: 1px solid rgb(var(--color-foreground-rgb, 37 55 70) / 0.3); border-radius: 50%;
  background: none; color: inherit; cursor: pointer; }
.custom-cart-upsell__plus svg { width: 14px; height: 14px; }
.custom-cart-upsell__plus:disabled { opacity: 0.4; }

/* ====== 22. Abstand zwischen gestapelten Karten-Badges ======
   „Bestseller" und „Du sparst" klebten aneinander und lasen sich als ein
   verbundener Block.

   Abstand als margin, NICHT als gap: Der Container ist display: block, und
   dort ist gap wirkungslos — gemessen stand computedGap auf 12px bei einer
   echten Luecke von 0px. Der Selektor trifft jedes Badge, das auf ein anderes
   folgt, egal wie viele gestapelt sind (Bestseller, Du sparst, 4 Stk.).
   Die Farbe des Aktions-Badges kommt aus den Theme-Einstellungen
   (badge_sale_*, Orange). */
.product-badges > * + * {
  margin-block-start: 12px;
}

/* ====== 23. Ersparnis als runder Punkt oben rechts auf der Karte ======
   Ersetzt die Textzeile „Du sparst X%" im Badge-Stapel — drei gestapelte
   Rechtecke lasen sich als Textblock auf dem Foto. Fester Durchmesser statt
   Padding, damit −5% und −36% denselben Kreis ergeben. */
.custom-sale-dot {
  position: absolute;
  top: var(--padding-sm, 0.75rem);
  inset-inline-end: var(--padding-sm, 0.75rem);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background-color: var(--color-primary-button-background, #fc4c02);
  color: var(--color-primary-button-text, #ffffff);
  font-size: 0.8125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* ====== 24. Prio-Schalter in der Schublade ====== */
/* Sitzt in der Summe zwischen Rabatt und Gesamtbetrag. Getoente Flaeche statt
   Umrandung: Rabatt und Summe darum sind randlose Zeilen, eine Randbox mitten
   drin las sich wie ein Fremdkoerper. */
.custom-cart-prio { display: flex; align-items: center; gap: var(--gap-sm, .75rem);
  margin-block: var(--gap-xs, .5rem); padding: var(--padding-md, .75rem);
  border-radius: 10px; background: rgb(var(--color-foreground-rgb, 37 55 70) / .05);
  cursor: pointer; }
.custom-cart-prio__text { flex: 1; min-width: 0; }
.custom-cart-prio__name { display: block; font-weight: 600; font-size: var(--font-size--sm, .875rem); }
.custom-cart-prio__satz { display: block; font-size: var(--font-size--xs, .75rem);
  color: rgb(var(--color-foreground-rgb, 37 55 70) / .72); }
.custom-cart-prio__input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.custom-cart-prio__schalter { flex: 0 0 auto; width: 42px; height: 24px; border-radius: 999px;
  background: rgb(var(--color-foreground-rgb, 37 55 70) / .25); position: relative;
  transition: background-color 160ms cubic-bezier(.23,1,.32,1); }
.custom-cart-prio__schalter::after { content: ''; position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%; background: #fff;
  transition: translate 160ms cubic-bezier(.23,1,.32,1); }
.custom-cart-prio__input:checked + .custom-cart-prio__schalter { background: var(--color-primary-button-background, #fc4c02); }
.custom-cart-prio__input:checked + .custom-cart-prio__schalter::after { translate: 18px 0; }
.custom-cart-prio__input:focus-visible + .custom-cart-prio__schalter { outline: 2px solid var(--color-foreground); outline-offset: 2px; }

/* ==========================================================================
   25. Hero-Typografie: Malva im Black-Schnitt, in Signage-Größe
   ==========================================================================

   Malva (Harbor Type) liegt seit Langem selbst gehostet im Theme, inklusive
   Black-Schnitt (custom.malva-black.woff2, Gewicht 900 ist oben deklariert).
   Benutzt wurde er im Hero nie: gemessen bei 1280px stand die Zeile mit 32px,
   Gewicht 400, Zeilenhöhe 1,4 und normaler Laufweite — also im leichtesten
   Schnitt und einem Drittel der Größe, die eine Signage-Schrift verlangt.

   Zum Vergleich die Cloud-Design-Vorlage derselben Marke: clamp(56px, 8vw,
   96px), Gewicht 900, Zeilenhöhe 1,0, Laufweite −0,02em. Dieselbe Schrift,
   nur mit Überzeugung eingesetzt — daher der bessere Eindruck.

   Warum hier und nicht in den Block-Einstellungen: Der Text-Block bietet für
   `font_size` nur eine Auswahlliste bis 1.5rem und für das Gewicht überhaupt
   keine Einstellung. Zeilenhöhe und Laufweite ließen sich dort setzen, stehen
   aber bewusst mit hier, damit die vier Werte, die zusammen wirken, an einer
   Stelle stehen.

   `hyphens: auto`: Bei 40px auf 375px Breite passt „Handwerkerhelden." nicht
   in eine Zeile. Dieselbe Sprachtrennung wie bei den Kartentiteln.

   Groß-/Kleinschreibung bleibt unangetastet — Versalien tragen im Hero, aber
   die Entscheidung gehört der Marke, nicht dem Stylesheet. Umschaltbar bleibt
   sie im Editor über die Einstellung „Schreibweise" des Text-Blocks. */
.hero :is(h1, h2) {
  /* Minimum 2rem (32px): 2.5rem waren bei 375px zu wuchtig — die Zeile nahm
     drei Zeilen und die halbe Bildhoehe.

     Obergrenze von 5.5rem auf 4.25rem (88 -> 68px), auf Wunsch des Nutzers:
     Gemessen bei 1440x900 stand die Ueberschrift auf zwei Zeilen mit 176px
     Hoehe, das ist ein Viertel des ganzen Heros (678px). Der Abschnitt selbst
     ist nicht zu hoch — es war die Schriftmasse. Mit 68px sind es 136px, und
     das Verhaeltnis zur Unterzeile (16px) bleibt klar.

     Der vw-Anteil sinkt mit, damit die Kurve dazwischen stimmt: 7vw haetten
     bei 1024px 72px ergeben und damit fast den neuen Hoechstwert. Mit 5.5vw
     sind es dort 56px. Mobil aendert sich nichts, dort greift weiter das
     Minimum von 32px. */
  font-size: clamp(2rem, 5.5vw, 4.25rem);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.02em;
  hyphens: auto;
}

/* ==========================================================================
   26. Hero: Textspalte links, Schleier passend zur Textbreite
   ==========================================================================

   Ausgangslage gemessen: Der Overlay stand auf 60% Navy, gleichmaessig ueber
   das ganze Bild. Weisse Schrift erreichte damit an den hellsten Stellen des
   Motivs nur 3,72:1 — unter den geforderten 4,5:1. Die Wahrnehmung „kann man
   nicht lesen" war also messbar, nicht Geschmack.

   Loesung wie in der Cloud-Design-Vorlage: gerichteter Schleier von links,
   linksbuendiger Text. Zwei Dinge muessen dafuer zusammenkommen:

   1. Die Textspalte muss BEGRENZT sein. Ohne Begrenzung lief die Ueberschrift
      bei 1440px ueber 1349px Breite, also bis in den ausgelaufenen Teil des
      Verlaufs. 46rem halten sie in der dunklen Haelfte, rechts bleibt das
      Produkt sichtbar.

   2. Mobil braucht es einen anderen Schleier. Gemessen bei 375px lief der Text
      von 16 bis 359 von 375 Pixeln — es gibt dort keine rechte Haelfte, die
      man freilassen koennte, und der Kontrast fiel am Zeilenende auf 1,59.
      Deshalb unter 750px ein deckender Schleier statt des Verlaufs; 0,85
      Navy haelt selbst gegen die hellsten Bildstellen rund 4,9:1. */
@media screen and (min-width: 750px) {
  /* 52rem statt 46rem: „Handwerkerhelden." braucht bei 88px rund 830px. In
     46rem (736px) trennte die Ueberschrift als „Handwer-/kerhelden." — in
     einer Hero-Zeile ein unschoener Bruch. Der Schleier haelt dafuer bis 62%
     statt 55%; rechts bleiben noch ueber ein Drittel Bildbreite fuer das
     Produkt. */
  .hero__content-wrapper {
    max-width: 52rem;
  }

  /* Der Verlauf haelt seine Deckung ueber die Textzone und laeuft erst danach
     aus. Horizons Overlay-Snippet kann nur zwei Stufen (Farbe -> Alpha 0), und
     das reichte nicht: Bei 1440px endet die Ueberschrift bei 51% der Breite,
     dort war die Deckung auf 0,44 abgefallen und der Kontrast auf 2,39:1.
     Mit Halt bis 55% liegt der ganze Text bei voller Deckung.

     Farbe und Richtung kommen weiter aus den Section-Einstellungen: Der
     Snippet setzt --overlay-color und --overlay-color--end, hier werden nur
     die Haltepunkte vorgegeben. */
  .hero .overlay--gradient {
    background: linear-gradient(
      var(--overlay-direction),
      var(--overlay-color) 0%,
      var(--overlay-color) 62%,
      var(--overlay-color--end) 88%
    );
  }
}

@media screen and (max-width: 749px) {
  /* 0,85 und nicht 0,70. Die Absenkung auf 0,70 liess mehr vom Motiv durch,
     traf aber den orangen Dreiklang: gemessen 1,43:1, weil Orange und ein nur
     halb abgedunkeltes Foto mit orangefarbenen Produkten fast dieselbe
     Helligkeit haben. Mit 0,85 sind es rund 2,0:1 — noch keine 3, aber das ist
     die Grenze der Farbe selbst, nicht des Schleiers: Orange erreicht die 3:1
     erst auf nahezu deckendem Grund (Desktop: 3,60 bei 0,9). Weisse Schrift
     liegt hier unabhaengig davon bei 7,7:1. */
  .hero .overlay--gradient {
    background: rgb(37 55 70 / 0.9);
  }

  /* Der Dreiklang lief auf 375px ueber ZWEI Zeilen: gemessen 354px Textbreite
     auf 343px Platz, Block also 56px hoch — fast so viel wie die Ueberschrift
     selbst (64px). Als Markenton neben der Ueberschrift ist das zu laut.

     15px passt einzeilig (gemessen 276px). Damit verlaesst die Zeile aber die
     WCAG-Ausnahme fuer grossen Text (ab 18,67px fett genuegen 3:1) und braucht
     4,5:1. Gegen die hellste Stelle unter der Zeile, mit dem Schleier
     komponiert, gemessen:
       Schleier 0,85   #ff8f4d 3,40   #ffa46b 3,95   #ffbf99 4,82
       Schleier 0,90   #ff8f4d 3,98   #ffa46b 4,62
       Schleier 0,94   #ff8f4d 4,51
     Gewaehlt: Schleier 0,90 mit #ffa46b (4,62). Der Schleier entspricht damit
     dem Desktop, und der Ton bleibt Orange statt Lachs — #ffbf99 haette bei
     0,85 auch gereicht, liest aber nicht mehr als PRESCH-Orange. */
  :root {
    --presch-orange-auf-bild: #ffa46b;
  }

}

/* ==========================================================================
   27. Hero-Akzente, mobile Zentrierung, Menü in Versalien
   ==========================================================================

   Auf Wunsch des Nutzers.

   Das Akzentwort haengt an `<strong>` und nicht an einem `<span>`: Der
   Rich-Text-Editor der Text-Bloecke filtert unbekannte Tags heraus, `strong`
   bleibt stehen. Das Gewicht wird zurueckgesetzt, weil die Ueberschrift schon
   im Black-Schnitt laeuft — `strong` soll hier nur faerben. */
.hero :is(h1, h2) strong {
  color: var(--presch-orange, #fc4c02);
  font-weight: inherit;
}

/* Der Dreiklang steht als erste Zeile ueber der Ueberschrift, in Orange und
   gesperrt — er ist Markenton, nicht Information.

   1.25rem und nicht die 0.875rem des Blocks: Orange auf dem dunklen Schleier
   erreicht gemessen 3,60:1. Fuer kleinen Text sind 4,5:1 gefordert, fuer
   grossen (ab 18,67px fett) nur 3:1 — mit 20px fett liegt die Zeile also im
   gruenen Bereich, ohne dass die Markenfarbe verwaessert werden muss. */
.hero .text-block:first-child p {
  color: var(--presch-orange-auf-bild, #ff8f4d);
  /* Naeher an die Ueberschrift: Der Abstand kam aus dem `gap` der Hero-Spalte
     und liess die Zeile allein stehen. Ein negativer Ausgleich haelt sie am
     Wort „Werkzeug", ohne die Abstaende der uebrigen Bloecke anzutasten. */
  margin-block-end: -2.75rem;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Hauptmenue in Versalien: Die Labels sind kurz („Zubehör", „Feilen & Formen"),
   da hilft der ruhigere Umriss von Versalien der Lesbarkeit — im Gegensatz zu
   langen Komposita in Ueberschriften. Etwas Sperrung dazu, weil Versalien ohne
   Laufweite zusammenkleben. */
#header-component .header__row--bottom .menu-list__link-title {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 500;
}

/* Abschnittstitel im Black-Schnitt und zentriert — dieselbe Stimme wie der
   Hero. Zentriert auf ALLEN Breiten, nicht nur mobil: Die Startseite ist eine
   Folge mittiger Baender, ein linksbuendiger Titel darueber liest sich wie ein
   Ausrutscher.

   Die Collection-Seiten sind bewusst NICHT dabei: Dort steht der Titel neben
   der Kachel im Kopf und die Einleitung ist ein Lesetext — zentrierte
   Ueberschriften ueber linksbuendigem Fliesstext waeren dort falsch. */
.custom-category-grid__heading,
.custom-audience__heading,
.custom-benefits__heading,
.custom-awards-band__heading,
.custom-reviews__heading,
.prx__ueberschrift,
.section-resource-list__header .text-block :is(h2, h3) {
  font-weight: 900;
  text-align: center;
}

/* Der Kopf der Produktliste ist eine Flex-Spalte; ohne diese Zeile sitzt die
   Ueberschrift trotz `text-align` links, weil die Box nur inhaltsbreit ist. */
.section-resource-list__header {
  justify-content: center;
  text-align: center;
}

@media screen and (max-width: 749px) {
  /* Mobil alles im Hero zentriert: Der Schleier ist dort deckend, es gibt also
     keine dunkle Seite, an der sich linksbuendiger Text ausrichten muesste. */
  .hero__content-wrapper {
    align-items: center;
    text-align: center;
  }

  /* Die Ausrichtung muss auf der Ueberschriftenebene gesetzt werden: Der Block
     rechnet zwar `text-align: center`, aber eine Theme-Regel setzt sie auf dem
     h1 selbst wieder auf `left` — gemessen Block center, h1 left. */
  .hero .text-block,
  .hero .text-block :is(h1, h2, h3, p) {
    text-align: center;
  }

  /* Auf Collection-Seiten mobil ebenfalls zentriert — dort ist der Titel die
     einzige Zeile im Band. */
  .custom-collection-benefits__heading,
  .custom-collection-faq__heading,
  .custom-collection-media__heading {
    text-align: center;
  }
}

/* Die orange Unterkante der Kopfleiste ist wieder raus — auf Wunsch des
   Nutzers, sie stoerte. Sie war einmal ausdruecklich gewuenscht („die untere
   Linie auch das Orange vom Menue"), stand aber als 2px-Balken quer ueber jede
   Seite. Ohne sie schliesst der Header mit der dezenten 1px-Linie zwischen den
   beiden Kopfzeilen ab, die Horizon selbst setzt (gemessen #d6dde3).

   Falls die Kante wieder gewuenscht wird: eine Regel auf
   `#header-component .header__row--bottom` mit `border-block-end`, das war der
   Ort. */

/* Kurzbeschreibung im Collection-Band: 15px statt 14px und etwas mehr
   Zeilenabstand. Auf dem Foto liest sich kleiner Text schwerer als auf Weiss,
   auch bei ausreichendem Kontrast — gemessen 7,32:1 mobil, die Zahl war also
   nie das Problem, die Groesse schon. */
.custom-collection-hero--band .custom-collection-hero__kurz {
  font-size: 0.9375rem;
  line-height: 1.6;
}

/* ==========================================================================
   28. Produktkarten nach der Cloud-Design-Vorlage
   ==========================================================================

   Vorlage (Kollektionsseite im Design-System): weisse Karte mit 1px-Rand,
   8px Radius und flachem Schatten; quadratisches Bild; Titel 15px/700;
   Preis 24px/900 in Signalorange; Streichpreis 13px durchgestrichen daneben;
   Bewertung als Sternzeile darueber.

   Uebernommen wird die Anmutung, nicht das Markup — unsere Karten sind
   Horizon-Bloecke. Bildformat und Preisgroesse stehen deshalb in den
   Template-Einstellungen (square, 1.5rem), Flaeche und Farben hier.

   Der Preis ist der einzige orange Text auf weissem Grund: #FC4C02 auf Weiss
   liegt bei rund 3,4:1 — fuer 24px fett gilt die Schwelle 3:1, das haelt.
   Bei kleinerem Preistext waere Orange nicht zulaessig. */
.product-grid__item .product-card,
.product-grid__item > .card-gallery,
.resource-list__item .product-card {
  background-color: var(--color-background);
  border: 1px solid rgb(var(--color-foreground-rgb) / 0.12);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 0 rgb(var(--color-foreground-rgb) / 0.06);
  transition:
    transform 200ms var(--custom-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),
    box-shadow 200ms var(--custom-ease-out, cubic-bezier(0.23, 1, 0.32, 1));
}

/* Innenabstand fuer alles unter dem Bild — in der Vorlage 16/18/20. Das Bild
   selbst bleibt randlos, es sitzt in der Kartenkante. */
.product-grid__item .product-card > *:not(.card-gallery):not([class*='gallery']),
.resource-list__item .product-card > *:not(.card-gallery):not([class*='gallery']) {
  padding-inline: 14px;
}

.product-grid__item .product-card > *:last-child,
.resource-list__item .product-card > *:last-child {
  padding-block-end: 16px;
}

@media (hover: hover) and (pointer: fine) {
  .product-grid__item .product-card:hover,
  .resource-list__item .product-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgb(var(--color-foreground-rgb) / 0.1);
  }
}

/* Preis in Signalorange und im Black-Schnitt — die Zahl ist auf der Karte die
   Entscheidung, nicht eine Angabe unter vielen. */
.product-grid__item .price,
.resource-list__item .price {
  color: var(--presch-orange, #fc4c02);
  font-weight: 900;
  letter-spacing: -0.01em;
}

/* Streichpreis bleibt klein und gedeckt: Er ist die Bezugsgroesse. Selektor
   mit `[ref=priceContainer]`, weil die aeltere Aktionspreis-Regel aus
   Abschnitt 15 sonst gewinnt — gemessen blieb der Streichpreis bei 16px. */
.product-grid__item [ref='priceContainer'] .compare-at-price,
.resource-list__item [ref='priceContainer'] .compare-at-price,
.product-grid__item .compare-at-price,
.resource-list__item .compare-at-price {
  color: rgb(var(--color-foreground-rgb) / 0.6);
  font-size: 0.8125rem;
  font-weight: 400;
}

/* ==========================================================================
   29. Mega-Menue: Bilder quadratisch
   ==========================================================================
   Horizon setzt `aspect-ratio: 16 / 9` fest in blocks/_header-menu.liquid —
   an zwei Stellen, am Bild und am Platzhalter fuer Links ohne Bild. Die
   PRESCH-Kategoriebilder sind quadratische Icon-Kacheln; in 16:9 werden sie
   beschnitten, man sieht das Werkzeug nicht mehr vollstaendig.

   Ueberschrieben statt im Vendor-Block geaendert, damit ein Theme-Update die
   Anpassung nicht mitnimmt. */
#header-component .mega-menu__link-image,
#header-component .mega-menu__grid:has(.mega-menu__link-image) .mega-menu__column > div > .mega-menu__link:not(:has(.mega-menu__link-image))::before {
  aspect-ratio: 1 / 1;
}

/* ==========================================================================
   30. Mobiler Feinschliff der Schriftgroessen
   ==========================================================================
   Nach Sichtprobe des Nutzers am Geraet. Die Werte gelten nur unter 750px;
   am Desktop bleibt alles, wie es abgestimmt war. */
@media screen and (max-width: 749px) {
  /* Kartenpreis: 1.25rem sind auf einer 182px breiten Karte noch zu laut,
     zusammen mit Streichpreis und Prozent-Punkt in derselben Zeile. */
  .product-grid__item .price,
  .resource-list__item .price {
    font-size: 1.0625rem;
  }

  /* Sterne auf der Karte: Sie wurden vom Zaehler plattgedrueckt.

     Gemessen auf einer 182px breiten Karte: Die Zeile hat 152px Platz, die
     fuenf Sterne brauchen 96px und „158 Bewertungen" rund 105px. Beide sind
     Flex-Kinder mit `flex-shrink: 1`, und weil der Zaehler `white-space: nowrap`
     traegt, gab NUR der Stern nach: `.rating` schrumpfte auf 12px, jedes
     Stern-SVG auf 0,875px Breite bei 17,6px Hoehe. Das sind die komischen
     Striche.

     Zwei Zeilen sind hier die ehrliche Loesung: Die Sterne behalten ihre
     Groesse, der Zaehler rutscht darunter, wenn er nicht daneben passt. Ihn
     ganz auszublenden waere schlechter — die Bewertungszahl war ausdruecklich
     gewuenscht. */
  .product-grid__item .rating-wrapper,
  .resource-list__item .rating-wrapper {
    flex-wrap: wrap;
  }

  .product-grid__item .rating,
  .resource-list__item .rating {
    flex: 0 0 auto;
  }

  .product-grid__item .rating-count,
  .resource-list__item .rating-count {
    font-size: 0.75rem;
  }

  /* Der Kauf-Knopf auf der Karte war 36x36 — ueber der WCAG-Mindestgroesse von
     24, aber unter den 44, die fuer einen Daumen komfortabel sind. Und es ist
     der Knopf, der die Bestellung ausloest. */
  .product-grid__item .quick-add button,
  .resource-list__item .quick-add button {
    min-width: 44px;
    min-height: 44px;
  }

  /* Menue in der Schublade: Versalien wirken groesser als gemischte
     Schreibweise, 1rem war dadurch zu praesent.

     Der Ausschluss ist wichtig und war vorher mein Fehler: Ohne ihn traf diese
     Regel auch die oberste Ebene — aber nur dort, wo sie ein `<a>` ist. Die
     sechs Kategorien mit Untermenue sind `<summary>` und blieben bei 28px,
     „Bestseller" und „Angebote" sind `<a>` und landeten bei 15px. Daher der
     Groessensprung in derselben Liste. */
  #header-component .menu-drawer a:not(.menu-drawer__menu-item--mainlist),
  #header-component .header__drawer a:not(.menu-drawer__menu-item--mainlist) {
    font-size: 0.9375rem;
  }

  /* Die sechs Hauptpunkte der Schublade sind 28px gross und liefen in Gewicht
     400 — das ist bei uns bewusst Malva MEDIUM und nicht Book (siehe die
     @font-face-Notiz oben: Book traegt im Fliesstext 25% zu wenig Farbe). Bei
     28px kippt diese Rechnung: Da ist der lichte Schnitt der richtige, und
     Medium liest als fett.

     Gemessen ueber die Tintendeckung derselben Zeile in 28px (Canvas, Summe
     der Deckung):
       Medium 400  2014
       Book   350  1450   (72%, also 28% weniger Farbe)
       Light  300  1208   (60% — zu duenn fuer ein Menue)

     Deshalb 350. Die Unterpunkte (gemessen 15px, 89 Stueck) bleiben auf 400,
     dort waere Book wieder der ausgewaschene Fliesstext. */
  #header-component .menu-drawer__menu-item--mainlist {
    /* Eine Groesse fuer ALLE der obersten Ebene, `<a>` wie `<summary>`:
       gemessen standen 28px neben 15px in derselben Liste.

       1.125rem und nicht 1.25rem: Bei 20px war jede Zeile 54px hoch, acht
       Zeilen also 432px — mehr als die Haelfte des Bildschirms fuer das Menue
       allein. Mit 18px und 38px Mindesthoehe sind es 46px je Zeile, macht 64px
       Gewinn. Die Trefferflaeche bleibt bei 46px ueber den 44px, die ein
       Daumen braucht. */
    font-size: 1.125rem;
    font-weight: 350;
    min-height: 38px;
  }

  /* Haarlinien zwischen den Hauptzeilen. Eine Liste ohne Trennung liest sich
     bei acht gleich gesetzten Zeilen als Textblock; die Linie gibt jeder Zeile
     eine Kante, ohne Farbe ins Menue zu bringen. Nur direkte Kinder der
     Hauptliste — die Unterlisten bleiben unberuehrt. */
  #header-component .menu-drawer__menu > li + li {
    border-block-start: 1px solid rgb(var(--color-foreground-rgb) / 0.08);
  }

  /* Der Pfeil rechts hatte eine 34x46 grosse Flaeche und stand damit fast so
     schwer da wie die Beschriftung. Kleiner und gedeckt: Er zeigt an, dass es
     weitergeht, er ist nicht die Botschaft. */
  #header-component .menu-drawer__list-item .icon-caret,
  #header-component .menu-drawer__menu-item .svg-wrapper {
    color: rgb(var(--color-foreground-rgb) / 0.45);
  }

  #header-component .menu-drawer__list-item .icon-caret svg {
    width: 0.875rem;
    height: 0.875rem;
  }

  /* Und hier sitzt die eigentliche Zeilenhoehe: Der Container des Pfeils traegt
     `padding: 16px 0 16px 20px`, ist damit gemessen 46px hoch und schiebt die
     Zeile auf 54px — die Schrift hat daran keinen Anteil (Text 25px hoch). Mit
     8px oben und unten sind es 30px, die Zeile faellt auf die 45,6px
     Mindesthoehe des Listeneintrags. Der Abstand links bleibt, er trennt Pfeil
     und Beschriftung. */
  #header-component .menu-drawer__list-item .icon-caret {
    padding-block: 0.5rem;
  }

  /* Der Produktblock am Fuss der Schublade war gemessen mit 49 von 230px
     sichtbar — 78 Prozent nicht erreichbar, weil die Schublade nur 37px
     Scrollweg hat. Ausgeblendet war er einen Schritt lang, dann blieb unten
     eine Leerstelle. Mit den engeren Zeilen (46 statt 54) und 18 statt 20px
     Schrift endet die Liste jetzt bei 477 statt 532px — der Block hat also
     Platz und bleibt drin. Die Hoehe der Kacheln ist begrenzt, damit er die
     Hilfszeilen nicht wieder wegdrueckt. */
  #header-component .menu-drawer__featured-content .resource-card__media,
  #header-component .menu-drawer__featured-content .resource-card__image {
    aspect-ratio: 1 / 1;
    max-height: 96px;
  }

  /* Und das war die Ursache dafuer, dass der Block bisher unerreichbar war:
     Horizon gibt den Hilfszeilen `margin-block: auto …`. Der Auto-Rand saugt
     den freien Platz auf und schiebt alles darunter aus dem Kasten — und was
     ein Auto-Rand hinausschiebt, ist NICHT scrollbar. Gemessen: Scrollweg 0,
     Produktblock von 215px nur 65px sichtbar.

     Ohne Auto-Rand packt die Spalte von oben, und alles hat Platz. Der Abstand
     nach oben bleibt als fester Wert, damit die Hilfszeilen nicht an der Liste
     kleben. */
  #header-component .menu-drawer__utility-links {
    margin-block-start: var(--margin-md, 1rem);
  }
}

/* „Am haeufigsten gekauft" stand als h3 auf Blockgroesse und blieb neben den
   uebrigen Abschnittstiteln zurueck — dieselbe Groesse wie diese. */
.section-resource-list__header .text-block :is(h2, h3) {
  font-size: var(--font-size--h2, 2rem);
}

/* ==========================================================================
   31. Mega-Menue: Bruecke ueber den toten Streifen unter der Menuezeile
   ==========================================================================

   Fehlerbild des Nutzers: „Wenn man auf Messen geht und dann zur Kategorie
   runtergeht, geht das Menue manchmal zu."

   Nachgemessen bei 1440px:
     Menuepunkt endet         y 121
     .header__columns endet   y 132   (11,2px Innenabstand = --header-padding)
     Zeile endet              y 134   (2px orange Linie)
     Panel wird treffbar ab   y 132   (clip-path: inset(134px …), und
                                       clip-path schneidet auch Treffer weg)

   Zwischen Menuepunkt und Panel liegen also 11px, in denen der Zeiger auf
   `.header__columns` steht — weder auf dem `<li>`, an dem `pointerleave`
   haengt, noch auf dem Panel. Reproduziert: Zeiger 12px nach unten, und
   `aria-expanded` springt auf false, `--submenu-height` auf 0.

   Horizon hat dafuer eine Sicherheitsflaeche (`.menu-list__link::after`,
   Zeile 320 in blocks/_header-menu.liquid). Die ist volle Zeilenbreite und
   ueberdeckt den Streifen — aber nur, solange der Zeiger sich BEWEGT
   (`data-safety-box`, nach 50ms Stillstand wieder aus). Genau deshalb „manchmal":
   Wer im Streifen kurz zoegert, verliert das Menue.

   Diese Flaeche einfach dauerhaft einzuschalten waere falsch. Sie beginnt auf
   Hoehe der Links und liegt ueber der ganzen Zeile; dauerhaft sichtbar wuerde
   sie die Nachbarpunkte verdecken, und der Wechsel von „Messen" zu „Saegen"
   waere nicht mehr moeglich. Das 50ms-Fenster ist Absicht: Danach raeumt
   `#reconcilePointerTarget` die Flaeche weg und prueft per `elementFromPoint`,
   worauf der Zeiger wirklich steht.

   Deshalb eine ZWEITE, eigene Flaeche, die nur den Streifen UNTER den Links
   abdeckt (`bottom: 0` bezieht sich auf die Zeile — sie ist der positionierte
   Vorfahr, `offsetParent` des Links ist gemessen `.header__row`). Dort liegt
   kein Link, das Wechseln bleibt also unberuehrt, und weil sie zum Link gehoert
   und der Link im `<li>` sitzt, feuert `pointerleave` nicht mehr.

   `::before`, weil `::after` die Sicherheitsflaeche des Themes ist. Die 3px
   Zugabe holen die orange Linie mit; das Panel wird ab 132 treffbar, die
   Flaeche endet bei 134 — zwei Pixel Ueberlappung im Innenabstand des Panels,
   dort liegt kein Inhalt.

   Der Punkt „Mehr" braucht das nicht, den bruecken Horizons Zeilen 354–359
   schon. */
#header-component .header__row--bottom .menu-list__link[aria-expanded='true']::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: calc(var(--header-padding, 0.7rem) + 3px);
}

/* ==========================================================================
   32. Suchleiste im offenen Mobilmenue
   ==========================================================================

   Wunsch des Nutzers: „Auch wenn das Menue offen ist, die Suche oben als Leiste
   darstellen." Bei offener Schublade war die Suche gemessen unerreichbar — das
   Lupensymbol der Kopfleiste liegt unter dem Panel.

   Die Leiste sieht aus wie das Suchfeld der Kopfleiste (gleiche Rundung,
   gleicher gedeckter Grund, Lupe links), ist aber ein Knopf: Sie oeffnet
   Horizons Suchmodal ueber dieselbe Bindung wie das Symbol. Deshalb steht der
   Platzhaltertext auch in Platzhalterfarbe — er verspricht ein Feld, und genau
   das kommt beim Antippen.

   Sie klebt oben, damit sie beim Scrollen durch lange Menues erreichbar bleibt;
   der Grund der Schublade steht dahinter, sonst scheinen die Menuepunkte
   durch. */
/* HINWEIS: Hier stand zwischenzeitlich ein Lupensymbol oben rechts statt der
   Leiste. Zurueckgenommen — die Leiste war dem Nutzer lieber. Der Versuch ist in
   der Versionsgeschichte (Commit „Schublade: Suche als Lupensymbol oben rechts")
   samt Messwerten nachlesbar, falls die Frage wiederkommt: Symbol 44x44 oben
   rechts, Navigation begann dann bei y 52 statt y 120. */
.custom-drawer-search {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--gap-sm, 0.5rem);
  /* Nicht mehr randlos: Vorher lief die Leiste ueber die volle Breite der
     Schublade (gemessen 355px bei 0px Einzug), waehrend die Menuezeilen 18,2px
     eingerueckt sind — die Leiste stach also links und rechts heraus. Jetzt
     folgt sie derselben Quelle wie die Liste (`--drawer-padding`), steht damit
     bundig unter den Kategorien und ist rund 36px schmaler. */
  width: auto;
  margin-inline: var(--drawer-padding);
  /* 44px: Daumenmass. Die Zeilenhoehe allein traegt hier nicht. */
  min-height: 44px;
  /* Gemessen blieben unter der Leiste 13px bis zum ersten Menuepunkt — bei
     20px Schrift klebt die Zeile dann an der Leiste. */
  margin-block-end: var(--margin-lg, 1.5rem);
  padding-inline: var(--padding-md, 0.75rem);
  border: var(--style-border-width-inputs, 1px) solid var(--color-border);
  border-radius: var(--style-border-radius-inputs, 8px);
  /* Zwei Schichten, und das ist der Punkt: Der Grund MUSS deckend sein.
     Vorher stand hier nur `rgb(… / 0.04)` — die Leiste klebt oben, und beim
     Scrollen wanderten die Menuepunkte sichtbar hinter ihr durch. Genau das
     Fehlerbild „die Suche geht in die Schrift rein". Die Grundfarbe deckt, der
     Verlauf darueber traegt nur den leichten Ton. */
  background-color: var(--color-background);
  background-image: linear-gradient(
    rgb(var(--color-foreground-rgb) / 0.04),
    rgb(var(--color-foreground-rgb) / 0.04)
  );
  color: var(--color-foreground);
  text-align: start;
  cursor: pointer;
}

.custom-drawer-search__icon {
  display: flex;
  flex: 0 0 auto;
}

.custom-drawer-search__icon svg {
  width: 1.125rem;
  height: 1.125rem;
}

/* Wie ein Platzhalter, nicht wie eine Beschriftung: Der Ton ist gedeckt, damit
   die Leiste als leeres Feld gelesen wird und nicht als Menuepunkt. 0,6 traegt
   auf diesem Grund gemessen 4,9:1 — ueber der Schwelle fuer kleinen Text. */
.custom-drawer-search__text {
  color: rgb(var(--color-foreground-rgb) / 0.6);
  font-size: var(--font-size--sm, 0.875rem);
}

/* Die zwei Hilfszeilen unten im Mobilmenue auf eine Groesse.

   Gemessen standen dort „Anmelden" in 15px neben „EUR" in 26px fett — die
   Waehrung war der groesste Text im ganzen Menue, obwohl sie die leiseste
   Angabe ist (Horizon gibt dem Knopf die Klasse `h3`). Und meine 15px kamen
   nicht aus dieser Regel, sondern aus der Schubladen-Regel weiter oben: Die
   traegt eine id im Selektor und gewinnt gegen eine reine Klasse. Deshalb
   stehen beide Zeilen hier mit `#header-component` davor.

   1rem, eine Stufe unter den 1.25rem der Menuepunkte: Hilfszeilen, nicht
   Navigation. */
#header-component .menu-drawer a.custom-drawer-account,
#header-component .menu-drawer__utility-links .drawer-localization__button {
  font-size: 1rem;
  font-weight: 400;
}

#header-component .menu-drawer a.custom-drawer-account {
  color: rgb(var(--color-foreground-rgb) / 0.75);
}

.custom-drawer-account .svg-wrapper {
  display: flex;
}

/* Die Laenderzeile im Schubfach: Flagge, Landesname, Waehrung.

   Der Name traegt die Zeile, der Waehrungscode steht leiser daneben — er ist
   die Folge der Wahl, nicht die Wahl selbst. Vorher stand dort nur „EUR",
   und danach hat auch niemand eine Laenderauswahl gesucht.

   `align-items: center` ist noetig, weil die Flagge ein eigenes Kaestchen mit
   fester Groesse ist und sonst an der Schriftgrundlinie haengt. */
#header-component .menu-drawer__utility-links .mobile-localization--country {
  align-items: center;
  gap: 0.5rem;
}

/* Beide Groessen ausdruecklich: Gemessen kam der Landesname bei 12px heraus
   und die Waehrung bei 14px — die Nebenangabe war groesser als die Hauptsache,
   weil der Name seine Groesse von einer inneren Horizon-Regel erbt und nicht
   vom Knopf (16px). Also setzen wir beide selbst. */
#header-component .menu-drawer__utility-links .custom-drawer-country {
  font-size: 1rem;
  font-weight: 400;
}

#header-component .menu-drawer__utility-links .currency-code {
  color: rgb(var(--color-foreground-rgb) / 0.55);
  font-size: 0.8125rem;
}

/* ==========================================================================
   33. Dreiklang im Hero auf Mobil
   ==========================================================================
   Steht bewusst HIER am Dateiende und nicht oben bei Schleier und Farbton:
   Die Desktopregel `.hero .text-block:first-child p` in Abschnitt 27 hat
   dieselbe Spezifitaet. Bei Gleichstand gewinnt die spaetere Regel — mein
   erster Versuch stand vor ihr und blieb wirkungslos, gemessen weiter 20px.

   Begruendung der Werte steht bei der Schleierregel in Abschnitt 26. */
@media screen and (max-width: 749px) {
  .hero .text-block:first-child p {
    font-size: 0.9375rem;
  }

  /* Mit der einzeiligen Zeile wuchs der gemessene Abstand zur Ueberschrift von
     20 auf 43px. Der Ausgleich am Block muss also mobil eigene Werte tragen —
     der Desktopwert (-0.4375rem) ist auf die 28px-Zeile dort gerechnet. */
  .hero .text-block:first-child {
    /* -1.875rem ergab gemessen 13px Abstand, das klebte. -1.5rem sind 19px und
       damit dasselbe Bild wie vor der Verkleinerung (20px). */
    margin-block-end: -1.5rem;
  }
}

/* ==========================================================================
   34. Kaufleiste auf Produktseiten (mobil)
   ==========================================================================

   Fehlerbild des Nutzers: „Wenn man scrollt, ist die Schrift sehr gross und
   passt nicht in den Button."

   Nachgemessen bei 375px: Die Leiste ist ein Flex-Streifen mit 309px nutzbarer
   Breite (375 minus 22 Polster minus drei Luecken à 14,4). Darin liegen Bild
   (52, unnachgiebig), Titel, Preis und Knopf. Der Knopf traegt
   `flex: 0 1 auto`, darf also schrumpfen — und wurde auf 52x52 gequetscht, ein
   Quadrat mit 20px Innenraum fuer „In den Warenkorb legen (1)" in 16px. Die
   Schrift war nicht zu gross, der Knopf war zu klein.

   Wer den Platz nahm, war nicht der Preis: Die Preisspalte war 168px breit,
   davon 114px allein der Badge „Du sparst 20%". Der steht ohnehin schon in der
   Kaufbox weiter oben. Der Titel daneben war auf 38px zusammengedrueckt und
   damit unlesbar — und er ist auf der Seite des Produkts die redundanteste
   Angabe.

   Bleibt: Bild, Preis, Knopf. Der Knopf nimmt sich mit `flex: 1 1 auto` den
   Rest, statt auf seinen Inhalt geschrumpft zu werden, und `nowrap` haelt die
   Beschriftung in einer Zeile. */
@media screen and (max-width: 749px) {
  /* Auch das Vorschaubild geht: Mit Bild bekam der Knopf 222px, die
     Beschriftung „In den Warenkorb legen (1)" braucht in 15px aber 236px — es
     fehlten 42px. Kleiner setzen half nicht: Erst bei 12px passte der Text,
     und 12px sind fuer den Hauptknopf zu klein. Ohne Bild sind es 288px
     Knopfbreite gegen 236px Text.

     Was bleibt, ist die richtige Auswahl: Preis links, Kaufknopf rechts. Bild
     und Titel zeigen auf der Seite des Produkts nur, was ohnehin darueber
     steht. */
  .sticky-add-to-cart__price .custom-savings-badge,
  .sticky-add-to-cart__info,
  .sticky-add-to-cart__image {
    display: none;
  }

  .sticky-add-to-cart__button {
    flex: 1 1 auto;
    min-width: 0;
    padding-inline: 0.875rem;
    font-size: 0.9375rem;
    white-space: nowrap;
  }
}

/* ==========================================================================
   35. Kopfleiste beim Scrollen: verworfen, und warum
   ==========================================================================

   Der Wunsch war „auf Desktop soll das Menue beim Runterscrollen kleiner
   werden, es nimmt sehr viel Platz ein". Drei Fassungen, drei Fehlerbilder,
   alle vom Nutzer gemeldet:

     1. Navigationszeile klappt weg          -> „geht komplett weg"
     2. Zeilen werden kompakt (133 -> 111px) -> „geht halb weg", weil der
        `clip-path` der Mega-Menue-Flaeche einen festen Wert traegt
        (`inset(134px …)`) und bei kleinerem Kopf die oberen 23px abschnitt
     3. Kompakt mit Vorbehalt fuer offene Menues -> „springt beim Scrollen"

   Zu 3: Die Hoehe der Kopfleiste ist im Theme an mehreren Stellen Bezugsgroesse
   — `--header-height` schreibt `assets/header.js` laufend auf den `body`, und
   daran haengen die Klappflaeche der Suche, die Schublade, der Kontobereich und
   die klebenden Spalten der Produktseite. Wer die Hoehe im Scrollen aendert,
   verschiebt all das mit; dazu kippt der IntersectionObserver, der
   `data-sticky-state` setzt, in der Naehe seiner Schwelle hin und her, sobald
   die Hoehe selbst das Ergebnis beeinflusst. Das ist die Rueckkopplung, die man
   als Springen sieht.

   Die Zeilenhoehen sind ausserdem hart gesetzt (`grid-template-rows: 46px` oben,
   `40px` unten) und das Polster der Spaltenboxen liess sich mit keinem Mittel
   aendern, auch nicht mit `!important` inline. Eine saubere Verkleinerung
   braucht also einen Eingriff in die Kopfleisten-Section selbst, nicht ein
   Overlay aus dieser Datei — und die Entscheidung darueber gehoert dem Nutzer.

   Bis dahin bleibt die Kopfleiste, wie sie ist: 133px, klebend, unveraendert
   beim Scrollen. Nichts springt, nichts verschwindet.

   Wer es erneut versucht: `enable_sticky_header` kennt neben 'always' auch
   'scroll-up'. Damit faehrt die GANZE Leiste beim Runterscrollen aus dem Bild
   und beim Hochscrollen zurueck — Horizons eigene, getestete Mechanik, ohne
   Geometrie anzufassen. Es ist eine Einstellung, keine Zeile CSS. */

/* ==========================================================================
   36. Navigationszeile: keine leere Spalte reservieren
   ==========================================================================
   Gemessen bei 1280px Fenster: Die Zeile ist ein Raster aus 1031,58px Menue
   und 137,42px zweiter Spalte — und diese zweite Spalte ist LEER. In der
   Navigationszeile steht nur der Menue-Block, Horizons Grundraster legt aber
   drei Spalten an (`1fr auto 1fr`, links/mitte/rechts).

   Der Schaden entsteht im Zusammenspiel mit dem Ueberlauf-Element: Eine
   `overflow-list` verkleinert sich selbst, indem sie Punkte ins „Mehr"-Menue
   schiebt. Ihre Mindestbreite ist damit klein, und das Raster erfaehrt nie,
   dass das Menue eigentlich mehr Platz braeuchte — die leere Spalte behaelt
   ihren Anteil, und stattdessen verschwinden „Bohren & Haemmern" und
   „Zubehoer" hinter „Mehr".

   Eine Spalte statt zwei gibt dem Menue die 137px plus den 20px-Abstand
   zurueck. Horizon selbst hat dieselbe Regel schon fuer Zeilen ganz ohne
   Spalte (`.header__columns:not(:has(.header__column))`) — hier fehlte der
   Fall „genau eine".

   Die Bedingung prueft die Spalten selbst und nicht die Zeile: Erster Versuch
   zielte auf `.header__navigation-bar-row`, das Menue sitzt aber in
   `.header__row--bottom` — die Navigationszeile ist in dieser Konfiguration
   leer und unsichtbar. Ueber die Spalten formuliert gilt die Regel fuer jede
   Zeile, die nur eine linke Spalte hat, und laesst die obere Zeile
   (links/mitte/rechts, gemessen 444,5 / 260 / 444,5px) unberuehrt.

   Gesetzt wird die VARIABLE, nicht die Eigenschaft: Horizon leitet
   `grid-template-columns` daraus ab und ueberschreibt sie in mehreren
   Medienabfragen. Wer die Eigenschaft setzt, kaempft gegen diese Regeln;
   wer die Variable setzt, fuettert sie.
   -------------------------------------------------------------------------- */
#header-component .header__columns:has(.header__column--left):not(:has(.header__column--center)):not(:has(.header__column--right)) {
  --header-template-columns: 1fr;
}

/* Und das Menue muss den gewonnenen Platz auch nehmen.

   Gemessen nach der Rasteraenderung: Spalte 1169px, Menue weiter 1032px. Als
   Flex-Element mit `flex: 0 1 auto` sitzt es auf Inhaltsbreite — und weil die
   `overflow-list` ihren Inhalt selbst verkleinert, ist diese Inhaltsbreite
   genau so gross wie das, was gerade hineinpasst. Ein Kreis: Sie fragt nie
   nach mehr, also bekommt sie nie mehr.

   Deshalb ausdruecklich wachsen lassen und die Breite bis zur Liste
   durchreichen. Erst dann rechnet der Ueberlauf mit den 1169px. */
#header-component .header__columns:has(.header__column--left):not(:has(.header__column--center)):not(:has(.header__column--right)) header-menu {
  flex: 1 1 auto;
  min-width: 0;
}

#header-component .header__columns:has(.header__column--left):not(:has(.header__column--center)):not(:has(.header__column--right)) :is(.header-menu__inner, .menu-list, overflow-list.overflow-menu) {
  width: 100%;
}

/* Und etwas Polster aus den Menuepunkten.

   `.menu-list__link-title` traegt `padding-inline: calc(var(--gap-xl) / 2)`,
   also 16px je Seite und damit 32px je Punkt. Gemessen sind das bei sechs
   Punkten 192px allein fuer Abstaende, gegen 871px Text — jeder fuenfte Pixel
   der Leiste ist Luft.

   11px je Seite lassen zwischen zwei Punkten immer noch 22px, das reicht bei
   14px-Versalien zum Trennen. Gewonnen: rund 60px, die Schwelle fuer das
   „Mehr"-Menue wandert damit um etwa 60px nach unten. */
#header-component .header__row--bottom .menu-list__link-title {
  padding-inline: 11px;
}

/* Den negativen Aussenabstand der inneren Liste einseitig zuruecknehmen.

   Horizon gibt `.overflow-menu::part(list)` ein `margin-inline` von -16px je
   Seite, damit das Polster des ersten und letzten Punkts nach aussen faellt
   und die Schrift an der Seitenkante sitzt. Solange das Menue auf
   Inhaltsbreite stand und die Spalte breiter war, gab es dafuer Spielraum.

   Seit das Menue seine Spalte ausfuellt, ist dieser Ueberstand schaedlich: Die
   innere Liste ist 32px breiter als der Host, der Umbruchtest laesst also 32px
   mehr Inhalt zu, als die Seite zeigen kann. Gemessen bei 1000px Fenster war
   „Zubehoer" um 17px abgeschnitten, ohne dass das „Mehr"-Menue erschien — der
   Ueberlauf hielt alles fuer passend.

   Links bleibt der Ueberstand (11px, passend zum Polster), damit der erste
   Menuepunkt weiter an der Seitenkante steht. Rechts wird er entfernt: Dort
   faellt nur unsichtbares Polster weg, und der Umbruchtest rechnet wieder
   ehrlich. */
#header-component .header__row--bottom overflow-list.overflow-menu::part(list) {
  margin-inline: -11px 0;
}

/* ==========================================================================
   37. Kategorie-Kacheln auf Mobil: Label UNTER dem Bild
   ==========================================================================
   Die Kachel legt das weisse Label normalerweise ueber das Bild, 12px vom
   unteren Rand. Am Desktop passt das: Die Kachel ist dort 225px breit und
   hoch genug, das Label deckt einen Streifen ab.

   Auf dem Telefon nicht. Gemessen bei 375px und zwei Spalten ist die Kachel
   166x166px, das Label mit Mindesthoehe 44px plus 12px Abstand verdeckt also
   die unteren 56px — ein Drittel des Bildes, und zwar genau den Teil, in dem
   bei freigestellten Werkzeugfotos das Motiv liegt.

   Deshalb mobil gestapelt: Bild oben in seinem Format, Label darunter. Die
   Kachel verliert dafuer ihr festes Seitenverhaeltnis (`auto`), sonst wuerde
   das Label aus der Kachel herausragen und `overflow: hidden` es abschneiden.

   Der Radius wandert von der Kachel aufs Bild, und der Platzhaltergrund wird
   durchsichtig: Beides gehoerte zum Bild, nicht zur gestapelten Kachel — sonst
   liegt ein grauer Block hinter dem Label.

   Bewusst nur im Kategorie-Raster (`.custom-category-grid`): Dieselbe Kachel
   wird anderswo mit anderen Groessen eingesetzt, dort ueberlagert sie weiter.
   -------------------------------------------------------------------------- */
@media screen and (max-width: 749px) {
  .custom-category-grid .custom-collection-card {
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow: visible;
    border-radius: 0;
    background-color: transparent;
  }

  .custom-category-grid .custom-collection-card__image {
    height: auto;
    aspect-ratio: var(--custom-collection-card-ratio, 4 / 5);
  }

  .custom-category-grid .custom-collection-card__label {
    position: static;
    /* `translate` UND die Randabstaende zuruecknehmen: Die Ueberlagerung
       zentrierte per `inset-inline-start: 50%` und `translate: -50%`. Bleibt
       eines davon stehen, sitzt das Label um seine halbe Breite verschoben. */
    inset-block-end: auto;
    inset-inline-start: auto;
    translate: none;
    max-width: 100%;
    margin-inline: auto;
  }
}

/* ==========================================================================
   38. Kaeuferschutz-Siegel beim Runterscrollen ausblenden
   ==========================================================================
   Das Trusted-Shops-Siegel klebt unten links und liegt beim Lesen ueber dem
   Inhalt. Es soll verschwinden, sobald man nach unten liest, und beim
   Zurueckscrollen wiederkommen.

   Ohne Skript: Horizon setzt `data-scroll-direction` bereits am
   `#header-component` (gemessen: `none`, `up`, `down`). Das Siegel haengt aber
   woanders im Dokument — mit `:has()` am `body` laesst sich der Zustand des
   Headers trotzdem abfragen. Kein Scroll-Listener, kein zusaetzliches Asset.

   Die id des Siegels traegt einen Hash (`trustbadge-container-98e3dadd…`), der
   sich beim Neukonfigurieren aendern kann. Deshalb Praefix-Selektor statt
   vollstaendiger id.

   `visibility` zusaetzlich zur Deckkraft, damit das Siegel im ausgeblendeten
   Zustand nicht per Tabulator erreichbar bleibt — ein unsichtbarer Fokus ist
   schlimmer als ein sichtbares Siegel.
   -------------------------------------------------------------------------- */
/* Zwei Fallen, beide gemessen:

   1. Nicht die HUELLE ansprechen. `#trustbadge-container-…` ist 0x0 und der
      sichtbare Teil haengt darin in einem EIGENEN `position: fixed`-Div —
      Deckkraft und Transform an der Huelle bewirkten nichts. Ziel ist der
      Knopf `#minimized-trustbadge-…` selbst.

   2. `!important` ist hier keine Bequemlichkeit, sondern noetig: Das Widget
      setzt seine eigene Deckkraft mit `!important`. Ohne blieb der Wert
      gemessen bei 1, mit greift er (geprueft: 0,3 kam an). Fremdcode mit
      `!important` laesst sich nur so ueberstimmen.

   Die Scrollrichtung liefert Horizon selbst am `#header-component`
   (`none`, `up`, `down`) — mit `:has()` am `body` abgefragt, also ohne
   eigenen Scroll-Listener und ohne zusaetzliches Asset. */
/* Auch der Uebergang braucht `!important` — gemessen meldete das Element
   `transition-property: none`, das Widget setzt also seine eigene. Ohne den
   Uebergang schaltet das Siegel hart um, statt auszublenden. */
/* Spezifitaet hochziehen, nicht nur `!important`: Auch mit `!important` blieb
   `transition-property` gemessen auf `none` — das Widget setzt seine Regel
   offenbar ueber eine id, und bei zwei `!important` gewinnt der spezifischere
   Selektor. Das `:has(#header-component)` bringt eine id mit und liegt damit
   darueber. */
body:has(#header-component) [id^='minimized-trustbadge-'] {
  transition: opacity 220ms ease, visibility 220ms ease !important;
}

/* Zweiter Anlass zum Ausblenden: das offene Mobilmenue. Gemeldet — beim
   Scrollen verschwindet das Siegel, im offenen Menue blieb es stehen und lag
   dort ueber der Navigation.

   Zustand ist `details.menu-drawer-container[open]`: Horizons Schublade ist ein
   `details`-Element, und der Klick auf die Zusammenfassung setzt das Attribut
   (gemessen: vorher false, nach dem Antippen true). Kein Skript noetig.

   `#header-component` steht im Selektor, obwohl es fuer die Auswahl nicht
   gebraucht wird — es bringt die id mit. Ohne sie verliert die Regel gegen die
   eigene Regel des Widgets, die ueber eine id kommt; das war schon beim
   Scroll-Ausblenden die Falle (siehe oben). Nachgemessen: die Schublade liegt
   innerhalb von #header-component. */
body:has(#header-component[data-scroll-direction='down']) [id^='minimized-trustbadge-'],
body:has(#header-component details.menu-drawer-container[open]) [id^='minimized-trustbadge-'] {
  opacity: 0 !important;
  visibility: hidden !important;
  pointer-events: none !important;
}

@media (prefers-reduced-motion: reduce) {
  [id^='minimized-trustbadge-'] {
    transition: none;
  }
}

/* ============================================================================
   39. Lange Zusammensetzungen duerfen die Seite nicht sprengen
   ----------------------------------------------------------------------------
   Gemeldet ueber Handy-Screenshots: rechts ein weisser Streifen, die dunkle
   Kopfleiste reichte nicht bis zum Rand.

   Gemessen auf dem Innensechskantschluessel-Set bei 375px Layoutbreite: Das
   `h1` war 495px breit — genau die Breite des Wortes
   „INNENSECHSKANTSCHLÜSSEL" in Malva 900. Damit wuchs das Dokument auf 519px,
   alles mit `100vw` (Sticky-Kaufleiste, Cookie-Banner) folgte auf 519, waehrend
   `body` bei 375 blieb. Daraus entstand der weisse Streifen.

   Der Kern ist eine Feinheit: Horizon setzt `p, h1..h6 { overflow-wrap:
   break-word }`. Das erlaubt den Umbruch beim Rendern, aendert aber die
   `min-content`-Breite NICHT — die Box verlangt weiter die vollen 495px. Nur
   `overflow-wrap: anywhere` verkleinert auch `min-content`.

   `hyphens: auto` steht davor, weil das Dokument `lang="de"` traegt: Dann
   trennt der Browser „Innensechskant-schlüssel" an einer gueltigen Stelle,
   statt mitten im Wort zu brechen. `anywhere` ist nur die letzte Sicherung.

   Nachgemessen nach der Aenderung: Titel 327px, Dokument 375px, Kopfleiste und
   Sticky-Leiste beide 375px.

   Gilt fuer alle eigenen Ueberschriften und Kachelnamen — deutsche
   Werkzeugnamen sind lang, und das Problem trifft jede Stelle gleich.
   ========================================================================= */
.custom-pdp-hero__title,
.custom-sticky-buy-bar__title,
.custom-collection-hero__title,
.custom-collection-intro__heading,
.custom-collection-benefits__heading,
.custom-collection-benefits__title,
.custom-collection-description__titel,
.custom-collection-faq__heading,
.custom-collection-cta__heading,
.custom-collection-media__heading,
.custom-about__titel,
.custom-about__heading,
.custom-spec-table__heading,
.custom-cross-sell__heading,
.custom-cross-sell__title,
.custom-usecase-cards__heading,
.custom-feature-rows__heading,
.custom-feature-rows__title,
.custom-faq__heading,
.custom-reviews__heading,
.custom-hero-stein__heading,
.custom-image-band__heading,
.custom-pdp-banner__heading,
.custom-category-grid__heading,
.custom-awards-band__heading,
.custom-benefits__heading,
.custom-benefit__title,
.custom-trust-band__heading,
.custom-trust-item__title,
.custom-audience__heading,
.custom-hotspots__heading,
.custom-hotspot__title {
  hyphens: auto;
  overflow-wrap: anywhere;
  /* `hyphens: auto` trennt wie im Buchsatz JEDES Wort, wenn es die Zeile
     fuellt — auf Mobil stand „PER-FEKTE" und „JE-DER" in den Ueberschriften
     (Design-Audit 2026-08-27). Gewollt war nur die Rettung langer Komposita.
     Erst ab 14 Zeichen trennen: „Innensechskantschluessel" bricht weiter
     sauber, kurze Woerter bleiben ganz. Firefox kennt die Eigenschaft nicht
     und behaelt das alte Verhalten — verschmerzbar. */
  hyphenate-limit-chars: 14 7 7;
  -webkit-hyphenate-limit-before: 7;
  -webkit-hyphenate-limit-after: 7;
}

/* ============================================================================
   40. Fortschritt bis zum Gratisversand
   ----------------------------------------------------------------------------
   Sitzt in der Warenkorb-Zusammenfassung ueber der Summe. Die Zusammenfassung
   klebt in der Schublade am unteren Rand, der Balken ist damit immer im Blick.

   Dunkelblau und nicht orange: Direkt darunter steht der orange
   „Zur Kasse"-Knopf, und Orange ist in diesem Shop die Handlungsfarbe. Zwei
   orange Flaechen uebereinander nehmen sich gegenseitig die Wirkung. Erreicht
   ist der Balken gruen — dasselbe #1f9d55 wie „Auf Lager" auf der Produktseite.

   Der Uebergang laeuft nur dort, wo das Markup erhalten bleibt. Nach einer
   Mengenaenderung tauscht Shopifys Section Rendering das Element aus, dann
   steht der Balken sofort auf seinem neuen Wert — das ist kein Fehler, sondern
   der Preis dafuer, die Rechnung nicht doppelt in JavaScript zu halten.
   ========================================================================= */
.custom-cart-versand {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-block: 4px 12px;
}

.custom-cart-versand__text {
  margin: 0;
  font-size: 14px;
  line-height: 1.4;
  color: var(--custom-color-dark, #253746);
}

.custom-cart-versand__haken {
  font-weight: 900;
}

.custom-cart-versand__bahn {
  height: 8px;
  border-radius: 999px;
  background: rgb(37 55 70 / 0.12);
  overflow: hidden;
}

/* Bewegt wird `transform: scaleX`, nicht die Breite. Eine Breitenanimation
   loest in jedem Frame Layout aus; `scaleX` laeuft im Compositor.

   Kein eigener Radius mehr: Die Bahn hat `overflow: hidden` und rundet die
   Enden selbst. Ein mitskalierter Radius am Kind waere bei kleinen Werten
   waagerecht gequetscht. */
.custom-cart-versand__fuellung {
  display: block;
  width: 100%;
  height: 100%;
  transform: scaleX(var(--anteil-faktor, 0));
  transform-origin: left center;
  background: var(--custom-color-dark, #253746);
  transition: transform 320ms cubic-bezier(0.2, 0, 0.1, 1);
}

.custom-cart-versand--erreicht .custom-cart-versand__text {
  color: #1f9d55;
}

.custom-cart-versand--erreicht .custom-cart-versand__fuellung {
  background: #1f9d55;
}

@media (prefers-reduced-motion: reduce) {
  .custom-cart-versand__fuellung {
    transition: none;
  }
}

/* ============================================================================
   41. Fussbereich des Warenkorbs enger
   ----------------------------------------------------------------------------
   Gemessen bei 375px, vorher: Fussbereich 340px hoch, davon Rabattcode-Zeile
   46px, Versandbalken 36px, Gesamtzeile 26px, Steuerhinweis 38px, Knopf 52px.
   Der Rest waren Polster und Abstaende: 24px oben, 24px unten und drei
   Zwischenraeume von je 20px.

   38px fuer eine einzige Zeile Kleingedrucktes kamen von der Zeilenhoehe der
   Grundtypografie. Bei 12px Schrift und 1,35 Zeilenhoehe bleibt der Hinweis
   lesbar und braucht ein Drittel davon.

   custom.css laedt nach styles.css — gleichrangige Regeln gewinnen also, ohne
   dass hier `!important` noetig waere.
   ========================================================================= */
.cart-drawer__summary {
  padding-block: 20px 16px;
  row-gap: 14px;
}

.cart-totals {
  row-gap: 12px;
}

.cart-totals__tax-note {
  font-size: 12px;
}

.cart-totals__tax-note small {
  display: block;
  line-height: 1.35;
}

/* ============================================================================
   42. Werbekacheln im Schubladenmenue: Bestseller und Angebote
   ----------------------------------------------------------------------------
   Beide standen als gewoehnliche Textzeilen unten im Menue `horizon-schublade`
   (Bestseller an siebter, Angebote an achter Stelle). Jetzt sind sie Kacheln
   mit abgerundeten Ecken ganz oben: Beschriftung links, quadratisches
   Vorschaubild rechts.

   Warum die Reihenfolge hier und nicht im Menue: Ein Menue ist ein Shop-Objekt.
   Es ueber die API neu zu schreiben heisst, alle 25 Eintraege samt Typen neu
   aufzubauen — und wird ein Eintrag dabei aus `collection_link` ein reiner
   Adressverweis, faellt er auf /collections aus dem Raster, weil die
   Kategorie-Uebersicht genau diesen Typ abfragt. Hier ist es rueckbaubar und
   beruehrt den Shop nicht.

   Die Liste ist `display: block`, deshalb wird sie erst zur Flex-Spalte —
   `order` wirkt nur auf Flex- und Grid-Kinder. Nachgemessen: Listenhoehe vorher
   365px, nachher 365px.

   WEISSE Karte, nicht dunkle: Die beiden Produktbilder haben verschiedene
   Gruende — die Winkelschmiege steht auf Weiss, das Zwingen-Sparset auf
   Dunkelblau. Eine dunkle Karte haette dem weissen Bild einen hellen Klotz
   verpasst. Auf Weiss wirkt jedes Motiv wie ein Vorschaubild, unabhaengig von
   seinem eigenen Grund.

   `background-size: auto 100%` bei quadratischen Motiven ergibt genau ein
   Quadrat in Kachelhoehe am rechten Rand. Das `padding-inline-end` am Link
   haelt die Beschriftung davon frei.

   Die Bildadressen kommen aus snippets/custom.globals.liquid — custom.css ist
   ein statisches Asset, in dem kein Liquid laeuft.

   WICHTIG fuer spaeter: Werden die beiden im Menue selbst nach oben gezogen,
   sind die `order`-Regeln ueberfluessig und sollten weg — sonst steht hier eine
   unsichtbare zweite Wahrheit ueber die Reihenfolge.
   ========================================================================= */
.menu-drawer__navigation > .menu-drawer__menu {
  display: flex;
  flex-direction: column;
}

/* Kein oranger Balken links mehr. Er war als `border-inline-start: 3px`
   angelegt, und ein Rahmen mit 3px links gegen 1px oben verjuengt sich im
   Radius — sichtbar wurde ein loser Splitter neben der runden Ecke, der wie
   abgeschnitten aussah. Als Hintergrundebene folgte er der Rundung, sah aber
   weiter wie ein loses Stueck aus: Die Kachel selbst war auf weissem Grund mit
   14 Prozent Rahmendeckkraft kaum zu erkennen, der Strich stand also allein.

   Statt den Strich zu retten, traegt jetzt die Kachel selbst: kraeftigerer
   Rahmen und ein weicher Schatten, der eine weisse Karte auf weissem Grund
   abhebt. Damit ist es die Kachel, die auffaellt — genau das war der Wunsch,
   der Strich war meine Zutat. */
/* Die ID ist noetig: Abschnitt 36 setzt
   `#header-component .menu-drawer__menu > li + li { border-block-start: … }`
   mit (1,2,0) und gewann gegen (0,3,0) — der Kachelrahmen kam dadurch mit 0,08
   Deckkraft heraus statt mit 0,16 und war kaum zu sehen. Gemessen. */
#header-component .menu-drawer__navigation > .menu-drawer__menu > .menu-drawer__list-item:has(> a[href$='/collections/bestseller']),
#header-component .menu-drawer__navigation > .menu-drawer__menu > .menu-drawer__list-item:has(> a[href$='/collections/angebote']) {
  margin-block: 6px;
  border: 1px solid rgb(37 55 70 / 0.16);
  border-radius: 12px;
  box-shadow: 0 2px 6px rgb(37 55 70 / 0.1);
  background-color: #fff;
  background-repeat: no-repeat;
  background-position: right center;
  background-size: auto 100%;
  overflow: hidden;
}

#header-component .menu-drawer__navigation > .menu-drawer__menu > .menu-drawer__list-item:has(> a[href$='/collections/bestseller']) {
  order: -2;
  background-image: var(--presch-schublade-bestseller);
}

#header-component .menu-drawer__navigation > .menu-drawer__menu > .menu-drawer__list-item:has(> a[href$='/collections/angebote']) {
  order: -1;
  background-image: var(--presch-schublade-angebote);
}

/* Die ID im Selektor ist noetig, nicht Ziererei: Abschnitt 36 setzt
   `#header-component .menu-drawer__menu-item--mainlist { font-weight: 350 }`,
   also (1,1,0). Eine Klasse mit Attribut hat (0,2,0) und verlor — gemessen
   blieb das Gewicht bei 350.

   Die Schrift bleibt dunkel: #fc4c02 auf Weiss ergibt gemessen 3,4:1 und liegt
   damit unter den 4,5:1 fuer normalen Text. Die Markierung uebernehmen
   Kachelform, Schatten und Bild. */
#header-component .menu-drawer__menu-item[href$='/collections/bestseller'],
#header-component .menu-drawer__menu-item[href$='/collections/angebote'] {
  display: flex;
  align-items: center;
  min-height: 64px;
  padding-inline: 14px 76px;
  color: var(--custom-color-dark, #253746);
  font-weight: 700;
}

/* ============================================================================
   43. „Löschen" in der Suche nicht mehr abschneiden
   ----------------------------------------------------------------------------
   Auf Mobil zeigt Horizon im Suchfeld statt des Symbols den Text „Löschen"
   (eigene Regel im Theme: Symbol aus, Text ein, unter 750px). Der Knopf ist
   aber ein Flex-Element mit `flex: 0 1 auto` und `min-width: 44px`, darf also
   schrumpfen — und `overflow: hidden` schneidet ab, was nicht passt.

   Gemessen bei 430px: Zeile 367px, Eingabefeld 305px, fuer den Knopf blieben
   49,6px. „Löschen" braucht in 16px aber 61px. Es fehlten also 11px, und weil
   der Text mittig sitzt, wurde links das L angeschnitten.

   `flex-shrink: 0` dreht die Reihenfolge um: Der Knopf behaelt seine Textbreite,
   das Eingabefeld gibt die 11px ab. Ein angeschnittenes Bedienelement ist der
   schlechtere Tausch — 11px weniger Feld merkt niemand.

   `white-space: nowrap` als Sicherung: Ohne sie koennte der Text bei noch
   engeren Geraeten umbrechen und die Zeile hoeher machen.
   ========================================================================= */
@media screen and (max-width: 749px) {
  .predictive-search__reset-button {
    flex: 0 0 auto;
    white-space: nowrap;
  }
}


/* ====== Rechtszeile unter dem PDP-Preis (PAngV, Feedback 2026-08-28) ======
   "inkl. MwSt. / Kostenloser Versand" bzw. "... / zzgl. Versandkosten" (Link).
   Liegt IM priceContainer und bricht dort als eigene Zeile um — ruhig und
   klein, damit der Preis die Buehne behaelt, aber die Auskunft einen Klick
   entfernt ist. */
.custom-price__rechtszeile {
  display: flex;
  flex-basis: 100%;
  width: 100%;
  align-items: center;
  gap: 6px;
  margin-block-start: 4px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: rgb(var(--color-foreground-rgb, 37 55 70) / 0.65);
}

.custom-price__rechtszeile a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.custom-price__rechtszeile a:hover {
  color: var(--color-primary-button-background, #fc4c02);
}


/* ====== Richtlinien-Seiten (z. B. Versandkosten) ======
   Feedback 2026-08-28: Logos rendeten seitenbreit, Tabelle lief mobil aus
   dem Bild. Horizon setzt im RTE `max-width: 100%` und dehnt Bilder — hier
   bekommen Bilder MIT width-Attribut ihre Attributgroesse zurueck (`revert`
   rollt die Autorenregel auf den presentational hint zurueck), und Tabellen
   scrollen in der eigenen Box statt die Seite zu sprengen. */
/* `revert` fiel auf die intrinsische Bildgroesse zurueck (Chrome zaehlt
   width-Attribute zur Autorenebene) — deshalb feste Groessen ueber die
   Alt-Texte der Logos, in allen Sprachfassungen. vertical-align haelt beide
   auf einer Linie nebeneinander. */
.shopify-policy__body .rte img[alt="DHL Logo"],
.shopify-policy__body .rte img[alt="Logo DHL"],
.shopify-policy__body .rte img[alt="DHL-logo"] {
  /* display: inline-block gegen Horizons img { display: block } im RTE —
     sonst stapeln die Logos trotz gemeinsamem Absatz untereinander. */
  display: inline-block;
  width: 100px;
  height: auto;
  vertical-align: middle;
  margin-inline-end: 14px;
}

.shopify-policy__body .rte img[alt="DPD Logo"],
.shopify-policy__body .rte img[alt="Logo DPD"],
.shopify-policy__body .rte img[alt="DPD-logo"] {
  display: inline-block;
  width: 44px;
  height: 44px;
  vertical-align: middle;
}

.shopify-policy__body .rte table {
  display: block;
  overflow-x: auto;
  max-width: 100%;
}

.shopify-policy__body .rte th,
.shopify-policy__body .rte td {
  white-space: nowrap;
}
