Header Image
td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003cth\u003eAccessories\u003c\/th\u003e\n\u003ctd\u003e93339,94799,93483,93520\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\u003c\/table\u003e"}; window._RestockRocketConfig.variantsInventoryPolicy = {57747196445055 : "deny",57747196477823 : "deny",57747196510591 : "deny",57747196543359 : "deny",57747196576127 : "deny",}; window._RestockRocketConfig.variantsInventoryQuantity = {57747196445055 : parseInt("0"),57747196477823 : parseInt("0"),57747196510591 : parseInt("0"),57747196543359 : parseInt("0"),57747196576127 : parseInt("0"),}; window._RestockRocketConfig.variantsPreorderCount = {57747196445055 : parseInt(""),57747196477823 : parseInt(""),57747196510591 : parseInt(""),57747196543359 : parseInt(""),57747196576127 : parseInt(""),}; window._RestockRocketConfig.variantsPreorderCountForMarket = {57747196445055 : null,57747196477823 : null,57747196510591 : null,57747196543359 : null,57747196576127 : null,}; window._RestockRocketConfig. Czechia (CZKKč) once here so both the accelerated-checkout block // gate (STOQ-1612) and the click tracker (STOQ-1595) read one clearly-owned flag rather // than a side effect buried in either consumer's try/catch: whether this shop has preorders // configured at all — an enabled selling plan plus at least one preorder variant id, // independent of the block toggle. Fail-open: on error the flag stays unset and both // consumers no-op. try { var _sqCfg = window._RestockRocketConfig; var _sqPlanEnabled = Array.isArray(_sqCfg.sellingPlans) && _sqCfg.sellingPlans.some(function (p) { return p && p.enabled; }); var _sqPreCount = ((_sqCfg.cachedPreorderVariantIds && _sqCfg.cachedPreorderVariantIds.preorder_variant_ids) || []).length; _sqCfg.preordersConfigured = !!(_sqPlanEnabled && _sqPreCount); } catch (e) { /* fail open */ } // STOQ-1612: block (not hide) Buy Now / Shop Pay until our JS runs, so a tap in the // load window can't bypass preorder. pointer-events via .stoq-buy-now-pe

<

