Dandy Horse XC 30
This wheelset provides the best possible traction at the lightest possible weight. The carbon rims and Sapim D-light spokes make them stiff and durable, while the wider internal width helps to keep the tires from slipping in the mud.
Weight: from 1260 g
Price range: € 1 297 through € 1 633
Dandy Horse XC 25
Lightweight and agile wheels on aluminum rims, designed for fast cross-country riding.
Weight: from 1540 g
Price range: € 528 through € 792

MTB

We are a professional wheel builder for demanding athletes. We are craftsmen and take our craft very seriously. We do not compromise on the quality of components or the precision of centering. We have a wide range of wheels for all MTB disciplines – marathons, cross-country (XC) and enduro. We have wheels in every size – 27.5” and 29er. We build MTB wheels on Dandy Horse and DT Swiss hubs, and on special order also from other manufacturers. We also build wheels from supplied components. We are constantly improving and expanding our knowledge, so that we can build the best bicycle wheels in the world.

Grab an extra 5% off

Sign up for our newsletter to receive exclusive offers

(function() { const popupID = 4091; // <- Twoje ID popupu const requiredMs = 60000; // 60 sekund const startKey = "popupTimerStart_" + popupID; const closedKey = "popupClosed_" + popupID; const shownSessionKey = "popupShownSession_" + popupID; const maxWaitForElementorMs = 10000; // ile maksymalnie czekamy na elementorProFrontend // Jeśli zamknięto już popup (localStorage) — nie pokazuj więcej if (localStorage.getItem(closedKey)) return; // Ustal moment rozpoczęcia liczenia (persistuje między podstronami) let start = localStorage.getItem(startKey); if (!start) { start = Date.now(); localStorage.setItem(startKey, start); } else { start = parseInt(start, 10); } // Oblicz ile jeszcze brakuje do wymaganych 60s function msRemaining() { return Math.max(0, requiredMs - (Date.now() - start)); } // Funkcja pokazująca popup (gdy elementorProFrontend już gotowy) function tryShowPopup() { // jeśli użytkownik zamknął popup w międzyczasie — przerwij if (localStorage.getItem(closedKey)) return; // jeśli już pokazano w tej sesji — nie pokazuj ponownie if (sessionStorage.getItem(shownSessionKey)) return; // upewnij się, że obiekt elementora jest dostępny if (typeof elementorProFrontend !== "undefined" && elementorProFrontend && elementorProFrontend.modules && elementorProFrontend.modules.popup) { elementorProFrontend.modules.popup.showPopup({ id: popupID }); sessionStorage.setItem(shownSessionKey, "1"); } else { // jeśli elementor jeszcze nie załadowany — nic nie robimy tutaj console.warn("Elementor Pro popup module not ready yet."); } } // Czekaj na elementorProFrontend (polling), ale nie dłużej niż maxWaitForElementorMs function waitForElementorReady(cb) { const interval = 200; let waited = 0; const t = setInterval(function() { if (typeof elementorProFrontend !== "undefined" && elementorProFrontend && elementorProFrontend.modules && elementorProFrontend.modules.popup) { clearInterval(t); cb(true); } else { waited += interval; if (waited >= maxWaitForElementorMs) { clearInterval(t); cb(false); } } }, interval); } // Gdy popup zostanie zamknięty — zapisz to na stałe w localStorage (function bindCloseListener() { if (window.jQuery) { jQuery(document).on('elementor/popup/hide', function(event, id) { if (id === popupID) { localStorage.setItem(closedKey, "1"); } }); } else { // jeśli jQuery jeszcze nie dostępne, spróbuj za chwilę let tries = 0; const t = setInterval(function() { tries++; if (window.jQuery) { clearInterval(t); jQuery(document).on('elementor/popup/hide', function(event, id) { if (id === popupID) { localStorage.setItem(closedKey, "1"); } }); } else if (tries > 50) { clearInterval(t); } }, 200); } })(); // Teraz ustaw timeout — jeśli pozostały czas 0 => pokaż natychmiast (po upewnieniu się, że elementor jest gotowy) const remaining = msRemaining(); if (remaining <= 0) { waitForElementorReady(function(ready) { if (ready) tryShowPopup(); else { // jeśli elementor nie gotowy — spróbuj jeszcze raz po krótkim timeout setTimeout(tryShowPopup, 500); } }); } else { // ustaw timeout na pozostały czas; po upływie — spróbuj pokazać popup setTimeout(function() { waitForElementorReady(function(ready) { if (ready) tryShowPopup(); else { // jeśli elementor nie gotowy — spróbuj z małym opóźnieniem setTimeout(tryShowPopup, 500); } }); }, remaining); } // Dodatkowo: jeśli użytkownik zamknął popup w innej karcie/oknie, ten skrypt też to zauważy dzięki storage event window.addEventListener('storage', function(e) { if (e.key === closedKey && e.newValue) { // nic do zrobienia tutaj — warunki wyżej sprawią, że nic się nie pokaże } }); })();