{"id":53814,"date":"2025-03-18T10:07:53","date_gmt":"2025-03-18T09:07:53","guid":{"rendered":"https:\/\/dev.diamantrad.com\/?page_id=53814"},"modified":"2026-04-01T15:26:45","modified_gmt":"2026-04-01T13:26:45","slug":"mens-bikes","status":"publish","type":"page","link":"https:\/\/www.diamantrad.com\/en-GB\/bikes\/mens-bikes\/","title":{"rendered":"Mens Bikes"},"content":{"rendered":"\n<div class=\"wp-block-cover\"><img data-dominant-color=\"937985\" data-has-transparency=\"false\" loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1687\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" class=\"wp-block-cover__image-background wp-image-53693 size-full not-transparent\" alt=\"Di 25 mahon lifestyle\" src=\"https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-scaled.avif\" style=\"--dominant-color: #937985; object-position:76% 77%\" data-object-fit=\"cover\" data-object-position=\"76% 77%\" srcset=\"https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-scaled.avif 2560w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-300x198.avif 300w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-1024x675.avif 1024w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-768x506.avif 768w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-1536x1012.avif 1536w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I0292_300dpi-2048x1350.avif 2048w\" \/><span aria-hidden=\"true\" class=\"wp-block-cover__background has-color-primary-background-color has-background-dim-30 has-background-dim\"><\/span><div class=\"wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained\">\n<p class=\"has-text-align-center has-large-font-size wp-block-paragraph\"><\/p>\n\n\n<div class=\"lazyblock-cover-text-Z1Xu0aJ wp-block-lazyblock-cover-text\"><div class=\"covertext container py-5 d-flex flex-column colorscheme-light justify-content-center\" id=\"covertext-Z1Xu0aJ\">\r\n  <div class=\"lazyblock-inner-blocks\">\n\n<h2 class=\"wp-block-heading\">Men&#8217;s bikes<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">&#8230;are bikes &#8220;with a bar&#8221;<\/h4>\n\n<\/div>\r\n<\/div><\/div><\/div><\/div>\n\n\n<div class=\"lazyblock-nncontainer-Z1iG3WA wp-block-lazyblock-nncontainer\"><div class=\"section-standard\">\r\n  <div class=\"container\" id=\"container-Z1iG3WA\">\r\n    <div class=\"row\">\r\n      <div class=\"col py-4 py-lg-5\">\r\n        <div class=\"lazyblock-inner-blocks\">\n\n<p class=\"wp-block-paragraph\">You reached this page because you searched for &#8220;men\u2019s bikes&#8221;. Many use \u201cmen\u2019s bike\u201d as a synonym for bikes \u201cwith a bar\u2014more precisely, a top tube. Modern terms like high-step or stepover better describe the frame style. These labels focus on the actual distinction: It\u2019s all about how you mount the bike and what you prefer aesthetically. Whatever you call them, we&#8217;re here to help you find the perfect bike for your needs.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Almost our entire range of bikes comes in multiple frame styles. Our newest e-bikes can flexibly transform from stepover to lowstep and back. Those bkes turn the \u00abbar\u00bb into a multifunctional modular accessory bar to carry some of your stuff.&nbsp;&nbsp;<\/p>\n\n<\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div><\/div>\n\n<div class=\"lazyblock-nncontainer-sfmjb wp-block-lazyblock-nncontainer\"><div class=\"section-light\">\r\n  <div class=\"container\" id=\"container-sfmjb\">\r\n    <div class=\"row\">\r\n      <div class=\"col py-4 py-lg-5\">\r\n        <div class=\"lazyblock-inner-blocks\">\n<div class=\"lazyblock-bikefinder-Z2mdr1x wp-block-lazyblock-bikefinder\"><template id=\"bikeTeaserComponent\">\n  <template x-if=\"frames.value.length\">\n    <div class=\"bikefinder-tile px-3 py-4 px-lg-4\" :class=\"classNames\">\n      <div class=\"bikefinder-tile-content\">\n        <a :href=\"selectedFrame.value.link\" class=\"bikefinder-title\">\n          <h4\n            class=\"mb-0\"\n            x-text=\"extractOrCleanString(selectedFrame.value.title)\"\n          ><\/h4>\n        <\/a>\n\n        <p\n          class=\"bikefinder-subtitle\"\n          x-text=\"$store.utils.t($store.utils.translations.frames[extractOrCleanString(selectedFrame.value.title, true)])\"\n        ><\/p>\n\n        <div\n          class=\"bikefinder-preis\"\n          x-text=\"getAbText() + ' ' + formatNumber(selectedFrame.value.price_lowest) + ' ' + getCurrency()\"\n        ><\/div>\n        <a :href=\"selectedFrame.value.link\" class=\"color-images mx-auto mb-4\"\n          ><picture>\n            <img\n              :src=\"selectedFrameImage.value\"\n              class=\"img-fluid lazy\"\n              :alt=\"selectedFrame.value.title\"\n          \/><\/picture>\n        <\/a>\n\n        <div class=\"bikefinder-controls mb-3\">\n          <div class=\"color-switch\">\n            <template x-for=\"(color, index) in selectedFrame.value.colors\">\n              <span\n                @click=\"onColorClicked(color)\"\n                :class=\"'bike-color-' + color.value.toLowerCase()\"\n                data-bs-toggle=\"tooltip\"\n                data-bs-placement=\"top\"\n                :title=\"color.description\"\n              ><\/span>\n            <\/template>\n          <\/div>\n\n          <div class=\"bikefinder-rahmen\">\n            <ul\n              class=\"nav nav-tabs\"\n              x-data=\"{ frames: framesAsGenerations ? selectedFrameByGeneration: frames }\"\n            >\n              <template x-for=\"(frame, index) in frames.value\">\n                <li\n                  class=\"nav-item\"\n                  @click=\"onFrameClicked(frame)\"\n                  x-show=\"!framesAsGenerations || isFrameInFiltered(frame)\"\n                >\n                  <span\n                    class=\"nav-link\"\n                    :class=\"selectedFrame.value.id == frame.id ? 'active' : ''\"\n                    x-data=\"{ meta: getFrameMeta(frame.frameType) }\"\n                  >\n                    <img\n                      width=\"48\"\n                      height=\"28\"\n                      :src=\"meta.icon\"\n                      data-bs-toggle=\"tooltip\"\n                      data-bs-placement=\"top\"\n                      :title=\"$store.utils.t(meta.text)\"\n                    \/>\n                  <\/span>\n                <\/li>\n              <\/template>\n            <\/ul>\n          <\/div>\n        <\/div>\n      <\/div>\n      <template x-if=\"framesAsGenerations\">\n        <div\n          x-data=\"generation({ generations: frames, generationClickedCallback: generationsCallback })\"\n        ><\/div>\n      <\/template>\n    <\/div>\n  <\/template>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\n      \"biketeaser\",\n      ({ frames, framesAsGenerations, framesMeta }) => ({\n        template: null,\n        frames: { value: frames },\n        selectedFrameByGeneration: { value: [] },\n        selectedFrame: { value: null },\n        framesMeta: framesMeta,\n        selectedFrameImage: {},\n        framesAsGenerations: framesAsGenerations,\n        generationsCallback: null,\n        classNames: \"\",\n        currentVariant: null,\n        init() {\n          this.setup();\n          this.$nextTick(() => {\n            this.mounted();\n            this.render();\n          });\n        },\n        setup() {\n          this.template = document.getElementById(\"bikeTeaserComponent\");\n        },\n        mounted() {\n          if (this.frames.value.length) {\n            if (this.framesAsGenerations) {\n              this.selectedFrameByGeneration.value = this.frames.value[0];\n              this.selectedFrame.value = this.frames.value[0];\n            } else {\n              this.selectedFrame.value = this.frames.value;\n            }\n\n            const frame = this.getFrameWithSpecialRecommendedRetailpriceOrFirst(\n              this.selectedFrame.value,\n            );\n\n            let variant = this.getVariantsWithKey(\n              frame,\n              \"special_recommended_retailprice\",\n            )[0];\n            if (!variant) {\n              variant = frame.variants[0];\n            }\n\n            const uniqueFrameImageOfVariant = this.getImageByVariant(\n              frame,\n              variant,\n            );\n\n            this.selectedFrame.value = frame;\n            this.selectedFrameImage = uniqueFrameImageOfVariant;\n\n            this.setClassNames(variant.id);\n          }\n          this.generationsCallback = this.onGenerationClicked.bind(this);\n        },\n        render() {\n          this.$el.innerHTML = this.template.innerHTML;\n        },\n        getFrameWithSpecialRecommendedRetailpriceOrFirst(frames) {\n          const frame = frames.find((frame) => {\n            return frame.hasOwnProperty(\"special_recommended_retailprice\");\n          });\n          return frame ? frame : frames[0];\n        },\n        getVariantsWithKey(frame, key, value = \"\") {\n          if (\n            frame.commonValues.hasOwnProperty(key) &&\n            (value ? frame.commonValues[key] === value : true)\n          ) {\n            return frame.variants;\n          }\n\n          return frame.variants.filter((variant) => {\n            return variant[key] && (value ? variant[key] === value : true);\n          });\n        },\n        getRecomendedRetailpriceVariantColor(color) {\n          const variantsWithPrice = this.getVariantsWithKey(\n            this.selectedFrame.value,\n            \"special_recommended_retailprice\",\n          );\n\n          const variantsWithColor = this.getVariantsWithKey(\n            this.selectedFrame.value,\n            \"primary_basecolour\",\n            color.value,\n          );\n\n          const variantsWithPriceIds = variantsWithPrice.map(\n            (variant) => variant.id,\n          );\n          let variant = variantsWithPrice.find((variant) =>\n            variantsWithPriceIds.includes(variant.id),\n          );\n          if (!variant) {\n            variant = variantsWithColor.length ? variantsWithColor[0] : this.selectedFrame.value.variants[0];\n          }\n\n          return {\n            value: variant ? variant.value : \"\",\n            variantId: variant ? variant.id : null,\n          };\n        },\n        getImageByVariant(frame, variant) {\n          if (!variant) {\n            return { value: frame?.commonValues?.pos_image, variantId: null };\n          }\n          const uniqueImage = frame.images?.find((image) => {\n            return image.value == variant[image.propertyPath];\n          });\n\n          return uniqueImage\n            ? { value: uniqueImage.value, variantId: variant.id }\n            : { value: frame.commonValues?.pos_image, variantId: variant.id };\n        },\n        isFrameInFiltered(frame) {\n          return frame.hasVariants.length ? true : false;\n        },\n        extractTextInBrackets(text) {\n          const match = text.match(\/\\((.*?)\\)\/);\n          return match ? match[1] : \"\";\n        },\n        onFrameClicked(frame) {\n          this.selectedFrame.value = frame;\n          const variantsWithPrice = this.getVariantsWithKey(\n            frame,\n            \"special_recommended_retailprice\",\n          );\n\n          const variantsWithPosImage = this.getVariantsWithKey(\n            frame,\n            \"pos_image\",\n          );\n\n          const variantsWithPriceIds = variantsWithPrice.map(\n            (variant) => variant.id,\n          );\n\n          let variant = variantsWithPrice.find((variant) =>\n            variantsWithPriceIds.includes(variant.id),\n          );\n          if (!variant) {\n            variant = frame.variants[0];\n          }\n\n          const uniqueFrameImageOfVariant = this.getImageByVariant(\n            frame,\n            variant,\n          );\n\n          this.selectedFrameImage = uniqueFrameImageOfVariant;\n          this.setClassNames(variant.id);\n        },\n        onGenerationClicked(generation) {\n          this.selectedFrameByGeneration.value = generation;\n          this.selectedFrame.value = this.selectedFrameByGeneration.value[0];\n          this.selectedFrameImage = this.selectedFrame.value.images[0];\n          this.setClassNames(this.selectedFrame.value.images[0].variantId);\n        },\n        onColorClicked(color) {\n          this.selectedFrameImage = this.selectedFrame.value.images.find(\n            (image) => image.variantId == color.variantId,\n          );\n\n          const colorRetailprice =\n            this.getRecomendedRetailpriceVariantColor(color);\n          this.setClassNames(colorRetailprice.variantId);\n        },\n        setClassNames(variantId) {\n          \/\/ Maybe many?\n          this.currentVariant = this.selectedFrame.value.variants.find(\n            (variant) => {\n              return variant.id === variantId;\n            },\n          );\n\n          let names = [];\n          if (this.isReducedPrice(this.currentVariant) && this.isLastChance()) {\n            names.push(\"sale\");\n            names.push(\"lastchance\");\n          } else if (this.isReducedPrice(this.currentVariant)) {\n            names.push(\"sale\");\n          } else if (this.isLastChance()) {\n            names.push(\"lastchance\");\n          }\n\n          if (this.isNewBike()) {\n            names.push(\"newbike\");\n          }\n          this.classNames = names.join(\" \");\n        },\n        getPriceText(price) {\n          return \"Ab \" + price + \" EUR\";\n        },\n        formatNumber(number) {\n          if (this.$store.utils.country === \"CH\") {\n            return number.toString().replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \"'\");\n          } else {\n            return number.toString().replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \".\");\n          }\n        },\n        getAbText() {\n          const lang = this.$store.utils.lang;\n          return (\n            {\n              da: \"Fra\",\n              de: \"Ab\",\n              en: \"From\",\n              fi: \"Alkaen\",\n              fr: \"\u00c0 partir de\",\n              nl: \"Vanaf\",\n              pl: \"Od\",\n              sv: \"Fr\u00e5n\",\n            }[lang] || \"Ab\"\n          );\n        },\n        getCurrency() {\n          const currencyMap = {\n            CH: \"CHF\",\n            DK: \"DKK\",\n            GB: \"GBP\",\n            PL: \"PLN\",\n            SE: \"SEK\",\n          };\n          const country = this.$store.utils.country;\n          return currencyMap[country] || \"EUR\";\n        },\n        isReducedPrice(variant) {\n          if (variant && variant.special_recommended_retailprice) {\n            return variant.special_recommended_retailprice;\n          }\n          return this.selectedFrame.value.specialRecommendedRetailprice.find(\n            (price) => price.variantId === this.selectedFrame.value.id,\n          );\n        },\n        isLastChance() {\n          return this.selectedFrame.value.lastchance;\n        },\n        isNewBike() {\n          return this.selectedFrame.value.newbike;\n        },\n        removeAllBrackets(str) {\n          const regex = \/\\[.*?\\]|\\(.*?\\)|\\{.*?\\}\/g;\n          return str.replace(regex, \"\");\n        },\n        extractBrackets(str) {\n          const regex = \/\\[.*?\\]|\\(.*?\\)|\\{.*?\\}\/g;\n\n          const matches = str.match(regex);\n\n          return matches || [];\n        },\n        getFrameMeta(frameType) {\n          return this.framesMeta[frameType] || { icon: '', text: '' };\n        },\n        extractOrCleanString(str, returnExtracted = false) {\n          if (!str) return \"\";\n          const pattern =\n            \/\\(?\\b(HCH|MIT|Lowstep|SCH|TIE|Midstep|Stepover|HER|TRA)\\b\\)?\/i;\n          const match = str.match(pattern);\n\n          if (match) {\n            return returnExtracted\n              ? match[1]\n              : str.replace(pattern, \"\").replace(\/\\s+\/g, \" \").trim();\n          }\n\n          return returnExtracted ? null : str.trim();\n        },\n      }),\n    );\n  });\n<\/script>\n<template id=\"generationComponent\">\n  <template x-if=\"getGenerationWithoutActive().length\">\n    <div class=\"dropdown bikefinder-generations\">\n      <button\n        class=\"btn btn-secondary dropdown-toggle p-0\"\n        type=\"button\"\n        :id=\"'dropdownGenerations-' + selectedGeneration.id\"\n        data-bs-toggle=\"dropdown\"\n        aria-expanded=\"false\"\n        x-text=\"$store.utils.t($store.utils.translations.futureGenerations)\"\n      ><\/button>\n      <div\n        class=\"dropdown-menu dropdown-generations\"\n        :aria-labelledby=\"'dropdownGenerations-' + selectedGeneration.id\"\n      >\n        <template\n          x-for=\"(generation, index) in getGenerationWithoutActive(generations)\"\n          :key=\"'genNav-' + index\"\n        >\n          <a\n            @click=\"onGenerationClicked(generation)\"\n            class=\"dropdown-item\"\n            x-text=\"mainTitle(generation)\"\n          ><\/a>\n        <\/template>\n      <\/div>\n    <\/div>\n  <\/template>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\"generation\", ({ generations, generationClickedCallback }) => ({\n      template: null,\n      generations: generations,\n      selectedGeneration: {},\n      selectedFrameImage: {},\n      generationClickedCallback: generationClickedCallback,\n      init() {\n        this.setup();\n        this.$nextTick(() => {\n          this.mounted();\n          this.render();\n        });\n      },\n      setup() {\n        this.template = document.getElementById(\"generationComponent\");\n      },\n      mounted() {\n        if (this.generations.value.length) {\n          this.selectedGeneration = this.generations.value[0];\n        }\n      },\n      render() {\n        this.$el.innerHTML = this.template.innerHTML;\n      },\n      onGenerationClicked(generation) {\n        this.generationClickedCallback(generation);\n        this.selectedGeneration = generation;\n      },\n      active(generation, selectedGeneration) {\n        return generation === selectedGeneration;\n      },\n      getGenerationWithoutActive() {\n        return this.generations.value.filter(\n          (generation) => generation != this.selectedGeneration\n        );\n      },\n      getGenerationFrame(generation) {\n        return generation[0];\n      },\n      extractOrCleanString(str, returnExtracted = false) {\n        const pattern =\n          \/\\(?\\b(HCH|MIT|Lowstep|SCH|TIE|Midstep|Stepover|HER|TRA)\\b\\)?\/i;\n        const match = str.match(pattern);\n\n        if (match) {\n          return returnExtracted\n            ? match[1]\n            : str.replace(pattern, \"\").replace(\/\\s+\/g, \" \").trim();\n        }\n\n        return returnExtracted ? null : str.trim();\n      },\n      mainTitle(generation) {\n        let frame = this.getGenerationFrame(generation);\n        let title = this.extractOrCleanString(frame.title);\n        return (\n          title +\n          \" \" +\n          this.addModelYear(frame) +\n          \" - \" +\n          this.formatNumber(frame.price_lowest) +\n          \" \" +\n          this.getCurrency()\n        );\n      },\n      addModelYear(frame) {\n        if (frame.modelYear) {\n          return \" (\" + frame.modelYear + \")\";\n        }\n        return \"\";\n      },\n      getCurrency() {\n        const currencyMap = {\n          CH: \"CHF\",\n          DK: \"DKK\",\n          GB: \"GBP\",\n          PL: \"PLN\",\n          SE: \"SEK\",\n        };\n        const country = this.$store.utils.country;\n        return currencyMap[country] || \"EUR\";\n      },\n      formatNumber(number) {\n        if (this.$store.utils.country === \"CH\") {\n          return number.toString().replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \"'\");\n        } else {\n          return number.toString().replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, \".\");\n        }\n      },\n    }));\n  });\n<\/script>\n<template id=\"filterComponent\">\n  <template x-if=\"showReset\">\n    <div id=\"filter\" class=\"bikefinder-filter mb-5 text-start\">\n      <h5 class=\"text-uppercase h-underline mt-4 position-relative\">\n        Filter\n        <div x-show=\"isFilterActive()\" class=\"small reset-filters\">\n          <span\n            @click=\"resetFilter()\"\n            class=\"btn-reset-filters\"\n            x-text=\"$store.utils.t($store.utils.translations.resetFilter)\"\n          >\n          <\/span>\n        <\/div>\n      <\/h5>\n      <div class=\"bike-counter mb-4\">\n        <span id=\"bikeCount\" x-text=\"countOfFilteredBikes.value\"><\/span> Bikes\n      <\/div>\n\n      <!-- Biketyp -->\n      <h5\n        class=\"mb-1\"\n        x-text=\"$store.utils.t($store.utils.translations.bikeType)\"\n      ><\/h5>\n      <div\n        class=\"small text-grey mb-2\"\n        x-text=\"$store.utils.t($store.utils.translations.bikeTypeSpeed)\"\n      ><\/div>\n      <div\n        x-key=\"'typeLineSelection'\"\n        x-data=\"lineselection(\n        { \n            items: typeFilterProps.sort((a, b) => a.context.order < b.context.order ? -1 : 1),\n            onSelected: onTypeSelected,\n            selectedFilter: selectedFilter,\n        }\n      )\"\n      ><\/div>\n\n      <template x-if=\"!hideBattery\">\n        <div class=\"bikefinder-filter-akku\">\n          <!-- Akku -->\n          <h5\n            class=\"mb-1\"\n            x-text=\"$store.utils.t($store.utils.translations.battery)\"\n          ><\/h5>\n          <div\n            class=\"small text-grey mb-2\"\n            x-text=\"$store.utils.t($store.utils.translations.unitBattery)\"\n          ><\/div>\n          <div\n            x-show=\"showReset\"\n            x-data=\"sliderselection(\n            { \n                items: batteryFilterProps,\n                onSelected: onBatterySelected,\n                id: 'battery-slider',\n                domLoaded: domLoaded,\n                options: { step: 100, values: true }\n            }\n          )\"\n          ><\/div>\n        <\/div>\n      <\/template>\n\n      <!-- Rahmenformen -->\n      <h5 x-text=\"$store.utils.t($store.utils.translations.frameShape)\"><\/h5>\n\n      <div\n        x-key=\"'frameLineSelection'\"\n        x-data=\"lineselection(\n        { \n            items: frameFilterProps.sort((a, b) => a.context.order < b.context.order ? -1 : 1),\n            onSelected: onFrameSelected,\n            selectedFilter: selectedFilter,\n        }\n      )\"\n      ><\/div>\n\n      <!-- Schaltung -->\n      <h5 x-text=\"$store.utils.t($store.utils.translations.gear)\"><\/h5>\n      <div\n        x-data=\"choiceselection(\n        { \n            items: gearFilterProps,\n            onSelected: onGearSelected \n        }\n      )\"\n      ><\/div>\n\n      <!-- Preis -->\n      <h5\n        class=\"mb-1\"\n        x-text=\"$store.utils.t($store.utils.translations.price)\"\n      ><\/h5>\n      <div\n        class=\"small text-grey mb-2\"\n        x-text=\"$store.utils.t($store.utils.translations.inCurrency)\"\n      ><\/div>\n      <div\n        x-data=\"sliderselection(\n        { \n            items: priceFilterProps,\n            onSelected: onPriceSelected,\n            id: 'price-slider',\n            domLoaded: domLoaded,\n            options: { step: 100 }\n        }\n      )\"\n      ><\/div>\n\n      <!-- Sale -->\n      <h5 x-text=\"$store.utils.t($store.utils.translations.sale)\"><\/h5>\n      <div\n        x-data=\"multiplechoiceselection(\n        { \n            items: saleFilterProps.concat(lastchanceFilterProps),\n            onSelected: onSaleOrLastchanceSelected \n        }\n      )\"\n      ><\/div>\n\n      <!-- Farben -->\n      <h5 x-text=\"$store.utils.t($store.utils.translations.color)\"><\/h5>\n      <div\n        x-data=\"colorselection(\n        { \n            items: colorFilterProps,\n            onSelected: onColorSelected \n        }\n      )\"\n      ><\/div>\n\n      <!-- Gewicht -->\n      <h5\n        class=\"mb-1\"\n        x-text=\"$store.utils.t($store.utils.translations.weight)\"\n      ><\/h5>\n      <div\n        class=\"small text-grey mb-2\"\n        x-text=\"$store.utils.t($store.utils.translations.unitWeight)\"\n      ><\/div>\n      <div\n        class=\"rslider\"\n        x-data=\"sliderselection(\n        { \n            items: weightFilterProps,\n            onSelected: onWeightSelected,\n            id: 'weight-slider',\n            domLoaded: domLoaded\n        }\n      )\"\n      ><\/div>\n    <\/div>\n  <\/template>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\n      \"filter\",\n      ({\n        frameFilterProps,\n        typeFilterProps,\n        batteryFilterProps,\n        gearFilterProps,\n        priceFilterProps,\n        weightFilterProps,\n        saleFilterProps,\n        lastchanceFilterProps,\n        newbikeFilterProps,\n        countOfFilteredBikes,\n        maxBikesCount,\n        colorFilterProps,\n        selectedFilter,\n        controller,\n      }) => ({\n        template: null,\n        frameFilterProps: frameFilterProps,\n        typeFilterProps: typeFilterProps,\n        batteryFilterProps: batteryFilterProps,\n        gearFilterProps: gearFilterProps,\n        priceFilterProps: priceFilterProps,\n        weightFilterProps: weightFilterProps,\n        saleFilterProps: saleFilterProps,\n        lastchanceFilterProps: lastchanceFilterProps,\n        newbikeFilterProps: newbikeFilterProps,\n        countOfFilteredBikes: countOfFilteredBikes,\n        maxBikesCount: maxBikesCount,\n        colorFilterProps: colorFilterProps,\n        selectedFrame: {},\n        selectedFrameImage: {},\n        controller: controller,\n        showReset: true,\n        domLoaded: false,\n        domUpdate: { value: 0 },\n        selectedFilter: selectedFilter,\n        hideBattery: false,\n        init() {\n          this.setup();\n          this.$nextTick(() => {\n            this.mounted();\n            this.render();\n          });\n        },\n        setup() {\n          this.template = document.getElementById(\"filterComponent\");\n        },\n        mounted() {},\n        render() {\n          this.$el.innerHTML = this.template.innerHTML;\n\n          document.addEventListener(\"DOMContentLoaded\", () => {\n            this.domLoaded = true;\n          });\n\n          this.$watch(\"selectedFilter\", (filter) => {\n            this.hideFilterSections(filter);\n          });\n        },\n        hideFilterSections(filter) {\n          \/\/ Hide Battery\n          const hideBattery = [\"Bike\", \"S-Pedelec\"].includes(\n            filter.properties?.category?.value\n          );\n\n          if (hideBattery) {\n            this.hideBattery = true;\n          } else {\n            this.hideBattery = false;\n          }\n        },\n        onFrameSelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, initial);\n        },\n        onTypeSelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, initial);\n        },\n        onBatterySelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, initial);\n        },\n        onGearSelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, initial);\n        },\n        onPriceSelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, initial);\n        },\n        onWeightSelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, initial);\n        },\n        onSaleOrLastchanceSelected(property, checked, initial = true) {\n          if (checked) {\n            this.controller.filterAddPropertyAction(property, initial);\n          } else {\n            this.controller.filterRemovePropertyAction(property);\n          }\n        },\n        onColorSelected(property, initial = true) {\n          this.controller.filterAddPropertyAction(property, true);\n        },\n        resetFilter() {\n          this.showReset = false;\n          this.controller.resetFilterAction();\n\n          this.$nextTick(() => {\n            this.showReset = true;\n          });\n        },\n        isFilterActive() {\n          return !this.selectedFilter.initial;\n        },\n      })\n    );\n  });\n<\/script>\n<template id=\"lineSelectionComponent\">\n  <div class=\"bikefilter-biketyp mb-4\">\n    <ul class=\"nav nav-tabs\">\n      <template x-for=\"(item, index) in items\">\n        <li class=\"nav-item\">\n          <button\n            @click=\"selected(item, index)\"\n            class=\"nav-link\"\n            :class=\"activeItem &#038;&#038; activeItem.value === item.value ? 'active' : ''\"\n            style=\"outline: none\"\n            data-bs-toggle=\"tooltip\"\n            data-placement=\"top\"\n            :title=\"$store.utils.t(item.context.text)\"\n          >\n            <template x-if=\"item.context &#038;&#038; item.context.type == 'icon'\">\n              <img :src=\"item.context.icon\" style=\"width: 48px; height: 28px\" \/>\n            <\/template>\n            <template x-if=\"item.context &#038;&#038; item.context.type == 'text'\">\n              <span\n                style=\"width: 48px; height: 28px\"\n                x-text=\"$store.utils.t(item.context.text)\"\n              ><\/span>\n            <\/template>\n          <\/button>\n        <\/li>\n      <\/template>\n    <\/ul>\n  <\/div>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\"lineselection\", ({ items, onSelected, selectedFilter }) => ({\n      template: null,\n      items: items,\n      onSelected: onSelected,\n      selectedFilter: selectedFilter,\n      selectedIndex: -1,\n      activeItem: null,\n      init() {\n        this.setup();\n        this.$nextTick(() => {\n          this.mounted();\n          this.render();\n        });\n      },\n      setup() {\n        this.template = document.getElementById(\"lineSelectionComponent\");\n      },\n      mounted() {\n        this.$watch(\"selectedFilter\", (filter) => {\n          this.activeItem = this.findActiveItem(filter);\n        });\n      },\n      render() {\n        this.$el.innerHTML = this.template.innerHTML;\n      },\n      selected(item, index) {\n        this.selectedIndex = index;\n        this.onSelected(item, false);\n      },\n      findActiveItem(filter) {\n        if (this.items[0].propertyPath in filter.properties) {\n          let found = this.items.find((item) => {\n            return (\n              item.value === filter.properties[this.items[0].propertyPath].value\n            );\n          });\n          return found;\n        }\n      },\n    }));\n  });\n<\/script>\n<template id=\"sliderSelectionComponent\">\n\t<div :style=\"!sliderReady ? 'opacity: 0' : ''\" class=\"bikefilter-rahmenform mb-4 mt-3\">\n\t\t<div :style=\"!domLoaded &#038;&#038; !slider ? 'opacity: 0' : ''\">\n\t\t\t<input :id=\"id\" type=\"range\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/template>\n\n<script>\n\tdocument.addEventListener(\"alpine:init\", () => {\n\t\tAlpine.data(\"sliderselection\", ({ items, onSelected, id, domLoaded, options = {} }) => ({\n\t\t\ttemplate: null,\n\t\t\titems: [],\n\t\t\tonSelected: onSelected,\n\t\t\tid: id,\n\t\t\tvalue: 0,\n\t\t\tslider: items,\n\t\t\tdomLoaded: domLoaded,\n\t\t\tmin: 0,\n\t\t\tmax: 0,\n\t\t\toptions: options,\n\t\t\tinitial: true,\n\t\t\tsliderReady: false,\n\t\t\tinit() {\n\t\t\t\tthis.setup();\n\t\t\t\tthis.$nextTick(() => {\n\t\t\t\t\tthis.mounted();\n\t\t\t\t\tthis.render();\n\t\t\t\t});\n\t\t\t},\n\t\t\tsetup() {\n\t\t\t\tthis.template = document.getElementById(\"sliderSelectionComponent\");\n\t\t\t},\n\t\t\tmounted() {\n\t\t\t\tif (items.length) {\n\t\t\t\t\tthis.items = items.sort((a, b) => (Number(a.value) > Number(b.value) ? 1 : -1));\n\n\t\t\t\t\tthis.min = this.items[0].value;\n\t\t\t\t\tthis.max = this.items.slice(-1)[0].value;\n\t\t\t\t\tthis.value = this.max;\n\t\t\t\t}\n\t\t\t},\n\t\t\trender() {\n\t\t\t\tthis.$el.innerHTML = this.template.innerHTML;\n\n\t\t\t\tdocument.addEventListener(\"DOMContentLoaded\", () => {\n\t\t\t\t\tthis.domLoaded = true;\n\t\t\t\t\tthis.initRangeSlider();\n\t\t\t\t});\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (!this.domLoaded) {\n\t\t\t\t\t\tthis.initRangeSlider();\n\t\t\t\t\t}\n\t\t\t\t}, 400);\n\t\t\t},\n\t\t\tinitRangeSlider() {\n\t\t\t\tthis.domLoaded = true;\n\t\t\t\tthis.initial = true;\n\n\t\t\t\tconst min = this.roundMin(parseInt(this.min, 10));\n\t\t\t\tconst max = this.roundMax(parseInt(this.max, 10));\n\n\t\t\t\tthis.slider = new rSlider({\n\t\t\t\t\ttarget: \"#\" + this.id,\n\t\t\t\t\tvalues: options.values && options.values == true ? this.getAllValues() : { min: min, max: max },\n\t\t\t\t\trange: true,\n\t\t\t\t\ttooltip: true,\n\t\t\t\t\tstep: options.step ? options.step : 1,\n\t\t\t\t\tscale: false,\n\t\t\t\t\tlabels: true,\n\t\t\t\t\tvariableWidth: true,\n\t\t\t\t\tunit: \"kg\",\n\t\t\t\t\tset: [this.min, this.max],\n\t\t\t\t\tonChange: (vals) => {\n\t\t\t\t\t\t\/\/ vals is not correct so get from index\n\t\t\t\t\t\tlet min = Number(this.slider.conf.values[this.slider.values.start]);\n\t\t\t\t\t\tlet max = Number(this.slider.conf.values[this.slider.values.end]);\n\t\t\t\t\t\tthis.setValue(min, max);\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tconst sliderElements = document.querySelectorAll(\".rs-container\");\n\t\t\t\tsliderElements.forEach((element) => {\n\t\t\t\t\telement.addEventListener(\"mousedown\", () => {\n\t\t\t\t\t\tthis.initial = false;\n\t\t\t\t\t});\n\t\t\t\t\telement.addEventListener(\"touchstart\", () => {\n\t\t\t\t\t\tthis.initial = false;\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\tthis.sliderReady = true;\n\t\t\t},\n\t\t\tsetValue(min, max) {\n\t\t\t\tlet range = this.items.filter((item) => {\n\t\t\t\t\tconst itemValue = Number(item.value);\n\t\t\t\t\treturn itemValue >= min && itemValue <= max;\n\t\t\t\t});\n\t\t\t\tif (range.length === 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet maxOfRange = range.reduce((max, obj) => {\n\t\t\t\t\treturn Number(obj.value) > Number(max.value) ? obj : max;\n\t\t\t\t}, range[0]);\n\n\t\t\t\tlet minOfRange = range.reduce((min, obj) => {\n\t\t\t\t\treturn Number(obj.value) < Number(min.value) ? obj : min;\n\t\t\t\t}, range[0]);\n\n\t\t\t\tif (maxOfRange) {\n\t\t\t\t\tif (minOfRange) {\n\t\t\t\t\t\tmaxOfRange[\"min\"] = minOfRange.value;\n\t\t\t\t\t\tthis.select(maxOfRange, false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tselect(property) {\n\t\t\t\tthis.onSelected(property, this.initial);\n\t\t\t},\n\t\t\tgetAllValues() {\n\t\t\t\treturn this.items.map((item) => Number(item.value));\n\t\t\t},\n\t\t\troundMin(num) {\n\t\t\t\tif (num > 100) {\n\t\t\t\t\treturn Math.floor(num \/ 50) * 50;\n\t\t\t\t} else {\n\t\t\t\t\treturn Math.floor(num \/ 10) * 10;\n\t\t\t\t}\n\t\t\t},\n\t\t\troundMax(num) {\n\t\t\t\tif (num > 100) {\n\t\t\t\t\treturn Math.ceil(num \/ 50) * 50;\n\t\t\t\t} else {\n\t\t\t\t\treturn Math.ceil(num \/ 10) * 10;\n\t\t\t\t}\n\t\t\t},\n\t\t}));\n\t});\n<\/script>\n<template id=\"choiceSelectionComponent\">\n  <div class=\"bikefilter-schaltung mb-4\">\n    <fieldset>\n      <template x-for=\"(item, index) in items\">\n        <div class=\"form-check\">\n          <input\n            type=\"radio\"\n            :id=\"item.propertyPath + index\"\n            name=\"drone\"\n            value=\"huey\"\n            x-on:input.change=\"onSelected(item, false)\"\n            class=\"form-check-input\"\n          \/>\n          <label\n            :for=\"item.propertyPath + index\"\n            x-text=\"$store.utils.t(item.context.text)\"\n            class=\"form-check-label\"\n          ><\/label>\n        <\/div>\n      <\/template>\n    <\/fieldset>\n  <\/div>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\"choiceselection\", ({ items, onSelected }) => ({\n      template: null,\n      items: items,\n      onSelected: onSelected,\n      value: 0,\n      init() {\n        this.setup();\n        this.$nextTick(() => {\n          this.mounted();\n          this.render();\n        });\n      },\n      setup() {\n        this.template = document.getElementById(\"choiceSelectionComponent\");\n      },\n      mounted() {},\n      render() {\n        this.$el.innerHTML = this.template.innerHTML;\n      },\n    }));\n  });\n<\/script>\n<template id=\"multipleChoiceSelectionComponent\">\n  <div class=\"bikefilter-schaltung mb-4\">\n    <fieldset>\n      <template x-for=\"(item, index) in items\">\n        <div class=\"form-check\">\n          <input\n            type=\"checkbox\"\n            :id=\"item.propertyPath + index\"\n            name=\"drone\"\n            value=\"huey\"\n            x-on:input.change=\"onSelected(item, $event.target.checked, false)\"\n            class=\"form-check-input\"\n          \/>\n          <label\n            :for=\"item.propertyPath + index\"\n            x-text=\"$store.utils.t(item.context.text)\"\n            class=\"form-check-label\"\n          ><\/label>\n        <\/div>\n      <\/template>\n    <\/fieldset>\n  <\/div>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\"multiplechoiceselection\", ({ items, onSelected }) => ({\n      template: null,\n      items: items,\n      onSelected: onSelected,\n      value: 0,\n      init() {\n        this.setup();\n        this.$nextTick(() => {\n          this.mounted();\n          this.render();\n        });\n      },\n      setup() {\n        this.template = document.getElementById(\n          \"multipleChoiceSelectionComponent\"\n        );\n      },\n      mounted() {},\n      render() {\n        this.$el.innerHTML = this.template.innerHTML;\n      },\n    }));\n  });\n<\/script>\n<template id=\"colorSelectionComponent\">\n  <div class=\"color-options mb-4\">\n    <ul class=\"ps-0\">\n      <template x-for=\"(item, index) in items\">\n        <li>\n          <button\n            @click=\"selected(item, index, false)\"\n            :class=\"'btn filter-color-' + item.value.toLowerCase() + ' ' + ((selectedIndex == index) ? 'active' : '')\"\n            data-bs-toggle=\"tooltip\"\n            data-placement=\"top\"\n            :title=\"item.description\"\n          ><\/button>\n        <\/li>\n      <\/template>\n    <\/ul>\n  <\/div>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\"colorselection\", ({ items, onSelected }) => ({\n      template: null,\n      items: items,\n      onSelected: onSelected,\n      selectedIndex: -1,\n      init() {\n        this.setup();\n        this.$nextTick(() => {\n          this.mounted();\n          this.render();\n        });\n      },\n      setup() {\n        this.template = document.getElementById(\"colorSelectionComponent\");\n      },\n      mounted() {},\n      render() {\n        this.$el.innerHTML = this.template.innerHTML;\n      },\n      selected(item, index, initial) {\n        this.selectedIndex = index;\n        this.onSelected(item, initial);\n      },\n    }));\n  });\n<\/script>\n<template id=\"bikefinderComponent\">\n  <div class=\"bikefinder\">\n    <div class=\"row\">\n      <div class=\"col-md-4 col-lg-3 bikefinder-filter-col\">\n        <button\n          class=\"btn btn-primary filter-toggle d-md-none mb-3\"\n          data-show=\"Filter anzeigen\"\n          data-hide=\"Filter ausblenden\"\n          x-text=\"$store.utils.t($store.utils.translations.showFilter)\"\n        ><\/button>\n\n        <div\n          class=\"bikefinder-filter-content\"\n          x-data=\"filter({ \n            frameFilterProps: uniquePropFrames(), \n            typeFilterProps: model.uniquePropTypes(), \n            batteryFilterProps: uniquePropBatteries(), \n            gearFilterProps: uniquePropGears(),\n            priceFilterProps: uniquePropPrices(),\n            weightFilterProps: uniquePropWeights(),\n            saleFilterProps: model.uniquePropSales(),\n            lastchanceFilterProps: model.uniquePropLastchance(),\n            newbikeFilterProps: model.uniquePropNewbike(),\n            countOfFilteredBikes: state.countOfFilteredBikes,\n            maxBikesCount: state.maxBikesCount,\n            colorFilterProps: uniquePropColors(),\n            selectedFilter: state.selectedFilter,\n            controller: controller\n          })\"\n        ><\/div>\n      <\/div>\n      <div class=\"col-md-8 col-lg-9\">\n        <div class=\"dropdown text-end dropdown-underline\">\n          <button\n            class=\"btn btn-secondary dropdown-toggle p-0 pb-1 me-3 me-md-4\"\n            type=\"button\"\n            id=\"dropdownSort\"\n            data-bs-toggle=\"dropdown\"\n            aria-haspopup=\"true\"\n            aria-expanded=\"false\"\n            x-text=\"$store.utils.t($store.utils.translations.sortBy)\"\n          ><\/button>\n\n          <div\n            class=\"dropdown-menu dropdown-menu-end dropdown-sort\"\n            aria-labelledby=\"dropdownSort\"\n          >\n            <a\n              @click=\"controller.sortNewestAlphaAction()\"\n              class=\"dropdown-item\"\n              :class=\"state.currentSort == 'newestalpha' ? 'active' : ''\"\n              id=\"sort-newest-alpha\"\n              x-text=\"$store.utils.t($store.utils.translations.sortByNewestAlpha)\"\n            ><\/a>\n            <a\n              @click=\"controller.sortAlphaAction()\"\n              class=\"dropdown-item\"\n              :class=\"state.currentSort == 'alpha' ? 'active' : ''\"\n              id=\"sort-alpha\"\n              x-text=\"$store.utils.t($store.utils.translations.sortByAlpha)\"\n            ><\/a>\n            <a\n              @click=\"controller.sortPriceAction()\"\n              class=\"dropdown-item\"\n              :class=\"state.currentSort == 'priceASC' ? 'active' : 'peter'\"\n              id=\"sort-price-asc\"\n              x-text=\"$store.utils.t($store.utils.translations.sortByAsc)\"\n            ><\/a>\n            <a\n              @click=\"controller.sortPriceAction(true)\"\n              class=\"dropdown-item\"\n              :class=\"state.currentSort == 'priceDESC' ? 'active' : 'peter'\"\n              id=\"sort-price-desc\"\n              x-text=\"$store.utils.t($store.utils.translations.sortByDesc)\"\n            ><\/a>\n          <\/div>\n        <\/div>\n        <template x-if=\"showBikeSort &#038;&#038; initialReady\">\n          <div\n            x-data=\"{ bikesByGenerations: state.filteredBikesGroupedByGenerations  }\"\n            class=\"bikefinder-bikes p-md-3 p-lg-4\"\n          >\n            <div\n              x-show=\"state.countOfFilteredBikes.value == 0\"\n              class=\"no-results\"\n            >\n              <span\n                x-text=\"$store.utils.t($store.utils.translations.noResults)\"\n              ><\/span>\n            <\/div>\n            <div class=\"bikefinder-grid\">\n              <template x-for=\"(value, index) in bikesByGenerations\">\n                <div\n                  x-data=\"biketeaser({ frames: bikesByGenerations[index], framesAsGenerations: true, framesMeta: model.frameFilterModel })\"\n                ><\/div>\n              <\/template>\n            <\/div>\n          <\/div>\n        <\/template>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/template>\n\n<script>\n  document.addEventListener(\"alpine:init\", () => {\n    Alpine.data(\n      \"bikefinder\",\n      ({\n        blockId,\n        model,\n        store,\n        state,\n        utils,\n        controller,\n        filterParamsResolver,\n      }) => ({\n        blockId: blockId,\n        model: model,\n        store: store,\n        state: state,\n        utils: utils,\n        controller: controller,\n        filterParamsResolver: filterParamsResolver,\n        showBikeSort: false,\n        initialReady: false,\n        init() {\n          this.setup();\n          this.$nextTick(() => {\n            this.mounted();\n            this.render();\n          });\n        },\n        setup() {\n          this.template = document.getElementById(\"bikefinderComponent\");\n        },\n        mounted() {\n          this.model.variantsToUniqueFramesAndFlattedVariants(\n            this.model.modules[this.blockId].bikes,\n            this.blockId\n          );\n\n          this.$watch(\"state.selectedFilter\", (value) => {\n            this.filter(value);\n          });\n\n          this.$watch(\"state.filteredBikesGroupedByGenerations\", (grouped) => {\n            this.reactiveBikeSort();\n          });\n\n          setTimeout(() => {\n            const { filters } = this.filterParamsResolver.defaultParams;\n            Object.keys(filters).forEach((key) => {\n              this.filterByParams(key, filters[key], true);\n            });\n            \/\/ wait to set all default filter properties - for resetFilterAction() -- to prevent watch updates on state.selectedFilter\n            this.state.defaultFilterProperties = JSON.stringify(\n              this.state.selectedFilter.properties\n            );\n\n            this.initialReady = true;\n          }, 1500);\n        },\n        render() {\n          this.$el.innerHTML = this.template.innerHTML;\n        },\n        filterByParams(key, value, initial) {\n          const propsMap = {\n            category: {\n              getProps: () => this.model.uniquePropTypes(),\n              keyName: \"value\",\n            },\n            primary_basecolour: {\n              getProps: () => this.uniquePropColors(),\n              keyName: \"value\",\n            },\n            frame_type: {\n              getProps: () => this.uniquePropFrames(),\n              keyName: \"value\",\n            },\n            \"bike_specifics.gear.gear_type\": {\n              getProps: () => this.uniquePropGears(),\n              keyName: \"value\",\n            },\n            \"ebike_specifics.battery_range.battery_capacity\": {\n              getProps: () => this.uniquePropBatteries(),\n              keyName: \"value\",\n            },\n          };\n\n          if (key in propsMap) {\n            const mapResult = propsMap[key];\n            const prop = mapResult\n              .getProps()\n              .find((prop) => prop[mapResult[\"keyName\"]] == value);\n            if (prop) {\n              this.controller.filterAddPropertyAction(prop, initial);\n            }\n\n            this.state.selectedFilter.initial = false;\n          }\n        },\n\n        filter(value) {\n          this.model.groupedFrames[this.blockId].forEach((group) => {\n            group.forEach((frame) => {\n              frame.filter(value);\n            });\n          });\n\n          this.state.filteredBikes =\n            this.controller.getOnlyBikesWhereFramesWithVariants(\n              this.model.groupedFrames[this.blockId]\n            );\n\n          const generations = this.controller.getGenerations(\n            this.state.filteredBikes\n          );\n          this.state.filteredBikesGroupedByGenerations = generations;\n\n          const countOfBikes = this.controller.calculateCountOfFilteredBikes(\n            this.blockId\n          );\n          if (this.state.selectedFilter.initial) {\n            this.state.maxBikesCount.value = countOfBikes;\n          }\n\n          this.state.countOfFilteredBikes.value = countOfBikes;\n          this.controller.sortNewestAlphaAction();\n\n          \/\/ Sync Filter\n          this.filterParamsResolver.setFiltersParams(\n            this.filterParamsResolver.getActiveFilters()\n          );\n        },\n        reactiveBikeSort() {\n          this.showBikeSort = false;\n          this.$nextTick(() => {\n            this.showBikeSort = true;\n          });\n        },\n        uniquePropFrames() {\n          return this.model.uniquePropFrames(this.blockId);\n        },\n        uniquePropBatteries() {\n          return this.model.uniquePropBatteries(this.blockId);\n        },\n        uniquePropGears() {\n          return this.model.uniquePropGears(this.blockId);\n        },\n        uniquePropPrices() {\n          return this.model.uniquePropPrices(this.blockId);\n        },\n        uniquePropWeights() {\n          return this.model.uniquePropWeights(this.blockId);\n        },\n        uniquePropColors() {\n          return this.model.uniquePropColors(this.blockId);\n        },\n      })\n    );\n  });\n<\/script>\n\n<style type=\"text\/css\">\n  body.modal-open {\n    padding-right: 0px !important;\n    overflow: auto !important;\n  }\n\n  body {\n    padding-right: 0 !important;\n  }\n\n  body.modal-open header,\n  body.modal-open .content {\n    padding-right: 0 !important;\n  }\n<\/style>\n<div x-data='bikefinder({ \n    blockId: \"Z2mdr1x\", \n    model: $store.bikefinderModel, \n    store: $store.bikefinderStore, \n    state: $store.bikefinderState, \n    utils: $store.utils, \n    controller: $store.bikefinderController,\n    filterParamsResolver: $store.bikefinderFilterParamsResolver })'>\n<\/div>\n<\/div>\n<\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div><\/div>\n\n<div class=\"lazyblock-nncontainer-ZLKerg wp-block-lazyblock-nncontainer\"><div class=\"section-standard\">\r\n  <div class=\"container\" id=\"container-ZLKerg\">\r\n    <div class=\"row\">\r\n      <div class=\"col py-4 py-lg-5\">\r\n        <div class=\"lazyblock-inner-blocks\">\n\n<h3 class=\"wp-block-heading\">Why do \u00abmen\u2019s bikes\u00bb have a \u00abbar\u00bb?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To clarify: This \u00abbar\u00bb is not a bar, but the top tube. Its original purpose was stability.Vorneweg: Diese \u00abStange\u00bb ist keine Stange, sondern das Oberrohr. Together with the down tube and seat tube, the top tube creates a triangular structure\u2014the most stable geometric form. At identical weight, triangular frames are stiffer and more robust, and at identical stability, they are lighter than other frame style.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Things have changed in the past 130 years. While modern lowstep and midstep frames from Diamant are just as stable as our stepover frames, they are only up to 200g heavier, thanks to advanced engineering. Today, only two reasons merit the existence of a top tube: Some people prefer the classic look, and some people appreciate a top tube to attach some accessories.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What are the differences between stepover, midstep, and lowstep bikes?&nbsp;<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you ride a stepover bike, you can attach accessories to it. Some bikes come with dedicated mounting bolts pre-installed. On midstep bikes, you might lose mounting points&nbsp;at the seat tube. Lowstep riders tend to not carry anything in their (virtual) frame triangle since that would obstruct the comfortable step-through space.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Regardless of frame style, Diamant uses consistent unisex geometry. If it\u2019s a bike in size L, you\u2019ll be sitting as upright or stretched and you\u2019ll be riding as sportive or dynamic, be it a stepover or a lowstep.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These differences used to be larger. (Unfortunately, some manufacturers still design inconsistent geometries.) Lowstep bikes used to have longer headtubes. Sometimes, manufacturers would even recommend different weight limits. On modern premium bikes, that\u2019s a thing of the past.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Some subtle differences remain. Some top tubes slope generously, i.e. they intersect the headtube at a much higher position than the seat tube. Then, the seat tube needs to resist more force. Additional material compensates for the increased load. On lowstep bikes, these forces move to the bottom bracket. While lowstep bikes used to feel a little bit soft, we now have mastered this engineering challenge. A little more material at the right location creates the same stability \u2013 that weight penalty never exceeds 200g.<\/p>\n\n<\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div><\/div>\n\n\n<div class=\"wp-block-cover is-light\"><img data-dominant-color=\"9b7f80\" data-has-transparency=\"false\" loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1707\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" class=\"wp-block-cover__image-background wp-image-53711 size-full not-transparent\" alt=\"Di 25 mahon lifestyle\" src=\"https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-scaled.avif\" style=\"--dominant-color: #9b7f80; object-position:48% 16%\" data-object-fit=\"cover\" data-object-position=\"48% 16%\" srcset=\"https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-scaled.avif 2560w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-300x200.avif 300w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-1024x683.avif 1024w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-768x512.avif 768w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-1536x1024.avif 1536w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Mahon_Lifestyle_67I9036_300dpi-2048x1365.avif 2048w\" \/><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-0 has-background-dim\"><\/span><div class=\"wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained\">\n<p class=\"has-text-align-center has-large-font-size wp-block-paragraph\"><\/p>\n<\/div><\/div>\n\n\n<div class=\"lazyblock-nncontainer-nX4D wp-block-lazyblock-nncontainer\"><div class=\"section-standard\">\r\n  <div class=\"container\" id=\"container-nX4D\">\r\n    <div class=\"row\">\r\n      <div class=\"col py-4 py-lg-5\">\r\n        <div class=\"lazyblock-inner-blocks\">\n\n<h3 class=\"wp-block-heading\">Are stepover bikes lighter, faster, or more robust?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes, stepover bikes tend to save some weight. Depending on the bike, the difference might be 50g or 200g. In any case, that\u2019s less than 1% of the total weight of a bike.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yes and no, stepover bikes may be a bit faster, but it might also be the other way around. While ride dynamics and rolling resistance do not change, aerodynamic properties inevitably do change. We are not aware of any systematic review to quantify direction and magnitude of this effect.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No, at normal use, all frames are identically robust. We design all our bikes for the same maximum weight limit across all frame styles.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Do men and women need different frame styles?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is a crystal-clear statement: no. Arguably there are anatomical differences between men and women. However, there are just as many differences between men and other men. Modern bikes, including ours, feature unisex geometry and adjustable components with ergonomic options to fit more than just some body, but every body.<\/p>\n\n<\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div><\/div>\n\n\n<div class=\"wp-block-cover is-light\"><img data-dominant-color=\"a37c80\" data-has-transparency=\"false\" loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1707\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" class=\"wp-block-cover__image-background wp-image-53723 size-full not-transparent\" alt=\"Di 25 suvea lifestyle\" src=\"https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-scaled.avif\" style=\"--dominant-color: #a37c80; object-position:39% 52%\" data-object-fit=\"cover\" data-object-position=\"39% 52%\" srcset=\"https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-scaled.avif 2560w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-300x200.avif 300w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-1024x683.avif 1024w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-768x512.avif 768w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-1536x1024.avif 1536w, https:\/\/www.diamantrad.com\/wp-content\/uploads\/2025\/03\/DI_25_Suvea_Lifestyle_67I5046_300dpi-2048x1365.avif 2048w\" \/><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim-0 has-background-dim\"><\/span><div class=\"wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained\">\n<p class=\"has-text-align-center has-large-font-size wp-block-paragraph\"><\/p>\n<\/div><\/div>\n\n\n<div class=\"lazyblock-nncontainer-1WmIn6 wp-block-lazyblock-nncontainer\"><div class=\"section-standard\">\r\n  <div class=\"container\" id=\"container-1WmIn6\">\r\n    <div class=\"row\">\r\n      <div class=\"col py-4 py-lg-5\">\r\n        <div class=\"lazyblock-inner-blocks\">\n\n<h3 class=\"wp-block-heading\">Are their lowstep bikes specifically for men?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Diamant does not offer such bikes. We understand the possibilities of ergonomically adjustable components. Some manufacturers do offer frames tailored to women that come pre-installed with saddle for female anatomy and lighter suspension forks congruent with lower body weights. That can make sense in performance-oriented bikes. We follow a unisex strategy across our entire lineup.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What are the wheel sizes for men\u2019s bikes?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Historically, \u00abwomen\u2019s bikes\u00bb featured 26\u201d wheels, while \u00abmen\u2019s bikes\u00bb came with 28\u201d wheels. This distinction no longer applies. We would only equip 26\u201d wheels on very small frame sizes for very short riders. Instead, we use 27.5\u201d rims on all our e-bikes and even on some of our bikes without a motor. On these bikes, we use wider and voluminous tires.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We learned from mountainbikes: wide, high-volume tires need less tire pressure, but offer additional comfort, traction, and safety, especially on e-bikes. They are more widespread on e-bikes because they are heavier. When you ride your bike without a motor into rough terrain, they might still offer benefits to riders. Our newest platforms offer additional clearance to make a conscious choice.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Did Diamant invent the Diamond frame?&nbsp;<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Originally, stepover frames were also known as \u00abdiamond frames\u00bb in some languages, as the traditional frame, made up of two triangles, had a geometric form resembling a diamond. Later, \u201cmen\u2019s bikes\u201d became the more popular label, as manufacturers tried to advertise the freshly invented lowstep bikes as the preferred choice for women (wearing skirts). The \u201cdiamond\u201d frame never disappeared entirely though. In any case, the \u201cdiamond frame\u00bb predates the Diamant bike brand. In fact, our name derives from a steel alloy, not the frame style. The similar label is pure coincidence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Every Diamant bike is and is not a men\u2019s bike<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u00abMen\u2019s bike\u00bb is a wrong term. Historically, it might have had some significance, but it is outdates. Our bikes are unisex. Sure: We do observe more interest in colorful designs in our bikes with midstep and lowstep, and we do offer additional options in response. Nonetheless, these bikes are simply bikes with a more comfortable stepthrough.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">People are different. Small adjustments can make a world of difference if a bike doesn\u2019t fit properly on the first test ride. Visit your local Diamant dealer to ensure your bike is perfectly tuned to your very personal needs.&nbsp;&nbsp;<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a role=\"button\" class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.diamantrad.com\/en-GB\/bikes\/\">View all bikes<\/a><\/div>\n<\/div>\n\n<\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Find your men&#8217;s bike from the current collection: \u2713 E-bikes \u2713 City bikes \u2713 Trekking\u00ae bikes &#038; more.<\/p>\n","protected":false},"author":8,"featured_media":53696,"parent":38318,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_crdt_document":"","slim_seo":{"title":"Bicycles for men from Diamant","description":"Find your men's bike from the current collection: \u2713 E-bikes \u2713 City bikes \u2713 Trekking\u00ae bikes & more."},"footnotes":""},"class_list":["post-53814","page","type-page","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/pages\/53814","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/comments?post=53814"}],"version-history":[{"count":4,"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/pages\/53814\/revisions"}],"predecessor-version":[{"id":74991,"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/pages\/53814\/revisions\/74991"}],"up":[{"embeddable":true,"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/pages\/38318"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/media\/53696"}],"wp:attachment":[{"href":"https:\/\/www.diamantrad.com\/en-GB\/wp-json\/wp\/v2\/media?parent=53814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}