/**
 * Eigene Regeln für vp_neoteric
 * ---------------------------------------------------------------------------
 * Angelegt am 29.07.2026 beim Umstieg von vp_merchant.
 * Herkunft: templates/vp_merchant/css/custom/custom.custom.css (548 Zeilen).
 *
 * WARUM DIESE DATEI
 * "user.css" ist der offizielle Platz von Joomla für eigene Regeln. Sie ist im
 * Template unter dem Namen "template.user" angemeldet und wird zuletzt geladen,
 * also nach allen Herstellerregeln. Der Hersteller schreibt sie NIE - sie
 * überlebt jedes Template-Update.
 *
 * DIE FIRMENFARBE STEHT NICHT HIER
 * Sie steht seit dem 30.07.2026 in der Template-Konfiguration:
 * System -> Templates -> Website-Templatestile -> "vp_neoteric - Umbau 2026"
 * -> Reiter Anpassung -> Stil. Dort gesetzt:
 *
 *   --template-primary-color                  #004494   (das Blau aus dem Logo)
 *   --template-primary-contrast-color         #ffffff   (Schrift darauf)
 *   --template-primary-hover-color            #333333   (beim Überfahren)
 *   --template-primary-hover-contrast-color   #ffffff
 *   --template-link-color                     #004494
 *   --template-link-hover-color               #333333
 *
 * Damit färben sich alle Knöpfe, Links und Marken des Templates von selbst -
 * eine Farbänderung ist ein Feld in der Verwaltung, keine Suche in CSS-Dateien.
 * Die Werte entsprechen dem alten Template (@btn-primary-bg: #004494,
 * @btn-primary-hover-bg: #333333, Schrift jeweils weiss).
 *
 * WER HIER EINE FARBE BRAUCHT, schreibt sie deshalb nicht fest hin, sondern
 * holt sie über die Variable, mit dem alten Wert als Rückfallebene:
 *
 *   background-color: var(--template-primary-color, #004494);
 *
 * Der zweite Wert greift nur, wenn die Variable fehlt - etwa wenn diese Datei
 * einmal unter einem anderen Template landet.
 *
 * WAS NICHT ÜBERNOMMEN WURDE
 * Rund die Hälfte der alten Regeln sprach Klassen an, die es nur in
 * vp_merchant gab: #vpf-header, .navbar-offcanvas, .brand, .horizontal-module,
 * .bottom-horizontal .nav-pills, .category-name, .owl-item, die Symbolschrift
 * VPFrameworkIcon und das Bootstrap-4-Akkordeon. Diese Regeln wären hier
 * wirkungslos und wurden weggelassen statt mitgeschleppt.
 *
 * Zwei Regeln wurden bewusst NICHT übernommen, obwohl sie wirken würden:
 *
 *   .category-page-title { display: none; }
 *       Blendete die Überschrift auf Kategorieseiten aus. Das neue Template
 *       zeigt sie ("E-BIKE"). Ob sie bleiben soll, ist eine Gestaltungsfrage -
 *       deshalb hier nicht stillschweigend wieder ausgeblendet.
 *
 *   @import 'all.css';  (Font Awesome 5, 137 KB)
 *       Joomla 5 liefert Font Awesome 6 mit. Achtung bei Klassennamen im
 *       Inhalt: Version 5 schreibt "fas fa-…", Version 6 "fa-solid fa-…".
 * ---------------------------------------------------------------------------
 */


/* ===========================================================================
   GESTALTUNGSWERTE - der eine Ort für Radien, Rahmen, Schatten, Übergänge
   ---------------------------------------------------------------------------
   Angelegt am 04.08.2026. Das ausführliche Konzept mit Begründungen und
   Messwerten steht in projekte\website\unterlagen\gestaltungsregeln.md.

   WARUM EIGENE NAMEN mit dem Vorsatz "fw-" (Fahrrad Wittstock), obwohl das
   Template 267 eigene Variablen mitbringt: Die Namen des Herstellers gehören
   ihm und können sich beim nächsten Update ändern. Die Namen hier sind der
   EINE Ort zum Nachziehen, falls das passiert.

   WAS HIER NICHT STEHT: die Firmenfarbe. Sie steht in der
   Template-Konfiguration (Anpassung -> Stil) und wird über
   var(--template-primary-color) geholt. Eine Farbänderung bleibt damit ein
   Feld in der Verwaltung.

   VOR EINER ÄNDERUNG hier: Es ändert sich die ganze Seite auf einmal. Das ist
   der Zweck - aber danach gehört ein Blick auf mehrere Seiten, nicht nur auf
   die, an der man gerade arbeitet.
   =========================================================================== */