Djibouti (DJFFdj) translation data in metafield // Metafield hasn't been backfilled yet - force refresh console.debug('STOQ - multi-language enabled but no translation data in cache, fetching fresh'); return null; } // Translations object exists in metafield - cache is valid // If current locale isn't translated, applyTranslations will gracefully use default locale from base fields if (window._RestockRocketConfig.normalizedLocale && !Object.prototype.hasOwnProperty.call(settings.translations, window._RestockRocketConfig.normalizedLocale)) { console.debug('STOQ - locale not explicitly translated, will use default language from cache'); } // Don't return null - continue using cache even for untranslated locales } const updatedAt = new Date(settings.updated_at); if (isNaN(updatedAt.getTime())) { console.debug('STOQ - Invalid updated_at date format in settings'); return null; } const
Denmark (DKKkr.) < tomer interaction. // Detected variants: the variants present in this page's Liquid context (product page has them; // collection/index/etc. don't expose variants from Liquid). Used to disambiguate "embed didn't // load" vs "embed loaded but the variant wasn't a preorder/BIS candidate" in order debug. try { const _stoqInitConfig = window._RestockRocketConfig; const _stoqDetectedVariantIds = (_stoqInitConfig.product && Array.isArray(_stoqInitConfig.product.variants)) ? _stoqInitConfig.product.variants.map(function(v) { return v.id }) : []; const _stoqSelectedVariantId = _stoqInitConfig.selected_variant_id; Shopify?.analytics?.publish?.('stoq_initialized', { cart_token: _stoqInitConfig.cartToken || '', page_url: window.location.href, page_type: _stoqInitConfig.pageType || '', shop_domain: _stoqInitConfig.shop || '', market_id: _stoqInitConfig.marketId || '', detected_variant_ids: _stoqDetectedVariantIds, selected_variant_id: _stoqSele
on block above) — nothing to bypass otherwise. variant_id is read per-clicked-button // from its form so it's correct on collection/index/search too. block_accelerated_checkout // context (STOQ-1612) rides in `properties` (forwarded verbatim by the pixel, no schema // change): a buy_now click on a preorder variant while the gate was armed is a visible // bypass signal for order debug. Also sends page_url (top-level, like the pixel's native // events) and two preorder signals in properties (see below). try { var _sqTrack = window._RestockRocketConfig; if (_sqTrack.preordersConfigured) { document.addEventListener('click', function (e) { try { var t = e.target; if (!t || !t.closest) return; var host = t.closest('.shopify-payment-button, shopify-payment-terms'); if (!host) return; var channel = host.matches && host.matches('shopify-payment-terms') ? 'shop_pay_installments' : 'buy_now'; var form = host.close
Egypt (EGPج.م) ack.product && _sqTrack.product.id) || '', channel: channel, market_id: _sqTrack.marketId || '', page_type: _sqTrack.pageType || '', cart_token: _sqTrack.cartToken || '', page_url: (window.location && window.location.href) || '', properties: { // Mirror the bundle's own preorder check (preorder.js checkInventoryProvider- // WithCachedFallback): the live set config.preorderVariantIds (refreshed after // page load by loadVariantInventoryData) OR the Liquid-injected // cachedPreorderVariantIds — always present, so it covers clicks before the // bundle loads (why this tracker is inline). ORing both (not preferring one) // matches the bundle and is correct even if the live set is an empty array. Both // hold integer ids; the click-time id comes off a DOM input (.value → string) or // selected_variant_id, so coerce with Number forDjibouti (DJFFdj) er bypass is detectable too. is_instock_variant: (function () { var has = function (a) { return Array.isArray(a) && a.indexOf(_sqVidNum) !== -1; }; return has(_sqTrack.inStockVariantIds) || has(_sqTrack.cachedInStockVariantIds && _sqTrack.cachedInStockVariantIds.in_stock_variant_ids); })(), // The enrolled plan's Shopify selling-plan id + inventory_provider (stoq = STOQ tracks // the OOS count; shopify = in-stock preorder). Tells order-debug what kind of preorder // the Buy Now bypassed, without a downstream lookup. enrolled_plan_id: (_sqPlan && (_sqPlan.shopify_selling_plan_id || _sqPlan.shopify_selling_plan_group_id)) || '', enrolled_plan_provider: (_sqPlan && _sqPlan.inventory_provider) || '', block_enabled: !!(_sqTrack.cachedSettings && _sqTrack.cachedSettings.block_accelerated_checkout), gate_armed: !!_sqTrack.a ); delete settings.translations; return settings; } console.debug(`STOQ - Applying translations for normalized locale: ${normalizedLocale} (original: ${window._RestockRocketConfig.locale})`); const translatedFields = translations[normalizedLocale]; if (translatedFields && typeof translatedFields === 'object') { Object.keys(translatedFields).forEach(function(key) { const value = translatedFields[key]; if (value !== null && value !== undefined && value !== '') { settings[key] = value; } }); } else { console.debug('STOQ - No translated fields found for locale:', normalizedLocale); } delete settings.translations; return settings; } catch (e) { console.debug('STOQ - error applying translations:', e); return settings; } } // Setup event listener for cart selling plan updates // This must be called before any scripts are loaded to avoid race conditions func ditive, does not gate init) ---- // The inlined `cachedSettings` comes from the app-embed Liquid render, which // Shopify edge-caches and can serve stale. Reading the same `settings` metafield // back over the Storefront API is a POST to /api/
Equatorial Guinea (XAFCFA) version>/graphql.json — never // CDN-cached — so it returns the live value on every page load. We fetch it // best-effort and stash it on `window._RestockRocketConfig.storefrontSettings` // so individual behaviours can migrate onto the fresh value over time. This is // PURELY ADDITIVE: it does NOT change the resolution flow below, never blocks // init, and silently no-ops on any failure / missing token. (function loadStorefrontSettings() { const cfg = window._ReEgypt (EGPج.م) ('Storefront API HTTP ' + response.status); } return response.json(); }) .then(function(body) { if (body && body.errors && body.errors.length) { throw new Error('Storefront API errors: ' + body.errors.map(function(e) { return e && e.message; }).join(', ')); } const value = body && body.data && body.data.shop && body.data.shop.metafield && body.data.shop.metafield.value; if (!value) { throw new Error('Storefront API returned no settings metafield value'); } cfg.storefrontSettings = JSON.parse(value); console.debug('STOQ - stored live settings from Storefront API on config.storefrontSettings'); }) .catch(function(e) { console.debug('STOQ - Storefront settings fetch failed (non-fatal):', e && e.message); }); } if (typeof window.requestIdleCallback === 'function') { window.requestIdleCallback(run, { timeout: 5000 }); } else { setTimeout(run, 0); } })(); // First try to get sett .then(function(response) { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(function(settings) { initializeScripts(settings); }) .catch(function(error) { // If request failed and we have cached settings (even if expired), use them as fallback if (cachedSettings) { console.debug('STOQ - using expired cached settings as fallback'); initializeScripts(cachedSettings); } else { console.error('STOQ - failed to load settings:', error); } }) .catch(function(e) { console.error(e) }) } function fetchEmbedConfig(endpoint, apply) { return fetch( `${window._RestockRocketConfig.host}/api/v1/embed/${endpoint}.json`, { headers: { 'X-Shopify-Shop-Domain': window._RestockRocketConfig.shop || window.Shopify.shop, 'ngrok-skip-browser-warning': 'skip' } } ) .then(function(response) { if Equatorial Guinea (XAFCFA) e if(usePreorderBuild) { // cart/article/blog/list-collections: full build so the cart sweep runs. createRestockRocketScript(window._RestockRocketConfig.scriptUrlCollection); } else { console.debug(`STOQ - no scripts enabled for ${pageType}`); } // Dispatch custom event when app is loaded // Cart selling plan updates will be triggered by stoq:inventory-data-loaded event const appLoadedEvent = new CustomEvent('stoq:loaded', { detail: { pageType: window._RestockRocketConfig.pageType, enabled: settings.enable_app, settings: settings, preorderEnabled: settings.preorder_enabled } }); console.debug('STOQ - dispatching app loaded event'); window.dispatchEvent(appLoadedEvent); } }
html.stoq-buy-now-pending .shopify-payment-button{pointer-events:none!important}.stoq-hide-buy-now .shopify-payment-button{display:none!important}.restock-rocket-button,.restock-rocket-button-float{opacity:1!important;border:none!important;cursor:pointer!important;background-image:none!important;box-shadow:none!important;padding:15px 20px;font-size:16px;width:100%;font-family:inherit}@font-face{font-family:OpenSans;font-weight:200;src:url(https://d382hokyqag45a.cloudfront.net/assets/OpenSans-Light.woff)}@font-face{font-family:OpenSans;font-weight:300;src:url(https://d382hokyqag45a.cloudfront.net/assets/OpenSans-Regular.woff)}@font-face{font-family:OpenSans;font-weight:600;src:url(https://d382hokyqag45a.cloudfront.net/assets/OpenSans-SemiBold.woff)}.restock-rocket-button-container{position:relative;z-index:1;width:100%}.restock-rocket-button-container-float-right{position:fixed;z-index:123123;top:calc(50% - 200px);right:0;transform:rotate(270deg);transform-origin:bottom right}.restock-rocket-button-container-float-left{position:fixed;z-index:123123;top:calc(50% - 200px);left:40px;transform:rotate(90deg);transform-origin:top left}.restock-rocket-button-container-float-left:hover,.restock-rocket-button-container-float-right:hover,.restock-rocket-button-container:hover,.restock-rocket-button-float:hover,.restock-rocket-button:hover{opacity:.8}.restock-rocket-button{min-height:50px;margin-top:10px;margin-bottom:10px}.restock-rocket-button-collection{position:relative;font-size:13px;line-height:1;padding:7px;height:auto;z-index:3}.restock-rocket-wrapper{background-color:rgba(0,0,0,.5);z-index:123123123;width:100%;height:100%;overflow:auto;position:fixed;right:0;top:0;transition-property:all;transition-duration:.3s;display:flex;flex-direction:column;justify-content:center;}.restock-rocket-wrapper-inline{width:100%;height:100%;margin-top:20px}.restock-rocket-preorder-description{padding:10px 15px;margin-top:20px;display:flex;flex-direction:column;gap:10px;}.preorder-description-details{margin-bottom:0;display:flex;flex-direction:column;gap:10px;}.preorder-detail-item{display:flex;flex-direction:row;justify-content:start;gap:8px;align-items:center;}.restock-rocket-payment-widget{border:1px solid #ebebeb;margin-bottom:20px;}.restock-rocket-payment-option{display:flex;flex-wrap:wrap;align-items:center;gap:5px;padding:15px 20px;}.restock-rocket-payment-option:not(:last-child){border-bottom:1px solid #ebebeb;}.restock-rocket-payment-input-container{flex:1 1 auto;min-width:0}.restock-rocket-preorder-discount-badge{background:#ebebeb;height:25px;line-height:25px;padding:0 15px;border-radius:25px;font-size:0.8rem;flex:0 0 auto}.restock-rocket-payment-input{margin-right:10px;margin-top:-3px;vertical-align:middle;margin-left:0;accent-color:#202223}.restock-rocket-payment-description{margin-top:4px;flex:1 1 100%}.restock-rocket-preorder-badge{font-size:13px;line-height:1;padding:5px 13px 6px;border-radius:40px;height:auto;border:none;width:auto;z-index:2;margin:0;background:0 0}.preorder-badge-collection{position:absolute;top:10px;right:10px}.preorder-badge-product{margin-left:10px}.restock-rocket-price-strike{text-decoration:line-through;color: #666666;}.restock-rocket-discounted-price{margin-left:10px;}.restock-rocket-acknowledgement-checkbox{margin-bottom:12px;display:flex;align-items:flex-start;gap:8px;font-size:14px;line-height: 1.5;}.restock-rocket-acknowledge-checkbox-input{width:18px;height:18px;margin-top:2px;cursor:pointer;flex-shrink:0;accent-color: #0d0d0d;}.restock-rocket-acknowledge-checkbox-label{flex:1;cursor:pointer;}.restock-rocket-preorder-countdown-timer{display:flex;flex-direction:column;align-items:center;padding:16px;margin:8px 0;font-family:inherit;}.restock-rocket-preorder-countdown-timer .countdown-header{font-size:16px;margin-bottom:6px;text-align:center}.restock-rocket-preorder-countdown-timer .countdown-units{display:flex;flex-wrap:wrap;gap:12px;justify-content:center}.restock-rocket-preorder-countdown-timer .countdown-unit{display:flex;flex-direction:column;align-items:center;gap:6px}.restock-rocket-preorder-countdown-timer .countdown-box{min-width:40px;padding:10px 6px;text-align:center;font-size:20px;line-height:1}.restock-rocket-preorder-countdown-timer .countdown-label{font-size:14px;font-weight:500;text-align:center;text-transform:capitalize;opacity:.7}@media (max-width:768px){.restock-rocket-preorder-countdown-timer{padding:14px}.restock-rocket-preorder-countdown-timer .countdown-box{min-width:55px;padding:14px 10px;font-size:26px}.restock-rocket-preorder-countdown-timer .countdown-label{font-size:11px}}@media (max-width:480px){.restock-rocket-preorder-countdown-timer{padding:12px}.restock-rocket-preorder-countdown-timer .countdown-units{width:100%;gap:10px}.restock-rocket-preorder-countdown-timer .countdown-box{width:100%;min-width:50px;padding:12px 8px;font-size:24px}.restock-rocket-preorder-countdown-timer .countdown-label{font-size:10px}}.restock-rocket-toast{position:fixed;cursor:pointer;background:#fff;border:0;min-width:40px;min-height:40px;box-shadow:0 0 15px rgba(0,0,0,.1)!important;z-index:622004;padding:20px 30px;font-family:inherit;font-size:inherit;color:#000;display:flex;justify-content:center;align-items:center}.restock-rocket-toast a{text-decoration:none;font-weight:700;color:#000}.restock-rocket-toast .dismiss{margin-left:15px;z-index:1;font-size:20px;}.restock-rocket-toast-top{top:60px}.restock-rocket-toast-bottom{bottom:75px}.restock-rocket-toast-left,.restock-rocket-toast-right{-webkit-animation:.5s forwards slide;animation:.5s forwards slide}.restock-rocket-toast-left{left:0;transform:translateX(-100%);-webkit-transform:translateX(-100%);border-radius:0 10px 10px 0}.restock-rocket-toast-left.slide-out{-webkit-animation:.5s forwards slide-out-left;animation:.5s forwards slide-out-left}.restock-rocket-toast-right{right:0;transform:translateX(100%);-webkit-transform:translateX(100%);border-radius:10px 0 0 10px}.restock-rocket-toast-right.slide-out{-webkit-animation:.5s forwards slide-out-right;animation:.5s forwards slide-out-right}@keyframes slide{100%{transform:translateX(0)}}@-webkit-keyframes slide{100%{-webkit-transform:translateX(0)}}@keyframes slide-out-left{0%{transform:translateX(0)}100%{transform:translateX(-100%)}}@-webkit-keyframes slide-out-left{0%{-webkit-transform:translateX(0)}100%{-webkit-transform:translateX(-100%)}}@keyframes slide-out-right{0%{transform:translateX(0)}100%{transform:translateX(100%)}}@-webkit-keyframes slide-out-right{0%{-webkit-transform:translateX(0)}100%{-webkit-transform:translateX(100%)}}.restock-rocket-preorder-progress-bar{padding:12px 15px;margin-bottom:20px;font-family:inherit;}.restock-rocket-preorder-progress-bar .preorder-progress-text{margin-bottom:8px;}.restock-rocket-preorder-progress-bar .preorder-progress-bar-row{display:flex;align-items:center;gap:10px;}.restock-rocket-preorder-progress-bar .preorder-progress-track{flex:1;height:12px;overflow:hidden;}.restock-rocket-preorder-progress-bar .preorder-progress-fill{display:block;height:100%;min-width:2px;transition:width 0.3s ease;}.restock-rocket-preorder-progress-bar .preorder-progress-percentage{font-weight:500;min-width:35px;text-align:right;} Estonia (EUR€)
Eritrea (GBP£)
Eswatini (GBP£)
Ethiopia (ETBBr)
Liberia (GBP£)
Madagascar (GBP£)



Malta (EUR€) Mayotte (EUR€) If the item is showing in stock, we aim to post the product within 24 hours. Please allow 5 working days to receive the item. We also have a physical store, if you are local please pop in - 82 Newington Road, EH91QN, Edinburgh.#relatedProducts--template--26482384994687__related { --PT: 60px; --PB: 60px; } #relatedProducts--template--26482384994687__related .tabs__nav { --text-size: calc(var(--adjust-heading) * 1.35); } @media screen and (max-width: 767px) { #relatedProducts--template--26482384994687__related .grid--mobile, #relatedProducts--template--26482384994687__related .carousel--mobile { grid-template-columns: repeat(1, minmax(0, 1fr)); } } Recently viewedServicingWorkshop PricesDelivery & Returns
Mauritania (GBP£)
Mauritius (MUR₨)
Moldova (MDLL)
Monaco (EUR€)
I'm looking to buy this product, when will it arrive and how much does postage cost?
Postage is free on orders over £50. Orders under £50, our postage charge is £3.99.ProjektRide Bike Shop Edinburgh
You May Also Like
Book a Service
Cycle to Work
Information