:root {
    /* Ecken. Zwei Stufen, weil dieselbe Rundung auf einem 40 px hohen Knopf
       und auf einem bildschirmhohen Panel nicht gleich WIRKT.
       .25rem sind bei der Grundschrift von 14 px genau 3,5 px. */
    --fw-radius: .25rem;         /* alles Bedienbare und alle Kästen */
    --fw-radius-gross: .5rem;    /* nur was von unten einfährt: Panel, Dialog */
    --fw-radius-rund: 50%;       /* nur echte Kreise: Lagerampel, Zählerblase */

    /* Rahmen. 2px für Bedienelemente ist keine neue Erfindung, sondern der
       gemessene Mehrheitswert - 32 von 35 berandeten Knöpfen und 24 von 31
       Feldern hatten ihn schon (--btn-border-width des Templates). */
    --fw-rand: 1px;              /* Kästen, Karten, Trennlinien */
    --fw-rand-stark: 2px;        /* Knöpfe und Eingabefelder */

    /* Eine Linienfarbe statt bisher vier (#e6e6e6, #f2f2f2, #ececec,
       rgba(0,0,0,.08)). Sichtbar wurde das dort, wo zwei aneinanderstießen. */
    --fw-linie: var(--border-color, #dfe3e7);

    /* Schatten. Knöpfe bekommen keinen - ein Knopf ist durch Fläche, Rahmen
       und Beschriftung erkennbar. Der Schatten bleibt dem vorbehalten, was
       tatsächlich über der Seite schwebt. */
    --fw-schatten-klein: 0 .125rem .25rem rgba(0, 0, 0, .075);
    --fw-schatten: 0 .5rem 1rem rgba(0, 0, 0, .15);

    /* Kurz und nur für Farben. "transition: all" wird NICHT benutzt: Es zieht
       auch Größen und Positionen mit - daher kam das Hüpfen des
       Widerrufs-Knopfes beim Überfahren. */
    --fw-uebergang: .15s ease-in-out;

    /* Für Flächen, die auf- und zufahren - bisher nur die Filterspalte am
       Schreibtisch. ERGÄNZT am 04.08.2026 (Aufgabe 70).
       Warum länger als der Farbübergang: 150 ms sind zu wenig, um eine 324 px
       breite Spalte als Bewegung zu lesen; es sähe aus wie ein Springen mit
       Nachzieheffekt. Über etwa 300 ms wirkt es zäh. */
    --fw-uebergang-flaeche: .25s ease-in-out;

    /* Eine Fingerkuppe trifft rund 40 px. Am AGB-Kästchen ist das schon
       einmal aufgefallen: 13 px groß, der Link 7 px daneben - beim Ankreuzen
       ging regelmäßig das AGB-Fenster auf. */
    --fw-tippflaeche: 40px;
}


/* --- Knöpfe ----------------------------------------------------------------
   ES WIRD NUR DIE VARIABLE GESETZT, nicht die Eigenschaft. Das Template
   schreibt in seiner eigenen .btn-Regel
       border-radius: var(--btn-border-radius);
   und liest damit selbst hier nach. Eine Zeile wirkt so auf jeden Knopf, auch
   auf die, die es heute noch nicht gibt.

   Der Gegenentwurf wäre gewesen, alle Knopfklassen aufzuzählen und mit
   !important zu überschreiben. Das müsste bei jedem neuen Knopf erweitert
   werden und blockiert spätere Anpassungen.
   --------------------------------------------------------------------------- */
.btn {
    --btn-border-radius: var(--fw-radius);
    --btn-border-width: var(--fw-rand-stark);
    /* Das Template gibt Knöpfen einen eingesetzten Lichtrand
       (inset 0 1px 0 rgba(255,255,255,.15)) - eine Bootstrap-2-Optik, die auf
       dem dunklen Blau als schmutziger Streifen erscheint. */
    --btn-box-shadow: none;
    transition: color var(--fw-uebergang), background-color var(--fw-uebergang),
                border-color var(--fw-uebergang);
}


/* --- Die Tastatur-Markierung ------------------------------------------------
   DER WICHTIGSTE PUNKT DIESER DATEI.

   Am 04.08.2026 mit echtem Tastendruck gemessen: Ein .btn, mit der
   Tabulatortaste angesteuert, stand auf outline:none OHNE Ersatz. Die Prüfung
   auf :focus-visible traf zu - sichtbar war trotzdem nichts. Ein gewöhnlicher
   Link zeigte dagegen den Ring des Browsers. Wer ohne Maus arbeitet, sah also
   nicht, wo er steht.

   WARUM :focus-visible UND NICHT :focus
   :focus zeigt den Ring auch nach einem Mausklick. Das sieht nach einem Fehler
   aus - und genau deshalb wurde er früher vielerorts abgeschaltet, womit die
   Tastaturbedienung mit verschwand. :focus-visible zeigt ihn nur, wenn der
   Browser erkennt, dass ohne Maus gearbeitet wird. Damit ist beides zu haben.

   WARUM outline UND NICHT box-shadow
   Ein outline belegt keinen Platz im Layout, verschiebt also nichts. Und er
   bleibt sichtbar, wenn eine andere Regel den Schatten überschreibt. Der Ring
   folgt dabei von selbst der Eckenrundung des Elements.

   WER DIESE REGEL LÖSCHT, macht die Seite ohne Maus unbedienbar - und es fällt
   niemandem auf, der eine Maus benutzt.
   --------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
.cf_flt_header:focus-visible,
.proopc-btn:focus-visible {
    outline: var(--fw-rand-stark) solid var(--template-primary-color, #004494);
    outline-offset: 2px;
}

/* In der oberen Leiste und im Fußbereich steht der Ring auf dunklem Grund -
   dort wäre das Firmenblau unsichtbar. Deshalb dort weiß. */
.top-bar-content a:focus-visible,
.footer-area a:focus-visible,
.top-right a:focus-visible {
    outline-color: #ffffff;
}


/* ===========================================================================
   Lagerampel - die farbigen Punkte vor "auf Lager"
   Das neue Template benutzt dieselben Klassennamen wie das alte und zusätzlich
   .low-stock. Deshalb greifen diese Regeln unverändert.
   =========================================================================== */

span[class*="-stock"]:before {
    content: '';
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: inline-block;
    margin-right: 5px;
}

.normal-stock:before { background-color: #05a54b; }  /* auf Lager */
.no-stock:before     { background-color: grey;    }  /* nicht auf Lager */
.depot-stock:before  { background-color: orange;  }  /* Zentrallager, 5-10 Tage */
.low-stock:before    { background-color: #f0ad4e; }  /* neu in vp_neoteric: Restbestand */

.product-inner span[class*="-stock"] { padding-left: 10px; }


/* ===========================================================================
   Preise
   =========================================================================== */

/* Erzeugt das "UVP" vor dem Streichpreis. Ohne diese Regel steht dort nur eine
   durchgestrichene Zahl ohne Erklärung. */
span.PricebasePriceWithTax::before {
    content: "UVP ";
}

.product-price-before-discount {
    text-decoration: none;
    font-size: 12px;
    padding-right: 10px;
}


/* ===========================================================================
   Custom Fields For All - die Knöpfe für Rahmenhöhe und andere Auswahlfelder
   =========================================================================== */

.cf4all_button {
    border: var(--fw-rand-stark) solid #cdd3d9 !important;
    border-radius: var(--fw-radius) !important;
    /* Die Erweiterung legt einen weichen dunklen Schatten (0 0 4px rgba(10,10,10,.5))
       um diese Knöpfe - der einzige Schatten dieser Art auf der Seite. Nach den
       Gestaltungsregeln tragen Knöpfe keinen Schatten; die Auswahl wird über
       Rahmen und Fläche angezeigt, und das tut sie weiter unten bereits. */
    box-shadow: none !important;
}

.cf4all_button:hover {
    background-color: white !important;
    box-shadow: none;
    border: var(--fw-rand-stark) solid #848484 !important;
}

.cf4all_buttons input[type="radio"]:checked + label,
.cf4all_buttons input[type="checkbox"]:checked + label,
.cf4all_color_buttons input[type="radio"]:checked + label,
.cf4all_color_buttons input[type="checkbox"]:checked + label {
    background-color: white;
    border: var(--fw-rand-stark) solid var(--template-primary-color) !important;
    box-shadow: none;
}

.cf4all_no_color_btn {
    background-color: transparent !important;
}

.cf4all_button::before {
    content: '';
    width: 4px;
    height: 28px;
    position: absolute;
    margin: -7px 0 0 -11.5px;
    border-top-left-radius: 1.5px;
    border-bottom-left-radius: 1.5px;
}

/* Abstand am "Größe ermitteln"-Knopf neben der Feldbeschriftung */
.modal-span { padding-left: 0.3em; }


/* ===========================================================================
   Custom Filters
   ---------------------------------------------------------------------------
   BERICHTIGUNG vom 30.07.2026: Am 29.07. stand hier, das Markup habe sich
   geändert. Das war falsch. Custom Filters gibt unter vp_neoteric exakt
   dieselben Klassen aus wie vorher - cf_flt_wrapper, cf_wrapper_inner,
   headexpand. Die senkrechte Darstellung entstand allein dadurch, dass diese
   Regeln fehlten.
   =========================================================================== */

/* NICHT übernommen: .cf-searchmod-input { width: 100% !important; }
   Im alten Template füllte das Suchfeld damit die Spalte. Unter vp_neoteric
   sprengt es die Zeile: das Feld nimmt die volle Breite, der Knopf "SUCHE"
   rutscht darunter. Am 29.07.2026 am Bild festgestellt und wieder entfernt. */

.cf_breadcrumbs_wrapper { margin-top: 1em; }

/* ---------------------------------------------------------------------------
   Die Filter stehen in der linken Seitenspalte
   ---------------------------------------------------------------------------
   GEÄNDERT am 03.08.2026. Vorher war das hier eine waagerechte Leiste über den
   Produkten, aus der sich die Liste schwebend öffnete. Das war für FÜNF Filter
   gebaut und dafür auch richtig.

   Seit die Artikelmerkmale aus der Warenwirtschaft filterbar sind, sind es in
   der Kategorie E-Bike FÜNFUNDZWANZIG - am 03.08.2026 gezählt. Als Leiste
   ergäbe das drei Zeilen graue Kästchen am Schreibtisch und neun auf dem Handy,
   bevor das erste Rad zu sehen ist.

   Modul 115 steht deshalb jetzt in der Position "left". Das Template gibt sie
   als <aside id="left-aside"> aus und rechnet die Breiten selbst aus
   (index.php:126-137): links belegt und rechts leer ergibt col-lg-3 für die
   Spalte und col-lg-9 für den Inhalt. An index.php ist NICHTS geändert.

   WORAN DIESE REGELN HÄNGEN - und warum das anders ist als vorher:
   an #left-aside und .aside-inner. Beides steht im Template und ist dort
   nachlesbar.

   Vorher hing der halbe Abschnitt an der Klasse cf_formtoolbar-inner, die es
   in keiner Datei gibt: Die Modulvorlage schreibt
   class="cf_form<?= moduleclass_sfx ?>" - OHNE Leerzeichen dazwischen
   (mod_cf_filtering/tmpl/default.php:69 und :74). Aus dem Modulzusatz
   "toolbar-inner clearfix" wurde so die Klasse cf_formtoolbar-inner.
   Der Zusatz lautet jetzt " shopfilter", MIT FÜHRENDEM LEERZEICHEN, und daraus
   wird sauber class="cf_form shopfilter".
   Der Fallstrick besteht weiter - wer den Zusatz ändert, ändert Klassennamen.
   Er trägt hier nur nichts Wichtiges mehr.
   --------------------------------------------------------------------------- */

/* Die beiden folgenden Regeln betreffen seit dem Umzug NICHT mehr die Filter.
   In der Position content-top-horizontal steht jetzt nur noch Modul 154
   (der Textblock der Startseite) - dort wirken sie weiter, und deshalb bleiben
   sie stehen. Sie zu löschen würde die Abstände auf der Startseite verändern,
   ohne dass das mit den Filtern etwas zu tun hätte. */
.content-top-horizontal-section { margin-top: 0; }
.main-section:has(.content-top-horizontal-section) { padding-top: 18px; }

/* Die Modulhülle bringt mb-5 mit (html/layouts/chromes/block.php). In einer
   Spalte ist das zu viel, und im Handy-Panel entstünde darunter ein leerer
   Streifen über dem Knopf. */
#left-aside .mod-block { margin-bottom: 0; }

/* --- Die Platzhalter, solange die Filter unterwegs sind --------------------
   Das Modul lädt asynchron; der Server schickt die Spalte LEER und der
   Ajax-Aufruf bringt die 25 Filter nach. Ohne Platzhalter springt die Spalte
   von null auf halbe Bildschirmhöhe, und die Produkte daneben rutschen mit.
   Deshalb steht filter_placeholders am Modul auf 1.

   WAS DER HERSTELLER LIEFERT UND WAS FEHLT: Er bringt die Kästen samt einer
   Schimmer-Bewegung mit (.cf-placeholder-loading), aber der Verlauf besteht
   aus Weißtönen mit 5 bis 60 % Deckkraft - auf weißem Grund ist das praktisch
   unsichtbar. Am 03.08.2026 nachgesehen: die Spalte blieb leer, obwohl sechs
   Platzhalter im Quelltext standen. Es fehlt schlicht die Grundfarbe, auf der
   der Schimmer laufen soll. Die kommt hier dazu.
   --------------------------------------------------------------------------- */
.filter-placeholder__title,
.filter-placeholder__option {
    background-color: #ececec;
    border-radius: var(--fw-radius);
    /* Der Hersteller setzt am Schimmer left: -45%; ohne eigene Breite bliebe
       der Kasten dadurch zur Hälfte ausserhalb der Spalte. */
    position: relative;
    left: 0;
}

/* Der Titel-Platzhalter steht für eine Überschrift, nicht für eine ganze
   Zeile - sonst sieht die Spalte aus wie ein Absatz Fließtext. */
.filter-placeholder__title { width: 60%; }

.filter-placeholder { margin-bottom: 18px; }

/* Ein Filter: Block über die volle Spaltenbreite, durch eine Linie getrennt.
   Der frühere graue Kasten stammt aus der Leiste, wo er die Filter
   nebeneinander abgrenzte; untereinander ergäbe er eine unruhige Treppe. */
.cf_flt_wrapper {
    padding: 0;
    border-bottom: var(--fw-rand) solid var(--fw-linie);
}

/* Beschriftung links, Pfeil rechts. In einer Leiste stand der Pfeil direkt
   hinter dem Wort; in einer Spalte gehört er an den rechten Rand, sonst
   flattert er je nach Wortlänge im Nirgendwo.
   Der Hersteller gibt den Pfeil als ERSTES Kind aus - ohne das order stünde er
   links vor der Beschriftung. */
/* ZU DEN WAAGERECHTEN WERTEN - sie gehören zusammen und dürfen nicht einzeln
   geändert werden. ERGÄNZT am 04.08.2026 auf Meldung des Anwenders:
   "wenn der Fokus auf der Filteroption liegt, ist der Text links ohne Abstand -
   erst erkennbar, wenn die Hintergrundfarbe wechselt."

   WAS DAHINTERSTECKT: Die Erweiterung legt beim Überfahren eine graue Fläche
   unter den Filterkopf (.cf_flt_header:hover, #eaeaea). Solange nichts gefärbt
   ist, fällt nicht auf, dass der Innenabstand waagerecht 0 war - gemessen am
   04.08.2026 begannen Kopfrand UND Beschriftung bei exakt 14 px. Mit der
   grauen Fläche klebte die Schrift dann an deren Kante.

   DER INNENABSTAND ALLEIN GENÜGT NICHT: Er würde die Beschriftung gegenüber
   allem anderen in der Spalte einrücken - gegen die Überschrift "Filter", gegen
   die Kästchen der Filterlisten. Der negative Außenabstand nimmt ihn wieder
   zurück: Im Ruhezustand steht alles wie vorher, nur die graue Fläche ist
   breiter als die Schrift. Wer eine der beiden Zahlen ändert, ändert beide.

   Dasselbe Paar steht im Handy-Block weiter unten noch einmal, dort mit
   größerem senkrechtem Abstand. */
.cf_flt_header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5em;
    padding: .75em .5em;
    margin: 0 -.5em;
    font-size: 1.05em;
    cursor: pointer;
}

.cf_flt_header .headexpand { order: 2; flex: 0 0 auto; }

.cf_flt_header:hover { color: var(--template-primary-color, #004494); }

/* Die aufgeklappte Liste steht jetzt IM FLUSS statt zu schweben. In einer
   Spalte ist das richtig: die Filter darunter rücken nach, nichts verdeckt
   etwas, und es braucht keinen Bezugsrahmen und keinen z-index mehr. */
.cf_wrapper_inner {
    color: #333333;
    position: static;
    z-index: auto;
    min-width: 0;
    box-shadow: none;
    padding: 0 0 .8em 0;
}

/* Ein Eintrag der Filterliste: Kästchen und Beschriftung nebeneinander, auf
   gleicher Höhe, und die ganze Zeile ist antippbar.

   WARUM NICHT ÜBER DIE ZEILENHÖHE: Die stand hier auf 2.8em (= 39 px), damit
   die Zeilen auf dem Handy groß genug zum Tippen sind. Die Beschriftung wird
   in einer so hohen Zeile mittig gesetzt, das Kästchen sitzt aber oben - am
   30.07.2026 als Versatz von 9 px gemessen.
   Jetzt macht flexbox die Ausrichtung, die Tippfläche kommt über min-height.
   Beides ist voneinander unabhängig; der Versatz kann so nicht zurückkommen. */
.cf_filters_list li {
    line-height: 1.4;
    border-bottom: var(--fw-rand) solid var(--fw-linie);
}

.cf_filters_list li .form-check {
    display: flex;
    align-items: center;
    gap: .6em;
    /* Bootstrap rückt das Kästchen über padding-left und einen negativen
       Aussenabstand ein. Beides stört im Flexbox-Aufbau. */
    padding-left: 0;
    margin: 0;
    /* So hoch wie die Zeile vorher war - die Tippfläche bleibt erhalten. */
    min-height: 2.8em;
}

.cf_filters_list li .form-check .form-check-input {
    float: none;
    margin: 0;
    /* Nicht schrumpfen lassen, wenn die Beschriftung lang wird. */
    flex: 0 0 auto;
}

/* Die Beschriftung füllt den Rest der Zeile. Dadurch trifft ein Fingertipp
   irgendwo in der Zeile - nicht nur das 14 Pixel große Kästchen. */
.cf_filters_list li .form-check label {
    flex: 1 1 auto;
    margin: 0;
    cursor: pointer;
}

/* Einträge OHNE Kästchen: das sind im Warengruppenbaum die Gruppen, die
   Unterpunkte haben (Klasse cf_parentLi). Die Erweiterung gibt sie ohne
   .form-check aus - sie bekamen deshalb die Mindesthöhe von oben nicht ab und
   liefen nur auf Zeilenhöhe. Im Baum stehen beide Sorten abwechselnd
   untereinander; der Zeilenrhythmus sprang dadurch sichtbar.

   Der Wert muss mit dem der .form-check-Regel oben übereinstimmen - und ebenso
   im Handy-Block weiter unten, wo dort 3.2em steht. Wer einen ändert, ändert
   beide, sonst kommt der Versatz auf einer der beiden Breiten zurück.

   Das gap ersetzt den Leerraum zwischen Beschriftung und Trefferzahl: In einem
   Flex-Behälter fällt der Zeilenumbruch im Quelltext weg, der bei den Einträgen
   MIT Kästchen für den Abstand sorgt. Ohne gap klebte "(228)" am Namen. */
.cf_filters_list li.cf_parentLi {
    display: flex;
    align-items: center;
    gap: .25em;
    min-height: 2.8em;
}

.cf_filters_list_li .cfLiLevel:hover { background-color: #f2f2f2; }

/* Der Pfeil im Filterkopf bleibt dem Hersteller überlassen.
   ENTFERNT am 30.07.2026: hier standen vier übernommene Altregeln, die aus dem
   Pfeil im zugeklappten Zustand ein Kästchen mit 1em Innenabstand machten
   (rund dreifache Breite) und im aufgeklappten ein blaues 29-px-Feld mit "x",
   um 29 px nach unten geschoben.
   Folge: Der Filter änderte beim Anklicken seine Breite. Am Schreibtisch war
   das ein Zucken, auf dem Handy verschob sich die ganze Leiste.
   Der Hersteller gibt den Pfeil als 1em-Kästchen mit Chevron aus und dreht ihn
   im zugeklappten Zustand um 90 Grad - gleiche Größe in beiden Zuständen, also
   kein Sprung. Genau dabei bleibt es jetzt.
   Wer hier wieder etwas einträgt: Breite und Höhe müssen in BEIDEN Zuständen
   gleich bleiben, sonst kommt das Verschieben zurück. */

/* ENTFERNT am 03.08.2026: die Schaltfläche .cf-fertig, die user.js früher in
   JEDE aufgeklappte Filterliste einhängte. Sie war nötig, solange auf dem Handy
   jeder einzelne Filter als eigenes Overlay von unten kam - ohne sie war nicht
   ersichtlich, wie man es wieder zumacht.
   Jetzt kommt das ganze Panel von unten, und es hat EINEN Abschluss am Fuß
   ("Ergebnisse anzeigen") statt einen je Filter. Der zugehörige Einhänge-Block
   in user.js ist mit entfallen. */

span.cf_clear { display: inline-block; width: 100%; }

span.cf_clear a {
    color: var(--template-primary-contrast-color, white);
    background-color: var(--template-primary-color, #004494);
    display: block;
    width: auto;
    float: right;
    padding: 0 0.3em;
}

/* Die blauen Kästchen der gewählten Filter und der Knopf "Alles zurücksetzen".
   ACHTUNG bei der Schriftfarbe: .cf_tag allein (Spezifität 0-1-0) verliert
   gegen die Template-Regel für Links in der Brotkrumenleiste (0-1-1) - die
   Beschriftung wurde dadurch grau (#777777) auf blauem Grund, also kaum
   lesbar. Deshalb steht hier a.cf_tag statt .cf_tag, und die innere
   Beschriftung wird ausdrücklich mitgenommen.

   Diese Regeln stehen bewusst VOR dem Handy-Block weiter unten, damit der die
   Größen überschreiben kann. */
a.cf_tag,
a.cf_tag .cf_tag_inner,
.cf_resetAll_link {
    display: inline-block;
    background-color: var(--template-primary-color, #004494);
    color: var(--template-primary-contrast-color, white);
    opacity: 0.85;
    text-decoration: none;
    border: var(--fw-rand) solid transparent;
    border-radius: var(--fw-radius);
    font-size: 15px;
}

/* Der innere Teil sitzt im blauen Kästchen - er braucht keinen eigenen
   Hintergrund und keinen Rahmen, nur die Schriftfarbe von oben. */
a.cf_tag .cf_tag_inner {
    background-color: transparent;
    border: 0;
    opacity: 1;
}

a.cf_tag:hover,
a.cf_tag:focus {
    background-color: var(--template-primary-hover-color, #333333);
    color: var(--template-primary-hover-contrast-color, white);
}

a.cf_tag:hover .cf_tag_inner,
a.cf_tag:focus .cf_tag_inner {
    color: var(--template-primary-hover-contrast-color, white);
}

.cf_resetAll_link {
    /* Oben und unten kein Innenabstand, die Höhe macht min-height. Sonst ist
       der Knopf 45 px hoch, die Filter daneben 42 - am 30.07.2026 gemessen.
       42 px ist die Höhe der Filter. Wird deren Schriftgröße geändert,
       ist dieser Wert nachzuziehen. */
    padding: 0 1em !important;
    margin: 0 0 0 0.5em !important;
    min-height: 42px;
    display: inline-flex;
    align-items: center;
}

.cf_resetAll_link:hover {
    color: black;
    background-color: #E6E6E6;
}

span.cf_clear a:hover,
span.cf_clear a:focus {
    background-color: var(--template-primary-hover-color, #333333);
    color: var(--template-primary-hover-contrast-color, white);
}

/* Trefferzahl neben dem Filternamen etwas zurücknehmen. */
.cf_flt_counter { opacity: .7; font-weight: normal; }

/* --- Schreibtisch ab 992 px: die Spalte fährt mit und lässt sich wegklappen -
   Bei 449 E-Bikes auf 38 Seiten wäre eine Spalte, die nach dem ersten Bildlauf
   aus dem Bild wandert, nur halb so nützlich. position: sticky hält sie da.
   --------------------------------------------------------------------------- */
@media (min-width: 992px) {
    /* Der Fuss gehoert nur ins Panel.
       Bootstrap blendet oberhalb der Grenze seinen EIGENEN .offcanvas-header
       aus - von .shopfilter-fuss weiss es nichts, das ist unsere Klasse. Ohne
       diese Regel klebte "Ergebnisse anzeigen" am Schreibtisch unter der
       Spalte. Am 03.08.2026 im Nullfall aufgefallen, wo die kurze Spalte den
       Knopf sichtbar machte - bei 25 Filtern stand er weit unterhalb des
       Bildes und wäre lange unbemerkt geblieben. */
    .shopfilter-fuss { display: none; }

    /* Die Kopfzeile dagegen wird wieder eingeblendet: sie gibt der Spalte die
       Überschrift "Filter". Bootstrap versteckt sie oberhalb der Grenze, weil
       sie dort das Schliesskreuz trägt - und genau das bleibt verborgen. */
    #left-aside .offcanvas-header {
        display: flex;
        align-items: center;
        padding: 0 0 .6em 0;
        border-bottom: var(--fw-rand-stark) solid var(--template-primary-color, #004494);
        margin-bottom: .2em;
    }

    #left-aside .offcanvas-header .btn-close { display: none; }

    /* KLEBEN MUSS DIE GANZE SPALTE, nicht nur die Liste darin.
       Erster Versuch am 03.08.2026 war sticky auf .aside-inner - dann scrollt
       die Überschrift weg, während die Liste stehenbleibt. Kopf und Liste sind
       Geschwister, kleben muss also ihr gemeinsamer Kasten.

       align-self ist dabei der Punkt, an dem es sonst still scheitert: Eine
       Rasterzelle wird von .row auf volle Höhe gestreckt (align-items:
       stretch). Ein Element, das so hoch ist wie sein Behälter, kann nicht
       kleben - sticky bliebe wirkungslos, ohne dass etwas kaputt aussieht. */
    #left-aside {
        position: sticky;
        /* Lässt die Kopfleiste frei (rund 70 px). */
        top: 80px;
        align-self: flex-start;
        max-height: calc(100vh - 100px);
        display: flex;
        flex-direction: column;
    }

    /* Gescrollt wird nur die Liste - die Überschrift bleibt oben stehen.
       25 Filterköpfe sind höher als jedes Fenster.

       HIER KEIN -webkit-overflow-scrolling: touch. Mobile Browser machen aus
       einem so ausgezeichneten Behälter einen eigenen Stapelkontext und
       sperren position:fixed-Kinder darin ein; das hat am 30.07.2026 einen Tag
       gekostet. Die Eigenschaft ist seit iOS 13 überflüssig. */
    #left-aside .aside-inner {
        overflow-y: auto;
        min-height: 0;   /* sonst schrumpft ein Flex-Kind nicht unter seinen Inhalt */

        /* Abstand zur Bildlaufleiste. ERGÄNZT am 04.08.2026 (Aufgabe 70).
           Gemessen: Der Inhalt endete bei 294,8 px, die Bildlaufleiste begann
           bei 295 px - die Filterzeilen, die Trennlinien und vor allem das
           Feld "Suche in den Optionen" stießen ohne jeden Abstand daran.
           Im Handy-Panel fiel das nicht auf, weil dort weiter unten schon
           padding: 0 1em steht; deshalb war nur der Schreibtisch betroffen.

           NUR RECHTS: Links steht die Spalte bündig zum Seiteninhalt darunter
           - ein Innenabstand dort würde die Filter gegenüber dem Rest der
           Seite einrücken. Der Wert ist derselbe wie im Panel (1em = 14 px). */
        padding-right: 1em;

        /* ZURÜCK AUF BLOCK, und das ist keine Kosmetik.
           .aside-inner trägt die Bootstrap-Klasse .offcanvas-body, und die ist
           display: flex. Ihre Kinder werden dadurch zu Flex-Elementen in einer
           ZEILE und schrumpfen auf ihre Inhaltsbreite.

           Mit den fertigen Filtern fällt das nicht auf - Beschriftungen und
           Kästchen bringen eine Eigenbreite mit. Die LADEPLATZHALTER bringen
           keine: sie sind leere <div> und wurden dadurch 0 Pixel breit. Am
           03.08.2026 gemessen, die ganze Elternkette von .filter-placeholder
           bis .mod-position-left stand auf 0 - sichtbar war nur nichts.

           Die Spalte selbst ist der Flex-Behälter (siehe oben), damit die
           Überschrift stehenbleibt und nur die Liste scrollt. Hier drin wird
           wieder gestapelt wie gewohnt. */
        display: block;
    }

    /* Eine einzelne Liste darf die Spalte nicht sprengen - Hersteller hat 78
       Werte. Zwei Bildlaufleisten ineinander sind nicht schön, aber besser als
       ein Filter, der alle anderen aus dem Bild schiebt. */
    .cf_wrapper_inner { max-height: 45vh; overflow-y: auto; }

    /* --- Spalte weggeklappt ------------------------------------------------
       Der Knopf über den Produkten setzt die Klasse am <body>; die
       Rasterklassen kommen vom Server (col-lg-3 / col-lg-9) und werden hier
       überschrieben. Es wird NICHTS im Seitenbaum verschoben - die Erweiterung
       baut ihre Anfrage mit new FormData(form), und was aus dem Formular
       herauswandert, wird stillschweigend nicht mehr mitgeschickt.

       DIE MEDIA-QUERY IST PFLICHT, nicht Kosmetik: Der Zustand steht in
       localStorage und gilt im selben Browser geräteübergreifend. Stünde das
       Wegklappen ohne Klammer, wäre auf dem Handy das ganze Panel weg,
       sobald jemand am Schreibtisch einmal zugeklappt hat.

       GEÄNDERT am 04.08.2026 (Aufgabe 70): Vorher stand hier schlicht
       display: none - die Spalte war von einem Bild auf das nächste weg, und
       die Produkte sprangen dabei um eine Kachelbreite nach links. Jetzt fährt
       sie zu.

       WARUM NICHT display ANIMIERT WIRD: display kennt keine Zwischenwerte,
       ein Übergang darauf tut schlicht nichts. Animiert wird stattdessen die
       BREITE - und zwar über "width", nicht über flex-basis:

         Die Rasterklasse col-lg-3 des Templates setzt "flex: 0 0 auto" und
         "width: 25%". Ein Übergang von flex-basis "auto" auf einen Wert
         animiert NICHT (auto hat keinen Zwischenwert), ein Übergang von
         width 25% auf 0 dagegen schon. Deshalb rechnen alle Regeln hier mit
         width - und deshalb steht der Ausgangswert NICHT hier: er kommt vom
         Template. Wer die Spaltenbreite ändert, ändert die Rasterklasse; hier
         ist nichts nachzuziehen.

       min-width: 0 IST PFLICHT. Ein Flex-Element hat min-width: auto und
       lässt sich nicht unter seine Inhaltsbreite verkleinern - die Spalte
       bliebe trotz width: 0 rund 300 px breit. Dieselbe Falle wie beim Logo
       weiter unten.

       visibility gehört dazu, damit die zugeklappte Spalte nicht mehr mit der
       Tabulatortaste erreichbar ist. Sie wechselt beim Aufklappen sofort auf
       sichtbar und beim Zuklappen erst am Ende der Bewegung - genau richtig,
       ohne dass dafür etwas zu rechnen wäre. */
    #left-aside {
        transition: width var(--fw-uebergang-flaeche),
                    max-width var(--fw-uebergang-flaeche),
                    padding var(--fw-uebergang-flaeche),
                    opacity var(--fw-uebergang-flaeche),
                    visibility var(--fw-uebergang-flaeche);
    }

    .filterspalte-zu #left-aside {
        width: 0;
        max-width: 0;
        min-width: 0;          /* siehe Kommentar oben - ohne das wirkt width: 0 nicht */
        padding-left: 0;
        padding-right: 0;
        opacity: 0;
        visibility: hidden;
        /* Solange die Spalte zufährt, ragte ihr Inhalt sonst über die
           schrumpfende Breite hinaus und legte sich über die Produkte. */
        overflow: hidden;
    }

    #left-aside ~ #content {
        transition: width var(--fw-uebergang-flaeche);
    }

    .filterspalte-zu #left-aside ~ #content {
        width: 100%;
    }

    /* Das Produktraster an die schmalere Spalte anpassen.
       VirtueMart steht auf products_per_row = 4, der Override macht daraus
       col-lg-3. Neben der Filterspalte blieben davon bei 1600 px Inhaltsbreite
       rund 300 px je Kachel statt 400 - deshalb hier drei je Zeile, und bei
       weggeklappter Spalte wieder vier.

       Der Geschwister-Selektor greift nur, wo die Spalte überhaupt im
       Seitenbaum steht, also auf Kategorieseiten. Er findet #left-aside auch
       dann noch, wenn es zugeklappt ist - darum wirkt die zweite Regel.

       DASS DIE KACHELN MITWANDERN, IST DER TRICK an der ganzen Bewegung:
       Drei Kacheln in 75 % Breite und vier Kacheln in 100 % Breite sind
       GLEICH BREIT (0,75/3 = 0,25). Laufen beide Übergänge gleich lang, bleibt
       die einzelne Kachel während der ganzen Bewegung fast unverändert breit -
       es rutscht nur die vierte von unten herauf. Ohne den Übergang hier
       würden die Kacheln erst schmal werden und dann wieder wachsen. */
    #left-aside ~ #content .product-grid-view {
        width: 33.3333%;
        max-width: 33.3333%;
        transition: width var(--fw-uebergang-flaeche),
                    max-width var(--fw-uebergang-flaeche);
    }

    .filterspalte-zu #left-aside ~ #content .product-grid-view {
        width: 25%;
        max-width: 25%;
    }

    /* Wer im Betriebssystem "Bewegung reduzieren" eingestellt hat, bekommt
       keine. Das ist keine Höflichkeit: Bei einer Gleichgewichtsstörung lösen
       großflächige Bewegungen echte Übelkeit aus. Das Ergebnis ist dasselbe,
       nur sofort. */
    @media (prefers-reduced-motion: reduce) {
        #left-aside,
        #left-aside ~ #content,
        #left-aside ~ #content .product-grid-view {
            transition: none;
        }
    }
}

/* --- Handy unter 992 px: die Spalte kommt als Panel von unten ---------------
   GEÄNDERT am 03.08.2026. Vorher stand hier ein Dreierraster grauer Kästchen,
   aus dem jeder EINZELNE Filter als eigenes Overlay von unten kam. Bei 25
   Filtern wären das neun Zeilen Kästchen, bevor das erste Rad zu sehen ist.

   ES WIRD NICHTS SELBST GEBAUT - das Template bringt das Panel mit.
   In template.css steht .offcanvas-lg.offcanvas-bottom, und zwar bei genau
   max-width: 991.98px - derselben Grenze, die user.js als HANDY_BIS führt.
   Ab 992 px hebt Bootstrap alles von selbst wieder auf.
   user.js setzt #left-aside deshalb nur die Klassen "offcanvas-lg
   offcanvas-bottom" und .aside-inner die Klasse "offcanvas-body". Im
   Seitenbaum wird nichts verschoben.

   Damit kommen von Bootstrap, statt hier gebaut zu werden:
     - die Abdunklung (z-index 1040) und das Panel (1045) - genau die Ebenen,
       die im Projekt ohnehin für Schubladen gelten. Es ist keine eigene Zahl
       zu vergeben, und der frühere Wert 2000 (über allem, auch über Dialogen)
       entfällt.
     - die Scroll-Sperre des Hintergrunds (ScrollBarHelper),
     - Schließen mit Esc und mit Klick auf die Abdunklung.

   WAS BOOTSTRAP NICHT TUT: ein offcanvas-lg schließt sich beim Vergrößern des
   Fensters über 992 px NICHT von selbst. Abdunklung und Scroll-Sperre blieben
   hängen und die Seite wäre unbedienbar. Dafür sorgt ein resize-Zuhörer in
   user.js - das ist kein Schönheitsfehler, sondern ein Totalausfall.

   ENTFALLEN ist damit auch der frühere Block, der .cf_wrapper_inner auf
   position: fixed setzte. Er MUSS weg bleiben: ein fixed-Kind im
   Scrollbehälter des Panels stellt genau die Stapelkontext-Falle wieder her,
   die oben beschrieben ist. */
@media (max-width: 991.98px) {
    /* Das Panel etwas niedriger als das Fenster, damit oben ein Streifen der
       Seite sichtbar bleibt - das hält die Orientierung, wo man gerade ist. */
    #left-aside.offcanvas-lg.offcanvas-bottom {
        height: 85vh;
        /* Nur die Oberkante wird gerundet - das Panel sitzt am unteren Rand. */
        border-radius: var(--fw-radius-gross) var(--fw-radius-gross) 0 0;
    }

    /* Die Spalte bringt als Rasterzelle den Bootstrap-Rinnenabstand mit; im
       Panel säße der Inhalt dadurch in einer zu schmalen Rinne. */
    #left-aside.offcanvas-lg { padding-left: 0; padding-right: 0; }

    #left-aside .offcanvas-header {
        border-bottom: var(--fw-rand) solid var(--fw-linie);
        padding: .9em 1em;
    }

    #left-aside .offcanvas-title { font-size: 1.15rem; font-weight: bold; margin: 0; }

    #left-aside .aside-inner { padding: 0 1em; }

    /* Im Panel scrollt der Rumpf als Ganzes. Eine zweite Bildlaufleiste je
       Filterliste wäre hier mit dem Daumen kaum zu bedienen. */
    .cf_wrapper_inner { max-height: none; overflow: visible; }

    /* Der Fuß mit "Ergebnisse anzeigen". Er braucht KEIN position: sticky mehr:
       .offcanvas-lg ist unter 992 px display:flex mit flex-direction: column,
       der Fuß ist dadurch ein echter Fuß. */
    .shopfilter-fuss {
        border-top: var(--fw-rand) solid var(--fw-linie);
        padding: .8em 1em;
        background-color: #fff;
    }

    .shopfilter-fuss button {
        display: block;
        width: 100%;
        border: 0;
        border-radius: var(--fw-radius);
        padding: .9em 1em;
        background-color: var(--template-primary-color, #004494);
        color: var(--template-primary-contrast-color, #fff);
        font-weight: bold;
        letter-spacing: .02em;
        cursor: pointer;
    }

    .shopfilter-fuss button:hover,
    .shopfilter-fuss button:focus {
        background-color: var(--template-primary-hover-color, #333333);
        color: var(--template-primary-hover-contrast-color, #fff);
    }

    /* Im Panel ist Platz - der Filterkopf darf so groß bleiben wie am
       Schreibtisch. Die frühere Verkleinerung auf .85rem samt Abschneiden
       diente allein dazu, "Lagerbestand" in ein Drittel von 387 px zu
       quetschen; das Raster gibt es nicht mehr.
       Die Tippfläche bleibt großzügig, dafür sorgt das padding weiter oben.

       DIE .5em WAAGERECHT MÜSSEN HIER STEHEN BLEIBEN. Diese Regel überschreibt
       das padding der Grundregel vollständig; stünde hier nur ".9em 0", klebte
       die Beschriftung im Panel wieder an der grauen Fläche - der negative
       Außenabstand von oben bliebe aber wirksam und zöge sie sogar noch nach
       links aus der Spalte heraus. */
    .cf_flt_header { padding: .9em .5em; }

    /* Die blauen Kästchen der bereits gewählten Filter (Modul CF Breadcrumbs).
       Sie stehen weiterhin über den Produkten, nicht im Panel - deshalb bleiben
       diese Größen unverändert.
       Der innere Teil bringt eigenen Innenabstand mit (6 px oben und unten);
       ohne dessen Rücknahme bliebe das Kästchen trotz kleinerer Schrift
       gleich hoch. */
    a.cf_tag {
        font-size: .85rem;
        padding: .35em .6em;
        margin: 0 .3em .3em 0;
    }

    a.cf_tag .cf_tag_inner {
        font-size: .85rem;
        padding: 0;
    }

    /* Auch der Abstand über den Kästchen darf knapper ausfallen.
       Die Hülle heißt hier .cf_breadcrumbs_wrapper - NICHT .cf_wrapp_all.
       Letztere gehört zum Filtermodul; das Brotkrumen-Modul benutzt einen
       eigenen Klassennamen. Ein Blick in den Seitenquelltext spart hier
       eine Fehlersuche. */
    .cf_breadcrumbs_wrapper {
        margin-top: .5em;
    }

    .cf_resetAll_link {
        padding: .5em .6em !important;
        margin: 0 !important;
        font-size: .85rem;
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        overflow: hidden;
        text-overflow: ellipsis;
        min-height: 40px;
    }

    /* ENTFERNT am 03.08.2026: hier stand .cf_wrapper_inner als
       position: fixed am unteren Rand mit z-index 2000 - das Bottom-Sheet je
       EINZELFILTER. Es ist durch das eine Panel für alle Filter ersetzt.

       DIESE REGEL DARF NICHT ZURÜCKKOMMEN. Ein position:fixed-Kind im
       Scrollbehälter des Panels stellt die Stapelkontext-Falle wieder her, die
       oben im Abschnittskopf beschrieben ist - und 2000 läge über Panel (1045)
       und Abdunklung (1040). Zum Nachmessen:
         [...document.querySelectorAll('.cf_wrapper_inner')]
             .map(e => getComputedStyle(e).position)
       darf kein "fixed" enthalten. */

    /* Größere Kästchen für den Finger. 14 Pixel sind mit der Maus zu treffen,
       mit dem Daumen nicht - besonders beim Lagerbestand-Filter, der nur eine
       einzige Zeile hat und dadurch klein und verloren unten am Rand sitzt.
       Zusammen mit der antippbaren ganzen Zeile (siehe oben) wird daraus eine
       Fläche über die volle Breite. */
    .cf_filters_list li .form-check {
        min-height: 3.2em;
        padding: 0 .2em;
    }

    /* Gegenstück zur Regel weiter oben: die Einträge ohne Kästchen wachsen auf
       dem Handy im gleichen Maß mit. */
    .cf_filters_list li.cf_parentLi {
        min-height: 3.2em;
        padding: 0 .2em;
    }

    .cf_filters_list li .form-check .form-check-input {
        width: 1.4em;
        height: 1.4em;
    }

    /* ENTFERNT am 03.08.2026: .cf-fertig, der Schließknopf je Einzelfilter.
       Seine Aufgabe erfüllt jetzt .shopfilter-fuss weiter oben - einmal für
       das ganze Panel statt fünfundzwanzigmal. */
}

/* --- Der Knopf über den Produkten ------------------------------------------
   Er hat zwei Aufgaben, je nach Breite, und user.js hängt ihn deshalb nur
   einmal ein:
     unter  992 px  öffnet er das Panel (über die Bootstrap-Data-API),
     ab     992 px  klappt er die Spalte weg und wieder auf.

   Er wird von user.js in die Werkzeugleiste über dem Raster gesetzt. Weil die
   in #bd_results liegt und bei JEDER Filterauswahl per Ajax ersetzt wird, setzt
   user.js ihn nach jedem CfResultsUpdate neu.
   --------------------------------------------------------------------------- */
.shopfilter-knopf {
    display: inline-flex;
    align-items: center;
    gap: .5em;
    padding: .55em 1.1em;
    /* Rahmenstärke wie bei jedem anderen Knopf - vorher 1px und damit als
       einziger Knopf der Werkzeugleiste dünner als seine Nachbarn. */
    border: var(--fw-rand-stark) solid var(--template-primary-color, #004494);
    border-radius: var(--fw-radius);
    background-color: transparent;
    color: var(--template-primary-color, #004494);
    font-weight: bold;
    cursor: pointer;
    transition: color var(--fw-uebergang), background-color var(--fw-uebergang);
}

.shopfilter-knopf:hover,
.shopfilter-knopf:focus {
    background-color: var(--template-primary-color, #004494);
    color: var(--template-primary-contrast-color, #fff);
}

/* Die Zahl der gesetzten Filter. Sie steht nur da, wenn wirklich etwas gewählt
   ist - eine "(0)" wäre bloß Rauschen. */
.shopfilter-knopf .shopfilter-anzahl {
    display: inline-block;
    min-width: 1.6em;
    padding: 0 .35em;
    border-radius: 1em;
    background-color: var(--template-primary-color, #004494);
    color: var(--template-primary-contrast-color, #fff);
    font-size: .8em;
    text-align: center;
}

.shopfilter-knopf:hover .shopfilter-anzahl,
.shopfilter-knopf:focus .shopfilter-anzahl {
    background-color: var(--template-primary-contrast-color, #fff);
    color: var(--template-primary-color, #004494);
}

/* ---------------------------------------------------------------------------
   Seitenblätterung umbrechen lassen
   Bei 449 E-Bikes und 12 je Seite entstehen 38 Seiten. Die Blätterleiste wird
   dadurch 542 Pixel breit und sprengt auf dem Handy die Zeile - am 30.07.2026
   im 375-Pixel-Rahmen gemessen. Sie darf umbrechen.
   --------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
    .pagination {
        flex-wrap: wrap;
        justify-content: center;
        row-gap: .3rem;
    }
}

/* VERSCHOBEN am 30.07.2026: Die Regeln für die blauen Kästchen und für
   "Alles zurücksetzen" standen hier - also HINTER dem Handy-Block. Dadurch
   hätten sie dessen Größenangaben überstimmt, zumal sie mit !important
   arbeiten. Sie stehen jetzt weiter oben, vor dem Handy-Block.
   Die Reihenfolge in dieser Datei ist kein Zufall: Bei gleicher Spezifität
   gewinnt die zuletzt geschriebene Regel. */

/* ENTFERNT am 30.07.2026: hier stand .cf_filters_list li ein zweites Mal,
   wortgleich mit der Regel weiter oben. Eine Dublette aus der Übernahme.
   Sie stand HINTER der oberen und hätte jede Änderung dort still überschrieben. */

.cf_filters_list_li .cfLiLevel:hover { background-color: #f2f2f2; }

.tree_0 {
    font-size: larger;
    text-transform: uppercase;
}


/* ===========================================================================
   Beiträge - Tabellen, Logos, Hintergründe
   Diese Regeln hängen an Klassen, die im Inhalt der Beiträge stehen, nicht am
   Template. Sie gelten unverändert weiter.
   =========================================================================== */

table.info { width: 100%; }

.info td {
    padding: 0.6em;
    text-align: center;
}

.info thead {
    background-color: #e3e3e3;
    font-weight: bold;
    font-size: larger;
}

.info tr:nth-child(even) { background-color: #f3f3f3; }

.logos div img {
    padding: 1em;
    margin: 1em;
    background-color: white;
}

.bg_white   { background-color: white; }
.pad_bot_6em { padding-bottom: 6em; }

/* Der einzige feste Firmenfarbwert, der geblieben ist: die achtstellige
   Schreibweise enthält am Ende die Deckkraft (12 = rund 7 %). Über die
   Variable ginge das nur mit color-mix(), was den Nutzen nicht rechtfertigt.
   Wird die Firmenfarbe je geändert, ist dies die eine Stelle zum Nachziehen. */
.bl div[itemprop="articleBody"] { background-color: #00449412; }
.gr div[itemprop="articleBody"] { background-color: #1a1a1a12; }
.row div[itemprop="articleBody"] { padding: 0 15px; }

.paddingtop20  { padding-top: 20px; }
.paddingtop100 { padding-top: 100px; }


/* ===========================================================================
   Bild-neben-Text in Beiträgen (Flexbox)
   =========================================================================== */

.col-text {
    height: 30em;
    display: flex;
    align-items: center;
    justify-content: center;
    border: var(--fw-rand) solid var(--fw-linie);
    border-radius: var(--fw-radius);
    background-color: #ffffffa6;
}

.grid-flex {
    display: flex;
    flex-grow: 1;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-around;
}

.col      { flex: 1; }
.col-left { order: -1; }

.Aligner-item { width: 80%; }

.col-image {
    background-size: cover;
    background-position: center center;
}

@media (max-width: 640px) {
    .grid-flex {
        height: 45em;
        flex-direction: column;
    }
    .col-left { order: 0; }
    .Aligner-item { width: 90%; }
}


/* ===========================================================================
   Widerrufs-Button im Fußbereich (gesetzlich gefordert)
   ---------------------------------------------------------------------------
   ACHTUNG: In der alten Datei war hier ein Kommentar nicht geschlossen. Die
   schließende Klammer der Regel lag dadurch im Kommentar, und der Browser
   verwarf die gesamte :hover-Regel. Am 29.07.2026 behoben - hier steht die
   berichtigte Fassung.

   Zwei Angaben waren in der alten Datei auskommentiert und sind es hier
   geblieben, weil unklar ist, ob das Absicht war: color: #ffffff und
   border-radius: 4px.
   =========================================================================== */

a.widerruf-btn {
    display: inline-flex;    /* verhindert das Strecken über die volle Breite */
    width: max-content;      /* Breite genau auf die Textlänge */
    align-items: center;
    justify-content: center;
    background-color: var(--template-primary-color, #004494);
    color: var(--template-primary-contrast-color, #ffffff);
    padding: 7px !important;
    font-weight: bold;
    text-transform: uppercase;
    border: var(--fw-rand-stark) solid var(--template-primary-color, #004494);
    border-radius: var(--fw-radius);
    /* GEÄNDERT am 04.08.2026: vorher "transition: all 0.3s ease" und ein
       Schatten. Zusammen mit dem translateY beim Überfahren war das der
       einzige Knopf der ganzen Seite, der beim Überfahren hüpfte und dabei
       seinen Schatten wechselte. Jetzt wechseln nur die Farben - wie überall
       sonst auch. Siehe unterlagen\gestaltungsregeln.md, Abschnitt 3.3. */
    transition: color var(--fw-uebergang), background-color var(--fw-uebergang),
                border-color var(--fw-uebergang);
}

/* Beim Überfahren wechselt der Knopf auf Anthrazit - so war es im alten
   Template (@btn-primary-hover-bg: #333333, Schrift blieb weiss).
   VORHER stand hier dieselbe Farbe wie im Ruhezustand: der Knopf sah beim
   Überfahren unverändert aus, nur Schatten und Position änderten sich. */
a.widerruf-btn:hover,
a.widerruf-btn:focus {
    background-color: var(--template-primary-hover-color, #333333);
    border-color: var(--template-primary-hover-color, #333333);
    color: var(--template-primary-hover-contrast-color, #ffffff) !important;
}


/* ===========================================================================
   Kleinigkeiten
   =========================================================================== */

/* Notbehelf gegen ein altes Chrome-Problem mit loading="lazy". Vor dem
   endgültigen Übernehmen prüfen, ob es noch gebraucht wird. */
.responsive-image,
.manufacturer-image { min-height: 1px; }

/* NICHT übernommen: .site-logo { max-width: 170px; }
   Das war auf das Kopfgerüst von vp_merchant abgestimmt. vp_neoteric setzt die
   Logogröße selbst; die Regel ließ das Logo sichtbar schrumpfen. Soll es
   kleiner werden, gehört das in die Template-Einstellungen, nicht hierher. */

/* Das Logo darf den Bildschirm nicht sprengen.
   ---------------------------------------------------------------------------
   Die SVG-Datei bringt eine feste Breite von 250pt mit, das sind rund 333
   Pixel. Auf einem Handy mit 390 Pixeln Breite passt das zusammen mit dem
   Menüknopf daneben nicht mehr: das Logo wird rechts abgeschnitten, die
   Symbole rechts daneben verschwinden ganz, und die Seite lässt sich seitlich
   schieben. Das Template bringt dafür keine eigene Regel mit.

   ACHTUNG, hier steckt eine Falle: "max-width: 100%" allein genügt NICHT.
   Der Kopfbereich ist ein Flex-Kasten, und Flex-Elemente lassen sich
   standardmäßig nicht unter ihre Inhaltsbreite verkleinern (min-width: auto).
   Die Prozentangabe bezieht sich dann auf einen Kasten, der selbst schon zu
   breit ist - und bewirkt nichts. Deshalb beides: min-width aufheben UND eine
   feste Obergrenze in Pixeln.

   Die Regel greift erst unter 992px; darüber gilt die zweite weiter unten. */
@media (max-width: 991.98px) {
    .mobile-header-center,
    .mobile-header-center .brand-logo {
        min-width: 0;
    }
    .mobile-header-center .logo,
    .mobile-header-center .brand-logo img {
        max-width: 190px;
        height: auto;
    }
}

/* Und auf dem Schreibtisch etwas kleiner.
   ---------------------------------------------------------------------------
   Ergänzt am 02.08.2026 auf Wunsch des Anwenders. Die SVG-Datei bringt 333 x
   120 Pixel mit, und genau so groß wurde das Logo über 992px auch dargestellt
   - es beherrschte damit die ganze Kopfzeile.

   GEÄNDERT am 04.08.2026 (Vikunja-Aufgabe 70): von 250 auf 200 Pixel, erneut
   auf Wunsch des Anwenders. Das ergibt rund 72 Pixel Höhe statt 90.

   Die Höhe wird bewusst NICHT gesetzt: "height: auto" lässt das
   Seitenverhältnis der Datei gelten. Eine feste Höhe daneben würde den
   Schriftzug verzerren, sobald das Logo einmal ausgetauscht wird.

   Wer es anders will, ändert nur diese eine Zahl. Zu beachten ist dabei nur
   der Wert im Block darüber: unter 992 px gelten 190 Pixel, damit das Logo
   neben dem Menüknopf auf ein 390-Pixel-Handy passt. Die beiden Zahlen sollten
   sich nicht überkreuzen - das Logo würde beim Verbreitern des Fensters sonst
   kleiner statt größer. */
@media (min-width: 992px) {
    .brand-logo .logo,
    .brand-logo img {
        max-width: 200px;
        height: auto;
    }
}

/* Obere Leiste (Anmelden / Mein Konto / Mein Warenkorb) umbrechen lassen.
   Dieselbe Flex-Falle wie beim Logo: die drei Einträge stehen in einer Zeile,
   die sich nicht verkleinern lässt, und "Mein Warenkorb" wird abgeschnitten.
   Ab hier dürfen sie umbrechen und werden etwas kleiner gesetzt. */
@media (max-width: 575.98px) {
    .top-right,
    .top-right .mod-inline,
    .top-right .mod-menu {
        min-width: 0;
        flex-wrap: wrap;
        justify-content: center;
    }
    .top-right { font-size: 0.8rem; }
}

.visforms div.row { margin: 5px -3px; }

.module-cont { margin-bottom: 10px !important; }

/* ===========================================================================
   Inhaltsbreite: 1600 px statt 1320 px
   ---------------------------------------------------------------------------
   Entscheidung des Anwenders am 01.08.2026, nachdem ihm die schmalere Seite
   aufgefallen war. Gemessen: Das ALTE Template (vp_merchant) lief mit
   max-width 1600px, das neue bringt 1320px mit. Die 280 px Unterschied sieht
   man, sobald der Bildschirm breiter als etwa 1700 px ist.

   ZWEI PROBLEME WERDEN MIT EINER MASSNAHME GELÖST:

   1. Die Werbebanner waren UNSCHARF. Die Bilddateien sind 1930 px breit,
      dargestellt wurden sie auf einem 3072er Bildschirm mit 3057 px - also auf
      158 % hochgerechnet. Mit der Begrenzung sind es 83 %, das Bild wird nicht
      mehr gestreckt.
   2. Die Artikelbilder waren zu klein. Die Dateien sind 420 px breit, genutzt
      wurden davon 302 px (72 %). Jetzt sind es 372 px (89 %) - größer UND
      immer noch unter 100 %, also weiterhin scharf. Über 100 % wären sie
      unscharf; deshalb ist 1600 px hier auch die sinnvolle Obergrenze.

   WARUM ZWEI REGELN NÖTIG SIND:
   Der Slider hängt NICHT im .container-xxl. Von der Bilddatei bis hinauf zu
   .site-content steht in der ganzen Elternkette "max-width: none" - er ist der
   einzige Abschnitt der Seite ohne jede Begrenzung. Wer nur .container-xxl
   ändert, verbreitert den Inhalt und lässt den Banner weiter randlos laufen;
   der Bruch zwischen beiden bliebe genau so bestehen.
   =========================================================================== */
.container-xxl {
    max-width: 1600px;
}

.slider-section {
    max-width: 1600px;
    margin-left: auto;                      /* ohne die beiden bleibt der */
    margin-right: auto;                     /* Slider linksbündig stehen  */
}

/* Diese Zeile gehört zur Verbreiterung und darf nicht ohne sie stehen.
   ---------------------------------------------------------------------------
   Ohne sie entsteht bei Fensterbreiten zwischen etwa 1600 und 1710 px ein
   waagerechter Bildlauf von rund 75 px. Gemessen (Überstand in px):
       390: 0 | 768: 0 | 1366: 0 | 1600: 90 | 1650: 73 | 1920: 0 | 3072: 0
   Es ist also ein schmales Band - aber ausgerechnet dort liegen gängige
   Notebook-Auflösungen. Verursacher sind absolut positionierte Elemente in den
   ausfahrbaren Seitenpanels (Wunschliste/Vergleich), die rechts hinausragen.
   Sie taten das vorher auch schon; erst der breitere Container schiebt sie über
   den Fensterrand.

   ES MUSS "clip" SEIN, NICHT "hidden". "hidden" erzeugt einen eigenen
   Scrollkontext und sperrt darin schwebende Elemente ein - genau daran ist in
   dieser Datei schon einmal die Filterleiste auf dem Handy gescheitert (siehe
   den Abschnitt weiter unten). "clip" schneidet nur ab und ändert am
   Scrollverhalten nichts; das senkrechte Scrollen bleibt nachweislich erhalten.

   Beide Elemente sind nötig: Am body allein wirkt es nicht, weil dann das
   html-Element weiterscrollt - nachgemessen, Überstand blieb bei 73 px. */
html,
body {
    overflow-x: clip;
}

/* ===========================================================================
   Knöpfe im Bestellabschluss (VP One Page Checkout)
   ---------------------------------------------------------------------------
   Sie kamen bisher aus dem Plugin selbst
   (plugins/system/vponepagecheckout/assets/css/dark-checkout.css) und trugen
   NICHT die Firmenfarbe: "Kaufen" türkis (#49afcd), die Knöpfe der
   Anmeldeseite dunkelgrau (#363636). Weder das alte noch das neue Template
   hat das je überschrieben - es war vorher genauso. Aufgefallen ist es erst,
   seit der Rest der Seite sauber in der Firmenfarbe steht.

   Entscheidung des Anwenders am 01.08.2026: ALLE Knöpfe in Firmenfarbe.
   Begründung: Die grauen Knöpfe stehen auf der Anmeldeseite, der "Kaufen"-Knopf
   auf der Bestellseite - sie sind nie gleichzeitig zu sehen. Ein Absetzen des
   Hauptknopfes bringt hier also nichts.

   DREI DINGE, DIE MAN WISSEN MUSS:

   1. Die Farbe steht NICHT hier, sondern kommt aus der Template-Konfiguration
      (var(--template-primary-color)). #004494 ist nur der Rückfallwert, falls
      die Variable einmal fehlt. Wird die Firmenfarbe im Template-Stil geändert,
      ziehen diese Knöpfe von selbst mit - genauso wie der Rest dieser Datei.

   2. "background-image: none" ist die eigentliche Arbeit. Das Plugin legt einen
      Farbverlauf über den Knopf. Ein Verlauf liegt VOR der Hintergrundfarbe -
      wer nur background-color setzt, ändert nichts Sichtbares und sucht dann
      lange nach dem Grund.

   3. Der Schriftschatten des Plugins (text-shadow, dunkel) ist entfernt. Auf
      dem hellen Türkis war er gedacht; auf dem dunklen Blau macht er die
      weiße Schrift schmutzig.

   WARUM ÜBERALL ZWEI KLASSEN STEHEN (.proopc-btn.proopc-btn-info):
   Gemessen am 01.08.2026: Das Plugin-CSS wird als 20. Datei geladen, diese
   hier als 11. Bei GLEICHER Genauigkeit gewinnt die spätere Datei - eine
   einfache Regel ".proopc-btn-info" hätte also nichts bewirkt. Die Knöpfe
   tragen beide Klassen (class="proopc-btn proopc-btn-info"), deshalb reicht
   das Verketten, um genauer zu sein als das Plugin. Das ist der saubere Weg;
   "!important" wäre der grobe und würde spätere Anpassungen blockieren.
   Aus demselben Grund haben die Zustandsregeln unten ebenfalls beide Klassen -
   die Plugin-Regeln für :hover und [disabled] sind selbst schon zweistufig.
   =========================================================================== */
.proopc-btn.proopc-btn-info,
.proopc-btn.proopc-btn-inverse {
    background-color: var(--template-primary-color, #004494);
    background-image: none;                 /* siehe Punkt 2 oben */
    border-color: var(--template-primary-color, #004494);
    color: var(--template-primary-contrast-color, #fff);
    text-shadow: none;
}

.proopc-btn.proopc-btn-info:hover,
.proopc-btn.proopc-btn-info:focus,
.proopc-btn.proopc-btn-info:active,
.proopc-btn.proopc-btn-info.active,
.proopc-btn.proopc-btn-inverse:hover,
.proopc-btn.proopc-btn-inverse:focus,
.proopc-btn.proopc-btn-inverse:active,
.proopc-btn.proopc-btn-inverse.active {
    background-color: var(--template-primary-hover-color, #333333);
    background-image: none;
    border-color: var(--template-primary-hover-color, #333333);
    color: var(--template-primary-hover-contrast-color, #fff);
}

/* Abgeschaltete Knöpfe müssen abgeschaltet AUSSEHEN. Das ist hier kein
   Randfall: Der "Kaufen"-Knopf wird vom Plugin ausdrücklich mit "disabled"
   ausgeliefert (default_confirm.php Zeile 38) und erst freigeschaltet, wenn
   alle Angaben vollständig sind. Ohne diese Regel trüge er von der ersten
   Sekunde an die Firmenfarbe und sähe aus wie anklickbar - im
   Bestellabschluss ist das die teuerste Art von Missverständnis. */
.proopc-btn.proopc-btn-info.disabled,
.proopc-btn.proopc-btn-info[disabled],
.proopc-btn.proopc-btn-inverse.disabled,
.proopc-btn.proopc-btn-inverse[disabled] {
    background-color: #848484;
    background-image: none;
    border-color: #848484;
    color: #ffffff;
    opacity: 0.65;
}

/* Hinweiskasten unmittelbar über dem "Kaufen"-Knopf.
   Wird von user.js eingehängt, wenn der Kaufabschluss etwas bemängelt - die
   Meldung des Checkout steht sonst ganz oben auf der Seite, am Handy über
   2500 Pixel vom Knopf entfernt (am 01.08.2026 gemessen).
   Die Farben sind dieselben wie in der Meldung oben, damit erkennbar bleibt,
   dass es dieselbe Sache ist. */
.user-kaufhinweis {
    margin: 0 0 .75rem 0;
    padding: .6rem .8rem;
    border: var(--fw-rand) solid #f5c2c7;
    border-radius: var(--fw-radius);
    background-color: #f8d7da;
    color: #842029;
    font-size: 14px;
    line-height: 1.4;
}

/* Die Schrittzeichen im Bestellvorgang in der Firmenfarbe.
   Ergänzt am 05.08.2026, damit es aussieht wie auf der Live-Seite.

   Das Plugin setzt sie schwarz:
   .proopc-step { background: #000 }   (light-checkout.css, Zeile 1057)

   WARUM DER WÄHLER ZWEISTUFIG IST: light-checkout.css wird später geladen als
   diese Datei. Eine schlichte Regel ".proopc-step" wäre gleich genau (0,1,0)
   und würde deshalb verlieren. Alle Schrittzeichen stehen ohne Ausnahme in
   einer Überschrift mit der Klasse .proopc-process-title - in beiden Vorlagen
   des Plugins (default_style1.php und default_entrysingle.php, am 05.08.2026
   nachgesehen). Damit ist die Regel zweistufig (0,2,0) und gewinnt, ohne dass
   "!important" nötig wäre. Die Live-Seite löst dieselbe Stelle mit
   "!important" - das blockiert spätere Anpassungen und ist hier vermieden.

   Die Variable ist dieselbe wie bei den Knöpfen weiter oben. Wer die
   Firmenfarbe einmal ändert, ändert sie damit an beiden Stellen zugleich.
   Die weiße Schrift kommt vom Plugin und passt auf das Dunkelblau. */
.proopc-process-title .proopc-step {
    background: var(--template-primary-color, #004494);
}

/* Sinnbilder der Zahlarten NEBEN den Namen statt darüber.
   Ergänzt am 05.08.2026.

   WAS ZU SEHEN WAR: Vorauskasse (bank.svg), BAR (card.svg + euro.svg) und
   Dienstrad-Leasing (leasing.svg) haben ein Sinnbild - es stand aber in einer
   eigenen Zeile über dem Namen.

   DIE URSACHE ist eine Regel des Einseiten-Checkout, nicht des Templates:
   .proopc-column3 .vmCartPaymentLogo { display: block }   (light-checkout.css)

   WARUM HIER EINE KENNUNG IM WÄHLER STEHT: Am 05.08.2026 gemessen wird
   light-checkout.css als 18. Datei geladen, diese hier als 8. Bei GLEICHER
   Genauigkeit gewinnt die spätere - eine Regel ".vmCartPaymentLogo" hätte also
   nichts bewirkt. Der Wähler des Plugins ist zweistufig (0,2,0); mit der
   Kennung #proopc-payment-form (1,1,0) ist diese Regel genauer und kommt ohne
   "!important" aus. Dieselbe Überlegung wie bei den Knöpfen weiter oben. */
#proopc-payment-form .vmCartPaymentLogo {
    display: inline-block;
    vertical-align: middle;
    margin-right: 5px;
}

/* PayPal bekommt sein Sinnbild - das Plugin liefert keines mit.

   WARUM NICHT ÜBER DIE ZAHLART SELBST: Das Feld "Sinnbilder"
   (payment_logos) gehört zum Zahlungsplugin "standard". Das PayPal-Plugin
   kennt es nicht - in paypal_checkout.xml kommt payment_logos nicht vor
   (am 05.08.2026 nachgesehen). Ein Eintrag dort bliebe wirkungslos.

   WARUM NICHT WÖRTLICH WIE AUF DER LIVE-SEITE: Dort steht ein Zeichen aus der
   Schrift "VPFrameworkIcon" (content: "\e4dd"). Diese Schrift heißt im neuen
   Template VP-Prime und hat kein PayPal-Zeichen - der Kniff liefe ins Leere.

   STATTDESSEN dieselbe Bilddatei, aus der auch bank.svg und leasing.svg
   stammen: images/virtuemart/payment/paypal.svg. Damit sieht es aus wie die
   anderen drei, und es hängt an keiner Schriftart.

   DER WÄHLER HÄNGT AM MERKMAL, NICHT AN DER REIHENFOLGE: Das Eingabefeld trägt
   data-pmtype="paypal_checkout", die Beschriftung folgt unmittelbar darauf.
   Die Live-Regel arbeitete mit nth-child(1); sobald eine Zahlart dazukommt
   oder die Reihenfolge sich ändert, sitzt das Sinnbild dort an der falschen.

   27 px, weil bank.svg genau so groß gerendert wird (gemessen).

   DER PFAD IST RELATIV zu dieser Datei - fünf Ebenen hinauf bis zur Wurzel.
   Ein absoluter Pfad "/images/..." wäre auf der lokalen Installation unter
   /test-neu/ falsch und würde dort ein leeres Kästchen zeigen. */
#proopc-payment-form input[data-pmtype="paypal_checkout"] + label .vmpayment_name::before {
    content: "";
    display: inline-block;
    width: 27px;
    height: 27px;
    margin-right: 5px;
    vertical-align: middle;
    background: url("../../../../../images/virtuemart/payment/paypal.svg") no-repeat center center;
    background-size: contain;
}

/* ===========================================================================
   Fußbereich
   Ergänzt am 01.08.2026 nach den Anmerkungen aus der Vikunja-Aufgabe
   "Template Anpassungen".
   =========================================================================== */

/* Zahlungssymbole nebeneinander statt untereinander.

   DIE URSACHE ist ein Bootstrap-Wechsel, kein Fehler im Inhalt: Bis
   Bootstrap 4 legte die Regel .list-inline > li die Einträge selbst
   nebeneinander. Bootstrap 5 - und damit vp_neoteric - hat das aufgeteilt:
   .list-inline macht nur noch die Aufzählungspunkte weg, nebeneinander stellt
   erst die ZUSÄTZLICHE Klasse .list-inline-item an jedem <li>. Die drei
   Stellen im Inhalt tragen sie nicht, weil sie aus der Zeit davor stammen -
   die Symbole standen deshalb untereinander.

   Statt an drei Stellen den Inhalt zu ändern (Modul "Zahlungsarten", Modul
   "Bleib in Verbindung" (unveröffentlicht) und Beitrag "Zahlarten") wird das
   alte Verhalten hier einmal wiederhergestellt. Das erwischt auch die Stellen,
   die beim Umbau noch niemand gesehen hat. */
.list-inline > li {
    display: inline-block;
}

/* Zeilenabstand der Öffnungszeiten wie bei den Menüpunkten daneben.

   Der große Abstand kam aus einem line-height: 2.6em, das ALS INLINE-STIL im
   Beitrag "Öffnungszeiten" stand - Altbestand, im alten Template genauso.
   Der Inline-Stil ist am 01.08.2026 aus dem Beitrag entfernt worden; damit
   erbt der Block die 1,5 des Templates (21 px).

   Bleibt der Absatzabstand: Bootstrap gibt jedem <p> unten 28 px mit, die
   Menüpunkte daneben stehen aber nur 35 px auseinander. Mit 14 px kommt der
   Absatz auf dieselben 35 px (21 + 14).

   ACHTUNG bei der Kennung: #mod-custom113 ist die Modul-ID der Öffnungszeiten.
   Wird das Modul einmal neu angelegt statt bearbeitet, bekommt es eine andere
   ID und diese Regel läuft ins Leere - dann hier die neue Nummer eintragen. */
#mod-custom113 p {
    margin-bottom: .875rem;
}

/* ===========================================================================
   Megamenü — Mindestbreite der Spalten
   Ergänzt am 02.08.2026 nach der Vikunja-Aufgabe 67
   "Template Anpassungen lokal-neu".
   =========================================================================== */

/* DAS PROBLEM: Im Untermenü "Teile" liefen die Beschriftungen ineinander -
   "FAHRRADSTÄNDERGEPÄCKTRÄGER" stand als ein Wort auf dem Bildschirm.

   DIE URSACHE: Das Modul baut das Untermenü als Raster und schreibt die
   Spalten als Inline-Stil an das <ul>, z. B.
   grid-template-columns: repeat(6, minmax(16.6666666667%, 1fr));
   Die Prozentangabe bezieht sich auf die Breite des Aufklappfensters - und
   die steht noch gar nicht fest, weil das Fenster (position: absolute, ohne
   Breitenangabe) sich erst nach seinem Inhalt richtet. Die Mindestbreite
   greift dadurch nicht, die Spalten werden gleichmäßig schmal aufgeteilt, und
   längere Wörter ragen aus ihrer Spalte heraus. Gemessen am 02.08.2026 bei
   sechs Spalten: 125 px Spalte, davon 83 px nutzbar, "Fahrradständer" braucht
   124 px - 41 px zu wenig.

   DIE LÖSUNG: eine Mindestbreite an der Spalte selbst. Ein Rasterfeld mit
   min-width hebt die Mindestbreite seiner Spur an; weil das Aufklappfenster
   sich nach seinem Inhalt richtet, wächst es mit. Das wirkt für JEDES
   Untermenü, auch für künftige - anders als eine Einstellung, die man je
   Menüpunkt nachziehen müsste.

   ZUR ZAHL: 15rem sind hier 210 px (Grundschrift 14 px). Das längste Wort im
   Menü ist "Fahrradhandschuhe" mit 155 px, dazu 42 px Innenabstand = 197 px.
   Bleiben 13 px Luft. Wer längere Namen aufnimmt, prüft das nach.

   ACHTUNG: Die Zahl darf nicht beliebig wachsen. Bei vier Spalten sind
   4 × 210 = 840 px nötig; ab etwa 992 px Fensterbreite schaltet das Template
   auf das Handymenü um, darüber bleibt also Platz. Bei SECHS Spalten wären es
   1260 px - mehr als der Inhaltsbereich hergibt. Deshalb steht "Teile" seit
   dem 02.08.2026 auf drei Spalten (Menüpunkt "Teile", Reiter des Megamenüs,
   "Spalten je Zeile"). Wer dort wieder auf sechs stellt, bekommt den
   seitlichen Überlauf zurück. */
.mod-megamenu--container.mod-megamenu--level-1 > .mod-megamenu--sub > .mod-megamenu--item {
    min-width: 15rem;
}

/* --- Die Obergrenze für die auf 1600 px gesetzten Aufklappfenster ----------
   ERGÄNZT am 04.08.2026 (Vikunja-Aufgabe 70: "ob es sich an Templatebreite
   anpassen kann - mir sind die Bilder unter E-Bikes und Fahrräder zu klein").

   WAS GEÄNDERT WURDE: "E-Bikes" und "Fahrräder" stehen jetzt auf einer festen
   Fensterbreite von 1600 px statt auf "auto" - das ist dieselbe Zahl wie bei
   .container-xxl weiter unten, also die Inhaltsbreite der Seite. Gesetzt wird
   sie am MENÜPUNKT, nicht hier; das Skript dazu ist
   werkzeuge\megamenu-breite-setzen.php.

   Gemessen am 04.08.2026: vorher 842 px breit, vier Spalten zu 210 px, das
   Kategoriebild 168 px bei 420 px Dateibreite - also auf 40 % verkleinert.
   Bei 1600 px sind es rund 400 px je Spalte und rund 360 px Bild: deutlich
   größer und weiterhin unter der Dateibreite, also scharf.

   WARUM DIESE REGEL TROTZDEM NÖTIG IST - und sie ist es:
   Das Modul schreibt die 1600 px als Inline-Stil an das Fenster und
   VERKLEINERT es bei schmalen Bildschirmen nicht. Es verschiebt nur nach
   links (menu.js, setFirstLevelDropdownPosition); reicht der Platz auch dann
   nicht, ragt der Rest rechts hinaus. Und weil html und body auf
   "overflow-x: clip" stehen (siehe Abschnitt "Inhaltsbreite"), gäbe es dort
   nicht einmal eine Bildlaufleiste - die halbe Spalte wäre schlicht weg.
   Auf einem 1366-px-Notebook beträfe das rund 250 px.

   ZUR ZAHL 3rem: Davon gehen rund 15 px für die senkrechte Bildlaufleiste ab.
   "100vw" ist die Fensterbreite EINSCHLIESSLICH der Leiste, der sichtbare
   Bereich ist also schmaler. Mit 2rem gemessen: das Fenster reichte bis
   1297,2 px bei 1296 px sichtbarer Breite - 1,2 px zu viel. Übrig bleiben so
   rund 27 px echter Abstand zum Rand, damit der Schatten nicht an der Kante
   klebt.

   Das Modul rechnet seine Position aus der tatsächlichen Breite, misst also
   die hier begrenzte - die Verschiebung nach links stimmt damit weiterhin. */
.mod-megamenu--container.mod-megamenu--width-custom {
    max-width: calc(100vw - 3rem);
}

/* ===========================================================================
   Kaufabschluss — AGB-Zustimmung
   Ergänzt am 02.08.2026 nach der Vikunja-Aufgabe 67
   "Template Anpassungen lokal-neu".
   =========================================================================== */

/* DAS PROBLEM: Am Handy ging beim Ankreuzen der AGB-Zustimmung ständig das
   AGB-Fenster auf. Gemessen am 02.08.2026: das Kästchen ist 13 x 13 Pixel
   groß, der Link beginnt 7 Pixel daneben. Eine Fingerkuppe trifft rund
   40 Pixel - sie erwischt also fast zwangsläufig den Link.

   Die zweite Hälfte der Lösung steckt in der Vorlage
   templates/vp_neoteric/html/plg_system_vponepagecheckout/default_cartfields.php:
   dort ist der Link aus dem <label> herausgenommen und auf die Wörter
   "Allgemeinen Geschäftsbedingungen" begrenzt. Hier geht es nur um die Größe
   der Trefferflächen.

   ZU DEN ZAHLEN: 1,5rem sind hier 21 Pixel für das Kästchen, dazu 0,875rem
   (12 px) Abstand zum Text. Die beiden Textteile bekommen oben und unten
   je 0,375rem Innenabstand, damit auch sie bequem zu treffen sind. Die
   Fingerkuppe braucht rund 40 Pixel; erreicht wird das durch Kästchen plus
   Zeilenhöhe, nicht durch das Kästchen allein - ein 40 Pixel großes Kästchen
   sähe auf dem Schreibtisch falsch aus.

   WARUM ÜBERALL "#ProOPC" DAVORSTEHT: Der One-Page-Checkout bringt in
   plugins/system/vponepagecheckout/assets/css/light-checkout.css drei Regeln
   mit, die genau hier greifen und mit einer ID-Kennung geschrieben sind:

     #ProOPC label                        { display: block }         (Zeile 139)
     #ProOPC .checkbox input[type=…]      { float: left; margin-left: -20px }
     .radio, .checkbox                    { padding-left: 20px }     (Zeile 1814)

   Eine ID schlägt jede Anzahl von Klassen. Ohne das vorangestellte #ProOPC
   wirken die Regeln hier nur zur Hälfte - am 02.08.2026 genau so gemessen:
   die Höhe des Kästchens änderte sich, die Breite nicht, und die Textteile
   standen weiter untereinander statt in einer Zeile. Wer diese Regeln kürzt,
   bekommt das zurück. */
#ProOPC .cart-tos-group .prooopc-tos-label {
    display: flex;
    align-items: flex-start;
    column-gap: .875rem;
    padding-left: 0;     /* die 20 px des alten .checkbox-Musters entfallen */
}

#ProOPC .cart-tos-group .checkbox input[type="checkbox"].terms-of-service {
    float: none;         /* im Flexfluss wirkungslos, aber sonst irreführend */
    flex: 0 0 auto;      /* darf nicht schrumpfen, sonst ist es am Handy wieder winzig */
    width: 1.5rem;
    height: 1.5rem;
    margin: .125rem 0 0; /* auf Höhe der ersten Textzeile; ersetzt das -20px */
}

/* Die beiden Textteile bleiben INLINE (nicht block, nicht inline-block): nur
   so laufen sie mit dem Link in einer Zeile und brechen am Handy sauber um.
   Der Innenabstand vergrößert die Trefferfläche, ohne die Zeile
   auseinanderzuziehen. */
#ProOPC .cart-tos-group .terms-of-service-cont label {
    display: inline;
    margin: 0;
    padding: .375rem 0;
    cursor: pointer;
}

/* Der Link soll als Link erkennbar sein - vorher war der ganze Satz Link,
   jetzt nur noch zwei Wörter, und die müssen sich abheben. */
#ProOPC .cart-tos-group .terms-of-service-cont a.terms-of-service {
    text-decoration: underline;
    padding: .375rem 0;
}

/* ===========================================================================
   Bike-Leasing-Seite — Klappmenü und Partnerlogos
   Ergänzt am 02.08.2026 nach der Vikunja-Aufgabe 67
   "Template Anpassungen lokal-neu".
   =========================================================================== */

/* Der Beitrag "Bike Leasing" (ID 24) stammt aus der Bootstrap-3-Zeit. Die
   Umstellung des Markups auf Bootstrap 5 macht das Skript
   projekte\website\werkzeuge\beitrag-bikeleasing-bootstrap5.ps1 - danach
   FUNKTIONIERT das Klappmenü wieder. Es SIEHT nur nicht danach aus: Die
   Fragen stehen als unterstrichene Textknöpfe da, und man erkennt nicht, dass
   sie sich aufklappen lassen. Das holen die folgenden Regeln nach.

   Bewusst an .card/.card-header aufgehängt und nicht an einer eigenen Klasse:
   So greift es auch bei weiteren Beiträgen mit demselben Aufbau, ohne dass
   jemand daran denken muss. */
.item-page .card > .card-header {
    padding: 0;
    background: transparent;
}

.item-page .card > .card-header .btn-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    padding: 1rem 1.25rem;
    text-align: left;
    text-decoration: none;
    font-weight: 600;
    color: var(--template-link-color, #004494);
}

.item-page .card > .card-header .btn-link:hover,
.item-page .card > .card-header .btn-link:focus {
    text-decoration: none;
    background-color: rgba(0, 68, 148, .06);
}

/* Der Pfeil rechts. Er wird aus einem Rahmen gebaut statt aus einem Symbol -
   so hängt er an keiner Symbolschrift, die bei einem Update umbenannt werden
   kann (genau das ist bei fa-external-link schon passiert). */
.item-page .card > .card-header .btn-link::after {
    content: "";
    flex: 0 0 auto;
    width: .5rem;
    height: .5rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);       /* zeigt nach unten = zugeklappt */
    transform-origin: center;
    transition: transform .2s ease;
    margin-top: -.25rem;
}

/* aria-expanded pflegt Bootstrap selbst - daran hängt der Pfeil, nicht an
   einer eigenen Klasse. Damit stimmt die Anzeige auch dann, wenn ein Bereich
   über die Tastatur oder von der Klappgruppe geschlossen wird. */
.item-page .card > .card-header .btn-link[aria-expanded="true"]::after {
    transform: rotate(-135deg);     /* zeigt nach oben = aufgeklappt */
    margin-top: .25rem;
}

/* Die Partnerlogos hatten sehr unterschiedliche Größen: neun tragen im Beitrag
   ein festes style="height: 150px", drei nicht - die wurden dadurch deutlich
   größer. Statt den Beitrag an zwölf Stellen zu ändern, wird die Höhe hier
   einmal einheitlich gesetzt.

   WARUM HIER !important STEHT (sonst nirgends in dieser Datei): Die Höhe steht
   als Inline-Stil im Beitrag, und ein Inline-Stil schlägt jede normale Regel.
   Ohne !important bliebe alles, wie es war. Die Alternative wäre gewesen, die
   zwölf Inline-Stile aus dem Beitrag zu entfernen - dann steht die Gestaltung
   aber wieder an zwei Orten, sobald jemand ein Logo nachträgt und die Höhe
   mitkopiert.

   ZUR ZAHL: 7rem sind 98 Pixel - etwas weniger als die 150 Pixel von vorher,
   dafür bei allen zwölf Logos gleich. Ein blosses "height: auto" reicht NICHT - die
   SVG-Dateien bringen sehr unterschiedliche Eigengrößen mit, manche nur rund
   25 Pixel hoch; die Logos wurden damit winzig (am 02.08.2026 am Bild
   gesehen). Deshalb wird eine feste Höhe gesetzt und die Breite folgt dem
   Seitenverhältnis. */
.item-page .logos img {
    height: 7rem !important;
    width: auto;
    max-width: 100%;
    object-fit: contain;
}

.item-page .logos > div {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}

/* ===========================================================================
   Inhaltsseiten — die "feature"-Blöcke (Symbol, Überschrift, Text)
   Ergänzt am 02.08.2026 nach der Vikunja-Aufgabe 67, überarbeitet am selben
   Tag nach der Rückmeldung des Anwenders.
   =========================================================================== */

/* WORUM ES GEHT: Fast alle im Fußbereich verlinkten Seiten sind aus demselben
   Baustein aufgebaut - einem <div class="feature">, darin ein Symbol, eine
   Überschrift, eine kleinere Zwischenzeile und Text. Der Baustein stammt aus
   dem alten Template, das ihn selbst gestaltet hat. vp_neoteric kennt ihn
   nicht: Die Symbole standen als 14 Pixel große schwarze Zeichen lose über der
   Überschrift, ohne Bezug zu ihr, und die Blöcke schwammen ohne erkennbare
   Gruppierung nebeneinander.

   ZUR ANORDNUNG (Wunsch des Anwenders, 02.08.2026): Das Symbol steht VOR der
   Überschrift in derselben Zeile, als Umriss in der Schriftfarbe - so wie die
   Symbole oben im Kopf (Wunschliste, Vergleichen, Warenkorb). Kein farbiger
   Kreis, kein Block darüber.

   WIE DAS OHNE ÄNDERUNG AM INHALT GEHT: Im Markup steht das Symbol als
   Geschwister VOR der Überschrift, nicht darin. Ein Raster mit zwei Spalten
   löst das: Symbol in Spalte 1 Zeile 1, Überschrift in Spalte 2 Zeile 1, alles
   Weitere über beide Spalten. Fehlt das Symbol, nimmt die Überschrift von
   selbst die volle Breite - dafür sorgt der Nachbarschaftsselektor "+", nicht
   eine Sonderregel je Seite.

   FARBEN kommen aus den Template-Variablen, nicht fest verdrahtet - siehe Kopf
   dieser Datei. */

.item-page .feature {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: .625rem;
    align-content: start;
    padding: 1.75rem;
    border: var(--fw-rand) solid var(--fw-linie);
    /* GEÄNDERT am 04.08.2026: hier standen .5rem (7 px) - der einzige Ort auf
       der ganzen Seite mit diesem Wert, und er stammte aus eigener Arbeit.
       Jetzt derselbe Radius wie Knöpfe, Felder und Karten. */
    border-radius: var(--fw-radius);
    background-color: #fff;
    transition: box-shadow var(--fw-uebergang), border-color var(--fw-uebergang);
}

.item-page .feature:hover {
    border-color: var(--template-primary-color, #004494);
    box-shadow: var(--fw-schatten-klein);
}

/* Standard: alles über die volle Breite. Nur Symbol und die unmittelbar
   folgende Überschrift teilen sich die erste Zeile. */
.item-page .feature > * {
    grid-column: 1 / -1;
}

.item-page .feature > .icon,
.item-page .feature > img.icon {
    grid-column: 1;
    grid-row: 1;
    align-self: center;
    width: auto;
    height: auto;
    margin: 0;
    font-size: 1.5rem;
    line-height: 1;
    color: inherit;          /* Schriftfarbe, kein eigener Farbton */
    background: none;        /* kein Kreis, kein Feld */
}

.item-page .feature > img.icon {
    width: 1.75rem;
    height: 1.75rem;
    object-fit: contain;
}

.item-page .feature > .icon + .heading,
.item-page .feature > .icon + h4,
.item-page .feature > img.icon + .heading,
.item-page .feature > img.icon + h4 {
    grid-column: 2;
    grid-row: 1;
}

.item-page .feature > .heading,
.item-page .feature > h4 {
    margin: 0 0 .25rem;
    font-size: 1.25rem;
    line-height: 1.3;
    align-self: center;
}

/* Die Zwischenzeile war eine zweite fette Überschrift und stach dadurch
   stärker hervor als die eigentliche. Jetzt ist sie eine ruhige Beschriftung. */
.item-page .feature > .below-heading {
    margin: .25rem 0 .75rem;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: #6c757d;
}

.item-page .feature > p:last-child,
.item-page .feature > ul:last-child {
    margin-bottom: 0;
}

.item-page .feature ul {
    padding-left: 1.1rem;
    margin-bottom: 0;
}

.item-page .feature ul li {
    margin-bottom: .375rem;
}

/* KEIN height: 100% MEHR - das war ein Fehler.
   Er wirkte nur dort richtig, wo je Spalte GENAU EIN Block steht. Auf
   "Zahlung & Versand" stehen aber vier Blöcke untereinander in einer Spalte;
   jeder wurde dadurch so hoch wie die ganze Spalte (gemessen: 4 x 1279 px) und
   schob sich über den Fußbereich.

   Richtig ist: die Spalte zum Flex-Behälter machen und nur einen ALLEINIGEN
   Block darin wachsen lassen. Stehen mehrere darin, behalten alle ihre
   natürliche Höhe und bekommen einen Abstand. */
.item-page .row > [class*="col-"] {
    display: flex;
    flex-direction: column;
    margin-bottom: 1.5rem;
}

.item-page .row > [class*="col-"] > .feature:only-child {
    flex: 1 1 auto;
}

.item-page .feature + .feature {
    margin-top: 1.5rem;
}

/* Auf dem Handy stehen die Karten untereinander; dann darf der Rahmen
   schmaler werden. */
@media (max-width: 575.98px) {
    .item-page .feature {
        padding: 1.25rem;
    }
}

/* ---------------------------------------------------------------------------
   Blöcke ohne Symbol — Entscheidung des Anwenders vom 02.08.2026
   ---------------------------------------------------------------------------
   Die Symbolschriften werden ausgeblendet, die eingebundenen BILDER (die
   nummerierten SVG auf der Leasingseite) bleiben - die sind Inhalt und nicht
   Schmuck. Deshalb steht hier "span.icon" und nicht nur ".icon".

   WARUM ohne Symbole: Von den 20 Blöcken auf diesen Seiten tragen 7 Namen aus
   der Symbolschrift des ALTEN Templates (icon-credit, icon-mobile,
   icon-checkmark, icon-checkbox, icon-paypal, icon-checkmark-circle,
   icon-thumbs-up). Diese Schrift kam beim Umbau nicht mit - dort erschien
   nichts, bei "PayPal" klaffte eine Lücke. Die Symbolschrift des NEUEN
   Templates (vpi-*, dieselbe wie bei Wunschliste/Vergleichen/Warenkorb im
   Kopf) hat 85 Zeichen, aber keines für Lieferung, Werkzeug, Karte, Handy,
   Geld, Fahrrad oder PayPal. Für ein einheitliches Bild hätte man Font
   Awesome dazunehmen müssen - gefüllte Zeichen in einer anderen
   Formensprache. Der Anwender hat sich deshalb bewusst für reine Schrift
   entschieden; nachrüsten lässt sich das nach dem Umzug jederzeit.

   WIEDER EINSCHALTEN: diese eine Regel auskommentieren. Die Anordnung
   "Symbol vor der Überschrift" steht oben und bleibt erhalten - es wird also
   nichts neu gebaut, nur wieder sichtbar gemacht.
   --------------------------------------------------------------------------- */
.item-page .feature > span.icon {
    display: none;
}

/* Abstand vor dem Knopf "Ihre Bestellung ansehen" auf der Dankeseite.
   Bei PayPal liefert das Zahlungs-Plugin nur den Satz "Ihre Bestellung wurde
   bearbeitet." als reinen Text, ohne abschliessendes Element - der Knopf
   klebte unmittelbar daran. Bei Vorauskasse bringt das Plugin seinen eigenen
   Block mit, dann ist diese Regel wirkungslos und stoert nicht. */
.vm-order-done .vm-order-done__link {
    margin-top: 1.25rem;
}

/* ---------------------------------------------------------------------------
   Der Cookie-Hinweis lag ueber den Schubladen von rechts (03.08.2026)
   ---------------------------------------------------------------------------
   GEMESSEN am 03.08.2026 bei 1309 x 875: Der Knopf "Meine Wunschliste" am
   Fuss der Wunschlisten-Schublade liegt bei 813-854 px, der Cookie-Hinweis
   beginnt bei 776 px. Der Knopf ist damit VOLLSTAENDIG verdeckt - und an
   seiner Stelle liegt ausgerechnet der Knopf "EINVERSTANDEN" des Hinweises
   (mit elementFromPoint nachgewiesen). Ein Klick dorthin nimmt also Cookies
   an, statt die Wunschliste zu oeffnen. Das ist schlimmer als ein verdeckter
   Knopf: Es passiert etwas anderes als beabsichtigt.

   Betroffen ist nicht nur die Wunschliste, sondern JEDE der fuenf Schubladen -
   Wunschliste, Vergleich, Mini-Warenkorb, Anmeldung und das Handy-Menue. Alle
   haben ihren Aktionsknopf am unteren Rand, der Mini-Warenkorb den Weg zum
   Warenkorb. Auf dem Handy trifft es damit die Kaufstrecke.

   URSACHE ist allein die Stapelreihenfolge. Das Template gibt dem Hinweis
   z-index 900001 - eine Zahl, die ihn ueber alles legt, auch ueber Dialoge:

       Cookie-Hinweis   900001
       vme-message-box    1055   (die kurze Meldung nach dem Merken)
       Schubladen         1045
       Abdunklung         1040

   ABSICHTLICH NICHT die Position geaendert. `cookie_consent_position` steht
   seit dem 30.07.2026 bewusst auf "bottom", weil der Hinweis unten rechts auf
   dem Handy zu breit war und die Seite seitlich ueberlaufen liess. Ein Wechsel
   zurueck auf "bottom-left" oder "bottom-right" wuerde diesen Fund von damals
   wieder aufreissen - und auf dem Handy zieht das Template beide ohnehin auf
   volle Breite (Medienabfrage bis 767.98 px setzt links UND rechts).

   STATTDESSEN wird der Hinweis eine Schicht unter die Abdunklung gelegt. Eine
   offene Schublade verdeckt ihn dann, statt umgekehrt; nach dem Schliessen ist
   er sofort wieder da. 1039 ist mit Bedacht gewaehlt: noch ueber der
   Kopfleiste (Bootstrap fixed-top = 1030), aber unter der Abdunklung (1040).

   NEBENWIRKUNG, und zwar eine erwuenschte: Die kurze Meldung nach dem Merken
   eines Artikels (`vme-message-box`, 1055) liegt jetzt ebenfalls oben. Vorher
   haette der Hinweis sie beim Erstbesuch verdecken koennen - also genau die
   Meldung, die am selben Tag uebersetzt wurde.

   WAS MAN DAFUER IN KAUF NIMMT: Solange eine Schublade offen ist, kann man
   den Cookies nicht zustimmen. Das ist richtig so - es ist immer nur ein
   Dialog zugleich offen, und der Hinweis verschwindet nicht, er wartet.
   --------------------------------------------------------------------------- */
.vp-cookie-consent {
    z-index: 1039;
}

/* ===========================================================================
   Fremde Erweiterungen an die Gestaltungsregeln angleichen (04.08.2026)
   ---------------------------------------------------------------------------
   Die Bauteile hier stammen aus mitgelieferten Bibliotheken und Plugins, die
   ihr eigenes Aussehen mitbringen. Sie stehen auf der Seite unmittelbar neben
   den Knöpfen des Templates - in der Filterspalte sogar untereinander.

   ZUR REIHENFOLGE, und das ist der Grund für die Schreibweisen unten:
   Die user.css wird als 11. von 18 Stylesheets geladen. Sieben kommen DANACH
   (Offcanvas-Menü, Mini-Warenkorb, VM-Essentials, JCE-Mediabox,
   Custom Fields For All). Gegen deren Regeln gewinnt diese Datei nicht durch
   ihre Stellung, sondern nur durch höhere Genauigkeit - deshalb sind die
   Selektoren hier bewusst länger als nötig aussieht.
   =========================================================================== */

/* --- Kaufabschluss: die Form der Knöpfe ------------------------------------
   Die FARBEN stehen weiter oben und bleiben unverändert (Entscheidung des
   Anwenders vom 01.08.2026). Hier geht es nur um Form und Schatten.

   Das Plugin gibt seinen Knöpfen 4 px Radius und einen eingesetzten
   Lichtrand plus Schlagschatten - eine Bootstrap-2-Optik von 2012. Neben den
   flachen Knöpfen des Templates fällt das auf.

   Es steht bewusst .proopc-btn ALLEIN (nicht nur die beiden Zusatzklassen wie
   bei den Farben weiter oben): Die Form soll für jeden Knopf des Kaufabschlusses
   gelten, auch für die, die keine Farbklasse tragen. */
.proopc-btn,
a.proopc-btn,
button.proopc-btn,
input.proopc-btn {
    border-radius: var(--fw-radius);
    box-shadow: none;
    text-shadow: none;
    background-image: none;
    transition: color var(--fw-uebergang), background-color var(--fw-uebergang),
                border-color var(--fw-uebergang);
}

/* Eingabefelder des Kaufabschlusses: dieselbe Rundung wie überall. */
#ProOPC input[type="text"],
#ProOPC input[type="email"],
#ProOPC input[type="tel"],
#ProOPC input[type="password"],
#ProOPC select,
#ProOPC textarea {
    border-radius: var(--fw-radius);
}

/* --- Der Lupenknopf im Preisfilter -----------------------------------------
   Er trug als einziger Knopf der Seite ein eigenes Blaugrau (#6d757e) - am
   03.08.2026 in der Filterspalte gemessen und im Bildschirmfoto deutlich neben
   dem blauen "SUCHE" darüber zu sehen. Er löst dieselbe Sache aus wie "SUCHE"
   und soll deshalb auch so aussehen.

   ES WERDEN DIE VARIABLEN GESETZT, NICHT DIE EIGENSCHAFTEN - und das ist hier
   der ganze Punkt. Der erste Versuch am 04.08.2026 schrieb
   "background-color: …" direkt hin und blieb WIRKUNGSLOS: Der Knopf trägt
   .btn.btn-secondary, und .btn-secondary setzt --btn-bg. Die Regel
   ".btn { background-color: var(--btn-bg) }" des Templates gewinnt gegen eine
   gleich genaue eigene Regel nicht durch Reihenfolge, sondern weil sie den
   Wert aus der Variablen holt, die weiterhin auf Grau stand.

   Wer hier "background-color" hinschreibt, misst hinterher unverändertes Grau
   und sucht den Fehler an der falschen Stelle. */
.cf_search_button {
    --btn-bg: var(--template-primary-color, #004494);
    --btn-border-color: var(--template-primary-color, #004494);
    --btn-color: var(--template-primary-contrast-color, #fff);
    --btn-hover-bg: var(--template-primary-hover-color, #333333);
    --btn-hover-border-color: var(--template-primary-hover-color, #333333);
    --btn-hover-color: var(--template-primary-contrast-color, #fff);
    --btn-active-bg: var(--template-primary-hover-color, #333333);
    --btn-active-border-color: var(--template-primary-hover-color, #333333);
}

/* DIE VARIABLE ALLEIN GENÜGT HIER NICHT - nachgemessen am 04.08.2026:
   --btn-bg stand danach nachweislich auf #004494, die Fläche blieb trotzdem
   grau (rgb(109,117,126)). Keine der drei auffindbaren Regeln erklärt diesen
   Wert; die Ursache liegt vermutlich in einem :is()/:where()-Selektor des
   Templates, den eine Prüfung mit element.matches() nicht als solchen erkennt.

   Statt die Kaskade weiter zu ergründen, steht die Farbe hier zusätzlich
   ausdrücklich - mit zwei Klassen plus Element und damit eindeutig genauer als
   alles, was das Template mitbringt. Kein !important: Das wäre der grobe Weg
   und würde spätere Anpassungen blockieren. */
button.cf_search_button.btn,
.cf_search_button.btn-secondary {
    background-color: var(--template-primary-color, #004494);
    border-color: var(--template-primary-color, #004494);
    color: var(--template-primary-contrast-color, #fff);
}

button.cf_search_button.btn:hover,
button.cf_search_button.btn:focus,
.cf_search_button.btn-secondary:hover,
.cf_search_button.btn-secondary:focus {
    background-color: var(--template-primary-hover-color, #333333);
    border-color: var(--template-primary-hover-color, #333333);
    color: var(--template-primary-contrast-color, #fff);
}

/* KEINE Radius-Regel für die LINKE Seite dieses Knopfes, und das ist Absicht.
   Er sitzt in einer .input-group ("von … bis …" plus Lupe). Bootstrap macht
   dort die INNENkanten eckig und rundet nur die Aussenkanten der Gruppe - das
   ist richtig so, sonst klaffen zwischen Feld und Knopf zwei runde Ecken
   aufeinander. Am 04.08.2026 nachgesehen: die 0 px stammen aus der Regel
   ".cf-form-search .input-append > :not(:first-child)" des Templates.
   Eingabegruppen sind damit die eine bewusste Ausnahme von der Radiusregel.

   Der Lupenknopf steht dabei richtig: 0 / 3,5 / 3,5 / 0 - links eckig zum Feld
   hin, rechts gerundet zum Rand. Er ist das letzte Element seiner Gruppe.

   HIER STEHT KEINE REGEL FÜR DEN KNOPF "SUCHE" IN DER KOPFZEILE, obwohl er
   dasselbe Problem hatte (am 04.08.2026 gemeldet: rundherum eckig, während das
   Suchfeld daneben links schon gerundet war). Der Grund ist ein unsichtbares
   Geschwister, und das lässt sich in CSS nicht ausnehmen - die Lösung steht
   deshalb in der user.js, Abschnitt "Der Knopf SUCHE …". Wer hier sucht, findet
   sie dort. */

/* --- Der Mengenknopf am Produkt --------------------------------------------
   Er trug 0,3rem statt 0,25rem. Die Klasse allein genügt hier nicht: Die
   Vorgabe kommt aus media/…/com_vmessentials/style.min.css, und die wird als
   16. Datei geladen - also NACH dieser hier. Gegen eine spätere Datei hilft
   bei gleicher Genauigkeit nichts; deshalb steht das Element davor. */
button.quantity-controls,
.btn.quantity-controls,
.quantity-box .quantity-controls {
    border-radius: var(--fw-radius);
}

/* --- Die Auswahlfelder (Choices.js) ----------------------------------------
   "Sortieren nach" und "Alle Hersteller" stehen in derselben Werkzeugleiste
   wie der Knopf "Filter ausblenden". Die Bibliothek liefert sie eckig, der
   Knopf daneben ist gerundet. */
.choices__inner,
.choices[data-type*="select-one"] .choices__inner {
    border-radius: var(--fw-radius);
}

/* Die aufgeklappte Liste schwebt über der Seite - sie bekommt deshalb den
   Schatten, den schwebende Dinge nach den Regeln tragen. */
.choices__list--dropdown,
.choices__list[aria-expanded] {
    border-radius: var(--fw-radius);
    box-shadow: var(--fw-schatten);
}

/* --- Die Symbolknöpfe an der Produktkachel und am Artikel -------------------
   ERGÄNZT am 04.08.2026 nach Vikunja-Aufgabe 70 ("Bei den Icons auch den
   Borderradius setzen").

   BERICHTIGUNG zu unterlagen\gestaltungsregeln.md, Abschnitt 8: Dort steht,
   die Symbolknöpfe seien "unangetastet, weil sie keine Fläche haben, also
   auch keine Ecken zum Vereinheitlichen". Für die Pfeile der Karussells
   stimmt das. Für DIESE hier nicht: Herz (Wunschliste), Pfeile (Vergleich)
   und Lupe (Schnellansicht) sind am 04.08.2026 als 40 x 40 px große Kästen
   mit weißer Fläche und Rahmen in --fw-linie gemessen worden - also sehr wohl
   mit sichtbarer Ecke. Sie standen als einzige Kästen der Seite noch auf 0.

   ES IST DAS <i>, NICHT DER KNOPF. Die Erweiterung gibt dem Knopf selbst
   weder Fläche noch Rahmen (.btn-vme-round: background: 0 none; border: 0
   none) und hängt beides an das Symbolzeichen darin. Eine Regel am Knopf
   bliebe deshalb wirkungslos.

   WARUM ELEMENT PLUS KLASSE: media/…/com_vmessentials/style.min.css wird als
   16. Datei geladen, diese hier als 11. Gegen ".btn-vme-round > i" (eine
   Klasse, ein Element) gewinnt bei gleicher Genauigkeit die spätere Datei -
   das vorangestellte a/button gibt den Ausschlag.

   NUR DER RADIUS. Die Rahmenstärke bleibt bei 1 px, obwohl die Regeln für
   Knöpfe --fw-rand-stark vorsehen: Ein 2 px starker Rahmen um ein 40 px
   großes Symbol wirkt schwer, und danach war nicht gefragt. */
a.btn-vme-round > i,
button.btn-vme-round > i {
    border-radius: var(--fw-radius);
}

/* --- Kästen, Karten, Meldungen ---------------------------------------------
   .card kam bereits auf den richtigen Wert; die Zeile steht hier trotzdem,
   damit alle Flächen an EINER Stelle nachzulesen sind statt verstreut. */
.card,
.alert,
.well,
.panel {
    border-radius: var(--fw-radius);
}

/* --- Dialogfenster ---------------------------------------------------------
   ERGÄNZT am 04.08.2026 nach Vikunja-Aufgabe 70 ("Dialogbox Borderradius
   setzen, Rahmenfarbe mit weniger Kontrast wählen").

   WAS DA ZU SEHEN WAR: Das Fenster "Rahmengröße bestimmen" hatte eckige Ecken
   und einen 3 px starken SCHWARZEN Rahmen - der einzige schwarze Rahmen der
   ganzen Seite.

   DIE URSACHE ist, dass es überhaupt keine Regel dafür gab. Am 04.08.2026 die
   Stilvorlagen durchsucht: keine einzige setzt an diesem Element Rahmen oder
   Radius. Schwarz und eckig ist die VORGABE DES BROWSERS für <dialog> - und
   die sieht in jedem Browser etwas anders aus. Wer hier nichts hinschreibt,
   überlässt das Aussehen also nicht dem Template, sondern dem Zufall.

   ZWEI BAUARTEN, DASSELBE AUSSEHEN. Auf der Seite gibt es Dialoge aus zwei
   Quellen, und beide standen auf 0 px Radius:
     joomla-dialog  - Joomlas eigenes Element (Größenberatung, Bildergalerie)
     .modal-content - Bootstrap (Schnellansicht, AGB-Fenster im Kaufabschluss)
   Sie sind nie gleichzeitig zu sehen, aber nacheinander - und dann fällt ein
   Unterschied auf.

   DIE WERTE stehen in unterlagen\gestaltungsregeln.md, Abschnitt 5:
   Dialoge tragen den GROSSEN Radius (7 px). Der kleine (3,5 px) ist für
   Knöpfe und Felder gedacht; auf einer bildschirmhohen Fläche wäre er kaum zu
   sehen. Dazu der große Schatten - ein Dialog schwebt über der Seite, und
   genau dafür ist er da.

   Der Rahmen bleibt, nur eben in der Linienfarbe der Seite statt in Schwarz.
   Ganz weglassen wäre nach den Regeln auch vertretbar (dort steht "keiner"),
   der Anwender hat aber ausdrücklich "weniger Kontrast" verlangt und nicht
   "weg" - und auf einem hellen Hintergrund braucht ein weißes Fenster eine
   Kante. */
joomla-dialog dialog,
dialog.joomla-dialog-element {
    border: var(--fw-rand) solid var(--fw-linie);
    border-radius: var(--fw-radius-gross);
    box-shadow: var(--fw-schatten);
}

.modal-content {
    border: var(--fw-rand) solid var(--fw-linie);
    border-radius: var(--fw-radius-gross);
    box-shadow: var(--fw-schatten);
}

/* NACHGETRAGEN am 05.08.2026: Der Kasten war rund, die OBEREN Ecken blieben
   trotzdem eckig - zu sehen am Fenster "Produkt erfolgreich hinzugefügt".

   WARUM: Bootstrap gibt dem Kopf einen eigenen Radius aus
   --modal-inner-border-radius, und der steht im Template auf 0. Am 05.08.2026
   im Browser nachgemessen: .modal-content 7 px, .modal-header 0 px. Der Kopf
   hat einen farbigen Hintergrund (rgb(48,99,141)) und deckt die eben
   gerundeten Ecken damit wieder zu. Bei weißen Köpfen sieht man es nicht -
   deshalb ist es lange niemandem aufgefallen.

   NICHT über overflow:hidden am Kasten lösen. Das würde zwar alles auf einen
   Schlag beschneiden, aber eben auch Auswahllisten und Hinweisblasen, die aus
   einem Dialog herausragen dürfen.

   Der Fuß bekommt dieselbe Behandlung. Er ist heute weiß, also unsichtbar -
   sobald er einmal eine Farbe erhält, wäre sonst dasselbe Problem unten. */
.modal-header {
    border-top-left-radius: var(--fw-radius-gross);
    border-top-right-radius: var(--fw-radius-gross);
}

.modal-footer {
    border-bottom-left-radius: var(--fw-radius-gross);
    border-bottom-right-radius: var(--fw-radius-gross);
}

/* --- Die Schubladen von rechts ---------------------------------------------
   Fünf Stück (Wunschliste, Vergleich, Mini-Warenkorb, Anmeldung, Handy-Menü).
   Sie schweben über der Seite und bekommen deshalb den großen Schatten. Eine
   Rundung erhalten sie NICHT: sie sitzen bündig am Fensterrand, dort wäre eine
   runde Ecke ein Spalt. Das Handy-Filterpanel von unten ist der Sonderfall und
   steht weiter oben. */
.offcanvas,
.offcanvas-end,
.offcanvas-start {
    box-shadow: var(--fw-schatten);
}

/* --- Abgeschaltete Knöpfe --------------------------------------------------
   Ein abgeschalteter Knopf muss abgeschaltet AUSSEHEN. Das ist hier kein
   Randfall: Der "Kaufen"-Knopf wird vom Kaufabschluss ausdrücklich mit
   "disabled" ausgeliefert und erst freigeschaltet, wenn alle Angaben
   vollständig sind. Sähe er dabei anklickbar aus, wäre das im Bestellvorgang
   das teuerste Missverständnis überhaupt.

   Der Mauszeiger gehört dazu: Er ist die einzige Rückmeldung, die man BEKOMMT,
   BEVOR man klickt. */
.btn:disabled,
.btn.disabled,
button:disabled,
.proopc-btn[disabled],
.proopc-btn.disabled {
    cursor: not-allowed;
}
