1<!doctype html> 2<html class="collection.events-collectie js" lang="en"> 3 <head>
3<script data-source-attribution="shopify.event_observer.bootstrap"> 4(function(){let e=navigator,t=`prototype`,n=`sendBeacon`,r=e[n],i=fetch,a=XMLHttpRequest[t],{open:o,send:s}=a,c=`EventListener`,l=`add${c}`,u=`remove${c}`,d=EventTarget[t],f=d[l],p=d[u],m=e=>Error((e=document.currentScript)&&[e?.src,e?.id||e?.dataset?.sourceAttribution]),h=(e=[],t=0)=>(e.p=n=>e[t++%1e3]=n,[e,t=>(e.forEach(e.p=t),e.length=0)]),[g,_]=h(),[v,y]=h(),b,x=new WeakMap,S=e=>e&&g.p([e,b||[m()]]);d[l]=function(e,t,n){let r=this,i=t?.handleEvent||t,a=x.get(t),o=m();i?.call&&!a&&x.set(t,a=function(e){b=[o,e.type];try{i.call(t==i?this:t,e)}finally{b=null}}),v.p([e,o,a,r?.tagName||r+``,r?.id]),f.call(r,e,a||t,n)},d[u]=function(e,t,n){p.call(this,e,x.get(t)||t,n)},a.open=function(e,t){x.set(this,[t+``,e]),o.apply(this,arguments)},a.send=function(e){S(x.get(this)),s.call(this,e)},fetch=(e,t)=>(S([(e?.url||e)+``,t?.method]),i(e,t)),e[n]=(t,n)=>(S([t+``,``]),r.call(e,t,n)),setTimeout(()=>import("//granrondo.cc/cdn/shopifycloud/storefront/assets/storefront/event_observer_reporter-ed358274.js").then(e=>e.$(_,y,f,i,`89912770934`)))})(); 5//# sourceURL=event-observer-collector.js 6</script>
6 7
8<script type="application/vnd.locksmith+json" data-locksmith>{"version":"v346","locked":false,"initialized":true,"scope":"collection","access_granted":true,"access_denied":false,"requires_customer":false,"manual_lock":false,"remote_lock":false,"has_timeout":false,"remote_rendered":null,"hide_resource":false,"hide_links_to_resource":false,"hide_price":false,"hide_add_to_cart":false,"transparent":true,"locks":{"all":[],"opened":[]},"keys":[],"keys_signature":"7d134c1eeeaa0bc5227844f58440d5fb8ef11fc597a6610310f55b975f5d0e30","state":{"template":"collection.events-collectie","theme":178807996790,"product":null,"collection":"events","page":null,"blog":null,"article":null,"app":null},"now":1791129347,"path":"\/collections\/events","locale_root_url":"\/en-en","canonical_url":"https:\/\/granrondo.cc\/en-en\/collections\/events","customer_id":null,"customer_id_signature":"7d134c1eeeaa0bc5227844f58440d5fb8ef11fc597a6610310f55b975f5d0e30","cart":null}</script>
8<script data-locksmith>!function(){undefined;!function(){var s=window.Locksmith={},e=document.querySelector('script[type="application/vnd.locksmith+json"]'),n=e&&e.innerHTML;if(s.state={},s.util={},s.loading=!1,n)try{s.state=JSON.parse(n)}catch(d){}if(document.addEventListener&&document.querySelector){var o,i,a,t=[76,79,67,75,83,77,73,84,72,49,49],c=function(){i=t.slice(0)},l="style",r=function(e){e&&27!==e.keyCode&&"click"!==e.type||(document.removeEventListener("keydown",r),document.removeEventListener("click",r),o&&document.body.removeChild(o),o=null)};c(),document.addEventListener("keyup",function(e){if(e.keyCode===i[0]){if(clearTimeout(a),i.shift(),0<i.length)return void(a=setTimeout(c,1e3));c(),r(),(o=document.createElement("div"))[l].width="50%",o[l].maxWidth="1000px",o[l].height="85%",o[l].border="1px rgba(0, 0, 0, 0.2) solid",o[l].background="rgba(255, 255, 255, 0.99)",o[l].borderRadius="4px",o[l].position="fixed",o[l].top="50%",o[l].left="50%",o[l].transform="translateY(-50%) translateX(-50%)",o[l].boxShadow="0 2px 5px rgba(0, 0, 0, 0.3), 0 0 100vh 100vw rgba(0, 0, 0, 0.5)",o[l].zIndex="2147483645";var t=document.createElement("textarea");t.value=JSON.stringify(JSON.parse(n),null,2),t[l].border="none",t[l].display="block",t[l].boxSizing="border-box",t[l].width="100%",t[l].height="100%",t[l].background="transparent",t[l].padding="22px",t[l].fontFamily="monospace",t[l].fontSize="14px",t[l].color="#333",t[l].resize="none",t[l].outline="none",t.readOnly=!0,o.appendChild(t),document.body.appendChild(o),t.addEventListener("click",function(e){e.stopImmediatePropagation()}),t.select(),document.addEventListener("keydown",r),document.addEventListener("click",r)}})}s.isEmbedded=-1!==window.location.search.indexOf("_ab=0&_fd=0&_sc=1"),s.path=s.state.path||window.location.pathname,s.basePath=s.state.locale_root_url.concat("/apps/locksmith").replace(/^\/\//,"/"),s.reloading=!1,s.util.console=window.console||{log:function(){},error:function(){}},s.util.makeUrl=function(e,t){var n,o=s.basePath+e,i=[],a=s.cache();for(n in a)i.push(n+"="+encodeURIComponent(a[n]));for(n in t)i.push(n+"="+encodeURIComponent(t[n]));return s.state.customer_id&&(i.push("customer_id="+encodeURIComponent(s.state.customer_id)),i.push("customer_id_signature="+encodeURIComponent(s.state.customer_id_signature))),o+=(-1===o.indexOf("?")?"?":"&")+i.join("&")},s._initializeCallbacks=[],s.on=function(e,t){if("initialize"!==e)throw'Locksmith.on() currently only supports the "initialize" event';s._initializeCallbacks.push(t)},s.initializeSession=function(e){if(!s.isEmbedded){var t=!1,n=!0,o=!0;(e=e||{}).silent&&(o=n=!(t=!0)),s.ping({silent:t,spinner:n,reload:o,callback:function(){s._initializeCallbacks.forEach(function(e){e()})}})}},s.cache=function(e){var t={};try{var n=function i(e){return(document.cookie.match("(^|; )"+e+"=([^;]*)")||0)[2]};t=JSON.parse(decodeURIComponent(n("locksmith-params")||"{}"))}catch(d){}if(e){for(var o in e)t[o]=e[o];document.cookie="locksmith-params=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",document.cookie="locksmith-params="+encodeURIComponent(JSON.stringify(t))+"; path=/"}return t},s.cache.cart=s.state.cart,s.cache.cartLastSaved=null,s.params=s.cache(),s.util.reload=function(){s.reloading=!0;try{window.location.href=window.location.href.replace(/#.*/,"")}catch(d){s.util.console.error("Preferred reload method failed",d),window.location.reload()}},s.cache.saveCart=function(e){if(!s.cache.cart||s.cache.cart===s.cache.cartLastSaved)return e?e():null;var t=s.cache.cartLastSaved;s.cache.cartLastSaved=s.cache.cart,fetch("/cart/update.js",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({attributes:{locksmith:s.cache.cart}})}).then(function(e){if(!e.ok)throw new Error("Cart update failed: "+e.status);return e.json()}).then(function(){e&&e()})["catch"](function(e){if(s.cache.cartLastSaved=t,!s.reloading)throw e})},s.util.spinnerHTML='<style>body{background:#FFF}@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}#loading{display:flex;width:100%;height:50vh;
8color:#777;align-items:center;justify-content:center}#loading .spinner{display:block;animation:spin 600ms linear infinite;position:relative;width:50px;height:50px}#loading .spinner-ring{stroke:currentColor;stroke-dasharray:100%;stroke-width:2px;stroke-linecap:round;fill:none}</style><div id="loading"><div class="spinner"><svg width="100%" height="100%"><svg preserveAspectRatio="xMinYMin"><circle class="spinner-ring" cx="50%" cy="50%" r="45%"></circle></svg></svg></div></div>',s.util.clobberBody=function(e){document.body.innerHTML=e},s.util.clobberDocument=function(e){e.responseText&&(e=e.responseText),document.documentElement&&document.removeChild(document.documentElement);var t=document.open("text/html","replace");t.writeln(e),t.close(),setTimeout(function(){var e=t.querySelector("[autofocus]");e&&e.focus()},100)},s.util.serializeForm=function(e){if(e&&"FORM"===e.nodeName){var t,n,o={};for(t=e.elements.length-1;0<=t;t-=1)if(""!==e.elements[t].name)switch(e.elements[t].nodeName){case"INPUT":switch(e.elements[t].type){default:case"text":case"hidden":case"password":case"button":case"reset":case"submit":o[e.elements[t].name]=e.elements[t].value;break;case"checkbox":case"radio":e.elements[t].checked&&(o[e.elements[t].name]=e.elements[t].value);break;case"file":}break;case"TEXTAREA":o[e.elements[t].name]=e.elements[t].value;break;case"SELECT":switch(e.elements[t].type){case"select-one":o[e.elements[t].name]=e.elements[t].value;break;case"select-multiple":for(n=e.elements[t].options.length-1;0<=n;n-=1)e.elements[t].options[n].selected&&(o[e.elements[t].name]=e.elements[t].options[n].value)}break;case"BUTTON":switch(e.elements[t].type){case"reset":case"submit":case"button":o[e.elements[t].name]=e.elements[t].value}}return o}},s.util.on=function(e,a,s,t){t=t||document;var c="locksmith-"+e+a,n=function(e){var t=e.target,n=e.target.parentElement,o=t&&t.className&&(t.className.baseVal||t.className)||"",i=n&&n.className&&(n.className.baseVal||n.className)||"";("string"==typeof o&&-1!==o.split(/\s+/).indexOf(a)||"string"==typeof i&&-1!==i.split(/\s+/).indexOf(a))&&!e[c]&&(e[c]=!0,s(e))};t.attachEvent?t.attachEvent(e,n):t.addEventListener(e,n,!1)},s.util.enableActions=function(e){s.util.on("click","locksmith-action",function(e){e.preventDefault();var t=e.target;t.dataset.confirmWith&&!confirm(t.dataset.confirmWith)||(t.disabled=!0,t.innerText=t.dataset.disableWith,s.post("/action",t.dataset.locksmithParams,{spinner:!1,type:"text",success:function(e){(e=JSON.parse(e.responseText)).message&&alert(e.message),s.util.reload()}}))},e)},s.util.inject=function(e,t){var n=["data","locksmith","append"];if(-1!==t.indexOf(n.join("-"))){var o=document.createElement("div");o.innerHTML=t,e.appendChild(o)}else e.innerHTML=t;var i,a,s=e.querySelectorAll("script");for(a=0;a<s.length;++a){i=s[a];var c=document.createElement("script");if(i.type&&(c.type=i.type),i.src)c.src=i.src;else{var l=document.createTextNode(i.innerHTML);c.appendChild(l)}e.appendChild(c)}var r=e.querySelector("[autofocus]");r&&r.focus()},s.post=function(e,t,n){!1!==(n=n||{}).spinner&&s.util.clobberBody(s.util.spinnerHTML);var o={};n.container===document?(o.layout=1,n.success=function(e){s.util.clobberDocument(e)}):n.container&&(o.layout=0,n.success=function(e){var t="string"==typeof n.container?document.getElementById(n.container):n.container;t&&(s.util.inject(t,e),t.id===t.firstChild.id&&t.parentElement.replaceChild(t.firstChild,t))}),n.form_type&&(t.form_type=n.form_type),n.include_layout_classes!==undefined&&(t.include_layout_classes=n.include_layout_classes),n.lock_id!==undefined&&(t.lock_id=n.lock_id),s.loading=!0;var i=s.util.makeUrl(e,o),a="json"===n.type||"text"===n.type;fetch(i,{method:"POST",headers:{"Content-Type":"application/json",Accept:a?"application/json":"text/html"},body:JSON.stringify(t)}).then(function(e){if(!e.ok)throw new Error("Request failed: "+e.status);return e.text()}).then(function(e){var t=n.success||s.util.clobberDocument;t(a?{responseText:e}:e)})["catch"](function(e){if(!s.reloading)if("dashboard.weglot.com"!==window.location.host){if(!n.silent)throw alert("Something went wrong! Please refresh and try again."),e;console.error(e)}else console.error(e)})["finally"](function(){s.loading=!1})},s.postResource=function(e,t){e.path=s.path,e.search=window.location.search,e.state=s.state,e.passcode&&(e.passcode=e.passcode.trim()),e.email&&(e.email=e.email.trim()),e.state.cart=s.cache.cart,e.locksmith_json=s.jsonTag,e.locksmith_json_signature=s.jsonTagSignature,s.post("/resource",e,t)},s.ping=function(e){if(!s.isEmbedded){e=e||{};s.post("/ping",{path:s.path,search:window.location.search,state:s.state},{spinner:!!e.spinner,silent:"undefined"==typeof e.silent||e.silent,type:"text",success:function(e){e&&e.responseText?(e=JSON.parse(e.responseText)).messages&&0<e.messages.length&&s.showMessages(e.messages):console.error("[Locksmith] Invalid result in ping callback:",e)}})}},s.timeoutMonitor=function(){var e=s.cache.cart;s.ping({callback:function(){e!==s.cache.cart||setTimeout(function(){s.timeoutMonitor()},6e4)}})},s.showMessages=function(e){var t=document.createElement("div");t.style.position="fixed",t.style.left=0,t.style.right=0,t.style.bottom="-50px",t.style.opacity=0,t.style.background="#191919",t.style.color="#ddd",t.style.transition="bottom 0.2s, opacity 0.2s",t.style.zIndex=999999,t.innerHTML=["<style>"," .locksmith-ab .locksmith-b { display: none; }"," .locksmith-ab.toggled .locksmith-b { display: flex; }"," .locksmith-ab.toggled .locksmith-a { display: none; }"," .locksmith-flex { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; padding: 10px 20px; }"," .locksmith-message + .locksmith-message { border-top: 1px #555 solid; }"," .locksmith-message a { color: inherit; font-weight: bold; }"," .locksmith-message a:hover { color: inherit; opacity: 0.8; }"," a.locksmith-ab-toggle { font-weight: inherit; text-decoration: underline; }"," .locksmith-text { flex-grow: 1; }"," .locksmith-cta { flex-grow: 0; text-align: right; }"," .locksmith-cta button { transform: scale(0.8); transform-origin: left; }"," .locksmith-cta > * { display: block; }"," .locksmith-cta > * + * { margin-top: 10px; }"," .locksmith-message a.locksmith-close { flex-grow: 0; text-decoration: none; margin-left: 15px; font-size: 30px; font-family: monospace; display: block; padding: 2px 10px; }"," @media screen and (max-width: 600px) {"," .locksmith-wide-only { display: none !important; }"," .locksmith-flex { padding: 0 15px; }"," .locksmith-flex > * { margin-top: 5px; margin-bottom: 5px; }"," .locksmith-cta { text-align: left; }"," }"," @media screen and (min-width: 601px) {"," .locksmith-narrow-only { display: none !important; }"," }","</style>"].join("")+e.map(function(e){return'<div class="locksmith-message">'+e+"</div>"}).join(""),document.body.appendChild(t),document.body.style.position="relative",document.body.parentElement.style.paddingBottom=t.offsetHeight+"px",setTimeout(function(){t.style.bottom=0,t.style.opacity=1},50),s.util.on("click","locksmith-ab-toggle",function(e){e.preventDefault();for(var t=e.target.parentElement;-1===t.className.split(" ").indexOf("locksmith-ab");)t=t.parentElement;-1!==t.className.split(" ").indexOf("toggled")?t.className=t.className.replace("toggled",""):t.className=t.className+" toggled"}),s.util.enableActions(t)}}()}();</script>
8 9
9<script data-locksmith>Locksmith.cache.cart=null</script>
9 10 11
11<script data-locksmith>Locksmith.jsonTag="{\"version\":\"v346\",\"locked\":false,\"initialized\":true,\"scope\":\"collection\",\"access_granted\":true,\"access_denied\":false,\"requires_customer\":false,\"manual_lock\":false,\"remote_lock\":false,\"has_timeout\":false,\"remote_rendered\":null,\"hide_resource\":false,\"hide_links_to_resource\":false,\"hide_price\":false,\"hide_add_to_cart\":false,\"transparent\":true,\"locks\":{\"all\":[],\"opened\":[]},\"keys\":[],\"keys_signature\":\"7d134c1eeeaa0bc5227844f58440d5fb8ef11fc597a6610310f55b975f5d0e30\",\"state\":{\"template\":\"collection.events-collectie\",\"theme\":178807996790,\"product\":null,\"collection\":\"events\",\"page\":null,\"blog\":null,\"article\":null,\"app\":null},\"now\":1791129347,\"path\":\"\\\/collections\\\/events\",\"locale_root_url\":\"\\\/en-en\",\"canonical_url\":\"https:\\\/\\\/granrondo.cc\\\/en-en\\\/collections\\\/events\",\"customer_id\":null,\"customer_id_signature\":\"7d134c1eeeaa0bc5227844f58440d5fb8ef11fc597a6610310f55b975f5d0e30\",\"cart\":null}";Locksmith.jsonTagSignature="5801b3d98ab44212d1842fb7cc5bed79bc1dd2d27072c5312bb555a4e9586a13"</script>
11 12 13 14
15<script> 16(function () { 17 'use strict'; 18 19 if (window._grFetchDedup) return; 20 window._grFetchDedup = true; 21 22 /* Exact, niet als patroon. Wat hier niet letterlijk in staat, blijft met 23 rust â inclusief alles wat naar Apps Script gaat. */ 24 var SHEETS = [ 25 'https://opensheet.elk.sh/1_Bc2komUMc7pVNT8rQkO0_Djnh41O5wCOvBMozarCms/routes', 26 'https://opensheet.elk.sh/1z4oQxDzP6xwMxKY61Lp9X7Ky3wpQ27XjV79oIrJOtWo/Activiteiten' 27 ]; 28 29 var VENSTER_MS = 10000; // alleen tijdens de laadstorm 30 var GEDULD_MS = 8000; // zo lang wacht een meelifter hoogstens 31 var start = Date.now(); 32 var lopend = Object.create(null); 33 var bespaard = 0; 34 35 var origineel = window.fetch; 36 if (typeof origineel !== 'function' || typeof Response !== 'function') return; 37 38 function bouwResponse(b) { 39 var r = new Response(b.tekst, { 40 status: b.status, statusText: b.statusText, headers: b.headers 41 }); 42 try { Object.defineProperty(r, 'url', { value: b.url }); } catch (e) {} 43 return r; 44 } 45 46 window.fetch = function (bron, opties) { 47 /* Alleen de kale vorm fetch("https://â¦"). Eén argument, een string, en 48 een URL die letterlijk in de lijst staat. Al het andere gaat door 49 zonder dat wij het aanraken. */ 50 var kaal = arguments.length === 1 51 && typeof bron === 'string' 52 && SHEETS.indexOf(bron) > -1 53 && (Date.now() - start) < VENSTER_MS; 54 55 if (!kaal) return origineel.apply(this, arguments); 56 57 var url = bron; 58 var zelf = this; 59 var eigenVerzoek = function () { return origineel.call(zelf, url); }; 60 61 if (lopend[url]) { 62 bespaard++; 63 /* Meeliften mag, maar niet onbeperkt lang. Loopt het gedeelde verzoek 64 vast of duurt het te lang, dan halen we het alsnog zelf op. Dat is 65 het verschil met versie 2, waar precies dit tot 30 seconden stilstand 66 leidde. */ 67 var gered = false; 68 return Promise.race([ 69 lopend[url].then(function (b) { gered = true; return bouwResponse(b); }), 70 new Promise(function (res) { 71 setTimeout(function () { if (!gered) res(eigenVerzoek()); }, GEDULD_MS); 72 }) 73 ]).catch(eigenVerzoek); // gedeeld verzoek mislukt? dan gewoon zelf. 74 } 75 76 var belofte = eigenVerzoek().then(function (r) { 77 return r.text().then(function (tekst) { 78 return { 79 tekst: tekst, status: r.status, statusText: r.statusText, 80 headers: r.headers, url: r.url 81 }; 82 }); 83 }); 84 85 lopend[url] = belofte; 86 belofte.then( 87 function () { setTimeout(function () { delete lopend[url]; }, VENSTER_MS); }, 88 function () { delete lopend[url]; } 89 ); 90 91 return belofte.then(bouwResponse); 92 }; 93 94 setTimeout(function () { 95 lopend = Object.create(null); 96 if (!window._grFetchStil) { 97 console.info('[GR fetch] ' + bespaard + ' dubbele dataverzoeken samengevoegd tijdens het laden.'); 98 } 99 }, VENSTER_MS + 500); 100 101 window.grFetchDedupStand = function () { 102 return { bespaard: bespaard, nogActief: (Date.now() - start) < VENSTER_MS }; 103 }; 104})(); 105</script>
105 106
107<script> 108(function () { 109 var path = (window.location.pathname || "/"); 110 path = path.replace(/\/+$/, ""); 111 if (path === "") path = "/"; 112 113 // Bovenaan, vóór alle andere routes: 114if (path === "/shop") { 115 window.location.replace("https://granrondo.cc/products/rondobox"); 116 return; 117} 118 119 // Gebruik overal streepjes (-) zodat dit direct overeenkomt met de URL slugs 120 var routes = { 121 "nederland": { code: "DERVNL", afk: "nl", item: "55331900686710", reseller: "55330927149430" }, 122 "achterhoek": { code: "DERVDAH", afk: "ah", item: "55331876733302", reseller: "55321966575990" }, 123 "amsterdam": { code: "DERVAM", afk: "am", item: "55242755015030", reseller: "55298321908086" }, 124 "drenthe": { code: "DERVDR", afk: "dr", item: "55331878076790", reseller: "55322156695926" }, 125 "flevoland": { code: "DERVFL", afk: "fl", item: "55331887808886", reseller: "55329044038006" }, 126 "friesland": { code: "DERVFR", afk: "fr", item: "55331888857462", reseller: "55642467664246" }, 127 "gelderland": { code: "DERVGD", afk: "gd", item: "55331889840502", reseller: "55329051640182" }, 128 "groningen": { code: "DERVGR", afk: "gr", item: "55331892691318", reseller: "55329059537270" }, 129 "limburg-nl": { code: "DERVLB", afk: "lb", item: "55331893870966", reseller: "55329065009526" }, 130 "noord-brabant": { code: "DERVNB", afk: "nb", item: "55331894788470", reseller: "55330849489270" }, 131 "noord-holland": { code: "DERVNH", afk: "nh", item: "55331895378294", reseller: "55330862072182" }, 132 "overijssel": { code: "DERVOV", afk: "ov", item: "55331896852854", reseller: "55330916401526" }, 133 "utrecht": { code: "DERVUT", afk: "ut", item: "55331897573750", reseller: "55330945597814" }, 134 "veluwe": { code: "DERVVE", afk: "ve", item: "55331880075638", reseller: "55327306383734" }, 135 "zeeland": { code: "DERVZL", afk: "zl", item: "55331901243766", reseller: "55331006022006" }, 136 "zuid-holland": { code: "DERVZH", afk: "zh", item: "55331903635830", reseller: "55330962866550" }, 137 "belgie": { code: "DERVBE", afk: "be", item: "55331909271926", reseller: "55153273176438" }, 138 "vlaanderen": { code: "DERVV", afk: "vl", item: "55153273143670", reseller: "55153273209206" }, 139 "salland": { code: "GRNLSA", afk: "sa", item: null, reseller: null }, 140 "twente": { code: "GRNLTW", afk: "tw", item: "58070356918646", reseller: null }, 141 "antwerpen": { code: "GRBEAN", afk: "bean", item: "58070296297846", reseller: null }, 142 "bruxelles": { code: "GRBEBH", afk: "bebr", item: "58070315303286", reseller: null }, 143 "brabant-wallon":{ code: "GRBEBW", afk: "bebw", item: "58070310814070", reseller: null }, 144 "hainaut": { code: "GRBEHA", afk: "beha", item: "58070320021878", reseller: null }, 145 "liege": { code: "GRBELG", afk: "belg", item: "58070327460214", reseller: null }, 146 "limburg-be": { code: "GRBELI", afk: "beli", item: "58070330179958", reseller: null }, 147 "luxembourg": { code: "GRBELU", afk: "belu", item: "58070334407030", reseller: null }, 148 "namur": { code: "GRBENA", afk: "bena", item: "58070335816054", reseller: null }, 149 "oost-vlaanderen":{ code: "GRBEOV", afk: "beov", item: "58070349709686", reseller: null }, 150 "vlaams-brabant": { code: "GRBEVB", afk: "bevb", item: "58070352134518", reseller: null }, 151 "wallonie": { code: "GRBEWA", afk: "bewa", item: "58070353903990", reseller: null }, 152 "west-vlaanderen":{ code: "GRBEWV", afk: "bewv", item: "58070356066678", reseller: null }, 153 "letzebuerg": { code: "GRLU", afk: "lu", item: "58070359736694", reseller: null }, 154 "great-britain": { code: "GRGB", afk: "gb", item: null, reseller: null } 155 }; 156 157 var byCode = {}; 158 var byAfk = {}; 159 Object.keys(routes).forEach(function (gebied) { 160 var r = routes[gebied]; 161 if (r.code) byCode[r.code.toUpperCase()] = { gebied: gebied, r: r }; 162 if (r.afk) byAfk[r.afk.toLowerCase()] = { gebied: gebied, r: r }; 163 }); 164 165 function abs(pathOrUrl) { 166 if (!pathOrUrl) return null; 167 if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl; 168 return "https://granrondo.cc" + pathOrUrl; 169 } 170 171 // Helper om paden te bouwen 172 function productPath(gebied) { return "/products/gran-rondo-" + gebied; } 173 function previewPath(gebied) { return "/products/gran-rondo-" + gebied + "?preview"; } 174 175 // A) DERVXX+reseller 176 var mReseller = path.match(/^\/((?:DERV|GRNL|GRBE)[A-Z]+)\+reseller$/i); 177 if (mReseller) { 178 var hitR = byCode[mReseller[1].toUpperCase()]; 179 if (hitR && hitR.r.reseller) { 180 window.location.replace("https://granrondo.cc/cart/" + hitR.r.reseller + ":1?storefront=true&discount=reseller"); 181 return; 182 } 183 } 184 185 // B) DERVXX-<korting> 186 var mItem = path.match(/^\/((?:DERV|GR|GRNL|GRBE)[A-Z]+)-(.+)$/i); 187 if (mItem) { 188 var hit = byCode[mItem[1].toUpperCase()]; 189 if (hit && hit.r.item) { 190 window.location.replace("https://granrondo.cc/cart/" + hit.r.item + ":1?storefront=true&discount=" + mItem[1].toUpperCase() + "-" + encodeURIComponent(mItem[2])); 191 return; 192 } 193 } 194 195 // C) /b/<afk> -> product 196 var mB = path.match(/^\/b\/([a-z0-9_-]+)$/i); 197 if (mB) { 198 var hitB = byAfk[mB[1].toLowerCase()]; 199 if (hitB) { 200 window.location.replace(abs(productPath(hitB.gebied))); 201 return; 202 } 203 } 204 205 // D) /t/<afk> -> preview 206 var mT = path.match(/^\/t\/([a-z0-9_-]+)$/i); 207 if (mT) { 208 var hitT = byAfk[mT[1].toLowerCase()]; 209 if (hitT) { 210 window.location.replace(abs(previewPath(hitT.gebied))); 211 return; 212 } 213 } 214 215 // E) /<gebied> -> product 216 var mSlug = path.match(/^\/([a-z0-9_-]+)$/i); 217 if (mSlug) { 218 var slug = mSlug[1].toLowerCase(); 219 if (routes[slug]) { 220 window.location.replace(abs(productPath(slug))); 221 return; 222 } 223 } 224})(); 225</script>
225 226 227 228 229 <meta charset="utf-8"> 230 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 231 <meta name="viewport" content="width=device-width,initial-scale=1"> 232 <meta name="theme-color" content=""> 233 <link rel="canonical" href="https://granrondo.cc/en-en/collections/events"> 234 <link rel="manifest" href="https://cdn.shopify.com/s/files/1/0899/1277/0934/files/manifest.json"><link rel="icon" type="image/png" href="//granrondo.cc/cdn/shop/files/CC_color_287ede2d-447b-4696-bc2b-a6aa7af3e415.png?crop=center&height=32&v=1742861988&width=32"><link rel="preconnect" href="https://fonts.shopifycdn.com" crossorigin><title> 235 Events 236 âï¸ GRANRONDO.cc</title> 237 238 239 240 241 242<meta property="og:site_name" content="GRANRONDO.cc"> 243<meta property="og:url" content="https://granrondo.cc/en-en/collections/events"><meta property="og:title" content="Events"> 244<meta property="og:type" content="website"> 245<meta property="og:description" content="Hey, wanna join for a Rondo? Join us and let your cycling adventures spin with Gran Rondo! ð´ââï¸â¨ Cycling together for KiKa â for a world where every child can be cancer-free."> 246<meta property="og:image" content="http://granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790"> 247<meta property="og:image:secure_url" content="https://granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790"> 248<meta property="og:image:width" content="1800"> 249 <meta property="og:image:height" content="1350"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Events"> 250<meta name="twitter:description" content="Hey, wanna join for a Rondo? Join us and let your cycling adventures spin with Gran Rondo! ð´ââï¸â¨ Cycling together for KiKa â for a world where every child can be cancer-free."> 251 252 253
253<script src="//granrondo.cc/cdn/shop/t/1/assets/constants.js?v=132983761750457495441737013876" defer="defer"></script>
253 254
254<script src="//granrondo.cc/cdn/shop/t/1/assets/pubsub.js?v=158357773527763999511737013878" defer="defer"></script>
254 255
255<script src="//granrondo.cc/cdn/shop/t/1/assets/global.js?v=152862011079830610291754231177" defer="defer"></script>
255 256
256<script src="//granrondo.cc/cdn/shop/t/1/assets/details-disclosure.js?v=13653116266235556501737013876" defer="defer"></script>
256 257
257<script src="//granrondo.cc/cdn/shop/t/1/assets/details-modal.js?v=25581673532751508451737013876" defer="defer"></script>
257 258
258<script src="//granrondo.cc/cdn/shop/t/1/assets/search-form.js?v=133129549252120666541737013878" defer="defer"></script>
258<script src="//granrondo.cc/cdn/shop/t/1/assets/animations.js?v=88693664871331136111737013876" defer="defer"></script>
258<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
258<meta name="robots" content="noindex,nofollow"> 259<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/89912770934/digital_wallets/dialog"> 260<link rel="ucp" href="/.well-known/ucp" version="2026-08-25"><link rel="alternate" type="application/atom+xml" title="Feed" href="/en-en/collections/events.atom" /> 261<link rel="alternate" hreflang="x-default" href="https://granrondo.cc/collections/events"> 262<link rel="alternate" hreflang="nl" href="https://granrondo.cc/collections/events"> 263<link rel="alternate" hreflang="en" href="https://granrondo.cc/en/collections/events"> 264<link rel="alternate" hreflang="en-AT" href="https://granrondo.cc/en-en/collections/events"> 265<link rel="alternate" hreflang="en-BG" href="https://granrondo.cc/en-en/collections/events"> 266<link rel="alternate" hreflang="en-HR" href="https://granrondo.cc/en-en/collections/events"> 267<link rel="alternate" hreflang="en-CY" href="https://granrondo.cc/en-en/collections/events"> 268<link rel="alternate" hreflang="en-CZ" href="https://granrondo.cc/en-en/collections/events"> 269<link rel="alternate" hreflang="en-DE" href="https://granrondo.cc/en-en/collections/events"> 270<link rel="alternate" hreflang="en-DK" href="https://granrondo.cc/en-en/collections/events"> 271<link rel="alternate" hreflang="en-EE" href="https://granrondo.cc/en-en/collections/events"> 272<link rel="alternate" hreflang="en-FI" href="https://granrondo.cc/en-en/collections/events"> 273<link rel="alternate" hreflang="en-FR" href="https://granrondo.cc/en-en/collections/events"> 274<link rel="alternate" hreflang="en-GR" href="https://granrondo.cc/en-en/collections/events"> 275<link rel="alternate" hreflang="en-HU" href="https://granrondo.cc/en-en/collections/events"> 276<link rel="alternate" hreflang="en-IE" href="https://granrondo.cc/en-en/collections/events"> 277<link rel="alternate" hreflang="en-IT" href="https://granrondo.cc/en-en/collections/events"> 278<link rel="alternate" hreflang="en-LV" href="https://granrondo.cc/en-en/collections/events"> 279<link rel="alternate" hreflang="en-LT" href="https://granrondo.cc/en-en/collections/events"> 280<link rel="alternate" hreflang="en-LU" href="https://granrondo.cc/en-en/collections/events"> 281<link rel="alternate" hreflang="en-MT" href="https://granrondo.cc/en-en/collections/events"> 282<link rel="alternate" hreflang="en-PL" href="https://granrondo.cc/en-en/collections/events"> 283<link rel="alternate" hreflang="en-PT" href="https://granrondo.cc/en-en/collections/events"> 284<link rel="alternate" hreflang="en-RO" href="https://granrondo.cc/en-en/collections/events"> 285<link rel="alternate" hreflang="en-SK" href="https://granrondo.cc/en-en/collections/events"> 286<link rel="alternate" hreflang="en-SI" href="https://granrondo.cc/en-en/collections/events"> 287<link rel="alternate" hreflang="en-ES" href="https://granrondo.cc/en-en/collections/events"> 288<link rel="alternate" hreflang="en-SE" href="https://granrondo.cc/en-en/collections/events"> 289<link rel="alternate" hreflang="en-AE" href="https://granrondo.cc/en-en/collections/events"> 290<link rel="alternate" hreflang="en-AU" href="https://granrondo.cc/en-en/collections/events"> 291<link rel="alternate" hreflang="en-CA" href="https://granrondo.cc/en-en/collections/events"> 292<link rel="alternate" hreflang="en-CH" href="https://granrondo.cc/en-en/collections/events"> 293<link rel="alternate" hreflang="en-GB" href="https://granrondo.cc/en-en/collections/events"> 294<link rel="alternate" hreflang="en-HK" href="https://granrondo.cc/en-en/collections/events"> 295<link rel="alternate" hreflang="en-IL" href="https://granrondo.cc/en-en/collections/events"> 296<link rel="alternate" hreflang="en-JP" href="https://granrondo.cc/en-en/collections/events"> 297<link rel="alternate" hreflang="en-KR" href="https://granrondo.cc/en-en/collections/events"> 298<link rel="alternate" hreflang="en-MY" href="https://granrondo.cc/en-en/collections/events"> 299<link rel="alternate" hreflang="en-NO" href="https://granrondo.cc/en-en/collections/events"> 300<link rel="alternate" hreflang="en-NZ" href="https://granrondo.cc/en-en/collections/events"> 301<link rel="alternate" hreflang="en-SG" href="https://granrondo.cc/en-en/collections/events"> 302<link rel="alternate" hreflang="en-US" href="https://granrondo.cc/en-en/collections/events"> 303<link rel="alternate" hreflang="en-AF" href="https://granrondo.cc/en-en/collections/events"> 304<link rel="alternate" hreflang="en-AX" href="https://granrondo.cc/en-en/collections/events"> 305<link rel="alternate" hreflang="en-AL" href="https://granrondo.cc/en-en/collections/events"> 306<link rel="alternate" hreflang="en-DZ" href="https://granrondo.cc/en-en/collections/events"> 307<link rel="alternate" hreflang="en-AD" href="https://granrondo.cc/en-en/collections/events"> 308<link rel="alternate" hreflang="en-AO" href="https://granrondo.cc/en-en/collections/events"> 309<link rel="alternate" hreflang="en-AI" href="https://granrondo.cc/en-en/collections/events"> 310<link rel="alternate" hreflang="en-AG" href="https://granrondo.cc/en-en/collections/events"> 311<link rel="alternate" hreflang="en-AR" href="https://granrondo.cc/en-en/collections/events"> 312<link rel="alternate" hreflang="en-AM" href="https://granrondo.cc/en-en/collections/events"> 313<link rel="alternate" hreflang="en-AW" href="https://granrondo.cc/en-en/collections/events"> 314<link rel="alternate" hreflang="en-AC" href="https://granrondo.cc/en-en/collections/events"> 315<link rel="alternate" hreflang="en-AZ" href="https://granrondo.cc/en-en/collections/events"> 316<link rel="alternate" hreflang="en-BS" href="https://granrondo.cc/en-en/collections/events"> 317<link rel="alternate" hreflang="en-BH" href="https://granrondo.cc/en-en/collections/events"> 318<link rel="alternate" hreflang="en-BD" href="https://granrondo.cc/en-en/collections/events"> 319<link rel="alternate" hreflang="en-BB" href="https://granrondo.cc/en-en/collections/events"> 320<link rel="alternate" hreflang="en-BY" href="https://granrondo.cc/en-en/collections/events"> 321<link rel="alternate" hreflang="en-BZ" href="https://granrondo.cc/en-en/collections/events"> 322<link rel="alternate" hreflang="en-BJ" href="https://granrondo.cc/en-en/collections/events"> 323<link rel="alternate" hreflang="en-BM" href="https://granrondo.cc/en-en/collections/events"> 324<link rel="alternate" hreflang="en-BT" href="https://granrondo.cc/en-en/collections/events"> 325<link rel="alternate" hreflang="en-BO" href="https://granrondo.cc/en-en/collections/events"> 326<link rel="alternate" hreflang="en-BA" href="https://granrondo.cc/en-en/collections/events"> 327<link rel="alternate" hreflang="en-BW" href="https://granrondo.cc/en-en/collections/events"> 328<link rel="alternate" hreflang="en-BR" href="https://granrondo.cc/en-en/collections/events"> 329<link rel="alternate" hreflang="en-IO" href="https://granrondo.cc/en-en/collections/events"> 330<link rel="alternate" hreflang="en-VG" href="https://granrondo.cc/en-en/collections/events"> 331<link rel="alternate" hreflang="en-BN" href="https://granrondo.cc/en-en/collections/events"> 332<link rel="alternate" hreflang="en-BF" href="https://granrondo.cc/en-en/collections/events"> 333<link rel="alternate" hreflang="en-BI" href="https://granrondo.cc/en-en/collections/events"> 334<link rel="alternate" hreflang="en-KH" href="https://granrondo.cc/en-en/collections/events"> 335<link rel="alternate" hreflang="en-BQ" href="https://granrondo.cc/en-en/collections/events"> 336<link rel="alternate" hreflang="en-CF" href="https://granrondo.cc/en-en/collections/events"> 337<link rel="alternate" hreflang="en-CL" href="https://granrondo.cc/en-en/collections/events"> 338<link rel="alternate" hreflang="en-CN" href="https://granrondo.cc/en-en/collections/events"> 339<link rel="alternate" hreflang="en-CX" href="https://granrondo.cc/en-en/collections/events"> 340<link rel="alternate" hreflang="en-CC" href="https://granrondo.cc/en-en/collections/events"> 341<link rel="alternate" hreflang="en-CO" href="https://granrondo.cc/en-en/collections/events"> 342<link rel="alternate" hreflang="en-KM" href="https://granrondo.cc/en-en/collections/events"> 343<link rel="alternate" hreflang="en-CG" href="https://granrondo.cc/en-en/collections/events"> 344<link rel="alternate" hreflang="en-CD" href="https://granrondo.cc/en-en/collections/events"> 345<link rel="alternate" hreflang="en-CK" href="https://granrondo.cc/en-en/collections/events"> 346<link rel="alternate" hreflang="en-CR" href="https://granrondo.cc/en-en/collections/events"> 347<link rel="alternate" hreflang="en-CW" href="https://granrondo.cc/en-en/collections/events"> 348<link rel="alternate" hreflang="en-DJ" href="https://granrondo.cc/en-en/collections/events"> 349<link rel="alternate" hreflang="en-DM" href="https://granrondo.cc/en-en/collections/events"> 350<link rel="alternate" hreflang="en-DO" href="https://granrondo.cc/en-en/collections/events"> 351<link rel="alternate" hreflang="en-EC" href="https://granrondo.cc/en-en/collections/events"> 352<link rel="alternate" hreflang="en-EG" href="https://granrondo.cc/en-en/collections/events"> 353<link rel="alternate" hreflang="en-SV" href="https://granrondo.cc/en-en/collections/events"> 354<link rel="alternate" hreflang="en-GQ" href="https://granrondo.cc/en-en/collections/events"> 355<link rel="alternate" hreflang="en-ER" href="https://granrondo.cc/en-en/collections/events"> 356<link rel="alternate" hreflang="en-SZ" href="https://granrondo.cc/en-en/collections/events"> 357<link rel="alternate" hreflang="en-ET" href="https://granrondo.cc/en-en/collections/events"> 358<link rel="alternate" hreflang="en-FO" href="https://granrondo.cc/en-en/collections/events"> 359<link rel="alternate" hreflang="en-FK" href="https://granrondo.cc/en-en/collections/events"> 360<link rel="alternate" hreflang="en-FJ" href="https://granrondo.cc/en-en/collections/events"> 361<link rel="alternate" hreflang="en-PH" href="https://granrondo.cc/en-en/collections/events"> 362<link rel="alternate" hreflang="en-GF" href="https://granrondo.cc/en-en/collections/events"> 363<link rel="alternate" hreflang="en-PF" href="https://granrondo.cc/en-en/collections/events"> 364<link rel="alternate" hreflang="en-TF" href="https://granrondo.cc/en-en/collections/events"> 365<link rel="alternate" hreflang="en-GA" href="https://granrondo.cc/en-en/collections/events"> 366<link rel="alternate" hreflang="en-GM" href="https://granrondo.cc/en-en/collections/events"> 367<link rel="alternate" hreflang="en-GE" href="https://granrondo.cc/en-en/collections/events"> 368<link rel="alternate" hreflang="en-GH" href="https://granrondo.cc/en-en/collections/events"> 369<link rel="alternate" hreflang="en-GI" href="https://granrondo.cc/en-en/collections/events"> 370<link rel="alternate" hreflang="en-GD" href="https://granrondo.cc/en-en/collections/events"> 371<link rel="alternate" hreflang="en-GL" href="https://granrondo.cc/en-en/collections/events"> 372<link rel="alternate" hreflang="en-GP" href="https://granrondo.cc/en-en/collections/events"> 373<link rel="alternate" hreflang="en-GT" href="https://granrondo.cc/en-en/collections/events"> 374<link rel="alternate" hreflang="en-GG" href="https://granrondo.cc/en-en/collections/events"> 375<link rel="alternate" hreflang="en-GN" href="https://granrondo.cc/en-en/collections/events"> 376<link rel="alternate" hreflang="en-GW" href="https://granrondo.cc/en-en/collections/events"> 377<link rel="alternate" hreflang="en-GY" href="https://granrondo.cc/en-en/collections/events"> 378<link rel="alternate" hreflang="en-HT" href="https://granrondo.cc/en-en/collections/events"> 379<link rel="alternate" hreflang="en-HN" href="https://granrondo.cc/en-en/collections/events"> 380<link rel="alternate" hreflang="en-IS" href="https://granrondo.cc/en-en/collections/events"> 381<link rel="alternate" hreflang="en-IN" href="https://granrondo.cc/en-en/collections/events"> 382<link rel="alternate" hreflang="en-ID" href="https://granrondo.cc/en-en/collections/events"> 383<link rel="alternate" hreflang="en-IQ" href="https://granrondo.cc/en-en/collections/events"> 384<link rel="alternate" hreflang="en-IM" href="https://granrondo.cc/en-en/collections/events"> 385<link rel="alternate" hreflang="en-CI" href="https://granrondo.cc/en-en/collections/events"> 386<link rel="alternate" hreflang="en-JM" href="https://granrondo.cc/en-en/collections/events"> 387<link rel="alternate" hreflang="en-YE" href="https://granrondo.cc/en-en/collections/events"> 388<link rel="alternate" hreflang="en-JE" href="https://granrondo.cc/en-en/collections/events"> 389<link rel="alternate" hreflang="en-JO" href="https://granrondo.cc/en-en/collections/events"> 390<link rel="alternate" hreflang="en-KY" href="https://granrondo.cc/en-en/collections/events"> 391<link rel="alternate" hreflang="en-CV" href="https://granrondo.cc/en-en/collections/events"> 392<link rel="alternate" hreflang="en-CM" href="https://granrondo.cc/en-en/collections/events"> 393<link rel="alternate" hreflang="en-KZ" href="https://granrondo.cc/en-en/collections/events"> 394<link rel="alternate" hreflang="en-KE" href="https://granrondo.cc/en-en/collections/events"> 395<link rel="alternate" hreflang="en-KG" href="https://granrondo.cc/en-en/collections/events"> 396<link rel="alternate" hreflang="en-KI" href="https://granrondo.cc/en-en/collections/events"> 397<link rel="alternate" hreflang="en-UM" href="https://granrondo.cc/en-en/collections/events"> 398<link rel="alternate" hreflang="en-KW" href="https://granrondo.cc/en-en/collections/events"> 399<link rel="alternate" hreflang="en-XK" href="https://granrondo.cc/en-en/collections/events"> 400<link rel="alternate" hreflang="en-LA" href="https://granrondo.cc/en-en/collections/events"> 401<link rel="alternate" hreflang="en-LS" href="https://granrondo.cc/en-en/collections/events"> 402<link rel="alternate" hreflang="en-LB" href="https://granrondo.cc/en-en/collections/events"> 403<link rel="alternate" hreflang="en-LR" href="https://granrondo.cc/en-en/collections/events"> 404<link rel="alternate" hreflang="en-LY" href="https://granrondo.cc/en-en/collections/events"> 405<link rel="alternate" hreflang="en-LI" href="https://granrondo.cc/en-en/collections/events"> 406<link rel="alternate" hreflang="en-MO" href="https://granrondo.cc/en-en/collections/events"> 407<link rel="alternate" hreflang="en-MG" href="https://granrondo.cc/en-en/collections/events"> 408<link rel="alternate" hreflang="en-MW" href="https://granrondo.cc/en-en/collections/events"> 409<link rel="alternate" hreflang="en-MV" href="https://granrondo.cc/en-en/collections/events"> 410<link rel="alternate" hreflang="en-ML" href="https://granrondo.cc/en-en/collections/events"> 411<link rel="alternate" hreflang="en-MA" href="https://granrondo.cc/en-en/collections/events"> 412<link rel="alternate" hreflang="en-MQ" href="https://granrondo.cc/en-en/collections/events"> 413<link rel="alternate" hreflang="en-MR" href="https://granrondo.cc/en-en/collections/events"> 414<link rel="alternate" hreflang="en-MU" href="https://granrondo.cc/en-en/collections/events"> 415<link rel="alternate" hreflang="en-YT" href="https://granrondo.cc/en-en/collections/events"> 416<link rel="alternate" hreflang="en-MX" href="https://granrondo.cc/en-en/collections/events"> 417<link rel="alternate" hreflang="en-MD" href="https://granrondo.cc/en-en/collections/events"> 418<link rel="alternate" hreflang="en-MC" href="https://granrondo.cc/en-en/collections/events"> 419<link rel="alternate" hreflang="en-MN" href="https://granrondo.cc/en-en/collections/events"> 420<link rel="alternate" hreflang="en-ME" href="https://granrondo.cc/en-en/collections/events"> 421<link rel="alternate" hreflang="en-MS" href="https://granrondo.cc/en-en/collections/events"> 422<link rel="alternate" hreflang="en-MZ" href="https://granrondo.cc/en-en/collections/events"> 423<link rel="alternate" hreflang="en-MM" href="https://granrondo.cc/en-en/collections/events"> 424<link rel="alternate" hreflang="en-NA" href="https://granrondo.cc/en-en/collections/events"> 425<link rel="alternate" hreflang="en-NR" href="https://granrondo.cc/en-en/collections/events"> 426<link rel="alternate" hreflang="en-NP" href="https://granrondo.cc/en-en/collections/events"> 427<link rel="alternate" hreflang="en-NI" href="https://granrondo.cc/en-en/collections/events"> 428<link rel="alternate" hreflang="en-NC" href="https://granrondo.cc/en-en/collections/events"> 429<link rel="alternate" hreflang="en-NE" href="https://granrondo.cc/en-en/collections/events"> 430<link rel="alternate" hreflang="en-NG" href="https://granrondo.cc/en-en/collections/events"> 431<link rel="alternate" hreflang="en-NU" href="https://granrondo.cc/en-en/collections/events"> 432<link rel="alternate" hreflang="en-MK" href="https://granrondo.cc/en-en/collections/events"> 433<link rel="alternate" hreflang="en-NF" href="https://granrondo.cc/en-en/collectio
433ns/events"> 434<link rel="alternate" hreflang="en-UG" href="https://granrondo.cc/en-en/collections/events"> 435<link rel="alternate" hreflang="en-UA" href="https://granrondo.cc/en-en/collections/events"> 436<link rel="alternate" hreflang="en-UZ" href="https://granrondo.cc/en-en/collections/events"> 437<link rel="alternate" hreflang="en-OM" href="https://granrondo.cc/en-en/collections/events"> 438<link rel="alternate" hreflang="en-TL" href="https://granrondo.cc/en-en/collections/events"> 439<link rel="alternate" hreflang="en-PK" href="https://granrondo.cc/en-en/collections/events"> 440<link rel="alternate" hreflang="en-PS" href="https://granrondo.cc/en-en/collections/events"> 441<link rel="alternate" hreflang="en-PA" href="https://granrondo.cc/en-en/collections/events"> 442<link rel="alternate" hreflang="en-PG" href="https://granrondo.cc/en-en/collections/events"> 443<link rel="alternate" hreflang="en-PY" href="https://granrondo.cc/en-en/collections/events"> 444<link rel="alternate" hreflang="en-PE" href="https://granrondo.cc/en-en/collections/events"> 445<link rel="alternate" hreflang="en-PN" href="https://granrondo.cc/en-en/collections/events"> 446<link rel="alternate" hreflang="en-QA" href="https://granrondo.cc/en-en/collections/events"> 447<link rel="alternate" hreflang="en-RE" href="https://granrondo.cc/en-en/collections/events"> 448<link rel="alternate" hreflang="en-RU" href="https://granrondo.cc/en-en/collections/events"> 449<link rel="alternate" hreflang="en-RW" href="https://granrondo.cc/en-en/collections/events"> 450<link rel="alternate" hreflang="en-KN" href="https://granrondo.cc/en-en/collections/events"> 451<link rel="alternate" hreflang="en-LC" href="https://granrondo.cc/en-en/collections/events"> 452<link rel="alternate" hreflang="en-VC" href="https://granrondo.cc/en-en/collections/events"> 453<link rel="alternate" hreflang="en-BL" href="https://granrondo.cc/en-en/collections/events"> 454<link rel="alternate" hreflang="en-MF" href="https://granrondo.cc/en-en/collections/events"> 455<link rel="alternate" hreflang="en-PM" href="https://granrondo.cc/en-en/collections/events"> 456<link rel="alternate" hreflang="en-SB" href="https://granrondo.cc/en-en/collections/events"> 457<link rel="alternate" hreflang="en-WS" href="https://granrondo.cc/en-en/collections/events"> 458<link rel="alternate" hreflang="en-SM" href="https://granrondo.cc/en-en/collections/events"> 459<link rel="alternate" hreflang="en-ST" href="https://granrondo.cc/en-en/collections/events"> 460<link rel="alternate" hreflang="en-SA" href="https://granrondo.cc/en-en/collections/events"> 461<link rel="alternate" hreflang="en-SN" href="https://granrondo.cc/en-en/collections/events"> 462<link rel="alternate" hreflang="en-RS" href="https://granrondo.cc/en-en/collections/events"> 463<link rel="alternate" hreflang="en-SC" href="https://granrondo.cc/en-en/collections/events"> 464<link rel="alternate" hreflang="en-SL" href="https://granrondo.cc/en-en/collections/events"> 465<link rel="alternate" hreflang="en-SH" href="https://granrondo.cc/en-en/collections/events"> 466<link rel="alternate" hreflang="en-SX" href="https://granrondo.cc/en-en/collections/events"> 467<link rel="alternate" hreflang="en-SD" href="https://granrondo.cc/en-en/collections/events"> 468<link rel="alternate" hreflang="en-SO" href="https://granrondo.cc/en-en/collections/events"> 469<link rel="alternate" hreflang="en-SJ" href="https://granrondo.cc/en-en/collections/events"> 470<link rel="alternate" hreflang="en-LK" href="https://granrondo.cc/en-en/collections/events"> 471<link rel="alternate" hreflang="en-SR" href="https://granrondo.cc/en-en/collections/events"> 472<link rel="alternate" hreflang="en-TJ" href="https://granrondo.cc/en-en/collections/events"> 473<link rel="alternate" hreflang="en-TW" href="https://granrondo.cc/en-en/collections/events"> 474<link rel="alternate" hreflang="en-TZ" href="https://granrondo.cc/en-en/collections/events"> 475<link rel="alternate" hreflang="en-TH" href="https://granrondo.cc/en-en/collections/events"> 476<link rel="alternate" hreflang="en-TG" href="https://granrondo.cc/en-en/collections/events"> 477<link rel="alternate" hreflang="en-TK" href="https://granrondo.cc/en-en/collections/events"> 478<link rel="alternate" hreflang="en-TO" href="https://granrondo.cc/en-en/collections/events"> 479<link rel="alternate" hreflang="en-TT" href="https://granrondo.cc/en-en/collections/events"> 480<link rel="alternate" hreflang="en-TA" href="https://granrondo.cc/en-en/collections/events"> 481<link rel="alternate" hreflang="en-TD" href="https://granrondo.cc/en-en/collections/events"> 482<link rel="alternate" hreflang="en-TN" href="https://granrondo.cc/en-en/collections/events"> 483<link rel="alternate" hreflang="en-TR" href="https://granrondo.cc/en-en/collections/events"> 484<link rel="alternate" hreflang="en-TM" href="https://granrondo.cc/en-en/collections/events"> 485<link rel="alternate" hreflang="en-TC" href="https://granrondo.cc/en-en/collections/events"> 486<link rel="alternate" hreflang="en-TV" href="https://granrondo.cc/en-en/collections/events"> 487<link rel="alternate" hreflang="en-UY" href="https://granrondo.cc/en-en/collections/events"> 488<link rel="alternate" hreflang="en-VU" href="https://granrondo.cc/en-en/collections/events"> 489<link rel="alternate" hreflang="en-VA" href="https://granrondo.cc/en-en/collections/events"> 490<link rel="alternate" hreflang="en-VE" href="https://granrondo.cc/en-en/collections/events"> 491<link rel="alternate" hreflang="en-VN" href="https://granrondo.cc/en-en/collections/events"> 492<link rel="alternate" hreflang="en-WF" href="https://granrondo.cc/en-en/collections/events"> 493<link rel="alternate" hreflang="en-EH" href="https://granrondo.cc/en-en/collections/events"> 494<link rel="alternate" hreflang="en-ZM" href="https://granrondo.cc/en-en/collections/events"> 495<link rel="alternate" hreflang="en-ZW" href="https://granrondo.cc/en-en/collections/events"> 496<link rel="alternate" hreflang="en-ZA" href="https://granrondo.cc/en-en/collections/events"> 497<link rel="alternate" hreflang="en-GS" href="https://granrondo.cc/en-en/collections/events"> 498<link rel="alternate" hreflang="en-SS" href="https://granrondo.cc/en-en/collections/events"> 499<link rel="alternate" type="application/json+oembed" href="https://granrondo.cc/en-en/collections/events.oembed">
500<script async="async" src="/checkouts/internal/preloads.js?locale=en-US"></script>
vendor: 1 bytes, line 500
500
501<script id="apple-pay-shop-capabilities" type="application/json">{"shopId":89912770934,"countryCode":"NL","currencyCode":"USD","merchantCapabilities":["supports3DS"],"merchantId":"gid:\/\/shopify\/Shop\/89912770934","merchantName":"GRANRONDO.cc","requiredBillingContactFields":["postalAddress","email","phone"],"requiredShippingContactFields":["postalAddress","email","phone"],"shippingType":"shipping","supportedNetworks":["visa","maestro","masterCard","amex"],"total":{"type":"pending","label":"GRANRONDO.cc","amount":"1.00"},"shopifyPaymentsEnabled":true,"supportsSubscriptions":true}</script>
vendor: 1 bytes, line 501
501
502<script id="shopify-features" type="application/json">{"accessToken":"f5e1f0bfbe1322cfe5146304123a4b1f","betas":["rich-media-storefront-analytics"],"domain":"granrondo.cc","predictiveSearch":true,"shopId":89912770934,"locale":"en"}</script>
vendor: 1 bytes, line 502
502
503<script>var Shopify = Shopify || {}; 504Shopify.shop = "khdz0c-aq.myshopify.com"; 505Shopify.locale = "en"; 506Shopify.currency = {"active":"USD","rate":"1.1481426"}; 507Shopify.country = "US"; 508Shopify.theme = {"name":"Gran Rondo","id":178807996790,"schema_name":"Dawn","schema_version":"15.2.0","theme_store_id":887,"role":"main"}; 509Shopify.theme.handle = "null"; 510Shopify.theme.style = {"id":null,"handle":null}; 511Shopify.cdnHost = "granrondo.cc/cdn"; 512Shopify.routes = Shopify.routes || {}; 513Shopify.routes.root = "/en-en/"; 514Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js"; 515Shopify.SignInWithShop = Shopify.SignInWithShop || {}; 516Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {}; 517Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 517
517
518<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 518
518
519<script>!function(o){function n(){var o=[];function n(){o.push(Array.prototype.slice.apply(arguments))}return n.q=o,n}var t=o.Shopify=o.Shopify||{};t.loadFeatures=n(),t.autoloadFeatures=n()}(window);</script>
vendor: 1 bytes, line 519
519
520<script> 521 window.Shopify = window.Shopify || {}; 522 window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {}; 523 window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 }; 524 window.Shopify.SignInWithShop.eligible = false; 525</script>
vendor: 1 bytes, line 525
525
526<script id="shop-js-analytics" type="application/json">{"pageType":"collection"}</script>
vendor: 1 bytes, line 526
526
527<script defer="defer" async type="module" src="https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"></script>
vendor: 1 bytes, line 527
527
528<script type="module"> 529 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"); 530 531 window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true}); 532 533</script>
vendor: 1 bytes, line 533
533
534<script id="__st">var __st={"a":89912770934,"offset":7200,"reqid":"cc422a89-d3e5-4da3-a97c-b151b1c79dd5-1791129347","pageurl":"granrondo.cc\/en-en\/collections\/events","u":"1dec95e72a10","p":"collection","rtyp":"collection","rid":673588085110};</script>
vendor: 1 bytes, line 534
534
535<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 535
535
536<script id="captcha-bootstrap">!function(){'use strict';const t='contact',e='account',n='new_comment',o=[[t,t],['blogs',n],['comments',n],[t,'customer']],c=[[e,'customer_login'],[e,'guest_login'],[e,'recover_customer_password'],[e,'create_customer']],r=t=>t.map((([t,e])=>`form[action*='/${t}']:not([data-nocaptcha='true']) input[name='form_type'][value='${e}']`)).join(','),a=t=>()=>t?[...document.querySelectorAll(t)].map((t=>t.form)):[];function s(){const t=[...o],e=r(t);return a(e)}const i='password',u='form_key',d=['recaptcha-v3-token','g-recaptcha-response','h-captcha-response',i],f=()=>{try{return window.sessionStorage}catch{return}},m='__shopify_v',_=t=>t.elements[u];function p(t,e,n=!1){try{const o=window.sessionStorage,c=JSON.parse(o.getItem(e)),{data:r}=function(t){const{data:e,action:n}=t;return t[m]||n?{data:e,action:n}:{data:t,action:n}}(c);for(const[e,n]of Object.entries(r))t.elements[e]&&(t.elements[e].value=n);n&&o.removeItem(e)}catch(o){console.error('form repopulation failed',{error:o})}}const l='form_type',E='cptcha';function T(t){t.dataset[E]=!0}const w=window,h=w.document,L='Shopify',v='ce_forms',y='captcha';let A=!1;((t,e)=>{const n=(g='f06e6c50-85a8-45c8-87d0-21a2b65856fe',I='https://cdn.shopify.com/shopifycloud/storefront-forms-hcaptcha/ce_storefront_forms_captcha_hcaptcha.v1.5.3.iife.js',D={infoText:'Protected by hCaptcha',privacyText:'Privacy',termsText:'Terms'},(t,e,n)=>{const o=w[L][v],c=o.bindForm;if(c)return c(t,g,e,D).then(n);var r;o.q.push([[t,g,e,D],n]),r=I,A||(h.body.append(Object.assign(h.createElement('script'),{id:'captcha-provider',async:!0,src:r})),A=!0)});var g,I,D;w[L]=w[L]||{},w[L][v]=w[L][v]||{},w[L][v].q=[],w[L][y]=w[L][y]||{},w[L][y].protect=function(t,e){n(t,void 0,e),T(t)},Object.freeze(w[L][y]),function(t,e,n,w,h,L){const[v,y,A,g]=function(t,e,n){const i=e?o:[],u=t?c:[],d=[...i,...u],f=r(d),m=r(i),_=r(d.filter((([t,e])=>n.includes(e))));return[a(f),a(m),a(_),s()]}(w,h,L),I=t=>{const e=t.target;return e instanceof HTMLFormElement?e:e&&e.form},D=t=>v().includes(t);t.addEventListener('submit',(t=>{const e=I(t);if(!e)return;const n=D(e)&&!e.dataset.hcaptchaBound&&!e.dataset.recaptchaBound,o=_(e),c=g().includes(e)&&(!o||!o.value);(n||c)&&t.preventDefault(),c&&!n&&(function(t){try{if(!f())return;!function(t){const e=f();if(!e)return;const n=_(t);if(!n)return;const o=n.value;o&&e.removeItem(o)}(t);const e=Array.from(Array(32),(()=>Math.random().toString(36)[2])).join('');!function(t,e){_(t)||t.append(Object.assign(document.createElement('input'),{type:'hidden',name:u})),t.elements[u].value=e}(t,e),function(t,e){const n=f();if(!n)return;const o=[...t.querySelectorAll(`input[type='${i}']`)].map((({name:t})=>t)),c=[...d,...o],r={};for(const[a,s]of new FormData(t).entries())c.includes(a)||(r[a]=s);n.setItem(e,JSON.stringify({[m]:1,action:t.action,data:r}))}(t,e)}catch(e){console.error('failed to persist form',e)}}(e),e.submit())}));const S=(t,e)=>{t&&!t.dataset[E]&&(n(t,e.some((e=>e===t))),T(t))};for(const o of['focusin','change'])t.addEventListener(o,(t=>{const e=I(t);D(e)&&S(e,y())}));const B=e.get('form_key'),M=e.get(l),P=B&&M;t.addEventListener('DOMContentLoaded',(()=>{const t=y();if(P)for(const e of t)e.elements[l].value===M&&p(e,B);[...new Set([...A(),...v().filter((t=>'true'===t.dataset.shopifyCaptcha))])].forEach((e=>S(e,t)))}))}(h,new URLSearchParams(w.location.search),n,t,e,['guest_login'])})(!0,!0)}();</script>
vendor: 1 bytes, line 536
536
537<script integrity="sha256-JjoPp5ZfB1sSAs5SQaol1x1GgvveM+BgmRzyDexInEQ=" data-source-attribution="shopify.loadfeatures" defer="defer" src="//granrondo.cc/cdn/shopifycloud/storefront/assets/storefront/load_feature-1bd60354.js" crossorigin="anonymous"></script>
vendor: 1 bytes, line 537
537
538<script>(function () {var userAgent = navigator.userAgent;var platform = navigator.platform;var maxTouchPoints = navigator.maxTouchPoints || 0;var isIOS = /iPad|iPhone|iPod/.test(platform) || (platform === 'MacIntel' && maxTouchPoints > 1);var isMacSafari = platform.indexOf('Mac') === 0 && /Safari/.test(userAgent) && !/Chrome|Chromium|CriOS|FxiOS|Edg|OPR|Android/.test(userAgent);var isAppleSafari = isIOS || isMacSafari;if (isAppleSafari) {fetch('/sf_private_access_tokens' + location.search).catch(function () {});}function browserMajorVersion(pattern) {var match = userAgent.match(pattern);return match ? parseInt(match[1], 10) : null;}function shouldLoadAutosizesPolyfill() {if (!window.PerformanceObserver?.supportedEntryTypes?.includes('paint')) {return false;}var chromeVersion = browserMajorVersion(/Chrome\/(\d+)/);if (chromeVersion !== null) {return chromeVersion < 126;}var firefoxVersion = browserMajorVersion(/Firefox\/(\d+)/);if (firefoxVersion !== null) {return firefoxVersion < 150;}var safariVersion = isAppleSafari ? browserMajorVersion(/Version\/(\d+).*Safari\//) : null;if (safariVersion !== null) {return safariVersion < 27;}return true;}if (shouldLoadAutosizesPolyfill()) {var autosizesScript = document.createElement('script');autosizesScript.async = true;autosizesScript.crossOrigin = 'anonymous';autosizesScript.src = "//granrondo.cc/cdn/shopifycloud/storefront/assets/storefront/autosizes-84416378.js";(document.head || document.documentElement).appendChild(autosizesScript);}window.ShopifyAnalytics = window.ShopifyAnalytics || {};window.ShopifyAnalytics.performance = window.ShopifyAnalytics.performance || {};(function () {var LONG_FRAME_THRESHOLD = 50;var longAnimationFrames = [];var activeRafId = null;function collectLongFrames() {var previousTime = null;function rafMonitor(now) {if (activeRafId === null) {return;}var delta = now - previousTime;if (delta > LONG_FRAME_THRESHOLD) {longAnimationFrames.push({startTime: previousTime,endTime: now,});}previousTime = now;activeRafId = requestAnimationFrame(rafMonitor);}previousTime = performance.now();activeRafId = requestAnimationFrame(rafMonitor);}if (!window.PerformanceObserver?.supportedEntryTypes?.includes('long-animation-frame')) {collectLongFrames();var timeoutId = setTimeout(function () {cancelAnimationFrame(activeRafId);}, 10000);window.ShopifyAnalytics.performance.getLongAnimationFrames = function (stopCollection) {if (stopCollection === undefined) {stopCollection = false;}if (stopCollection) {clearTimeout(timeoutId);cancelAnimationFrame(activeRafId);}return longAnimationFrames;};}})();})();</script>
538<script id="shopify-origin-trials" async="async" integrity="sha256-qJbe/jEZBHtr5W/BlA2cKAz3vkXu6vJQyLjgvgCC86g=" src="//cdn.shopify.com/shopifycloud/storefront/assets/storefront/origin_trials-318ab40a.js" crossorigin="anonymous" onload="window.__shopifyOriginTrialsDone = true" onerror="window.__shopifyOriginTrialsDone = true"></script>
vendor: 1 bytes, line 538
538
539<script> 540 window.Shopify = window.Shopify || {}; 541 window.Shopify.MCP = window.Shopify.MCP || {}; 542 window.Shopify.MCP.enabled = true; 543 window.Shopify.MCP.shop = "khdz0c-aq.myshopify.com"; 544 window.Shopify.MCP.mcpEndpoint = "https:\/\/granrondo.cc\/api\/mcp"; 545 window.Shopify.MCP.tools = [{"name":"search_shop_policies_and_faqs","description":"Used to get facts about the stores policies, products, or services.\nSome examples of questions you can ask are:\n - What is your return policy?\n - What is your shipping policy?\n - What is your phone number?\n - What are your hours of operation?\"\n","inputSchema":{"$schema":"https:\/\/json-schema.org\/draft\/2020-12\/schema","type":"object","properties":{"query":{"type":"string","description":"A natural language query."},"context":{"type":"string","description":"Additional information about the request such as user demographics, mood, location, or other relevant details that could help in tailoring the response appropriately."}},"required":["query"]}}]; 546</script>
vendor: 1 bytes, line 546
546
547<script>(()=>{var d="shopify:webmcp_adapter_loaded",n=Symbol.for("shopify.webmcp_adapter_loading");function s(c,a,{win:r=window,doc:o=document}={}){function p(){try{return r.localStorage.getItem(d)==="true"}catch{return!1}}function l(){try{r.localStorage.setItem(d,"true")}catch{}}function u(){return typeof(o.modelContext||r.navigator?.modelContext)?.registerTool=="function"}function f(){if(r[n]||!u())return;let t=o.head||o.getElementsByTagName("head")[0];if(!t)return;let e=o.createElement("script");e.type="module",e.crossOrigin="anonymous",a&&(e.integrity=a),e.src=c,e.addEventListener("load",l,{once:!0}),e.addEventListener("error",()=>{r[n]=!1},{once:!0}),t.appendChild(e),r[n]=!0}function _(t){let e=o.getElementById("shopify-origin-trials");if(!e||r.__shopifyOriginTrialsDone){t();return}e.addEventListener("load",t,{once:!0}),e.addEventListener("error",t,{once:!0})}function i(){_(()=>r.setTimeout(f,0))}function m(){o.addEventListener("DOMContentLoaded",i,{once:!0})}p()?i():m()}s("\/\/granrondo.cc\/cdn\/shopifycloud\/storefront\/assets\/storefront\/webmcp-c6b62ece.js","sha256-ke4DDuBjdvea3vxLWxHc9E9nq8zihuG4IfYEGbb77ys=");})(); 548</script>
vendor: 1 bytes, line 548
548
549<script data-source-attribution="shopify.dynamic_checkout.dynamic.init">var Shopify=Shopify||{};Shopify.PaymentButton=Shopify.PaymentButton||{isStorefrontPortableWallets:!0,init:function(){window.Shopify.PaymentButton.init=function(){};var t=document.createElement("script");t.src="https://granrondo.cc/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js",t.type="module",document.head.appendChild(t)}}; 550</script>
vendor: 1 bytes, line 550
550
551<script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> 552 function portableWalletsHideBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.add("hidden"),t.setAttribute("aria-hidden","true"),n.removeEventListener("click",e))}function portableWalletsShowBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.remove("hidden"),t.removeAttribute("aria-hidden"),n.addEventListener("click",e))}window.Shopify?.PaymentButton&&(window.Shopify.PaymentButton.hideBuyerConsent=portableWalletsHideBuyerConsent,window.Shopify.PaymentButton.showBuyerConsent=portableWalletsShowBuyerConsent); 553</script>
vendor: 1 bytes, line 553
553
554<script data-source-attribution="shopify.dynamic_checkout.cart.bootstrap">document.addEventListener("DOMContentLoaded",(function(){function t(){return document.querySelector("shopify-accelerated-checkout-cart, shopify-accelerated-checkout")}if(t())Shopify.PaymentButton.init();else{new MutationObserver((function(e,n){t()&&(Shopify.PaymentButton.init(),n.disconnect())})).observe(document.body,{childList:!0,subtree:!0})}})); 555</script>
555 556<link id="shopify-accelerated-checkout-styles" rel="stylesheet" media="screen" href="https://granrondo.cc/cdn/shopifycloud/portable-wallets/latest/accelerated-checkout-backwards-compat.css" crossorigin="anonymous"> 557<style id="shopify-accelerated-checkout-cart"> 558 #shopify-buyer-consent { 559 margin-top: 1em; 560 display: inline-block; 561 width: 100%; 562} 563 564#shopify-buyer-consent.hidden { 565 display: none; 566} 567 568#shopify-subscription-policy-button { 569 background: none; 570 border: none; 571 padding: 0; 572 text-decoration: underline; 573 font-size: inherit; 574 cursor: pointer; 575} 576 577#shopify-subscription-policy-button::before { 578 box-shadow: none; 579} 580 581 </style>
582<script id="sections-script" data-sections="header" defer="defer" src="//granrondo.cc/cdn/shop/t/1/compiled_assets/scripts.js?v=184325197989695213571737013894"></script>
vendor: 1 bytes, line 582
582
583<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
583 584 585 586 <style data-shopify> 587 @font-face { 588 font-family: Assistant; 589 font-weight: 400; 590 font-style: normal; 591 font-display: swap; 592 src: url("//granrondo.cc/cdn/fonts/assistant/assistant_n4.9120912a469cad1cc292572851508ca49d12e768.woff2") format("woff2"), 593 url("//granrondo.cc/cdn/fonts/assistant/assistant_n4.6e9875ce64e0fefcd3f4446b7ec9036b3ddd2985.woff") format("woff"); 594} 595 596 @font-face { 597 font-family: Assistant; 598 font-weight: 700; 599 font-style: normal; 600 font-display: swap; 601 src: url("//granrondo.cc/cdn/fonts/assistant/assistant_n7.bf44452348ec8b8efa3aa3068825305886b1c83c.woff2") format("woff2"), 602 url("//granrondo.cc/cdn/fonts/assistant/assistant_n7.0c887fee83f6b3bda822f1150b912c72da0f7b64.woff") format("woff"); 603} 604 605 606 607 @font-face { 608 font-family: Assistant; 609 font-weight: 400; 610 font-style: normal; 611 font-display: swap; 612 src: url("//granrondo.cc/cdn/fonts/assistant/assistant_n4.9120912a469cad1cc292572851508ca49d12e768.woff2") format("woff2"), 613 url("//granrondo.cc/cdn/fonts/assistant/assistant_n4.6e9875ce64e0fefcd3f4446b7ec9036b3ddd2985.woff") format("woff"); 614} 615 616 617 618 :root, 619 .color-scheme-1 { 620 --color-background: 255,255,255; 621 622 --gradient-background: #ffffff; 623 624 625 626 627 --color-foreground: 39,29,98; 628 --color-background-contrast: 191,191,191; 629 --color-shadow: 39,29,98; 630 --color-button: 255,182,0; 631 --color-button-text: 255,255,255; 632 --color-secondary-button: 255,255,255; 633 --color-secondary-button-text: 255,182,0; 634 --color-link: 255,182,0; 635 --color-badge-foreground: 39,29,98; 636 --color-badge-background: 255,255,255; 637 --color-badge-border: 39,29,98; 638 --payment-terms-background-color: rgb(255 255 255); 639 } 640 641 642 .color-scheme-2 { 643 --color-background: 239,241,253; 644 645 --gradient-background: #eff1fd; 646 647 648 649 650 --color-foreground: 39,29,98; 651 --color-background-contrast: 126,142,239; 652 --color-shadow: 39,29,98; 653 --color-button: 255,182,0; 654 --color-button-text: 255,255,255; 655 --color-secondary-button: 239,241,253; 656 --color-secondary-button-text: 39,29,98; 657 --color-link: 39,29,98; 658 --color-badge-foreground: 39,29,98; 659 --color-badge-background: 239,241,253; 660 --color-badge-border: 39,29,98; 661 --payment-terms-background-color: rgb(239 241 253); 662 } 663 664 665 .color-scheme-3 { 666 --color-background: 17,239,214; 667 668 --gradient-background: #11efd6; 669 670 671 672 673 --color-foreground: 39,29,98; 674 --color-background-contrast: 8,120,108; 675 --color-shadow: 39,29,98; 676 --color-button: 255,182,0; 677 --color-button-text: 255,255,255; 678 --color-secondary-button: 17,239,214; 679 --color-secondary-button-text: 255,182,0; 680 --color-link: 255,182,0; 681 --color-badge-foreground: 39,29,98; 682 --color-badge-background: 17,239,214; 683 --color-badge-border: 39,29,98; 684 --payment-terms-background-color: rgb(17 239 214); 685 } 686 687 688 .color-scheme-4 { 689 --color-background: 39,29,98; 690 691 --gradient-background: #271d62; 692 693 694 695 696 --color-foreground: 255,255,255; 697 --color-background-contrast: 47,35,118; 698 --color-shadow: 39,29,98; 699 --color-button: 255,182,0; 700 --color-button-text: 255,255,255; 701 --color-secondary-button: 39,29,98; 702 --color-secondary-button-text: 255,255,255; 703 --color-link: 255,255,255; 704 --color-badge-foreground: 255,255,255; 705 --color-badge-background: 39,29,98; 706 --color-badge-border: 255,255,255; 707 --payment-terms-background-color: rgb(39 29 98); 708 } 709 710 711 .color-scheme-5 { 712 --color-background: 239,241,253; 713 714 --gradient-background: #eff1fd; 715 716 717 718 719 --color-foreground: 39,29,98; 720 --color-background-contrast: 126,142,239; 721 --color-shadow: 39,29,98; 722 --color-button: 17,239,214; 723 --color-button-text: 255,255,255; 724 --color-secondary-button: 239,241,253; 725 --color-secondary-button-text: 255,255,255; 726 --color-link: 255,255,255; 727 --color-badge-foreground: 39,29,98; 728 --color-badge-background: 239,241,253; 729 --color-badge-border: 39,29,98; 730 --payment-terms-background-color: rgb(239 241 253); 731 } 732 733 734 .color-scheme-7d63ddd2-a163-4a64-933e-98b6d2a3a767 { 735 --color-background: 255,255,255; 736 737 --gradient-background: #ffffff; 738 739 740 741 742 --color-foreground: 39,29,98; 743 --color-background-contrast: 191,191,191; 744 --color-shadow: 39,29,98; 745 --color-button: 17,239,214; 746 --color-button-text: 255,255,255; 747 --color-secondary-button: 255,255,255; 748 --color-secondary-button-text: 17,239,214; 749 --color-link: 17,239,214; 750 --color-badge-foreground: 39,29,98; 751 --color-badge-background: 255,255,255; 752 --color-badge-border: 39,29,98; 753 --payment-terms-background-color: rgb(255 255 255); 754 } 755 756 757 .color-scheme-8c7fa919-021c-4331-91fd-07cc703971ae { 758 --color-background: 17,239,214; 759 760 --gradient-background: #11efd6; 761 762 763 764 765 --color-foreground: 255,255,255; 766 --color-background-contrast: 8,120,108; 767 --color-shadow: 39,29,98; 768 --color-button: 255,182,0; 769 --color-button-text: 255,182,0; 770 --color-secondary-button: 17,239,214; 771 --color-secondary-button-text: 255,182,0; 772 --color-link: 255,182,0; 773 --color-badge-foreground: 255,255,255; 774 --color-badge-background: 17,239,214; 775 --color-badge-border: 255,255,255; 776 --payment-terms-background-color: rgb(17 239 214); 777 } 778 779 780 .color-scheme-39e54bf2-8e08-472b-9cf4-d057e89900fb { 781 --color-background: 208,213,253; 782 783 --gradient-background: #d0d5fd; 784 785 786 787 788 --color-foreground: 39,29,98; 789 --color-background-contrast: 86,104,248; 790 --color-shadow: 39,29,98; 791 --color-button: 255,182,0; 792 --color-button-text: 255,255,255; 793 --color-secondary-button: 208,213,253; 794 --color-secondary-button-text: 255,182,0; 795 --color-link: 255,182,0; 796 --color-badge-foreground: 39,29,98; 797 --color-badge-background: 208,213,253; 798 --color-badge-border: 39,29,98; 799 --payment-terms-background-color: rgb(208 213 253); 800 } 801 802 803 body, .color-scheme-1, .color-scheme-2, .color-scheme-3, .color-scheme-4, .color-scheme-5, .color-scheme-7d63ddd2-a163-4a64-933e-98b6d2a3a767, .color-scheme-8c7fa919-021c-4331-91fd-07cc703971ae, .color-scheme-39e54bf2-8e08-472b-9cf4-d057e89900fb { 804 color: rgba(var(--color-foreground), 0.75); 805 background-color: rgb(var(--color-background)); 806 } 807 808 :root { 809 --font-body-family: Assistant, sans-serif; 810 --font-body-style: normal; 811 --font-body-weight: 400; 812 --font-body-weight-bold: 700; 813 814 --font-heading-family: Assistant, sans-serif; 815 --font-heading-style: normal; 816 --font-heading-weight: 400; 817 818 --font-body-scale: 1.2; 819 --font-heading-scale: 1.0; 820 821 --media-padding: px; 822 --media-border-opacity: 0.0; 823 --media-border-width: 0px; 824 --media-radius: 30px;
825 --media-shadow-opacity: 0.0; 826 --media-shadow-horizontal-offset: 2px; 827 --media-shadow-vertical-offset: 4px; 828 --media-shadow-blur-radius: 0px; 829 --media-shadow-visible: 0; 830 831 --page-width: 120rem; 832 --page-width-margin: 0rem; 833 834 --product-card-image-padding: 0.0rem; 835 --product-card-corner-radius: 4.0rem; 836 --product-card-text-alignment: center; 837 --product-card-border-width: 0.0rem; 838 --product-card-border-opacity: 0.1; 839 --product-card-shadow-opacity: 0.2; 840 --product-card-shadow-visible: 1; 841 --product-card-shadow-horizontal-offset: 0.2rem; 842 --product-card-shadow-vertical-offset: 0.4rem; 843 --product-card-shadow-blur-radius: 0.0rem; 844 845 --collection-card-image-padding: 0.0rem; 846 --collection-card-corner-radius: 4.0rem; 847 --collection-card-text-alignment: center; 848 --collection-card-border-width: 0.0rem; 849 --collection-card-border-opacity: 0.1; 850 --collection-card-shadow-opacity: 0.2; 851 --collection-card-shadow-visible: 1; 852 --collection-card-shadow-horizontal-offset: 0.2rem; 853 --collection-card-shadow-vertical-offset: 0.4rem; 854 --collection-card-shadow-blur-radius: 0.0rem; 855 856 --blog-card-image-padding: 0.0rem; 857 --blog-card-corner-radius: 4.0rem; 858 --blog-card-text-alignment: center; 859 --blog-card-border-width: 0.0rem; 860 --blog-card-border-opacity: 0.1; 861 --blog-card-shadow-opacity: 0.0; 862 --blog-card-shadow-visible: 0; 863 --blog-card-shadow-horizontal-offset: 0.0rem; 864 --blog-card-shadow-vertical-offset: 0.4rem; 865 --blog-card-shadow-blur-radius: 0.5rem; 866 867 --badge-corner-radius: 4.0rem; 868 869 --popup-border-width: 2px; 870 --popup-border-opacity: 0.1; 871 --popup-corner-radius: 20px; 872 --popup-shadow-opacity: 0.05; 873 --popup-shadow-horizontal-offset: 0px; 874 --popup-shadow-vertical-offset: 4px; 875 --popup-shadow-blur-radius: 5px; 876 877 --drawer-border-width: 2px; 878 --drawer-border-opacity: 0.1; 879 --drawer-shadow-opacity: 0.2; 880 --drawer-shadow-horizontal-offset: 2px; 881 --drawer-shadow-vertical-offset: 4px; 882 --drawer-shadow-blur-radius: 0px; 883 884 --spacing-sections-desktop: 0px; 885 --spacing-sections-mobile: 0px; 886 887 --grid-desktop-vertical-spacing: 40px; 888 --grid-desktop-horizontal-spacing: 20px; 889 --grid-mobile-vertical-spacing: 20px; 890 --grid-mobile-horizontal-spacing: 10px; 891 892 --text-boxes-border-opacity: 0.0; 893 --text-boxes-border-width: 0px; 894 --text-boxes-radius: 40px; 895 --text-boxes-shadow-opacity: 0.0; 896 --text-boxes-shadow-visible: 0; 897 --text-boxes-shadow-horizontal-offset: 0px; 898 --text-boxes-shadow-vertical-offset: 4px; 899 --text-boxes-shadow-blur-radius: 0px; 900 901 --buttons-radius: 40px; 902 --buttons-radius-outset: 42px; 903 --buttons-border-width: 2px; 904 --buttons-border-opacity: 1.0; 905 --buttons-shadow-opacity: 0.2; 906 --buttons-shadow-visible: 1; 907 --buttons-shadow-horizontal-offset: 2px; 908 --buttons-shadow-vertical-offset: 4px; 909 --buttons-shadow-blur-radius: 0px; 910 --buttons-border-offset: 0.3px; 911 912 --inputs-radius: 40px; 913 --inputs-border-width: 2px; 914 --inputs-border-opacity: 1.0; 915 --inputs-shadow-opacity: 0.0; 916 --inputs-shadow-horizontal-offset: 2px; 917 --inputs-margin-offset: 0px; 918 --inputs-shadow-vertical-offset: 4px; 919 --inputs-shadow-blur-radius: 0px; 920 --inputs-radius-outset: 42px; 921 922 --variant-pills-radius: 40px; 923 --variant-pills-border-width: 2px; 924 --variant-pills-border-opacity: 1.0; 925 --variant-pills-shadow-opacity: 0.0; 926 --variant-pills-shadow-horizontal-offset: 0px; 927 --variant-pills-shadow-vertical-offset: 4px; 928 --variant-pills-shadow-blur-radius: 5px; 929 } 930 931 *, 932 *::before, 933 *::after { 934 box-sizing: inherit; 935 } 936 937 html { 938 box-sizing: border-box; 939 font-size: calc(var(--font-body-scale) * 62.5%); 940 height: 100%; 941 } 942 943 body { 944 display: grid; 945 grid-template-rows: auto auto 1fr auto; 946 grid-template-columns: 100%; 947 min-height: 100%; 948 margin: 0; 949 font-size: 1.5rem; 950 letter-spacing: 0.06rem; 951 line-height: calc(1 + 0.8 / var(--font-body-scale)); 952 font-family: var(--font-body-family); 953 font-style: var(--font-body-style); 954 font-weight: var(--font-body-weight); 955 } 956 957 @media screen and (min-width: 750px) { 958 body { 959 font-size: 1.6rem; 960 } 961 } 962 </style> 963 964 <link href="//granrondo.cc/cdn/shop/t/1/assets/base.css?v=159796337528943292111761599533" rel="stylesheet" type="text/css" media="all" /> 965 <link rel="stylesheet" href="//granrondo.cc/cdn/shop/t/1/assets/component-cart-items.css?v=123238115697927560811737013876" media="print" onload="this.media='all'"> 966 <link rel="preload" as="font" href="//granrondo.cc/cdn/fonts/assistant/assistant_n4.9120912a469cad1cc292572851508ca49d12e768.woff2" type="font/woff2" crossorigin> 967 968 969 <link rel="preload" as="font" href="//granrondo.cc/cdn/fonts/assistant/assistant_n4.9120912a469cad1cc292572851508ca49d12e768.woff2" type="font/woff2" crossorigin> 970 971<link href="//granrondo.cc/cdn/shop/t/1/assets/component-localization-form.css?v=170315343355214948141737013876" rel="stylesheet" type="text/css" media="all" /> 972
972<script src="//granrondo.cc/cdn/shop/t/1/assets/localization-form.js?v=144176611646395275351737013877" defer="defer"></script>
972<script> 973 if (Shopify.designMode) { 974 document.documentElement.classList.add('shopify-design-mode'); 975 } 976 </script>
976 977 <!-- BEGIN app block: shopify://apps/xo-insert-code/blocks/insert-code-header/72017b12-3679-442e-b23c-5c62460717f5 --><!-- XO-InsertCode Header --> 978 <meta name="viewport" content="width=device-width, 979initial-scale=1.0, 980maximum-scale=1.0, 981user-scalable=no"> 982 983<!-- atleta -->
984<script type="text/javascript"> 985 !function(){var e=document.getElementsByTagName("script")[0],t=document.createElement("script");t.src="https://cdn.atleta.cc/embed/widget.js";var n=document.querySelector("[nonce]");n&&t.setAttribute("nonce",n.nonce||n.getAttribute("nonce")),e.parentNode.insertBefore(t,e)}(); 986</script>
986 987 988<!-- Nodig voor anchor links -->
989<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
vendor: 1 bytes, line 989
989
990<script src="https://unpkg.com/smoothscroll-polyfill/dist/smoothscroll.min.js"></script>
vendor: 1 bytes, line 990
990
991<script src="https://unpkg.com/smoothscroll-anchor-polyfill"></script>
991 992 993<link rel="preconnect" href="https://fonts.googleapis.com"> 994<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 995<link href="https://fonts.googleapis.com/css2?family=Rum+Raisin&display=swap" rel="stylesheet"> 996
997<script> 998 document.addEventListener("DOMContentLoaded", function () { 999 // Zoek alle menu-links (kun je eventueel specifieker maken met nav selector) 1000 document.querySelectorAll('a[href*=".com"]').forEach(function (link) { 1001 // Alleen toepassen op externe links (die niet naar je eigen domein gaan) 1002 if (!link.href.includes(window.location.hostname)) { 1003 link.setAttribute("target", "_blank"); 1004 link.setAttribute("rel", "noopener"); 1005 } 1006 }); 1007 }); 1008</script>
1008 1009
1010<script> 1011document.addEventListener('DOMContentLoaded', function() { 1012 // Functie die alle teksten omzet naar vlaggetjes 1013 function vervangDoorVlaggen() { 1014 // 1. Knoppen in het menu (zowel desktop als mobiel) 1015 const buttonSpans = document.querySelectorAll('button.localization-selector span'); 1016 buttonSpans.forEach(function(span) { 1017 if (span.textContent.includes('Nederlands')) { 1018 span.textContent = 'ð³ð± NL'; 1019 } else if (span.textContent.includes('English')) { 1020 span.textContent = 'ð¬ð§ EN'; 1021 } 1022 }); 1023 1024 // 2. Uitklaplijsten 1025 const listSpans = document.querySelectorAll('.disclosure__link span:last-child'); 1026 listSpans.forEach(function(span) { 1027 if (span.textContent.includes('Nederlands')) { 1028 span.textContent = 'ð³ð± Nederlands'; 1029 } else if (span.textContent.includes('English')) { 1030 span.textContent = 'ð¬ð§ English'; 1031 } 1032 }); 1033 } 1034 1035 // Eerste keer uitvoeren direct nadat de pagina klaar is 1036 vervangDoorVlaggen(); 1037 1038 // Stel de waakhond in op alle taal-formulieren 1039 const forms = document.querySelectorAll('.localization-form'); 1040 1041 if (forms.length > 0) { 1042 const observer = new MutationObserver(function() { 1043 // Pauzeer waakhond even om te voorkomen dat hij vastloopt 1044 observer.disconnect(); 1045 vervangDoorVlaggen(); 1046 1047 // Zet waakhond weer aan voor elk formulier 1048 forms.forEach(function(form) { 1049 observer.observe(form, { childList: true, subtree: true, characterData: true }); 1050 }); 1051 }); 1052 1053 // Start de waakhond voor elk gevonden formulier 1054 forms.forEach(function(form) { 1055 observer.observe(form, { childList: true, subtree: true, characterData: true }); 1056 }); 1057 } 1058}); 1059</script>
1059 1060 1061 1062<style> 1063 :root { 1064 --color-lighter: #EFF1FD; 1065 --color-light: #D0D5FD; 1066 --color-brand-light: #B5FAF2; 1067 --color-brand: #11EFD6; 1068 --color-brand-50: #11EFD690; 1069 --color-brand-dark: #11EFD690; 1070 --color-link: #0CA694; 1071 --color-action: #FFB600; 1072 --color-dark: #271D62; 1073 --color-gravel: #EDE4BB; 1074 --color-white: #FFFFFF; 1075 1076 --color-white-rgb: 255, 255, 255; 1077 --color-action-rgb: 255, 182, 0; 1078 --color-light-rgb: 208, 213, 253; 1079} 1080account-icon, 1081a.header__icon.header__icon--account, 1082.header--mobile-center .header__icon--search { 1083 display: none!important; 1084} 1085main#MainContent { 1086 min-height: 50vh; 1087} 1088 1089.menu-drawer__localization .list-social.list-unstyled, 1090.menu-drawer__localization.header-localization localization-form:first-child, 1091.skip-to-content-link { 1092 display: none !important; 1093} 1094/* ---------------------------------------- 1095 Fonts 1096-----------------------------------------*/ 1097@font-face { 1098 font-family: "ashemore"; 1099 src: url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_regular.ttf?v=1739145129") format("truetype"), 1100 url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_regular.woff?v=1739145017") format("woff"); 1101 font-style: normal; 1102 font-weight: 400; 1103} 1104 1105@font-face { 1106 font-family: "ashemore"; 1107 src: url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_regular_italic.ttf?v=1739145129") format("truetype"), 1108 url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_regular_italic.woff?v=1739145018") format("woff"); 1109 font-style: italic; 1110 font-weight: 400; 1111} 1112 1113@font-face { 1114 font-family: "ashemore"; 1115 src: url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_medium.ttf?v=1739145128") format("truetype"), 1116 url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_medium.woff?v=1739145018") format("woff"); 1117 font-style: normal; 1118 font-weight: 600; 1119} 1120 1121@font-face { 1122 font-family: "ashemore"; 1123 src: url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_medium_italic.ttf?v=1739145129") format("truetype"), 1124 url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/ashemore_cond_medium.woff?v=1739145018") format("woff"); 1125 font-style: italic; 1126 font-weight: 600; 1127} 1128 1129/* ---------------------------------------- 1130 Base 1131-----------------------------------------*/ 1132html { scroll-behavior: smooth; } 1133 1134body { 1135 font-family: "ashemore" !important; 1136 color: rgba(var(--color-foreground), 1); 1137 letter-spacing: 0; 1138} 1139 1140h1, .h1, 1141h2, .h2, 1142h3, .h3, 1143h4, .h4, 1144h5, .h5, 1145h6, .h6, 1146.sdd-download-product, 1147.sdd-download-file { 1148 letter-spacing: 0.05em !important; 1149 font-weight: 400; 1150 text-transform: uppercase; 1151 font-family: "rum raisin" !important; 1152} 1153 1154h1 { 1155 margin: auto !important; 1156 font-size: 3.8rem; 1157} 1158h2 { 1159 font-size: 2.7rem; 1160 margin-bottom: 1rem; 1161} 1162h2 ~ h2{ 1163 margin-top:0rem!important; 1164} 1165h1 ~ h3 { 1166 font-size: 3rem; 1167 color: var(--color-brand); 1168} 1169@media screen and (max-width: 749px) { 1170 h1 { font-size: 6rem; } 1171 h1 ~ h3 { font-size: 2.2rem; } 1172} 1173h2 ~ h2{
1174 margin-top:0rem!important; 1175} 1176 1177h1 ~ .metafield-rich_text_field em, 1178.card__content .metafield-rich_text_field em { 1179 font-style: normal !important; 1180 text-decoration: none !important; 1181} 1182h1 ~ .metafield-rich_text_field p, 1183.card__content .metafield-rich_text_field p { 1184 font-family: "rum raisin" !important; 1185 text-transform: uppercase; 1186 white-space: nowrap; 1187 display: inline-block; 1188 padding: 0.2rem 1.5rem; 1189 margin-left: 0.1rem; 1190 margin-right: 0.1rem; 1191 border-radius: 3rem; 1192 border: 3px solid var(--color-lighter); 1193 background: var(--color-lighter); 1194 font-style: normal !important; 1195 text-decoration: none !important; 1196 font-size: 1.4rem; 1197 line-height: 2.4rem; 1198 letter-spacing: normal !important; 1199} 1200 1201h1.gravel ~ .metafield-rich_text_field p, 1202h1 ~ .metafield-rich_text_field ~ .metafield-rich_text_field p, 1203.card__content .metafield-rich_text_field ~ .metafield-rich_text_field p { 1204 border: 3px solid var(--color-brand-light); 1205 background: var(--color-brand-light); 1206} 1207 1208h1 ~ .metafield-rich_text_field p strong, .card__content .metafield-rich_text_field p strong { 1209font-size: 20px; 1210 line-height: .5; 1211} 1212 1213 1214.color-scheme-3 h1 ~ .metafield-rich_text_field p{ 1215 border: 3px solid var(--color-white); 1216 background-color: rgba(var(--color-white-rgb), 0.5); 1217} 1218 1219.multicolumn .title { 1220 margin: auto!important; 1221} 1222.collection-hero h1 { text-align: center; } 1223 1224.subtitle { color: rgba(var(--color-foreground),1) !important; } 1225 1226p + h1, p + .h1, 1227p + h2, p + .h2, 1228p + h3, p + .h3 { 1229 margin-top: 4rem; 1230 margin-bottom: 0 !important; 1231 padding-bottom: 0 !important; 1232} 1233 1234p + h4, p + .h4, 1235p + h5, p + .h5 { 1236 margin-top: 3rem; 1237 margin-bottom: 0 !important; 1238 padding-bottom: 0 !important; 1239} 1240 1241h4 + .metafield-rich_text_field { padding-top: .5rem !important; } 1242 1243.metafield-rich_text_field ~ .metafield-rich_text_field { padding-top: 2.5rem !important; } 1244 1245.card__content .metafield-rich_text_field ~ .metafield-rich_text_field, 1246h1 ~ .metafield-rich_text_field ~ .metafield-rich_text_field, 1247h2 ~ .metafield-rich_text_field ~ .metafield-rich_text_field { 1248 padding-top: 0 !important; 1249 margin-top: -1rem !important; 1250} 1251 1252.metafield-rich_text_field p ~ p { margin-top: 1rem !important; } 1253.image-with-text__text p { margin-bottom: 0 !important; } 1254 1255h5, .h5 { font-size: 2.2rem; } 1256h6, .h6 { font-size: 1.5rem; color: var(--color-dark); } 1257 1258.product__title h1 { font-size: 3.8rem !important; } 1259 1260.banner__text.rte.caption-with-letter-spacing p { 1261 font-size: 2.2rem !important; 1262 font-family: "rum raisin" !important; 1263} 1264 1265.link, .customer a { 1266 text-transform: uppercase; 1267 font-family: "rum raisin"; 1268 font-size: 1.5rem; 1269 letter-spacing: 0.1em; 1270} 1271 1272a.button, 1273button { 1274 letter-spacing: 0.1em; 1275 text-transform: uppercase; 1276 font-family: "rum raisin" !important; 1277 font-size: 1.8rem !important; 1278} 1279 1280a.btn.btn-primary.btn-block.button.button--primary { 1281 max-width: 600px; 1282 padding: 2rem; 1283} 1284 1285.halloffame a:not(.button), 1286p a { 1287 text-decoration: none; 1288 //border-bottom: dotted 1px; 1289 color: var(--color-link)!important; 1290background: var(--color-brand-light); 1291} 1292 1293.rte a { 1294 text-decoration: underline; 1295 text-decoration-style: dotted; 1296 text-decoration-color: var(--color-dark); 1297} 1298.rte h3 a { 1299 position: relative; 1300 text-decoration: none; 1301 background-color: var(--color-brand); 1302 color: var(--color-white); 1303 padding: 0 0.25em; 1304 box-decoration-break: clone; 1305 -webkit-box-decoration-break: clone; 1306} 1307 1308.rte h3 a:hover { 1309 color: var(--color-white); 1310 text-decoration: none; 1311 position: relative; 1312 background-color: var(--color-action); 1313 } 1314 1315.rte h4 a, 1316.rte h4 a:hover { 1317 color: var(--color-dark); 1318 text-decoration: underline; 1319 text-decoration-style: dotted; 1320 text-decoration-color: var(--color-dark); 1321 position: relative; 1322} 1323 1324 1325 1326a[target="_blank"]::after { 1327 position: relative; 1328 display: inline; 1329 content: " â"; 1330} 1331 1332a.button[href*="#"]::after { 1333 position: relative; 1334 display: inline; 1335 margin-left: 0.2rem; 1336 content: "â£"; 1337} 1338a.button[href*="#booking"]::after { 1339 position: relative; 1340 display: inline; 1341 margin-left: 0.2rem; 1342 content: "â"; 1343} 1344.rte ul, .rte ol { 1345 list-style-position: outside!important; 1346 padding-left: 2rem; 1347} 1348 1349.rte ul, .rte ol { 1350 list-style-position: inside !important; 1351} 1352 1353/* Icons nav */ 1354nav.icons { 1355 display: flex; 1356 width: 150px; 1357 justify-content: space-between; 1358} 1359nav.icons a[target="_blank"]::after {
1360 content: ""; 1361 text-decoration: none; 1362 border-bottom: 0 !important; 1363} 1364nav.icons a { border-bottom: none !important; } 1365 1366/* Verberg specifieke collection-list item */ 1367.collection-list .collection-list__item:has(a[href*="/collections/inchecken"]) { 1368 display: none; 1369} 1370 1371/* Color schemes inherit body color already */ 1372 1373/* Header */ 1374.header-wrapper--border-bottom { border: 0 !important; } 1375 1376 summary.list-menu__item { 1377 padding-right: 2.7rem; 1378 } 1379.list-menu__item { 1380 margin-right: 1.5rem; 1381 } 1382/* Desktop nav beperken (li 1,8,9 zichtbaar) */ 1383@media screen and (min-width: 990px) { 1384 nav > .list-menu > li:not(:nth-child(1)):not(:nth-child(2)):not(:nth-child(3)):not(:nth-child(4)) { 1385 display: none; 1386 } 1387} 1388.menu-drawer__utility-links { 1389} 1390 1391 1392.list-menu--disclosure { 1393 width: 25rem!important; 1394} 1395.header__menu-item .icon-caret { 1396 right: 1.3rem; 1397} 1398 1399@media screen and (min-width: 750px) { 1400.header__menu-item { 1401 color: rgba(var(--color-foreground),1); 1402font-size:1.9rem !important; 1403} 1404.header-localization:not(.menu-drawer__localization), 1405.header>.header__search .header__icon--summary { 1406 scale: 1.2; 1407} 1408} 1409 1410section#shopify-section-sections--24695135142262__custom_liquid_W9xJgX { 1411 align-content: flex-end; 1412} 1413 1414/* Titles / badges */ 1415.accordion__title { text-align: center !important; flex: auto; } 1416.product__tax.caption.rte, 1417.price .badge.price__badge-sale { display: none; } 1418 1419.accordion__content {text-align: center !important; flex: auto;} 1420 1421.collapsible-row-layout .accordion .accordion__content { 1422 padding-top: 1.5rem!important; 1423} 1424.accordion__title { 1425 max-width: 100%!important; 1426 padding-left: 1.5rem !important; 1427 padding-right: 1.5rem !important; 1428} 1429.collapsible-content summary:hover { 1430 background: transparent !important; 1431} 1432.collapsible-content summary[aria-expanded="true"]{ 1433 border-bottom: 2px dashed var(--color-light); 1434} 1435 1436.product .badge.price__badge-sale { 1437 font-size: 1.4rem; 1438 font-weight: 600; 1439 text-transform: uppercase; 1440 font-family: "rum raisin"; 1441} 1442 1443.product__text.caption-with-letter-spacing { 1444 opacity: .8; 1445 font-size: 1.2rem; 1446 font-weight: 600; 1447 text-transform: uppercase; 1448 font-family: "rum raisin"; 1449 line-height: 1.2; 1450} 1451 1452.price__badge-sale { 1453 padding: 1rem 1.8rem .8rem 1.8rem; 1454 margin: 0 !important; 1455} 1456 1457.price { 1458 text-align: center; 1459 background: rgba(var(--color-white-rgb), .8); 1460 border-radius: 40px; 1461 padding: .5rem .9rem .6rem 1.7rem; 1462 display: inline; 1463} 1464 1465.product .price-item--sale, 1466.product .price-item--regular { 1467 color: var(--color-action); 1468 font-size: 1.7rem; 1469 font-weight: 600; 1470 letter-spacing: 0; 1471} 1472 1473/* Thumbnails */ 1474.product .thumbnail { border-radius: 7%; } 1475.product .thumbnail[aria-current] { box-shadow: 0 0 0 0.2rem var(--color-brand); } 1476.quantity { margin: auto; } 1477 1478/* Features */ 1479div#features { margin-top: 2.5rem !important; text-align: center !important; } 1480 1481@media screen and (max-width: 749px) { 1482 div#features p { padding-left: 0.5rem !important; font-size: 12px !important; } 1483} 1484 1485/* Hero / iframe masker */ 1486.button-wrapper { 1487 height: initial; 1488 position: absolute; 1489 top: 50%; 1490 left: 50%; 1491 transform: translate(-50%, -50%); 1492 z-index: 2; 1493} 1494 1495#shopify-section-template--26670909456758__custom_liquid_dDXNYE { 1496 margin-top: -15rem!important; 1497} 1498#shopify-section-template--25520115122550__custom_liquid_UH39KY, 1499#shopify-section-template--26670909456758__custom_liquid_dDXNYE { 1500 height: 120rem; 1501 position: relative; 1502 overflow-x: clip; 1503 clip-path: ellipse(70% 50% at 50% 50%) !important; 1504} 1505#shopify-section-template--26670909456758__custom_liquid_dDXNYE + section { margin-top: -20rem;} 1506#shopify-section-template--26670909456758__custom_liquid_dDXNYE + section > * { padding-top: 20rem;} 1507 1508@media screen and (max-width: 749px) { 1509 #shopify-section-template--25520115122550__custom_liquid_UH39KY, 1510 #shopify-section-template--26670909456758__custom_liquid_dDXNYE { height: 40rem; margin-top: 4px; } 1511} 1512@media screen and (min-width: 750px) { 1513 #shopify-section-template--25520115122550__custom_liquid_UH39KY, 1514 #shopify-section-template--26670909456758__custom_liquid_dDXNYE { margin-top: 8px; } 1515} 1516 1517#shopify-section-template--25520115122550__custom_liquid_UH39KY iframe, 1518 #shopify-section-template--26670909456758__custom_liquid_dDXNYE iframe { 1519 width: 100%; 1520 padding-top: 8px; 1521 height: calc(120rem - 8px); 1522 display: block; 1523} 1524 1525@media screen and (max-width: 749px) { 1526 #shopify-section-template--25520115122550__custom_liquid_UH39KY iframe, 1527 #shopify-section-template--26670909456758__custom_liquid_dDXNYE iframe { 1528 padding-top: 8px; 1529 margin-top: 0; 1530 height: calc(43rem - 8px); 1531 } 1532} 1533 1534.section-divider-mask { 1535 display: flex; 1536 position: relative; 1537 max-height: 8vw; 1538 overflow: hidden !important; 1539} 1540@media screen and (max-width: 749px) { 1541 .section-divider-mask { max-height: 20vw !important; } 1542} 1543 1544.section-divider { width: 100%; height: 100%; } 1545.section-divider, 1546section[id*="image_banner"] { 1547 position: relative; 1548 overflow-x: clip; 1549} 1550 1551.section-divider::after{ 1552 display: inline-block; 1553 position: absolute; 1554 content: " "; 1555 background: transparent; 1556 width: 200%; 1557 left: -50%; 1558 top: 0; 1559 height: 100%; 1560 border-bottom-left-radius: 150% 150%; 1561 border-bottom-right-radius: 150% 150%; 1562 border-top-left-radius: 150% 150%; 1563 border-top-right-radius: 150% 150%; 1564 pointer-events: none; 1565 border: dashed 16px var(--color-white); 1566} 1567#shopify-section-template--25520115122550__custom_liquid_UH39KY::after, 1568 #shopify-section-template--26670909456758__custom_liquid_dDXNYE::after, 1569section[id*="image_banner"]::after { 1570 display: inline-block; 1571 position: absolute; 1572 content: " "; 1573 background: transparent; 1574 width: 140%; 1575 left: -20%; 1576 top: 0; 1577 height: 100%; 1578 border-bottom-left-radius: 150% 150%; 1579 border-bottom-right-radius: 150% 150%; 1580 border-top-left-radius: 150% 150%; 1581 border-top-right-radius: 150% 150%; 1582 pointer-events: none; 1583 border: dashed 16px var(--color-white); 1584} 1585 1586@media screen and (max-width: 749px) { 1587 #shopify-section-template--25520115122550__custom_liquid_UH39KY::after, 1588 #shopify-section-template--26670909456758__custom_liquid_dDXNYE::after, 1589 .section-divider::after, 1590 section[id*="image_banner"]::after { 1591 border-width: 7px; 1592 } 1593} 1594 1595.section-divider .banner__media { 1596 clip-path: ellipse(100% 50% at 50% 50%) !important; 1597 margin-top: 8px; 1598 height: calc(100% - 16px); 1599} 1600section[id*="image_banner"] .banner__media { 1601 clip-path: ellipse(70% 50% at 50% 50%) !important; 1602 margin-top: 8px; 1603 height: calc(100% - 16px); 1604} 1605 1606@media screen and (max-width: 749px) { 1607 .section-divider .banner__media, 1608 section[id*="image_banner"] .banner__media { 1609 margin-top: 4px; 1610 height: calc(100% - 8px); 1611 } 1612} 1613 1614section[id*="image_banner"] .banner::before { 1615 display: block !important; 1616 position: absolute; 1617 content: " "; 1618 height: 100%; 1619 width: 100%; 1620 z-index: -1; 1621 opacity: 1 !important; 1622} 1623 1624/* Banner heights */ 1625@media screen and (min-width: 750px) { 1626 .banner--medium:not(.banner--adapt) { 1627 height: 100px !important; 1628 min-height: 75vw !important; 1629 max-height: 60rem !important; 1630 } 1631} 1632@media screen and (max-width: 749px) { 1633 .banner--medium.banner--mobile-bottom:not(.banner--adapt) .banner__media, 1634 .banner--medium.banner--stacked:not(.banner--mobile-bottom):not(.banner--adapt) > .banner__media { 1635 height: 100vw; 1636 } 1637 .banner__box { 1638 padding-top: 7rem !important; 1639 padding-bottom: 7rem !important; 1640 } 1641} 1642.section-body-last { 1643height:10rem; 1644} 1645@media screen and (min-width: 750px) { 1646.section-body-last { 1647height:15rem; 1648} 1649} 1650@media screen and (min-width: 1500px) { 1651.section-body-last { 1652height:25rem; 1653} 1654} 1655@media screen and (min-width: 2000px) { 1656.section-body-last { 1657height:55rem; 1658} 1659} 1660/* Header cleanup voor specifieke secties */ 1661[class*="wat-zit-er-in-de-box"] header > *:not(.header__heading-link), 1662[class*="preview"] header > *:not(.header__heading-link) { display: none; } 1663 1664/* Cart */ 1665.cart__footer { display: block !important; text-align: center; } 1666.cart__note { top: 0 !important; margin-top: 3rem; margin-bottom: 3rem; } 1667.cart__note.field::after { border-radius: 0 !important; } 1668.cart-item__quantity-wrapper { place-content: flex-end; } 1669.cart-item__details a + div.product-option, 1670.cart-item__final-price.product-option { color: var(--color-action); } 1671.cart-item .discounts__discount, 1672.cart-item .discounts__discount > .icon { opacity: 0.8; } 1673.cart-item__details dl .product-option:not(:first-child) { opacity: 0.5 !important; } 1674 1675@media screen and (max-width: 749px) { 1676 .cart-item__details { grid-column: span 3 !important; } 1677 /* Als je grid-template-columns wilde zetten, doe dat op de grid-container, bv.: */ 1678 /* .cart-items-grid { grid-template-columns: repeat(4, 1fr) !important; } */ 1679} 1680 1681@media screen and (min-width: 750px) { 1682 cart-remove-button .button { 1683 background-color: var(--color-action); 1684 border-radius: 5px; 1685 color: white !important; 1686 } 1687} 1688cart-items.is-empty, 1689cart.is-empty { 1690padding-bottom:100px!important; 1691} 1692cart-items.is-empty h1, 1693cart.is-empty h1 { 1694margin-bottom:2rem!important; 1695} 1696 1697/* Forms / product */ 1698variant-selects, 1699product-form { max-width: 100% !important; overflow: hidden !important; } 1700 1701/* YouTube wrapper */ 1702.youtube-video-wrapper { 1703 max-width: 854px; 1704 margin: 0 auto; 1705 width: 100%; 1706} 1707.youtube-video-container { 1708 position: relative; 1709 padding-bottom: 56.25%; 1710 height: 0; 1711 overflow: hidden; 1712 max-width: 100%; 1713} 1714.youtube-video-container iframe { 1715 position: absolute; 1716 top: 0; left: 0; 1717 width: 100%; height: 100%; 1718} 1719 1720/* Modal (generic) */ 1721.modal-overlay { 1722 position: fixed; 1723 top: 0; left: 0; 1724 z-index: 9999; 1725 display: none; 1726 height: 100% !important; 1727 max-height: 100vh !important; 1728 max-width: 100% !important; 1729 width: 100% !important; 1730 padding: 0 !important; 1731} 1732.modal-overlay-inner { 1733 position: fixed; 1734 overflow: hidden !important; 1735 width: 100%; height: 100%; 1736 top: 0; 1737} 1738.modal-content { 1739 position: relative; 1740 margin-top: -70px; 1741 max-width: 100%; 1742 height: calc(100% + 70px); 1743 padding: 40px; 1744 background: var(--color-white); 1745} 1746.wolfmaps.modal-content { 1747 margin-top: initial !important; 1748 height: 100% !important; 1749} 1750.modal-content iframe { 1751 position: absolute; 1752 overflow: hidden; 1753 height: 100%; width: 100%; 1754 top: 0; left: 0; right: 0; bottom: 0; 1755 background: var(--color-white); 1756} 1757.modal-close { 1758 position: absolute; 1759 height: 40px; width: 40px; 1760 border-radius: 50%; 1761 top: 11px; right: 15px; 1762 font-size: 4rem !important; 1763 line-height: 2rem; 1764 padding-left: 9px; 1765 background: var(--color-white); 1766 color: black; 1767 border: none; 1768 cursor: pointer; 1769 z-index: 10000; 1770} 1771 1772/* Custom modal */ 1773.custom-modal-overlay { 1774 position: fixed; 1775 top: 0; left: 0; 1776 width: 100%; height: 100%; 1777 background: rgba(0,0,0,0.5); 1778 display: none; 1779 align-items: center; 1780 justify-content: center; 1781 z-index: 10000; 1782} 1783.custom-modal { 1784 background: var(--color-white); 1785 padding: 40px 40px 40px; 1786 padding-top: 60px; 1787 width: 100%; 1788 max-width: 550px; 1789 max-height: 90%; 1790 overflow: auto; 1791 border-radius: 8px; 1792 position: relative; 1793 box-shadow: 0 2px 10px rgba(0,0,0,0.3); 1794} 1795@media (max-width: 749px) { 1796 .custom-modal { 1797 max-height: none; 1798 height: 100%; 1799 border-radius: 0; 1800 } 1801} 1802.custom-modal-close { 1803 position: absolute; 1804 top: 10px; right: 10px; 1805 background: transparent; 1806 color: var(--color-brand); 1807 border: none; 1808 font-size: 4rem !important; 1809 line-height: 1; 1810 cursor: pointer; 1811} 1812 1813/* Product form tweaks */ 1814.product__info-container .product-form { margin-top: -2rem !important; } 1815.gpo-helptext, .gpo-ov-helptext { line-height: 1.3 !important; } 1816.gpo-app { margin: 0 !important; } 1817.gpo-group { margin-bottom: 0 !important; } 1818.gpo-element { margin-bottom: 35px !important; } 1819 1820.gpo-group h3 { 1821margin-top:3rem!important; 1822} 1823.gpo-group h3 ~ p:last-child { 1824margin-bottom:3rem!important; 1825} 1826 1827.field__input:focus, 1828.select__select:focus, 1829.customer .field input:focus, 1830.customer select:focus, 1831.localization-form__select:focus, 1832.field__input:focus-visible, 1833.select__select:focus-visible, 1834.customer .field input:focus-visible, 1835.customer select:focus-visible, 1836.localization-form__select:focus-visible, 1837.gpo-group .gpo-element select:hover { 1838 box-shadow: none; 1839 outline: 0; 1840 border: 0 solid var(--color-dark); 1841 background-color: var(--color-light); 1842} 1843.product-form__input--pill input[type=radio] + label:hover { background-color: var(--color-light); } 1844 1845.product-form__input--pill input[type=radio]:disabled+label, .product-form__input--pill input[type=radio].disabled+label { 1846 display: none; 1847} 1848 1849.gpo-input:focus-visible { 1850 box-shadow: none; 1851 outline-offset: 0; 1852 border: 2px solid var(--color-dark); 1853 background: var(--color-white); 1854} 1855.gpo-input-wrap { 1856 max-width: 100%!important; 1857} 1858.gpo-form__group:not(.gpo-group) { 1859 padding: 0!important; 1860} 1861.gpo-group__childs { 1862 margin: 0!important; 1863} 1864.gpo-app { 1865 margin-left: 0!important; 1866 width: 100%!important; 1867} 1868.gpo-choicelist { 1869 margin: auto!important; 1870} 1871.gpo-choicelist input + label:hover:before, 1872.gpo-choicelist input:not(:checked) + label:before { 1873 border: 2px solid var(--color-dark) !important; 1874 box-shadow: none !important; 1875} 1876.gpo-choicelist input:checked + label:before { border: 2px solid var(--color-dark) !important; } 1877 1878.gpo-choicelist input + label:before, 1879.gpo-choicelist.gpo-checkbox input + label:after { left: 5px !important; } 1880.gpo-choicelist input + label { padding-left: 45px !important; } 1881.gpo-choicelist.gpo-checkbox input + label:after { color: var(--color-dark); } 1882.gpo-input-wrap .gpo-input, .gpo-input-wrap .iti { padding: 1rem 2rem !important; } 1883.gpo-swatches.buttons input + label { padding: 1rem 2rem !important; } 1884
1885.gpo-label + .gpo-helptext, 1886.gpo-label { margin-bottom: 10px !important; } 1887 1888.gpo-group .gpo-element select { 1889 -webkit-appearance: none !important; 1890 -moz-appearance: none !important; 1891 appearance: none !important; 1892 padding: 1.5rem 2rem !important; 1893 background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23000000%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C1.414%2C0l5-5a1%2C1%2C1%2C0%2C0-1.414-1.414Z%22%20fill%3D%22%23000000%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E") !important; 1894 background-repeat: no-repeat !important; 1895 background-position: right 17px center !important; 1896 background-size: 0.75em 1.5em !important; 1897} 1898 1899.gpo-choicelist.gpo-checkbox input + label:after { 1900 width: 30px !important; 1901 height: 30px !important; 1902 line-height: 30px !important; 1903 font-size: 24px !important; 1904} 1905.gpo-choicelist input + label:before { width: 30px !important; height: 30px !important; } 1906.gpo-choicelist input + label, .gpo-choicelist input + label span { width: auto !important; } 1907 1908.product-form__input { margin: 0 0 3rem !important; } 1909.product-form__submit { margin-top: 2rem !important; margin-bottom: 1rem !important; } 1910.product-form__submit span::after { display: inline; content: " â"; } 1911.product__info-container .product-form { margin: 0 !important; } 1912 1913.image-with-text__text-item .button, 1914.sdd-download-button { 1915 background-color: var(--color-action) !important; 1916 color: var(--color-white) !important; 1917} 1918.sdd-download-button { 1919 --shadow-horizontal-offset: 2 !important; 1920 --shadow-vertical-offset: 4 !important; 1921 --shadow-blur-radius: 0.2 !important; 1922 --shadow-opacity: 0.2 !important; 1923 --shadow-visible: 1 !important; 1924 --border-offset: 0.3 !important; 1925 --border-opacity: 1 !important; 1926 border-radius: 42px !important; 1927 border-color: var(--color-action) !important; 1928} 1929.sdd-download-warning { display: none !important; } 1930 1931/* FIX: comma + typo */ 1932.sdd-download-product, 1933.sdd-download-file { display: none !important; } 1934 1935.sdd-download-file { 1936 font-size: 3rem !important; 1937 color: var(--color-dark); 1938} 1939 1940/* Typografie-consistentie in inputs/labels */ 1941.gpo-choicelist input + label, 1942.gpo-choicelist input + label span, 1943.gpo-swatches.buttons input + label, 1944.product-form__input--pill input[type=radio] + label, 1945.gpo-swatches { 1946 width: 98%; 1947 font-family: "ashemore" !important; 1948 font-size: 1.5rem !important; 1949 line-height: 1.5 !important; 1950 font-weight: 400 !important; 1951 letter-spacing: .04rem !important; 1952} 1953 1954.gpo-label span.addOn, 1955.gpo-label.required span.label-content::after, 1956.customer .field input, 1957.customer select, 1958.field__input, 1959.select__select { 1960 font-family: "ashemore" !important; 1961 font-size: 1.4rem !important; 1962 line-height: 1.5 !important; 1963 font-weight: 600 !important; 1964 letter-spacing: .04rem !important; 1965 text-align: center; 1966} 1967 1968.gpo-label, 1969.gpo-label span.label-content, 1970.form__label { 1971 font-family: "rum raisin" !important; 1972 text-transform: uppercase; 1973 font-size: 1.6rem !important; 1974 line-height: 1.5 !important; 1975 font-weight: 600 !important; 1976 letter-spacing: .04rem !important; 1977 text-align: center; 1978 color: rgb(var(--color-foreground))!important; 1979} 1980.gpo-label, 1981.gpo-paragraph { 1982 color: rgb(var(--color-foreground)); 1983} 1984 1985 1986.product-form__input--pill input[type=radio] + label { padding: 1rem !important; } 1987.gpo-input-wrap { max-width: 98%; } 1988 1989div#features p:first-child { margin-bottom: 3rem !important; } 1990 1991/* Newsletter footer compositing */ 1992#shopify-section-sections--24695135142262__newsletter_wfTdJQ { 1993 margin-top: -20vw; 1994 position: relative; 1995 overflow-x: clip; 1996 background: linear-gradient(to bottom, transparent 0%, transparent 50%, var(--color-dark) 50%, var(--color-dark) 100%); 1997 padding-bottom: 30rem; 1998} 1999@media screen and (min-width: 750px) { 2000 #shopify-section-sections--24695135142262__newsletter_wfTdJQ { padding-top: 5rem; margin-top: -16vw; } 2001} 2002#shopify-section-sections--24695135142262__newsletter_wfTdJQ .color-scheme-4.gradient { background: transparent !important; } 2003 2004#shopify-section-sections--24695135142262__newsletter_wfTdJQ::before { 2005 content: ""; 2006 position: absolute; 2007 inset: 0; 2008 z-index: 1; 2009 height: calc(100% - 8px); 2010 top: 4px; 2011 background: 2012 linear-gradient(rgba(var(--color-light-rgb), 0.2), rgba(var(--color-light-rgb), 0.2)), 2013 url("https://cdn.shopify.com/s/files/1/0899/1277/0934/files/footer.jpg?v=1757616995") right/cover no-repeat; 2014 clip-path: ellipse(70% 50% at 50% 50%); 2015} 2016@media (max-width: 749px) { 2017 #shopify-section-sections--24695135142262__newsletter_wfTdJQ::before { 2018 width: 180%; 2019 left: -40%; 2020 } 2021} 2022#shopify-section-sections--24695135142262__newsletter_wfTdJQ::after {
2023 content: ""; 2024 position: absolute; 2025 top: 0; left: -20%; 2026 width: 140%; height: 100%; 2027 z-index: 2; 2028 pointer-events: none; 2029 background: transparent; 2030 border-top-left-radius: 150% 150%; 2031 border-top-right-radius: 150% 150%; 2032 border-bottom-left-radius: 150% 150%; 2033 border-bottom-right-radius: 150% 150%; 2034 border: dashed 16px var(--color-white); 2035} 2036@media (max-width: 749px) { 2037 #shopify-section-sections--24695135142262__newsletter_wfTdJQ::after { 2038 width: 250%; left: -75%; border-width: 7px; 2039 } 2040} 2041#shopify-section-sections--24695135142262__newsletter_wfTdJQ .newsletter__wrapper { 2042 position: relative; 2043 z-index: 2; 2044 background: transparent !important; 2045 margin-top: 8px; 2046} 2047@media (max-width: 749px) { 2048 #shopify-section-sections--24695135142262__newsletter_wfTdJQ .newsletter__wrapper { margin-top: 4px; } 2049} 2050 2051/* ---------------------------------------- 2052 EVENTLIST â FIXED 2053-----------------------------------------*/ 2054h6.ra-event-date span, 2055.eventlist span { 2056 background-color: var(--color-white); 2057 border-radius: 5rem; 2058 padding: 0 1rem; 2059 margin-bottom: 0.5rem; 2060 display: inline-block; 2061} 2062.eventlist a { 2063 position: relative; /* referentie voor ::before overlay */ 2064 display: inline-block; 2065} 2066.eventlist span ~ a::before { 2067 position: absolute; 2068 display: block; 2069 content: ""; 2070 inset: 0; 2071 background-color: rgba(var(--color-white-rgb), 0.2); 2072 z-index: 1; 2073 pointer-events: none; /* overlay blokkeert geen clicks */ 2074} 2075 2076.eventlist span ~ a{ 2077 z-index: 2; 2078} 2079 2080h6.ra-event-date span.eventgravel, 2081.eventlist span.eventgravel { background-color: var(--color-gravel); } 2082 2083h6.ra-event-date span.eventroadgravel, 2084.eventlist span.eventroadgravel { background-color: var(--color-brand-light); } 2085 2086@media (max-width: 749px) { 2087 .eventlist h4 b { 2088 display: block; 2089 opacity: 0; 2090 line-height: 0; 2091 font-size: 1px; /* unit verplicht */ 2092 } 2093 .eventlist h4 a { 2094 margin-top: 0.5rem; 2095 } 2096} 2097 2098/* ---------------------------------------- 2099Slider 2100-----------------------------------------*/ 2101 2102.slider-button.slider-button--prev::after { 2103content: "â"; 2104color: var(--color-white); 2105margin: auto; 2106position: absolute; 2107padding-left: 3px; 2108} 2109.slider-button.slider-button--next::after { 2110content: "â"; 2111color: var(--color-white); 2112margin: auto; 2113position: absolute; 2114padding-left: 3px; 2115} 2116.slider-buttons { 2117position: absolute; 2118top: 32% !important; 2119align-self: center; 2120justify-content: space-between !important; 2121left: 5%; 2122width: 90%; 2123} 2124@media screen and (max-width: 1689px) { 2125.slider-button { 2126background-color: var(--color-white) !important; 2127border-radius: 50%; 2128opacity: 1 !important; 2129} 2130.slider-counter { display: none !important; } 2131.slider-buttons .svg-wrapper { display: none !important; } 2132} 2133.slider-button { 2134width: 4rem; 2135height: 4rem; 2136max-width: 4rem; 2137max-height: 4rem; 2138line-height: 2.8rem; 2139padding: 0; 2140color: var(--color-white) !important; 2141background: var(--color-brand) !important; 2142opacity: 0.8 !important; 2143} 2144.slider-button .icon { color: var(--color-white) !important; } 2145.slider-button[disabled] { opacity: .2 !important; } 2146.slider-button--prev { margin-left: 1rem; } 2147.slider-button--next { margin-right: 1rem; } 2148slider-component .icon.icon-caret { display: none; } 2149 2150 2151@media screen and (min-width: 1690px) { 2152.slider-buttons {top: 37% !important;} 2153.slider.slider--tablet { 2154position: relative; 2155flex-wrap: inherit; 2156overflow-x: auto; 2157scroll-snap-type: x mandatory; 2158scroll-behavior: smooth; 2159scroll-padding-left: 1.5rem; 2160-webkit-overflow-scrolling: touch; 2161margin-bottom: 1rem; 2162} 2163.slider-button { 2164background-color: var(--color-brand) !important; 2165border-radius: 50%; 2166opacity: 1 !important; 2167transform: scale(2); 2168} 2169.slider-button.slider-button--prev::after, 2170.slider-button.slider-button--next::after { 2171transform: scale(.75); 2172} 2173.slider-counter { display: none !important; } 2174} 2175 2176/* ---------------------------------------- 2177Masonry 2178-----------------------------------------*/ 2179 2180.masonry { 2181column-count: 2; 2182column-gap: 24px; 2183} 2184@media (max-width: 1200px) { .masonry { column-count: 2; } } 2185@media (max-width: 740px) { .masonry { column-count: 1; } } 2186 2187.masonry-item { 2188break-inside: avoid; 2189overflow: hidden; 2190transform: translateZ(0); 2191margin-bottom: 2rem; 2192} 2193 2194.masonry-item a:after { 2195 display: none; 2196} 2197 2198.masonry-item .strava-embed-placeholder, 2199.masonry-item iframe { 2200width: 100% !important; 2201display: block; 2202border: 0; 2203} 2204 2205.masonry-item h2 { 2206background: var(--color-light); 2207border-radius: 5rem; 2208padding:1.5rem; 2209} 2210 2211cart-items h1 { 2212 font-size: 3rem; 2213} 2214@media screen and (min-width: 990px) { 2215cart-items h1 { 2216 font-size: 4rem; 2217} 2218} 2219cart-items th { 2220 font-size: 1.7rem; 2221 font-family: "rum raisin"; 2222} 2223cart-items .title-wrapper-with-link a { 2224 display: none; 2225} 2226cart-items.cart-item__image, 2227cart-items .cart-item__image-container { 2228 border-radius: 10px; 2229} 2230cart-items th:last-child, 2231cart-items th:nth-child(2), 2232cart-items .cart-item__totals { 2233 display: none; 2234} 2235cart-items a[href*="inchecken"] ~ .product-option, 2236.card__content a[href*="inchecken"] ~ .cart-item__final-price { 2237} 2238cart-items a[href*="donatie"] ~ dl { 2239} 2240.cart-items thead th:first-child { 2241 width: 80%; 2242} 2243.cart-items .cart-remove-button .icon-remove { 2244 height: 3rem; 2245 width: 3rem; 2246} 2247.cart .card__badge * { 2248 background-color: #ffb600; 2249 color: white !important; 2250 font-weight: 600; 2251 font-size: 1.9rem; 2252 text-transform: uppercase; 2253 font-family: "acumin_pro"; 2254} 2255.cart .price-item--sale { 2256 color: #ffb600; 2257 font-size: 2rem; 2258 font-weight: 600; 2259 letter-spacing: 0; 2260} 2261.cart .link.product__view-details { 2262 display: none; 2263} 2264.cart .featured-product a { 2265 text-decoration: none; 2266 border-bottom: dotted 1px; 2267 color: #0ca694; 2268} 2269.cart .product-form__input--pill input[type="radio"] + label { 2270 width: initial; 2271 padding: 0.5rem 1.5rem !important; 2272} 2273 2274.cart .form__label { 2275 text-align:left; 2276} 2277 2278.partnerlist { 2279column-count: 2; 2280column-gap: 24px; 2281} 2282@media (max-width: 1200px) { .partnerlist { column-count: 2; } } 2283@media (max-width: 740px) { .partnerlist { column-count: 1; } } 2284 2285.partnerlist-item { 2286display:flex; 2287align-items: center; 2288justify-content: center; 2289margin: 0 0 24px; 2290min-height: 160px; 2291overflow: hidden; 2292} 2293 2294.partnerlist-item a { 2295 text-decoration: none; 2296 border: 0; 2297 padding: 2rem; 2298} 2299 2300.partnerlist-item a:after { 2301 display: none; 2302} 2303.partnerlist-item img { 2304display:block; 2305max-height:200px; 2306max-width:min(100%, 320px); 2307height:auto; 2308width:auto; 2309} 2310 2311.color-scheme-2 .multicolumn-card, 2312.color-scheme-3 .multicolumn-card { 2313background: transparent!important; 2314} 2315.color-scheme-2 .multicolumn-card__info, 2316.color-scheme-3 .multicolumn-card__info { 2317background: var(--color-white)!important; 2318border-radius: var(--text-boxes-radius); 2319} 2320 2321.multicolumn-list__item { 2322margin:auto; 2323} 2324 2325@media screen and (min-width: 1690px) { 2326 .grid--4-col-desktop .grid__item { 2327 width: calc(25% - var(--grid-desktop-horizontal-spacing) * 2 / 4); 2328 max-width: calc(25% - var(--grid-desktop-horizontal-spacing) 4); 2329 } 2330} 2331@media screen and (min-width: 750px) { 2332 .grid__item { 2333 width: calc(33% % - * 3 / 4); 2334 max-width: calc(33% - var(--grid-desktop-horizontal-spacing) / 2); 2335 } 2336} 2337.rich-text__buttons { 2338 display: inline-grid!important; 2339} 2340.rich-text__buttons a + a { 2341 background-color: var(--color-brand); 2342} 2343.rich-text__buttons a + a::after { 2344 display:none!important; 2345} 2346a.button, { 2347 max-width: 40rem; 2348 padding: 1.5rem; 2349} 2350.circles-container { max-width: 900px; margin: 0 auto; position: relative; } 2351.circles-controls-bar { display: flex; flex-direction: column; gap: 40px; margin-bottom: 25px; width: 100%; } 2352.control-row-center { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; width: 100%; position: relative; gap: 15px; } 2353 2354shopify-forms-embed { 2355 background: white; 2356 padding: 2rem; 2357 max-width: 550px; 2358 margin: auto; 2359 text-align: left; 2360 border-radius: 2rem; 2361 2362@media screen and (min-width: 750px) { 2363 padding: 3rem; 2364 border-radius: 3rem; 2365} 2366} 2367</style> 2368 2369 2370<!-- End: XO-InsertCode Header --> 2371 2372 2373<!-- END app block --><!-- BEGIN app block: shopify://apps/terms-checkbox/blocks/app-embed/17661ca5-aeea-41b9-8091-d8f7233e8b22 --> 2374
2375<script> 2376 window.roarJs = window.roarJs || {}; 2377 2378 window.roarJs.LegalConfig = { 2379 metafields: { 2380 shop: "khdz0c-aq.myshopify.com", 2381 settings: 2382 2383 {"enabled":"1","param":{"message":"Ik heb de {link} gelezen en ga hiermee akkoord.","error_message":"You must agree to continue","error_display":"before","greeting":{"enabled":"0","message":"Please agree to the T\u0026C before purchasing!","delay":"1"},"link_order":["link"],"links":{"link":{"label":"voorwaarden van GranRondo.cc","target":"_blank","url":"\/terms","policy":"terms-of-service"}},"force_enabled":"0","optional":"0","optional_message_enabled":"0","optional_message_value":"Thank you! The page will be moved to the checkout page.","optional_checkbox_hidden":"0","time_enabled":"1","time_label":"Accepted the terms and conditions ","checkbox":"3"},"popup":{"title":"Terms and Conditions","width":"600","button":"Process to Checkout","icon_color":"#197bbd"},"style":{"checkbox":{"size":"23","color":"#11efd6"},"message":{"font":"Assistant:200,300,regular,500,600,700,800","size":"16","customized":{"enabled":"1","color":"#271d62","accent":"#0ca694","error":"#de3618"},"align":"inherit","padding":{"top":"0","right":"0","bottom":"0","left":"0"}}},"only1":"true","installer":[]} 2384 2385 , 2386 moneyFormat: "${{amount}}" 2387 } 2388 }; 2389</script>
2389 2390
2391<script src="https://cdn.shopify.com/extensions/01a0f919-351b-7219-a335-1d067cc2d4aa/terms-and-conditions-in-cart-14/assets/legal.js" defer></script>
2391 2392 2393 2394<!-- END app block -->
2394<script src="https://cdn.shopify.com/extensions/01a0fdff-2b95-7a42-80bb-495e663795ed/forms-2610/assets/shopify-forms-loader.js" type="text/javascript" defer="defer"></script>
vendor: 1 bytes, line 2394
2394
2395<script src="https://cdn.shopify.com/extensions/01a0f5c2-a34a-7217-a998-4319ae5864cf/globo-product-options-469/assets/gpomain.js" type="text/javascript" defer="defer"></script>
2395 2396<link href="https://cdn.shopify.com/extensions/01a0f919-351b-7219-a335-1d067cc2d4aa/terms-and-conditions-in-cart-14/assets/legal.css" rel="stylesheet" type="text/css" media="all"> 2397<link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
2398<script>(function(){if ("sendBeacon" in navigator && "performance" in window) {try {var session_token_from_headers = performance.getEntriesByType('navigation')[0].serverTiming.find(x => x.name == '_s').description;} catch {var session_token_from_headers = undefined;}var session_cookie_matches = document.cookie.match(/_shopify_s=([^;]*)/);var session_token_from_cookie = session_cookie_matches && session_cookie_matches.length === 2 ? session_cookie_matches[1] : "";var session_token = session_token_from_headers || session_token_from_cookie || "";function handle_abandonment_event(e) {var entries = performance.getEntries().filter(function(entry) {return /monorail-edge.shopifysvc.com/.test(entry.name);});if (!window.abandonment_tracked && entries.length === 0) {window.abandonment_tracked = true;var currentMs = Date.now();var navigation_start = performance.timing.navigationStart;var payload = {shop_id: 89912770934,url: window.location.href,navigation_start,duration: currentMs - navigation_start,session_token,page_type: "collection"};window.navigator.sendBeacon("https://monorail-edge.shopifysvc.com/v1/produce", JSON.stringify({schema_id: "online_store_buyer_site_abandonment/1.1",payload: payload,metadata: {event_created_at_ms: currentMs,event_sent_at_ms: currentMs}}));}}window.addEventListener('pagehide', handle_abandonment_event);}}());</script>
vendor: 1 bytes, line 2398
2398
2399<script> 2400 window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || []; 2401</script>
vendor: 1 bytes, line 2401
2401
2402<script>(function(){var wpmLoader=function(){"use strict";var e=/Googlebot|Storebot-Google|bingbot|Baiduspider|YandexBot|DuckDuckBot|Slurp|facebookexternalhit|Twitterbot|LinkedInBot|Applebot|AdsBot-Google|Mediapartners-Google|APIs-Google|PetalBot|SemrushBot|AhrefsBot|MJ12bot|DotBot|Acunetix|PerplexityBot|Perplexity-User/i,t=/bytedance/i;function i(){try{var e=document.cookie;if(!e||"string"!=typeof e)return;for(var t=0,i=e.split(";");t<i.length;t++){var n=i[t],r=n.indexOf("=");if(-1!==r){var o=n.slice(0,r).trim();if(o){var a=void 0;try{a=decodeURIComponent(o)}catch(e){a=o}if("_shopify_s"===a){var d=n.slice(r+1).trim();try{return decodeURIComponent(d)}catch(e){return d}}}}}return}catch(e){return}}function n(e){try{"undefined"!=typeof console&&"function"==typeof console.warn&&console.warn(e)}catch(e){}}function r(e,t){return"string"==typeof e&&e.length>0&&e.length<=t?e:void 0}function o(e){var t;switch(null==(t=null==e?void 0:e.navigation)?void 0:t.type){case 0:return"navigate";case 1:return"reload";case 2:return"back_forward";default:return}}function a(){var e,t,i;try{var n=null==(i=null==(t=null==(e=self.ShopifyAnalytics)?void 0:e.lib)?void 0:t.trekkie)?void 0:i.state;return"awaiting-consent"===n||"initialized"===n?n:void 0}catch(e){return}}return function(d,s,u,l){var c=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};try{var p=c.trekkieShim;!0!==p&&"true"!==p||null!=window.__TREKKIE_SHIM_QUEUE||(window.__TREKKIE_SHIM_QUEUE=[])}catch(e){}var f,v,h,y,g=(v=(f={modern:/Edge?\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(9{2}|\d{3,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(15\.\d+|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9{2}|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]\d+|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/([2-9]\d|\d{3,})\.\d+/,legacy:/Edge?\/(1[6-9]|[2-9]\d|\d{3,})\.\d+(\.\d+|)|Firefox\/(5[4-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)|Chrom(ium|e)\/(5[1-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)([\d.]+$|.*Safari\/(?![\d.]+ Edge\/[\d.]+$))|(Maci|X1{2}).+ Version\/(10\.\d+|(1[1-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(3[89]|[4-9]\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(10[._]\d+|(1[1-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(15\.([5-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(5\.\d+|([6-9]|\d{2,})\.\d+)|Android.+MQ{2}Browser\/(14(\.(9|\d{2,})|)|(1[5-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/}).modern,h=f.legacy,(y=navigator.userAgent).match(e)?"bot":y.match(v)?"modern":y.match(h)?"legacy":y.match(t)?"bot":"unknown"),m=function(e){var t,i,n=r(e,128);try{var a=window.performance,d=null==(t=null==a?void 0:a.getEntriesByType)?void 0:t.call(a,"navigation")[0];if(!d)return{requestId:n,navigationType:o(a)};var s="type"in d?r(d.type,64):void 0,u="serverTiming"in d&&Array.isArray(d.serverTiming)?d.serverTiming:[];return{requestId:null!=n?n:r(null==(i=u.find(function(e){return"requestID"===e.name}))?void 0:i.description,128),navigationType:s}}catch(e){return{requestId:n}}}(c.requestId),w=function(e){var t=e.version,r=e.browserTarget,o=e.surface,a=e.shopId,d=e.monorailEndpoint,s=window.location.href;return{emit:function(e){var u=e.status,l=e.errorMsg,c=e.failureReason,p=e.useKeepaliveFallback,f=void 0!==p&&p,v=e.navigationType,h=e.pagehidePersisted,y=e.requestId,g=e.trekkieState;if(d){var m,w;try{var b=(new Date).getTime();m=JSON.stringify({metadata:{event_sent_at_ms:b},events:[{schema_id:"web_pixels_manager_load/3.3",payload:{version:t,bundle_target:r,page_url:s,status:u,surface:o,error_msg:l,failure_reason:c,navigation_type:v,pagehide_persisted:h,request_id:y,trekkie_state:g,shop_id:a,visit_token:i()},metadata:{event_created_at_ms:b}}]})}catch(e){return}try{if("function"==typeof window.navigator.sendBeacon&&-1===(w=window.navigator.userAgent).indexOf("iPhone; CPU iPhone OS 12_")&&-1===w.indexOf("iPad; CPU OS 12_")&&-1===w.indexOf("iPod touch; CPU iPhone OS 12_")&&window.navigator.sendBeacon.bind(window.navigator)(d,m))return}catch(e){}if(f)try{"function"==typeof window.fetch&&window.fetch(d,{method:"POST",headers:{"Content-Type":"text/plain"},body:m,keepalive:!0}
2402).catch(function(){})}catch(e){}else try{var _=new XMLHttpRequest;_.open("POST",d,!0),_.setRequestHeader("Content-Type","text/plain"),_.send(m)}catch(e){n("[Web Pixels Manager] Got an unhandled error while logging to Monorail.")}}else n("[Web Pixels Manager] No Monorail endpoint provided, skipping logging.")}}}({version:u,browserTarget:g,surface:d.surface,shopId:d.shopId,monorailEndpoint:d.monorailEndpoint});if(Boolean(null==(_=null==(b=window.Shopify)?void 0:b.analytics)?void 0:_.replayQueue))w.emit({status:"setup-skipped",errorMsg:"replay queue already initialized."});else{var b,_;w.emit({status:"setup-started"}),window.Shopify=window.Shopify||{};var S=window.Shopify;S.analytics=S.analytics||{};var P=S.analytics;P.replayQueue=[],P.publish=function(e,t,i){return P.replayQueue.push([e,t,i]),!0};try{self.performance.mark("wpm:start")}catch(e){}var k,C="modern"===g?"modern":"legacy",E=(null!=l?l:{modern:"",legacy:""})[C],I=[(k={baseUrl:s,hashVersion:u,buildTarget:C}).baseUrl,"/wpm","/b",k.hashVersion,"modern"===k.buildTarget?"m":"l",".js"].join(""),O=!1,T=!1;try{c.browserTarget=g,function(){O=!0;try{window.addEventListener("pagehide",M)}catch(e){O=!1}}(),R(function(){try{R(x)}catch(e){D(e)}}),w.emit({status:"loading",requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()})}catch(e){D(e)}}function U(){var e;if(q(),!function(){var e,t;return Boolean(null==(t=null==(e=window.Shopify)?void 0:e.analytics)?void 0:t.initialized)}()){var t,i,n;try{if("function"!=typeof(null==(e=window.webPixelsManager)?void 0:e.init))return void A();if(!(null!==(n=i=t=window.webPixelsManager.init(d))&&"function"!=typeof n&&Object(n)===n&&"publish"in i&&"function"==typeof i.publish&&"publishCustomEvent"in i&&"function"==typeof i.publishCustomEvent&&"visitor"in i&&"function"==typeof i.visitor))return void A()}catch(e){return void A(e)}var r=window.Shopify.analytics;r.replayQueue.forEach(function(e){var i=e[0],n=e[1],r=e[2];t.publishCustomEvent(i,n,r)}),r.replayQueue=[],r.publish=t.publishCustomEvent,r.visitor=t.visitor,r.initialized=!0}}function A(e){B("manager_api_unavailable",void 0===e?void 0:Q(e))}function x(){B("script_load_failed","".concat(I," has failed to load"))}function B(e,t){T||(T=!0,q(),w.emit({status:"failed",errorMsg:t,failureReason:e,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function M(e){O&&(q(),w.emit({status:"pagehide-while-loading",useKeepaliveFallback:!0,pagehidePersisted:e.persisted,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function q(){O=!1;try{window.removeEventListener("pagehide",M)}catch(e){}}function R(e){var t;!function(e){var t=e.src,i=e.async,n=void 0===i||i,r=e.onload,o=e.onerror,a=e.sri,d=e.scriptDataAttributes,s=void 0===d?{}:d,u=document.createElement("script"),l=document.querySelector("head"),c=document.querySelector("body");if(u.async=n,u.src=t,a&&(u.integrity=a,u.crossOrigin="anonymous"),s)for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))try{u.dataset[p]=String(s[p])}catch(e){}if(r&&u.addEventListener("load",r),o&&u.addEventListener("error",o),l)l.appendChild(u);else{if(!c)throw new Error("Did not find a head or body element to append the script");c.appendChild(u)}}({src:I,async:!0,onload:U,onerror:e,sri:(t=E,"string"==typeof t&&/^sha384-[A-Za-z0-9+/=]+$/.test(t)?E:""),scriptDataAttributes:c})}function D(e){B("script_append_failed",Q(e))}function Q(e){return e instanceof Error?e.message:"Unknown error"}}}();wpmLoader({shopId: 89912770934,storefrontBaseUrl: "https://granrondo.cc",extensionsBaseUrl: "https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager",monorailEndpoint: "https://granrondo.cc/.well-known/shopify/monorail/unstable/produce_batch",surface: "storefront-renderer",enabledBetaFlags: ["4c64608a","16072cab","8450a54b","7ee89bf1"],webPixelsConfigList: [{"id":"3679748470","configuration":"{\"pixel_id\":\"1421458882980031\",\"pixel_type\":\"facebook_pixel\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"96420dbe9ea96c426a1b7f364f977719","type":"APP","apiClientId":2329312,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"2086601078","configuration":"{\"myshopifyDomain\":\"khdz0c-aq.myshopify.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"23b97d18e2aa74363140dc29c9284e87","type":"APP","apiClientId":2775569,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_phone","read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"shopify-app-pixel","configuration":"{}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"APP","privacyPurposes":["ANALYTICS","MARKETING"]},{"id":"shopify-custom-pixel","eventPayloadVersion":"v1","runtimeContext":"LAX","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING"]}],isMerchantRequest: false,initData: {"shop":{"name":"GRANRONDO.cc","paymentSettings":{"currencyCode":"EUR"},"myshopifyDomain":"khdz0c-aq.myshopify.com","countryCode":"NL","storefrontUrl":"https:\/\/granrondo.cc\/en-en"},"customer":null,"cart":null,"checkout":null,"productVariants":[],"products":[{"id":"
240215103264981366","handle":"gran-rondo-nederland-event","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"57095877263734","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15775162171766","handle":"gran-rondo-wallonie-event","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"58075596226934","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15871005032822","handle":"gran-rondo-great-britain-event","isCollective":null,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"58641994482038","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]}],"purchasingCompany":null},},"https://granrondo.cc/cdn","5982071ew7ea472e3p69b68784m2150dfea",{"modern":"","legacy":""},{"trekkieShim":true,"agentContext":true,"apiClientId":"580111","facebookCapiEnabled":"true","themeId":"178807996790","themeStoreId":"887","themePublished":"true","eventMetadataId":"3ee5a290-e7c8-4d42-b335-a233aa3ddabe","pageType":"collection","resourceId":"673588085110","shopId":"89912770934","storefrontBaseUrl":"https:\/\/granrondo.cc","extensionBaseUrl":"https:\/\/extensions.shopifycdn.com\/cdn\/shopifycloud\/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[\"4c64608a\", \"16072cab\", \"8450a54b\", \"7ee89bf1\"]","isMerchantRequest":"false","hashVersion":"5982071ew7ea472e3p69b68784m2150dfea","publish":"custom","events":"[[\"page_viewed\",{}],[\"collection_viewed\",{\"collection\":{\"id\":\"673588085110\",\"title\":\"Events\",\"productVariants\":[{\"price\":{\"amount\":87.0,\"currencyCode\":\"USD\"},\"product\":{\"title\":\"Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge\",\"vendor\":\"GRANRONDO.cc\",\"id\":\"15103264981366\",\"untranslatedTitle\":\"Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge\",\"url\":\"\/en-en\/products\/gran-rondo-nederland-event\",\"type\":\"event\"},\"id\":\"57095877263734\",\"image\":{\"src\":\"\/\/granrondo.cc\/cdn\/shop\/files\/GranRondoCoverNederland.jpg?v=1790862405\"},\"sku\":null,\"title\":\"Longest Day(s) Challenge â Regular â 75 euro \/ Yourself \/ ð Rondobox with goodies and energy bites â included for free\",\"untranslatedTitle\":\"Longest Weekend Challenge â Regular â 135 euro \/ ð Rondobox met goodies en energybites â gratis inbegrepen \/ Jezelf\"},{\"price\":{\"amount\":155.0,\"currencyCode\":\"USD\"},\"product\":{\"title\":\"Gran Rondo ð¡ð´ Wallonie 400\",\"vendor\":\"GRANRONDO.cc\",\"id\":\"15775162171766\",\"untranslatedTitle\":\"Gran Rondo ð¡ð´ Wallonie 400\",\"url\":\"\/en-en\/products\/gran-rondo-wallonie-event\",\"type\":\"event\"},\"id\":\"58075596226934\",\"image\":{\"src\":\"\/\/granrondo.cc\/cdn\/shop\/files\/GranRondoCoverBEWA.jpg?v=1777413232\"},\"sku\":null,\"title\":\"Regular Ticket (1p) â 135 euro\",\"untranslatedTitle\":\"Regular Ticket (1p) â 135 euro\"},{\"price\":{\"amount\":155.0,\"currencyCode\":\"USD\"},\"product\":{\"title\":\"Gran Rondo âð¬ð§ Great Britain - 700 Miles Race\",\"vendor\":\"GRANRONDO.cc\",\"id\":\"15871005032822\",\"untranslatedTitle\":\"Gran Rondo âð¬ð§ Great Britain - 700 Miles Race\",\"url\":\"\/en-en\/products\/gran-rondo-great-britain-event\",\"type\":\"event\"},\"id\":\"58641994482038\",\"image\":{\"src\":\"\/\/granrondo.cc\/cdn\/shop\/files\/GRANRONDOcoverGB.jpg?v=1788879711\"},\"sku\":null,\"title\":\"Regular Ticket (1p) â 135 euro\",\"untranslatedTitle\":\"Regular Ticket (1p) â 135 euro\"}]}}]]"});})();</script>
2402<script> 2403 window.ShopifyAnalytics = window.ShopifyAnalytics || {}; 2404 window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; 2405 window.ShopifyAnalytics.meta.currency = 'USD'; 2406 var meta = {"products":[{"id":15103264981366,"gid":"gid:\/\/shopify\/Product\/15103264981366","vendor":"GRANRONDO.cc","type":"event","handle":"gran-rondo-nederland-event","variants":[{"id":57095877263734,"price":8700,"name":"Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge - Longest Day(s) Challenge â Regular â 75 euro \/ Yourself \/ ð Rondobox with goodies and energy bites â included for free","public_title":"Longest Day(s) Challenge â Regular â 75 euro \/ Yourself \/ ð Rondobox with goodies and energy bites â included for free","sku":null},{"id":57095877296502,"price":8700,"name":"Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge - Longest Day(s) Challenge â Regular â 75 euro \/ Someone else \/ ð Rondobox with goodies and energy bites â included for free","public_title":"Longest Day(s) Challenge â Regular â 75 euro \/ Someone else \/ ð Rondobox with goodies and energy bites â included for free","sku":null}],"remote":false},{"id":15775162171766,"gid":"gid:\/\/shopify\/Product\/15775162171766","vendor":"GRANRONDO.cc","type":"event","handle":"gran-rondo-wallonie-event","variants":[{"id":58075596226934,"price":15500,"name":"Gran Rondo ð¡ð´ Wallonie 400 - Regular Ticket (1p) â 135 euro","public_title":"Regular Ticket (1p) â 135 euro","sku":null},{"id":58230166290806,"price":26500,"name":"Gran Rondo ð¡ð´ Wallonie 400 - Duo Ticket (2p) â 115 euro p.p.","public_title":"Duo Ticket (2p) â 115 euro p.p.","sku":null},{"id":58601446211958,"price":0,"name":"Gran Rondo ð¡ð´ Wallonie 400 - Preregister - Free","public_title":"Preregister - Free","sku":null}],"remote":false},{"id":15871005032822,"gid":"gid:\/\/shopify\/Product\/15871005032822","vendor":"GRANRONDO.cc","type":"event","handle":"gran-rondo-great-britain-event","variants":[{"id":58641994482038,"price":15500,"name":"Gran Rondo âð¬ð§ Great Britain - 700 Miles Race - Regular Ticket (1p) â 135 euro","public_title":"Regular Ticket (1p) â 135 euro","sku":null},{"id":58641994514806,"price":26500,"name":"Gran Rondo âð¬ð§ Great Britain - 700 Miles Race - Duo Ticket (2p) â 115 euro p.p.","public_title":"Duo Ticket (2p) â 115 euro p.p.","sku":null}],"remote":false}],"page":{"pageType":"collection","resourceType":"collection","resourceId":673588085110,"requestId":"cc422a89-d3e5-4da3-a97c-b151b1c79dd5-1791129347"}}; 2407 for (var attr in meta) { 2408 window.ShopifyAnalytics.meta[attr] = meta[attr]; 2409 } 2410</script>
vendor: 1 bytes, line 2410
2410
2411<script class="analytics"> 2412 (function () { 2413 var customDocumentWrite = function(content) { 2414 var jquery = null; 2415 2416 if (window.jQuery) { 2417 jquery = window.jQuery; 2418 } else if (window.Checkout && window.Checkout.$) { 2419 jquery = window.Checkout.$; 2420 } 2421 2422 if (jquery) { 2423 jquery('body').append(content); 2424 } 2425 }; 2426 2427 var hasLoggedConversion = function(token) { 2428 if (token) { 2429 return document.cookie.indexOf('loggedConversion=' + token) !== -1; 2430 } 2431 return false; 2432 } 2433 2434 var setCookieIfConversion = function(token) { 2435 if (token) { 2436 var twoMonthsFromNow = new Date(Date.now()); 2437 twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); 2438 2439 document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; 2440 } 2441 } 2442 2443 var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; 2444 window.ShopifyAnalytics.lib.trekkie = window.trekkie; 2445 if (trekkie.integrations) { 2446 return; 2447 } 2448 trekkie.methods = [ 2449 'identify', 2450 'page', 2451 'ready', 2452 'track', 2453 'trackForm', 2454 'trackLink' 2455 ]; 2456 trekkie.factory = function(method) { 2457 return function() { 2458 var args = Array.prototype.slice.call(arguments); 2459 args.unshift(method); 2460 trekkie.push(args); 2461 if (method == 'track' || method == 'page') { 2462 var pageUrl; 2463 try { 2464 pageUrl = window.location.href; 2465 } catch (e) {} 2466 var pageReferrer; 2467 try { 2468 pageReferrer = document.referrer; 2469 } catch (e) {} 2470 try { 2471 if (window.__TREKKIE_SHIM_QUEUE == null) { 2472 window.__TREKKIE_SHIM_QUEUE = []; 2473 } 2474 window.__TREKKIE_SHIM_QUEUE.push({ 2475 from: 'trekkie-stub', 2476 method: method, 2477 args: args.slice(1), 2478 pageContext: { 2479 url: pageUrl, 2480 referrer: pageReferrer 2481 } 2482 }); 2483 } catch (e) { 2484 // no-op 2485 } 2486 } 2487 return trekkie; 2488 }; 2489 }; 2490 for (var i = 0; i < trekkie.methods.length; i++) { 2491 var key = trekkie.methods[i]; 2492 trekkie[key] = trekkie.factory(key); 2493 } 2494 trekkie.load = function(config) { 2495 trekkie.config = config || {}; 2496 trekkie.config.initialDocumentCookie = document.cookie; 2497 var first = document.getElementsByTagName('script')[0]; 2498var script = document.createElement('script'); 2499script.type = 'text/javascript'; 2500script.onerror = function(e) { 2501 var scriptFallback = document.createElement('script'); 2502 scriptFallback.type = 'text/javascript'; 2503 scriptFallback.onerror = function(error) { 2504 var Monorail = { 2505 produce: function produce(monorailDomain, schemaId, payload) { 2506 var currentMs = new Date().getTime(); 2507 var event = { 2508 schema_id: schemaId, 2509 payload: payload, 2510 metadata: { 2511 event_created_at_ms: currentMs, 2512 event_sent_at_ms: currentMs 2513 } 2514 }; 2515 return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); 2516 }, 2517 sendRequest: function sendRequest(endpointUrl, payload) { 2518 // Try the sendBeacon API 2519 if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { 2520 var blobData = new window.Blob([payload], { 2521 type: 'text/plain' 2522 }); 2523 2524 if (window.navigator.sendBeacon(endpointUrl, blobData)) { 2525 return true; 2526 } // sendBeacon was not successful 2527 2528 } // XHR beacon 2529 2530 var xhr = new XMLHttpRequest(); 2531 2532 try { 2533 xhr.open('POST', endpointUrl); 2534 xhr.setRequestHeader('Content-Type', 'text/plain'); 2535 xhr.send(payload); 2536 } catch (e) { 2537 console.log(e); 2538 } 2539 2540 return false; 2541 }, 2542 isIos12: function isIos12() { 2543 return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; 2544 } 2545 }; 2546 Monorail.produce('monorail-edge.shopifysvc.com', 2547 'trekkie_storefront_load_errors/1.1', 2548 {shop_id: 89912770934, 2549 theme_id: 178807996790, 2550 app_name: "storefront", 2551 context_url: window.location.href, 2552 source_url: "//granrondo.cc/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js"}); 2553 2554 }; 2555 scriptFallback.async = true; 2556 scriptFallback.src = '//granrondo.cc/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js'; 2557 first.parentNode.insertBefore(scriptFallback, first); 2558}; 2559script.async = true; 2560script.src = '//granrondo.cc/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js'; 2561first.parentNode.insertBefore(script, first); 2562 2563 }; 2564 trekkie.load( 2565 {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":89912770934,"isMerchantRequest":null,"themeId":178807996790,"themeCityHash":"16074661382724102556","contentLanguage":"en","currency":"USD","eventMetadataId":"3ee5a290-e7c8-4d42-b335-a233aa3ddabe"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1","4c64608a"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":true,"source":"trekkie-storefront-renderer","apiClientId":580111}} 2566 ); 2567 2568 var loaded = false;
2569 trekkie.ready(function() { 2570 if (loaded) return; 2571 loaded = true; 2572 2573 window.ShopifyAnalytics.lib = window.trekkie; 2574 2575 var originalDocumentWrite = document.write; 2576 document.write = customDocumentWrite; 2577 try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; 2578 document.write = originalDocumentWrite; 2579 2580 var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) 2581 var token = match? match[1]: undefined; 2582 if (!hasLoggedConversion(token)) { 2583 setCookieIfConversion(token); 2584 window.ShopifyAnalytics.lib.track("Viewed Product Category",{"currency":"USD","category":"Collection: events","collectionName":"events","collectionId":673588085110,"nonInteraction":true},undefined,undefined,{"shopifyEmitted":true}); 2585 } 2586 }); 2587 2588 window.ShopifyAnalytics.lib.page(null,{"pageType":"collection","resourceType":"collection","resourceId":673588085110,"requestId":"cc422a89-d3e5-4da3-a97c-b151b1c79dd5-1791129347","shopifyEmitted":true}); 2589 2590 var eventsListenerScript = document.createElement('script'); 2591 eventsListenerScript.async = true; 2592 eventsListenerScript.src = "//granrondo.cc/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js"; 2593 document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); 2594})();</script>
vendor: 1 bytes, line 2594
2594
2595<script 2596 defer 2597 src="https://granrondo.cc/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js" 2598 data-application="storefront-renderer" 2599 data-shop-id="89912770934" 2600 data-render-region="gcp-us-west1" 2601 data-page-type="collection" 2602 data-theme-instance-id="178807996790" 2603 data-theme-name="Dawn" 2604 data-theme-version="15.2.0" 2605 data-monorail-region="shop_domain" 2606 data-resource-timing-sampling-rate="10" 2607 data-shs="true" 2608 data-shs-beacon="true" 2609 data-shs-export-with-fetch="true" 2610 data-shs-logs-sample-rate="1" 2611 data-shs-beacon-endpoint="https://granrondo.cc/api/collect" 2612></script>
2612 2613<meta name="shopify-y" content="2f145c5c-5973-4287-96e9-c62b0b79d1c8" data-expiration="1822686947000"><meta name="shopify-s" content="af74a3ef-b55e-41f4-8757-20db1e3c0bb0" data-expiration="1791131147000"><meta name="new-cookie-storage-activated" content="t"> 2614</head> 2615 2616 <body class="gradient animate--hover-3d-lift"> 2617 <a class="skip-to-content-link button visually-hidden" href="#MainContent"> 2618 Skip to content 2619 </a><!-- BEGIN sections: header-group --> 2620<div id="shopify-section-sections--24695135207798__announcement-bar" class="shopify-section shopify-section-group-header-group announcement-bar-section"><link href="//granrondo.cc/cdn/shop/t/1/assets/component-slideshow.css?v=17933591812325749411737013876" rel="stylesheet" type="text/css" media="all" /> 2621<link href="//granrondo.cc/cdn/shop/t/1/assets/component-slider.css?v=97592406805511041321761432556" rel="stylesheet" type="text/css" media="all" /> 2622 2623 2624<div 2625 class="utility-bar color-scheme-39e54bf2-8e08-472b-9cf4-d057e89900fb gradient" 2626 2627> 2628 <div class="page-width utility-bar__grid"><div class="localization-wrapper"> 2629</div> 2630 </div> 2631</div> 2632 2633 2634</div><div id="shopify-section-sections--24695135207798__header" class="shopify-section shopify-section-group-header-group section-header"><link rel="stylesheet" href="//granrondo.cc/cdn/shop/t/1/assets/component-list-menu.css?v=151968516119678728991737013876" media="print" onload="this.media='all'"> 2635<link rel="stylesheet" href="//granrondo.cc/cdn/shop/t/1/assets/component-search.css?v=165164710990765432851737013876" media="print" onload="this.media='all'"> 2636<link rel="stylesheet" href="//granrondo.cc/cdn/shop/t/1/assets/component-menu-drawer.css?v=147478906057189667651737013876" media="print" onload="this.media='all'"> 2637<link rel="stylesheet" href="//granrondo.cc/cdn/shop/t/1/assets/component-cart-notification.css?v=54116361853792938221737013876" media="print" onload="this.media='all'"><style> 2638 header-drawer { 2639 justify-self: start; 2640 margin-left: -1.2rem; 2641 }@media screen and (min-width: 990px) { 2642 header-drawer { 2643 display: none; 2644 } 2645 }.menu-drawer-container { 2646 display: flex; 2647 } 2648 2649 .list-menu { 2650 list-style: none; 2651 padding: 0; 2652 margin: 0; 2653 } 2654 2655 .list-menu--inline { 2656 display: inline-flex; 2657 flex-wrap: wrap; 2658 } 2659 2660 summary.list-menu__item { 2661 padding-right: 2.7rem; 2662 } 2663 2664 .list-menu__item { 2665 display: flex; 2666 align-items: center; 2667 line-height: calc(1 + 0.3 / var(--font-body-scale)); 2668 } 2669 2670 .list-menu__item--link { 2671 text-decoration: none; 2672 padding-bottom: 1rem; 2673 padding-top: 1rem; 2674 line-height: calc(1 + 0.8 / var(--font-body-scale)); 2675 } 2676 2677 @media screen and (min-width: 750px) { 2678 .list-menu__item--link { 2679 padding-bottom: 0.5rem; 2680 padding-top: 0.5rem; 2681 } 2682 } 2683</style><style data-shopify>.header { 2684 padding: 18px 3rem 18px 3rem; 2685 } 2686 2687 .section-header { 2688 position: sticky; /* This is for fixing a Safari z-index issue. PR #2147 */ 2689 margin-bottom: 30px; 2690 } 2691 2692 @media screen and (min-width: 750px) { 2693 .section-header { 2694 margin-bottom: 40px; 2695 } 2696 } 2697 2698 @media screen and (min-width: 990px) { 2699 .header { 2700 padding-top: 36px; 2701 padding-bottom: 36px; 2702 } 2703 }</style>
2703<script src="//granrondo.cc/cdn/shop/t/1/assets/cart-notification.js?v=133508293167896966491737013876" defer="defer"></script>
2703<div class="header-wrapper color-scheme-1 gradient"><header class="header header--top-center header--mobile-center page-width header--has-menu"> 2704 2705<header-drawer data-breakpoint="tablet"> 2706 <details id="Details-menu-drawer-container" class="menu-drawer-container"> 2707 <summary 2708 class="header__icon header__icon--menu header__icon--summary link focus-inset" 2709 aria-label="Menu" 2710 > 2711 <span><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-hamburger" viewBox="0 0 18 16"><path fill="currentColor" d="M1 .5a.5.5 0 1 0 0 1h15.71a.5.5 0 0 0 0-1zM.5 8a.5.5 0 0 1 .5-.5h15.71a.5.5 0 0 1 0 1H1A.5.5 0 0 1 .5 8m0 7a.5.5 0 0 1 .5-.5h15.71a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5"/></svg> 2712<svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-close" viewBox="0 0 18 17"><path fill="currentColor" d="M.865 15.978a.5.5 0 0 0 .707.707l7.433-7.431 7.579 7.282a.501.501 0 0 0 .846-.37.5.5 0 0 0-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 1 0-.707-.708L8.991 7.853 1.413.573a.5.5 0 1 0-.693.72l7.563 7.268z"/></svg> 2713</span> 2714 </summary> 2715 <div id="menu-drawer" class="gradient menu-drawer motion-reduce color-scheme-1"> 2716 <div class="menu-drawer__inner-container"> 2717 <div class="menu-drawer__navigation-container"> 2718 <nav class="menu-drawer__navigation"> 2719 <ul class="menu-drawer__menu has-submenu list-menu" role="list"><li><a 2720 id="HeaderDrawer-jouw-rondos" 2721 href="/en-en/pages/dashboard" 2722 class="menu-drawer__menu-item list-menu__item link link--text focus-inset" 2723 2724 > 2725 Your Rondos 2726 </a></li><li><a 2727 id="HeaderDrawer-events" 2728 href="/en-en/collections/events" 2729 class="menu-drawer__menu-item list-menu__item link link--text focus-inset menu-drawer__menu-item--active" 2730 2731 aria-current="page" 2732 2733 > 2734 Events 2735 </a></li><li><details id="Details-menu-drawer-menu-item-3"> 2736 <summary 2737 id="HeaderDrawer-shop" 2738 class="menu-drawer__menu-item list-menu__item link link--text focus-inset" 2739 > 2740 Shop 2741 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-arrow" viewB
2741ox="0 0 14 10"><path fill="currentColor" fill-rule="evenodd" d="M8.537.808a.5.5 0 0 1 .817-.162l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 1 1-.708-.708L11.793 5.5H1a.5.5 0 0 1 0-1h10.793L8.646 1.354a.5.5 0 0 1-.109-.546" clip-rule="evenodd"/></svg> 2742</span> 2743 <span class="svg-wrapper"><svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 2744</span> 2745 </summary> 2746 <div 2747 id="link-shop" 2748 class="menu-drawer__submenu has-submenu gradient motion-reduce" 2749 tabindex="-1" 2750 > 2751 <div class="menu-drawer__inner-submenu"> 2752 <button class="menu-drawer__close-button link link--text focus-inset" aria-expanded="true"> 2753 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-arrow" viewB
2753ox="0 0 14 10"><path fill="currentColor" fill-rule="evenodd" d="M8.537.808a.5.5 0 0 1 .817-.162l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 1 1-.708-.708L11.793 5.5H1a.5.5 0 0 1 0-1h10.793L8.646 1.354a.5.5 0 0 1-.109-.546" clip-rule="evenodd"/></svg> 2754</span> 2755 Shop 2756 </button> 2757 <ul class="menu-drawer__menu list-menu" role="list" tabindex="-1"><li><a 2758 id="HeaderDrawer-shop-rondoboxen-gidsen" 2759 href="/en-en/collections/all" 2760 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2761 2762 > 2763 Rondoboxes & Guides 2764 </a></li><li><a 2765 id="HeaderDrawer-shop-rondoneurs-kit" 2766 href="/en-en/collections/rondoneurs-kit" 2767 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2768 2769 > 2770 Rondoneurs Kit 2771 </a></li><li><details id="Details-menu-drawer-shop-service"> 2772 <summary 2773 id="HeaderDrawer-shop-service" 2774 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2775 > 2776 Service 2777 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-arrow" viewB
2777ox="0 0 14 10"><path fill="currentColor" fill-rule="evenodd" d="M8.537.808a.5.5 0 0 1 .817-.162l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 1 1-.708-.708L11.793 5.5H1a.5.5 0 0 1 0-1h10.793L8.646 1.354a.5.5 0 0 1-.109-.546" clip-rule="evenodd"/></svg> 2778</span> 2779 <span class="svg-wrapper"><svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 2780</span> 2781 </summary> 2782 <div 2783 id="childlink-service" 2784 class="menu-drawer__submenu has-submenu gradient motion-reduce" 2785 > 2786 <button 2787 class="menu-drawer__close-button link link--text focus-inset" 2788 aria-expanded="true" 2789 > 2790 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-arrow" viewB
2790ox="0 0 14 10"><path fill="currentColor" fill-rule="evenodd" d="M8.537.808a.5.5 0 0 1 .817-.162l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 1 1-.708-.708L11.793 5.5H1a.5.5 0 0 1 0-1h10.793L8.646 1.354a.5.5 0 0 1-.109-.546" clip-rule="evenodd"/></svg> 2791</span> 2792 Service 2793 </button> 2794 <ul 2795 class="menu-drawer__menu list-menu" 2796 role="list" 2797 tabindex="-1" 2798 ><li> 2799 <a 2800 id="HeaderDrawer-shop-service-vraag-antwoord" 2801 href="/en-en/pages/service" 2802 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2803 2804 > 2805 Question & Answer 2806 </a> 2807 </li><li> 2808 <a 2809 id="HeaderDrawer-shop-service-bestelstatus" 2810 href="https://account.granrondo.cc/orders?locale=en®ion_country=US&buyer_flags=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJraGR6MGMtYXEubXlzaG9waWZ5LmNvbSIsImZsYWdzIjpbXSwiZXhwIjoxNzkxNzM0MTQ4LCJuYmYiOjE3OTExMjkzNDh9.JJR3o2H8oj7UyznNdneLTGHxMoaQ1WLTeSO0ehjAZ4w" 2811 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2812 2813 > 2814 Order Status 2815 </a> 2816 </li><li> 2817 <a 2818 id="HeaderDrawer-shop-service-contact" 2819 href="/en-en/pages/service#contactus" 2820 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2821 2822 > 2823 Contact 2824 </a> 2825 </li></ul> 2826 </div> 2827 </details></li></ul> 2828 </div> 2829 </div> 2830 </details></li><li><details id="Details-menu-drawer-menu-item-4"> 2831 <summary 2832 id="HeaderDrawer-join-the-circle" 2833 class="menu-drawer__menu-item list-menu__item link link--text focus-inset" 2834 > 2835 Join the Circle 2836 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-arrow" viewB
2836ox="0 0 14 10"><path fill="currentColor" fill-rule="evenodd" d="M8.537.808a.5.5 0 0 1 .817-.162l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 1 1-.708-.708L11.793 5.5H1a.5.5 0 0 1 0-1h10.793L8.646 1.354a.5.5 0 0 1-.109-.546" clip-rule="evenodd"/></svg> 2837</span> 2838 <span class="svg-wrapper"><svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 2839</span> 2840 </summary> 2841 <div 2842 id="link-join-the-circle" 2843 class="menu-drawer__submenu has-submenu gradient motion-reduce" 2844 tabindex="-1" 2845 > 2846 <div class="menu-drawer__inner-submenu"> 2847 <button class="menu-drawer__close-button link link--text focus-inset" aria-expanded="true"> 2848 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-arrow" viewB
2848ox="0 0 14 10"><path fill="currentColor" fill-rule="evenodd" d="M8.537.808a.5.5 0 0 1 .817-.162l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 1 1-.708-.708L11.793 5.5H1a.5.5 0 0 1 0-1h10.793L8.646 1.354a.5.5 0 0 1-.109-.546" clip-rule="evenodd"/></svg> 2849</span> 2850 Join the Circle 2851 </button> 2852 <ul class="menu-drawer__menu list-menu" role="list" tabindex="-1"><li><a 2853 id="HeaderDrawer-join-the-circle-rondoneur-worden" 2854 href="/en-en/products/join" 2855 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2856 2857 > 2858 Join as Rondoneur 2859 </a></li><li><a 2860 id="HeaderDrawer-join-the-circle-hall-of-fame" 2861 href="/en-en/pages/rondo-hall-of-fame" 2862 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2863 2864 > 2865 Hall of Fame 2866 </a></li><li><a 2867 id="HeaderDrawer-join-the-circle-samen-voor-kika" 2868 href="/en-en/pages/samen-voor-kika" 2869 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2870 2871 > 2872 Together for Kika 2873 </a></li><li><a 2874 id="HeaderDrawer-join-the-circle-mr-granrondo" 2875 href="/en-en/pages/mr-granrondo" 2876 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2877 2878 > 2879 mr.granrondo 2880 </a></li><li><a 2881 id="HeaderDrawer-join-the-circle-instagram" 2882 href="https://www.instagram.com/ridearound.cc" 2883 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2884 2885 > 2886 Instagram 2887 </a></li><li><a 2888 id="HeaderDrawer-join-the-circle-strava" 2889 href="https://www.strava.com/clubs/granrondo" 2890 class="menu-drawer__menu-item link link--text list-menu__item focus-inset" 2891 2892 > 2893 Strava 2894 </a></li></ul> 2895 </div> 2896 </div> 2897 </details></li><li><a 2898 id="HeaderDrawer-je-startlijst-mandje" 2899 href="/en-en/cart" 2900 class="menu-drawer__menu-item list-menu__item link link--text focus-inset" 2901 2902 > 2903 Your Startlist / Basket 2904 </a></li></ul> 2905 </nav> 2906 <div class="menu-drawer__utility-links"><div class="menu-drawer__localization header-localization"><localization-form><form method="post" action="/en-en/localization" id="HeaderCountryMobileForm" accept-charset="UTF-8" class="localization-form" enctype="multipart/form-data"><input type="hidden" name="form_type" value="localization" /><input type="hidden" name="utf8" value="â" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="return_to" value="/en-en/collections/events" /><div> 2907 <h2 class="visually-hidden" id="HeaderCountryMobileLabel"> 2908 Country/region 2909 </h2> 2910 2911<div class="disclosure"> 2912 <button 2913 type="button" 2914 class="disclosure__button localization-form__select localization-selector link link--text caption-large" 2915 aria-expanded="false" 2916 aria-controls="HeaderCountryMobile-country-results" 2917 aria-describedby="HeaderCountryMobileLabel" 2918 > 2919 <span>United States | 2920 USD
2921 $</span> 2922 <svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 2923 2924 </button> 2925 <div class="disclosure__list-wrapper country-selector" hidden> 2926 <div class="country-filter"> 2927 2928 <div class="field"> 2929 <input 2930 class="country-filter__input field__input" 2931 id="country-filter-input" 2932 type="search" 2933 name="country_filter" 2934 value="" 2935 placeholder="Search" 2936 role="combobox" 2937 aria-owns="country-results" 2938 aria-controls="country-results" 2939 aria-haspopup="listbox" 2940 aria-autocomplete="list" 2941 autocorrect="off" 2942 autocomplete="off" 2943 autocapitalize="off" 2944 spellcheck="false" 2945 > 2946 <label class="field__label" for="country-filter-input">Search</label> 2947 <button 2948 type="reset" 2949 class="country-filter__reset-button field__button hidden" 2950 aria-label="Clear search term" 2951 ><svg fill="none" stroke="currentColor" class="icon icon-close" viewBox="0 0 18 18"><circle cx="9" cy="9" r="8.5" stroke-opacity=".2"/><path stroke-linecap="round" stroke-linejoin="round" d="M11.83 11.83 6.172 6.17M6.229 11.885l5.544-5.77"/></svg> 2952</button> 2953 <div class="country-filter__search-icon field__button motion-reduce"><svg fill="none" class="icon icon-search" viewBox="0 0 18 19"><path fill="currentColor" fill-rule="evenodd" d="M11.03 11.68A5.784 5.784 0 1 1 2.85 3.5a5.784 5.784 0 0 1 8.18 8.18m.26 1.12a6.78 6.78 0 1 1 .72-.7l5.4 5.4a.5.5 0 1 1-.71.7z" clip-rule="evenodd"/></svg> 2954</div> 2955 </div> 2956 2957 <button 2958 class="country-selector__close-button button--small link" 2959 type="button" 2960 aria-label="Close" 2961 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-close" viewBox="0 0 18 17"><path fill="currentColor" d="M.865 15.978a.5.5 0 0 0 .707.707l7.433-7.431 7.579 7.282a.501.501 0 0 0 .846-.37.5.5 0 0 0-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 1 0-.707-.708L8.991 7.853 1.413.573a.5.5 0 1 0-.693.72l7.563 7.268z"/></svg> 2962</button> 2963 </div> 2964 <div id="sr-country-search-results" class="visually-hidden" aria-live="polite"></div> 2965 <div 2966 class="disclosure__list country-selector__list country-selector__list--with-multiple-currencies" 2967 id="HeaderCountryMobile-country-results" 2968 > 2969 2970 <ul role="list" class="list-unstyled countries"><li class="disclosure__item" tabindex="-1"> 2971 <a 2972 class="link link--text disclosure__link caption-large focus-inset" 2973 href="#" 2974 2975 data-value="AF" 2976 id="Afghanistan" 2977 > 2978 <span 2979 2980 class="visibility-hidden" 2981 2982 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 2983</span> 2984 <span class="country">Afghanistan</span> 2985 <span class="localization-form__currency motion-reduce"> 2986 AFN 2987 Ø</span> 2988 </a> 2989 </li><li class="disclosure__item" tabindex="-1"> 2990 <a 2991 class="link link--text disclosure__link caption-large focus-inset" 2992 href="#" 2993 2994 data-value="AX" 2995 id="Ã land Islands" 2996 > 2997 <span 2998 2999 class="visibility-hidden" 3000 3001 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3002</span>
3003 <span class="country">à land Islands</span> 3004 <span class="localization-form__currency motion-reduce"> 3005 EUR 3006 â¬</span> 3007 </a> 3008 </li><li class="disclosure__item" tabindex="-1"> 3009 <a 3010 class="link link--text disclosure__link caption-large focus-inset" 3011 href="#" 3012 3013 data-value="AL" 3014 id="Albania" 3015 > 3016 <span 3017 3018 class="visibility-hidden" 3019 3020 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3021</span> 3022 <span class="country">Albania</span> 3023 <span class="localization-form__currency motion-reduce"> 3024 ALL 3025 L</span> 3026 </a> 3027 </li><li class="disclosure__item" tabindex="-1"> 3028 <a 3029 class="link link--text disclosure__link caption-large focus-inset" 3030 href="#" 3031 3032 data-value="DZ" 3033 id="Algeria" 3034 > 3035 <span 3036 3037 class="visibility-hidden" 3038 3039 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3040</span> 3041 <span class="country">Algeria</span> 3042 <span class="localization-form__currency motion-reduce"> 3043 DZD 3044 د.ج</span> 3045 </a> 3046 </li><li class="disclosure__item" tabindex="-1"> 3047 <a 3048 class="link link--text disclosure__link caption-large focus-inset" 3049 href="#" 3050 3051 data-value="AD" 3052 id="Andorra" 3053 > 3054 <span 3055 3056 class="visibility-hidden" 3057 3058 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3059</span> 3060 <span class="country">Andorra</span> 3061 <span class="localization-form__currency motion-reduce"> 3062 EUR 3063 â¬</span> 3064 </a> 3065 </li><li class="disclosure__item" tabindex="-1"> 3066 <a 3067 class="link link--text disclosure__link caption-large focus-inset" 3068 href="#" 3069 3070 data-value="AO" 3071 id="Angola" 3072 > 3073 <span 3074 3075 class="visibility-hidden" 3076 3077 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3078</span> 3079 <span class="country">Angola</span> 3080 <span class="localization-form__currency motion-reduce"> 3081 EUR 3082 â¬</span> 3083 </a> 3084 </li><li class="disclosure__item" tabindex="-1"> 3085 <a 3086 class="link link--text disclosure__link caption-large focus-inset" 3087 href="#" 3088 3089 data-value="AI" 3090 id="Anguilla" 3091 > 3092 <span 3093 3094 class="visibility-hidden" 3095 3096 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
3096<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3097</span> 3098 <span class="country">Anguilla</span> 3099 <span class="localization-form__currency motion-reduce"> 3100 XCD 3101 $</span> 3102 </a> 3103 </li><li class="disclosure__item" tabindex="-1"> 3104 <a 3105 class="link link--text disclosure__link caption-large focus-inset" 3106 href="#" 3107 3108 data-value="AG" 3109 id="Antigua & Barbuda" 3110 > 3111 <span 3112 3113 class="visibility-hidden" 3114 3115 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3116</span> 3117 <span class="country">Antigua & Barbuda</span> 3118 <span class="localization-form__currency motion-reduce"> 3119 XCD 3120 $</span> 3121 </a> 3122 </li><li class="disclosure__item" tabindex="-1"> 3123 <a 3124 class="link link--text disclosure__link caption-large focus-inset" 3125 href="#" 3126 3127 data-value="AR" 3128 id="Argentina" 3129 > 3130 <span 3131 3132 class="visibility-hidden" 3133 3134 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3135</span> 3136 <span class="country">Argentina</span> 3137 <span class="localization-form__currency motion-reduce"> 3138 EUR 3139 â¬</span> 3140 </a> 3141 </li><li class="disclosure__item" tabindex="-1"> 3142 <a 3143 class="link link--text disclosure__link caption-large focus-inset" 3144 href="#" 3145 3146 data-value="AM" 3147 id="Armenia" 3148 > 3149 <span 3150 3151 class="visibility-hidden" 3152 3153 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3154</span> 3155 <span class="country">Armenia</span> 3156 <span class="localization-form__currency motion-reduce"> 3157 AMD 3158 Õ¤Ö.</span> 3159 </a> 3160 </li><li class="disclosure__item" tabindex="-1"> 3161 <a 3162 class="link link--text disclosure__link caption-large focus-inset" 3163 href="#" 3164 3165 data-value="AW" 3166 id="Aruba" 3167 > 3168 <span 3169 3170 class="visibility-hidden" 3171 3172 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3173</span> 3174 <span class="country">Aruba</span> 3175 <span class="localization-form__currency motion-reduce"> 3176 AWG 3177 Æ</span> 3178 </a> 3179 </li><li class="disclosure__item" tabindex="-1"> 3180 <a 3181 class="link link--text disclosure__link caption-large focus-inset" 3182 href="#" 3183 3184 data-value="AC" 3185 id="Ascension Island" 3186 >
3187 <span 3188 3189 class="visibility-hidden" 3190 3191 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3192</span> 3193 <span class="country">Ascension Island</span> 3194 <span class="localization-form__currency motion-reduce"> 3195 SHP 3196 £</span> 3197 </a> 3198 </li><li class="disclosure__item" tabindex="-1"> 3199 <a 3200 class="link link--text disclosure__link caption-large focus-inset" 3201 href="#" 3202 3203 data-value="AU" 3204 id="Australia" 3205 > 3206 <span 3207 3208 class="visibility-hidden" 3209 3210 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3211</span> 3212 <span class="country">Australia</span> 3213 <span class="localization-form__currency motion-reduce"> 3214 AUD 3215 $</span> 3216 </a> 3217 </li><li class="disclosure__item" tabindex="-1"> 3218 <a 3219 class="link link--text disclosure__link caption-large focus-inset" 3220 href="#" 3221 3222 data-value="AT" 3223 id="Austria" 3224 > 3225 <span 3226 3227 class="visibility-hidden" 3228 3229 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3230</span> 3231 <span class="country">Austria</span> 3232 <span class="localization-form__currency motion-reduce"> 3233 EUR 3234 â¬</span> 3235 </a> 3236 </li><li class="disclosure__item" tabindex="-1"> 3237 <a 3238 class="link link--text disclosure__link caption-large focus-inset" 3239 href="#" 3240 3241 data-value="AZ" 3242 id="Azerbaijan" 3243 > 3244 <span 3245 3246 class="visibility-hidden" 3247 3248 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3249</span> 3250 <span class="country">Azerbaijan</span> 3251 <span class="localization-form__currency motion-reduce"> 3252 AZN 3253 â¼</span> 3254 </a> 3255 </li><li class="disclosure__item" tabindex="-1"> 3256 <a 3257 class="link link--text disclosure__link caption-large focus-inset" 3258 href="#" 3259 3260 data-value="BS" 3261 id="Bahamas" 3262 > 3263 <span 3264 3265 class="visibility-hidden" 3266 3267 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3268</span> 3269 <span class="country">Bahamas</span> 3270 <span class="localization-form__currency motion-reduce"> 3271 BSD
3272 $</span> 3273 </a> 3274 </li><li class="disclosure__item" tabindex="-1"> 3275 <a 3276 class="link link--text disclosure__link caption-large focus-inset" 3277 href="#" 3278 3279 data-value="BH" 3280 id="Bahrain" 3281 > 3282 <span 3283 3284 class="visibility-hidden" 3285 3286 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3287</span> 3288 <span class="country">Bahrain</span> 3289 <span class="localization-form__currency motion-reduce"> 3290 EUR 3291 â¬</span> 3292 </a> 3293 </li><li class="disclosure__item" tabindex="-1"> 3294 <a 3295 class="link link--text disclosure__link caption-large focus-inset" 3296 href="#" 3297 3298 data-value="BD" 3299 id="Bangladesh" 3300 > 3301 <span 3302 3303 class="visibility-hidden" 3304 3305 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3306</span> 3307 <span class="country">Bangladesh</span> 3308 <span class="localization-form__currency motion-reduce"> 3309 BDT 3310 à§³</span> 3311 </a> 3312 </li><li class="disclosure__item" tabindex="-1"> 3313 <a 3314 class="link link--text disclosure__link caption-large focus-inset" 3315 href="#" 3316 3317 data-value="BB" 3318 id="Barbados" 3319 > 3320 <span 3321 3322 class="visibility-hidden" 3323 3324 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3325</span> 3326 <span class="country">Barbados</span> 3327 <span class="localization-form__currency motion-reduce"> 3328 BBD 3329 $</span> 3330 </a> 3331 </li><li class="disclosure__item" tabindex="-1"> 3332 <a 3333 class="link link--text disclosure__link caption-large focus-inset" 3334 href="#" 3335 3336 data-value="BY" 3337 id="Belarus" 3338 > 3339 <span 3340 3341 class="visibility-hidden" 3342 3343 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3344</span> 3345 <span class="country">Belarus</span> 3346 <span class="localization-form__currency motion-reduce"> 3347 EUR 3348 â¬</span> 3349 </a> 3350 </li><li class="disclosure__item" tabindex="-1"> 3351 <a 3352 class="link link--text disclosure__link caption-large focus-inset" 3353 href="#" 3354 3355 data-value="BE" 3356 id="Belgium" 3357 > 3358 <span 3359 3360 class="visibility-hidden" 3361 3362 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3363</span>
3364 <span class="country">Belgium</span> 3365 <span class="localization-form__currency motion-reduce"> 3366 EUR 3367 â¬</span> 3368 </a> 3369 </li><li class="disclosure__item" tabindex="-1"> 3370 <a 3371 class="link link--text disclosure__link caption-large focus-inset" 3372 href="#" 3373 3374 data-value="BZ" 3375 id="Belize" 3376 > 3377 <span 3378 3379 class="visibility-hidden" 3380 3381 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3382</span> 3383 <span class="country">Belize</span> 3384 <span class="localization-form__currency motion-reduce"> 3385 BZD 3386 $</span> 3387 </a> 3388 </li><li class="disclosure__item" tabindex="-1"> 3389 <a 3390 class="link link--text disclosure__link caption-large focus-inset" 3391 href="#" 3392 3393 data-value="BJ" 3394 id="Benin" 3395 > 3396 <span 3397 3398 class="visibility-hidden" 3399 3400 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3401</span> 3402 <span class="country">Benin</span> 3403 <span class="localization-form__currency motion-reduce"> 3404 XOF 3405 Fr</span> 3406 </a> 3407 </li><li class="disclosure__item" tabindex="-1"> 3408 <a 3409 class="link link--text disclosure__link caption-large focus-inset" 3410 href="#" 3411 3412 data-value="BM" 3413 id="Bermuda" 3414 > 3415 <span 3416 3417 class="visibility-hidden" 3418 3419 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3420</span> 3421 <span class="country">Bermuda</span> 3422 <span class="localization-form__currency motion-reduce"> 3423 USD 3424 $</span> 3425 </a> 3426 </li><li class="disclosure__item" tabindex="-1"> 3427 <a 3428 class="link link--text disclosure__link caption-large focus-inset" 3429 href="#" 3430 3431 data-value="BT" 3432 id="Bhutan" 3433 > 3434 <span 3435 3436 class="visibility-hidden" 3437 3438 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3439</span> 3440 <span class="country">Bhutan</span> 3441 <span class="localization-form__currency motion-reduce"> 3442 EUR 3443 â¬</span> 3444 </a> 3445 </li><li class="disclosure__item" tabindex="-1"> 3446 <a 3447 class="link link--text disclosure__link caption-large focus-inset" 3448 href="#" 3449 3450 data-value="BO" 3451 id="Bolivia" 3452 > 3453 <span 3454 3455 class="visibility-hidden" 3456 3457 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
3457<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3458</span> 3459 <span class="country">Bolivia</span> 3460 <span class="localization-form__currency motion-reduce"> 3461 BOB 3462 Bs.</span> 3463 </a> 3464 </li><li class="disclosure__item" tabindex="-1"> 3465 <a 3466 class="link link--text disclosure__link caption-large focus-inset" 3467 href="#" 3468 3469 data-value="BA" 3470 id="Bosnia & Herzegovina" 3471 > 3472 <span 3473 3474 class="visibility-hidden" 3475 3476 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3477</span> 3478 <span class="country">Bosnia & Herzegovina</span> 3479 <span class="localization-form__currency motion-reduce"> 3480 BAM 3481 ÐÐ</span> 3482 </a> 3483 </li><li class="disclosure__item" tabindex="-1"> 3484 <a 3485 class="link link--text disclosure__link caption-large focus-inset" 3486 href="#" 3487 3488 data-value="BW" 3489 id="Botswana" 3490 > 3491 <span 3492 3493 class="visibility-hidden" 3494 3495 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3496</span> 3497 <span class="country">Botswana</span> 3498 <span class="localization-form__currency motion-reduce"> 3499 BWP 3500 P</span> 3501 </a> 3502 </li><li class="disclosure__item" tabindex="-1"> 3503 <a 3504 class="link link--text disclosure__link caption-large focus-inset" 3505 href="#" 3506 3507 data-value="BR" 3508 id="Brazil" 3509 > 3510 <span 3511 3512 class="visibility-hidden" 3513 3514 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3515</span> 3516 <span class="country">Brazil</span> 3517 <span class="localization-form__currency motion-reduce"> 3518 EUR 3519 â¬</span> 3520 </a> 3521 </li><li class="disclosure__item" tabindex="-1"> 3522 <a 3523 class="link link--text disclosure__link caption-large focus-inset" 3524 href="#" 3525 3526 data-value="IO" 3527 id="British Indian Ocean Territory" 3528 > 3529 <span 3530 3531 class="visibility-hidden" 3532 3533 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3534</span> 3535 <span class="country">British Indian Ocean Territory</span> 3536 <span class="localization-form__currency motion-reduce"> 3537 USD 3538 $</span> 3539 </a> 3540 </li><li class="disclosure__item" tabindex="-1"> 3541 <a 3542 class="link link--text disclosure__link caption-large focus-inset" 3543 href="#" 3544 3545 data-value="VG" 3546 id="British Virgin Islands" 3547 >
3548 <span 3549 3550 class="visibility-hidden" 3551 3552 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3553</span> 3554 <span class="country">British Virgin Islands</span> 3555 <span class="localization-form__currency motion-reduce"> 3556 USD 3557 $</span> 3558 </a> 3559 </li><li class="disclosure__item" tabindex="-1"> 3560 <a 3561 class="link link--text disclosure__link caption-large focus-inset" 3562 href="#" 3563 3564 data-value="BN" 3565 id="Brunei" 3566 > 3567 <span 3568 3569 class="visibility-hidden" 3570 3571 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3572</span> 3573 <span class="country">Brunei</span> 3574 <span class="localization-form__currency motion-reduce"> 3575 BND 3576 $</span> 3577 </a> 3578 </li><li class="disclosure__item" tabindex="-1"> 3579 <a 3580 class="link link--text disclosure__link caption-large focus-inset" 3581 href="#" 3582 3583 data-value="BG" 3584 id="Bulgaria" 3585 > 3586 <span 3587 3588 class="visibility-hidden" 3589 3590 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3591</span> 3592 <span class="country">Bulgaria</span> 3593 <span class="localization-form__currency motion-reduce"> 3594 EUR 3595 â¬</span> 3596 </a> 3597 </li><li class="disclosure__item" tabindex="-1"> 3598 <a 3599 class="link link--text disclosure__link caption-large focus-inset" 3600 href="#" 3601 3602 data-value="BF" 3603 id="Burkina Faso" 3604 > 3605 <span 3606 3607 class="visibility-hidden" 3608 3609 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3610</span> 3611 <span class="country">Burkina Faso</span> 3612 <span class="localization-form__currency motion-reduce"> 3613 XOF 3614 Fr</span> 3615 </a> 3616 </li><li class="disclosure__item" tabindex="-1"> 3617 <a 3618 class="link link--text disclosure__link caption-large focus-inset" 3619 href="#" 3620 3621 data-value="BI" 3622 id="Burundi" 3623 > 3624 <span 3625 3626 class="visibility-hidden" 3627 3628 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3629</span> 3630 <span class="country">Burundi</span> 3631 <span class="localization-form__currency motion-reduce"> 3632 BIF 3633 Fr</span> 3634 </a> 3635 </li><li class="disclosure__item" tabindex="-1"> 3636 <a 3637 class="link link--text disclosure__link caption-large focus-inset" 3638 href="#" 3639 3640 data-value="KH" 3641 id="Cambodia" 3642 >
3643 <span 3644 3645 class="visibility-hidden" 3646 3647 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3648</span> 3649 <span class="country">Cambodia</span> 3650 <span class="localization-form__currency motion-reduce"> 3651 KHR 3652 á</span> 3653 </a> 3654 </li><li class="disclosure__item" tabindex="-1"> 3655 <a 3656 class="link link--text disclosure__link caption-large focus-inset" 3657 href="#" 3658 3659 data-value="CM" 3660 id="Cameroon" 3661 > 3662 <span 3663 3664 class="visibility-hidden" 3665 3666 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3667</span> 3668 <span class="country">Cameroon</span> 3669 <span class="localization-form__currency motion-reduce"> 3670 XAF 3671 CFA</span> 3672 </a> 3673 </li><li class="disclosure__item" tabindex="-1"> 3674 <a 3675 class="link link--text disclosure__link caption-large focus-inset" 3676 href="#" 3677 3678 data-value="CA" 3679 id="Canada" 3680 > 3681 <span 3682 3683 class="visibility-hidden" 3684 3685 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3686</span> 3687 <span class="country">Canada</span> 3688 <span class="localization-form__currency motion-reduce"> 3689 CAD 3690 $</span> 3691 </a> 3692 </li><li class="disclosure__item" tabindex="-1"> 3693 <a 3694 class="link link--text disclosure__link caption-large focus-inset" 3695 href="#" 3696 3697 data-value="CV" 3698 id="Cape Verde" 3699 > 3700 <span 3701 3702 class="visibility-hidden" 3703 3704 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3705</span> 3706 <span class="country">Cape Verde</span> 3707 <span class="localization-form__currency motion-reduce"> 3708 CVE 3709 $</span> 3710 </a> 3711 </li><li class="disclosure__item" tabindex="-1"> 3712 <a 3713 class="link link--text disclosure__link caption-large focus-inset" 3714 href="#" 3715 3716 data-value="BQ" 3717 id="Caribbean Netherlands" 3718 > 3719 <span 3720 3721 class="visibility-hidden" 3722 3723 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3724</span> 3725 <span class="country">Caribbean Netherlands</span> 3726 <span class="localization-form__currency motion-reduce"> 3727 USD
3728 $</span> 3729 </a> 3730 </li><li class="disclosure__item" tabindex="-1"> 3731 <a 3732 class="link link--text disclosure__link caption-large focus-inset" 3733 href="#" 3734 3735 data-value="KY" 3736 id="Cayman Islands" 3737 > 3738 <span 3739 3740 class="visibility-hidden" 3741 3742 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3743</span> 3744 <span class="country">Cayman Islands</span> 3745 <span class="localization-form__currency motion-reduce"> 3746 KYD 3747 $</span> 3748 </a> 3749 </li><li class="disclosure__item" tabindex="-1"> 3750 <a 3751 class="link link--text disclosure__link caption-large focus-inset" 3752 href="#" 3753 3754 data-value="CF" 3755 id="Central African Republic" 3756 > 3757 <span 3758 3759 class="visibility-hidden" 3760 3761 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3762</span> 3763 <span class="country">Central African Republic</span> 3764 <span class="localization-form__currency motion-reduce"> 3765 XAF 3766 CFA</span> 3767 </a> 3768 </li><li class="disclosure__item" tabindex="-1"> 3769 <a 3770 class="link link--text disclosure__link caption-large focus-inset" 3771 href="#" 3772 3773 data-value="TD" 3774 id="Chad" 3775 > 3776 <span 3777 3778 class="visibility-hidden" 3779 3780 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3781</span> 3782 <span class="country">Chad</span> 3783 <span class="localization-form__currency motion-reduce"> 3784 XAF 3785 CFA</span> 3786 </a> 3787 </li><li class="disclosure__item" tabindex="-1"> 3788 <a 3789 class="link link--text disclosure__link caption-large focus-inset" 3790 href="#" 3791 3792 data-value="CL" 3793 id="Chile" 3794 > 3795 <span 3796 3797 class="visibility-hidden" 3798 3799 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3800</span> 3801 <span class="country">Chile</span> 3802 <span class="localization-form__currency motion-reduce"> 3803 EUR 3804 â¬</span> 3805 </a> 3806 </li><li class="disclosure__item" tabindex="-1"> 3807 <a 3808 class="link link--text disclosure__link caption-large focus-inset" 3809 href="#" 3810 3811 data-value="CN" 3812 id="China" 3813 > 3814 <span 3815 3816 class="visibility-hidden" 3817 3818 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
3818<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3819</span> 3820 <span class="country">China</span> 3821 <span class="localization-form__currency motion-reduce"> 3822 CNY 3823 Â¥</span> 3824 </a> 3825 </li><li class="disclosure__item" tabindex="-1"> 3826 <a 3827 class="link link--text disclosure__link caption-large focus-inset" 3828 href="#" 3829 3830 data-value="CX" 3831 id="Christmas Island" 3832 > 3833 <span 3834 3835 class="visibility-hidden" 3836 3837 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3838</span> 3839 <span class="country">Christmas Island</span> 3840 <span class="localization-form__currency motion-reduce"> 3841 AUD 3842 $</span> 3843 </a> 3844 </li><li class="disclosure__item" tabindex="-1"> 3845 <a 3846 class="link link--text disclosure__link caption-large focus-inset" 3847 href="#" 3848 3849 data-value="CC" 3850 id="Cocos (Keeling) Islands" 3851 > 3852 <span 3853 3854 class="visibility-hidden" 3855 3856 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3857</span> 3858 <span class="country">Cocos (Keeling) Islands</span> 3859 <span class="localization-form__currency motion-reduce"> 3860 AUD 3861 $</span> 3862 </a> 3863 </li><li class="disclosure__item" tabindex="-1"> 3864 <a 3865 class="link link--text disclosure__link caption-large focus-inset" 3866 href="#" 3867 3868 data-value="CO" 3869 id="Colombia" 3870 > 3871 <span 3872 3873 class="visibility-hidden" 3874 3875 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3876</span> 3877 <span class="country">Colombia</span> 3878 <span class="localization-form__currency motion-reduce"> 3879 EUR 3880 â¬</span> 3881 </a> 3882 </li><li class="disclosure__item" tabindex="-1"> 3883 <a 3884 class="link link--text disclosure__link caption-large focus-inset" 3885 href="#" 3886 3887 data-value="KM" 3888 id="Comoros" 3889 > 3890 <span 3891 3892 class="visibility-hidden" 3893 3894 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3895</span> 3896 <span class="country">Comoros</span> 3897 <span class="localization-form__currency motion-reduce"> 3898 KMF 3899 Fr</span> 3900 </a> 3901 </li><li class="disclosure__item" tabindex="-1"> 3902 <a 3903 class="link link--text disclosure__link caption-large focus-inset" 3904 href="#" 3905 3906 data-value="CG" 3907 id="Congo - Brazzaville" 3908 >
3909 <span 3910 3911 class="visibility-hidden" 3912 3913 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3914</span> 3915 <span class="country">Congo - Brazzaville</span> 3916 <span class="localization-form__currency motion-reduce"> 3917 XAF 3918 CFA</span> 3919 </a> 3920 </li><li class="disclosure__item" tabindex="-1"> 3921 <a 3922 class="link link--text disclosure__link caption-large focus-inset" 3923 href="#" 3924 3925 data-value="CD" 3926 id="Congo - Kinshasa" 3927 > 3928 <span 3929 3930 class="visibility-hidden" 3931 3932 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3933</span> 3934 <span class="country">Congo - Kinshasa</span> 3935 <span class="localization-form__currency motion-reduce"> 3936 CDF 3937 Fr</span> 3938 </a> 3939 </li><li class="disclosure__item" tabindex="-1"> 3940 <a 3941 class="link link--text disclosure__link caption-large focus-inset" 3942 href="#" 3943 3944 data-value="CK" 3945 id="Cook Islands" 3946 > 3947 <span 3948 3949 class="visibility-hidden" 3950 3951 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3952</span> 3953 <span class="country">Cook Islands</span> 3954 <span class="localization-form__currency motion-reduce"> 3955 NZD 3956 $</span> 3957 </a> 3958 </li><li class="disclosure__item" tabindex="-1"> 3959 <a 3960 class="link link--text disclosure__link caption-large focus-inset" 3961 href="#" 3962 3963 data-value="CR" 3964 id="Costa Rica" 3965 > 3966 <span 3967 3968 class="visibility-hidden" 3969 3970 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3971</span> 3972 <span class="country">Costa Rica</span> 3973 <span class="localization-form__currency motion-reduce"> 3974 CRC 3975 â¡</span> 3976 </a> 3977 </li><li class="disclosure__item" tabindex="-1"> 3978 <a 3979 class="link link--text disclosure__link caption-large focus-inset" 3980 href="#" 3981 3982 data-value="CI" 3983 id="Côte dâIvoire" 3984 > 3985 <span 3986 3987 class="visibility-hidden" 3988 3989 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 3990</span> 3991 <span class="country">Côte dâIvoire</span>
3992 <span class="localization-form__currency motion-reduce"> 3993 XOF 3994 Fr</span> 3995 </a> 3996 </li><li class="disclosure__item" tabindex="-1"> 3997 <a 3998 class="link link--text disclosure__link caption-large focus-inset" 3999 href="#" 4000 4001 data-value="HR" 4002 id="Croatia" 4003 > 4004 <span 4005 4006 class="visibility-hidden" 4007 4008 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4009</span> 4010 <span class="country">Croatia</span> 4011 <span class="localization-form__currency motion-reduce"> 4012 EUR 4013 â¬</span> 4014 </a> 4015 </li><li class="disclosure__item" tabindex="-1"> 4016 <a 4017 class="link link--text disclosure__link caption-large focus-inset" 4018 href="#" 4019 4020 data-value="CW" 4021 id="Curaçao" 4022 > 4023 <span 4024 4025 class="visibility-hidden" 4026 4027 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4028</span> 4029 <span class="country">Curaçao</span> 4030 <span class="localization-form__currency motion-reduce"> 4031 ANG 4032 Æ</span> 4033 </a> 4034 </li><li class="disclosure__item" tabindex="-1"> 4035 <a 4036 class="link link--text disclosure__link caption-large focus-inset" 4037 href="#" 4038 4039 data-value="CY" 4040 id="Cyprus" 4041 > 4042 <span 4043 4044 class="visibility-hidden" 4045 4046 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4047</span> 4048 <span class="country">Cyprus</span> 4049 <span class="localization-form__currency motion-reduce"> 4050 EUR 4051 â¬</span> 4052 </a> 4053 </li><li class="disclosure__item" tabindex="-1"> 4054 <a 4055 class="link link--text disclosure__link caption-large focus-inset" 4056 href="#" 4057 4058 data-value="CZ" 4059 id="Czechia" 4060 > 4061 <span 4062 4063 class="visibility-hidden" 4064 4065 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4066</span> 4067 <span class="country">Czechia</span> 4068 <span class="localization-form__currency motion-reduce"> 4069 CZK 4070 KÄ</span> 4071 </a> 4072 </li><li class="disclosure__item" tabindex="-1"> 4073 <a 4074 class="link link--text disclosure__link caption-large focus-inset" 4075 href="#" 4076 4077 data-value="DK" 4078 id="Denmark" 4079 > 4080 <span 4081 4082 class="visibility-hidden" 4083 4084 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
4084<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4085</span> 4086 <span class="country">Denmark</span> 4087 <span class="localization-form__currency motion-reduce"> 4088 DKK 4089 kr.</span> 4090 </a> 4091 </li><li class="disclosure__item" tabindex="-1"> 4092 <a 4093 class="link link--text disclosure__link caption-large focus-inset" 4094 href="#" 4095 4096 data-value="DJ" 4097 id="Djibouti" 4098 > 4099 <span 4100 4101 class="visibility-hidden" 4102 4103 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4104</span> 4105 <span class="country">Djibouti</span> 4106 <span class="localization-form__currency motion-reduce"> 4107 DJF 4108 Fdj</span> 4109 </a> 4110 </li><li class="disclosure__item" tabindex="-1"> 4111 <a 4112 class="link link--text disclosure__link caption-large focus-inset" 4113 href="#" 4114 4115 data-value="DM" 4116 id="Dominica" 4117 > 4118 <span 4119 4120 class="visibility-hidden" 4121 4122 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4123</span> 4124 <span class="country">Dominica</span> 4125 <span class="localization-form__currency motion-reduce"> 4126 XCD 4127 $</span> 4128 </a> 4129 </li><li class="disclosure__item" tabindex="-1"> 4130 <a 4131 class="link link--text disclosure__link caption-large focus-inset" 4132 href="#" 4133 4134 data-value="DO" 4135 id="Dominican Republic" 4136 > 4137 <span 4138 4139 class="visibility-hidden" 4140 4141 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4142</span> 4143 <span class="country">Dominican Republic</span> 4144 <span class="localization-form__currency motion-reduce"> 4145 DOP 4146 $</span> 4147 </a> 4148 </li><li class="disclosure__item" tabindex="-1"> 4149 <a 4150 class="link link--text disclosure__link caption-large focus-inset" 4151 href="#" 4152 4153 data-value="EC" 4154 id="Ecuador" 4155 > 4156 <span 4157 4158 class="visibility-hidden" 4159 4160 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4161</span> 4162 <span class="country">Ecuador</span> 4163 <span class="localization-form__currency motion-reduce"> 4164 USD 4165 $</span> 4166 </a> 4167 </li><li class="disclosure__item" tabindex="-1"> 4168 <a 4169 class="link link--text disclosure__link caption-large focus-inset" 4170 href="#" 4171 4172 data-value="EG" 4173 id="Egypt" 4174 >
4175 <span 4176 4177 class="visibility-hidden" 4178 4179 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4180</span> 4181 <span class="country">Egypt</span> 4182 <span class="localization-form__currency motion-reduce"> 4183 EGP 4184 ج.Ù </span> 4185 </a> 4186 </li><li class="disclosure__item" tabindex="-1"> 4187 <a 4188 class="link link--text disclosure__link caption-large focus-inset" 4189 href="#" 4190 4191 data-value="SV" 4192 id="El Salvador" 4193 > 4194 <span 4195 4196 class="visibility-hidden" 4197 4198 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4199</span> 4200 <span class="country">El Salvador</span> 4201 <span class="localization-form__currency motion-reduce"> 4202 USD 4203 $</span> 4204 </a> 4205 </li><li class="disclosure__item" tabindex="-1"> 4206 <a 4207 class="link link--text disclosure__link caption-large focus-inset" 4208 href="#" 4209 4210 data-value="GQ" 4211 id="Equatorial Guinea" 4212 > 4213 <span 4214 4215 class="visibility-hidden" 4216 4217 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4218</span> 4219 <span class="country">Equatorial Guinea</span> 4220 <span class="localization-form__currency motion-reduce"> 4221 XAF 4222 CFA</span> 4223 </a> 4224 </li><li class="disclosure__item" tabindex="-1"> 4225 <a 4226 class="link link--text disclosure__link caption-large focus-inset" 4227 href="#" 4228 4229 data-value="ER" 4230 id="Eritrea" 4231 > 4232 <span 4233 4234 class="visibility-hidden" 4235 4236 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4237</span> 4238 <span class="country">Eritrea</span> 4239 <span class="localization-form__currency motion-reduce"> 4240 EUR 4241 â¬</span> 4242 </a> 4243 </li><li class="disclosure__item" tabindex="-1"> 4244 <a 4245 class="link link--text disclosure__link caption-large focus-inset" 4246 href="#" 4247 4248 data-value="EE" 4249 id="Estonia" 4250 > 4251 <span 4252 4253 class="visibility-hidden" 4254 4255 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4256</span> 4257 <span class="country">Estonia</span> 4258 <span class="localization-form__currency motion-reduce"> 4259 EUR 4260 â¬</span> 4261 </a> 4262 </li><li class="disclosure__item" tabindex="-1"> 4263 <a 4264 class="link link--text disclosure__link caption-large focus-inset" 4265 href="#" 4266 4267 data-value="SZ" 4268 id="Eswatini" 4269 >
4270 <span 4271 4272 class="visibility-hidden" 4273 4274 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4275</span> 4276 <span class="country">Eswatini</span> 4277 <span class="localization-form__currency motion-reduce"> 4278 EUR 4279 â¬</span> 4280 </a> 4281 </li><li class="disclosure__item" tabindex="-1"> 4282 <a 4283 class="link link--text disclosure__link caption-large focus-inset" 4284 href="#" 4285 4286 data-value="ET" 4287 id="Ethiopia" 4288 > 4289 <span 4290 4291 class="visibility-hidden" 4292 4293 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4294</span> 4295 <span class="country">Ethiopia</span> 4296 <span class="localization-form__currency motion-reduce"> 4297 ETB 4298 Br</span> 4299 </a> 4300 </li><li class="disclosure__item" tabindex="-1"> 4301 <a 4302 class="link link--text disclosure__link caption-large focus-inset" 4303 href="#" 4304 4305 data-value="FK" 4306 id="Falkland Islands" 4307 > 4308 <span 4309 4310 class="visibility-hidden" 4311 4312 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4313</span> 4314 <span class="country">Falkland Islands</span> 4315 <span class="localization-form__currency motion-reduce"> 4316 FKP 4317 £</span> 4318 </a> 4319 </li><li class="disclosure__item" tabindex="-1"> 4320 <a 4321 class="link link--text disclosure__link caption-large focus-inset" 4322 href="#" 4323 4324 data-value="FO" 4325 id="Faroe Islands" 4326 > 4327 <span 4328 4329 class="visibility-hidden" 4330 4331 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4332</span> 4333 <span class="country">Faroe Islands</span> 4334 <span class="localization-form__currency motion-reduce"> 4335 DKK 4336 kr.</span> 4337 </a> 4338 </li><li class="disclosure__item" tabindex="-1"> 4339 <a 4340 class="link link--text disclosure__link caption-large focus-inset" 4341 href="#" 4342 4343 data-value="FJ" 4344 id="Fiji" 4345 > 4346 <span 4347 4348 class="visibility-hidden" 4349 4350 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4351</span> 4352 <span class="country">Fiji</span> 4353 <span class="localization-form__currency motion-reduce"> 4354 FJD
4355 $</span> 4356 </a> 4357 </li><li class="disclosure__item" tabindex="-1"> 4358 <a 4359 class="link link--text disclosure__link caption-large focus-inset" 4360 href="#" 4361 4362 data-value="FI" 4363 id="Finland" 4364 > 4365 <span 4366 4367 class="visibility-hidden" 4368 4369 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4370</span> 4371 <span class="country">Finland</span> 4372 <span class="localization-form__currency motion-reduce"> 4373 EUR 4374 â¬</span> 4375 </a> 4376 </li><li class="disclosure__item" tabindex="-1"> 4377 <a 4378 class="link link--text disclosure__link caption-large focus-inset" 4379 href="#" 4380 4381 data-value="FR" 4382 id="France" 4383 > 4384 <span 4385 4386 class="visibility-hidden" 4387 4388 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4389</span> 4390 <span class="country">France</span> 4391 <span class="localization-form__currency motion-reduce"> 4392 EUR 4393 â¬</span> 4394 </a> 4395 </li><li class="disclosure__item" tabindex="-1"> 4396 <a 4397 class="link link--text disclosure__link caption-large focus-inset" 4398 href="#" 4399 4400 data-value="GF" 4401 id="French Guiana" 4402 > 4403 <span 4404 4405 class="visibility-hidden" 4406 4407 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4408</span> 4409 <span class="country">French Guiana</span> 4410 <span class="localization-form__currency motion-reduce"> 4411 EUR 4412 â¬</span> 4413 </a> 4414 </li><li class="disclosure__item" tabindex="-1"> 4415 <a 4416 class="link link--text disclosure__link caption-large focus-inset" 4417 href="#" 4418 4419 data-value="PF" 4420 id="French Polynesia" 4421 > 4422 <span 4423 4424 class="visibility-hidden" 4425 4426 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4427</span> 4428 <span class="country">French Polynesia</span> 4429 <span class="localization-form__currency motion-reduce"> 4430 XPF 4431 Fr</span> 4432 </a> 4433 </li><li class="disclosure__item" tabindex="-1"> 4434 <a 4435 class="link link--text disclosure__link caption-large focus-inset" 4436 href="#" 4437 4438 data-value="TF" 4439 id="French Southern Territories" 4440 > 4441 <span 4442 4443 class="visibility-hidden" 4444 4445 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
4445<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4446</span> 4447 <span class="country">French Southern Territories</span> 4448 <span class="localization-form__currency motion-reduce"> 4449 EUR 4450 â¬</span> 4451 </a> 4452 </li><li class="disclosure__item" tabindex="-1"> 4453 <a 4454 class="link link--text disclosure__link caption-large focus-inset" 4455 href="#" 4456 4457 data-value="GA" 4458 id="Gabon" 4459 > 4460 <span 4461 4462 class="visibility-hidden" 4463 4464 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4465</span> 4466 <span class="country">Gabon</span> 4467 <span class="localization-form__currency motion-reduce"> 4468 XOF 4469 Fr</span> 4470 </a> 4471 </li><li class="disclosure__item" tabindex="-1"> 4472 <a 4473 class="link link--text disclosure__link caption-large focus-inset" 4474 href="#" 4475 4476 data-value="GM" 4477 id="Gambia" 4478 > 4479 <span 4480 4481 class="visibility-hidden" 4482 4483 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4484</span> 4485 <span class="country">Gambia</span> 4486 <span class="localization-form__currency motion-reduce"> 4487 GMD 4488 D</span> 4489 </a> 4490 </li><li class="disclosure__item" tabindex="-1"> 4491 <a 4492 class="link link--text disclosure__link caption-large focus-inset" 4493 href="#" 4494 4495 data-value="GE" 4496 id="Georgia" 4497 > 4498 <span 4499 4500 class="visibility-hidden" 4501 4502 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4503</span> 4504 <span class="country">Georgia</span> 4505 <span class="localization-form__currency motion-reduce"> 4506 EUR 4507 â¬</span> 4508 </a> 4509 </li><li class="disclosure__item" tabindex="-1"> 4510 <a 4511 class="link link--text disclosure__link caption-large focus-inset" 4512 href="#" 4513 4514 data-value="DE" 4515 id="Germany" 4516 > 4517 <span 4518 4519 class="visibility-hidden" 4520 4521 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4522</span> 4523 <span class="country">Germany</span> 4524 <span class="localization-form__currency motion-reduce"> 4525 EUR 4526 â¬</span> 4527 </a> 4528 </li><li class="disclosure__item" tabindex="-1"> 4529 <a 4530 class="link link--text disclosure__link caption-large focus-inset" 4531 href="#" 4532 4533 data-value="GH" 4534 id="Ghana" 4535 >
4536 <span 4537 4538 class="visibility-hidden" 4539 4540 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4541</span> 4542 <span class="country">Ghana</span> 4543 <span class="localization-form__currency motion-reduce"> 4544 EUR 4545 â¬</span> 4546 </a> 4547 </li><li class="disclosure__item" tabindex="-1"> 4548 <a 4549 class="link link--text disclosure__link caption-large focus-inset" 4550 href="#" 4551 4552 data-value="GI" 4553 id="Gibraltar" 4554 > 4555 <span 4556 4557 class="visibility-hidden" 4558 4559 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4560</span> 4561 <span class="country">Gibraltar</span> 4562 <span class="localization-form__currency motion-reduce"> 4563 GBP 4564 £</span> 4565 </a> 4566 </li><li class="disclosure__item" tabindex="-1"> 4567 <a 4568 class="link link--text disclosure__link caption-large focus-inset" 4569 href="#" 4570 4571 data-value="GR" 4572 id="Greece" 4573 > 4574 <span 4575 4576 class="visibility-hidden" 4577 4578 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4579</span> 4580 <span class="country">Greece</span> 4581 <span class="localization-form__currency motion-reduce"> 4582 EUR 4583 â¬</span> 4584 </a> 4585 </li><li class="disclosure__item" tabindex="-1"> 4586 <a 4587 class="link link--text disclosure__link caption-large focus-inset" 4588 href="#" 4589 4590 data-value="GL" 4591 id="Greenland" 4592 > 4593 <span 4594 4595 class="visibility-hidden" 4596 4597 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4598</span> 4599 <span class="country">Greenland</span> 4600 <span class="localization-form__currency motion-reduce"> 4601 DKK 4602 kr.</span> 4603 </a> 4604 </li><li class="disclosure__item" tabindex="-1"> 4605 <a 4606 class="link link--text disclosure__link caption-large focus-inset" 4607 href="#" 4608 4609 data-value="GD" 4610 id="Grenada" 4611 > 4612 <span 4613 4614 class="visibility-hidden" 4615 4616 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4617</span> 4618 <span class="country">Grenada</span> 4619 <span class="localization-form__currency motion-reduce"> 4620 XCD
4621 $</span> 4622 </a> 4623 </li><li class="disclosure__item" tabindex="-1"> 4624 <a 4625 class="link link--text disclosure__link caption-large focus-inset" 4626 href="#" 4627 4628 data-value="GP" 4629 id="Guadeloupe" 4630 > 4631 <span 4632 4633 class="visibility-hidden" 4634 4635 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4636</span> 4637 <span class="country">Guadeloupe</span> 4638 <span class="localization-form__currency motion-reduce"> 4639 EUR 4640 â¬</span> 4641 </a> 4642 </li><li class="disclosure__item" tabindex="-1"> 4643 <a 4644 class="link link--text disclosure__link caption-large focus-inset" 4645 href="#" 4646 4647 data-value="GT" 4648 id="Guatemala" 4649 > 4650 <span 4651 4652 class="visibility-hidden" 4653 4654 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4655</span> 4656 <span class="country">Guatemala</span> 4657 <span class="localization-form__currency motion-reduce"> 4658 GTQ 4659 Q</span> 4660 </a> 4661 </li><li class="disclosure__item" tabindex="-1"> 4662 <a 4663 class="link link--text disclosure__link caption-large focus-inset" 4664 href="#" 4665 4666 data-value="GG" 4667 id="Guernsey" 4668 > 4669 <span 4670 4671 class="visibility-hidden" 4672 4673 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4674</span> 4675 <span class="country">Guernsey</span> 4676 <span class="localization-form__currency motion-reduce"> 4677 GBP 4678 £</span> 4679 </a> 4680 </li><li class="disclosure__item" tabindex="-1"> 4681 <a 4682 class="link link--text disclosure__link caption-large focus-inset" 4683 href="#" 4684 4685 data-value="GN" 4686 id="Guinea" 4687 > 4688 <span 4689 4690 class="visibility-hidden" 4691 4692 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4693</span> 4694 <span class="country">Guinea</span> 4695 <span class="localization-form__currency motion-reduce"> 4696 GNF 4697 Fr</span> 4698 </a> 4699 </li><li class="disclosure__item" tabindex="-1"> 4700 <a 4701 class="link link--text disclosure__link caption-large focus-inset" 4702 href="#" 4703 4704 data-value="GW" 4705 id="Guinea-Bissau" 4706 > 4707 <span 4708 4709 class="visibility-hidden" 4710 4711 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4712</span>
4713 <span class="country">Guinea-Bissau</span> 4714 <span class="localization-form__currency motion-reduce"> 4715 XOF 4716 Fr</span> 4717 </a> 4718 </li><li class="disclosure__item" tabindex="-1"> 4719 <a 4720 class="link link--text disclosure__link caption-large focus-inset" 4721 href="#" 4722 4723 data-value="GY" 4724 id="Guyana" 4725 > 4726 <span 4727 4728 class="visibility-hidden" 4729 4730 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4731</span> 4732 <span class="country">Guyana</span> 4733 <span class="localization-form__currency motion-reduce"> 4734 GYD 4735 $</span> 4736 </a> 4737 </li><li class="disclosure__item" tabindex="-1"> 4738 <a 4739 class="link link--text disclosure__link caption-large focus-inset" 4740 href="#" 4741 4742 data-value="HT" 4743 id="Haiti" 4744 > 4745 <span 4746 4747 class="visibility-hidden" 4748 4749 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4750</span> 4751 <span class="country">Haiti</span> 4752 <span class="localization-form__currency motion-reduce"> 4753 EUR 4754 â¬</span> 4755 </a> 4756 </li><li class="disclosure__item" tabindex="-1"> 4757 <a 4758 class="link link--text disclosure__link caption-large focus-inset" 4759 href="#" 4760 4761 data-value="HN" 4762 id="Honduras" 4763 > 4764 <span 4765 4766 class="visibility-hidden" 4767 4768 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4769</span> 4770 <span class="country">Honduras</span> 4771 <span class="localization-form__currency motion-reduce"> 4772 HNL 4773 L</span> 4774 </a> 4775 </li><li class="disclosure__item" tabindex="-1"> 4776 <a 4777 class="link link--text disclosure__link caption-large focus-inset" 4778 href="#" 4779 4780 data-value="HK" 4781 id="Hong Kong SAR" 4782 > 4783 <span 4784 4785 class="visibility-hidden" 4786 4787 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4788</span> 4789 <span class="country">Hong Kong SAR</span> 4790 <span class="localization-form__currency motion-reduce"> 4791 HKD 4792 $</span> 4793 </a> 4794 </li><li class="disclosure__item" tabindex="-1"> 4795 <a 4796 class="link link--text disclosure__link caption-large focus-inset" 4797 href="#" 4798 4799 data-value="HU" 4800 id="Hungary" 4801 > 4802 <span 4803 4804 class="visibility-hidden" 4805 4806 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
4806<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4807</span> 4808 <span class="country">Hungary</span> 4809 <span class="localization-form__currency motion-reduce"> 4810 HUF 4811 Ft</span> 4812 </a> 4813 </li><li class="disclosure__item" tabindex="-1"> 4814 <a 4815 class="link link--text disclosure__link caption-large focus-inset" 4816 href="#" 4817 4818 data-value="IS" 4819 id="Iceland" 4820 > 4821 <span 4822 4823 class="visibility-hidden" 4824 4825 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4826</span> 4827 <span class="country">Iceland</span> 4828 <span class="localization-form__currency motion-reduce"> 4829 ISK 4830 kr</span> 4831 </a> 4832 </li><li class="disclosure__item" tabindex="-1"> 4833 <a 4834 class="link link--text disclosure__link caption-large focus-inset" 4835 href="#" 4836 4837 data-value="IN" 4838 id="India" 4839 > 4840 <span 4841 4842 class="visibility-hidden" 4843 4844 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4845</span> 4846 <span class="country">India</span> 4847 <span class="localization-form__currency motion-reduce"> 4848 INR 4849 â¹</span> 4850 </a> 4851 </li><li class="disclosure__item" tabindex="-1"> 4852 <a 4853 class="link link--text disclosure__link caption-large focus-inset" 4854 href="#" 4855 4856 data-value="ID" 4857 id="Indonesia" 4858 > 4859 <span 4860 4861 class="visibility-hidden" 4862 4863 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4864</span> 4865 <span class="country">Indonesia</span> 4866 <span class="localization-form__currency motion-reduce"> 4867 IDR 4868 Rp</span> 4869 </a> 4870 </li><li class="disclosure__item" tabindex="-1"> 4871 <a 4872 class="link link--text disclosure__link caption-large focus-inset" 4873 href="#" 4874 4875 data-value="IQ" 4876 id="Iraq" 4877 > 4878 <span 4879 4880 class="visibility-hidden" 4881 4882 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4883</span> 4884 <span class="country">Iraq</span> 4885 <span class="localization-form__currency motion-reduce"> 4886 EUR 4887 â¬</span> 4888 </a> 4889 </li><li class="disclosure__item" tabindex="-1"> 4890 <a 4891 class="link link--text disclosure__link caption-large focus-inset" 4892 href="#" 4893 4894 data-value="IE" 4895 id="Ireland" 4896 >
4897 <span 4898 4899 class="visibility-hidden" 4900 4901 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4902</span> 4903 <span class="country">Ireland</span> 4904 <span class="localization-form__currency motion-reduce"> 4905 EUR 4906 â¬</span> 4907 </a> 4908 </li><li class="disclosure__item" tabindex="-1"> 4909 <a 4910 class="link link--text disclosure__link caption-large focus-inset" 4911 href="#" 4912 4913 data-value="IM" 4914 id="Isle of Man" 4915 > 4916 <span 4917 4918 class="visibility-hidden" 4919 4920 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4921</span> 4922 <span class="country">Isle of Man</span> 4923 <span class="localization-form__currency motion-reduce"> 4924 GBP 4925 £</span> 4926 </a> 4927 </li><li class="disclosure__item" tabindex="-1"> 4928 <a 4929 class="link link--text disclosure__link caption-large focus-inset" 4930 href="#" 4931 4932 data-value="IL" 4933 id="Israel" 4934 > 4935 <span 4936 4937 class="visibility-hidden" 4938 4939 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4940</span> 4941 <span class="country">Israel</span> 4942 <span class="localization-form__currency motion-reduce"> 4943 ILS 4944 âª</span> 4945 </a> 4946 </li><li class="disclosure__item" tabindex="-1"> 4947 <a 4948 class="link link--text disclosure__link caption-large focus-inset" 4949 href="#" 4950 4951 data-value="IT" 4952 id="Italy" 4953 > 4954 <span 4955 4956 class="visibility-hidden" 4957 4958 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4959</span> 4960 <span class="country">Italy</span> 4961 <span class="localization-form__currency motion-reduce"> 4962 EUR 4963 â¬</span> 4964 </a> 4965 </li><li class="disclosure__item" tabindex="-1"> 4966 <a 4967 class="link link--text disclosure__link caption-large focus-inset" 4968 href="#" 4969 4970 data-value="JM" 4971 id="Jamaica" 4972 > 4973 <span 4974 4975 class="visibility-hidden" 4976 4977 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4978</span> 4979 <span class="country">Jamaica</span> 4980 <span class="localization-form__currency motion-reduce"> 4981 JMD
4982 $</span> 4983 </a> 4984 </li><li class="disclosure__item" tabindex="-1"> 4985 <a 4986 class="link link--text disclosure__link caption-large focus-inset" 4987 href="#" 4988 4989 data-value="JP" 4990 id="Japan" 4991 > 4992 <span 4993 4994 class="visibility-hidden" 4995 4996 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 4997</span> 4998 <span class="country">Japan</span> 4999 <span class="localization-form__currency motion-reduce"> 5000 JPY 5001 Â¥</span> 5002 </a> 5003 </li><li class="disclosure__item" tabindex="-1"> 5004 <a 5005 class="link link--text disclosure__link caption-large focus-inset" 5006 href="#" 5007 5008 data-value="JE" 5009 id="Jersey" 5010 > 5011 <span 5012 5013 class="visibility-hidden" 5014 5015 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5016</span> 5017 <span class="country">Jersey</span> 5018 <span class="localization-form__currency motion-reduce"> 5019 EUR 5020 â¬</span> 5021 </a> 5022 </li><li class="disclosure__item" tabindex="-1"> 5023 <a 5024 class="link link--text disclosure__link caption-large focus-inset" 5025 href="#" 5026 5027 data-value="JO" 5028 id="Jordan" 5029 > 5030 <span 5031 5032 class="visibility-hidden" 5033 5034 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5035</span> 5036 <span class="country">Jordan</span> 5037 <span class="localization-form__currency motion-reduce"> 5038 EUR 5039 â¬</span> 5040 </a> 5041 </li><li class="disclosure__item" tabindex="-1"> 5042 <a 5043 class="link link--text disclosure__link caption-large focus-inset" 5044 href="#" 5045 5046 data-value="KZ" 5047 id="Kazakhstan" 5048 > 5049 <span 5050 5051 class="visibility-hidden" 5052 5053 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5054</span> 5055 <span class="country">Kazakhstan</span> 5056 <span class="localization-form__currency motion-reduce"> 5057 KZT 5058 â¸</span> 5059 </a> 5060 </li><li class="disclosure__item" tabindex="-1"> 5061 <a 5062 class="link link--text disclosure__link caption-large focus-inset" 5063 href="#" 5064 5065 data-value="KE" 5066 id="Kenya" 5067 > 5068 <span 5069 5070 class="visibility-hidden" 5071 5072 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5073</span>
5074 <span class="country">Kenya</span> 5075 <span class="localization-form__currency motion-reduce"> 5076 KES 5077 KSh</span> 5078 </a> 5079 </li><li class="disclosure__item" tabindex="-1"> 5080 <a 5081 class="link link--text disclosure__link caption-large focus-inset" 5082 href="#" 5083 5084 data-value="KI" 5085 id="Kiribati" 5086 > 5087 <span 5088 5089 class="visibility-hidden" 5090 5091 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5092</span> 5093 <span class="country">Kiribati</span> 5094 <span class="localization-form__currency motion-reduce"> 5095 EUR 5096 â¬</span> 5097 </a> 5098 </li><li class="disclosure__item" tabindex="-1"> 5099 <a 5100 class="link link--text disclosure__link caption-large focus-inset" 5101 href="#" 5102 5103 data-value="XK" 5104 id="Kosovo" 5105 > 5106 <span 5107 5108 class="visibility-hidden" 5109 5110 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5111</span> 5112 <span class="country">Kosovo</span> 5113 <span class="localization-form__currency motion-reduce"> 5114 EUR 5115 â¬</span> 5116 </a> 5117 </li><li class="disclosure__item" tabindex="-1"> 5118 <a 5119 class="link link--text disclosure__link caption-large focus-inset" 5120 href="#" 5121 5122 data-value="KW" 5123 id="Kuwait" 5124 > 5125 <span 5126 5127 class="visibility-hidden" 5128 5129 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5130</span> 5131 <span class="country">Kuwait</span> 5132 <span class="localization-form__currency motion-reduce"> 5133 EUR 5134 â¬</span> 5135 </a> 5136 </li><li class="disclosure__item" tabindex="-1"> 5137 <a 5138 class="link link--text disclosure__link caption-large focus-inset" 5139 href="#" 5140 5141 data-value="KG" 5142 id="Kyrgyzstan" 5143 > 5144 <span 5145 5146 class="visibility-hidden" 5147 5148 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5149</span> 5150 <span class="country">Kyrgyzstan</span> 5151 <span class="localization-form__currency motion-reduce"> 5152 KGS 5153 som</span> 5154 </a> 5155 </li><li class="disclosure__item" tabindex="-1"> 5156 <a 5157 class="link link--text disclosure__link caption-large focus-inset" 5158 href="#" 5159 5160 data-value="LA" 5161 id="Laos" 5162 > 5163 <span 5164 5165 class="visibility-hidden" 5166 5167 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
5167<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5168</span> 5169 <span class="country">Laos</span> 5170 <span class="localization-form__currency motion-reduce"> 5171 LAK 5172 â</span> 5173 </a> 5174 </li><li class="disclosure__item" tabindex="-1"> 5175 <a 5176 class="link link--text disclosure__link caption-large focus-inset" 5177 href="#" 5178 5179 data-value="LV" 5180 id="Latvia" 5181 > 5182 <span 5183 5184 class="visibility-hidden" 5185 5186 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5187</span> 5188 <span class="country">Latvia</span> 5189 <span class="localization-form__currency motion-reduce"> 5190 EUR 5191 â¬</span> 5192 </a> 5193 </li><li class="disclosure__item" tabindex="-1"> 5194 <a 5195 class="link link--text disclosure__link caption-large focus-inset" 5196 href="#" 5197 5198 data-value="LB" 5199 id="Lebanon" 5200 > 5201 <span 5202 5203 class="visibility-hidden" 5204 5205 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5206</span> 5207 <span class="country">Lebanon</span> 5208 <span class="localization-form__currency motion-reduce"> 5209 LBP 5210 Ù.Ù</span> 5211 </a> 5212 </li><li class="disclosure__item" tabindex="-1"> 5213 <a 5214 class="link link--text disclosure__link caption-large focus-inset" 5215 href="#" 5216 5217 data-value="LS" 5218 id="Lesotho" 5219 > 5220 <span 5221 5222 class="visibility-hidden" 5223 5224 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5225</span> 5226 <span class="country">Lesotho</span> 5227 <span class="localization-form__currency motion-reduce"> 5228 EUR 5229 â¬</span> 5230 </a> 5231 </li><li class="disclosure__item" tabindex="-1"> 5232 <a 5233 class="link link--text disclosure__link caption-large focus-inset" 5234 href="#" 5235 5236 data-value="LR" 5237 id="Liberia" 5238 > 5239 <span 5240 5241 class="visibility-hidden" 5242 5243 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5244</span> 5245 <span class="country">Liberia</span> 5246 <span class="localization-form__currency motion-reduce"> 5247 EUR 5248 â¬</span> 5249 </a> 5250 </li><li class="disclosure__item" tabindex="-1"> 5251 <a 5252 class="link link--text disclosure__link caption-large focus-inset" 5253 href="#" 5254 5255 data-value="LY" 5256 id="Libya" 5257 >
5258 <span 5259 5260 class="visibility-hidden" 5261 5262 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5263</span> 5264 <span class="country">Libya</span> 5265 <span class="localization-form__currency motion-reduce"> 5266 EUR 5267 â¬</span> 5268 </a> 5269 </li><li class="disclosure__item" tabindex="-1"> 5270 <a 5271 class="link link--text disclosure__link caption-large focus-inset" 5272 href="#" 5273 5274 data-value="LI" 5275 id="Liechtenstein" 5276 > 5277 <span 5278 5279 class="visibility-hidden" 5280 5281 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5282</span> 5283 <span class="country">Liechtenstein</span> 5284 <span class="localization-form__currency motion-reduce"> 5285 CHF 5286 CHF</span> 5287 </a> 5288 </li><li class="disclosure__item" tabindex="-1"> 5289 <a 5290 class="link link--text disclosure__link caption-large focus-inset" 5291 href="#" 5292 5293 data-value="LT" 5294 id="Lithuania" 5295 > 5296 <span 5297 5298 class="visibility-hidden" 5299 5300 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5301</span> 5302 <span class="country">Lithuania</span> 5303 <span class="localization-form__currency motion-reduce"> 5304 EUR 5305 â¬</span> 5306 </a> 5307 </li><li class="disclosure__item" tabindex="-1"> 5308 <a 5309 class="link link--text disclosure__link caption-large focus-inset" 5310 href="#" 5311 5312 data-value="LU" 5313 id="Luxembourg" 5314 > 5315 <span 5316 5317 class="visibility-hidden" 5318 5319 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5320</span> 5321 <span class="country">Luxembourg</span> 5322 <span class="localization-form__currency motion-reduce"> 5323 EUR 5324 â¬</span> 5325 </a> 5326 </li><li class="disclosure__item" tabindex="-1"> 5327 <a 5328 class="link link--text disclosure__link caption-large focus-inset" 5329 href="#" 5330 5331 data-value="MO" 5332 id="Macao SAR" 5333 > 5334 <span 5335 5336 class="visibility-hidden" 5337 5338 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5339</span> 5340 <span class="country">Macao SAR</span> 5341 <span class="localization-form__currency motion-reduce"> 5342 MOP 5343 P</span> 5344 </a> 5345 </li><li class="disclosure__item" tabindex="-1"> 5346 <a 5347 class="link link--text disclosure__link caption-large focus-inset" 5348 href="#" 5349 5350 data-value="MG" 5351 id="Madagascar" 5352 >
5353 <span 5354 5355 class="visibility-hidden" 5356 5357 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5358</span> 5359 <span class="country">Madagascar</span> 5360 <span class="localization-form__currency motion-reduce"> 5361 EUR 5362 â¬</span> 5363 </a> 5364 </li><li class="disclosure__item" tabindex="-1"> 5365 <a 5366 class="link link--text disclosure__link caption-large focus-inset" 5367 href="#" 5368 5369 data-value="MW" 5370 id="Malawi" 5371 > 5372 <span 5373 5374 class="visibility-hidden" 5375 5376 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5377</span> 5378 <span class="country">Malawi</span> 5379 <span class="localization-form__currency motion-reduce"> 5380 MWK 5381 MK</span> 5382 </a> 5383 </li><li class="disclosure__item" tabindex="-1"> 5384 <a 5385 class="link link--text disclosure__link caption-large focus-inset" 5386 href="#" 5387 5388 data-value="MY" 5389 id="Malaysia" 5390 > 5391 <span 5392 5393 class="visibility-hidden" 5394 5395 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5396</span> 5397 <span class="country">Malaysia</span> 5398 <span class="localization-form__currency motion-reduce"> 5399 MYR 5400 RM</span> 5401 </a> 5402 </li><li class="disclosure__item" tabindex="-1"> 5403 <a 5404 class="link link--text disclosure__link caption-large focus-inset" 5405 href="#" 5406 5407 data-value="MV" 5408 id="Maldives" 5409 > 5410 <span 5411 5412 class="visibility-hidden" 5413 5414 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5415</span> 5416 <span class="country">Maldives</span> 5417 <span class="localization-form__currency motion-reduce"> 5418 MVR 5419 MVR</span> 5420 </a> 5421 </li><li class="disclosure__item" tabindex="-1"> 5422 <a 5423 class="link link--text disclosure__link caption-large focus-inset" 5424 href="#" 5425 5426 data-value="ML" 5427 id="Mali" 5428 > 5429 <span 5430 5431 class="visibility-hidden" 5432 5433 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5434</span> 5435 <span class="country">Mali</span> 5436 <span class="localization-form__currency motion-reduce"> 5437 XOF 5438 Fr</span> 5439 </a> 5440 </li><li class="disclosure__item" tabindex="-1"> 5441 <a 5442 class="link link--text disclosure__link caption-large focus-inset" 5443 href="#" 5444 5445 data-value="MT" 5446 id="Malta" 5447 >
5448 <span 5449 5450 class="visibility-hidden" 5451 5452 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5453</span> 5454 <span class="country">Malta</span> 5455 <span class="localization-form__currency motion-reduce"> 5456 EUR 5457 â¬</span> 5458 </a> 5459 </li><li class="disclosure__item" tabindex="-1"> 5460 <a 5461 class="link link--text disclosure__link caption-large focus-inset" 5462 href="#" 5463 5464 data-value="MQ" 5465 id="Martinique" 5466 > 5467 <span 5468 5469 class="visibility-hidden" 5470 5471 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5472</span> 5473 <span class="country">Martinique</span> 5474 <span class="localization-form__currency motion-reduce"> 5475 EUR 5476 â¬</span> 5477 </a> 5478 </li><li class="disclosure__item" tabindex="-1"> 5479 <a 5480 class="link link--text disclosure__link caption-large focus-inset" 5481 href="#" 5482 5483 data-value="MR" 5484 id="Mauritania" 5485 > 5486 <span 5487 5488 class="visibility-hidden" 5489 5490 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5491</span> 5492 <span class="country">Mauritania</span> 5493 <span class="localization-form__currency motion-reduce"> 5494 EUR 5495 â¬</span> 5496 </a> 5497 </li><li class="disclosure__item" tabindex="-1"> 5498 <a 5499 class="link link--text disclosure__link caption-large focus-inset" 5500 href="#" 5501 5502 data-value="MU" 5503 id="Mauritius" 5504 > 5505 <span 5506 5507 class="visibility-hidden" 5508 5509 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5510</span> 5511 <span class="country">Mauritius</span> 5512 <span class="localization-form__currency motion-reduce"> 5513 MUR 5514 â¨</span> 5515 </a> 5516 </li><li class="disclosure__item" tabindex="-1"> 5517 <a 5518 class="link link--text disclosure__link caption-large focus-inset" 5519 href="#" 5520 5521 data-value="YT" 5522 id="Mayotte" 5523 > 5524 <span 5525 5526 class="visibility-hidden" 5527 5528 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5529</span> 5530 <span class="country">Mayotte</span> 5531 <span class="localization-form__currency motion-reduce"> 5532 EUR 5533 â¬</span> 5534 </a> 5535 </li><li class="disclosure__item" tabindex="-1"> 5536 <a 5537 class="link link--text disclosure__link caption-large focus-inset" 5538 href="#" 5539 5540 data-value="MX" 5541 id="Mexico" 5542 >
5543 <span 5544 5545 class="visibility-hidden" 5546 5547 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5548</span> 5549 <span class="country">Mexico</span> 5550 <span class="localization-form__currency motion-reduce"> 5551 EUR 5552 â¬</span> 5553 </a> 5554 </li><li class="disclosure__item" tabindex="-1"> 5555 <a 5556 class="link link--text disclosure__link caption-large focus-inset" 5557 href="#" 5558 5559 data-value="MD" 5560 id="Moldova" 5561 > 5562 <span 5563 5564 class="visibility-hidden" 5565 5566 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5567</span> 5568 <span class="country">Moldova</span> 5569 <span class="localization-form__currency motion-reduce"> 5570 MDL 5571 L</span> 5572 </a> 5573 </li><li class="disclosure__item" tabindex="-1"> 5574 <a 5575 class="link link--text disclosure__link caption-large focus-inset" 5576 href="#" 5577 5578 data-value="MC" 5579 id="Monaco" 5580 > 5581 <span 5582 5583 class="visibility-hidden" 5584 5585 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5586</span> 5587 <span class="country">Monaco</span> 5588 <span class="localization-form__currency motion-reduce"> 5589 EUR 5590 â¬</span> 5591 </a> 5592 </li><li class="disclosure__item" tabindex="-1"> 5593 <a 5594 class="link link--text disclosure__link caption-large focus-inset" 5595 href="#" 5596 5597 data-value="MN" 5598 id="Mongolia" 5599 > 5600 <span 5601 5602 class="visibility-hidden" 5603 5604 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5605</span> 5606 <span class="country">Mongolia</span> 5607 <span class="localization-form__currency motion-reduce"> 5608 MNT 5609 â®</span> 5610 </a> 5611 </li><li class="disclosure__item" tabindex="-1"> 5612 <a 5613 class="link link--text disclosure__link caption-large focus-inset" 5614 href="#" 5615 5616 data-value="ME" 5617 id="Montenegro" 5618 > 5619 <span 5620 5621 class="visibility-hidden" 5622 5623 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5624</span> 5625 <span class="country">Montenegro</span> 5626 <span class="localization-form__currency motion-reduce"> 5627 EUR 5628 â¬</span> 5629 </a> 5630 </li><li class="disclosure__item" tabindex="-1"> 5631 <a 5632 class="link link--text disclosure__link caption-large focus-inset" 5633 href="#" 5634 5635 data-value="MS" 5636 id="Montserrat" 5637 >
5638 <span 5639 5640 class="visibility-hidden" 5641 5642 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5643</span> 5644 <span class="country">Montserrat</span> 5645 <span class="localization-form__currency motion-reduce"> 5646 XCD 5647 $</span> 5648 </a> 5649 </li><li class="disclosure__item" tabindex="-1"> 5650 <a 5651 class="link link--text disclosure__link caption-large focus-inset" 5652 href="#" 5653 5654 data-value="MA" 5655 id="Morocco" 5656 > 5657 <span 5658 5659 class="visibility-hidden" 5660 5661 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5662</span> 5663 <span class="country">Morocco</span> 5664 <span class="localization-form__currency motion-reduce"> 5665 MAD 5666 د.Ù .</span> 5667 </a> 5668 </li><li class="disclosure__item" tabindex="-1"> 5669 <a 5670 class="link link--text disclosure__link caption-large focus-inset" 5671 href="#" 5672 5673 data-value="MZ" 5674 id="Mozambique" 5675 > 5676 <span 5677 5678 class="visibility-hidden" 5679 5680 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5681</span> 5682 <span class="country">Mozambique</span> 5683 <span class="localization-form__currency motion-reduce"> 5684 EUR 5685 â¬</span> 5686 </a> 5687 </li><li class="disclosure__item" tabindex="-1"> 5688 <a 5689 class="link link--text disclosure__link caption-large focus-inset" 5690 href="#" 5691 5692 data-value="MM" 5693 id="Myanmar (Burma)" 5694 > 5695 <span 5696 5697 class="visibility-hidden" 5698 5699 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5700</span> 5701 <span class="country">Myanmar (Burma)</span> 5702 <span class="localization-form__currency motion-reduce"> 5703 MMK 5704 K</span> 5705 </a> 5706 </li><li class="disclosure__item" tabindex="-1"> 5707 <a 5708 class="link link--text disclosure__link caption-large focus-inset" 5709 href="#" 5710 5711 data-value="NA" 5712 id="Namibia" 5713 > 5714 <span 5715 5716 class="visibility-hidden" 5717 5718 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5719</span> 5720 <span class="country">Namibia</span> 5721 <span class="localization-form__currency motion-reduce"> 5722 EUR 5723 â¬</span> 5724 </a> 5725 </li><li class="disclosure__item" tabindex="-1"> 5726 <a 5727 class="link link--text disclosure__link caption-large focus-inset" 5728 href="#" 5729 5730 data-value="NR" 5731 id="Nauru" 5732 >
5733 <span 5734 5735 class="visibility-hidden" 5736 5737 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5738</span> 5739 <span class="country">Nauru</span> 5740 <span class="localization-form__currency motion-reduce"> 5741 AUD 5742 $</span> 5743 </a> 5744 </li><li class="disclosure__item" tabindex="-1"> 5745 <a 5746 class="link link--text disclosure__link caption-large focus-inset" 5747 href="#" 5748 5749 data-value="NP" 5750 id="Nepal" 5751 > 5752 <span 5753 5754 class="visibility-hidden" 5755 5756 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5757</span> 5758 <span class="country">Nepal</span> 5759 <span class="localization-form__currency motion-reduce"> 5760 NPR 5761 Rs.</span> 5762 </a> 5763 </li><li class="disclosure__item" tabindex="-1"> 5764 <a 5765 class="link link--text disclosure__link caption-large focus-inset" 5766 href="#" 5767 5768 data-value="NL" 5769 id="Netherlands" 5770 > 5771 <span 5772 5773 class="visibility-hidden" 5774 5775 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5776</span> 5777 <span class="country">Netherlands</span> 5778 <span class="localization-form__currency motion-reduce"> 5779 EUR 5780 â¬</span> 5781 </a> 5782 </li><li class="disclosure__item" tabindex="-1"> 5783 <a 5784 class="link link--text disclosure__link caption-large focus-inset" 5785 href="#" 5786 5787 data-value="NC" 5788 id="New Caledonia" 5789 > 5790 <span 5791 5792 class="visibility-hidden" 5793 5794 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5795</span> 5796 <span class="country">New Caledonia</span> 5797 <span class="localization-form__currency motion-reduce"> 5798 XPF 5799 Fr</span> 5800 </a> 5801 </li><li class="disclosure__item" tabindex="-1"> 5802 <a 5803 class="link link--text disclosure__link caption-large focus-inset" 5804 href="#" 5805 5806 data-value="NZ" 5807 id="New Zealand" 5808 > 5809 <span 5810 5811 class="visibility-hidden" 5812 5813 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5814</span> 5815 <span class="country">New Zealand</span> 5816 <span class="localization-form__currency motion-reduce"> 5817 NZD
5818 $</span> 5819 </a> 5820 </li><li class="disclosure__item" tabindex="-1"> 5821 <a 5822 class="link link--text disclosure__link caption-large focus-inset" 5823 href="#" 5824 5825 data-value="NI" 5826 id="Nicaragua" 5827 > 5828 <span 5829 5830 class="visibility-hidden" 5831 5832 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5833</span> 5834 <span class="country">Nicaragua</span> 5835 <span class="localization-form__currency motion-reduce"> 5836 NIO 5837 C$</span> 5838 </a> 5839 </li><li class="disclosure__item" tabindex="-1"> 5840 <a 5841 class="link link--text disclosure__link caption-large focus-inset" 5842 href="#" 5843 5844 data-value="NE" 5845 id="Niger" 5846 > 5847 <span 5848 5849 class="visibility-hidden" 5850 5851 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5852</span> 5853 <span class="country">Niger</span> 5854 <span class="localization-form__currency motion-reduce"> 5855 XOF 5856 Fr</span> 5857 </a> 5858 </li><li class="disclosure__item" tabindex="-1"> 5859 <a 5860 class="link link--text disclosure__link caption-large focus-inset" 5861 href="#" 5862 5863 data-value="NG" 5864 id="Nigeria" 5865 > 5866 <span 5867 5868 class="visibility-hidden" 5869 5870 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5871</span> 5872 <span class="country">Nigeria</span> 5873 <span class="localization-form__currency motion-reduce"> 5874 NGN 5875 â¦</span> 5876 </a> 5877 </li><li class="disclosure__item" tabindex="-1"> 5878 <a 5879 class="link link--text disclosure__link caption-large focus-inset" 5880 href="#" 5881 5882 data-value="NU" 5883 id="Niue" 5884 > 5885 <span 5886 5887 class="visibility-hidden" 5888 5889 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5890</span> 5891 <span class="country">Niue</span> 5892 <span class="localization-form__currency motion-reduce"> 5893 NZD 5894 $</span> 5895 </a> 5896 </li><li class="disclosure__item" tabindex="-1"> 5897 <a 5898 class="link link--text disclosure__link caption-large focus-inset" 5899 href="#" 5900 5901 data-value="NF" 5902 id="Norfolk Island" 5903 > 5904 <span 5905 5906 class="visibility-hidden" 5907 5908 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5909</span>
5910 <span class="country">Norfolk Island</span> 5911 <span class="localization-form__currency motion-reduce"> 5912 AUD 5913 $</span> 5914 </a> 5915 </li><li class="disclosure__item" tabindex="-1"> 5916 <a 5917 class="link link--text disclosure__link caption-large focus-inset" 5918 href="#" 5919 5920 data-value="MK" 5921 id="North Macedonia" 5922 > 5923 <span 5924 5925 class="visibility-hidden" 5926 5927 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5928</span> 5929 <span class="country">North Macedonia</span> 5930 <span class="localization-form__currency motion-reduce"> 5931 MKD 5932 ден</span> 5933 </a> 5934 </li><li class="disclosure__item" tabindex="-1"> 5935 <a 5936 class="link link--text disclosure__link caption-large focus-inset" 5937 href="#" 5938 5939 data-value="NO" 5940 id="Norway" 5941 > 5942 <span 5943 5944 class="visibility-hidden" 5945 5946 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5947</span> 5948 <span class="country">Norway</span> 5949 <span class="localization-form__currency motion-reduce"> 5950 EUR 5951 â¬</span> 5952 </a> 5953 </li><li class="disclosure__item" tabindex="-1"> 5954 <a 5955 class="link link--text disclosure__link caption-large focus-inset" 5956 href="#" 5957 5958 data-value="OM" 5959 id="Oman" 5960 > 5961 <span 5962 5963 class="visibility-hidden" 5964 5965 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5966</span> 5967 <span class="country">Oman</span> 5968 <span class="localization-form__currency motion-reduce"> 5969 EUR 5970 â¬</span> 5971 </a> 5972 </li><li class="disclosure__item" tabindex="-1"> 5973 <a 5974 class="link link--text disclosure__link caption-large focus-inset" 5975 href="#" 5976 5977 data-value="PK" 5978 id="Pakistan" 5979 > 5980 <span 5981 5982 class="visibility-hidden" 5983 5984 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 5985</span> 5986 <span class="country">Pakistan</span> 5987 <span class="localization-form__currency motion-reduce"> 5988 PKR 5989 â¨</span> 5990 </a> 5991 </li><li class="disclosure__item" tabindex="-1"> 5992 <a 5993 class="link link--text disclosure__link caption-large focus-inset" 5994 href="#" 5995 5996 data-value="PS" 5997 id="Palestinian Territories" 5998 > 5999 <span 6000 6001 class="visibility-hidden" 6002 6003 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
6003<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6004</span> 6005 <span class="country">Palestinian Territories</span> 6006 <span class="localization-form__currency motion-reduce"> 6007 ILS 6008 âª</span> 6009 </a> 6010 </li><li class="disclosure__item" tabindex="-1"> 6011 <a 6012 class="link link--text disclosure__link caption-large focus-inset" 6013 href="#" 6014 6015 data-value="PA" 6016 id="Panama" 6017 > 6018 <span 6019 6020 class="visibility-hidden" 6021 6022 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6023</span> 6024 <span class="country">Panama</span> 6025 <span class="localization-form__currency motion-reduce"> 6026 USD 6027 $</span> 6028 </a> 6029 </li><li class="disclosure__item" tabindex="-1"> 6030 <a 6031 class="link link--text disclosure__link caption-large focus-inset" 6032 href="#" 6033 6034 data-value="PG" 6035 id="Papua New Guinea" 6036 > 6037 <span 6038 6039 class="visibility-hidden" 6040 6041 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6042</span> 6043 <span class="country">Papua New Guinea</span> 6044 <span class="localization-form__currency motion-reduce"> 6045 PGK 6046 K</span> 6047 </a> 6048 </li><li class="disclosure__item" tabindex="-1"> 6049 <a 6050 class="link link--text disclosure__link caption-large focus-inset" 6051 href="#" 6052 6053 data-value="PY" 6054 id="Paraguay" 6055 > 6056 <span 6057 6058 class="visibility-hidden" 6059 6060 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6061</span> 6062 <span class="country">Paraguay</span> 6063 <span class="localization-form__currency motion-reduce"> 6064 PYG 6065 â²</span> 6066 </a> 6067 </li><li class="disclosure__item" tabindex="-1"> 6068 <a 6069 class="link link--text disclosure__link caption-large focus-inset" 6070 href="#" 6071 6072 data-value="PE" 6073 id="Peru" 6074 > 6075 <span 6076 6077 class="visibility-hidden" 6078 6079 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6080</span> 6081 <span class="country">Peru</span> 6082 <span class="localization-form__currency motion-reduce"> 6083 PEN 6084 S/</span> 6085 </a> 6086 </li><li class="disclosure__item" tabindex="-1"> 6087 <a 6088 class="link link--text disclosure__link caption-large focus-inset" 6089 href="#" 6090 6091 data-value="PH" 6092 id="Philippines" 6093 >
6094 <span 6095 6096 class="visibility-hidden" 6097 6098 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6099</span> 6100 <span class="country">Philippines</span> 6101 <span class="localization-form__currency motion-reduce"> 6102 PHP 6103 â±</span> 6104 </a> 6105 </li><li class="disclosure__item" tabindex="-1"> 6106 <a 6107 class="link link--text disclosure__link caption-large focus-inset" 6108 href="#" 6109 6110 data-value="PN" 6111 id="Pitcairn Islands" 6112 > 6113 <span 6114 6115 class="visibility-hidden" 6116 6117 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6118</span> 6119 <span class="country">Pitcairn Islands</span> 6120 <span class="localization-form__currency motion-reduce"> 6121 NZD 6122 $</span> 6123 </a> 6124 </li><li class="disclosure__item" tabindex="-1"> 6125 <a 6126 class="link link--text disclosure__link caption-large focus-inset" 6127 href="#" 6128 6129 data-value="PL" 6130 id="Poland" 6131 > 6132 <span 6133 6134 class="visibility-hidden" 6135 6136 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6137</span> 6138 <span class="country">Poland</span> 6139 <span class="localization-form__currency motion-reduce"> 6140 PLN 6141 zÅ</span> 6142 </a> 6143 </li><li class="disclosure__item" tabindex="-1"> 6144 <a 6145 class="link link--text disclosure__link caption-large focus-inset" 6146 href="#" 6147 6148 data-value="PT" 6149 id="Portugal" 6150 > 6151 <span 6152 6153 class="visibility-hidden" 6154 6155 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6156</span> 6157 <span class="country">Portugal</span> 6158 <span class="localization-form__currency motion-reduce"> 6159 EUR 6160 â¬</span> 6161 </a> 6162 </li><li class="disclosure__item" tabindex="-1"> 6163 <a 6164 class="link link--text disclosure__link caption-large focus-inset" 6165 href="#" 6166 6167 data-value="QA" 6168 id="Qatar" 6169 > 6170 <span 6171 6172 class="visibility-hidden" 6173 6174 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6175</span> 6176 <span class="country">Qatar</span> 6177 <span class="localization-form__currency motion-reduce"> 6178 QAR 6179 ر.Ù</span> 6180 </a> 6181 </li><li class="disclosure__item" tabindex="-1"> 6182 <a 6183 class="link link--text disclosure__link caption-large focus-inset" 6184 href="#" 6185 6186 data-value="RE" 6187 id="Réunion" 6188 >
6189 <span 6190 6191 class="visibility-hidden" 6192 6193 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6194</span> 6195 <span class="country">Réunion</span> 6196 <span class="localization-form__currency motion-reduce"> 6197 EUR 6198 â¬</span> 6199 </a> 6200 </li><li class="disclosure__item" tabindex="-1"> 6201 <a 6202 class="link link--text disclosure__link caption-large focus-inset" 6203 href="#" 6204 6205 data-value="RO" 6206 id="Romania" 6207 > 6208 <span 6209 6210 class="visibility-hidden" 6211 6212 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6213</span> 6214 <span class="country">Romania</span> 6215 <span class="localization-form__currency motion-reduce"> 6216 RON 6217 Lei</span> 6218 </a> 6219 </li><li class="disclosure__item" tabindex="-1"> 6220 <a 6221 class="link link--text disclosure__link caption-large focus-inset" 6222 href="#" 6223 6224 data-value="RU" 6225 id="Russia" 6226 > 6227 <span 6228 6229 class="visibility-hidden" 6230 6231 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6232</span> 6233 <span class="country">Russia</span> 6234 <span class="localization-form__currency motion-reduce"> 6235 EUR 6236 â¬</span> 6237 </a> 6238 </li><li class="disclosure__item" tabindex="-1"> 6239 <a 6240 class="link link--text disclosure__link caption-large focus-inset" 6241 href="#" 6242 6243 data-value="RW" 6244 id="Rwanda" 6245 > 6246 <span 6247 6248 class="visibility-hidden" 6249 6250 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6251</span> 6252 <span class="country">Rwanda</span> 6253 <span class="localization-form__currency motion-reduce"> 6254 RWF 6255 FRw</span> 6256 </a> 6257 </li><li class="disclosure__item" tabindex="-1"> 6258 <a 6259 class="link link--text disclosure__link caption-large focus-inset" 6260 href="#" 6261 6262 data-value="WS" 6263 id="Samoa" 6264 > 6265 <span 6266 6267 class="visibility-hidden" 6268 6269 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6270</span> 6271 <span class="country">Samoa</span> 6272 <span class="localization-form__currency motion-reduce"> 6273 WST 6274 T</span> 6275 </a> 6276 </li><li class="disclosure__item" tabindex="-1"> 6277 <a 6278 class="link link--text disclosure__link caption-large focus-inset" 6279 href="#" 6280 6281 data-value="SM" 6282 id="San Marino" 6283 >
6284 <span 6285 6286 class="visibility-hidden" 6287 6288 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6289</span> 6290 <span class="country">San Marino</span> 6291 <span class="localization-form__currency motion-reduce"> 6292 EUR 6293 â¬</span> 6294 </a> 6295 </li><li class="disclosure__item" tabindex="-1"> 6296 <a 6297 class="link link--text disclosure__link caption-large focus-inset" 6298 href="#" 6299 6300 data-value="ST" 6301 id="São Tomé & PrÃncipe" 6302 > 6303 <span 6304 6305 class="visibility-hidden" 6306 6307 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6308</span> 6309 <span class="country">São Tomé & PrÃncipe</span> 6310 <span class="localization-form__currency motion-reduce"> 6311 STD 6312 Db</span> 6313 </a> 6314 </li><li class="disclosure__item" tabindex="-1"> 6315 <a 6316 class="link link--text disclosure__link caption-large focus-inset" 6317 href="#" 6318 6319 data-value="SA" 6320 id="Saudi Arabia" 6321 > 6322 <span 6323 6324 class="visibility-hidden" 6325 6326 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6327</span> 6328 <span class="country">Saudi Arabia</span> 6329 <span class="localization-form__currency motion-reduce"> 6330 SAR 6331 ر.س</span> 6332 </a> 6333 </li><li class="disclosure__item" tabindex="-1"> 6334 <a 6335 class="link link--text disclosure__link caption-large focus-inset" 6336 href="#" 6337 6338 data-value="SN" 6339 id="Senegal" 6340 > 6341 <span 6342 6343 class="visibility-hidden" 6344 6345 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6346</span> 6347 <span class="country">Senegal</span> 6348 <span class="localization-form__currency motion-reduce"> 6349 XOF 6350 Fr</span> 6351 </a> 6352 </li><li class="disclosure__item" tabindex="-1"> 6353 <a 6354 class="link link--text disclosure__link caption-large focus-inset" 6355 href="#" 6356 6357 data-value="RS" 6358 id="Serbia" 6359 > 6360 <span 6361 6362 class="visibility-hidden" 6363 6364 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6365</span> 6366 <span class="country">Serbia</span>
6367 <span class="localization-form__currency motion-reduce"> 6368 RSD 6369 РСÐ</span> 6370 </a> 6371 </li><li class="disclosure__item" tabindex="-1"> 6372 <a 6373 class="link link--text disclosure__link caption-large focus-inset" 6374 href="#" 6375 6376 data-value="SC" 6377 id="Seychelles" 6378 > 6379 <span 6380 6381 class="visibility-hidden" 6382 6383 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6384</span> 6385 <span class="country">Seychelles</span> 6386 <span class="localization-form__currency motion-reduce"> 6387 EUR 6388 â¬</span> 6389 </a> 6390 </li><li class="disclosure__item" tabindex="-1"> 6391 <a 6392 class="link link--text disclosure__link caption-large focus-inset" 6393 href="#" 6394 6395 data-value="SL" 6396 id="Sierra Leone" 6397 > 6398 <span 6399 6400 class="visibility-hidden" 6401 6402 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6403</span> 6404 <span class="country">Sierra Leone</span> 6405 <span class="localization-form__currency motion-reduce"> 6406 SLL 6407 Le</span> 6408 </a> 6409 </li><li class="disclosure__item" tabindex="-1"> 6410 <a 6411 class="link link--text disclosure__link caption-large focus-inset" 6412 href="#" 6413 6414 data-value="SG" 6415 id="Singapore" 6416 > 6417 <span 6418 6419 class="visibility-hidden" 6420 6421 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6422</span> 6423 <span class="country">Singapore</span> 6424 <span class="localization-form__currency motion-reduce"> 6425 SGD 6426 $</span> 6427 </a> 6428 </li><li class="disclosure__item" tabindex="-1"> 6429 <a 6430 class="link link--text disclosure__link caption-large focus-inset" 6431 href="#" 6432 6433 data-value="SX" 6434 id="Sint Maarten" 6435 > 6436 <span 6437 6438 class="visibility-hidden" 6439 6440 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6441</span> 6442 <span class="country">Sint Maarten</span> 6443 <span class="localization-form__currency motion-reduce"> 6444 ANG 6445 Æ</span> 6446 </a> 6447 </li><li class="disclosure__item" tabindex="-1"> 6448 <a 6449 class="link link--text disclosure__link caption-large focus-inset" 6450 href="#" 6451 6452 data-value="SK" 6453 id="Slovakia" 6454 > 6455 <span 6456 6457 class="visibility-hidden" 6458 6459 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
6459<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6460</span> 6461 <span class="country">Slovakia</span> 6462 <span class="localization-form__currency motion-reduce"> 6463 EUR 6464 â¬</span> 6465 </a> 6466 </li><li class="disclosure__item" tabindex="-1"> 6467 <a 6468 class="link link--text disclosure__link caption-large focus-inset" 6469 href="#" 6470 6471 data-value="SI" 6472 id="Slovenia" 6473 > 6474 <span 6475 6476 class="visibility-hidden" 6477 6478 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6479</span> 6480 <span class="country">Slovenia</span> 6481 <span class="localization-form__currency motion-reduce"> 6482 EUR 6483 â¬</span> 6484 </a> 6485 </li><li class="disclosure__item" tabindex="-1"> 6486 <a 6487 class="link link--text disclosure__link caption-large focus-inset" 6488 href="#" 6489 6490 data-value="SB" 6491 id="Solomon Islands" 6492 > 6493 <span 6494 6495 class="visibility-hidden" 6496 6497 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6498</span> 6499 <span class="country">Solomon Islands</span> 6500 <span class="localization-form__currency motion-reduce"> 6501 SBD 6502 $</span> 6503 </a> 6504 </li><li class="disclosure__item" tabindex="-1"> 6505 <a 6506 class="link link--text disclosure__link caption-large focus-inset" 6507 href="#" 6508 6509 data-value="SO" 6510 id="Somalia" 6511 > 6512 <span 6513 6514 class="visibility-hidden" 6515 6516 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6517</span> 6518 <span class="country">Somalia</span> 6519 <span class="localization-form__currency motion-reduce"> 6520 EUR 6521 â¬</span> 6522 </a> 6523 </li><li class="disclosure__item" tabindex="-1"> 6524 <a 6525 class="link link--text disclosure__link caption-large focus-inset" 6526 href="#" 6527 6528 data-value="ZA" 6529 id="South Africa" 6530 > 6531 <span 6532 6533 class="visibility-hidden" 6534 6535 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6536</span> 6537 <span class="country">South Africa</span> 6538 <span class="localization-form__currency motion-reduce"> 6539 EUR 6540 â¬</span> 6541 </a> 6542 </li><li class="disclosure__item" tabindex="-1"> 6543 <a 6544 class="link link--text disclosure__link caption-large focus-inset" 6545 href="#" 6546 6547 data-value="GS" 6548 id="South Georgia & South Sandwich Islands" 6549 >
6550 <span 6551 6552 class="visibility-hidden" 6553 6554 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6555</span> 6556 <span class="country">South Georgia & South Sandwich Islands</span> 6557 <span class="localization-form__currency motion-reduce"> 6558 GBP 6559 £</span> 6560 </a> 6561 </li><li class="disclosure__item" tabindex="-1"> 6562 <a 6563 class="link link--text disclosure__link caption-large focus-inset" 6564 href="#" 6565 6566 data-value="KR" 6567 id="South Korea" 6568 > 6569 <span 6570 6571 class="visibility-hidden" 6572 6573 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6574</span> 6575 <span class="country">South Korea</span> 6576 <span class="localization-form__currency motion-reduce"> 6577 KRW 6578 â©</span> 6579 </a> 6580 </li><li class="disclosure__item" tabindex="-1"> 6581 <a 6582 class="link link--text disclosure__link caption-large focus-inset" 6583 href="#" 6584 6585 data-value="SS" 6586 id="South Sudan" 6587 > 6588 <span 6589 6590 class="visibility-hidden" 6591 6592 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6593</span> 6594 <span class="country">South Sudan</span> 6595 <span class="localization-form__currency motion-reduce"> 6596 EUR 6597 â¬</span> 6598 </a> 6599 </li><li class="disclosure__item" tabindex="-1"> 6600 <a 6601 class="link link--text disclosure__link caption-large focus-inset" 6602 href="#" 6603 6604 data-value="ES" 6605 id="Spain" 6606 > 6607 <span 6608 6609 class="visibility-hidden" 6610 6611 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6612</span> 6613 <span class="country">Spain</span> 6614 <span class="localization-form__currency motion-reduce"> 6615 EUR 6616 â¬</span> 6617 </a> 6618 </li><li class="disclosure__item" tabindex="-1"> 6619 <a 6620 class="link link--text disclosure__link caption-large focus-inset" 6621 href="#" 6622 6623 data-value="LK" 6624 id="Sri Lanka" 6625 > 6626 <span 6627 6628 class="visibility-hidden" 6629 6630 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6631</span> 6632 <span class="country">Sri Lanka</span>
6633 <span class="localization-form__currency motion-reduce"> 6634 LKR 6635 â¨</span> 6636 </a> 6637 </li><li class="disclosure__item" tabindex="-1"> 6638 <a 6639 class="link link--text disclosure__link caption-large focus-inset" 6640 href="#" 6641 6642 data-value="BL" 6643 id="St. Barthélemy" 6644 > 6645 <span 6646 6647 class="visibility-hidden" 6648 6649 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6650</span> 6651 <span class="country">St. Barthélemy</span> 6652 <span class="localization-form__currency motion-reduce"> 6653 EUR 6654 â¬</span> 6655 </a> 6656 </li><li class="disclosure__item" tabindex="-1"> 6657 <a 6658 class="link link--text disclosure__link caption-large focus-inset" 6659 href="#" 6660 6661 data-value="SH" 6662 id="St. Helena" 6663 > 6664 <span 6665 6666 class="visibility-hidden" 6667 6668 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6669</span> 6670 <span class="country">St. Helena</span> 6671 <span class="localization-form__currency motion-reduce"> 6672 SHP 6673 £</span> 6674 </a> 6675 </li><li class="disclosure__item" tabindex="-1"> 6676 <a 6677 class="link link--text disclosure__link caption-large focus-inset" 6678 href="#" 6679 6680 data-value="KN" 6681 id="St. Kitts & Nevis" 6682 > 6683 <span 6684 6685 class="visibility-hidden" 6686 6687 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6688</span> 6689 <span class="country">St. Kitts & Nevis</span> 6690 <span class="localization-form__currency motion-reduce"> 6691 XCD 6692 $</span> 6693 </a> 6694 </li><li class="disclosure__item" tabindex="-1"> 6695 <a 6696 class="link link--text disclosure__link caption-large focus-inset" 6697 href="#" 6698 6699 data-value="LC" 6700 id="St. Lucia" 6701 > 6702 <span 6703 6704 class="visibility-hidden" 6705 6706 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6707</span> 6708 <span class="country">St. Lucia</span> 6709 <span class="localization-form__currency motion-reduce"> 6710 XCD 6711 $</span> 6712 </a> 6713 </li><li class="disclosure__item" tabindex="-1"> 6714 <a 6715 class="link link--text disclosure__link caption-large focus-inset" 6716 href="#" 6717 6718 data-value="MF" 6719 id="St. Martin" 6720 > 6721 <span 6722 6723 class="visibility-hidden" 6724 6725 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
6725<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6726</span> 6727 <span class="country">St. Martin</span> 6728 <span class="localization-form__currency motion-reduce"> 6729 EUR 6730 â¬</span> 6731 </a> 6732 </li><li class="disclosure__item" tabindex="-1"> 6733 <a 6734 class="link link--text disclosure__link caption-large focus-inset" 6735 href="#" 6736 6737 data-value="PM" 6738 id="St. Pierre & Miquelon" 6739 > 6740 <span 6741 6742 class="visibility-hidden" 6743 6744 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6745</span> 6746 <span class="country">St. Pierre & Miquelon</span> 6747 <span class="localization-form__currency motion-reduce"> 6748 EUR 6749 â¬</span> 6750 </a> 6751 </li><li class="disclosure__item" tabindex="-1"> 6752 <a 6753 class="link link--text disclosure__link caption-large focus-inset" 6754 href="#" 6755 6756 data-value="VC" 6757 id="St. Vincent & Grenadines" 6758 > 6759 <span 6760 6761 class="visibility-hidden" 6762 6763 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6764</span> 6765 <span class="country">St. Vincent & Grenadines</span> 6766 <span class="localization-form__currency motion-reduce"> 6767 XCD 6768 $</span> 6769 </a> 6770 </li><li class="disclosure__item" tabindex="-1"> 6771 <a 6772 class="link link--text disclosure__link caption-large focus-inset" 6773 href="#" 6774 6775 data-value="SD" 6776 id="Sudan" 6777 > 6778 <span 6779 6780 class="visibility-hidden" 6781 6782 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6783</span> 6784 <span class="country">Sudan</span> 6785 <span class="localization-form__currency motion-reduce"> 6786 EUR 6787 â¬</span> 6788 </a> 6789 </li><li class="disclosure__item" tabindex="-1"> 6790 <a 6791 class="link link--text disclosure__link caption-large focus-inset" 6792 href="#" 6793 6794 data-value="SR" 6795 id="Suriname" 6796 > 6797 <span 6798 6799 class="visibility-hidden" 6800 6801 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6802</span> 6803 <span class="country">Suriname</span> 6804 <span class="localization-form__currency motion-reduce"> 6805 EUR 6806 â¬</span> 6807 </a> 6808 </li><li class="disclosure__item" tabindex="-1"> 6809 <a 6810 class="link link--text disclosure__link caption-large focus-inset" 6811 href="#" 6812 6813 data-value="SJ" 6814 id="Svalbard & Jan Mayen" 6815 >
6816 <span 6817 6818 class="visibility-hidden" 6819 6820 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6821</span> 6822 <span class="country">Svalbard & Jan Mayen</span> 6823 <span class="localization-form__currency motion-reduce"> 6824 EUR 6825 â¬</span> 6826 </a> 6827 </li><li class="disclosure__item" tabindex="-1"> 6828 <a 6829 class="link link--text disclosure__link caption-large focus-inset" 6830 href="#" 6831 6832 data-value="SE" 6833 id="Sweden" 6834 > 6835 <span 6836 6837 class="visibility-hidden" 6838 6839 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6840</span> 6841 <span class="country">Sweden</span> 6842 <span class="localization-form__currency motion-reduce"> 6843 SEK 6844 kr</span> 6845 </a> 6846 </li><li class="disclosure__item" tabindex="-1"> 6847 <a 6848 class="link link--text disclosure__link caption-large focus-inset" 6849 href="#" 6850 6851 data-value="CH" 6852 id="Switzerland" 6853 > 6854 <span 6855 6856 class="visibility-hidden" 6857 6858 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6859</span> 6860 <span class="country">Switzerland</span> 6861 <span class="localization-form__currency motion-reduce"> 6862 CHF 6863 CHF</span> 6864 </a> 6865 </li><li class="disclosure__item" tabindex="-1"> 6866 <a 6867 class="link link--text disclosure__link caption-large focus-inset" 6868 href="#" 6869 6870 data-value="TW" 6871 id="Taiwan" 6872 > 6873 <span 6874 6875 class="visibility-hidden" 6876 6877 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6878</span> 6879 <span class="country">Taiwan</span> 6880 <span class="localization-form__currency motion-reduce"> 6881 TWD 6882 $</span> 6883 </a> 6884 </li><li class="disclosure__item" tabindex="-1"> 6885 <a 6886 class="link link--text disclosure__link caption-large focus-inset" 6887 href="#" 6888 6889 data-value="TJ" 6890 id="Tajikistan" 6891 > 6892 <span 6893 6894 class="visibility-hidden" 6895 6896 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6897</span> 6898 <span class="country">Tajikistan</span> 6899 <span class="localization-form__currency motion-reduce"> 6900 TJS 6901 Ð Ð</span> 6902 </a> 6903 </li><li class="disclosure__item" tabindex="-1"> 6904 <a 6905 class="link link--text disclosure__link caption-large focus-inset" 6906 href="#" 6907 6908 data-value="TZ" 6909 id="Tanzania" 6910 >
6911 <span 6912 6913 class="visibility-hidden" 6914 6915 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6916</span> 6917 <span class="country">Tanzania</span> 6918 <span class="localization-form__currency motion-reduce"> 6919 TZS 6920 Sh</span> 6921 </a> 6922 </li><li class="disclosure__item" tabindex="-1"> 6923 <a 6924 class="link link--text disclosure__link caption-large focus-inset" 6925 href="#" 6926 6927 data-value="TH" 6928 id="Thailand" 6929 > 6930 <span 6931 6932 class="visibility-hidden" 6933 6934 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6935</span> 6936 <span class="country">Thailand</span> 6937 <span class="localization-form__currency motion-reduce"> 6938 THB 6939 ฿</span> 6940 </a> 6941 </li><li class="disclosure__item" tabindex="-1"> 6942 <a 6943 class="link link--text disclosure__link caption-large focus-inset" 6944 href="#" 6945 6946 data-value="TL" 6947 id="Timor-Leste" 6948 > 6949 <span 6950 6951 class="visibility-hidden" 6952 6953 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6954</span> 6955 <span class="country">Timor-Leste</span> 6956 <span class="localization-form__currency motion-reduce"> 6957 USD 6958 $</span> 6959 </a> 6960 </li><li class="disclosure__item" tabindex="-1"> 6961 <a 6962 class="link link--text disclosure__link caption-large focus-inset" 6963 href="#" 6964 6965 data-value="TG" 6966 id="Togo" 6967 > 6968 <span 6969 6970 class="visibility-hidden" 6971 6972 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6973</span> 6974 <span class="country">Togo</span> 6975 <span class="localization-form__currency motion-reduce"> 6976 XOF 6977 Fr</span> 6978 </a> 6979 </li><li class="disclosure__item" tabindex="-1"> 6980 <a 6981 class="link link--text disclosure__link caption-large focus-inset" 6982 href="#" 6983 6984 data-value="TK" 6985 id="Tokelau" 6986 > 6987 <span 6988 6989 class="visibility-hidden" 6990 6991 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 6992</span> 6993 <span class="country">Tokelau</span> 6994 <span class="localization-form__currency motion-reduce"> 6995 NZD
6996 $</span> 6997 </a> 6998 </li><li class="disclosure__item" tabindex="-1"> 6999 <a 7000 class="link link--text disclosure__link caption-large focus-inset" 7001 href="#" 7002 7003 data-value="TO" 7004 id="Tonga" 7005 > 7006 <span 7007 7008 class="visibility-hidden" 7009 7010 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7011</span> 7012 <span class="country">Tonga</span> 7013 <span class="localization-form__currency motion-reduce"> 7014 TOP 7015 T$</span> 7016 </a> 7017 </li><li class="disclosure__item" tabindex="-1"> 7018 <a 7019 class="link link--text disclosure__link caption-large focus-inset" 7020 href="#" 7021 7022 data-value="TT" 7023 id="Trinidad & Tobago" 7024 > 7025 <span 7026 7027 class="visibility-hidden" 7028 7029 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7030</span> 7031 <span class="country">Trinidad & Tobago</span> 7032 <span class="localization-form__currency motion-reduce"> 7033 TTD 7034 $</span> 7035 </a> 7036 </li><li class="disclosure__item" tabindex="-1"> 7037 <a 7038 class="link link--text disclosure__link caption-large focus-inset" 7039 href="#" 7040 7041 data-value="TA" 7042 id="Tristan da Cunha" 7043 > 7044 <span 7045 7046 class="visibility-hidden" 7047 7048 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7049</span> 7050 <span class="country">Tristan da Cunha</span> 7051 <span class="localization-form__currency motion-reduce"> 7052 GBP 7053 £</span> 7054 </a> 7055 </li><li class="disclosure__item" tabindex="-1"> 7056 <a 7057 class="link link--text disclosure__link caption-large focus-inset" 7058 href="#" 7059 7060 data-value="TN" 7061 id="Tunisia" 7062 > 7063 <span 7064 7065 class="visibility-hidden" 7066 7067 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7068</span> 7069 <span class="country">Tunisia</span> 7070 <span class="localization-form__currency motion-reduce"> 7071 EUR 7072 â¬</span> 7073 </a> 7074 </li><li class="disclosure__item" tabindex="-1"> 7075 <a 7076 class="link link--text disclosure__link caption-large focus-inset" 7077 href="#" 7078 7079 data-value="TR" 7080 id="Türkiye" 7081 > 7082 <span 7083 7084 class="visibility-hidden" 7085 7086 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
7086<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7087</span> 7088 <span class="country">Türkiye</span> 7089 <span class="localization-form__currency motion-reduce"> 7090 EUR 7091 â¬</span> 7092 </a> 7093 </li><li class="disclosure__item" tabindex="-1"> 7094 <a 7095 class="link link--text disclosure__link caption-large focus-inset" 7096 href="#" 7097 7098 data-value="TM" 7099 id="Turkmenistan" 7100 > 7101 <span 7102 7103 class="visibility-hidden" 7104 7105 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7106</span> 7107 <span class="country">Turkmenistan</span> 7108 <span class="localization-form__currency motion-reduce"> 7109 EUR 7110 â¬</span> 7111 </a> 7112 </li><li class="disclosure__item" tabindex="-1"> 7113 <a 7114 class="link link--text disclosure__link caption-large focus-inset" 7115 href="#" 7116 7117 data-value="TC" 7118 id="Turks & Caicos Islands" 7119 > 7120 <span 7121 7122 class="visibility-hidden" 7123 7124 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7125</span> 7126 <span class="country">Turks & Caicos Islands</span> 7127 <span class="localization-form__currency motion-reduce"> 7128 USD 7129 $</span> 7130 </a> 7131 </li><li class="disclosure__item" tabindex="-1"> 7132 <a 7133 class="link link--text disclosure__link caption-large focus-inset" 7134 href="#" 7135 7136 data-value="TV" 7137 id="Tuvalu" 7138 > 7139 <span 7140 7141 class="visibility-hidden" 7142 7143 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7144</span> 7145 <span class="country">Tuvalu</span> 7146 <span class="localization-form__currency motion-reduce"> 7147 AUD 7148 $</span> 7149 </a> 7150 </li><li class="disclosure__item" tabindex="-1"> 7151 <a 7152 class="link link--text disclosure__link caption-large focus-inset" 7153 href="#" 7154 7155 data-value="UM" 7156 id="U.S. Outlying Islands" 7157 > 7158 <span 7159 7160 class="visibility-hidden" 7161 7162 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7163</span> 7164 <span class="country">U.S. Outlying Islands</span> 7165 <span class="localization-form__currency motion-reduce"> 7166 USD 7167 $</span> 7168 </a> 7169 </li><li class="disclosure__item" tabindex="-1"> 7170 <a 7171 class="link link--text disclosure__link caption-large focus-inset" 7172 href="#" 7173 7174 data-value="UG" 7175 id="Uganda" 7176 >
7177 <span 7178 7179 class="visibility-hidden" 7180 7181 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7182</span> 7183 <span class="country">Uganda</span> 7184 <span class="localization-form__currency motion-reduce"> 7185 UGX 7186 USh</span> 7187 </a> 7188 </li><li class="disclosure__item" tabindex="-1"> 7189 <a 7190 class="link link--text disclosure__link caption-large focus-inset" 7191 href="#" 7192 7193 data-value="UA" 7194 id="Ukraine" 7195 > 7196 <span 7197 7198 class="visibility-hidden" 7199 7200 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7201</span> 7202 <span class="country">Ukraine</span> 7203 <span class="localization-form__currency motion-reduce"> 7204 UAH 7205 â´</span> 7206 </a> 7207 </li><li class="disclosure__item" tabindex="-1"> 7208 <a 7209 class="link link--text disclosure__link caption-large focus-inset" 7210 href="#" 7211 7212 data-value="AE" 7213 id="United Arab Emirates" 7214 > 7215 <span 7216 7217 class="visibility-hidden" 7218 7219 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7220</span> 7221 <span class="country">United Arab Emirates</span> 7222 <span class="localization-form__currency motion-reduce"> 7223 AED 7224 د.Ø¥</span> 7225 </a> 7226 </li><li class="disclosure__item" tabindex="-1"> 7227 <a 7228 class="link link--text disclosure__link caption-large focus-inset" 7229 href="#" 7230 7231 data-value="GB" 7232 id="United Kingdom" 7233 > 7234 <span 7235 7236 class="visibility-hidden" 7237 7238 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7239</span> 7240 <span class="country">United Kingdom</span> 7241 <span class="localization-form__currency motion-reduce"> 7242 GBP 7243 £</span> 7244 </a> 7245 </li><li class="disclosure__item" tabindex="-1"> 7246 <a 7247 class="link link--text disclosure__link caption-large focus-inset" 7248 href="#" 7249 7250 aria-current="true" 7251 7252 data-value="US" 7253 id="United States" 7254 > 7255 <span 7256 7257 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7258</span> 7259 <span class="country">United States</span>
7260 <span class="localization-form__currency motion-reduce"> 7261 USD 7262 $</span> 7263 </a> 7264 </li><li class="disclosure__item" tabindex="-1"> 7265 <a 7266 class="link link--text disclosure__link caption-large focus-inset" 7267 href="#" 7268 7269 data-value="UY" 7270 id="Uruguay" 7271 > 7272 <span 7273 7274 class="visibility-hidden" 7275 7276 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7277</span> 7278 <span class="country">Uruguay</span> 7279 <span class="localization-form__currency motion-reduce"> 7280 UYU 7281 $U</span> 7282 </a> 7283 </li><li class="disclosure__item" tabindex="-1"> 7284 <a 7285 class="link link--text disclosure__link caption-large focus-inset" 7286 href="#" 7287 7288 data-value="UZ" 7289 id="Uzbekistan" 7290 > 7291 <span 7292 7293 class="visibility-hidden" 7294 7295 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7296</span> 7297 <span class="country">Uzbekistan</span> 7298 <span class="localization-form__currency motion-reduce"> 7299 UZS 7300 so'm</span> 7301 </a> 7302 </li><li class="disclosure__item" tabindex="-1"> 7303 <a 7304 class="link link--text disclosure__link caption-large focus-inset" 7305 href="#" 7306 7307 data-value="VU" 7308 id="Vanuatu" 7309 > 7310 <span 7311 7312 class="visibility-hidden" 7313 7314 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7315</span> 7316 <span class="country">Vanuatu</span> 7317 <span class="localization-form__currency motion-reduce"> 7318 VUV 7319 Vt</span> 7320 </a> 7321 </li><li class="disclosure__item" tabindex="-1"> 7322 <a 7323 class="link link--text disclosure__link caption-large focus-inset" 7324 href="#" 7325 7326 data-value="VA" 7327 id="Vatican City" 7328 > 7329 <span 7330 7331 class="visibility-hidden" 7332 7333 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7334</span> 7335 <span class="country">Vatican City</span> 7336 <span class="localization-form__currency motion-reduce"> 7337 EUR 7338 â¬</span> 7339 </a> 7340 </li><li class="disclosure__item" tabindex="-1"> 7341 <a 7342 class="link link--text disclosure__link caption-large focus-inset" 7343 href="#" 7344 7345 data-value="VE" 7346 id="Venezuela" 7347 > 7348 <span 7349 7350 class="visibility-hidden" 7351 7352 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9">
7352<path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7353</span> 7354 <span class="country">Venezuela</span> 7355 <span class="localization-form__currency motion-reduce"> 7356 USD 7357 $</span> 7358 </a> 7359 </li><li class="disclosure__item" tabindex="-1"> 7360 <a 7361 class="link link--text disclosure__link caption-large focus-inset" 7362 href="#" 7363 7364 data-value="VN" 7365 id="Vietnam" 7366 > 7367 <span 7368 7369 class="visibility-hidden" 7370 7371 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7372</span> 7373 <span class="country">Vietnam</span> 7374 <span class="localization-form__currency motion-reduce"> 7375 VND 7376 â«</span> 7377 </a> 7378 </li><li class="disclosure__item" tabindex="-1"> 7379 <a 7380 class="link link--text disclosure__link caption-large focus-inset" 7381 href="#" 7382 7383 data-value="WF" 7384 id="Wallis & Futuna" 7385 > 7386 <span 7387 7388 class="visibility-hidden" 7389 7390 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7391</span> 7392 <span class="country">Wallis & Futuna</span> 7393 <span class="localization-form__currency motion-reduce"> 7394 XPF 7395 Fr</span> 7396 </a> 7397 </li><li class="disclosure__item" tabindex="-1"> 7398 <a 7399 class="link link--text disclosure__link caption-large focus-inset" 7400 href="#" 7401 7402 data-value="EH" 7403 id="Western Sahara" 7404 > 7405 <span 7406 7407 class="visibility-hidden" 7408 7409 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7410</span> 7411 <span class="country">Western Sahara</span> 7412 <span class="localization-form__currency motion-reduce"> 7413 MAD 7414 د.Ù .</span> 7415 </a> 7416 </li><li class="disclosure__item" tabindex="-1"> 7417 <a 7418 class="link link--text disclosure__link caption-large focus-inset" 7419 href="#" 7420 7421 data-value="YE" 7422 id="Yemen" 7423 > 7424 <span 7425 7426 class="visibility-hidden" 7427 7428 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7429</span> 7430 <span class="country">Yemen</span> 7431 <span class="localization-form__currency motion-reduce"> 7432 YER 7433 ï·¼</span> 7434 </a> 7435 </li><li class="disclosure__item" tabindex="-1"> 7436 <a 7437 class="link link--text disclosure__link caption-large focus-inset" 7438 href="#" 7439 7440 data-value="ZM" 7441 id="Zambia" 7442 >
7443 <span 7444 7445 class="visibility-hidden" 7446 7447 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7448</span> 7449 <span class="country">Zambia</span> 7450 <span class="localization-form__currency motion-reduce"> 7451 EUR 7452 â¬</span> 7453 </a> 7454 </li><li class="disclosure__item" tabindex="-1"> 7455 <a 7456 class="link link--text disclosure__link caption-large focus-inset" 7457 href="#" 7458 7459 data-value="ZW" 7460 id="Zimbabwe" 7461 > 7462 <span 7463 7464 class="visibility-hidden" 7465 7466 ><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-checkmark" viewBox="0 0 12 9"><path fill="currentColor" fill-rule="evenodd" d="M11.35.643a.5.5 0 0 1 .006.707l-6.77 6.886a.5.5 0 0 1-.719-.006L.638 4.845a.5.5 0 1 1 .724-.69l2.872 3.011 6.41-6.517a.5.5 0 0 1 .707-.006z" clip-rule="evenodd"/></svg> 7467</span> 7468 <span class="country">Zimbabwe</span> 7469 <span class="localization-form__currency motion-reduce"> 7470 USD 7471 $</span> 7472 </a> 7473 </li></ul> 7474 </div> 7475 </div> 7476 <div class="country-selector__overlay"></div> 7477</div> 7478<input type="hidden" name="country_code" value="US"> 7479</div></form></localization-form> 7480 7481</div><ul class="list list-social list-unstyled" role="list"></ul> 7482 </div> 7483 </div> 7484 </div> 7485 </div> 7486 </details> 7487</header-drawer> 7488 7489 7490<details-modal class="header__search"> 7491 <details> 7492 <summary 7493 class="header__icon header__icon--search header__icon--summary link focus-inset modal__toggle" 7494 aria-haspopup="dialog" 7495 aria-label="Search" 7496 > 7497 <span> 7498 <span class="svg-wrapper"><svg fill="none" class="icon icon-search" viewBox="0 0 18 19"><path fill="currentColor" fill-rule="evenodd" d="M11.03 11.68A5.784 5.784 0 1 1 2.85 3.5a5.784 5.784 0 0 1 8.18 8.18m.26 1.12a6.78 6.78 0 1 1 .72-.7l5.4 5.4a.5.5 0 1 1-.71.7z" clip-rule="evenodd"/></svg> 7499</span> 7500 <span class="svg-wrapper header__icon-close"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-close" viewBox="0 0 18 17"><path fill="currentColor" d="M.865 15.978a.5.5 0 0 0 .707.707l7.433-7.431 7.579 7.282a.501.501 0 0 0 .846-.37.5.5 0 0 0-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 1 0-.707-.708L8.991 7.853 1.413.573a.5.5 0 1 0-.693.72l7.563 7.268z"/></svg> 7501</span> 7502 </span> 7503 </summary> 7504 <div 7505 class="search-modal modal__content gradient" 7506 role="dialog" 7507 aria-modal="true" 7508 aria-label="Search" 7509 > 7510 <div class="modal-overlay"></div> 7511 <div 7512 class="search-modal__content search-modal__content-bottom" 7513 tabindex="-1" 7514 ><search-form class="search-modal__form"><form action="/en-en/search" method="get" role="search" class="search search-modal__form"> 7515 <div class="field"> 7516 <input 7517 class="search__input field__input" 7518 id="Search-In-Modal-1" 7519 type="search" 7520 name="q" 7521 value="" 7522 placeholder="Search"> 7523 <label class="field__label" for="Search-In-Modal-1">Search</label> 7524 <input type="hidden" name="options[prefix]" value="last"> 7525 <button 7526 type="reset" 7527 class="reset__button field__button hidden" 7528 aria-label="Clear search term" 7529 > 7530 <span class="svg-wrapper"><svg fill="none" stroke="currentColor" class="icon icon-close" viewBox="0 0 18 18"><circle cx="9" cy="9" r="8.5" stroke-opacity=".2"/><path stroke-linecap="round" stroke-linejoin="round" d="M11.83 11.83 6.172 6.17M6.229 11.885l5.544-5.77"/></svg> 7531</span> 7532 </button> 7533 <button class="search__button field__button" aria-label="Search">
7534 <span class="svg-wrapper"><svg fill="none" class="icon icon-search" viewBox="0 0 18 19"><path fill="currentColor" fill-rule="evenodd" d="M11.03 11.68A5.784 5.784 0 1 1 2.85 3.5a5.784 5.784 0 0 1 8.18 8.18m.26 1.12a6.78 6.78 0 1 1 .72-.7l5.4 5.4a.5.5 0 1 1-.71.7z" clip-rule="evenodd"/></svg> 7535</span> 7536 </button> 7537 </div></form></search-form><button 7538 type="button" 7539 class="search-modal__close-button modal__close-button link link--text focus-inset" 7540 aria-label="Close" 7541 > 7542 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-close" viewBox="0 0 18 17"><path fill="currentColor" d="M.865 15.978a.5.5 0 0 0 .707.707l7.433-7.431 7.579 7.282a.501.501 0 0 0 .846-.37.5.5 0 0 0-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 1 0-.707-.708L8.991 7.853 1.413.573a.5.5 0 1 0-.693.72l7.563 7.268z"/></svg> 7543</span> 7544 </button> 7545 </div> 7546 </div> 7547 </details> 7548</details-modal> 7549<a href="/en-en" class="header__heading-link link link--text focus-inset"><div class="header__heading-logo-wrapper"> 7550 7551 <img src="//granrondo.cc/cdn/shop/files/GRANRONDO_logo_d66df12c-b6aa-49e1-b05d-5cbb94ca4fe7.png?v=1762039111&width=600" alt="GRANRONDO.cc" srcset="//granrondo.cc/cdn/shop/files/GRANRONDO_logo_d66df12c-b6aa-49e1-b05d-5cbb94ca4fe7.png?v=1762039111&width=240 240w, //granrondo.cc/cdn/shop/files/GRANRONDO_logo_d66df12c-b6aa-49e1-b05d-5cbb94ca4fe7.png?v=1762039111&width=360 360w, //granrondo.cc/cdn/shop/files/GRANRONDO_logo_d66df12c-b6aa-49e1-b05d-5cbb94ca4fe7.png?v=1762039111&width=480 480w" width="240" height="240.0" loading="eager" class="header__heading-logo motion-reduce" sizes="(max-width: 480px) 50vw, 240px"> 7552 </div></a> 7553 7554<nav class="header__inline-menu"> 7555 <ul class="list-menu list-menu--inline" role="list"><li><a 7556 id="HeaderMenu-jouw-rondos" 7557 href="/en-en/pages/dashboard" 7558 class="header__menu-item list-menu__item link link--text focus-inset" 7559 7560 > 7561 <span 7562 >Your Rondos</span> 7563 </a></li><li><a 7564 id="HeaderMenu-events" 7565 href="/en-en/collections/events" 7566 class="header__menu-item list-menu__item link link--text focus-inset" 7567 7568 aria-current="page" 7569 7570 > 7571 <span 7572 class="header__active-menu-item" 7573 7574 >Events</span> 7575 </a></li><li><header-menu> 7576 <details id="Details-HeaderMenu-3"> 7577 <summary 7578 id="HeaderMenu-shop" 7579 class="header__menu-item list-menu__item link focus-inset" 7580 > 7581 <span 7582 >Shop</span><svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 7583</summary> 7584 <ul 7585 id="HeaderMenu-MenuList-3" 7586 class="header__submenu list-menu list-menu--disclosure color-scheme-1 gradient caption-large motion-reduce global-settings-popup" 7587 role="list" 7588 tabindex="-1" 7589 ><li><a 7590 id="HeaderMenu-shop-rondoboxen-gidsen" 7591 href="/en-en/collections/all" 7592 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7593 7594 > 7595 Rondoboxes & Guides 7596 </a></li><li><a 7597 id="HeaderMenu-shop-rondoneurs-kit" 7598 href="/en-en/collections/rondoneurs-kit" 7599 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7600 7601 > 7602 Rondoneurs Kit 7603 </a></li><li><details id="Details-HeaderSubMenu-shop-service"> 7604 <summary 7605 id="HeaderMenu-shop-service" 7606 class="header__menu-item link link--text list-menu__item focus-inset caption-large" 7607 >
7608 <span>Service</span><svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 7609</summary> 7610 <ul 7611 id="HeaderMenu-SubMenuList-shop-service-" 7612 class="header__submenu list-menu motion-reduce" 7613 ><li> 7614 <a 7615 id="HeaderMenu-shop-service-vraag-antwoord" 7616 href="/en-en/pages/service" 7617 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7618 7619 > 7620 Question & Answer 7621 </a> 7622 </li><li> 7623 <a 7624 id="HeaderMenu-shop-service-bestelstatus" 7625 href="https://account.granrondo.cc/orders?locale=en®ion_country=US&buyer_flags=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJraGR6MGMtYXEubXlzaG9waWZ5LmNvbSIsImZsYWdzIjpbXSwiZXhwIjoxNzkxNzM0MTQ4LCJuYmYiOjE3OTExMjkzNDh9.JJR3o2H8oj7UyznNdneLTGHxMoaQ1WLTeSO0ehjAZ4w" 7626 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7627 7628 > 7629 Order Status 7630 </a> 7631 </li><li> 7632 <a 7633 id="HeaderMenu-shop-service-contact" 7634 href="/en-en/pages/service#contactus" 7635 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7636 7637 > 7638 Contact 7639 </a> 7640 </li></ul> 7641 </details></li></ul> 7642 </details> 7643 </header-menu></li><li><header-menu> 7644 <details id="Details-HeaderMenu-4"> 7645 <summary 7646 id="HeaderMenu-join-the-circle" 7647 class="header__menu-item list-menu__item link focus-inset" 7648 > 7649 <span 7650 >Join the Circle</span><svg class="icon icon-caret" viewBox="0 0 10 6"><path fill="currentColor" fill-rule="evenodd" d="M9.354.646a.5.5 0 0 0-.708 0L5 4.293 1.354.646a.5.5 0 0 0-.708.708l4 4a.5.5 0 0 0 .708 0l4-4a.5.5 0 0 0 0-.708" clip-rule="evenodd"/></svg> 7651</summary> 7652 <ul 7653 id="HeaderMenu-MenuList-4" 7654 class="header__submenu list-menu list-menu--disclosure color-scheme-1 gradient caption-large motion-reduce global-settings-popup" 7655 role="list" 7656 tabindex="-1" 7657 ><li><a 7658 id="HeaderMenu-join-the-circle-rondoneur-worden" 7659 href="/en-en/products/join" 7660 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7661 7662 > 7663 Join as Rondoneur 7664 </a></li><li><a 7665 id="HeaderMenu-join-the-circle-hall-of-fame" 7666 href="/en-en/pages/rondo-hall-of-fame" 7667 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7668 7669 > 7670 Hall of Fame 7671 </a></li><li><a 7672 id="HeaderMenu-join-the-circle-samen-voor-kika" 7673 href="/en-en/pages/samen-voor-kika" 7674 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7675 7676 > 7677 Together for Kika 7678 </a></li><li><a 7679 id="HeaderMenu-join-the-circle-mr-granrondo" 7680 href="/en-en/pages/mr-granrondo" 7681 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7682 7683 > 7684 mr.granrondo 7685 </a></li><li><a 7686 id="HeaderMenu-join-the-circle-instagram" 7687 href="https://www.instagram.com/ridearound.cc" 7688 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7689 7690 > 7691 Instagram 7692 </a></li><li><a 7693 id="HeaderMenu-join-the-circle-strava" 7694 href="https://www.strava.com/clubs/granrondo" 7695 class="header__menu-item list-menu__item link link--text focus-inset caption-large" 7696 7697 > 7698 Strava 7699 </a></li></ul> 7700 </details> 7701 </header-menu></li><li><a 7702 id="HeaderMenu-je-startlijst-mandje" 7703 href="/en-en/cart" 7704 class="header__menu-item list-menu__item link link--text focus-inset" 7705 7706 >
7707 <span 7708 >Your Startlist / Basket</span> 7709 </a></li></ul> 7710</nav> 7711 7712<div class="header__icons header__icons--localization header-localization"> 7713 <div class="desktop-localization-wrapper"> 7714</div> 7715 7716 7717<details-modal class="header__search"> 7718 <details> 7719 <summary 7720 class="header__icon header__icon--search header__icon--summary link focus-inset modal__toggle" 7721 aria-haspopup="dialog" 7722 aria-label="Search" 7723 > 7724 <span> 7725 <span class="svg-wrapper"><svg fill="none" class="icon icon-search" viewBox="0 0 18 19"><path fill="currentColor" fill-rule="evenodd" d="M11.03 11.68A5.784 5.784 0 1 1 2.85 3.5a5.784 5.784 0 0 1 8.18 8.18m.26 1.12a6.78 6.78 0 1 1 .72-.7l5.4 5.4a.5.5 0 1 1-.71.7z" clip-rule="evenodd"/></svg> 7726</span> 7727 <span class="svg-wrapper header__icon-close"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-close" viewBox="0 0 18 17"><path fill="currentColor" d="M.865 15.978a.5.5 0 0 0 .707.707l7.433-7.431 7.579 7.282a.501.501 0 0 0 .846-.37.5.5 0 0 0-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 1 0-.707-.708L8.991 7.853 1.413.573a.5.5 0 1 0-.693.72l7.563 7.268z"/></svg> 7728</span> 7729 </span> 7730 </summary> 7731 <div 7732 class="search-modal modal__content gradient" 7733 role="dialog" 7734 aria-modal="true" 7735 aria-label="Search" 7736 > 7737 <div class="modal-overlay"></div> 7738 <div 7739 class="search-modal__content search-modal__content-bottom" 7740 tabindex="-1" 7741 ><search-form class="search-modal__form"><form action="/en-en/search" method="get" role="search" class="search search-modal__form"> 7742 <div class="field"> 7743 <input 7744 class="search__input field__input" 7745 id="Search-In-Modal" 7746 type="search" 7747 name="q" 7748 value="" 7749 placeholder="Search"> 7750 <label class="field__label" for="Search-In-Modal">Search</label> 7751 <input type="hidden" name="options[prefix]" value="last"> 7752 <button 7753 type="reset" 7754 class="reset__button field__button hidden" 7755 aria-label="Clear search term" 7756 > 7757 <span class="svg-wrapper"><svg fill="none" stroke="currentColor" class="icon icon-close" viewBox="0 0 18 18"><circle cx="9" cy="9" r="8.5" stroke-opacity=".2"/><path stroke-linecap="round" stroke-linejoin="round" d="M11.83 11.83 6.172 6.17M6.229 11.885l5.544-5.77"/></svg> 7758</span> 7759 </button> 7760 <button class="search__button field__button" aria-label="Search"> 7761 <span class="svg-wrapper"><svg fill="none" class="icon icon-search" viewBox="0 0 18 19"><path fill="currentColor" fill-rule="evenodd" d="M11.03 11.68A5.784 5.784 0 1 1 2.85 3.5a5.784 5.784 0 0 1 8.18 8.18m.26 1.12a6.78 6.78 0 1 1 .72-.7l5.4 5.4a.5.5 0 1 1-.71.7z" clip-rule="evenodd"/></svg> 7762</span> 7763 </button> 7764 </div></form></search-form><button 7765 type="button" 7766 class="search-modal__close-button modal__close-button link link--text focus-inset" 7767 aria-label="Close" 7768 > 7769 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-close" viewBox="0 0 18 17"><path fill="currentColor" d="M.865 15.978a.5.5 0 0 0 .707.707l7.433-7.431 7.579 7.282a.501.501 0 0 0 .846-.37.5.5 0 0 0-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 1 0-.707-.708L8.991 7.853 1.413.573a.5.5 0 1 0-.693.72l7.563 7.268z"/></svg> 7770</span> 7771 </button> 7772 </div> 7773 </div> 7774 </details> 7775</details-modal> 7776 7777<a href="/en-en/cart" class="header__icon header__icon--cart link focus-inset" id="cart-icon-bubble"> 7778 7779 <span class="svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" class="icon icon-cart-empty" viewBox="0 0 40 40"><path fill="currentColor" fill-rule="evenodd" d="M15.75 11.8h-3.16l-.77 11.6a5 5 0 0 0 4.99 5.34h7.38a5 5 0 0 0 4.99-5.33L28.4 11.8zm0 1h-2.22l-.71 10.67a4 4 0 0 0 3.99 4.27h7.38a4 4 0 0 0 4-4.27l-.72-10.67h-2.22v.63a4.75 4.75 0 1 1-9.5 0zm8.5 0h-7.5v.63a3.75 3.75 0 1 0 7.5 0z"/></svg> 7780</span> 7781
7782 <span class="visually-hidden">Cart</span></a> 7783 </div> 7784 </header> 7785</div> 7786
7787<script type="application/ld+json"> 7788 { 7789 "@context": "http://schema.org", 7790 "@type": "Organization", 7791 "name": "GRANRONDO.cc", 7792 7793 "logo": "https:\/\/granrondo.cc\/cdn\/shop\/files\/GRANRONDO_logo_d66df12c-b6aa-49e1-b05d-5cbb94ca4fe7.png?v=1762039111\u0026width=500", 7794 7795 "sameAs": [ 7796 "", 7797 "", 7798 "", 7799 "", 7800 "", 7801 "", 7802 "", 7803 "", 7804 "" 7805 ], 7806 "url": "https:\/\/granrondo.cc" 7807 } 7808</script>
7808 7809</div> 7810<!-- END sections: header-group --> 7811 7812 <main id="MainContent" class="content-for-layout focus-none" role="main" tabindex="-1"> 7813 <section id="shopify-section-template--25436442198390__image_banner_h3pxNX" class="shopify-section section"><link href="//granrondo.cc/cdn/shop/t/1/assets/section-image-banner.css?v=124819179385751388401737013878" rel="stylesheet" type="text/css" media="all" /> 7814<style data-shopify>#Banner-template--25436442198390__image_banner_h3pxNX::after { 7815 opacity: 0.0; 7816 }</style><div 7817 id="Banner-template--25436442198390__image_banner_h3pxNX" 7818 class="banner banner--content-align-center banner--content-align-mobile-center banner--medium banner--desktop-transparent scroll-trigger animate--fade-in" 7819><div class="banner__media media animate--fixed scroll-trigger animate--fade-in"><img src="//granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=3840" alt="Events" srcset="//granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=375 375w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=550 550w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=750 750w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=1100 1100w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=1500 1500w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=1780 1780w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=2000 2000w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=3000 3000w, //granrondo.cc/cdn/shop/collections/RIDE-A-ROUND-DeechteRondevanZeeland202490.jpg?v=1748049790&width=3840 3840w" width="1800" height="1350.0" sizes="100vw" fetchpriority="high"> 7820 </div><div class="banner__content banner__content--middle-center page-width scroll-trigger animate--slide-in"> 7821 <div class="banner__box content-container content-container--full-width-mobile color-scheme-4 gradient"><h2 7822 class="banner__heading inline-richtext h1" 7823 7824 > 7825 Events 7826 </h2><div class="banner__text rte subtitle" > 7827 <p>Enjoy relaxed Social Rondoâs, Ultra Challenges, and other events!</p> 7828 </div></div> 7829 </div> 7830</div> 7831 7832 7833<style> #shopify-section-template--25436442198390__image_banner_h3pxNX .banner::before {background: linear-gradient( 180deg, var(--color-white) 50%, var(--color-brand) 51% );} @media screen and (min-width: 750px) {#shopify-section-template--25436442198390__image_banner_h3pxNX .banner--medium:not(.banner--adapt) {min-height: 70rem !important; max-height: 70rem !important; }} #shopify-section-template--25436442198390__image_banner_h3pxNX .banner__media:after {top: 0; background: #271d62; opacity: 0.6;} #shopify-section-template--25436442198390__image_banner_h3pxNX em {display: block; font-style: normal;} </style></section><section id="shopify-section-template--25436442198390__custom_liquid_YidzpH" class="shopify-section section"><style data-shopify>.section-template--25436442198390__custom_liquid_YidzpH-padding { 7834 padding-top: calc(64px * 0.75); 7835 padding-bottom: calc(0px * 0.75); 7836 } 7837 7838 @media screen and (min-width: 750px) { 7839 .section-template--25436442198390__custom_liquid_YidzpH-padding { 7840 padding-top: 64px; 7841 padding-bottom: 0px; 7842 } 7843 }</style><div class="color-scheme-3 gradient"> 7844 <div class="section-template--25436442198390__custom_liquid_YidzpH-padding"> 7845 <div class="rich-text__wrapper rich-text__wrapper--center page-width"> 7846 <div class="rich-text__blocks center"> 7847 <div class="eventlist rte"> 7848 <h6 style="padding-top:2rem; transform:scale(.8)"> 7849 <span class="eventroad">= road</span> 7850 <span class="eventroadgravel">= road / gravel</span>
7851 <span class="eventgravel">= gravel</span> 7852 </h6> 7853 </div> 7854 </div> 7855</div> 7856 </div> 7857</div> 7858 7859 7860</section><div id="shopify-section-template--25436442198390__product-grid" class="shopify-section section"><link href="//granrondo.cc/cdn/shop/t/1/assets/template-collection.css?v=58558206033505836701737013878" rel="stylesheet" type="text/css" media="all" /> 7861<link href="//granrondo.cc/cdn/shop/t/1/assets/component-card.css?v=120341546515895839841737013876" rel="stylesheet" type="text/css" media="all" /> 7862<link href="//granrondo.cc/cdn/shop/t/1/assets/component-price.css?v=70172745017360139101737013876" rel="stylesheet" type="text/css" media="all" /> 7863 7864<style data-shopify>.section-template--25436442198390__product-grid-padding { 7865 padding-top: 3px; 7866 padding-bottom: 0px; 7867 } 7868 7869 @media screen and (min-width: 750px) { 7870 .section-template--25436442198390__product-grid-padding { 7871 padding-top: 4px; 7872 padding-bottom: 0px; 7873 } 7874 }</style><div class="section-template--25436442198390__product-grid-padding gradient color-scheme-3"> 7875<div class=""> 7876 <link href="//granrondo.cc/cdn/shop/t/1/assets/component-facets.css?v=122898528428646687911737013876" rel="stylesheet" type="text/css" media="all" /> 7877
7877<script src="//granrondo.cc/cdn/shop/t/1/assets/facets.js?v=42798985796066624181737013876" defer="defer"></script>
7877<div 7878 class="product-grid-container scroll-trigger animate--slide-in" 7879 id="ProductGridContainer" 7880 7881 data-cascade 7882 7883 ><div 7884 class="collection page-width" 7885 > 7886 <div class="loading-overlay gradient"></div> 7887 <ul 7888 id="product-grid" 7889 data-id="template--25436442198390__product-grid" 7890 class=" 7891 grid product-grid grid--1-col-tablet-down 7892 grid--3-col-desktop 7893 7894 " 7895 > 7896 7897 7898<li 7899 class="grid__item scroll-trigger animate--slide-in" 7900 7901 data-cascade 7902 style="--animation-order: 1;" 7903 7904 > 7905 7906<link href="//granrondo.cc/cdn/shop/t/1/assets/component-rating.css?v=179577762467860590411737013876" rel="stylesheet" type="text/css" media="all" /> 7907 <link href="//granrondo.cc/cdn/shop/t/1/assets/component-volume-pricing.css?v=111870094811454961941737013876" rel="stylesheet" type="text/css" media="all" /> 7908 7909 <link href="//granrondo.cc/cdn/shop/t/1/assets/component-price.css?v=70172745017360139101737013876" rel="stylesheet" type="text/css" media="all" /> 7910 <link href="//granrondo.cc/cdn/shop/t/1/assets/quick-order-list.css?v=129932180309343703061737013878" rel="stylesheet" type="text/css" media="all" /> 7911 <link href="//granrondo.cc/cdn/shop/t/1/assets/quantity-popover.css?v=129068967981937647381737013878" rel="stylesheet" type="text/css" media="all" /> 7912<div class="card-wrapper product-card-wrapper underline-links-hover"> 7913 <div 7914 class=" 7915 card card--standard 7916 card--media 7917 7918 card--shape 7919 7920 7921 7922 " 7923 style="--ratio-percent: 100%;" 7924 > 7925 <div 7926 class="card__inner color-scheme-2 gradient ratio" 7927 style="--ratio-percent: 100%;" 7928 ><div class="card__media shape--round color-scheme-2 gradient"> 7929 <div class="media media--transparent media--hover-effect"> 7930 7931 <img 7932 srcset="//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=165 165w,//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=360 360w,//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=533 533w,//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=720 720w,//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=940 940w,//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=1066 1066w,//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405 1441w 7933 " 7934 src="//granrondo.cc/cdn/shop/files/GranRondoCoverNederland.jpg?v=1790862405&width=533" 7935 sizes="(min-width: 1200px) 267px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)" 7936 alt="Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge" 7937 class="motion-reduce" 7938 7939 width="1441" 7940 height="811" 7941 > 7942 7943<img 7944 srcset="//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=165 165w,//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=360 360w,//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=533 533w,//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=720 720w,//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=940 940w,//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=1066 1066w,//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811 1179w 7945 " 7946 src="//granrondo.cc/cdn/shop/files/0C4B7063-2A30-491F-8B29-7FA164AB5AFB.jpg?v=1776580811&width=533" 7947 sizes="(min-width: 1200px) 267px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)" 7948 alt="" 7949 class="motion-reduce" 7950 loading="lazy" 7951 width="1179" 7952 height="1652" 7953 ></div> 7954 </div><div class="card__content"> 7955 <div class="card__information"><h6 class="ra-event-date">
7956 <span class="eventroadgravel">20 jun '27</span> 7957 </h6><h3 7958 class="card__heading" 7959 7960 > 7961 <a 7962 href="/en-en/products/gran-rondo-nederland-event" 7963 id="StandardCardNoMediaLink-template--25436442198390__product-grid-15103264981366" 7964 class="full-unstyled-link" 7965 aria-labelledby="StandardCardNoMediaLink-template--25436442198390__product-grid-15103264981366 NoMediaStandardBadge-template--25436442198390__product-grid-15103264981366" 7966 > 7967 Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge 7968 </a> 7969 </h3> 7970 <div 7971 class="ra-prod-rating" 7972 data-roundid="Nederland" 7973 data-title="Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge" 7974 style="margin-top:.35rem;" 7975 ></div> 7976 </div> 7977 <div class="card__badge bottom right"><span 7978 id="NoMediaStandardBadge-template--25436442198390__product-grid-15103264981366" 7979 class="badge badge--bottom-left color-scheme-2" 7980 >Sold out</span></div> 7981 </div> 7982 </div> 7983 <div class="card__content"> 7984 <div class="card__information"><h6 class="ra-event-date"> 7985 <span class="eventroadgravel">17-20 Jun '27</span> 7986 </h6><h3 7987 class="card__heading h5" 7988 7989 id="title-template--25436442198390__product-grid-15103264981366" 7990 7991 > 7992 <a 7993 href="/en-en/products/gran-rondo-nederland-event" 7994 id="CardLink-template--25436442198390__product-grid-15103264981366" 7995 class="full-unstyled-link" 7996 aria-labelledby="CardLink-template--25436442198390__product-grid-15103264981366 Badge-template--25436442198390__product-grid-15103264981366" 7997 > 7998 Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge 7999 </a> 8000 </h3> 8001 <div 8002 class="ra-prod-rating" 8003 data-roundid="Nederland" 8004 data-title="Gran Rondo ð ð³ð± Nederland - Longest Weekend Challenge" 8005 style="margin-top:.35rem;" 8006 ></div> 8007 8008 <div class="card-information"><span class="caption-large light"></span> 8009<div 8010 class=" 8011 price price--sold-out" 8012 > 8013 <div class="price__container"><div class="price__regular"><span class="visually-hidden visually-hidden--inline">Regular price</span> 8014 <span class="price-item price-item--regular"> 8015 $87.00 8016 </span></div> 8017 <div class="price__sale"> 8018 <span class="visually-hidden visually-hidden--inline">Regular price</span> 8019 <span> 8020 <s class="price-item price-item--regular"> 8021 8022 $35.00 8023 8024 </s> 8025 </span><span class="visually-hidden visually-hidden--inline">Sale price</span> 8026 <span class="price-item price-item--sale price-item--last"> 8027 $87.00 8028 </span> 8029 </div> 8030 <small class="unit-price caption hidden"> 8031 <span class="visually-hidden">Unit price</span> 8032 <span class="price-item price-item--last"> 8033 <span></span> 8034 <span aria-hidden="true">/</span> 8035 <span class="visually-hidden"> per </span> 8036 <span> 8037 </span> 8038 </span> 8039 </small> 8040 </div></div> 8041 8042 8043</div> 8044 </div> 8045 8046 8047 <div class="card__badge bottom right"><span 8048 id="Badge-template--25436442198390__product-grid-15103264981366" 8049 class="badge badge--bottom-left color-scheme-2" 8050 >Sold out</span></div> 8051 </div> 8052 </div> 8053 </div> 8054 </li> 8055<li 8056 class="grid__item scroll-trigger animate--slide-in" 8057 8058 data-cascade 8059 style="--animation-order: 2;" 8060 8061 > 8062 8063<div class="card-wrapper product-card-wrapper underline-links-hover"> 8064 <div 8065 class=" 8066 card card--standard 8067 card--media 8068 8069 card--shape 8070 8071 8072 8073 " 8074 style="--ratio-percent: 100%;" 8075 > 8076 <div 8077 class="card__inner color-scheme-2 gradient ratio" 8078 style="--ratio-percent: 100%;" 8079 ><div class="card__media shape--round color-scheme-2 gradient"> 8080 <div class="media media--transparent media--hover-effect"> 8081 8082 <img 8083 srcset="//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=165 165w,//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=360 360w,//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=533 533w,//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=720 720w,//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=940 940w,//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=1066 1066w,//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232 1441w 8084 " 8085 src="//granrondo.cc/cdn/shop/files/GranRondoCoverBEWA.jpg?v=1777413232&width=533" 8086 sizes="(min-width: 1200px) 267px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)" 8087 alt="Gran Rondo ð¡ð´ Wallonie 400" 8088 class="motion-reduce" 8089 8090 width="1441" 8091 height="811" 8092 > 8093 8094<img 8095 srcset="//granrondo.cc/cdn/shop/files/42D2EA4C-1B61-40AB-B6B2-3275AD8C5A5A_1_105_c.jpg?v=1782417938&width=165 165w,//granrondo.cc/cdn/shop/files/42D2EA4C-1B61-40AB-B6B2-3275AD8C5A5A_1_105_c.jpg?v=1782417938&width=360 360w,//granrondo.cc/cdn/shop/files/42D2EA4C-1B61-40AB-B6B2-3275AD8C5A5A_1_105_c.jpg?v=1782417938&width=533 533w,//granrondo.cc/cdn/shop/files/42D2EA4C-1B61-40AB-B6B2-3275AD8C5A5A_1_105_c.jpg?v=1782417938&width=720 720w,//granrondo.cc/cdn/shop/files/42D2EA4C-1B61-40AB-B6B2-3275AD8C5A5A_1_105_c.jpg?v=1782417938 768w 8096 " 8097 src="//granrondo.cc/cdn/shop/files/42D2EA4C-1B61-40AB-B6B2-3275AD8C5A5A_1_105_c.jpg?v=1782417938&width=533" 8098 sizes="(min-width: 1200px) 267px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)" 8099 alt="" 8100 class="motion-reduce" 8101 loading="lazy" 8102 width="768" 8103 height="1024" 8104 ></div> 8105 </div><div class="card__content"> 8106 <div class="card__information"><h6 class="ra-event-date">
8107 <span class="eventroadgravel">1 jan '70</span> 8108 </h6><h3 8109 class="card__heading" 8110 8111 > 8112 <a 8113 href="/en-en/products/gran-rondo-wallonie-event" 8114 id="StandardCardNoMediaLink-template--25436442198390__product-grid-15775162171766" 8115 class="full-unstyled-link" 8116 aria-labelledby="StandardCardNoMediaLink-template--25436442198390__product-grid-15775162171766 NoMediaStandardBadge-template--25436442198390__product-grid-15775162171766" 8117 > 8118 Gran Rondo ð¡ð´ Wallonie 400 8119 </a> 8120 </h3> 8121 <div 8122 class="ra-prod-rating" 8123 data-roundid="Wallonie" 8124 data-title="Gran Rondo ð¡ð´ Wallonie 400" 8125 style="margin-top:.35rem;" 8126 ></div> 8127 </div> 8128 <div class="card__badge bottom right"></div> 8129 </div> 8130 </div> 8131 <div class="card__content"> 8132 <div class="card__information"><h6 class="ra-event-date"> 8133 <span class="eventroadgravel">2027</span> 8134 </h6><h3 8135 class="card__heading h5" 8136 8137 id="title-template--25436442198390__product-grid-15775162171766" 8138 8139 > 8140 <a 8141 href="/en-en/products/gran-rondo-wallonie-event" 8142 id="CardLink-template--25436442198390__product-grid-15775162171766" 8143 class="full-unstyled-link" 8144 aria-labelledby="CardLink-template--25436442198390__product-grid-15775162171766 Badge-template--25436442198390__product-grid-15775162171766" 8145 > 8146 Gran Rondo ð¡ð´ Wallonie 400 8147 </a> 8148 </h3> 8149 <div 8150 class="ra-prod-rating" 8151 data-roundid="Wallonie" 8152 data-title="Gran Rondo ð¡ð´ Wallonie 400" 8153 style="margin-top:.35rem;" 8154 ></div> 8155 8156 <div class="card-information"><span class="caption-large light"></span> 8157<div 8158 class=" 8159 price " 8160 > 8161 <div class="price__container"><div class="price__regular"><span class="visually-hidden visually-hidden--inline">Regular price</span> 8162 <span class="price-item price-item--regular"> 8163 From $0.00 8164 </span></div> 8165 <div class="price__sale"> 8166 <span class="visually-hidden visually-hidden--inline">Regular price</span> 8167 <span> 8168 <s class="price-item price-item--regular"> 8169 8170 8171 8172 </s> 8173 </span><span class="visually-hidden visually-hidden--inline">Sale price</span> 8174 <span class="price-item price-item--sale price-item--last"> 8175 From $0.00 8176 </span> 8177 </div> 8178 <small class="unit-price caption hidden"> 8179 <span class="visually-hidden">Unit price</span> 8180 <span class="price-item price-item--last"> 8181 <span></span> 8182 <span aria-hidden="true">/</span> 8183 <span class="visually-hidden"> per </span> 8184 <span> 8185 </span> 8186 </span> 8187 </small> 8188 </div></div> 8189 8190 8191</div> 8192 </div> 8193 8194 8195 <div class="card__badge bottom right"></div> 8196 </div> 8197 </div> 8198 </div> 8199 </li> 8200<li 8201 class="grid__item scroll-trigger animate--slide-in" 8202 8203 data-cascade 8204 style="--animation-order: 3;" 8205 8206 > 8207 8208<div class="card-wrapper product-card-wrapper underline-links-hover"> 8209 <div 8210 class=" 8211 card card--standard 8212 card--media 8213 8214 card--shape 8215 8216 8217 8218 " 8219 style="--ratio-percent: 100%;" 8220 > 8221 <div 8222 class="card__inner color-scheme-2 gradient ratio" 8223 style="--ratio-percent: 100%;" 8224 ><div class="card__media shape--round color-scheme-2 gradient"> 8225 <div class="media media--transparent media--hover-effect"> 8226 8227 <img 8228 srcset="//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=165 165w,//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=360 360w,//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=533 533w,//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=720 720w,//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=940 940w,//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=1066 1066w,//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711 1441w 8229 " 8230 src="//granrondo.cc/cdn/shop/files/GRANRONDOcoverGB.jpg?v=1788879711&width=533" 8231 sizes="(min-width: 1200px) 267px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)" 8232 alt="Gran Rondo âð¬ð§ Great Britain - 700 Miles Race" 8233 class="motion-reduce" 8234 8235 loading="lazy" 8236 8237 width="1441" 8238 height="811" 8239 > 8240 8241<img 8242 srcset="//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=165 165w,//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=360 360w,//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=533 533w,//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=720 720w,//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=940 940w,//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=1066 1066w,//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004 1800w 8243 " 8244 src="//granrondo.cc/cdn/shop/files/GranRondoGreatBritainImpression1.jpg?v=1788880004&width=533" 8245 sizes="(min-width: 1200px) 267px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)" 8246 alt="" 8247 class="motion-reduce" 8248 loading="lazy" 8249 width="1800" 8250 height="1200" 8251 ></div> 8252 </div><div class="card__content"> 8253 <div class="card__information"><h6 class="ra-event-date">
8254 <span class="eventroadgravel">summer 2027</span> 8255 </h6><h3 8256 class="card__heading" 8257 8258 > 8259 <a 8260 href="/en-en/products/gran-rondo-great-britain-event" 8261 id="StandardCardNoMediaLink-template--25436442198390__product-grid-15871005032822" 8262 class="full-unstyled-link" 8263 aria-labelledby="StandardCardNoMediaLink-template--25436442198390__product-grid-15871005032822 NoMediaStandardBadge-template--25436442198390__product-grid-15871005032822" 8264 > 8265 Gran Rondo âð¬ð§ Great Britain - 700 Miles Race 8266 </a> 8267 </h3> 8268 <div 8269 class="ra-prod-rating" 8270 data-roundid="Great Britain" 8271 data-title="Gran Rondo âð¬ð§ Great Britain - 700 Miles Race" 8272 style="margin-top:.35rem;" 8273 ></div> 8274 </div> 8275 <div class="card__badge bottom right"><span 8276 id="NoMediaStandardBadge-template--25436442198390__product-grid-15871005032822" 8277 class="badge badge--bottom-left color-scheme-2" 8278 >Sold out</span></div> 8279 </div> 8280 </div> 8281 <div class="card__content"> 8282 <div class="card__information"><h6 class="ra-event-date"> 8283 <span class="eventroadgravel">Summer 2027</span> 8284 </h6><h3 8285 class="card__heading h5" 8286 8287 id="title-template--25436442198390__product-grid-15871005032822" 8288 8289 > 8290 <a 8291 href="/en-en/products/gran-rondo-great-britain-event" 8292 id="CardLink-template--25436442198390__product-grid-15871005032822" 8293 class="full-unstyled-link" 8294 aria-labelledby="CardLink-template--25436442198390__product-grid-15871005032822 Badge-template--25436442198390__product-grid-15871005032822" 8295 > 8296 Gran Rondo âð¬ð§ Great Britain - 700 Miles Race 8297 </a> 8298 </h3> 8299 <div 8300 class="ra-prod-rating" 8301 data-roundid="Great Britain" 8302 data-title="Gran Rondo âð¬ð§ Great Britain - 700 Miles Race" 8303 style="margin-top:.35rem;" 8304 ></div> 8305 8306 <div class="card-information"><span class="caption-large light"></span> 8307<div 8308 class=" 8309 price price--sold-out" 8310 > 8311 <div class="price__container"><div class="price__regular"><span class="visually-hidden visually-hidden--inline">Regular price</span> 8312 <span class="price-item price-item--regular"> 8313 From $155.00 8314 </span></div> 8315 <div class="price__sale"> 8316 <span class="visually-hidden visually-hidden--inline">Regular price</span> 8317 <span> 8318 <s class="price-item price-item--regular"> 8319 8320 8321 8322 </s> 8323 </span><span class="visually-hidden visually-hidden--inline">Sale price</span> 8324 <span class="price-item price-item--sale price-item--last"> 8325 From $155.00 8326 </span> 8327 </div> 8328 <small class="unit-price caption hidden"> 8329 <span class="visually-hidden">Unit price</span> 8330 <span class="price-item price-item--last"> 8331 <span></span> 8332 <span aria-hidden="true">/</span> 8333 <span class="visually-hidden"> per </span> 8334 <span> 8335 </span> 8336 </span> 8337 </small> 8338 </div></div> 8339 8340 8341</div> 8342 </div> 8343 8344 8345 <div class="card__badge bottom right"><span 8346 id="Badge-template--25436442198390__product-grid-15871005032822" 8347 class="badge badge--bottom-left color-scheme-2" 8348 >Sold out</span></div> 8349 </div> 8350 </div> 8351 </div> 8352 </li></ul></div></div> 8353 </div></div> 8354 8355 8356<style> #shopify-section-template--25436442198390__product-grid .card-information {display: none;} #shopify-section-template--25436442198390__product-grid .card__badge * {background-color: #ffb600; color: white !important; font-weight: 600; font-size: 1.9rem; text-transform: uppercase; font-family: "acumin_pro"; display: none;} #shopify-section-template--25436442198390__product-grid .price-item--sale {color: #ffb600; font-size: 1.6rem; font-weight: 600; letter-spacing: 0;} #shopify-section-template--25436442198390__product-grid h6 {margin: 0.5rem;} </style></div><section id="shopify-section-template--25436442198390__custom_liquid_gk8VtN" class="shopify-section section"><style data-shopify>
8356.section-template--25436442198390__custom_liquid_gk8VtN-padding { 8357 padding-top: calc(0px * 0.75); 8358 padding-bottom: calc(0px * 0.75); 8359 } 8360 8361 @media screen and (min-width: 750px) { 8362 .section-template--25436442198390__custom_liquid_gk8VtN-padding { 8363 padding-top: 0px; 8364 padding-bottom: 0px; 8365 } 8366 }</style><div class="color-scheme-3 gradient"> 8367 <div class="section-template--25436442198390__custom_liquid_gk8VtN-padding"> 8368 <div class="section-body-last"><br> 8369</div> 8370 </div> 8371</div> 8372 8373 8374</section>
8374<script data-locksmith> 8375 var load = function () { 8376 8377 if (document.querySelectorAll('.locksmith-manual-trigger').length > 0) { 8378 Locksmith.ping(); 8379 } 8380 8381 8382 Locksmith.util.on('submit', 'locksmith-resource-form', function (event) { 8383 event.preventDefault(); 8384 var data = Locksmith.util.serializeForm(event.target); 8385 var options = { spinner: false, container: 'locksmith-content' }; 8386 // a form rendered inline (section replacement) must keep that context 8387 // on resubmit: same enclosing container (there may be several on the 8388 // page), and no layout classes or cancel affordance in the re-render 8389 var inlineContainer = event.target.closest && event.target.closest('[id^="locksmith-content"]'); 8390 if (inlineContainer) { 8391 options.container = inlineContainer; 8392 } 8393 if (event.target.getAttribute('data-locksmith-inline') === 'true') { 8394 options.include_layout_classes = false; 8395 } 8396 Locksmith.postResource(data, options); 8397 }); 8398 8399 Locksmith.util.on('click', 'locksmith-manual-trigger', function (event) { 8400 event.preventDefault(); 8401 Locksmith.postResource({}, { spinner: true, container: document }); 8402 }); 8403 8404 Locksmith.submitPasscode = function (passcode) { 8405 Locksmith.postResource( 8406 { passcode: passcode }, 8407 { spinner: false, container: 'locksmith-content' } 8408 ); 8409 }; 8410 }; 8411 8412 if (typeof Locksmith !== 'undefined') { 8413 load(); 8414 } else { 8415 window.addEventListener('load', load); 8416 } 8417 </script>
8417 8418 </main> 8419 8420 <!-- BEGIN sections: footer-group --> 8421<section id="shopify-section-sections--24695135142262__newsletter_wfTdJQ" class="shopify-section shopify-section-group-footer-group section"><link href="//granrondo.cc/cdn/shop/t/1/assets/component-newsletter.css?v=4727253280200485261737013876" rel="stylesheet" type="text/css" media="all" /> 8422<link href="//granrondo.cc/cdn/shop/t/1/assets/newsletter-section.css?v=62410470717655853621737013877" rel="stylesheet" type="text/css" media="all" /> 8423<style data-shopify>.section-sections--24695135142262__newsletter_wfTdJQ-padding { 8424 padding-top: 75px; 8425 padding-bottom: 75px; 8426 } 8427 8428 @media screen and (min-width: 750px) { 8429 .section-sections--24695135142262__newsletter_wfTdJQ-padding { 8430 padding-top: 100px; 8431 padding-bottom: 100px; 8432 } 8433 }</style><div class="newsletter center "> 8434 <div class="newsletter__wrapper color-scheme-4 gradient content-container isolate content-container--full-width section-sections--24695135142262__newsletter_wfTdJQ-padding"><h2 8435 class="inline-richtext h2 scroll-trigger animate--slide-in" 8436 8437 8438 data-cascade 8439 style="--animation-order: 1;" 8440 8441 > 8442 Thousands of cycling enthusiasts already know the feeling â these aren't just random circles drawn on a map. They are meticulously crafted, cyclist-friendly routes, filled with unique highlights. 8443 </h2><div
8444 class="newsletter__subheading rte scroll-trigger animate--slide-in" 8445 8446 8447 data-cascade 8448 style="--animation-order: 2;" 8449 8450 > 8451 <h6>MR.GRANRONDO â <a href="/en-en/pages/mr-granrondo" title="mr.granrondo">read my story</a></h6> 8452 </div><div id="shopify-block-Ab0kvTms0R3BrRy9FM__forms_inline_9mVh8A" class="shopify-block shopify-app-block"><div 8453 id='Ab0kvTms0R3BrRy9FM__forms_inline_9mVh8A' 8454 data-form-root='true' 8455 data-forms-id='forms-root-1143683' 8456 data-forms-text-color='#202020' 8457 data-forms-button-background-color='#202020' 8458 data-forms-button-label-color='#ffffff' 8459 data-forms-links-color='#03d3bb' 8460 data-forms-errors-color='#e02229' 8461 data-forms-text-alignment='left' 8462 data-forms-alignment='center' 8463 data-forms-padding-top='0' 8464 data-forms-padding-right='0' 8465 data-forms-padding-bottom='24' 8466 data-forms-padding-left='0' 8467></div> 8468
8469<script> 8470 window['ShopifyForms'] = { 8471 ...window['ShopifyForms'], 8472 currentPageType: "collection" 8473 }; 8474</script>
8474 8475 8476 8477</div> 8478</div> 8479</div> 8480 8481 8482<style> #shopify-section-sections--24695135142262__newsletter_wfTdJQ * {color: var(--color-dark);} @media screen and (min-width: 750px) {#shopify-section-sections--24695135142262__newsletter_wfTdJQ h2 {padding-top: 10rem; max-width: 50%; margin: auto; }} #shopify-section-sections--24695135142262__newsletter_wfTdJQ h6 a {color: var(--color-brand); text-shadow: 0px 0px 4px black; padding: 0 5px;} #shopify-section-sections--24695135142262__newsletter_wfTdJQ shopify-forms-embed {display: none !important;} </style></section><section id="shopify-section-sections--24695135142262__custom_liquid_9AE3Et" class="shopify-section shopify-section-group-footer-group section"><style data-shopify>.section-sections--24695135142262__custom_liquid_9AE3Et-padding { 8483 padding-top: calc(0px * 0.75); 8484 padding-bottom: calc(0px * 0.75); 8485 } 8486 8487 @media screen and (min-width: 750px) { 8488 .section-sections--24695135142262__custom_liquid_9AE3Et-padding { 8489 padding-top: 0px; 8490 padding-bottom: 0px; 8491 } 8492 }</style><div class="color-scheme-4 gradient"> 8493 <div class="section-sections--24695135142262__custom_liquid_9AE3Et-padding"> 8494
8494<script> 8495 function styleFormsEmbed() { 8496 const host = document.querySelector('shopify-forms-embed'); 8497 if (!host || !host.shadowRoot) return false; 8498 8499 const style = document.createElement('style'); 8500 style.textContent = ` 8501 * { 8502line-height: calc(1 + 0.8 / var(--font-body-scale)); 8503 font-family: var(--font-body-family); 8504 font-weight: var(--font-body-weight); 8505 color: var(--color-dark) !important; 8506 } 8507 button { 8508 color: var(--color-white) !important; 8509 background: var(--color-action) !important; 8510 letter-spacing: 0.1em !important; 8511 text-transform: uppercase !important; 8512 font-family: "rum raisin" !important; 8513 font-size: 1.5rem !important; 8514 border-radius: 50px !important; 8515 } 8516 input { 8517 border-radius: 50px !important; 8518 background: var(--color-lighter) !important; 8519 } 8520 h2 { 8521font-size:2.2rem!important; 8522 letter-spacing: 0.05em !important; 8523 text-transform: uppercase !important; 8524 font-family: "rum raisin" !important; 8525 } 8526p ~ p {margin-top:1rem!important;} 8527form p { font-size:1.6rem!important} 8528h2 + div p {font-size:1.4rem!important; 8529@media screen and (min-width: 750px) { 8530 font-size:1.6rem!important; 8531} 8532} 8533form + div p {font-size:1rem!important; font-family: var(--font-body-family); 8534 font-weight: var(--font-body-weight)!important; font-style: italic!important; 8535@media screen and (min-width: 750px) { 8536 font-size:1.2rem!important; 8537}}} 8538fieldset {margin-top:1rem!important;} 8539fieldset legend {font-size:1.4rem!important; font-weight: 600!important; 8540@media screen and (min-width: 750px) { 8541 font-size:1.6rem!important; 8542}}} 8543fieldset label span {font-size:1.3rem!important; 8544@media screen and (min-width: 750px) { 8545 font-size:1.5rem!important; 8546}} 8547form input~label { 8548 top: 18px !important; 8549} 8550 `; 8551 host.shadowRoot.appendChild(style); 8552 return true; 8553 } 8554 8555 if (!styleFormsEmbed()) { 8556 const observer = new MutationObserver(() => { 8557 if (styleFormsEmbed()) observer.disconnect(); 8558 }); 8559 observer.observe(document.body, { childList: true, subtree: true }); 8560 } 8561</script>
8561 8562 </div> 8563</div> 8564 8565 8566</section><div id="shopify-section-sections--24695135142262__footer" class="shopify-section shopify-section-group-footer-group"> 8567<link href="//granrondo.cc/cdn/shop/t/1/assets/section-footer.css?v=60318643098753476351737013878" rel="stylesheet" type="text/css" media="all" /> 8568<link href="//granrondo.cc/cdn/shop/t/1/assets/component-newsletter.css?v=4727253280200485261737013876" rel="stylesheet" type="text/css" media="all" /> 8569<link href="//granrondo.cc/cdn/shop/t/1/assets/component-list-menu.css?v=151968516119678728991737013876" rel="stylesheet" type="text/css" media="all" /> 8570<link href="//granrondo.cc/cdn/shop/t/1/assets/component-list-payment.css?v=69253961410771838501737013876" rel="stylesheet" type="text/css" media="all" /> 8571<link href="//granrondo.cc/cdn/shop/t/1/assets/component-list-social.css?v=35792976012981934991737013876" rel="stylesheet" type="text/css" media="all" /> 8572<style data-shopify>.footer { 8573 margin-top: 0px; 8574 } 8575 8576 .section-sections--24695135142262__footer-padding { 8577 padding-top: 45px; 8578 padding-bottom: 0px; 8579 } 8580 8581 @media screen and (min-width: 750px) { 8582 .footer { 8583 margin-top: 0px; 8584 } 8585 8586 .section-sections--24695135142262__footer-padding { 8587 padding-top: 60px; 8588 padding-bottom: 0px; 8589 } 8590 }</style><footer class="footer color-scheme-4 gradient section-sections--24695135142262__footer-padding"><div class="footer__content-top page-width"><div 8591 class="footer__blocks-wrapper grid grid--1-col grid--2-col grid--4-col-tablet scroll-tr
8591igger animate--slide-in" 8592 8593 data-cascade 8594 8595 ><div 8596 class="footer-block grid__item scroll-trigger animate--slide-in" 8597 8598 8599 data-cascade 8600 style="--animation-order: 1;" 8601 8602 ><div class="footer-block__details-content footer-block-image center"><div 8603 class="footer-block__image-wrapper" 8604 style="max-width: min(100%, 230px);" 8605 > 8606 <img 8607 srcset="//granrondo.cc/cdn/shop/files/GRANRONDO_logo_white_shadow.png?v=1761399590&width=230, //granrondo.cc/cdn/shop/files/GRANRONDO_logo_white_shadow.png?v=1761399590&width=460 2x" 8608 src="//granrondo.cc/cdn/shop/files/GRANRONDO_logo_white_shadow.png?v=1761399590&width=760" 8609 alt="" 8610 loading="lazy" 8611 width="4801" 8612 height="4801" 8613 > 8614 </div></div></div></div><div 8615 class="footer-block--newsletter scroll-trigger animate--slide-in" 8616 8617 data-cascade 8618 8619 ></div> 8620 </div><div 8621 class="footer__content-bottom scroll-trigger animate--slide-in" 8622 8623 data-cascade 8624 8625 > 8626 <div class="footer__content-bottom-wrapper page-width"> 8627 <div class="footer__column footer__localization isolate"></div> 8628 <div class="footer__column footer__column--info"></div> 8629 </div> 8630 <div class="footer__content-bottom-wrapper page-width footer__content-bottom-wrapper--center"> 8631 <div class="footer__copyright caption"> 8632 <small class="copyright__content" 8633 >© 2026, <a href="/en-en" title="">GRANRONDO.cc</a></small> 8634 <small class="copyright__content">Powered by Shopify</small></div> 8635 </div> 8636 </div> 8637</footer> 8638 8639 8640<style> #shopify-section-sections--24695135142262__footer .footer__content-bottom {display: none;} #shopify-section-sections--24695135142262__footer * {padding-bottom: 0.01rem;} </style></div><section id="shopify-section-sections--24695135142262__custom_liquid_VFbwHH" class="shopify-section shopify-section-group-footer-group section"><style data-shopify>.section-sections--24695135142262__custom_liquid_VFbwHH-padding { 8641 padding-top: calc(0px * 0.75); 8642 padding-bottom: calc(0px * 0.75); 8643 } 8644 8645 @media screen and (min-width: 750px) { 8646 .section-sections--24695135142262__custom_liquid_VFbwHH-padding { 8647 padding-top: 0px; 8648 padding-bottom: 0px; 8649 } 8650 }</style><div class="color-scheme-4 gradient"> 8651 <div class="section-sections--24695135142262__custom_liquid_VFbwHH-padding"> 8652 8653 8654 8655 8656<style> 8657:root { 8658 --c-red: #E53935; 8659} 8660.restricted-actions a[target="_blank"]::after { display: none; } 8661.comments-section { padding-top: 0.1rem; } 8662/* STIJLEN VOOR GEANNULEERDE RITTEN */ 8663.date-pill.cancelled { 8664 text-decoration: line-through; 8665 opacity: 0.7; 8666} 8667.cancelled-label { 8668 color: var(--c-red); 8669 font-weight: 800; 8670 font-size: 0.8em; 8671 text-transform: uppercase; 8672 margin-top: 4px; 8673} 8674.ride-card.cancelled-card { 8675 opacity: 0.8; 8676 background: #fdfdfd; 8677 border-color: #eee; 8678} 8679/* ALGEMEEN */ 8680.ride-route-stats { margin-top: 6px; font-size: 0.95em; } 8681.route-stats-block p { margin: 0; text-decoration: none !important; font-size: 1.2rem; line-height: 2.4rem; letter-spacing: normal !important; } 8682.route-stats-block em { font-family: 'rum raisin'; text-transform: uppercase; white-space: nowrap; } 8683.route-stats-block em:nth-child(2), .route-stats-block em:nth-child(4), .route-stats-block em:nth-child(5) { display: inline-block; } 8684.route-stats-block strong { margin-left: 4px; margin-right: 3px; } 8685.restricted-box { background: var(--color-white); border: 1px solid #eee; padding: 30px; border-radius: 12px; text-align: center; margin-top: 20px; margin-bottom: 20px; } 8686.restricted-box p { font-weight: 700; font-size: 1.1em; margin-bottom: 25px; color: var(--color-dark); } 8687.restricted-actions { display: flex; flex-direction: column; gap: 15px; align-items: center; justify-content: center; } 8688.btn-secondary { background: white; border: 2px solid var(--color-brand); color: var(--color-brand); padding: 12px 30px; cursor: pointer; border-radius: 999px; font-weight: 700; white-space: nowrap; font-size: 1.6rem !important; text-decoration: none; display: inline-block; max-width: 300px; text-transform: uppercase; font-family: "rum raisin", sans-serif; letter-spacing: .1rem; } 8689.btn-secondary:hover { background: var(--color-brand); color: white; } 8690.circles-modal .button--secondary, 8691.circles-modal .btn-secondary { background: white; border: 2px solid var(--color-brand); color: var(--color-brand); width: 100%; min-width: 100%; } 8692/* Knoppen in een modal vullen de breedte; .btn-secondary heeft een max-width 8693 van 300px die hier juist in de weg zit. */ 8694.circles-modal-content a.btn-primary, 8695.circles-modal-content a.btn-secondary { width: 100%; max-width: 100%; } 8696/* Meer info in de ticketmodal is de rustigste keuze van de drie; die staat in 8697 color-dark in plaats van de brandkleur. */ 8698.circles-modal #ticketModalInfoBtn { 8699 border-color: var(--color-dark); 8700 color: var(--color-dark); 8701} 8702.circles-modal #ticketModalInfoBtn:hover { 8703 background: var(--color-dark); 8704 color: var(--color-white); 8705} 8706.restricted-actions .btn-primary { text-decoration: none; display: inline-block; max-width: 300px; } 8707a.button, button { font-size: 1.5rem !important; } 8708body.modal-open { overflow: hidden; } 8709.hidden { display: none !important; } 8710.font-bold { font-weight: bold; } 8711.mt-10 { margin-top: 10px; } 8712.mb-5 { margin-bottom: 5px; } 8713.mb-10 { margin-bottom: 10px; } 8714.flex-1 { flex: 1; } 8715.flex-2 { flex: 2; } 8716.circles-modal.forced-modal .close-modal { display: none !important; } 8717.gr-modal-close { 8718 font-size: 60px !important; 8719 font-weight: 300; 8720} 8721.view-select-wrapper { position: relative; display: block; padding: 0; width: 100%; } 8722.view-select-wrapper::before { content: 'â°'; position: absolute; left: 15px; top: 48%; transform: translateY(-50%); font-size: 2.4rem; color: white; pointer-events: none; line-height: 1; font-weight: 900; z-index: 1; } 8723.control-row-toolbar { display: flex; align-items: center; justify-content: space-between; width: 100%; flex-wrap: wrap; gap: 15px; } 8724.toolbar-left { display: flex; align-items: center; gap: 15px; width: 100%; flex-wrap: wrap; } 8725.toolbar-actions { display: flex; gap: 20px; align-items: center; margin-left: auto; } 8726.toolbar-right { flex-shrink: 0; } 8727.btn-primary { background: var(--color-action); color: white; padding: 12px 30px; border: none; cursor: pointer; border-radius: 999px; font-weight: 700; white-space: nowrap; font-size: 1.8rem !important; text-transform: uppercase; font-family: "rum raisin", sans-serif; letter-spacing: .1rem; } 8728.btn-primary[disabled] { opacity: 0.5;
8728 cursor: not-allowed; } 8729.full-width { width: 100%; margin-top: 10px; } 8730.filter-toggle-link { text-decoration: none; color: var(--color-dark); font-weight: 400; white-space: nowrap; border-bottom: 2px solid transparent; font-size: 1.6rem !important; display: inline-flex; align-items: center; gap: 6px; } 8731.filter-toggle-link:hover { border-bottom: none; opacity: 0.8; } 8732.view-select { appearance: none; -webkit-appearance: none; border: none; background-color: var(--color-dark); border-radius: 999px; color: white; cursor: pointer; padding: 15px 25px 15px 45px; font-family: "rum raisin", sans-serif !important; font-size: 1.8rem !important; text-align-last: center!important; text-align: center!important; width:100%;text-transform: uppercase; outline: none; letter-spacing: 0.1em; } 8733.view-select:focus { outline: none; } 8734.search-wrapper { position: relative; flex-grow: 1; max-width: 300px; } 8735.search-wrapper input { width: 100%; padding: 15px 20px; border: 1px solid var(--color-light); border-radius: 999px; background-image: none !important; background-repeat: no-repeat; } 8736.loading-overlay-section { position: absolute; inset: 0; background: var(--color-lighter); z-index: 50; display: flex; align-items: center; justify-content: center; text-align: center; border-radius: 12px; } 8737.loading-box { background: var(--color-white); border-radius: 16px; padding: 24px 26px; box-shadow: 0 8px 30px rgba(0,0,0,0.10); min-width: 280px; } 8738.loading-box h2 { margin: 0 0 6px 0; font-size: 22px; font-weight: 800; } 8739.circles-filters { padding: 10px 0; animation: fadeIn 0.3s ease; } 8740@keyframes fadeIn { from { opacity:0; transform:translateY(-5px); } to { opacity:1; transform:translateY(0); } } 8741.filter-row { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; width: 100%; } 8742.filter-row select { flex: 1; padding: 10px 12px; border: 1px solid var(--color-light); border-radius: 999px; min-width: 140px; background: var(--color-white); color: inherit; appearance: none; -webkit-appearance: none; background-image: none !important; } 8743.ride-section { margin-top: 1rem; } 8744.ride-card { border: none; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); margin-bottom: 15px; background: white; overflow: visible; color: inherit; position: relative; } 8745.ride-card.popover-open { z-index: 999; } 8746.ride-header { display: grid; grid-template-columns: 100px 1fr auto auto auto; gap: 10px; padding: 15px 20px 10px 20px; align-items: center; cursor: pointer; position: relative; } 8747@media (max-width: 700px){ 8748 .control-row-toolbar { flex-direction: column; align-items: stretch; gap: 15px; } 8749 .toolbar-left { flex-direction: column; align-items: stretch; } 8750 .search-wrapper { width: 100%; max-width: 100%; } 8751 .toolbar-actions { justify-content: center; width: 100%; } 8752 .toolbar-right { display: flex; justify-content: center; } 8753 .ride-header { grid-template-columns: 1fr auto; grid-template-areas: "date parts_rsvp" "info info"; gap: 12px; padding: 15px; padding-bottom: 15px; align-items: center; justify-items: center; } 8754 .header-date { grid-area: date; text-align: left; width: 100%; display: flex; flex-direction: row; flex-wrap: wrap; gap: 4px; align-items: center; } 8755 .header-info { grid-area: info; width: 100%; text-align: center; } 8756 /* Hamburger staat rechtsboven, direct links van de bucketlist-knop */ 8757 .actions { padding-left: 0 !important; width: auto !important; margin-right: 0 !important; flex-direction: row !important; order: 2; } 8758 .mobile-parts-rsvp-container { grid-area: parts_rsvp; display: flex; align-items: center; justify-content: flex-end; gap: 10px; width: 100%; margin-top: 0; } 8759 .participants-preview { margin: 0; order: 1; } 8760 .rsvp-actions { margin: 0; order: 3; } 8761 .ride-details { text-align: left !important; } 8762 .detail-pills-container { justify-content: flex-start !important; } 8763} 8764@media (min-width: 701px) { .mobile-parts-rsvp-container { display: contents; } } 8765.eventgravel { background: var(--color-gravel); } 8766.eventroadgravel { background: var(--color-brand-light); } 8767.eventroad { background: var(--color-lighter); } 8768.date-pill { display: inline-block; padding: 6px 12px; border-radius: 999px; text-transform: uppercase; white-space: nowrap; margin: 0; font-size: 15px; } 8769.date-pill-finish { font-size: 15px; } 8770.header-date { display: flex; flex-direction: column; gap: 0; align-items: flex-start; } 8771.header-date .date-pill:not(.date-pill-finish) { margin-bottom: 6px; } 8772@media (max-width: 700px) { .header-date { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0; } .header-date .date-pill:not(.date-pill-finish) { margin-bottom: 0; margin-right: 8px; } } 8773.inline-nav-link { font-size: 0.82em; opacity: 0.65; color: inherit; text-decoration: underline; margin-left: 8px; white-space: nowrap; } 8774.ride-route-name { margin-top: 1rem; margin-bottom: 0; } 8775.event-name-pill { color: var(--color-brand); margin: .5rem 0 1rem; } 8776.participants-preview { display: flex; align-items: center; position: relative; cursor: pointer; } 8777.participants-avatars { display:flex; align-items:center; } 8778.avatar-img, .avatar-placeholder { width: 32px; height: 32px; border-radius: 50%; border: 2px solid white; margin-left: -10px; object-fit: cover; } 8779.avatar-placeholder { background: #ddd; color: #555; font-size: 11px; display: flex; align-items: center; justify-content: center; font-weight: bold; } 8780.participants-avatars :first-child { margin-left: 0; } 8781.participants-popover .avatar-img, .participants-popover .avatar-placeholder, .circles-modal-content .avatar-img, .circles-modal-content .avatar-placeholder { margin-left: 0px; } 8782.participant-count { font-size: 0.85em; opacity: 0.8; margin-right: 12px; font-weight: 900; } 8783.participants-popover { display: none; position: absolute; top: 120%;
8783 right: 0; transform: none; width: 300px; max-width: calc(100vw - 24px); background: var(--color-white); border: 1px solid #eee; box-shadow: 0 4px 20px rgba(0,0,0,0.15); border-radius: 12px; z-index: 1000; overflow: hidden; text-align: left; } 8784@media (max-width: 700px) { 8785 .participants-preview { position: static; } 8786 .mobile-parts-rsvp-container { position: relative; } 8787 .participants-popover { position: absolute; right: 10px; left: auto; transform: none; top: calc(100% + 8px); } 8788} 8789.participants-popover.show { display: block; } 8790.participants-popover-header { padding: 10px 12px; font-weight: 900; border-bottom: 1px solid #f1f1f1; background: #fafafa; } 8791.participants-popover-list { max-height: 220px; overflow-y: auto; } 8792.participants-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-bottom: 1px solid #f6f6f6; } 8793.participants-row .pname { font-weight: 700; font-size: 0.9em; display: flex; align-items: center; gap: 6px; } 8794/* Naam duwt de datum naar rechts; min-width:0 laat lange namen afkappen. */ 8795.participants-row .pmeta { flex: 1; min-width: 0; } 8796.participants-row .pname { overflow: hidden; text-overflow: ellipsis; } 8797/* Datum waarop de RSVP of het bucketlist-vinkje gezet is â alleen admins. */ 8798.participants-date { margin-left: auto; flex: 0 0 auto; color: #9a9a9a; font-size: 0.78em; white-space: nowrap; font-variant-numeric: tabular-nums; } 8799.status-dot.bucket { background: #2EDFC2; font-size: 9px; } 8800.status-dot { width: 16px; height: 16px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 900; color: var(--color-white); } 8801.status-dot.go { background: var(--color-brand); } .status-dot.maybe { background: var(--color-action); } 8802.rsvp-actions { position: relative; display: flex; align-items: center; gap: 8px; } 8803/* Sinds de acties in een hamburger-menu zitten is dit één knop; geen vaste 8804 breedte of negatieve marge meer nodig â die duwde het menu buiten het paneel. */ 8805.actions { display: flex; align-items: center; gap: 4px; } 8806@media (min-width: 701px) { .actions { justify-self: end; margin-right: 0; padding-left: 0; } } 8807.btn-rsvp-trigger { border: 1px solid var(--color-dark); border-radius: 999px; background: var(--color-dark); cursor: pointer; font-size: 14px; font-weight: 800; display: flex; align-items: center; gap: 6px; color: white; transition: all 0.2s; padding: 2px 10px; } 8808.btn-rsvp-trigger.active-green { border-color: var(--color-brand); background: var(--color-brand); } 8809.btn-rsvp-trigger.active-orange { border-color: var(--color-action); background: var(--color-action); } 8810.btn-rsvp-trigger.active-blue { border-color: var(--color-dark); background: var(--color-dark); } 8811.rsvp-popover { display: none; position: absolute; top: 115%; right: 0; width: 300px; max-width: calc(100vw - 24px); background: var(--color-white); border: 1px solid #eee; box-shadow: 0 4px 25px rgba(0,0,0,0.2); border-radius: 12px; z-index: 2002; overflow: hidden; text-align: left; } 8812.rsvp-popover.show { display: block; } 8813.rsvp-option { padding: 12px 15px; cursor: pointer; font-weight: 700; border-bottom: 1px solid #f5f5f5; text-align: center; } 8814.rsvp-option .ri { margin-right: 10px; } 8815.rsvp-option:hover { background: #f9f9f9; } 8816.rsvp-option.danger { color: var(--c-red); border-bottom: none; } 8817.rsvp-option.info-only { cursor: default; background: var(--color-white); color: var(--color-dark); border-bottom: none; } 8818.rsvp-option.text-green { color: var(--color-brand); } 8819.rsvp-option.text-orange { color: var(--color-action); } 8820.rsvp-option.text-blue { color: var(--color-dark); } 8821.rsvp-option.info-only { color: inherit; } 8822.rsvp-option.active-item { cursor: default; pointer-events: none; color: white; } 8823.rsvp-option.active-item.green { background: var(--color-brand); border-bottom-color: rgba(255,255,255,0.25); } 8824.rsvp-option.active-item.blue { background: var(--color-dark); border-bottom-color: rgba(255,255,255,0.25); } 8825/* Ticket in huis: actiekleur, net als de RSVP-knop zelf. */ 8826.rsvp-option.active-item.orange { background: var(--color-action); border-bottom-color: rgba(255,255,255,0.25); } 8827.rsvp-divider { height: 0; margin: 0; border: none;
8827 border-top: 2px solid #f0f0f0; display: block; } 8828.btn-icon-svg { background: none; border: none; cursor: pointer; padding: 6px; display: flex; align-items: center; justify-content: center; opacity: 0.6; transition: opacity 0.2s; } 8829.btn-icon-svg:hover { opacity: 1; } 8830.btn-icon-svg svg { width: 20px; height: 20px; stroke: var(--color-dark); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } 8831.ride-details { max-height: 0; overflow: hidden; opacity: 0; transition: max-height 0.3s ease-out, opacity 0.3s ease-out, padding 0.3s ease; background: var(--color-light); color: inherit; text-align: left; padding: 0 20px; border-top: 0px solid transparent; } 8832.ride-details.open { opacity: 1; padding-top: 20px; padding-bottom: 20px; border-top: 1px solid #f0f0f0; max-height: 5000px; background: var(--color-lighter); overflow: visible; } 8833.detail-pills-container { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 15px; align-items: center; } 8834/* Zichtbaarheid van pillen en opmerkingen wordt in de markup bepaald â het 8835 element bestaat alleen als hasAccess() toegang geeft (planner-script2). 8836 Deze twee regels overschrijven display:none dat elders is achtergebleven, 8837 bijvoorbeeld in de custom-liquid-secties van het thema. */ 8838.ride-details .detail-pills-container { display: flex !important; } 8839.ride-details .comments-section { display: block !important; } 8840.detail-pill { background: var(--color-white); border: 1px solid #eee; padding: 6px 12px; border-radius: 999px; font-size: 0.9em; display: flex; align-items: center; gap: 6px; position: relative; } 8841.detail-pill span.value { font-weight: 700; } 8842.detail-pill a { color: var(--color-brand); text-decoration: none; } 8843.detail-pill a:hover { text-decoration: underline; } 8844.host-avatar-small { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; border: 1px solid #eee; } 8845.ride-detail-line { font-size: 0.95em; margin-bottom: 15px; color: inherit; } 8846.ride-detail-line strong { font-weight: 800; opacity: 0.9; margin-right: 5px; } 8847.ride-details h4, .comments-section h4 { margin-bottom: 4px; margin-top: 20px; font-weight: 800; opacity: 0.9; } 8848.comments-sub-header { font-size: 0.85em; opacity: 0.6; margin-bottom: 12px; font-style: italic; display: block; } 8849.detail-extra { white-space: pre-wrap; margin-bottom: 15px; line-height: 1.5; } 8850.detail-extra a { color: var(--color-action); text-decoration: underline; } 8851.comment-list { max-height: 200px; overflow-y: auto; margin-bottom: 10px; font-size: 0.9em; } 8852.comment-item { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #eee; gap: 10px; } 8853.comment-avatar-img, .comment-avatar-placeholder { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex-shrink: 0; border: 1px solid #eee; } 8854.comment-avatar-placeholder { background: #ddd; color: #555; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 11px; } 8855.comment-content { flex: 1; } 8856.comment-meta { font-weight: 900; margin-right: 5px; } 8857.organizer-label { font-size: 0.8em; color: var(--color-brand); font-style: italic; margin-left: 4px; font-weight: normal; } 8858.comment-date { font-size: 0.75em; opacity: 0.6; } 8859.comment-delete-btn { background: none; border: none; cursor: pointer; opacity: 0.3; padding: 4px; margin-left: 10px; display: flex; align-items: flex-start; color: var(--color-dark); flex-shrink: 0; } 8860.comment-delete-btn:hover { opacity: 1; color: var(--c-red); } 8861.comment-delete-btn svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } 8862.comment-input-group { display: flex; gap: 8px; align-items: center; } 8863.comment-input-group input { flex: 1; padding: 15px 15px; border: 1px solid #ccc; border-radius: 999px; background: var(--color-white); } 8864.current-user-avatar-small { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; border: 1px solid #ddd; } 8865.current-user-placeholder-small { width: 40px; height: 40px; border-radius: 50%; background: #ddd; color: #555; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; } 8866.btn-send-comment { background: var(--color-action); color: white; border: none; border-radius: 999px; padding: 10px 20px; font-weight: 700; cursor: pointer; display: flex; align-items: center; justify-content: center; } 8867.mobile-icon { display: none; font-size: 1.2em; line-height: 1; } 8868@media (max-width: 600px) { 8869 .btn-send-comment { padding: 10px; width: 44px; height: 44px; border-radius: 50%; } 8870 .desktop-text { display: none; } 8871 .mobile-icon { display: block; } 8872 /* Date inputs: zorg dat placeholder-tekst zichtbaar is */ 8873 .form-group input[type="date"], 8874 .form-group input[type="time"] { color: #222; -webkit-text-fill-color: #222; font-size: 16px; } 8875 /* translate altijd tonen op mobiel */ 8876 .btn-translate { display: inline-block !important; margin-top: 4px; } 8877 /* Verhoog modal tot volledige hoogte zodat alles bereikbaar is */ 8878 .circles-modal-content { margin: 0 auto; border-radius: 16px 16px 0 0; max-height: 96vh; } 8879} 8880.circles-modal { display: none; position: fixed; z-index: 2000; inset: 0; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(2px); overflow: hidden; touch-action: none; } 8881.circles-modal-content { background-color: #fefefe; margin: 2% auto; padding: 25px; padding-bottom: 60px; border: 1px solid #ccc; width: 95%; max-width: 500px; border-radius: 16px; position: relative; max-height: 90vh; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; touch-action: pan-y; } 8882.circles-modal-content:has(.full-width) { padding-bottom: 120px; } 8883/* Plan Rondo modal: overlay scrollt zodat popovers niet worden geclipt */ 8884#planRondoModal { overflow-y: auto; touch-action: pan-y; z-index: 1999; }#planRondoModal > .circles-modal-content { overflow-y: visible !important; max-height: none !important; margin: 30px auto 60px; } 8885.circles-modal h2 { margin-top: 0; } 8886.close-modal { position: absolute; right: 20px; top: 15px; font-size: 28px; font-weight: bold; cursor: pointer; opacity: 0.5; } 8887.form-group { margin-bottom: 15px; width: 100%; } 8888.form-group label h4 { margin-top: 1rem; margin-bottom: 5px; font-size: 0.9em; opacity: 0.85; } 8889.form-group input, .form-group select, .form-group textarea { width: 100%; padding: 10px 12px; border: 1px solid #ccc; border-radius: 8px; box-sizing: border-box; font-family: inherit; background: var(--color-white); } 8890.form-row.profile-preview { display: flex; align-items: center; gap: 10px; } 8891.form-row.split { display: flex; gap: 10px; } 8892.public-group input { width: inherit; } 8893.date-changed-group input { width: inherit; } 8894.lock-message { background: #fff4e5; color: #663c00; padding: 10px; font-size: 0.9em; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #ff9800; display: none; } 8895.route-info-box { background: #f9f9f9; padding: 12px; border-radius: 12px; margin-bottom: 15px; border: 1px solid #eee; } 8896.route-info-title { font-weight: 700; font-size: 1.05em; margin-bottom: 6px; }
8897.rich-text-controls { display: flex; gap: 5px; margin-bottom: 5px; } 8898.days-checkboxes { display: flex; flex-direction: row; flex-wrap: wrap; gap: 10px; } 8899.days-checkboxes label { display: flex; align-items: center; gap: 8px; font-weight: normal; cursor: pointer; background: #f8f8f8; padding: 8px 12px; border-radius: 8px; border: 1px solid #eee; margin-bottom: 0; flex-basis: auto; } 8900.days-checkboxes input { margin: 0; width: auto; } 8901.pac-container { z-index: 2005 !important; } 8902.delete-container { margin-top: 10px; text-align: center; padding-top: 15px; } 8903.radio-group-inline { display: flex; gap: 20px; align-items: center; margin-top: 5px; } 8904.radio-label { margin-bottom: 0 !important; cursor: pointer; display: flex; align-items: center; gap: 6px; font-weight: normal !important; } 8905.radio-label input { margin: 0; width: auto; } 8906.rich-text-container { border: 1px solid #ccc; border-radius: 8px; overflow: hidden; background: var(--color-white); display: flex; flex-direction: column; } 8907.rich-text-toolbar { background: #fcfcfc; border-bottom: 1px solid #e0e0e0; padding: 6px 10px; display: flex; align-items: center; gap: 8px; } 8908.rich-text-toolbar button { background: transparent; border: 1px solid transparent; border-radius: 4px; cursor: pointer; padding: 4px 8px; min-width: 28px; height: 30px; display: flex; align-items: center; justify-content: center; color: #333; font-weight: bold; font-family: serif; font-size: 1.2rem !important; transition: background 0.2s; } 8909.rich-text-toolbar button:hover { background: #eee; border-color: #ddd; } 8910.rich-content-area { padding: 12px; width: 100%; min-height: 120px; display: block !important; background-color: var(--color-white); border: 1px solid transparent; color: inherit; font-family: inherit; outline: none; overflow-y: auto; } 8911.toolbar-divider { width: 1px; height: 20px; background: #ddd; margin: 0 4px; } 8912.btn-text-danger { background: none; border: none; color: var(--c-red); font-weight: bold; cursor: pointer; font-size: 1rem; opacity: 0.8; } 8913.btn-text-danger:hover { opacity: 1; } 8914.public-group { background: #f0f0f0; padding: 10px; border-radius: 999px; } 8915.date-changed-group { background: #fff4e5; padding: 10px; border-radius: 999px; } 8916.checkbox-label { display: flex; align-items: center; cursor: pointer; } 8917.checkbox-auto { width: auto; margin-right: 8px; } 8918#modalAvatarContainer { padding-top: 11px; } 8919.modal-title-row { display: flex; align-items: center; gap: 4px; margin-bottom: 12px; } 8920.modal-title-row h2 { margin: 0; } 8921.btn-modal-close { margin-left: auto; } 8922.btn-icon-edit { background: none; border: none; cursor: pointer; padding: 5px; color: var(--color-dark); opacity: 1; transition: all 0.2s; display: flex; align-items: center; justify-content: center; } 8923.btn-icon-edit:hover { opacity: 1; color: var(--color-action); transform: scale(1.1); } 8924.btn-icon-edit svg { width: 20px; height: 20px; } 8925.btn-modal-close svg { stroke-width: 6; } 8926.profile-modal-content { max-width: 480px; text-align: center; } 8927@media (min-width: 768px) { .profile-modal-content { max-width: 560px; } } 8928.profile-header-col { display: flex; flex-direction: column; align-items: center; margin-bottom: 20px; gap: 15px; } 8929.profile-edit-avatar { width: 100px; height: 100px; border-radius: 50%; object-fit: cover; background-color: #f4f4f4; border: 1px solid #ddd; } 8930.profile-tags-list { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: 5px; } 8931.profile-tag-pill { background: var(--color-brand); color: white; padding: 4px 10px; border-radius: 999px; font-size: 0.75em; font-weight: bold; letter-spacing: 0.05em; text-transform: uppercase; } 8932.loading-text { color: #666; font-style: italic; margin: 0; } 8933.form-group-profile { margin-bottom: 16px; width: 100%; text-align: left; } 8934.label-bold { display: block; font-weight: bold; margin-bottom: 5px; font-size: 0.9em; color: #555; } 8935.input-pill-centered { width: 100%; padding: 10px 16px; border: 1px solid #ccc; text-align: center; border-radius: 999px; box-sizing: border-box; font-size: 1em; } 8936.input-pill-select { appearance: none; -webkit-appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 16px center; padding-right: 36px; cursor: pointer; } 8937.input-pill-textarea { width: 100%; padding: 10px 16px; border: 1px solid #ccc; border-radius: 16px; box-sizing: border-box; font-size: 1em; font-family: inherit; resize: vertical; min-height: 80px; } 8938.profile-section-title { font-size: 0.75em; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-action); margin: 24px 0 12px; border-bottom: 1px solid #eee; padding-bottom: 6px; } 8939.input-prefix-group { display: flex; align-items: center; border: 1px solid #ccc; border-radius: 999px; overflow: hidden; background: var(--color-white); } 8940.input-prefix { padding: 10px 0 10px 16px; font-size: 0.85em; color: #888; white-space: nowrap; flex-shrink: 0; } 8941.input-prefix-field { flex: 1; border: none; outline: none; padding: 10px 16px 10px 4px; font-size: 1em; min-width: 0; background: transparent; } 8942.profile-public-toggle { margin-top: 8px; } 8943.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; cursor: pointer; } 8944.toggle-label-text { font-weight: bold; font-size: 0.95em; } 8945.toggle-hint { font-size: 0.8em; color: #888; margin: 4px 0 0; } 8946.toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; } 8947.toggle-switch input { opacity: 0; width: 0; height: 0; } 8948.toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .3s; border-radius: 24px; } 8949.toggle-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .3s; border-radius: 50%; } 8950.toggle-switch input:checked + .toggle-slider { background-color: var(--color-action); } 8951.toggle-switch input:checked + .toggle-slider:before { transform: translateX(20px); } 8952.input-file-hidden { display: none; } 8953.btn-upload-label { display: inline-block; padding: 8px 16px; background: #f1f1f1; color: #333; border: 1px solid #ccc; border-radius: 999px; cursor: pointer; font-weight: 700; font-size: 0.9em; transition: background 0.2s; } 8954.btn-upload-label:hover { background: #e0e0e0; } 8955.file-name-display { margin-top: 8px; font-size: 0.85em; color: #666; font-style: italic; word-break: break-all; } 8956.link-buttons-container { margin-top: 15px; border-top: 1px solid #eee; padding-top: 10px; display: flex; gap: 15px; align-items: center; } 8957@media (max-width: 700px) { .link-buttons-container { flex-direction: column; align-items: flex-start; gap: 8px; } } 8958.link-btn-action { font-weight: 900; color: var(--color-action); text-decoration: none; } 8959.link-btn-action:hover { text-decoration: underline; } 8960.link-btn-action:nth-child(1) { padding-right: 3rem; } 8961.link-btn-action::after { position: relative; display: inline; content: " â"; } 8962.pointer-events-none { pointer-events: none; } 8963.share-btn-wrapper { position: relative; } 8964.share-popover { display: none; position: absolute; top: 100%; right: 0; width: 190px; background: var(--color-white); border: 1px solid #eee; box-shadow: 0 4px 25px rgba(0,0,0,0.2); border-radius: 12px; z-index: 2003; overflow: hidden; text-align: left; } 8965.share-popover.show { display: block; } 8966.share-option { padding: 10px 14px; cursor: pointer; font-weight: 600; font-size: 1.3rem !important; border-bottom: 1px solid #f5f5f5; display: flex; align-items: center; gap: 10px; color: #333; transition: background 0.15s; } 8967.share-option svg { flex-shrink: 0; opacity: 0.75; stroke: var(--color-dark); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } 8968.share-option:hover { background: #f5f5f5; } 8969.share-option:hover svg { opacity: 1; } 8970.share-option:last-child { border-bottom: none; } 8971.share-option.copied { color: var(--color-brand); } 8972.share-option.copied svg { opacity: 1; stroke: var(--color-brand); } 8973/* ââ Actie-menu (hamburger) âââââââââââââââââââââââââââââââââââââââââ */ 8974.action-menu-wrapper { position: relative; } 8975.action-popover { display: none; position: absolute; top: 100%; right: 0; width: 220px; background: var(--color-white); border: 1px solid #eee; box-shadow: 0 4px 25px rgba(0,0,0,0.2); border-radius: 12px; z-index: 2004; overflow: hidden; text-align: left; } 8976.action-popover.show { display: block; } 8977.action-option { padding: 10px 14px; cursor: pointer; font-weight: 600; font-size: 1.3rem !important; border-bottom: 1px solid #f5f5f5; display: flex; align-items: center; gap: 10px; color: #333; transition: background 0.15s; text-decoration: none; } 8978.action-option:last-child { border-bottom: none; } 8979.action-option:hover { background: #f5f5f5; } 8980.action-option svg { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.75; stroke: var(--color-dark); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } 8981.action-option:hover svg { opacity: 1; } 8982.action-option::after { display: none !important; } 8983.action-option.copied { color: var(--color-brand); } 8984.action-option.copied svg { opacity: 1; stroke: var(--color-brand); } 8985/* ZOEK WISSEN + RESULTAAT BALK */ 8986.search-wrapper { position: relative; } 8987.search-clear-btn { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; font-size: 1.3rem; color: #999; line-height: 1; padding: 2px 4px; } 8988.search-clear-btn:hover { color: var(--color-dark); } 8989.search-result-bar { margin-top: 16px; margin-bottom: 12px; font-size: 1.35rem; color: #666; padding: 0 4px; text-align: center; } 8990.load-more-bar { text-align: center; margin: 20px 0 8px; } 8991.load-more-bar a { font-size: 1.7rem; font-weight: 700; color: var(--color-action); text-decoration: none; opacity: 1; } 8992.load-more-bar a:hover { opacity: 1; text-decoration: underline; } 8993.search-result-bar strong { color: var(--color-dark); } 8994.search-result-clear { color: var(--color-brand); font-weight: 700; text-decoration: none; } 8995.search-result-clear:hover { text-decoration: underline; } 8996.comment-textarea { resize: none; overflow: hidden; min-height: 36px; max-height: 120px; padding: 8px 12px; border-radius: 20px; border: 1px solid #ddd; font-family: inherit; font-size: 0.9em; width: 100%; box-sizing: border-box; line-height: 1.4; } 8997.comment-textarea:focus { outline: none; border-color: var(--color-brand); } 8998.btn-translate { font-size: 0.75em; font-weight: 600; background: var(--color-brand); color: var(--color-white); border: none; border-radius: 20px; padding: 3px 10px; cursor: pointer; margin-left: 8px; vertical-align: middle; opacity: 0.85; } 8999.btn-translate:hover { opacity: 1; } 9000.route-map-wrap { margin: 12px 0; border-radius: 12px; overflow: hidden; } 9001.route-map-img { width: 100%; aspect-ratio: 3/2; object-fit: cover; display: block; } 9002.participants-list .load-more-bar { font-size: 0.9rem; margin: 6px 0 4px; } 9003.participants-list .load-more-bar a { font-size: 0.9rem; } 9004</style> 9005 9006 9007 9008<style> 9009 .actions a[target="_blank"]::after { display:none !important; content:none !important; } 9010 /* ââ Wrapper (We leunen op globale planner CSS voor het lettertype) ââ */ 9011 .gr-pal-wrap { max-width:900px; margin:0 auto; padding:0 16px 30px; box-sizing:border-box; } 9012 /* ââ Stats grid ââ */ 9013 .gr-pal-stats-grid { display:flex; gap:10px; flex-wrap:wrap; margin-bottom:28px; } 9014 .gr-pal-stat { flex:1; min-width:90px; background:var(--color-white); border-radius:14px; padding:14px 12px; text-align:center; box-shadow:0 1px 6px rgba(0,0,0,.06); display:flex; flex-direction:column; align-items:center; justify-content:center; } 9015 .gr-pal-stat-lbl { font-family: 'Rum Raisin', sans-serif !important; color: rgba(var(--color-foreground), 0.75); line-height: 1em; display:block; font-size:.68em; text-transform:uppercase; letter-spacing:.05em; margin-bottom:4px; } 9016 .gr-pal-stat-val { display:block; font-size:1.4em; font-weight:900; color:var(--color-dark,#271D62); line-height:1.1; } 9017 /* ââ Controls (zoek + sorteer) ââ */
9018 .gr-pal-controls { display:flex; gap:10px; align-items:center; margin-bottom:18px; } 9019 .gr-pal-controls .gr-inp { flex:1; min-width:0; } 9020 .gr-pal-controls .gr-sel { flex-shrink:0; width:auto; min-width:150px; } 9021 /* ââ Add button ââ */ 9022 .gr-pal-add-btn { display:block; width:100%; padding:14px 20px; background:var(--color-action); color:var(--color-white); border:none; border-radius:999px; font-size:1em; font-weight:700; cursor:pointer; text-transform:uppercase; letter-spacing:.04em; margin-bottom:28px; transition:opacity .2s; } 9023 .gr-pal-add-btn:hover { opacity:.88; } 9024 /* ââ Ride list ââ */ 9025 .gr-pal-list { display:flex; flex-direction:column; } 9026 .gr-pal-list .ride-card { cursor:pointer; background: var(--color-white); margin-bottom: 15px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); } 9027 /* Eventnaam en Ticketverkoop verdwijnen zodra "Bucketlist" is gekozen bij 9028 "Rit aanmaken". Een eigen klasse en niet de bestaande .hidden, want die 9029 wordt door andere stukken code aan- en uitgezet â twee partijen op dezelfde 9030 klasse gaan elkaar tegenwerken. */ 9031 .gr-bucket-verborgen { display: none !important; } 9032 .gr-pal-list h3.ride-route-name { margin: 0; font-size: 1.2em; } 9033 /* Slotje achter de titel: deze rit staat op "Zichtbaar voor anderen? = Nee" 9034 en is dus alleen op je eigen dashboard te zien. */ 9035 .gr-pal-lock { 9036 display: inline-flex; 9037 align-items: center; 9038 margin-left: .4em; 9039 color: var(--gr-grey-500, #8a8a8a); 9040 opacity: .75; 9041 } 9042 .gr-pal-lock svg { display: block; } 9043 .gr-pal-list h4.date-pill { margin: 0; display: inline-block; } 9044 .gr-pal-list h4 { margin-bottom: 4px; margin-top: 20px; font-weight: 800; opacity: 0.9; font-size: 0.9em; color: var(--color-dark); } 9045 .gr-pal-list .detail-extra { white-space: pre-wrap; margin-bottom: 15px; line-height: 1.5; color: #555; font-size: 0.95em; } 9046 /* ââ Kaartkop ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 9047 De kaart heeft ook class .ride-header; planner-css geeft die vijf kolommen 9048 met dezelfde specificiteit, en zet `.actions { margin-right:-100px }` boven 9049 701px. Daarom: expliciete gebiedsnamen, en desktop/mobiel elk in hun eigen 9050 mediaquery zodat ze elkaar niet kunnen overschrijven. */ 9051 .gr-pal-ride-header { display: grid !important; padding: 15px; gap: 15px; align-items: center; } 9052 .gr-pal-ride-header .header-date { grid-area: date; } 9053 .gr-pal-ride-header .header-info { grid-area: info; } 9054 .gr-pal-ride-header .gr-pal-rating-cell { grid-area: rating; display: flex; align-items: center; } 9055 .gr-pal-ride-header .actions { grid-area: actions; display: flex; align-items: center; } 9056 .gr-pal-ride-header .header-date .date-pill { margin-bottom: 0; } 9057 .gr-pal-stars { display: flex; align-items: center; gap: 2px; flex-shrink: 0; } 9058 .gr-pal-stars img { width: 14px; height: 14px; } 9059 .gr-pal-stars-num { font-size:.78em; font-weight:900; color:var(--color-dark,#271D62); margin-left:5px; white-space:nowrap; } 9060 9061 /* ââ Desktop ââ datum | titel | beoordeling | hamburger ââ */ 9062 @media (min-width: 701px) { 9063 .gr-pal-ride-header { 9064 grid-template-columns: 110px 1fr auto auto !important; 9065 grid-template-areas: "date info rating actions" !important; 9066 } 9067 .gr-pal-ride-header .header-date { justify-content: center; align-self: center; } 9068 .gr-pal-ride-header .gr-pal-rating-cell { justify-self: end; align-self: center; justify-content: flex-end; } 9069 .gr-pal-ride-header .gr-pal-stars { justify-content: flex-end; } 9070 /* margin-right:-100px uit planner-css terugdraaien, anders hangt de 9071 hamburger buiten het paneel */ 9072 .gr-pal-ride-header .actions { 9073 justify-self: end; align-self: center; 9074 flex-direction: row !important; 9075 margin-right: 0 !important; padding-left: 0 !important; width: auto !important; 9076 } 9077 } 9078 9079 /* ââ Mobiel ââ datum + hamburger boven, titel, beoordeling onderin ââ */ 9080 @media (max-width: 700px) { 9081 .gr-pal-ride-header { 9082 grid-template-columns: 1fr auto !important; 9083 grid-template-areas: "date actions" "info info" "rating rating" !important; 9084 text-align: center; 9085 }
9086 .gr-pal-ride-header .header-date { 9087 width: 100%; text-align: left; 9088 justify-content: flex-start; justify-self: start; align-self: center; 9089 } 9090 .gr-pal-ride-header .header-info { width: 100%; text-align: center; justify-self: stretch; } 9091 .gr-pal-ride-header .gr-pal-rating-cell { justify-self: center; justify-content: center; width: 100%; margin-top: 5px; } 9092 .gr-pal-ride-header .gr-pal-stars { justify-content: center; margin-top: 4px; } 9093 .gr-pal-ride-header .actions { 9094 justify-self: end; align-self: center; 9095 margin-right: 0 !important; padding-left: 0 !important; width: auto !important; 9096 } 9097 } 9098 9099 .gr-pal-menu-wrapper { position: relative; } 9100 .gr-pal-action-popover { 9101 display: none; position: absolute; top: 100%; right: 0; width: 220px; 9102 background:var(--color-white); border:1px solid #eee; box-shadow:0 4px 25px rgba(0,0,0,.2); 9103 border-radius:12px; z-index:2004; overflow:hidden; text-align:left; 9104 } 9105 .gr-pal-action-popover.show { display:block; } 9106 .gr-pal-action-option { 9107 padding:10px 14px; cursor:pointer; font-weight:600; font-size:1.3rem; 9108 border-bottom:1px solid #f5f5f5; display:flex; align-items:center; gap:10px; 9109 color:#333; transition:background .15s; text-decoration:none; 9110 } 9111 .gr-pal-action-option:last-child { border-bottom:none; } 9112 .gr-pal-action-option:hover { background:#f5f5f5; } 9113 /* Verwijzing naar de activiteit, onderaan de uitklap in de palmareslijst. 9114 Een <a> en geen knop: het thema zet `button` op 1.8rem, en dit hoort een 9115 bescheiden link te zijn. Het pijltje dat het thema achter externe links 9116 hangt gaat eraf â het icoon vooraan zegt het al. */ 9117 .gr-pal-activiteit-link { 9118 display: inline-flex; align-items: center; gap: 7px; 9119 margin-top: 14px; padding: 8px 0; 9120 color: var(--color-dark, #271D62); 9121 font-size: .88em; line-height: 1.4; 9122 text-decoration: underline; 9123 } 9124 .gr-pal-activiteit-link:hover { opacity: .75; } 9125 .gr-pal-activiteit-link svg { width: 16px; height: 16px; flex: 0 0 auto; } 9126 .gr-pal-activiteit-link[target="_blank"]::after { content: none !important; display: none !important; } 9127 9128 .gr-pal-action-option svg { width:18px; height:18px; flex-shrink:0; opacity:.75; 9129 stroke:var(--color-dark,#271D62); fill:none; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; } 9130 .gr-pal-action-option:hover svg { opacity:1; } 9131 .gr-pal-action-option::after { display:none !important; } 9132 /* ââ Detailpanel: extra palmares styling ââ */ 9133 .gr-pal-list .ride-details { max-height:0; overflow:hidden; transition:max-height 0.3s ease-out, opacity 0.3s ease-out, padding 0.3s ease; opacity:0; background: var(--color-light); padding: 0 20px; cursor:default; } 9134 .gr-pal-list .ride-details.open { opacity:1; padding-top:20px; padding-bottom:20px; border-top:1px solid #f0f0f0; max-height:5000px; background:var(--color-lighter); } 9135 .gr-pal-plan-link::after { content:none !important; } 9136 .gr-pal-detail-link { font-size:.85em; font-weight:700; color:var(--color-action,#2EDFC2); text-decoration:none; } 9137 .gr-pal-detail-link:hover { text-decoration:underline; } 9138 /* ââ Load more ââ */ 9139 .gr-pal-loadmore { text-align:center; padding:20px 0 0; } 9140 .gr-pal-loadmore a { font-size:1em; font-weight:700; color:var(--color-action); text-decoration:none; cursor:pointer; } 9141 /* ââ Modals (gelijke stijl als Planner) ââ */ 9142 .gr-modal-overlay { position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,.5); z-index:9999; display:none; align-items:center; justify-content:center; backdrop-filter:blur(2px); } 9143 .gr-modal-content { background:var(--color-white); padding:25px; border-radius:16px; width:95%; max-width:500px; max-height:90vh; overflow-y:auto; position:relative; box-shadow:0 10px 25px rgba(0,0,0,.2); animation:grFadeIn .3s; } 9144 .modal-title-row { display:flex; align-items:center; gap:4px; margin-bottom:12px; } 9145 .modal-title-row h2 { margin:0; font-size:1.6em; color:var(--color-dark); } 9146 .btn-modal-close { margin-left:auto; } 9147 .btn-icon-edit { background:none; border:none; cursor:pointer; padding:5px; color:var(--color-dark); opacity:1; transition:all 0.2s; display:flex; align-items:center; justify-content:center; } 9148 .btn-icon-edit:hover { opacity:1; color:var(--color-action); transform:scale(1.1); } 9149 .btn-icon-edit svg { width:24px; height:24px; } 9150 .btn-modal-close svg { stroke-width: 6; } 9151 .gr-form-section { margin-bottom:15px; width:100%; } 9152 .gr-form-section label h4 { margin-top:1rem; margin-bottom:5px; font-size:0.9em; opacity:0.85; font-weight:bold; } 9153 .gr-section-help { display:block; font-size:.82em; color:#999; margin:0 0 8px; font-style:italic; } 9154 .gr-inp, .gr-sel, .gr-txta { width:100%; padding:10px 12px; border:1px solid #ccc; border-radius:8px; font-family:inherit; background:var(--color-white); box-sizing:border-box; } 9155 .gr-inp:focus, .gr-sel:focus, .gr-txta:focus { border-color:var(--color-brand); outline:none; } 9156 .form-row.split { display:flex; gap:10px; } 9157 .flex-1 { flex:1; } 9158 .flex-2 { flex:2; } 9159 .gr-radio-group { display:flex; gap:20px; align-items:center; margin-top:5px; } 9160 .gr-radio-label { display:flex; align-items:center; gap:6px; font-weight:normal; cursor:pointer; } 9161 .gr-radio-label input { margin:0; width:auto; } 9162 /* text-transform:none stond hier eerder en overrulede de uppercase uit 9163 planner-css â daardoor waren o.a. "+ Toevoegen", "Bestel je Tickets" en 9164 "Login of gratis account" ineens niet meer in kapitalen. */ 9165 .btn-primary { background:var(--color-action); color:white; padding:12px 30px; border:none; cursor:pointer; border-radius:999px; font-weight:700; font-size:1.8rem !important; width:100%; margin-top:10px; display:block; text-align:center; text-transform:uppercase; font-family:"rum raisin", sans-serif; letter-spacing:.1rem; } 9166 .btn-primary:hover { opacity:.9; } 9167 .btn-primary:disabled { opacity:.5; cursor:not-allowed; } 9168 .btn-text-danger { background:none; border:none;
9168 color:var(--c-red,#E53935); font-weight:bold; cursor:pointer; font-size:1rem; opacity:0.8; } 9169 .btn-text-danger:hover { opacity:1; } 9170 @keyframes grFadeIn { from{opacity:0;transform:translateY(-10px)} to{opacity:1;transform:translateY(0)} } 9171 @media(max-width:600px) { 9172 .gr-modal-content { margin:0 auto; border-radius:16px 16px 0 0; max-height:96vh; } 9173 .gr-inp[type="date"], .gr-inp[type="time"] { color:#222; -webkit-text-fill-color:#222; font-size:16px; } 9174 } 9175</style> 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195<style> 9196 /* ââ Bucketlist-modals (uit bucketlist-button.html) ââââââââââââââââââ 9197 Deze CSS staat hier zodat de login-popup er op ELKE pagina hetzelfde 9198 uitziet, ook waar het bucketlist-snippet niet geladen wordt. */ 9199 #grBucketlistLoginModal, 9200 #grBucketlistModal { 9201 display: none !important; 9202 position: fixed !important; 9203 top: 0 !important; right: 0 !important; bottom: 0 !important; left: 0 !important; 9204 z-index: 99999 !important; 9205 background: rgba(0,0,0,0.5); 9206 align-items: center !important; justify-content: center !important; 9207 padding: 20px; box-sizing: border-box; 9208 } 9209 #grBucketlistLoginModal.open, 9210 #grBucketlistModal.open { display: flex !important; } 9211 .gr-bl-modal-box { 9212 background: var(--color-white) !important; border-radius: 16px; padding: 46px 28px 28px; 9213 text-align: center; position: relative; font-family: inherit; color: var(--color-dark); 9214 width: 100%; max-width: 380px; box-sizing: border-box; 9215 display: block !important; flex: 0 0 auto; 9216 } 9217 .gr-bl-modal-close { 9218 position: absolute; top: 2px; right: 2px; background: none; border: none; 9219 font-size: 50px !important; cursor: pointer; color: inherit; line-height: 1; 9220 } 9221 .gr-bl-modal-box p { 9222 margin: 0 0 20px; font-size: 1.05em; font-weight: 700; line-height: 1.4; 9223 } 9224 #grBucketlistModal button, 9225 #grBucketlistLoginModal button { margin-bottom: 10px; } 9226 a.button[href*="#"]::after { content: " â"; } 9227 .gr-bl-btn-link { 9228 display: block; width: 100%; padding: 8px; font-family: inherit; 9229 font-size: 0.9em; text-transform: uppercase; letter-spacing: 0.04em; 9230 color: var(--color-dark); text-align: center; cursor: pointer; background: none; 9231 border: none; text-decoration: underline; opacity: 0.7; 9232 } 9233</style> 9234 9235 9236 <style> 9237 :where(.circles-modal) { 9238 display: none; position: fixed; z-index: 2000; inset: 0; 9239 background: rgba(0,0,0,.5); overflow-y: auto; 9240 } 9241 :where(.circles-modal-content) { 9242 background: var(--color-white); margin: 5% auto 40px; padding: 25px; width: 90%; 9243 max-width: 480px; border-radius: 20px; position: relative; 9244 font-family: 'ashemore', sans-serif; color: var(--color-dark); 9245 } 9246 :where(.circles-modal .close-modal) { 9247 position: absolute; right: 20px; top: 15px; font-size: 28px; 9248 font-weight: bold; cursor: pointer; opacity: .5; 9249 } 9250 :where(.circles-modal .btn-primary), :where(.circles-modal .btn-secondary) { 9251 padding: 12px 30px; border-radius: 999px; font-weight: 700; 9252 font-size: 1.8rem; text-transform: uppercase; letter-spacing: .1rem; 9253 font-family: 'rum raisin', sans-serif; cursor: pointer; 9254 text-decoration: none; display: inline-block; border: 2px solid transparent; 9255 } 9256 :where(.circles-modal .btn-primary) { background: var(--color-action, #E9483F); color: var(--color-white); } 9257 :where(.circles-modal .btn-secondary) { 9258 background: var(--color-white); color: var(--color-brand, #271D62); 9259 border-color: var(--color-brand, #271D62); 9260 } 9261 /* Meer info: color-dark in plaats van de brandkleur. */ 9262 :where(.circles-modal #ticketModalInfoBtn) { 9263 color: var(--color-dark, #271D62); 9264 border-color: var(--color-dark, #271D62); 9265 } 9266 </style> 9267 <div id="ticketModal" class="circles-modal"> 9268 <div class="circles-modal-content" style="text-align: center; padding: 40px 25px;"> 9269 <span class="close-modal" onclick="event.stopPropagation();document.getElementById('ticketModal').style.display='none';document.body.classList.remove('modal-open');">Ã</span> 9270 <p style="margin-bottom: 25px; font-size: 1.1em; font-weight: 700; line-height: 1.4; color: var(--color-dark);">Would you like to join this event?</p> 9271 <div style="display: flex; flex-direction: column; gap: 10px; align-items: center;"> 9272 <a id="ticketModalOrderBtn" href="#" target="_blank" class="btn-primary" style="text-decoration: none; display: inline-block;">Order your Tickets</a><a id="ticketModalPackageBtn" href="#" target="_blank" class="btn-secondary" style="text-decoration: none; display: none;">Bestel Rondopakket</a> 9273 <a id="ticketModalInfoBtn" href="#" target="_blank" class="btn-secondary" style="text-decoration: none; display: inline-block;">More info</a> 9274 </div> 9275 </div> 9276 </div> 9277
9277<script> 9278 /* Enige definitie van showTicketModal â stond eerder in planner-script2 en 9279 werkte daardoor alleen waar de planner geladen is. Twee knoppen als er geen 9280 pakket-URL is (event-tickets + meer info), drie als die er wel is: dan gaat 9281 het om "Bestel deze Rondo" bij een event en is de keuze tickets of pakket. 9282 Meer info wijst altijd naar de pagina zonder #booking. */ 9283 window.showTicketModal = function (boekUrl, shopUrl, pakketUrl) { 9284 var gEl = function (id) { return document.getElementById(id); }; 9285 var vraag = document.querySelector('#ticketModal p'); 9286 if (vraag) vraag.textContent = pakketUrl 9287 ? "Wil je meedoen aan het event, of op een andere datum met het Rondopakket?" 9288 : "Would you like to join this event?"; 9289 var pakket = gEl('ticketModalPackageBtn'); 9290 if (pakket) { 9291 if (pakketUrl) { 9292 pakket.href = pakketUrl; 9293 pakket.textContent = "Bestel Rondopakket"; 9294 pakket.style.display = 'inline-block'; 9295 } else { pakket.style.display = 'none'; } 9296 } 9297 var bestel = gEl('ticketModalOrderBtn'); 9298 if (bestel) { 9299 bestel.href = boekUrl || '#'; 9300 bestel.textContent = pakketUrl 9301 ? "EVENT TICKETS BOEKEN" 9302 : "Order your Tickets"; 9303 bestel.style.display = ''; 9304 } 9305 var info = gEl('ticketModalInfoBtn'); 9306 if (info) { 9307 info.href = (pakketUrl ? pakketUrl.split('#')[0] : shopUrl) || '#'; 9308 info.textContent = "More info"; 9309 info.style.display = ''; 9310 } 9311 var modal = gEl('ticketModal'); 9312 if (modal) { modal.style.display = 'block'; document.body.classList.add('modal-open'); } 9313 document.querySelectorAll('.rsvp-popover').forEach(function (p) { p.classList.remove('open'); }); 9314 }; 9315 </script>
9315 9316 9317 <!-- Inloggen vereist â gebruikt door de bucketlist-knop én de atlas-kaart --> 9318 <div id="grBucketlistLoginModal" onclick="if(event.target===this)this.classList.remove('open')"> 9319 <div class="gr-bl-modal-box"> 9320 <button class="gr-bl-modal-close" onclick="document.getElementById('grBucketlistLoginModal').classList.remove('open')">×</button> 9321 <p>Log in to see your planned rides.</p> 9322 <button class="btn btn-primary" onclick="window.location.href='https://granrondo.cc/customer_authentication/login?return_to=%2Fen%2Fpages%2Fdashboard&locale=en'"> 9323 Log in or create free account 9324 </button> 9325 </div> 9326 </div> 9327 9328 9329 9330 <!-- INLOGGEN VEREIST --> 9331 <div id="loginModal" class="circles-modal"> 9332 <div class="circles-modal-content" style="text-align: center; padding: 40px 25px;"> 9333 <span class="close-modal close-login-modal" onclick="event.stopPropagation();document.getElementById('loginModal').style.display='none';document.body.classList.remove('modal-open');">×</span> 9334 <p style="margin-bottom: 20px; font-size: 1.25em; font-weight: 800; line-height: 1.35; color: var(--color-dark);">You need to be logged in to view this content.<br>Log in om je Rondo's te plannen en te bewaren.</p> 9335 <div style="display: flex; flex-direction: column; gap: 10px; align-items: center;"> 9336 <a href="https://account.granrondo.cc" target="_blank" rel="noopener" class="btn-primary" style="text-decoration: none; display: inline-block;">Log in or create free account</a> 9337 </div> 9338 </div> 9339 </div> 9340 9341 <!-- GEEN TOEGANG / UPGRADE --> 9342 <div id="upgradeModal" class="circles-modal"> 9343 <div class="circles-modal-content" style="text-align: center; padding: 40px 25px;"> 9344 <span class="close-modal close-upgrade-modal" onclick="event.stopPropagation();document.getElementById('upgradeModal').style.display='none';document.body.classList.remove('modal-open');">×</span> 9345 <p style="margin-bottom: 25px; font-size: 1.1em; font-weight: 700; line-height: 1.4; color: var(--color-dark);">You don't have access to this info. Order this Rondo or become a Rondoneur to view this ride.</p> 9346 <div style="display: flex; flex-direction: column; gap: 10px; align-items: center;"> 9347 <a id="upgradeModalOrderBtn" href="https://granrondo.cc/en/collections/all" target="_blank" class="btn-primary" style="text-decoration: none; display: inline-block;">Order Rondo</a> 9348 <a href="https://granrondo.cc/en/join" target="_blank" class="btn-secondary" style="text-decoration: none; display: inline-block;">Become a Rondoneur</a> 9349 </div> 9350 </div> 9351 </div> 9352 9353 <!-- + ZET OP BUCKETLIST --> 9354 <div id="addToBucketlistModal" class="circles-modal" style="display:none;" onclick="if(event.target===this){this.style.display='none';document.body.classList.remove('modal-open');}"> 9355 <div class="circles-modal-content" style="position:relative;max-width:520px;width:92%;margin:auto;"> 9356 <div class="atbl-header"> 9357 <span class="close-modal" onclick="event.stopPropagation();document.getElementById('addToBucketlistModal').style.display='none';document.body.classList.remove('modal-open');">×</span> 9358 <h3>Which Rondo's would you like to add to your bucketlist?</h3> 9359 </div> 9360 <div class="atbl-body" id="atblBody"><!-- Gevuld door JS --></div> 9361 <div class="atbl-footer"> 9362 <button id="btnAtblConfirm" disabled>Add to Bucketlist</button> 9363 </div> 9364 </div> 9365 </div> 9366 9367 <style> 9368#addToBucketlistModal .circles-modal-content { 9369 padding: 0; 9370 display: flex; 9371 flex-direction: column; 9372 max-height: 85vh; 9373 overflow: hidden; 9374} 9375#addToBucketlistModal .atbl-header { 9376 padding: 24px 54px 14px 24px; 9377 border-bottom: 0; 9378} 9379#addToBucketlistModal .atbl-header h3 { 9380 margin: 0; 9381 font-size: 1.05em; 9382 font-weight: 800; 9383 color: var(--color-dark); 9384} 9385#addToBucketlistModal .atbl-body { 9386 flex: 1; 9387 overflow-y: auto; 9388 padding: 14px 24px 80px; 9389} 9390#addToBucketlistModal h6.atbl-group-title { 9391 font-size: 1.7rem; 9392 font-weight: 400; 9393 color: var(--color-dark); 9394 border-bottom: 0; 9395 padding-bottom: 0; 9396 margin: 16px 0 0; 9397} 9398#addToBucketlistModal h6.atbl-group-title:first-child { margin-top: 0; } 9399/* atbl-item is een <label>
9399 â volledig klikbaar vlak, geen JS nodig */ 9400#addToBucketlistModal .atbl-item { 9401 display: flex; 9402 align-items: center; 9403 gap: 12px; 9404 padding: 10px 0; 9405 cursor: pointer; 9406 user-select: none; 9407} 9408#addToBucketlistModal .atbl-item input[type="checkbox"] { 9409 width: 20px; 9410 height: 20px; 9411 flex-shrink: 0; 9412 cursor: pointer; 9413 accent-color: var(--color-action, #271D62); 9414} 9415#addToBucketlistModal .atbl-item span { 9416 flex: 1; 9417} 9418#addToBucketlistModal .atbl-item strong { 9419 display: block; 9420 font-weight: 700; 9421 font-size: 0.92em; 9422 color: var(--color-dark); 9423} 9424#addToBucketlistModal .atbl-item small { 9425 display: block; 9426 font-weight: 400; 9427 font-size: 0.82em; 9428 color: #888; 9429 margin-top: 2px; 9430} 9431#addToBucketlistModal .atbl-event-name { 9432 color: #555; 9433 font-weight: 600; 9434} 9435#addToBucketlistModal .atbl-meta .route-stats-block { 9436 display: inline; 9437} 9438#addToBucketlistModal .atbl-meta .route-stats-block p { 9439 display: inline; 9440 margin: 0; 9441} 9442#addToBucketlistModal .atbl-meta .route-stats-block em { 9443 display: inline-block; 9444 font-style: normal; 9445 margin-right: 2px; 9446} 9447#addToBucketlistModal .atbl-meta .route-stats-block em:nth-child(2), 9448#addToBucketlistModal .atbl-meta .route-stats-block em:nth-child(4), 9449#addToBucketlistModal .atbl-meta .route-stats-block em:nth-child(5) { 9450 display: none; 9451} 9452#addToBucketlistModal .atbl-meta .route-stats-block:not(:last-child) { 9453 margin-right: 15px; 9454} 9455#addToBucketlistModal .atbl-item.already-added { 9456 opacity: 0.4; 9457 pointer-events: none; 9458} 9459#addToBucketlistModal .atbl-footer { 9460 position: absolute; 9461 bottom: 0; left: 0; right: 0; 9462 padding: 14px 24px; 9463 background: white; 9464 border-top: 1px solid #e5e5f0; 9465 box-shadow: 0 -4px 16px rgba(0,0,0,0.07); 9466} 9467#addToBucketlistModal .atbl-footer button { 9468 width: 100%; 9469 padding: 14px; 9470 border-radius: 30px; 9471 background: var(--color-action, #271D62); 9472 color: var(--color-white); 9473 border: none; 9474 font-family: 'ashemore', sans-serif; 9475 font-size: 1em; 9476 font-weight: 700; 9477 cursor: pointer; 9478} 9479#addToBucketlistModal .atbl-footer button:disabled { 9480 opacity: 0.5; 9481 cursor: not-allowed; 9482} 9483 </style> 9484
9485<script> 9486/* De footer kan een voorouder met transform/filter bevatten; dan gedraagt 9487 position:fixed zich als absolute en valt de modal midden in de pagina. 9488 Verplaatsen naar <body> haalt ze uit elk stacking- en transformcontext. */ 9489(function () { 9490 function verplaats() { 9491 ['grBucketlistLoginModal', 'grBucketlistModal', 'ritModal', 'grPalEditModal', 'planRondoModal', 'rideModal', 'ticketModal', 9492 'loginModal', 'upgradeModal', 'addToBucketlistModal'] 9493 .forEach(function (id) { 9494 var m = document.getElementById(id); 9495 if (m && m.parentNode && m.parentNode !== document.body) document.body.appendChild(m); 9496 }); 9497 } 9498 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', verplaats); 9499 else verplaats(); 9500})(); 9501</script>
9501 9502 9503 9504 9505
9506<script> 9507(function () { 9508 var GR = window.GR = window.GR || {}; 9509 9510 // ââ Privacy âââââââââââââââââââââââââââââââââââââââââââââââââââ 9511 // Accepteert een profielobject ({ publiek, public }) of een ruwe string. 9512 // Retourneert true als het profiel expliciet op privé staat (waarde "FALSE"). 9513 // Lege waarde of "TRUE" = publiek (standaard). 9514 GR.isPrivé = function (profiel) { 9515 var val; 9516 if (profiel && typeof profiel === 'object') { 9517 val = profiel.publiek != null ? profiel.publiek : (profiel.public != null ? profiel.public : ''); 9518 } else { 9519 val = profiel != null ? profiel : ''; 9520 } 9521 return String(val).trim().toUpperCase() === 'FALSE'; 9522 }; 9523 9524 // ââ Route matcher (identiek aan rating script) ââââââââââââââââ 9525 // Bouw een matchfunctie op basis van de routes sheet. 9526 // Retourneert: matches(actGebied, roundId) â boolean 9527 GR.buildRondeMatcher = function (routes) { 9528 var naam2gebied = {}; 9529 (routes || []).forEach(function (r) { 9530 var naam = ((r && r['Naam']) || '').trim(); 9531 var gebied = ((r && r['Gebied']) || '').trim(); 9532 if (naam && gebied) naam2gebied[naam] = gebied; 9533 }); 9534 return function (actGebied, roundId) { 9535 actGebied = (actGebied || '').trim(); 9536 roundId = (roundId || '').trim(); 9537 if (!actGebied || !roundId) return false; 9538 if (actGebied === roundId) return true; 9539 if (roundId.length > 3 && actGebied.endsWith(roundId)) return true; 9540 var roundGebied = naam2gebied[roundId]; 9541 if (roundGebied) { 9542 if (roundGebied === actGebied) return true; 9543 if (roundId.length > 3 && roundGebied.endsWith(roundId)) return true; 9544 } 9545 return false; 9546 }; 9547 }; 9548 9549 // ââ Tijd parsen (HH:MM:SS of MM:SS â seconden) âââââââââââââââ 9550 GR.parseTime = function (t) { 9551 var p = (t || '').split(':').map(Number); 9552 return p.length === 3 ? p[0] * 3600 + p[1] * 60 + p[2] 9553 : p.length === 2 ? p[0] * 60 + p[1] 9554 : 0; 9555 }; 9556 9557 // ââ Duur van een activiteit âââââââââââââââââââââââââââââââââââ 9558 /* De kolom Tijd is bij de meeste rijen leeg, terwijl Datum Start en Datum 9559 Finish er wél een tijdstip bij hebben staan ("2026-09-20 9:30" en 9560 "2026-09-20 16:35"). In de Hall of Fame leverde dat een tijd van niets op, 9561 ook bij ritten waar alles ingevuld is. 9562 9563 Reden: het formulier rekende de duur alleen uit uit de twee datumvelden, en 9564 die zijn op dezelfde dag gelijk. Dat is bij de bron rechtgezet, maar dat 9565 helpt alleen nieuwe ritten. Daarom hier de terugval: staat er geen Tijd, dan 9566 leiden we hem af uit begin en eind. 9567 9568 Levert { sec, tekst } â de seconden om op te sorteren en uu:mm:ss om te 9569 tonen. Zonder bruikbare gegevens: 0 en een lege tekst, zodat de aanroeper 9570 zelf kan besluiten er niets neer te zetten. */ 9571 GR.duurVan = function (rij) { 9572 if (!rij) return { sec: 0, tekst: '' }; 9573 var opgegeven = String(rij['Tijd'] || rij.tijd || '').trim(); 9574 if (opgegeven) return { sec: GR.parseTime(opgegeven), tekst: opgegeven }; 9575 9576 var begin = _tijdstip(rij['Datum Start'] || rij.datumStart); 9577 var eind = _tijdstip(rij['Datum Finish'] || rij.datumFinish); 9578 if (!begin || !eind || eind <= begin) return { sec: 0, tekst: '' }; 9579 9580 var sec = Math.round((eind - begin) / 1000); 9581 return { sec: sec, tekst: _hms(sec) }; 9582 }; 9583 9584 /* "2026-09-20 9:30" leest geen enkele browser betrouwbaar: Safari geeft er 9585 Invalid Date op. Met een T ertussen wel, en dan als lokale tijd â wat klopt, 9586 want zo is het ingevoerd. Staat er alleen een datum, dan is er geen tijdstip 9587 en heeft rekenen geen zin. */ 9588 function _tijdstip(waarde) { 9589 var s = String(waarde == null ? '' : waarde).trim(); 9590 if (!s || s.indexOf(' ') === -1) return null; 9591 /* Het uur aanvullen tot twee cijfers, net als in GR.fmtDate hierboven. 9592 "2026-09-20 9:30" wordt anders "2026-09-20T9:30" en dat is geen geldige 9593 tijd â new Date() geeft er Invalid Date op, waarna deze functie null 9594 teruggaf en de rit dus geen duur kreeg. Precies de ritten met een 9595 starttijd vóór tienen vielen daardoor om. */ 9596 var d = new Date(s.replace(' ', 'T').replace(/T(\d):/, 'T0$1:')); 9597 return isNaN(d.getTime()) ? null : d; 9598 } 9599 9600 function _hms(sec) { 9601 function tw(n) { return (n < 10 ? '0' : '') + n; } 9602 return tw(Math.floor(sec / 3600)) + ':' + tw(Math.floor((sec % 3600) / 60)) + ':' + tw(sec % 60); 9603 } 9604 9605 // ââ Datum formatteren â "DD-MM-YYYY" âââââââââââââââââââââââââ 9606 GR.fmtDate = function (d) { 9607 if (!d) return ''; 9608 /* "2026-09-04 6:41" werd "2026-09-04T6:41", en dat is geen geldige tijd â 9609 het uur hoort twee cijfers te hebben. De datum kwam dan onbewerkt terug, 9610 waardoor in de Hall of Fame de helft van de records als "2026-09-04 6:41" 9611 stond en de andere helft netjes als "04-12-2024". Daarom het uur eerst 9612 aanvullen. */ 9613 var s = String(d).trim(); 9614 /* De sheet kent twee schrijfwijzen door elkaar: 2026-09-04 en 18-5-2023. 9615 new Date() begrijpt die tweede niet, dus die viel onbewerkt door â waardoor 9616 in dezelfde lijst "18-5-2023" naast "04-12-2024" stond. Hier zelf uit 9617 elkaar halen, dan leest alles hetzelfde. */ 9618 var nl = s.match(/^(\d{1,2})-(\d{1,2})-(\d{4})/); 9619 if (nl) { 9620 return String(nl[1]).padStart(2, '0') + '-' + String(nl[2]).padStart(2, '0') + '-' + nl[3]; 9621 } 9622 var ruw = s.replace(' ', 'T').replace(/T(\d):/, 'T0$1:'); 9623 var dt = new Date(ruw); 9624 if (isNaN(dt)) return s; 9625 return String(dt.getDate()).padStart(2, '0') + '-' 9626 + String(dt.getMonth() + 1).padStart(2, '0') + '-' 9627 + dt.getFullYear(); 9628 }; 9629 9630 // ââ HTML escapen ââââââââââââââââââââââââââââââââââââââââââââââ 9631 GR.esc = function (s) { 9632 return String(s || '') 9633 .replace(/&/g, '&') 9634 .replace(/</g, '<') 9635 .replace(/>/g, '>') 9636 .replace(/"/g, '"'); 9637 }; 9638 9639 // ââ NL-float parsen (1.234,56 â 1234.56) âââââââââââââââââââââ
9640 GR.parseNLFloat = function (v) { 9641 if (v == null) return NaN; 9642 var n = parseFloat( 9643 String(v).trim() 9644 .replace(/\.(?=\d{3}(\D|$))/g, '') 9645 .replace(',', '.') 9646 ); 9647 return isNaN(n) ? NaN : n; 9648 }; 9649 9650 // ââ Profielen opbouwen uit Profiel-sheet rows âââââââââââââââââ 9651 // Retourneert een object: { [email]: { naam, userId, publiek } } 9652 GR.buildProfielen = function (rows) { 9653 var profielen = {}; 9654 (rows || []).forEach(function (p) { 9655 var email = (p['E-mailadres'] || '').trim().toLowerCase(); 9656 if (!email) return; 9657 profielen[email] = { 9658 naam: p['Wat is je naam?'] || '', 9659 userId: p['ID'] || '', 9660 geslacht: p['Geslacht'] || '', 9661 /* De kolom in de Profiel-sheet heet "Public" met een hoofdletter P. 9662 Sleutels zijn hoofdlettergevoelig, dus 'Publiek' en 'public' misten 9663 hem allebei en GR.isPrivé gaf altijd false terug. Alle varianten 9664 blijven staan voor het geval de kolomnaam ooit wijzigt. */ 9665 publiek: String(p['Public'] || p['Publiek'] || p['public'] || '').trim().toUpperCase() 9666 }; 9667 }); 9668 return profielen; 9669 }; 9670})(); 9671</script>
9671 9672 9673
9674<script> 9675const gEI=id=>document.getElementById(id),gQS=s=>document.querySelector(s),gQSA=s=>document.querySelectorAll(s); 9676// CONFIGURATIE URLs (Hardcoded voor absolute stabiliteit) 9677const RIDE_SCRIPT_URL = "https://script.google.com/macros/s/AKfycbykfmZGR3AVsTqRF0LNs3Kx1zzVauuYSe-GGb2JzR8AeHYCjB8BNOQbXJZ5ouxa946n/exec"; 9678const PROFILE_SCRIPT_URL = RIDE_SCRIPT_URL; // Profiel loopt nu via jointhecircle.gs 9679// LAAD LABELS UIT LIQUID (Zelfs als het leeg is, crasht het script niet) 9680const L = {"gr-planner-welcome-hi":"Hi","gr-planner-time-for-ride":"Time for a Rondo","gr-planner-loading-dashboard":"Loading profile...","gr-planner-loading-title":"Loading Rondo'sâ¦","gr-planner-loading-sub":"Please wait","gr-loading-rides":"Fetching Rondo's...","gr-loading-profile":"Fetching Profile...","gr-loading-activities":"Fetching Activities...","gr-planner-error-load-title":"Error loading","gr-planner-loading-profile-data":"Searching data...","gr-planner-profile-timeout":"Profile data not available.","gr-planner-error-fetching":"Error fetching.","gr-planner-view-all":"All rides","gr-planner-view-events":"Events","gr-planner-view-planned":"Your rides","gr-planner-view-mine":"Your planned rides","gr-planner-view-archive":"Archive","gr-planner-view-voltooid":"Recent \/ Upcoming","gr-planner-view-gepland-bucketlist":"Planned","gr-db-tab-bucketlist":"Bucketlist","gr-db-tab-mine":"Your planned rides","gr-db-tab-all":"All rides","gr-db-tab-archive":"Archive","gr-db-tab-archief":"Archive","gr-db-tab-voltooid-palmares":"Completed \/ palmares","gr-db-btn-add":"+ Add","gr-db-modal-add-title":"Add...","gr-db-choice-bucketlist":"Rondo's on Bucketlist","gr-db-choice-plan":"Plan a new ride","gr-db-choice-activity":"Add Activity","gr-db-more-items":"Show more items...","gr-db-plan-access-msg":"\u003ca href=\"\/collections\/all\" style=\"color:var(--color-action);font-weight:700;\"\u003eOrder a Rondo\u003c\/a\u003e or \u003ca href=\"\/join\" style=\"color:var(--color-action);font-weight:700;\"\u003ebecome a Rondoneur\u003c\/a\u003e to plan all Rondo's.","gr-db-add-modal-title":"Which Rondo's would you like to add to your bucketlist?","gr-db-add-modal-btn":"Add to Bucketlist","gr-db-add-saving":"Addingâ¦","gr-db-add-group-events":"Events","gr-db-add-group-areas":"Rondo's","gr-db-add-already-added":"already added","gr-db-add-area-on-list":"Already on your bucketlist","gr-db-add-no-rides":"No Rondo's available.","gr-planner-btn-new-ride":"+ New Ride","gr-planner-btn-profile":"Profile","gr-planner-profile-title":"My Profile","gr-planner-btn-edit-profile":"âï¸ Edit Profile","gr-planner-btn-filters":"Filters","gr-planner-search-placeholder":"Search by area...","gr-planner-filter-countries":"All Countries","gr-planner-filter-types":"All Types","gr-planner-filter-paces":"All Paces","gr-planner-filter-days":"All Days","gr-planner-filter-target":"For who...","gr-planner-sort-date":"Sort: Date","gr-planner-sort-area":"Sort: Rondo \/ Area","gr-tempo-under-26":"\u003c 26 km\/h","gr-tempo-27-32":"27-32 km\/h","gr-tempo-over-33":"\u003e 33 km\/h","gr-planner-opt-pace-u20":"\u003c 20 km\/h","gr-planner-opt-pace-2025":"20â25 km\/h","gr-planner-opt-pace-2527":"25â27 km\/h","gr-planner-opt-pace-2732":"27â32 km\/h","gr-planner-opt-pace-o32":"\u003e 32 km\/h","gr-day-monday":"Monday","gr-day-tuesday":"Tuesday","gr-day-wednesday":"Wednesday","gr-day-thursday":"Thursday","gr-day-friday":"Friday","gr-day-saturday":"Saturday","gr-day-sunday":"Sunday","gr-target-everyone":"Everyone","gr-target-men":"Men","gr-target-women":"Women","gr-planner-login-required":"You need to be logged in to view this content.","gr-planner-login-sub":"","gr-planner-btn-register":"Create free account","gr-planner-btn-login":"Log in or create free account","gr-planner-upgrade-title":"You don't have access to this info.","gr-planner-upgrade-text":"Become a Rondoneur to use the Rondo Planner without limits.","gr-planner-btn-upgrade":"Join the Circle","gr-planner-no-access-text":"You don't have access to this info. Order this Rondo or become a Rondoneur to view this ride.","gr-planner-btn-order-rondo":"Order Rondo","gr-planner-btn-become-rondoneur":"Become a Rondoneur","gr-planner-no-access-info":"You don't have access to the info of this Rondo.","gr-planner-order-rondo":"Order this Rondo","gr-planner-unlock-all":"Unlock all Rondo's","gr-planner-join-rondoneur":"Join as Rondoneur","gr-planner-modal-new-ride":"Plan a new ride","gr-planner-modal-new-activity":"New activity","gr-planner-edit-ride":"Edit Ride","gr-planner-cancel-ride":"Cancel Ride","gr-planner-lock-message":"â ï¸ Because there are already participants, date and route can no longer be changed.","gr
9680-planner-label-create-ride":"Create ride","gr-planner-radio-specific":"Specific date","gr-planner-radio-days":"Preferred days","gr-planner-label-date-start":"Date *","gr-planner-opt-type-both":"Both","gr-planner-alert-finish-before-start":"End date cannot be before start date.","gr-planner-label-date-finish":"End date","gr-planner-label-time-finish":"End time","gr-planner-date-changed":"Note: Date \/ time changed","gr-planner-day-none":"To be determined","gr-planner-day-ntb":"Date \/ time: TBD.","gr-planner-chk-date-changed":"Add text: Note: Date \/ time changed","gr-planner-label-preferred-days":"Preferred days *","gr-planner-sub-preferred-days":"Agree on a date later.","gr-planner-label-area":"Rondo (area) *","gr-planner-opt-choose-area":"Choose area...","gr-planner-label-route":"Type *","gr-planner-opt-first-choose-area":"â Choose area","gr-planner-label-event-name":"Event Name","gr-planner-label-start-loc":"Start location","gr-planner-start-location":"Start location","gr-planner-placeholder-start-loc":"Address or location","gr-planner-label-pace":"Pace","gr-planner-opt-pace":"Choose (optional)","gr-planner-label-target":"For who","gr-planner-checkbox-public":"Visible to everyone (Public)","gr-planner-label-info":"Information","gr-planner-title-bold":"Bold","gr-planner-title-italic":"Italic","gr-planner-title-underline":"Underline","gr-planner-title-link":"Link","gr-planner-btn-link":"Link","gr-planner-placeholder-info":"Type your info here...","gr-planner-label-info-en":"Information (English)","gr-planner-btn-translate":"Translate","gr-planner-translating":"Translatingâ¦","gr-planner-btn-save":"Save","gr-planner-btn-saving":"Saving...","gr-planner-saving":"Saving...","gr-planner-saving-busy":"Saving...","gr-planner-saved-ok":"â Saved!","gr-planner-error-save":"Something went wrong. Please try again.","gr-planner-alert-save-error":"Something went wrong while saving.","gr-planner-btn-delete":"Delete ride","gr-planner-btn-cancel":"Cancel","gr-planner-alert-select-day":"Select at least 1 day","gr-planner-alert-date-time-required":"Date and time are required.","gr-planner-alert-no-permission-area":"You don't have permission to create a ride in this area.","gr-planner-alert-info-too-long":"Info text is too long (max 1200 characters).","gr-planner-alert-info-too-many-lines":"Info may contain a maximum of 12 lines.","gr-planner-confirm-cancel":"Are you sure you want to cancel this ride? Participants will see this as 'Cancelled'.","gr-planner-prompt-delete":"Type '__EXPECTED__' to delete:","gr-planner-confirm-close-unsaved":"Changes not saved. Close?","gr-planner-prompt-url":"Enter URL:","gr-planner-replace-with":"Replace with: ","gr-planner-share":"Share","gr-planner-share-via":"Share via...","gr-planner-copy-link":"Copy link","gr-planner-no-rides-found":"No rides found.","gr-planner-no-archived-rides":"No archived rides.","gr-planner-cancelled":"Cancelled","gr-planner-completed":"Completed","gr-planner-ride-default":"Ride","gr-planner-view-details":"View details","gr-planner-edit":"Edit","gr-planner-navigate-start":"Navigate to Start","gr-planner-view-guide":"View Rondo Guide","gr-planner-view-rondo":"View Rondo","gr-planner-participants":"Participants","gr-planner-no-participants-yet":"No participants yet.","gr-planner-you":"You?","gr
9680-planner-you-are-organizer":"You are the organizer","gr-planner-organizer-label":"organizer","gr-planner-guest":"Anonymous","gr-planner-unknown":"Unknown","gr-planner-nameless":"Unnamed","gr-planner-participating":"I'm joining","gr-planner-event-voltooid":"Event completed","gr-planner-niet-meegedaan":"Didn't participate","gr-planner-verwijder":"Remove","gr-planner-rsvp-maybe":"Maybe","gr-planner-rsvp-maybe-active":"I might join","gr-planner-rsvp-no":"I'm not joining","gr-planner-rsvp-voltooid":"Rondo Completed","gr-planner-rsvp-tag-auto":"Users with this tag are automatically signed up.","gr-planner-ticket-question":"Would you like to join this event?","gr-planner-ticket-order":"Order your Tickets","gr-planner-ticket-more-info":"More info","gr-planner-ticket-join":"Join","gr-planner-ticket-participating":"You're in ð","gr-planner-comments":"Comments","gr-planner-placeholder-comment":"Post a comment...","gr-planner-send":"Send","gr-planner-alert-comment-too-long":"Comment is too long (max 200 characters).","gr-planner-delete-message":"Delete message","gr-planner-confirm-delete-message":"Delete message?","gr-planner-load-more-rides":"Show more ridesâ¦","gr-planner-load-more-participants":"Show more participantsâ¦","gr-planner-plan-rondo-tooltip":"Plan this Rondo","gr-planner-plan-rondo-title":"Plan a Rondo","gr-planner-plan-rondo-sub-rides":"Join others or set your own date.","gr-planner-plan-rondo-sub-norides":"Set a date for your Rondo and invite others to join you.","gr-planner-plan-rondo-btn":"Set your own date","gr-planner-profile-edit-title":"Edit Profile","gr-planner-btn-upload-avatar":"Upload Profile Photo","gr-planner-label-profile-name":"Profile name (visible to others)","gr-planner-placeholder-name":"Your name","gr-planner-label-email":"Email address","gr-planner-link-edit-shop":"edit in shop profile","gr-planner-label-name":"Name","gr-planner-profile-section-personal":"Personal","gr-planner-label-city":"City","gr-planner-label-country":"Country","gr-planner-label-birthday":"Date of birth","gr-planner-label-gender":"Gender","gr-planner-opt-choose":"Choose...","gr-planner-opt-gender-man":"Male","gr-planner-opt-gender-vrouw":"Female","gr-planner-opt-gender-anders":"Non-binary","gr-planner-label-discipline":"Discipline","gr-planner-opt-disc-weg":"Road","gr-planner-opt-disc-gravel":"Gravel","gr-planner-opt-disc-gravel-weg":"Gravel \u0026 Road","gr-planner-opt-disc-mtb":"MTB","gr-planner-label-pace-pref":"Preferred pace","gr-planner-profile-section-online":"Online","gr-planner-label-strava":"Strava","gr-planner-label-komoot":"Komoot","gr-planner-label-instagram":"Instagram","gr-planner-label-website":"Website","gr-planner-profile-section-actie":"Charity","gr-planner-label-charity":"Charity page","gr-planner-hint-charity-link":"Create a charity page for KiKa","gr-planner-hint-charity-suffix":"or another Good Cause and share the link here:","gr-planner-charity-link-label":"Support for Charity","gr-planner-profile-section-bike":"My bike","gr-planner-label-bike":"Photo of your bike","gr-planner-btn-upload-bike":"Upload bike photo","gr-planner-label-bio":"Motivation \/ Bio","gr-planner-placeholder-bio":"Write here about your next Rondo participation \/ Your motivation \/ Your story","gr-planner-bio-read-more":"read more","gr-planner-bio-read-less":"read less","gr-planner-label-profile-public":"Profile publicly visible","gr-planner-hint-profile-public":"If public: name and profile visible to other members","gr-planner-btn-save-update":"SAVE \u0026 UPDATE","gr-planner-strava-label":"Connect with Strava","gr-planner-strava-hint":"Automatic synchronisation of your Rondo activities.","gr-planner-profile-require-name":"Please fill in your name first to be able to participate.","gr-planner-setup-profile-title":"Set up your profile","gr-planner-update-profile-title":"Update your profile","gr-planner-year-label":"year","gr-planner-edit-title":"Edit profile","gr-planner-read-more":"read more","gr-planner-read-less":"read less","gr-planner-palmares-confirm":"Would you like to add this Activity to your Palmares?","gr-planner-palmares-add":"Add activity","gr-planner-palmares-skip":"Don't add","gr-bucketlist-login-required":"Log in to see your planned rides.","gr-bucketlist-btn-login":"Log in or create free account","gr-bucketlist-title":"Planned \/ Bucketlist","gr-bucketlist-view-mine":"My Participations","gr-bucketlist-show-all":"Show full Planner","gr-bucketlist-loading":"Loading...","gr-bucketlist-empty":"No planned rides.","gr-bucketlist-error":"Could not load rides.","gr-bucketlist-on-list":"Saved to bucketlist","gr-bucketlist-areatag-status":"Rondo on your list","gr-bucketlist-btn":"Bucketlist","gr-bucketlist-planned":"Planned","gr-bucketlist-package":"View Rondo package","gr-bucketlist-btn-save":"Save to bu
9680cketlist","gr-bucketlist-btn-remove":"Remove from bucketlist","gr-bucketlist-saved-text":"â Saved for later on bucketlist","gr-bucketlist-open":"Open Bucketlist","gr-bucketlist-back-to-rondo":"Continue Shopping","gr-bucketlist-enrolled":"You're in ð","gr-bucketlist-bewaard-rondos":"Saved in Your Rondo's","gr-bucketlist-ticket-more":"Order more tickets","gr-rider-view-profile":"View profile","gr-leaderboard-title":"Fastest times","gr-leaderboard-your-result":"Your result","gr-leaderboard-more":"Show more activities","gr-profile-private":"User unknown.","gr-profile-go-back":"â Go back"} || {}; 9681/* Label met terugval. Een sleutel die in het metaobject staat maar leeg of 9682 alleen spaties is, is truthy â dan won de lege waarde van elke ||-terugval en 9683 kreeg je een lege balk in beeld. Deze helper behandelt dat als ontbrekend. */ 9684window._grLbl = function (sleutel, terugval) { 9685 var v = L[sleutel]; 9686 return (v && String(v).trim()) ? v : (terugval || ''); 9687}; 9688/* ââ Adressen in de taal van de bezoeker ââââââââââââââââââââââââââââââââââ 9689 Alles wat de planner aanwijst â de Rondopagina, de gids, het event, de Hall 9690 of Fame â staat in de sheet en in de code als https://granrondo.cc/⦠zonder 9691 taalvoorvoegsel. Op /en/ kwam je daardoor met één klik weer in het 9692 Nederlands terecht. 9693 9694 Deze functie zet het voorvoegsel van de pagina waar je nu bent ervoor. Op de 9695 hoofdtaal is er niets toe te voegen en komt het adres onaangeroerd terug. 9696 Een adres naar een ander domein â Strava, Komoot, account.granrondo.cc â 9697 blijft ook met rust: daar zegt ons taalvoorvoegsel niets. 9698 9699 Dezelfde functie staat in gr-atlas-kaart voor de kaart. Staat die er al, 9700 dan blijft die staan: twee keer hetzelfde, dus het maakt niet uit welke 9701 wint, maar één eigenaar is netter. */ 9702window._grTaalUrl = window._grTaalUrl || function (url) { 9703 if (!url) return url; 9704 /* Een kale ankerlink hoort bij deze pagina en wordt geen volledig adres: 9705 '#' zou anders https://granrondo.cc/en/# worden. */ 9706 if (String(url).charAt(0) === '#') return url; 9707 var taal = (location.pathname.split('/')[1] || ''); 9708 if (!/^[a-z]{2}$/.test(taal)) return url; 9709 try { 9710 var u = new URL(url, location.origin); 9711 if (u.host !== location.host) return url; 9712 if (u.pathname === '/' + taal || u.pathname.indexOf('/' + taal + '/') === 0) return url; 9713 u.pathname = '/' + taal + u.pathname; 9714 return u.toString(); 9715 } catch (e) { return url; } 9716};const SHOP_LOCALE = (function(){ 9717 const seg = window.location.pathname.split('/')[1]; 9718 return (seg && /^[a-z]{2}$/.test(seg)) ? seg : 'nl'; 9719})(); 9720// ZORG DAT DEZE STATUSSEN ALTIJD GEDEFINIEERD ZIJN (Essentieel voor de filters) 9721const STATUS_GO = "Ik doe mee"; 9722const STATUS_MAYBE = "Misschien"; 9723const STATUS_CANCELLED = "Geannuleerd"; 9724const STATUS_BUCKETLIST = "Bucketlist"; 9725const STATUS_VOLTOOID = "Rondo Voltooid"; 9726const ADMIN_EMAILS = ["[email protected]", "[email protected]"]; 9727const DEFAULT_PACE = 25; 9728let userEmail = ""; 9729let userTags = []; 9730let localDisplayName = L['gr-planner-guest'] || "Gast"; 9731// Naam NOOIT uit Shopify customer.name halen â altijd uit spreadsheet Profiel kolom B 9732try { 9733const rawEmail = null; 9734userEmail = typeof rawEmail === 'string' ? rawEmail : ""; 9735const rawTags = null; 9736userTags = Array.isArray(rawTags) ? rawTags : []; 9737} catch (e) { 9738console.warn("Liquid tags fallback: Gebruiker is uitgelogd."); 9739} 9740let localDisplayAvatar = ""; 9741const SVG_EDIT = `<svg viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>`; 9742const SVG_EYE = `<svg viewBox="0 0 24 24" style="fill:currentColor;stroke:none;display:block;"><polygon points="12,17 4,7 20,7"/></svg>`; 9743const SVG_TRASH = `<svg viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>`; 9744const SVG_SHARE = `<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg>`; 9745const SVG_HEART_FILLED = `<svg width="18" height="24" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-2px;display:inline-block;pointer-events:none;"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.27 2 8.5 2 5.41 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.41 22 8.5c0 3.77-3.4 6.86-8.55 11.53L12 21.35z"/></svg>`; 9746const SVG_SHOP = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path><line x1="3" y1="6" x2="21" y2="6"></line><path d="M16 10a4 4 0 0 1-8 0"></path></svg>`; 9747const SVG_BOOK = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path></svg>`; 9748const SVG_CALENDAR = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>`; 9749const SVG_MENU = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="15" y2="18"></line></svg>`; 9750const SVG_INFO = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>`; 9751const SVG_LINK = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>`; 9752const SVG_VOLCHECK = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>`; 9753const SVG_BIKE = `<svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" style="display:inline-block;"><circle cx="5" cy="17.5" r="4"/><circle cx="19" cy="17.5" r="4"/><path d="M5 17.5 L8.5 10 L11.5 17.5 M5 17.5 L11.5 17.5 M8.5 10 L16 9 L11.5 17.5 M16 9 L19 17.5 M14.8 8.6 L17.4 8.6 M7.4 9.8 L9.9 9.8"/></svg>`; 9754let activeView = window.GR_INITIAL_VIEW || "all"; 9755const GR_CACHE_KEY = 'gr_rides_v1'; 9756const GR_CACHE_TTL = 5 * 60 * 1000; 9757let deepLinkHandled = false;
9758let deepLinkRideId = null; 9759if (window.location.hash && window.location.hash.toLowerCase() === '#events') { 9760activeView = 'events'; 9761} 9762let allRides = [], allParticipants = [], allComments = [], routeData = {}, routeDetails = {}, areaTags = {}; 9763let knownTags = []; 9764let tagMembersMap = {}; 9765let activiteitenTags = []; // [{email, tag}] â activiteiten die al op palmares staan // { "nh20260412": [{email, name, initials, avatar}] } 9766let profileLoadedOnce = false; // voorkomt dat profielpopup meerdere keren verschijnt 9767let profileNameLoaded = false; // zodra profielnaam uit spreadsheet geladen is, nooit meer overschrijven 9768let formIsDirty = false; 9769const listEl = document.getElementById('listRides'); 9770const emptyEl = document.getElementById('emptyRides'); 9771/* rideModal staat sinds de verhuizing in gr-shared-modals (footer). Draait dit 9772 script eerder, dan is deze verwijzing null. `let` zodat hij later hersteld 9773 kan worden door _grRefreshRideEls() in planner-script5. */ 9774let modal = document.getElementById('rideModal'); 9775const profileModal = document.getElementById('profileModal'); 9776const loginModal = document.getElementById('loginModal'); 9777let form = document.getElementById('rideForm'); 9778let inpRondo = document.getElementById('inpRondo'); 9779let inpType = document.getElementById('inpType'); 9780const overlay = document.getElementById('loadingOverlay'); 9781const viewSelect = document.getElementById('viewSelect'); 9782const viewSelectWrapper = document.getElementById('viewSelectWrapper'); 9783const clean = (str) => String(str || "").trim().toLowerCase(); 9784if(viewSelect) viewSelect.value = activeView; 9785const toggleBtn = document.getElementById('btnToggleFilters'); 9786if(toggleBtn) { 9787toggleBtn.addEventListener('click', (e) => { 9788e.preventDefault(); 9789const p = document.getElementById('filterPanel'); 9790const isHidden = p.classList.contains('hidden'); 9791if(isHidden) p.classList.remove('hidden'); else p.classList.add('hidden'); 9792toggleBtn.innerHTML = isHidden ? `â ${L['gr-planner-btn-filters'] || 'Filters'}` : `â° ${L['gr-planner-btn-filters'] || 'Filters'}`; 9793}); 9794} 9795if(viewSelectWrapper) { 9796viewSelectWrapper.addEventListener('mousedown', (e) => { 9797if(!userEmail) { 9798e.preventDefault(); 9799loginModal.style.display = 'block'; 9800document.body.classList.add('modal-open'); 9801} 9802}); 9803} 9804if(viewSelect) { 9805viewSelect.addEventListener('change', (e) => { 9806activeView = e.target.value; 9807localStorage.setItem('rondo_view', activeView); 9808if(typeof render === "function") render(); 9809}); 9810} 9811window.addEventListener('click', function(e) { 9812if (!e.target.closest('.rsvp-actions') && !e.target.closest('.detail-rsvp-row')) { 9813 document.querySelectorAll('.rsvp-popover').forEach(p => { 9814 p.classList.remove('show'); 9815 p.style.position = ''; p.style.top = ''; p.style.right = ''; 9816 p.style.left = ''; p.style.transform = ''; p.style.zIndex = ''; 9817 }); 9818} 9819if (!e.target.closest('.participants-preview')) { 9820document.querySelectorAll('.participants-popover').forEach(p => p.classList.remove('show')); 9821document.querySelectorAll('.ride-card').forEach(c => c.classList.remove('popover-open')); 9822} 9823if (!e.target.closest('.share-btn-wrapper')) document.querySelectorAll('.share-popover').forEach(p => p.classList.remove('show')); 9824if (!e.target.closest('.action-menu-wrapper')) document.querySelectorAll('.action-popover').forEach(p => { p.style.display = 'none'; p.classList.remove('show'); }); 9825}); 9826let _loadingTimer = null; 9827/* Er staat meer dan één #loadingOverlay op de dashboardpagina (planner-html én 9828 dashboard-html leveren er allebei één). getElementById pakt alleen de eerste, 9829 waardoor de tweede eeuwig bleef draaien. Daarom altijd álle exemplaren pakken. */ 9830function _grOverlays() { 9831const set = new Set(); 9832document.querySelectorAll('#loadingOverlay, .loading-overlay-section').forEach(el => set.add(el)); 9833return Array.from(set); 9834} 9835/* Vangnet: zodra er ritten in de lijst staan, hoort er geen laadscherm meer 9836 te draaien â wat de reden ook is. Dit corrigeert elk pad dat setLoading(false) 9837 overslaat, en stopt vanzelf zodra het zijn werk gedaan heeft. */ 9838let _grWachthond = null; 9839function _grStartWachthond() { 9840if (_grWachthond) return; 9841let n = 0; 9842_grWachthond = setInterval(() => { 9843const lijst = document.getElementById('listRides'); 9844const heeftItems = (typeof allRides !== 'undefined' && allRides.length > 0) 9845|| (lijst && lijst.children.length > 0); 9846const zichtbaar = _grOverlays().some(o => !o.classList.contains('hidden') && o.style.display !== 'none'); 9847if (heeftItems && zichtbaar) { 9848console.warn('[GR] laadscherm draaide terwijl er al ritten stonden â alsnog verborgen'); 9849setLoading(false); 9850} 9851if ((heeftItems && !zichtbaar) || ++n > 120) { clearInterval(_grWachthond); _grWachthond = null; } 9852}, 500); 9853} 9854function setLoading(on) { 9855const els = _grOverlays(); 9856if (!els.length) return; // staat niet op elke pagina 9857if (_loadingTimer) { clearInterval(_loadingTimer); _loadingTimer = null; } 9858if (on) _grStartWachthond(); 9859if (on) { 9860const msgs = [ 9861 L['gr-loading-rides'] || "Ophalen Rondo's...", 9862 L['gr-loading-profile'] || "Ophalen Profiel...", 9863 L['gr-loading-activities'] || "Ophalen Activiteiten..." 9864]; 9865const teksten = () => els.map(el =>
9865 el.querySelector('.gr-loading-inline-text')).filter(Boolean); 9866let idx = 0; 9867els.forEach(el => { el.classList.remove('hidden'); el.style.display = ''; }); 9868teksten().forEach(t => t.textContent = msgs[0]); 9869_loadingTimer = setInterval(() => { idx = (idx + 1) % msgs.length; teksten().forEach(t => t.textContent = msgs[idx]); }, 1500); 9870} else { 9871els.forEach(el => { 9872el.classList.add('hidden'); 9873el.style.display = 'none'; // wint ook als de .hidden-CSS op die pagina ontbreekt 9874}); 9875} 9876} 9877window.requireLogin = function(e) { 9878if(e) { 9879e.preventDefault(); 9880e.stopPropagation(); 9881} 9882if(!userEmail) { 9883loginModal.style.display = 'block'; 9884document.body.classList.add('modal-open'); 9885return true; 9886} 9887return false; 9888}; 9889function fetchWithTimeout(url, ms = 18000) { 9890const ctrl = new AbortController(); 9891const tid = setTimeout(() => ctrl.abort(), ms); 9892/* Geen ?t=-cachebuster: Apps Script /exec antwoordt met een redirect naar 9893 googleusercontent.com, en een query string op die redirect kan de CORS- 9894 controle laten mislukken. cache:'no-store' doet hetzelfde zonder redirect-risico. */ 9895return fetch(url, { signal: ctrl.signal, cache: 'no-store' }).finally(() => clearTimeout(tid)); 9896} 9897/* Leest de rittencache. negeerTTL=true geeft ook verouderde data terug â 9898 gebruikt als noodgreep wanneer de server onbereikbaar is. */ 9899function _grLeesCache(negeerTTL) { 9900try { 9901const raw = localStorage.getItem(GR_CACHE_KEY); 9902if (!raw) return null; 9903const parsed = JSON.parse(raw); 9904if (!parsed || !parsed.data) return null; 9905if (!negeerTTL && (Date.now() - parsed.ts) >= GR_CACHE_TTL) return null; 9906return parsed; 9907} catch (e) { return null; } 9908} 9909/* Schrijft de huidige gegevens terug naar de rittencache. 9910 Zonder dit blijft een verwijderde opmerking of RSVP in localStorage staan en 9911 komt hij bij de volgende paginalading gewoon weer terug â de cache wordt 9912 namelijk vóór de server gelezen (laag 1 in init). */ 9913function _grCacheBijwerken() { 9914try { 9915const raw = localStorage.getItem(GR_CACHE_KEY); 9916if (!raw) return; 9917const p = JSON.parse(raw); 9918if (!p || !p.data) return; 9919p.data.berichten = allComments; 9920p.data.deelnemers = allParticipants; 9921p.data.ritten = allRides; 9922localStorage.setItem(GR_CACHE_KEY, JSON.stringify(p)); 9923} catch (e) { /* cache vol of onleesbaar â dan haalt de server het wel op */ } 9924} 9925window._grCacheBijwerken = _grCacheBijwerken; 9926 9927/* Vertaalt een fetch-fout naar iets waar je wat aan hebt in de console. */ 9928function _grDiagnose(err) { 9929if (!err) return 'Onbekende fout'; 9930if (err.name === 'AbortError') return 'Time-out: de server antwoordde niet binnen de wachttijd.'; 9931if (err.name === 'TypeError') { 9932 // Alleen fetch-fouten zijn netwerkproblemen; een TypeError uit eigen code 9933 // (bijv. een ontbrekend element) mag daar niet mee verward worden. 9934 return /fetch|network|load failed|NetworkError/i.test(err.message || '') 9935 ? 'Netwerk/CORS: de browser kon de server niet bereiken of de respons werd geblokkeerd.' 9936 : 'Codefout in de verwerking (geen netwerkprobleem) â zie de stacktrace hieronder.'; 9937} 9938if (err.name === 'SyntaxError') return 'Lege of ongeldige respons: de server stuurde geen JSON terug.'; 9939return err.name + ': ' + (err.message || ''); 9940} 9941function applyData(data) { 9942/* Vanaf hier weet het dashboard welke ritten er zijn. De toevoegknoppen hangen 9943 hierop: zolang de lijst nog binnenkomt is niet te zeggen wat je kunt 9944 toevoegen, en een knop die een lege keuzelijst opent is erger dan even geen 9945 knop. */ 9946window.GR_RITTEN_GELADEN = true; 9947/* _grSetDbTab heeft de knoppen verborgen omdat de data er nog niet was; nu wel, 9948 dus even opnieuw laten bepalen voor het tabblad dat openstaat. */ 9949setTimeout(function () { 9950 if (typeof window._grSetDbTab === 'function' && window.GR_DASHBOARD_TAB) { 9951 window._grSetDbTab(window.GR_DASHBOARD_TAB); 9952 } 9953}, 0); 9954allRides = data.ritten || []; 9955allParticipants = data.deelnemers || []; 9956allComments = data.berichten || []; 9957routeData = data.routeData || {}; 9958routeDetails = data.routeDetails|| {}; 9959areaTags = data.areaTags || {}; 9960knownTags = data.knownTags || []; 9961tagMembersMap = data.tagMembers || {}; 9962activiteitenTags = data.activiteitenTags || []; 9963// Merge Shopify tag members as virtual participants (status: going, fromTag: true)
9964allRides.forEach(ride => { 9965if (!ride.rsvpTag) return; 9966const tag = ride.rsvpTag.trim().toLowerCase(); 9967const members = tagMembersMap[tag] || []; 9968members.forEach(m => { 9969const alreadyIn = allParticipants.some(p => 9970p.ritId === ride.id && clean(p.email) === clean(m.email) 9971); 9972if (!alreadyIn) { 9973allParticipants.push({ 9974ritId: ride.id, 9975email: m.email, 9976status: STATUS_GO, 9977name: m.name, 9978avatar: m.avatar || '', 9979fromTag: true 9980}); 9981} 9982}); 9983}); 9984if (userEmail) { 9985const meInDb = allParticipants.find(p => clean(p.email) === clean(userEmail)) || 9986allRides.find(r => clean(r.email) === clean(userEmail)); 9987if (meInDb) { 9988// Naam alleen overschrijven als profielnaam uit spreadsheet nog niet geladen is 9989if (!profileNameLoaded) localDisplayName = meInDb.name || localDisplayName; 9990localDisplayAvatar = meInDb.avatar || meInDb.hostAvatar || ""; 9991} 9992} 9993setupData(); 9994if (userEmail) { 9995ensureOwnerAutoJoinEverywhere_(); 9996ensureTagAutoJoin_(); 9997} 9998render(); 9999setLoading(false); 10000handleActivityDeepLink(); 10001// If a deep-link ride was previously opened, keep it open after re-renders 10002if (deepLinkRideId) { 10003setTimeout(() => { 10004const card = document.querySelector(`[data-ride-id="${deepLinkRideId}"]`); 10005if (card) { 10006const det = card.querySelector('.ride-details'); 10007if (det && !det.classList.contains('open')) { 10008det.classList.add('open'); 10009det.style.maxHeight = '5000px'; 10010} 10011} 10012}, 50); 10013} 10014} 10015async function fetchFreshData() { 10016const res = await fetchWithTimeout(`${RIDE_SCRIPT_URL}?action=load`); 10017if (!res.ok) throw new Error('HTTP ' + res.status + ' ' + res.statusText); 10018const _txt = await res.text(); 10019if (!_txt || !_txt.trim()) throw new SyntaxError('Lege respons van server'); 10020const data = JSON.parse(_txt); 10021try { localStorage.setItem(GR_CACHE_KEY, JSON.stringify({ ts: Date.now(), data })); } catch(e) {} 10022return data; 10023} 10024function ensureTagAutoJoin_() { 10025if (!userEmail) return; 10026const lowerMe = clean(userEmail); 10027const touched = new Set(); 10028allRides.forEach(ride => { 10029if (!ride.rsvpTag) return; 10030const tag = clean(ride.rsvpTag); 10031if (!tag) return; 10032const userHasTag = userTags.some(t => clean(t) === tag); 10033if (!userHasTag) return; 10034const hasRow = allParticipants.some(p => p.ritId === ride.id && clean(p.email) === lowerMe); 10035if (!hasRow) { 10036// Use best available name/avatar: existing participant entry > localDisplay > Liquid name 10037const myExisting = allParticipants.find(p => clean(p.email) === lowerMe && p.name && p.name !== 'Gast'); 10038const bestName = (myExisting && myExisting.name) ? myExisting.name : localDisplayName; 10039const bestAvatar = (myExisting && myExisting.avatar) ? myExisting.avatar : localDisplayAvatar; 10040allParticipants.push({ ritId: ride.id, email: userEmail, status: STATUS_GO, name: bestName, avatar: bestAvatar }); 10041if (!touched.has(ride.id)) { 10042touched.add(ride.id); 10043sendPost({ action: 'rsvp', ritId: ride.id, email: userEmail, status: STATUS_GO }, 0); 10044} 10045} 10046}); 10047} 10048function handleActivityDeepLink() { 10049if (deepLinkHandled) return; 10050const params = new URLSearchParams(window.location.search); 10051const actId = params.get('activity'); 10052if (!actId) return; 10053deepLinkHandled = true; 10054// Match by full UUID or first-8-chars shortcode 10055const ride = allRides.find(r => r.id === actId || r.id.startsWith(actId)); 10056if (!ride) return; 10057const isPast = ride.datum && new Date(ride.datum) < new Date(); 10058const isCancelled = String(ride.status).toLowerCase() === 'geannuleerd'; 10059if (isPast || isCancelled) { 10060activeView = 'archive'; 10061const sel = document.getElementById('viewSelect'); 10062if (sel) sel.value = 'archive'; 10063} 10064deepLinkRideId = ride.id; 10065// Put shortcode in search field so the ride is filtered/visible 10066const searchEl = document.getElementById('filterArea'); 10067if (searchEl) searchEl.value = actId.substring(0, 8); 10068render(); 10069setTimeout(() => { 10070const card = document.querySelector(`[data-ride-id="${ride.id}"]`); 10071if (card) { 10072card.scrollIntoView({ behavior: 'smooth', block: 'center' }); 10073const det = card.querySelector('.ride-details'); 10074if (det && !det.classList.contains('open')) { 10075det.classList.add('open'); 10076det.style.maxHeight = '5000px'; 10077} 10078} 10079}, 300); 10080} 10081async function init() { 10082if (ADMIN_EMAILS.includes(clean(userEmail))) { 10083const pub = document.getElementById('publicRideGroup'); 10084if (pub) pub.classList.remove('hidden'); 10085} 10086// ?clearcache=1 in URL: leeg browser localStorage én GAS cache (voor admins) 10087if (new URLSearchParams(window.location.search).get('clearcache') === '1') { 10088try { localStorage.removeItem(GR_CACHE_KEY); } catch(e) {}
10089fetch(RIDE_SCRIPT_URL + '?action=clear_cache').catch(() => {}); 10090} 10091// Profielnaam zo vroeg mogelijk ophalen (parallel met data load) 10092// zodat localDisplayName uit spreadsheet kolom B komt vóór enige RSVP-actie 10093if (userEmail && !profileLoadedOnce) { profileLoadedOnce = true; loadProfileData(false); } 10094setLoading(true); 10095/* Ophalen en verwerken strikt gescheiden houden. Zat applyData binnen dezelfde 10096 try, dan werd een fout in de rendercode gemeld als netwerkfout, kwam er een 10097 zinloze retry overheen en verdween de echte stacktrace. */ 10098// Layer 1: verse cache direct tonen 10099const _vers = _grLeesCache(false); 10100if (_vers) { 10101console.info('[GR] laag 1: verse cache gebruikt (' + (_vers.data.ritten||[]).length + ' ritten)'); 10102applyData(_vers.data); 10103fetchFreshData() 10104 .then(fresh => applyData(fresh)) 10105 .catch(e => console.warn('[GR] achtergrondvernieuwing mislukt:', _grDiagnose(e), e)); 10106return; 10107} 10108// Layer 2: ophalen met time-out â bij fout één keer opnieuw met ruimere marge 10109let lastErr, verseData = null; 10110try { 10111const _t0 = Date.now(); 10112verseData = await fetchFreshData(); 10113console.info('[GR] laag 2: server gaf ' + (verseData.ritten||[]).length + ' ritten in ' + (Date.now()-_t0) + 'ms'); 10114} catch(err) { 10115lastErr = err; 10116console.warn('[GR] ophalen mislukt (poging 1):', _grDiagnose(err), err); 10117// Korte pauze vóór retry (Apps Script kan nog aan het opstarten zijn) 10118await new Promise(r => setTimeout(r, 2000)); 10119try { 10120const res = await fetchWithTimeout(`${RIDE_SCRIPT_URL}?action=load`, 25000); 10121if (!res.ok) throw new Error('HTTP ' + res.status + ' ' + res.statusText); 10122const txt = await res.text(); 10123if (!txt || !txt.trim()) throw new SyntaxError('Lege respons van server'); 10124verseData = JSON.parse(txt); 10125try { localStorage.setItem(GR_CACHE_KEY, JSON.stringify({ ts: Date.now(), data: verseData })); } catch(e) {} 10126} catch(err2) { 10127lastErr = err2; 10128console.warn('[GR] ophalen mislukt (poging 2):', _grDiagnose(err2), err2); 10129} 10130} 10131// Buiten de try: een fout hieronder is een codefout, geen netwerkfout. 10132if (verseData) { applyData(verseData); return; } 10133// Layer 3: verouderde cache is beter dan een leeg scherm 10134const _oud = _grLeesCache(true); 10135if (_oud) { 10136console.warn('[GR] server onbereikbaar â verouderde cache gebruikt van', new Date(_oud.ts).toLocaleString('nl-NL')); 10137applyData(_oud.data); 10138_grToonHerlaadmelding(lastErr, _oud.ts); 10139return; 10140} 10141// Layer 4: niets om te tonen â pas nu een echte foutmelding 10142setLoading(false); 10143_grToonFout(lastErr); 10144} 10145/* Meldingen komen in het eerste overlay-element; de rest blijft verborgen, 10146 zodat dezelfde tekst niet twee keer op de pagina verschijnt. */ 10147function _grMeldOverlay() { 10148setLoading(false); // alles verbergen + spinner-timer stoppen 10149const el = _grOverlays()[0]; 10150if (!el) return null; 10151el.classList.remove('hidden'); 10152el.style.display = ''; 10153const spin = el.querySelector('.gr-dashboard-spinner'); 10154if (spin) spin.style.display = 'none'; 10155return el; 10156} 10157/* Zorgt dat de overlay een eigen regel heeft voor meldingen, zodat we 10158 p.gr-loading-inline-text (de laadtekst) niet hoeven te kapen. */ 10159function _grMeldingRegel(overlay) { 10160if (!overlay) return null; 10161let box = overlay.querySelector('.loading-box') || overlay; 10162// planner-html levert al een .loading-sub-regel; die hergebruiken we 10163let el = overlay.querySelector('.gr-load-notice') || overlay.querySelector('.loading-sub'); 10164if (el) el.style.display = ''; 10165if (!el) { 10166el = document.createElement('p'); 10167el.className = 'gr-load-notice'; 10168el.style.cssText = 'margin:0;padding:0;font-size:0.9em;line-height:1.4;'; 10169box.appendChild(el); 10170} 10171return el; 10172} 10173/* Data is oud maar bruikbaar: onopvallende melding, planner blijft werken. */ 10174function _grToonHerlaadmelding(err, ts) { 10175const overlay = _grMeldOverlay(); 10176if (!overlay) return; 10177const laad = overlay.querySelector('p.gr-loading-inline-text'); 10178if (laad) laad.style.display = 'none'; 10179const kop = overlay.querySelector('h2, h4'); 10180if (kop) kop.style.display = 'none'; 10181const el = _grMeldingRegel(overlay); 10182if (!el) return; 10183el.style.color = '#888'; 10184const wanneer = ts ? new Date(ts).toLocaleString('nl-NL', { day:'numeric', month:'short', hour:'2-digit', minute:'2-digit' }) : ''; 10185el.innerHTML = (L['gr-planner-stale-cache'] || 'Server niet bereikbaar â je ziet opgeslagen gegevens') 10186+ (wanneer ? ' van ' + wanneer : '') 10187+ ' â <a href="#" class="gr-load-retry" style="color:inherit;font-weight:700;">' 10188+ (L['gr-planner-retry'] || 'Opnieuw proberen') + '</a>'; 10189_grBindHerlaad(overlay); 10190} 10191/* Geen data én geen cache: echte foutmelding met werkende retry-link. */ 10192function _grToonFout(err) { 10193console.error('[GR] Rittendata kon niet geladen worden. Diagnose:', _grDiagnose(err), '\nEndpoint:', RIDE_SCRIPT_URL + '?action=load', '\nOorspronkelijke fout:', err);
10194const overlay = _grMeldOverlay(); 10195if (!overlay) return; 10196const titel = L['gr-planner-error-load-title'] || 'Fout bij laden'; 10197const kop = overlay.querySelector('h2, h4'); 10198const laad = overlay.querySelector('p.gr-loading-inline-text'); 10199if (kop) { kop.style.display = ''; kop.textContent = titel; } 10200if (laad) { laad.style.display = kop ? 'none' : 'block'; if (!kop) laad.textContent = titel; } 10201const el = _grMeldingRegel(overlay); 10202if (el) { 10203el.style.color = '#888'; 10204el.innerHTML = _grDiagnose(err) 10205+ ' â <a href="#" class="gr-load-retry" style="color:inherit;font-weight:700;">' 10206+ (L['gr-planner-retry'] || 'Opnieuw proberen') + '</a>'; 10207} 10208_grBindHerlaad(overlay); 10209} 10210function _grBindHerlaad(overlay) { 10211const a = overlay && overlay.querySelector('.gr-load-retry'); 10212if (!a || a._grBound) return; 10213a._grBound = true; 10214a.addEventListener('click', function (e) { e.preventDefault(); window.grHerlaadPagina(); }); 10215} 10216function getCountryValue(d) { 10217if(!d) return ""; 10218return d.land || d.Land || d.landcode || d.Landcode || d.LandCode || d.country || ""; 10219} 10220function setupData() { 10221/* #inpRondo en #inpType zitten in rideModal, en dat staat sinds de verhuizing 10222 in gr-shared-modals.html (footer). Draait dit script eerder, dan waren de 10223 verwijzingen op regel 68 null â dát wierp de TypeError die als netwerkfout 10224 werd gerapporteerd. Daarom hier opnieuw opzoeken en overal guards. */ 10225if (!inpRondo) inpRondo = gEI('inpRondo'); 10226if (!inpType) inpType = gEI('inpType'); 10227const prevRondo = inpRondo ? inpRondo.value : ''; 10228const list = document.getElementById('areaList'); 10229if (list) list.innerHTML = ""; 10230if (inpRondo) inpRondo.innerHTML = `<option value="">${L['gr-planner-opt-choose-area'] || 'Kies gebied...'}</option>`; 10231const areas = Object.keys(routeData).sort(); 10232let allTypes = new Set(); 10233areas.forEach(a => { 10234const areaTag = areaTags[a] ? clean(areaTags[a]) : null; 10235if (!areaTag) return; 10236const hasAreaAccess = !!userEmail; // Alle ingelogde gebruikers zien alle gebieden 10237if (list) { let opt = document.createElement('option'); opt.value = a; list.appendChild(opt); } 10238if (hasAreaAccess && inpRondo) { 10239let opt2 = document.createElement('option'); 10240opt2.value = a; 10241opt2.text = a; 10242inpRondo.appendChild(opt2); 10243} 10244(routeData[a] || []).forEach(t => allTypes.add(t)); 10245}); 10246const typeSelect = document.getElementById('filterType'); 10247if (typeSelect) { 10248typeSelect.innerHTML = `<option value="">${L['gr-planner-filter-types'] || 'Alle Types'}</option>`; 10249Array.from(allTypes).sort().forEach(t => { 10250const opt = document.createElement('option'); opt.value = t; opt.text = t; typeSelect.appendChild(opt); 10251}); 10252} 10253const countrySet = new Set(); 10254Object.values(routeDetails).forEach(d => { 10255const val = getCountryValue(d); 10256if(val) countrySet.add(val); 10257}); 10258const countrySelect = document.getElementById('filterCountry'); 10259if (countrySelect) { 10260countrySelect.innerHTML = `<option value="">${L['gr-planner-filter-countries'] || 'Alle Landen'}</option>`; 10261Array.from(countrySet).sort().forEach(c => { 10262const opt = document.createElement('option'); opt.value = c; opt.text = c; countrySelect.appendChild(opt); 10263}); 10264} 10265if(prevRondo && inpRondo) { 10266if(!Array.from(inpRondo.options).some(o => o.value === prevRondo)) { 10267const oPrev = document.createElement('option'); oPrev.value = prevRondo; oPrev.text = prevRondo; inpRondo.appendChild(oPrev); 10268} 10269inpRondo.value = prevRondo; 10270} 10271/* setupData draait bij elke applyData (cache + verse data), dus listeners 10272 maar één keer binden â anders stapelen ze op. */ 10273if (inpRondo && !inpRondo._grBound) { inpRondo._grBound = true; inpRondo.addEventListener('change', updateTypeOptions); } 10274if (inpType && !inpType._grBound) { inpType._grBound = true; inpType.addEventListener('change', updateRouteInfo); } 10275['filterArea', 'filterType', 'filterPace', 'filterTarget', 'sortBy', 'filterDaySelect', 'filterCountry'].forEach(id => { 10276const el = document.getElementById(id); 10277if (el && !el._grBound) { el._grBound = true; el.addEventListener('input', render); } 10278}); 10279 10280} 10281function updateTypeOptions() { 10282const selectedArea = inpRondo.value; 10283inpType.innerHTML = ""; 10284document.getElementById('routeInfoBox').classList.add('hidden'); 10285if(!selectedArea || !routeData[selectedArea]) { 10286const opt = document.createElement('option'); opt.value = ""; opt.text = L['gr-planner-opt-first-choose-area'] || "â Kies gebied"; inpType.appendChild(opt); return; 10287} 10288const validTypes = routeData[selectedArea] || [];
10289validTypes.forEach(t => { 10290const opt = document.createElement('option'); opt.value = t; opt.text = t; inpType.appendChild(opt); 10291}); 10292const hasRoad = validTypes.some(t => t.toLowerCase().includes('road')); 10293const hasGravel = validTypes.some(t => t.toLowerCase().includes('gravel')); 10294if(validTypes.length >= 2 && hasRoad && hasGravel) { 10295const opt = document.createElement('option'); opt.value = "Beide"; opt.text = L['gr-planner-opt-type-both'] || "Beide"; inpType.appendChild(opt); 10296} 10297if(validTypes.length > 0) { 10298inpType.value = validTypes[0]; updateRouteInfo(); 10299} 10300} 10301function getRouteDetails(ride) { 10302const rondo = ride.rondo || ""; 10303const type = ride.type || ""; 10304const key = rondo + "|" + type; 10305if (routeDetails[key]) return routeDetails[key]; 10306if (type === "Road, Gravel") return routeDetails[rondo + "|Road"] || routeDetails[rondo + "|Gravel"] || {}; 10307if (type === "Beide") return routeDetails[rondo + "|Road"] || routeDetails[rondo + "|Gravel"] || {}; 10308// Case-insensitive fallback (voor verschillen in hoofd-/kleine letters) 10309const allRdKeys = Object.keys(routeDetails); 10310const lKey = key.toLowerCase(); 10311const ciMatch = allRdKeys.find(k => k.toLowerCase() === lKey); 10312if (ciMatch) return routeDetails[ciMatch]; 10313// Gedeeltelijke match op rondo-naam alleen (voor ticket-events zonder type, of afwijkend type) 10314if (rondo) { 10315 const lRondo = rondo.toLowerCase() + "|"; 10316 const partMatch = allRdKeys.find(k => k.toLowerCase().startsWith(lRondo)); 10317 if (partMatch) return routeDetails[partMatch]; 10318} 10319return {}; 10320} 10321function updateRouteInfo() { 10322const area = inpRondo.value; 10323const selType = inpType.value; 10324const lookupType = selType === 'Beide' ? 'Road' : selType; 10325const key = area + "|" + lookupType; 10326const infoBox = document.getElementById('routeInfoBox'); 10327if(routeDetails[key]) { 10328const d = routeDetails[key]; 10329document.getElementById('infoName').innerText = d.naam || area; 10330const label = selType === 'Beide' ? 'Road, Gravel' : selType; 10331document.getElementById('infoStats').innerHTML = buildRouteStatsHTML(label, d.richting, d.afstand, d.hm); 10332infoBox.classList.remove('hidden'); 10333// Vul standaard invite-tekst in bij NIEUWE rit (niet bij editten) 10334if (!modal._isEditMode) { 10335const editor = gEI('inpExtraDiv'); 10336const editorEn = gEI('inpExtraDivEn'); 10337if (editor && !editor._userEdited) { 10338const txt = (_isEn && d.inviteEn) ? d.inviteEn : (d.invite || d.inviteEn || ""); 10339editor.innerHTML = txt ? txt.replace(/\n/g, '<br>') : ""; 10340} 10341if (editorEn && !editorEn._userEdited) { 10342editorEn.innerHTML = d.inviteEn ? d.inviteEn.replace(/\n/g, '<br>') : ""; 10343} 10344} 10345} else { 10346infoBox.classList.add('hidden'); 10347} 10348} 10349function buildRouteStatsHTML(label, richting, dist, hm) { 10350let html = `<div class="route-stats-block"><p><em>${label}</em>`; 10351if (richting) html += `<em><strong>${richting}</strong></em>`; 10352if (dist) html += `<em>${String(dist).replace('.',',')}km</em>`; 10353if (hm) html += `<em><strong>â</strong></em><em>${hm}hm</em>`; 10354html += `</p></div>`; 10355return html; 10356} 10357function getInitials(name) { 10358if(!name) return "?";
10359const parts = String(name).trim().split(' ').filter(Boolean); 10360return (parts.length >= 2) ? (parts[0][0]+parts[1][0]).toUpperCase() : name.substring(0,2).toUpperCase(); 10361} 10362function updateAvatarsForCard(rideId) { 10363const row = gEI(`avatarsRow-${rideId}`); if(!row) return; 10364const _avRide = allRides.find(r => r.id === rideId); 10365const _avIsBucketlist = _avRide && _avRide.status === STATUS_BUCKETLIST; 10366const parts = allParticipants.filter(p => p.ritId === rideId && (p.status === STATUS_GO || p.status === STATUS_MAYBE || (!_avIsBucketlist && p.status === STATUS_VOLTOOID))); 10367let html = `<span class="participant-count">(${parts.length})</span>`; 10368parts.slice(0, 3).forEach(p => { 10369const pName = p.name === "Gast" ? L['gr-planner-guest'] : (p.name === "Onbekend" ? L['gr-planner-unknown'] : p.name); 10370if(p.avatar) html += `<img src="${p.avatar}" class="avatar-img" title="${pName}">`; 10371else html += `<div class="avatar-placeholder" title="${pName}">${getInitials(pName)}</div>`; 10372}); 10373row.innerHTML = html; 10374} 10375/* dd-mm-jjjj. De sheet levert een ISO-string; lukt het parsen niet, dan tonen 10376 we niets in plaats van "Invalid Date". */ 10377function _fmtDeelnemerDatum(waarde) { 10378if(!waarde) return ""; 10379const d = new Date(waarde); 10380if(isNaN(d.getTime())) return ""; 10381const p = n => String(n).padStart(2, '0'); 10382return `${p(d.getDate())}-${p(d.getMonth()+1)}-${d.getFullYear()}`; 10383} 10384function updateParticipantsListForCard(rideId) { 10385const listEl = gEI(`participants-list-${rideId}`); if(!listEl) return; 10386const _plRide = allRides.find(r => r.id === rideId); 10387const _plIsBucketlist = _plRide && _plRide.status === STATUS_BUCKETLIST; 10388/* Admins zien ook wie de Rondo alleen op zijn bucketlist heeft gezet â voor 10389 iedereen anders blijft de lijst wat hij was. */ 10390const _plIsAdmin = ADMIN_EMAILS.includes(clean(userEmail)); 10391const parts = allParticipants.filter(p => p.ritId === rideId && (p.status === STATUS_GO || p.status === STATUS_MAYBE || (_plIsAdmin && p.status === STATUS_BUCKETLIST) || (!_plIsBucketlist && p.status === STATUS_VOLTOOID))).sort((a,b) => (a.name||"").localeCompare(b.name||"")); 10392if(parts.length === 0) { listEl.innerHTML = `<div style="padding:12px; opacity:0.7;">${L['gr-planner-no-participants-yet'] || 'Nog geen deelnemers.'}</div>`; return; } 10393listEl.innerHTML = parts.map(p => { 10394const dot = p.status === STATUS_MAYBE ? `<span class="status-dot maybe">?</span>` : p.status === STATUS_VOLTOOID ? `<span class="status-dot go">ââ</span>` : p.status === STATUS_BUCKETLIST ? `<span class="status-dot bucket">â¥</span>` : `<span class="status-dot go">V</span>`; 10395const pName = p.name === "Gast" ? L['gr-planner-guest'] : (p.name === "Onbekend" ? L['gr-planner-unknown'] : p.name); 10396const av = p.avatar ? `<img src="${p.avatar}" style="width:34px;height:34px;border-radius:50%;object-fit:cover;">` : `<div class="avatar-placeholder" style="width:34px;height:34px;">${getInitials(pName)}</div>`;
10397/* Datum uit de Deelnemers-sheet: wanneer de RSVP of het vinkje gezet is. 10398 Alleen voor admins, en alleen als het backend-script hem meestuurt. */ 10399const _pd = _plIsAdmin ? _fmtDeelnemerDatum(p.datum) : ""; 10400const datumHtml = _pd ? `<span class="participants-date">${_pd}</span>` : ""; 10401return `<div class="participants-row">${av}<div class="pmeta"><div class="pname">${pName} ${dot}</div></div>${datumHtml}</div>`; 10402}).join(''); 10403} 10404function renderCommentsForCard(ride, isOwner) { 10405const commentsDiv = gEI(`comments-${ride.id}`); if(!commentsDiv) return; 10406commentsDiv.innerHTML = ""; 10407const myEmail = clean(userEmail); const rideOwnerEmail = clean(ride.email); 10408const isGlobalAdmin = ADMIN_EMAILS.includes(clean(userEmail)); 10409const cardComments = allComments.filter(c => c.ritId === ride.id).sort((a,b) => new Date(a.timestamp) - new Date(b.timestamp)); 10410cardComments.forEach(c => { 10411const commentEmail = clean(c.email); 10412const isMine = myEmail === commentEmail && userEmail; 10413const isRideOwner = (isOwner || (myEmail === rideOwnerEmail)) && userEmail; 10414const canDelete = isMine || isRideOwner || isGlobalAdmin; 10415const isCommenterOrganizer = (commentEmail === rideOwnerEmail); 10416let timeStr = ""; 10417if(c.timestamp) { const cd = new Date(c.timestamp); timeStr = `${cd.getDate()}/${cd.getMonth()+1} - ${cd.getHours()}:${cd.getMinutes().toString().padStart(2,'0')}`; } 10418let cName = c.name === "Gast" ? L['gr-planner-guest'] : (c.name === "Onbekend" ? L['gr-planner-unknown'] : c.name); 10419let avHtml = c.avatar ? `<img src="${c.avatar}" class="comment-avatar-img">` : `<div class="comment-avatar-placeholder">${getInitials(cName)}</div>`; 10420let nameHtml = `<span class="comment-meta">${cName}</span>`; 10421if (isCommenterOrganizer) nameHtml += `<span class="organizer-label">(${L['gr-planner-organizer-label'] || 'organisator'})</span>`; 10422const div = document.createElement('div'); div.className = 'comment-item'; 10423div.innerHTML = `${avHtml}<div class="comment-content">${nameHtml}<span class="comment-date">(${timeStr})</span><br><span class="comment-text">${(c.text||'').replace(/\n/g,'<br>')}</span></div>${canDelete ? `<button class="comment-delete-btn" title="${L['gr-planner-delete-message'] || 'Verwijder'}">${SVG_TRASH}</button>` : ''}`; 10424if(canDelete) { const btn = div.querySelector('.comment-delete-btn'); if(btn) btn.onclick = function() { window.deleteComment(ride.id, c.timestamp, div); }; } 10425commentsDiv.appendChild(div); 10426}); 10427}
10428function ensureOwnerAutoJoinEverywhere_() { 10429const lowerMe = clean(userEmail); if (!lowerMe) return; 10430const touched = new Set(); 10431allRides.forEach(ride => { 10432if(clean(ride.email) !== lowerMe) return; 10433const hasRow = allParticipants.some(p => p.ritId === ride.id && clean(p.email) === lowerMe); 10434if(!hasRow) { 10435allParticipants.push({ ritId: ride.id, email: userEmail, status: STATUS_GO, name: localDisplayName, avatar: localDisplayAvatar }); 10436if(!touched.has(ride.id)) { touched.add(ride.id); sendPost({ action: 'rsvp', ritId: ride.id, email: userEmail, status: STATUS_GO }, 0); } 10437} 10438}); 10439} 10440/* Schrijfacties gaan één voor één de deur uit, en we wachten op het antwoord 10441 van de server voordat de volgende vertrekt. 10442 10443 Voorheen werd de fetch afgevuurd zonder await en daarna simpelweg 200 ms 10444 gewacht. Verwijderde je een opmerking meteen na het plaatsen, dan kon de 10445 delete de server bereiken vóórdat de post verwerkt was: de verwijdering vond 10446 niets en de opmerking werd er daarna alsnog in gezet. */ 10447let _grPostKeten = Promise.resolve(); 10448/* ââ Pagina verversen na een wijziging ââââââââââââââââââââââââââââââââââââ 10449 Na opslaan werd er location.reload() gedaan. Daar kwam het dashboard en de 10450 kaart soms niet meer uit: eindeloos laden, en alleen een harde verversing 10451 hielp. Een gewone reload mag de pagina uit de bfcache terughalen en laat de 10452 oude pagina in de geschiedenis staan, dus met de terugknop kom je zó weer in 10453 dezelfde halve toestand terecht. 10454 10455 De echte boosdoener bleek de gedeelde cache in localStorage: die hield de 10456 stand van vóór de wijziging vast. Die gaat hier dus als eerste leeg. 10457 10458 Daarna werd er location.replace() gedaan in plaats van reload(). Dat ging mis 10459 zodra er een hash werd meegegeven: verschilt de nieuwe URL uitsluitend in het 10460 deel achter de #, dan ziet de browser dat niet als een navigatie. Hij springt 10461 naar het anker en laat de pagina verder met rust â geen enkel script draait 10462 opnieuw. Op het dashboard leverde dat een sluitknop op die niets leek te doen: 10463 de melding "Je rit is ingediend" bleef gewoon staan. Live nagemeten: na 10464 location.replace(pad + '#palmares') bestond een vóóraf gezette variabele nog 10465 steeds, dus het document was inderdaad niet vervangen. 10466 10467 Daarom nu: eerst de hash in de adresbalk zetten met replaceState (dat voegt 10468 geen stap aan de geschiedenis toe, dus de terugknop blijft schoon) en daarna 10469 expliciet herladen. Een reload haalt nooit uit de bfcache, dus de halve staat 10470 van de oude pagina komt net zo min terug als bij replace(). 10471 10472 De hash blijft staan, zodat je op hetzelfde tabblad terugkomt. */ 10473window.grHerlaadPagina = function (hash) { 10474 try { localStorage.removeItem('gr_rides_v1'); } catch (e) {} 10475 var nieuweHash = (hash != null) ? hash : location.hash; 10476 try { 10477 if (nieuweHash !== location.hash) { 10478 var url = location.pathname + location.search + nieuweHash; 10479 if (window.history && history.replaceState) history.replaceState(null, '', url); 10480 else location.hash = nieuweHash; 10481 } 10482 } catch (e) { /* adresbalk bijwerken is bijzaak; herladen is de hoofdzaak */ } 10483 location.reload(); 10484}; 10485 10486async function sendPost(data, waitTime = 200) { 10487const taak = _grPostKeten.then(async () => { 10488try { 10489await fetch(RIDE_SCRIPT_URL, { method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); 10490} catch(e) { console.warn('[GR] opslaan mislukt:', data && data.action, e); } 10491if(waitTime > 0) await new Promise(r => setTimeout(r, waitTime)); 10492}); 10493// Een mislukte actie mag de keten niet blokkeren voor de volgende. 10494_grPostKeten = taak.catch(() => {}); 10495return taak; 10496} 10497/* Deze elementen staan in planner-html / dashboard-wishlist. Op het dashboard 10498 bestaan ze, dus daar verandert er niets. Op andere pagina's gooide een kale 10499 .addEventListener een TypeError, waardoor de rest van dit bestand â inclusief 10500 init() en dus het laden van allRides â niet meer draaide. */ 10501const _btnOpenProfileDirect = gEI('btnOpenProfileDirect'); 10502if (_btnOpenProfileDirect) _btnOpenProfileDirect.addEventListener('click', function(e) { if(window.requireLogin(e)) return; if(!profileModal) return; profileModal.style.display = 'block'; loadProfileData(); }); 10503const _btnTriggerProfileEdit = gEI('btnTriggerProfileEdit'); 10504if (_btnTriggerProfileEdit) _btnTriggerProfileEdit.addEventListener('click', function(e) { if(window.requireLogin(e)) return; profileModal.style.display = 'block'; loadProfileData(); }); 10505var profileModalDismissed = false;
10506function closeProfileModal() { 10507if(!profileModal) return; 10508profileModal.style.display = 'none'; 10509profileModal.classList.remove('forced-modal'); 10510profileModalDismissed = true; 10511} 10512const _btnCloseProfileModal = gEI('btnCloseProfileModal'); 10513if (_btnCloseProfileModal) _btnCloseProfileModal.addEventListener('click', closeProfileModal); 10514const _btnCancelProfileModal = gEI('btnCancelProfileModal'); 10515if (_btnCancelProfileModal) _btnCancelProfileModal.addEventListener('click', closeProfileModal); 10516const _avatarInput = gEI('avatarInput'); 10517if (_avatarInput) _avatarInput.addEventListener('change', function(e) { 10518const fileNameDisplay = gEI('fileNameDisplay'); 10519if (this.files && this.files.length > 0) { fileNameDisplay.textContent = (L['gr-planner-replace-with'] || 'Vervang: ') + this.files[0].name; fileNameDisplay.classList.remove('hidden'); } 10520else { fileNameDisplay.textContent = ""; fileNameDisplay.classList.add('hidden'); } 10521}); 10522function renderProfileTags() { 10523const container = gEI('profileTagsContainer'); 10524if (!container) return; // profielformulier niet op deze pagina 10525container.innerHTML = ""; 10526if (!userTags || !userTags.length) return; 10527const isRondo = userTags.some(t => String(t).toLowerCase() === "rondoneur"); 10528if (isRondo) { const span = document.createElement('span'); span.className = 'profile-tag-pill'; span.innerText = "Rondoneur"; container.appendChild(span); return; } 10529if (!knownTags || !knownTags.length) return; 10530const matches = userTags.filter(t => knownTags.some(k => k.toLowerCase() === t.toLowerCase())); 10531matches.forEach(m => { const span = document.createElement('span'); span.className = 'profile-tag-pill'; span.innerText = m; container.appendChild(span); }); 10532} 10533function loadProfileData(forceCheck = false) { 10534renderProfileTags(); 10535const pForm = gEI("shopifyProfileForm"); 10536const pLoading = gEI("profileLoadingMsg"); 10537const pAvatar = gEI("currentAvatarEdit"); 10538/* Zonder profielformulier valt er niets in te vullen â maar het mag init() 10539 (en dus het laden van allRides) niet afbreken. */ 10540if (!pForm || !pLoading || !pAvatar) return; 10541pForm.classList.add('hidden'); pLoading.classList.remove('hidden'); pAvatar.classList.add('hidden'); 10542const _fnd = gEI('fileNameDisplay'); 10543if (_fnd) { _fnd.textContent = ""; _fnd.classList.add('hidden'); } 10544fetchWithTimeout(PROFILE_SCRIPT_URL + "?action=get_profile&email=" + encodeURIComponent(userEmail) + "&t=" + Date.now(), 14000) 10545.then(r => r.json()) 10546.then(data => { 10547pLoading.classList.add('hidden'); pForm.classList.remove('hidden'); 10548if (forceCheck && !profileModalDismissed) { if (!data.found || !data.name) { profileModal.style.display = 'block'; profileModal.classList.add('forced-modal'); } } 10549if(data && data.found) { 10550const p = data.planner || data; 10551const v = (sel, val) => { const el = gQS(sel); if (el && val) el.value = val; }; 10552const stripPrefix = (url, prefix) => (url || '').replace(prefix, '').replace(/^https?:\/\//, ''); 10553// Gebruik profielnaam uit spreadsheet (kolom B "Wat is je naam?") als localDisplayName â altijd winnend 10554if (p.name) { localDisplayName = p.name; profileNameLoaded = true; } 10555// Gebruik profielavatar uit spreadsheet als localDisplayAvatar 10556if (p.avatarUrl && String(p.avatarUrl).length > 10) { localDisplayAvatar = p.avatarUrl; } 10557if (p.name) v('input[name="name"]', p.name); 10558if (p.avatarUrl && String(p.avatarUrl).length > 10) { pAvatar.src = p.avatarUrl; pAvatar.classList.remove('hidden'); } 10559v('input[name="city"]', p.city); 10560v('input[name="country"]', p.country); 10561v('input[name="birthday"]', p.birthday); 10562v('select[name="gender"]', p.gender); 10563// Discipline: load comma-separated value into checkboxes (or fallback to select if present) 10564if (gQS('input[name="discipline"]')) { 10565const _discRaw = p.discipline || ''; 10566// Verwijder eventueel oud ###-formaat 10567const _discCurrent = _discRaw.includes('###') 10568 ? (_discRaw.split('###').filter(s => s.trim()).pop() || '').replace(/^LEEG$/, '') 10569 : _discRaw; 10570const discVals = [...new Set(_discCurrent.split(',').map(d => d.trim()).filter(Boolean))]; 10571// Scoped to the form â voorkomt dat verborgen/dubbele inputs ook worden geladen 10572const _profileForm = gEI('shopifyProfileForm'); 10573(_profileForm || document).querySelectorAll('input[name="discipline"]') 10574 .forEach(cb => { cb.checked = discVals.includes(cb.value.trim()); }); 10575} else { v('select[name="discipline"]', p.discipline); } 10576v('select[name="pace"]', p.pace);
10577v('input[name="strava"]', stripPrefix(p.strava, 'https://www.strava.com/athletes/')); 10578v('input[name="komoot"]', stripPrefix(p.komoot, 'https://www.komoot.com/user/')); 10579v('input[name="instagram"]', stripPrefix(p.instagram, 'https://instagram.com/')); 10580v('input[name="website"]', stripPrefix(p.website, 'https://')); 10581const bioEl = gQS('textarea[name="bio"]'); 10582if (bioEl && p.bio) bioEl.value = p.bio; 10583const pubEl = gEI('profilePublicToggle'); 10584if (pubEl) pubEl.checked = (p.public === true || String(p.public).toUpperCase() === 'TRUE'); 10585} 10586}) 10587.catch(err => { 10588console.error(err); 10589pLoading.classList.add('hidden'); pForm.classList.remove('hidden'); 10590if (err.name === 'AbortError') { pLoading.innerText = L['gr-planner-profile-timeout'] || 'Profieldata niet beschikbaar.'; pLoading.classList.remove('hidden'); } 10591else { pLoading.innerText = L['gr-planner-error-fetching'] || 'Fout bij laden profiel.'; pLoading.classList.remove('hidden'); } 10592}); 10593} 10594const _shopifyProfileForm = gEI('shopifyProfileForm'); 10595if (_shopifyProfileForm) _shopifyProfileForm.onsubmit = function(e) { 10596e.preventDefault(); 10597const submitBtn = gEI('submitProfileBtn'); 10598submitBtn.disabled = true; submitBtn.innerText = L['gr-planner-saving-busy'] || "Opslaan..."; 10599const fileInput = gEI('avatarInput'); 10600function sendProfilePayload(base64Image, mime) { 10601const g = sel => { const el = gQS(sel); return el ? el.value.trim() : ''; }; 10602const addPrefix = (prefix, val) => val ? prefix + val.replace(/^https?:\/\//, '') : ''; 10603var payload = { 10604action: 'save_profile', 10605planner: { 10606email: userEmail, 10607name: g('input[name="name"]'), 10608city: g('input[name="city"]'), 10609country: g('input[name="country"]'), 10610birthday: g('input[name="birthday"]'), 10611gender: g('select[name="gender"]'), 10612discipline: gQS('input[name="discipline"]') ? (()=>{ 10613 const _pf = gEI('shopifyProfileForm'); 10614 const _inputs = (_pf || document).querySelectorAll('input[name="discipline"]:checked'); 10615 // Case-insensitieve dedup: voorkomt dubbeling bij gemengde hoofdletters 10616 const _seen = new Set(); 10617 const _unique = Array.from(_inputs).map(cb => cb.value.trim()).filter(Boolean).filter(v => { 10618 const k = v.toLowerCase(); if (_seen.has(k)) return false; _seen.add(k); return true; 10619 }); 10620 return _unique.join(','); 10621})() : g('select[name="discipline"]'), 10622pace: g('select[name="pace"]'), 10623strava: addPrefix('https://www.strava.com/athletes/', g('input[name="strava"]')), 10624komoot: addPrefix('https://www.komoot.com/user/', g('input[name="komoot"]')), 10625instagram: addPrefix('https://instagram.com/', g('input[name="instagram"]')), 10626website: addPrefix('https://', g('input[name="website"]')), 10627bio: (() => { const el = gQS('textarea[name="bio"]'); return el ? el.value.trim() : ''; })(), 10628public: !!(gEI('profilePublicToggle') && gEI('profilePublicToggle').checked), 10629avatar: base64Image || "", 10630avatarMime: mime || "" 10631} 10632}; 10633fetch(PROFILE_SCRIPT_URL, { method: "POST", mode: "no-cors", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }) 10634.then(() => { 10635 // Wacht 800ms zodat GAS de save kan verwerken VÃÃR de reload 10636 // Verwijder ook de browser-cache zodat na reload verse data wordt geladen 10637 try { localStorage.removeItem(GR_CACHE_KEY); } catch(e) {} 10638 setTimeout(function () { window.grHerlaadPagina(); }, 800); 10639}) 10640.catch(err => { console.error(err); submitBtn.disabled = false; submitBtn.innerText = L['gr-planner-btn-save'] || "Opslaan"; alert(L['gr-planner-alert-save-error'] || "Fout"); }); 10641} 10642if (fileInput.files && fileInput.files.length > 0) { 10643var file = fileInput.files[0]; var reader = new FileReader(); 10644reader.onload = function() { var base64String = reader.result.replace("data:", "").replace(/^.+,/, ""); sendProfilePayload(base64String, file.type); }; 10645reader.readAsDataURL(file); 10646} else { sendProfilePayload(null, ""); } 10647}; 10648</script>
10648 10649 10650 10651
10652<script> 10653const _isEn=typeof SHOP_LOCALE!=='undefined'&&String(SHOP_LOCALE).startsWith('en'); 10654const MONTHS=_isEn 10655? ["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"] 10656: ["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"]; 10657window.showUpgradeModal=function(shopLink){ 10658const orderBtn=gEI('upgradeModalOrderBtn'); 10659if(orderBtn) orderBtn.href = window._grTaalUrl(shopLink||'https://granrondo.cc/collections/all'); 10660gEI('upgradeModal').style.display = 'block'; 10661document.body.classList.add('modal-open'); 10662}; 10663/* showTicketModal staat nu in gr-shared-modals.html (footer), samen met de 10664 #ticketModal zelf. Zo werkt de popup ook op pagina's zonder de planner â 10665 de kaart roept hem aan bij "Bestel deze Rondo" en "Tickets boeken". 10666 Eén definitie, dus geen kans dat de twee uit elkaar gaan lopen. */ 10667function getAreaTagForRide(rondo){ 10668if(!areaTags||!rondo) return null; 10669if(areaTags[rondo]) return clean(areaTags[rondo]); 10670const lRondo=clean(rondo); 10671const k=Object.keys(areaTags).find(key=>clean(key)===lRondo); 10672return k ? clean(areaTags[k]) : null; 10673} 10674/* Toegang tot het detailpaneel (routeinfo, pillen, opmerkingen). 10675 Regel: events zijn open voor iedereen die is ingelogd; niet-events vragen 10676 daarnaast de juiste tag. Uitgelogd geeft nooit toegang â ook niet bij een 10677 publieke rit, want dan zou een uitgelogde bezoeker het paneel al zien. */ 10678function hasAccess(ride, details){ 10679if(!userEmail) return false; 10680if(ADMIN_EMAILS.includes(clean(userEmail))) return true; 10681/* Event = isPublic óf een rsvpTag, zelfde definitie als _gIsEvent hierboven. 10682 isPublic gaf al toegang aan elke ingelogde gebruiker; tag-events volgen nu 10683 dezelfde lijn, zodat beide soorten events zich hetzelfde gedragen. */ 10684if(ride.isPublic || (ride.rsvpTag && String(ride.rsvpTag).trim())) return true; 10685if(userTags.some(t=>clean(t)==='rondoneur')) return true; 10686const areaTag=getAreaTagForRide(ride.rondo); 10687if(areaTag&&userTags.some(t=>clean(t)===areaTag)) return true; 10688if(ride.rsvpTag){ 10689const rsvpTags=ride.rsvpTag.split(',').map(t=>clean(t)).filter(Boolean); 10690if(rsvpTags.some(tag=>userTags.some(ut=>clean(ut)===tag))) return true; 10691} 10692const lowerMe=clean(userEmail); 10693const myP=allParticipants.find(p=>p.ritId===ride.id&&clean(p.email)===lowerMe); 10694if(myP) return true; 10695return false; 10696} 10697function render(){ 10698if(window.GR_DASHBOARD_MODE){ 10699if(!allRides.length)return; 10700const _dbTab=window.GR_DASHBOARD_TAB||'rondoguides'; 10701if(_dbTab==='rondoguides'){ renderRondogidsenSection(); return; } 10702if(_dbTab==='bucketlist'){ renderGeplandSection(); return; } 10703if(_dbTab==='mine') { renderMineSection(); return; } 10704if(_dbTab==='voltooid-palmares'){ renderVoltooidPalmaresSection(); return; } 10705if(_dbTab==='archief'){ renderArchiefsSection(); return; } 10706} 10707listEl.innerHTML = ""; emptyEl.classList.add('hidden'); 10708const _dbs=gEI('dbSearchFilter'); 10709const filterA=(gEI('filterArea')?gEI('filterArea').value.toLowerCase().trim():'')||(_dbs?_dbs.value.toLowerCase().trim():''); 10710const filterT=gEI('filterType')?gEI('filterType').value:''; 10711const filterC=gEI('filterCountry')?gEI('filterCountry').value:''; 10712const filterP=gEI('filterPace')?gEI('filterPace').value:''; 10713const filterTarget=gEI('filterTarget')?gEI('filterTarget').value:''; 10714const sortBy=gEI('sortBy')?gEI('sortBy').value:'date'; 10715const daySelectVal=gEI('filterDaySelect')?gEI('filterDaySelect').value:''; 10716const lowerMe = clean(userEmail); 10717const isArchive = (activeView==='archive'); 10718const isAdminArchive=(activeView==='admin-archive'); 10719const isVoltooid = (activeView==='voltooid'); 10720const isPast=(ride)=>{ 10721if(!ride.datum) return false; 10722const d=new Date(ride.datum); const now=new Date(); now.setHours(0,0,0,0); return d < now; 10723}; 10724let rides=[...allRides]; 10725const filtered=rides.filter(ride=>{ 10726if(!userEmail&&!ride.isPublic) return false; 10727if(ride.status===STATUS_BUCKETLIST&&activeView!=='bucketlist'&&activeView!=='planned'&&activeView!=='all'&&!isVoltooid&&!isAdminArchive) return false; 10728const inVerleden = isPast(ride); 10729const isCancelled=(ride.status===STATUS_CANCELLED); 10730if(activeView==='all'&&isCancelled) return false; 10731if(activeView==='events'&&isCancelled) return false;
10732if(isVoltooid&&isCancelled) return false; 10733if(isAdminArchive){ 10734if(!inVerleden&&!isCancelled) return false; 10735} else if(isArchive){ 10736if(!inVerleden&&!isCancelled) return false; 10737const isOwner=clean(ride.email)===lowerMe; 10738const myP=allParticipants.find(p=>p.ritId===ride.id&&clean(p.email)===lowerMe&&(p.status===STATUS_GO||p.status===STATUS_MAYBE)); 10739if(!isOwner&&!myP) return false; 10740} else if(isVoltooid){ 10741const _todayStr=new Date().toISOString().slice(0, 10); 10742const _rideDateStr=(ride.datum||'').slice(0, 10); 10743const isVandaagOfEerder=!!(_rideDateStr&&_rideDateStr<=_todayStr); 10744if(!isVandaagOfEerder&&ride.status!==STATUS_BUCKETLIST) return false; 10745}else{ if(inVerleden) return false; } 10746const d=getRouteDetails(ride); 10747const areaSearch=(ride.rondo||"").toLowerCase(); 10748const locSearch = (ride.startlocatie||"").toLowerCase(); 10749const shortCode=ride.id ? ride.id.substring(0, 8) : ''; 10750if(filterA&&!areaSearch.includes(filterA)&&!locSearch.includes(filterA)&&!shortCode.startsWith(filterA)) return false; 10751if(filterT&&ride.type!==filterT){ 10752if(!(ride.type==='Road, Gravel'&&(filterT==='Road'||filterT==='Gravel'))) return false; 10753} 10754if(filterP&&ride.tempo!==filterP) return false; 10755if(filterTarget&&ride.voorWie!==filterTarget) return false; 10756if(filterC){ const countryVal=getCountryValue(d); if(countryVal!==filterC) return false; } 10757if(daySelectVal){ 10758let rideDays=""; 10759if(ride.dagen) rideDays = ride.dagen.toLowerCase(); 10760else if(ride.datum){ const dateObj=new Date(ride.datum); const daysMap=['zo','ma','di','wo','do','vr','za']; rideDays = daysMap[dateObj.getDay()]; } 10761if(!rideDays.includes(daySelectVal)) return false; 10762} 10763return true; 10764}); 10765if(sortBy==='date'){ 10766filtered.sort((a,b)=>{ 10767const ad=a.datum ? new Date(a.datum).getTime() : 9999999999999; 10768const bd=b.datum ? new Date(b.datum).getTime() : 9999999999999; 10769return (isArchive||isAdminArchive||isVoltooid) ? (bd - ad) : ((ad!==bd) ? ad - bd : (a.rondo||"").localeCompare(b.rondo||"")); 10770}); 10771}else{ filtered.sort((a,b)=>(a.rondo||"").localeCompare(b.rondo||"")); } 10772let finalList=[]; 10773if(activeView==='all'||activeView==='archive'||activeView==='admin-archive'){ finalList = filtered; } 10774else if(activeView==='events'){ 10775finalList = filtered.filter(r=>{ const isAdm=ADMIN_EMAILS.includes(clean(r.email)); return isAdm||(r.eventNaam&&r.eventNaam.length > 0); }); 10776} else if(activeView==='planned'){ 10777finalList = filtered.filter(r=>{ 10778const myP=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe); 10779if(r.status===STATUS_BUCKETLIST) return !!myP; 10780const isOwner=clean(r.email)===lowerMe; 10781return isOwner||(myP&&(myP.status===STATUS_GO||myP.status===STATUS_MAYBE)); 10782}); 10783} else if(activeView==='bucketlist'){ 10784finalList = filtered.filter(r=>{ 10785const isOrg=clean(r.email)===lowerMe; 10786if(r.status===STATUS_BUCKETLIST){ 10787const myP=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe); 10788return isOrg||(!!myP&&myP.status!==STATUS_VOLTOOID); 10789} 10790const myP=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe); 10791return isOrg||(myP&&(myP.status===STATUS_GO||myP.status===STATUS_MAYBE)); 10792}); 10793} else if(activeView==='mine'){ finalList = filtered.filter(r=>clean(r.email)===lowerMe); } 10794else if(activeView==='voltooid'){ 10795const _vTodayStr=new Date().toISOString().slice(0, 10); 10796const _vUserActTags=activiteitenTags 10797 .filter(a=>clean(a.email)===lowerMe) 10798 .map(a=>clean(a.tag)) 10799 .filter(Boolean); 10800const _vIsOnPalmares=r=>{ 10801 const rsvpTags=r.rsvpTag ? r.rsvpTag.split(',').map(t=>clean(t)).filter(Boolean) : []; 10802 const aTag=(areaTags&&areaTags[r.rondo]) ? clean(areaTags[r.rondo]) : null; 10803 const tagsToCheck=rsvpTags.length > 0 ? rsvpTags : (aTag ? [aTag] : []); 10804 return tagsToCheck.some(tag=>_vUserActTags.includes(tag)); 10805}; 10806finalList = filtered.filter(r=>{ 10807 if(_vIsOnPalmares(r)) return false; 10808 if(r.status===STATUS_BUCKETLIST){ 10809 const _vAreaTag=(areaTags&&areaTags[r.rondo]) ? clean(areaTags[r.rondo]) : null; 10810 return !!(_vAreaTag&&userTags.some(t=>clean(t)===_vAreaTag)); 10811 } 10812 const rideDateStr=(r.datum||'').slice(0, 10); 10813 if(!rideDateStr||rideDateStr > _vTodayStr) return false; 10814 const myP2=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe&&(p.status===STATUS_GO||p.status===STATUS_MAYBE)); 10815 const _vAreaTag2=(areaTags&&areaTags[r.rondo]) ? clean(areaTags[r.rondo]) : null; 10816 const _vRsvpTags2=r.rsvpTag ? r.rsvpTag.split(',').map(t=>
10816clean(t)).filter(Boolean) : []; 10817 const hasTagAccess2=(_vAreaTag2&&userTags.some(t=>clean(t)===_vAreaTag2)) || 10818 (_vRsvpTags2.length > 0&&_vRsvpTags2.some(tag=>userTags.some(ut=>clean(ut)===tag))); 10819 return clean(r.email)===lowerMe||!!myP2||hasTagAccess2; 10820}); 10821} 10822if(finalList.length===0){ 10823emptyEl.classList.remove('hidden'); 10824emptyEl.innerHTML = isArchive ? (L['gr-planner-no-archived-rides']||"Geen gearchiveerde ritten.") : (L['gr-planner-no-rides-found']||"Geen ritten gevonden."); 10825return; 10826} 10827const PAGE_SIZE=10; 10828window._grFullList = finalList; 10829window._grShown = 0; 10830const renderBatch=(from, count)=>{ 10831const batch=finalList.slice(from, from + count); 10832batch.forEach(ride=>{ 10833let myParticipation=null; 10834if(userEmail) myParticipation = allParticipants.find(p=>p.ritId===ride.id&&clean(p.email)===lowerMe); 10835const isOwner=userEmail ? clean(ride.email)===lowerMe : false; 10836listEl.appendChild(createCard(ride, isOwner, myParticipation, isArchive)); 10837}); 10838setTimeout(()=>{ batch.forEach(r=>{ updateAvatarsForCard(r.id); updateParticipantsListForCard(r.id); }); }, 0); 10839window._grShown+=batch.length; 10840let moreBtn=gEI('btnLoadMore'); 10841if(window._grShown < finalList.length){ 10842if(!moreBtn){ 10843moreBtn = document.createElement('div'); 10844moreBtn.id = 'btnLoadMore'; 10845moreBtn.className = 'load-more-bar'; 10846moreBtn.innerHTML = `<a href="#">${L['gr-planner-load-more-rides']||'Toon meer rittenâ¦'} (${finalList.length - window._grShown})</a>`; 10847moreBtn.addEventListener('click', e=>{ e.preventDefault(); renderBatch(window._grShown, PAGE_SIZE); }); 10848listEl.after(moreBtn); 10849}else{ 10850moreBtn.innerHTML = `<a href="#">${L['gr-planner-load-more-rides']||'Toon meer rittenâ¦'} (${finalList.length - window._grShown})</a>`; 10851} 10852} else if(moreBtn){ moreBtn.remove(); } 10853}; 10854let existingBtn=gEI('btnLoadMore'); if(existingBtn) existingBtn.remove(); 10855renderBatch(0, PAGE_SIZE); 10856const clearBtn=gEI('btnClearSearch'); 10857if(clearBtn) clearBtn.classList.toggle('hidden', !filterA); 10858let countBar=gEI('searchResultBar'); 10859if(!countBar){ 10860countBar = document.createElement('div'); 10861countBar.id = 'searchResultBar'; 10862countBar.className = 'search-result-bar'; 10863listEl.after(countBar); 10864} 10865if(filterA){ 10866countBar.innerHTML = `<span>${finalList.length} resultaten gevonden voor <strong>${filterA}</strong>. <a href="#" class="search-result-clear" onclick="event.preventDefault();window.clearSearch()">Wissen en toon alle ritten</a></span>`; 10867countBar.style.display = 'block'; 10868}else{ 10869countBar.style.display = 'none'; 10870} 10871} 10872/* ââ Mag je de Rondogids van deze rit zien, en waar staat hij? âââââââââââââ 10873 Dezelfde afweging die createCard maakt voor de menu-optie "Bekijk Rondogids", 10874 maar los bruikbaar. De tab Rondogidsen heeft hem nodig om te bepalen wát er in 10875 de lijst komt, en de kaart om de knop de goede kant op te sturen. Twee keer 10876 dezelfde regel uitschrijven is precies hoe je lijst en knop uit elkaar laat 10877 lopen, dus hij staat hier één keer. 10878 10879 De regel zelf: bij een event telt alleen je eventtag â de gids van een event 10880 hoort achter het ticket te blijven, ook voor een admin. Bij een gewone Rondo 10881 volstaat je gebiedstag, Rondoneur, of de adminvlag. */ 10882window._grGidsVoorRit=function(ride){ 10883 if(!ride) return { mag:false, url:'' }; 10884 const details=(typeof getRouteDetails==='function') ? getRouteDetails(ride) : {}; 10885 const isTicketRide=!!(ride.tickets===true||String(ride.tickets).toUpperCase()==='TRUE'); 10886 const isLink=v=>typeof v==='string'&&v.length > 1&&v.toLowerCase()!=='true'&&v.toLowerCase()!=='false'; 10887 const ruweGids = 10888 isLink(details.guide) ? details.guide : 10889 isLink(details.guideLink) ? details.guideLink : 10890 isLink(details.rondogids) ? details.rondogids : 10891 isLink(details.Rondogids) ? details.Rondogids : 10892 isLink(ride.guideLink) ? ride.guideLink : ''; 10893 const ruweShop = isLink(details.shop) ? details.shop : 10894 (isLink(details.shopLink) ? details.shopLink : 10895 (isLink(ride.shopLink) ? ride.shopLink : '')); 10896 const shopUrl=ruweShop ? (isTicketRide ? ruweShop+'-event' : ruweShop) : ''; 10897 const rsvpTags=ride.rsvpTag ? ride.rsvpTag.split(',').map(t=>
10897clean(t)).filter(Boolean) : []; 10898 const areaTag=(typeof getAreaTagForRide==='function') ? getAreaTagForRide(ride.rondo) : null; 10899 const heeftArea=!!(areaTag&&userTags.some(t=>clean(t)===areaTag)); 10900 const heeftRsvp=rsvpTags.length > 0&&rsvpTags.some(tag=>userTags.some(ut=>clean(ut)===tag)); 10901 const isBeheerder=typeof ADMIN_EMAILS!=='undefined'&&ADMIN_EMAILS.includes(clean(userEmail)); 10902 const heeftRondoneur=userTags.some(t=>clean(t)==='rondoneur'); 10903 const mag=isTicketRide ? heeftRsvp : (isBeheerder||heeftRondoneur||heeftArea); 10904 const gidsUrl=ruweGids ? (isTicketRide ? ruweGids+'-event' : ruweGids) : ''; 10905 /* Het taalpad erop, zodat de gids niet terugvalt naar het Nederlands. */ 10906 return { mag: mag, url: window._grTaalUrl(gidsUrl || (mag&&shopUrl ? shopUrl : '')) }; 10907}; 10908function renderArchiefsSection(){ 10909const _aListEl=document.getElementById('listRides'); 10910const _aEmptyEl=document.getElementById('emptyRides'); 10911if(!_aListEl||!_aEmptyEl) return; 10912_aListEl.innerHTML='';_aListEl.style.display=''; 10913_aEmptyEl.classList.add('hidden');_aEmptyEl.style.display=''; 10914const lowerMe=clean(userEmail); 10915const _now=new Date();_now.setHours(0,0,0,0); 10916const archList=allRides.filter(r=>{ 10917const _aOwn=clean(r.email)===lowerMe; 10918if(r.status===STATUS_CANCELLED&&!_aOwn&&!window._grIsAdmin) return false; 10919if(r.status!==STATUS_CANCELLED&&(!r.datum||new Date(r.datum)>=_now)) return false; 10920if(window._grIsAdmin) return true; 10921const _aP=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe&&(p.status===STATUS_GO||p.status===STATUS_MAYBE)); 10922return _aOwn||!!_aP; 10923}); 10924archList.sort((a,b)=>new Date(b.datum||0)-new Date(a.datum||0)); 10925const _aDbQ=(gEI('dbSearchFilter')||{value:''}).value.trim().toLowerCase(); 10926const _aFiltered=_aDbQ?archList.filter(r=>{const d=getRouteDetails(r);return[d.naam,r.rondo,r.eventNaam].some(v=>(v||'').toLowerCase().includes(_aDbQ));}):archList; 10927if(!_aFiltered.length){_aEmptyEl.classList.remove('hidden');_aEmptyEl.innerHTML=`<p style="text-align:center;font-style:italic;padding:0;">${L['gr-planner-no-archived-rides']||'Geen gearchiveerde ritten.'}</p>`;return;} 10928_aFiltered.forEach(ride=>{ 10929const _aOwner=userEmail?clean(ride.email)===lowerMe:false; 10930const _aMyP=userEmail?allParticipants.find(p=>p.ritId===ride.id&&clean(p.email)===lowerMe):null; 10931_aListEl.appendChild(createCard(ride,_aOwner,_aMyP,true)); 10932}); 10933setTimeout(()=>{_aFiltered.forEach(r=>{updateAvatarsForCard(r.id);updateParticipantsListForCard(r.id);});},0); 10934} 10935function renderGeplandSection(){ 10936const _gListEl = document.getElementById('listRides'); 10937const _gEmptyEl=document.getElementById('emptyRides'); 10938if(!_gListEl||!_gEmptyEl) return; 10939_gListEl.innerHTML = ''; 10940_gListEl.style.display = ''; 10941_gEmptyEl.classList.add('hidden'); 10942_gEmptyEl.style.display = ''; 10943const lowerMe=clean(userEmail); 10944const _gUserActTags=activiteitenTags 10945 .filter(a=>clean(a.email)===lowerMe) 10946 .map(a=>clean(a.tag)) 10947 .filter(Boolean); 10948const _gIsOnPalmares=r=>{ 10949 const rsvpTags=r.rsvpTag ? r.rsvpTag.split(',').map(t=>clean(t)).filter(Boolean) : []; 10950 const aTag=getAreaTagForRide(r.rondo); 10951 const check=rsvpTags.length > 0 ? rsvpTags : (aTag ? [aTag] : []); 10952 return check.some(tag=>_gUserActTags.includes(tag)); 10953}; 10954const _gNow=new Date();_gNow.setHours(0,0,0,0); 10955const geplandList=allRides.filter(r=>{ 10956 if(r.status===STATUS_CANCELLED) return false; 10957 if(r.datum&&new Date(r.datum)<_gNow) return false; 10958 if(r.status===STATUS_VOLTOOID) return false; 10959 if(_gIsOnPalmares(r)) return false; 10960 const _gMyVoltooid=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe&&p.status===STATUS_VOLTOOID); 10961 if(_gMyVoltooid) return false; 10962 if(clean(r.email)===lowerMe) return true; 10963 const _rTags=r.rsvpTag ? r.rsvpTag.split(',').map(t=>clean(t)).filter(Boolean) : []; 10964 const hasRsvpTag=_rTags.length > 0&&_rTags.some(tag=>userTags.some(ut=>clean(ut)===tag)); 10965 if(hasRsvpTag) return true; 10966 const myP=allParticipants.find(p=>p.ritId===r.id&&clean(p.email)===lowerMe && 10967 (p.status===STATUS_GO||p.status===STATUS_MAYBE||p.status===STATUS_BUCKETLIST)); 10968 return !!myP; 10969}); 10970const _gIsTicket=r=>/^true$/i.test(r.tickets); 10971const _gIsEvent=r=>!!(r.isPublic||r.rsvpTag); 10972geplandList.sort((a, b)=>{ 10973 const aHasDate=!!(a.datum&&String(a.datum).trim()); 10974 const bHasDate=!!(b.datum&&String(b.datum).trim()); 10975 if(aHasDate&&bHasDate)return new Date(a.datum)-new Date(b.datum); 10976 if(aHasDate&&!bHasDate)return -1; 10977 if(!aHasDate&&bHasDate)return 1; 10978 const aT=_gIsTicket(a),bT=_gIsTicket(b); 10979 if(aT!==bT) return aT ? -1 : 1; 10980 const aE=_gIsEvent(a),bE=_gIsEvent(b); 10981 if(aE!==bE) return aE ? -1 : 1; 10982 return (a.rondo||'').localeCompare(b.rondo||''); 10983}); 10984const _dbSearch=(gEI('dbSearchFilter')||{}).value||''; 10985const _dbQ=_dbSearch.trim().toLowerCase(); 10986const filteredGepland=_dbQ ? geplandList.filter(r=>{ 10987 const d=getRouteDetails(r); 10988 return (d.naam||'').toLowerCase().includes(_dbQ) || 10989 (r.rondo||'').toLowerCase().includes(_dbQ) || 10990 (r.eventNaam||'').toLowerCase().includes(_dbQ) || 10991 r.id.toLowerCase().startsWith(_dbQ); 10992}) : geplandList; 10993if(filteredGepland.length===0){ 10994 _gEmptyEl.classList.remove('hidden'); 10995 _gEmptyEl.innerHTML = `<p style="text-align:center;font-style:italic;padding:0;">${L['gr-planner-no-rides-found']||'Geen ritten gevonden.'}</p>`; 10996 return; 10997} 10998const _GEL_INITIAL=5, _GEL_PAGE = 20; 10999let _gShown=0; 11000const _gLmBtn=document.createElement('div');
11001_gLmBtn.className='gr-pal-loadmore'; 11002_gListEl.appendChild(_gLmBtn); 11003function _gShowBatch(from, count){ 11004 const toShow=filteredGepland.slice(from, from + count); 11005 toShow.forEach(ride=>{ 11006 const isOwner=userEmail ? clean(ride.email)===lowerMe : false; 11007 const myP=userEmail ? allParticipants.find(p=>p.ritId===ride.id&&clean(p.email)===lowerMe) : null; 11008 _gListEl.insertBefore(createCard(ride, isOwner, myP, false), _gLmBtn); 11009 }); 11010 setTimeout(()=>{ toShow.forEach(r=>{ updateAvatarsForCard(r.id); updateParticipantsListForCard(r.id); }); }, 0); 11011 _gShown+=toShow.length; 11012 if(_gShown>=filteredGepland.length){ _gLmBtn.style.display = 'none'; } 11013 else { _gLmBtn.style.display = ''; _gLmBtn.innerHTML = `<a href="#">${L['gr-db-more-items']||'Toon meer items...'}</a>`; _gLmBtn.querySelector('a').addEventListener('click', function(e){ e.preventDefault(); _gShowBatch(_gShown, _GEL_PAGE); }); } 11014} 11015_gShowBatch(0, _GEL_INITIAL); 11016} 11017/* ââ Tab Rondogidsen ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 11018 Dezelfde kaarten als bij Geplande ritten, met één verschil: rsvp en het 11019 hamburgermenu maken plaats voor de knop "Toon gids" (dat gebeurt in 11020 createCard, die kijkt naar GR_DASHBOARD_TAB). 11021 11022 Eén kaart per Rondo, niet per rit. Een gids hoort bij de Rondo, dus vijf 11023 geplande ritten in de Veluwe zouden vijf keer dezelfde knop opleveren. Van elke 11024 Rondo kiezen we de rit die er het meest toe doet: eerst de eerstvolgende met 11025 een datum, anders een zonder datum, anders de laatst gereden. */ 11026function renderRondogidsenSection(){ 11027const _rgListEl=gEI('listRides'); 11028const _rgEmptyEl=gEI('emptyRides'); 11029if(!_rgListEl||!_rgEmptyEl) return; 11030_rgListEl.innerHTML=''; 11031_rgListEl.style.display=''; 11032_rgEmptyEl.classList.add('hidden'); 11033_rgEmptyEl.style.display=''; 11034const _rgNu=new Date(); _rgNu.setHours(0,0,0,0); 11035const perRondo={}; 11036allRides.forEach(function(r){ 11037 if(r.status===STATUS_CANCELLED) return; 11038 const gids=window._grGidsVoorRit(r); 11039 if(!gids.mag||!gids.url) return; 11040 const sleutel=(r.rondo||'').trim().toLowerCase()||r.id; 11041 const huidige=perRondo[sleutel]; 11042 if(!huidige){ perRondo[sleutel]=r; return; } 11043 perRondo[sleutel]=_rgBesteRit(huidige, r, _rgNu); 11044});
11045function _rgBesteRit(a, b, nu){ 11046 const rang=function(r){ 11047 if(!r.datum) return 1; // zonder datum: middenmoot 11048 return new Date(r.datum) >= nu ? 0 : 2; // komt eraan / al geweest 11049 }; 11050 const ra=rang(a), rb=rang(b); 11051 if(ra!==rb) return ra < rb ? a : b; 11052 if(ra===0) return new Date(a.datum) <= new Date(b.datum) ? a : b; // de eerstvolgende 11053 if(ra===2) return new Date(a.datum) >= new Date(b.datum) ? a : b; // de meest recente 11054 return a; 11055} 11056let gidsLijst=Object.keys(perRondo).map(function(k){ return perRondo[k]; }); 11057const _rgZoek=((gEI('dbSearchFilter')||{}).value||'').trim().toLowerCase(); 11058if(_rgZoek){ 11059 gidsLijst=gidsLijst.filter(function(r){ 11060 const d=getRouteDetails(r); 11061 return (d.naam||'').toLowerCase().includes(_rgZoek) || 11062 (r.rondo||'').toLowerCase().includes(_rgZoek); 11063 }); 11064} 11065gidsLijst.sort(function(a,b){ 11066 const na=(getRouteDetails(a).naam||a.rondo||''), nb=(getRouteDetails(b).naam||b.rondo||''); 11067 return na.localeCompare(nb); 11068}); 11069if(!gidsLijst.length){ 11070 _rgEmptyEl.classList.remove('hidden'); 11071 _rgEmptyEl.innerHTML='<p style="text-align:center;font-style:italic;padding:0;">'+ 11072 (L['gr-db-no-guides']||'Je hebt nog geen Rondogidsen. Zodra je een Rondo of event in huis hebt, staat de gids hier.')+'</p>'; 11073 return; 11074} 11075const lowerMeRg=clean(userEmail); 11076gidsLijst.forEach(function(ride){ 11077 const isOwner=userEmail ? clean(ride.email)===lowerMeRg : false; 11078 const myP=userEmail ? allParticipants.find(p=>p.ritId===ride.id&&clean(p.email)===lowerMeRg) : null; 11079 _rgListEl.appendChild(createCard(ride, isOwner, myP, false)); 11080}); 11081/* Geen updateAvatarsForCard of updateParticipantsListForCard hier: op een 11082 gidskaart staat het rijtje deelnemers niet in de markup, dus die twee zouden 11083 naar elementen zoeken die er niet zijn. */ 11084} 11085function renderMineSection(){ 11086const _mListEl=gEI('listRides'); 11087const _mEmptyEl=gEI('emptyRides'); 11088if(!_mListEl||!_mEmptyEl) return; 11089_mListEl.innerHTML=''; 11090_mListEl.style.display=''; 11091_mEmptyEl.classList.add('hidden'); 11092_mEmptyEl.style.display=''; 11093const lowerMe=clean(userEmail); 11094const _mD=new Date().setHours(0,0,0,0); 11095const mineList=allRides.filter(r=>{ 11096 if(r.status===STATUS_CANCELLED) return false; 11097 if(r.status===STATUS_VOLTOOID) return false; 11098 if(r.datum&&new Date(r.datum)<_mD) return false; 11099 if(clean(r.email)===lowerMe) return true; 11100 if(!r.rsvpTag||!/^true$/i.test(r.tickets)) return false; 11101 return r.rsvpTag.split(',').some(t=>userTags.some(u=>clean(u)===clean(t))); 11102}); 11103mineList.sort((a, b)=>{ 11104 const aHasDate=!!(a.datum&&String(a.datum).trim()); 11105 const bHasDate=!!(b.datum&&String(b.datum).trim()); 11106 if(aHasDate&&bHasDate)return new Date(a.datum)-new Date(b.datum); 11107 if(aHasDate&&!bHasDate)return -1; 11108 if(!aHasDate&&bHasDate)return 1; 11109 return (a.rondo||'').localeCompare(b.rondo||''); 11110}); 11111const _dbSearchM=(gEI('dbSearchFilter')||{}).value||''; 11112const _dbQM=_dbSearchM.trim().toLowerCase(); 11113const filteredMine=_dbQM ? mineList.filter(r=>{ 11114 const d=getRouteDetails(r); 11115 return (d.naam||'').toLowerCase().includes(_dbQM) || 11116 (r.rondo||'').toLowerCase().includes(_dbQM) || 11117 (r.eventNaam||'').toLowerCase().includes(_dbQM) || 11118 r.id.toLowerCase().startsWith(_dbQM); 11119}) : mineList; 11120if(filteredMine.length===0){ 11121 _mEmptyEl.classList.remove('hidden'); 11122 _mEmptyEl.innerHTML = `<p style="text-align:center;font-style:italic;padding:0;">${L['gr-planner-no-rides-found']||'Geen ritten gevonden.'}</p>`; 11123 return; 11124} 11125filteredMine.forEach(ride=>{ 11126 const myP=null; 11127 _mListEl.appendChild(createCard(ride, true, myP, false)); 11128}); 11129setTimeout(()=>{ filteredMine.forEach(r=>{ updateAvatarsForCard(r.id); updateParticipantsListForCard(r.id); }); }, 0); 11130} 11131function renderVoltooidPalmaresSection(){ 11132const _vListEl = document.getElementById('listRides'); 11133const _vEmptyEl=document.getElementById('emptyRides'); 11134if(_vListEl) { _vListEl.innerHTML = ''; _vListEl.style.display = 'none'; } 11135if(_vEmptyEl){ _vEmptyEl.classList.add('hidden'); _vEmptyEl.style.display = 'none'; } 11136const _vPalSec=document.getElementById('palmaresTabSection'); 11137if(_vPalSec) _vPalSec.style.display = ''; 11138} 11139window.renderVoltooidSection=function(){ 11140if(!window._grSetDbTab) return; 11141window._grSetDbTab('voltooid-palmares'); 11142}; 11143function getMultiRouteStatsHTML(ride){ 11144 const raw=(ride.type||'Route'); 11145 const types=raw.split(',').map(t=>
11145t.trim()).filter(Boolean); 11146 if(types.length<=1){ 11147 const d=getRouteDetails(ride); 11148 return buildRouteStatsHTML(types[0]||'Route', d.richting, (d.km||d.afstand), d.hm); 11149 } 11150 return types.map(t=>{ 11151 const d=getRouteDetails(Object.assign({}, ride, {type: t})); 11152 return buildRouteStatsHTML(t, d.richting, (d.km||d.afstand), d.hm); 11153 }).join(''); 11154} 11155window._openAddToBucketlistModal=function(){ 11156if(!userEmail){ 11157 const lm=document.getElementById('loginModal'); 11158 if(lm){ lm.style.display = 'block'; document.body.classList.add('modal-open'); } 11159 return; 11160} 11161const modal=document.getElementById('addToBucketlistModal'); 11162const body = document.getElementById('atblBody'); 11163const btn = document.getElementById('btnAtblConfirm'); 11164if(!modal||!body||!btn) return; 11165const lowerMe=clean(userEmail); 11166const myRsvpIds=new Set( 11167 allParticipants 11168 .filter(p=>clean(p.email)===lowerMe&&(p.status===STATUS_GO||p.status===STATUS_BUCKETLIST||p.status===STATUS_MAYBE)) 11169 .map(p=>p.ritId) 11170); 11171const events=allRides.filter(r => 11172 r.status!==STATUS_CANCELLED && 11173 r.status!==STATUS_VOLTOOID && 11174 (r.tickets===true||String(r.tickets).toUpperCase()==='TRUE') 11175); 11176const areas=allRides.filter(r=>r.status===STATUS_BUCKETLIST); 11177let html=''; 11178if(events.length){ 11179 html+=`<h6 class="atbl-group-title">${L['gr-db-add-group-events']||'Events'}</h6>`; 11180 events.forEach(r=>{ 11181 const alreadyOn=myRsvpIds.has(r.id)||clean(r.email)===lowerMe; 11182 const uid='atbl-' + r.id; 11183 const d=getRouteDetails(r); 11184 const productName=d.naam||r.rondo||r.id; 11185 const eventName = r.eventNaam&&r.eventNaam.trim() ? r.eventNaam.trim() : ''; 11186 const datumStr = r.datum ? new Date(r.datum).toLocaleDateString('nl-NL', {day:'numeric', month:'short', year:'numeric'}) : ''; 11187 const statsHtml = getMultiRouteStatsHTML(r); 11188 const alreadyTxt=L['gr-db-add-already-added']||'al toegevoegd'; 11189 html+=`<label class="atbl-item${alreadyOn ? ' already-added' : ''}" for="${uid}"> 11190 <input type="checkbox" class="atbl-check" id="${uid}" data-ride-id="${r.id}"${alreadyOn ? ' disabled' : ''}> 11191 <span> 11192 <strong>${productName}</strong> 11193 ${eventName ? `<small class="atbl-event-name">${eventName}${datumStr ? ' - ' + datumStr : ''}${alreadyOn ? ' â ' + alreadyTxt : ''}</small>` : ''} 11194 <small class="atbl-meta">${statsHtml}</small> 11195 </span> 11196 </label>`; 11197 }); 11198} 11199if(areas.length){ 11200 html+=`<h6 class="atbl-group-title">${L['gr-db-add-group-areas']||"Rondo's"}</h6>`; 11201 areas.forEach(r=>{ 11202 const alreadyOn=myRsvpIds.has(r.id)||clean(r.email)===lowerMe; 11203 const uid='atbl-' + r.id; 11204 const d=getRouteDetails(r); 11205 const areaName = d.naam||r.rondo||r.id; 11206 const statsHtml=getMultiRouteStatsHTML(r); 11207 const onListTxt=L['gr-db-add-area-on-list']||'Al op je bucketlist'; 11208 html+=`<label class="atbl-item${alreadyOn ? ' already-added' : ''}" for="${uid}"> 11209 <input type="checkbox" class="atbl-check" id="${uid}" data-ride-id="${r.id}"${alreadyOn ? ' disabled' : ''}> 11210 <span> 11211 <strong>${areaName}</strong> 11212 <small class="atbl-meta">${statsHtml}${alreadyOn ? ' â ' + onListTxt : ''}</small> 11213 </span> 11214 </label>`; 11215 }); 11216} 11217if(!html) html = `<p style="color:#888;padding:20px 0;">${L['gr-db-add-no-rides']||'Geen Rondo\'s beschikbaar.'}</p>`; 11218body.innerHTML = html; 11219btn.disabled = true; 11220body.addEventListener('change', function(){ 11221 btn.disabled = body.querySelectorAll('.atbl-check:checked').length===0; 11222}); 11223modal.style.display = 'block'; 11224document.body.classList.add('modal-open'); 11225}; 11226window._grPlanRondoFromDashboard=function(){ 11227 if(window.requireLogin&&window.requireLogin()) return; 11228 const isAdmin=typeof ADMIN_EMAILS!=='undefined'&&ADMIN_EMAILS.includes(clean(userEmail)); 11229 const isRondoneur=typeof userTags!=='undefined'&&userTags.some(t=>String(t).trim().toLowerCase()==='rondoneur'); 11230 const hasFullAccess=isAdmin||isRondoneur; 11231 window._grPlanRondoMode = true; 11232 window._grPlanRondoArea = null; 11233 window._grOpenRitModal(null); 11234 setTimeout(function(){ 11235 const _rm=document.getElementById('rideModal');const _t=(_rm&&_rm.querySelector('[id="modalTitle"]')||document.getElementById('modalTitle'));if(_t)_t.innerText=(typeof L!=='undefined'&&L['gr-planner-modal-new-ride'])||'Nieuwe rit plannen'; 11236 const rondoSel=document.getElementById('inpRondo'); 11237 const accessMsg=document.getElementById('dbPlanRondoAccessMsg'); 11238 if(!hasFullAccess&&rondoSel&&typeof areaTags!=='undefined'&&typeof userTags!=='undefined'){
11239 Array.from(rondoSel.options).forEach(function(opt){ 11240 if(!opt.value) return; 11241 const aTag=areaTags[opt.value] ? String(areaTags[opt.value]).trim().toLowerCase() : null; 11242 const hasTag=aTag&&userTags.some(t=>String(t).trim().toLowerCase()===aTag); 11243 opt.disabled = !hasTag; 11244 opt.style.display = hasTag ? '' : 'none'; 11245 }); 11246 if(accessMsg) accessMsg.style.display = ''; 11247 }else{ 11248 rondoSel&&Array.from(rondoSel.options).forEach(function(opt){ opt.disabled = false; opt.style.display = ''; }); 11249 if(accessMsg) accessMsg.style.display = 'none'; 11250 } 11251 }, 80); 11252}; 11253window._grInitDashboardTabs=function(){ 11254/* De zoekbalk werd hier aangezet en verderop nog eens, en _grSetDbTab bepaalde 11255 óók al iets over dezelfde eigenschap. Drie schrijvers voor één display; nu 11256 alleen _grSetDbTab, die een paar regels verderop toch meteen langskomt. */ 11257const ctrlBar=document.querySelector('.circles-controls-bar'); 11258if(ctrlBar) ctrlBar.style.display='block'; 11259const confirmBtn=document.getElementById('btnAtblConfirm'); 11260if(confirmBtn) confirmBtn.addEventListener('click', async function(){ 11261 const checks=document.querySelectorAll('#atblBody .atbl-check:checked'); 11262 if(!checks.length) return; 11263 confirmBtn.disabled = true; 11264 confirmBtn.textContent = L['gr-db-add-saving']||'Toevoegenâ¦'; 11265 const promises=Array.from(checks).map(cb=>{ 11266 const rId=cb.dataset.rideId; 11267 return fetch(RIDE_SCRIPT_URL, { 11268 method: 'POST', mode: 'no-cors', 11269 headers: { 'Content-Type': 'application/json' }, 11270 body: JSON.stringify({ action: 'rsvp', ritId: rId, email: userEmail, status: STATUS_GO }) 11271 }).catch(function(){}); 11272 }); 11273 await Promise.all(promises); 11274 try { localStorage.removeItem(GR_CACHE_KEY); } catch(e){} 11275 document.getElementById('addToBucketlistModal').style.display = 'none'; 11276 document.body.classList.remove('modal-open'); 11277 setTimeout(function(){ window.grHerlaadPagina('#bucketlist'); }, 400); 11278}); 11279const sel=document.getElementById('dbViewSelect'); 11280if(!sel) return; 11281const isAdmin=typeof ADMIN_EMAILS!=='undefined'&&ADMIN_EMAILS.includes(clean(userEmail)); 11282window._grIsAdmin=isAdmin;if(isAdmin)document.body.classList.add('gr-is-admin'); 11283if(isAdmin){ 11284 const optAll=document.createElement('option'); 11285 optAll.value = 'all'; 11286 optAll.textContent = (typeof L!=='undefined'&&L['gr-db-tab-all'])||'Alle ritten'; 11287 sel.insertBefore(optAll,sel.querySelector('[value=archief]')); 11288} 11289/* De optie Rondogidsen hoort in de keuzelijst thuis omdat die lijst de toestand 11290 is. In dashboard.liquid staat hij er al in; in oudere markup nog niet, dus 11291 bouwen we hem hier bij als hij ontbreekt. */ 11292if(!sel.querySelector('[value="rondoguides"]')){ 11293 const optGids=document.createElement('option'); 11294 optGids.value='rondoguides'; 11295 optGids.textContent=(typeof L!=='undefined'&&L['gr-db-tab-rondoguides'])||'Rondogidsen'; 11296 sel.insertBefore(optGids, sel.firstChild); 11297} 11298 11299/* ââ Tabs âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 11300 De tabs zetten alleen de keuzelijst en laten die het werk doen; zo loopt elke 11301 tabwissel langs precies dezelfde weg als voorheen. */ 11302/* Op [data-tab] en niet op de klas alleen: het â®-knopje staat sinds kort in 11303 dezelfde balk en draagt db-tab voor de vorm, maar is geen weergave. Zonder 11304 deze eis kreeg het een tabklik mee en zou _grMarkeerTab het proberen aan te 11305 zetten. */ 11306const _tabKnoppen=Array.prototype.slice.call(document.querySelectorAll('#dbTabs .db-tab[data-tab]')); 11307if(isAdmin){ 11308 const _tabAlle=document.querySelector('#dbTabs .db-tab[data-tab="all"]'); 11309 if(_tabAlle) _tabAlle.removeAttribute('hidden'); 11310} 11311_tabKnoppen.forEach(function(knop){ 11312 knop.addEventListener('click', function(){ 11313 window._grSetDbTab(knop.getAttribute('data-tab')); 11314 }); 11315}); 11316window._grMarkeerTab=function(tab){ 11317 _tabKnoppen.forEach(function(knop){ 11318 const actief=knop.getAttribute('data-tab')===tab; 11319 knop.classList.toggle('is-actief', actief); 11320 knop.setAttribute('aria-selected', actief ? 'true' : 'false'); 11321 }); 11322}; 11323 11324/* ââ Het â®-menu âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 11325 Gevuld uit de ext:-opties van de keuzelijst. Eén plek waar die links staan, 11326 en ze blijven werken als er ooit een bijkomt. */ 11327(function _vulMenu(){ 11328 const menuBtn=document.getElementById('dbMenuBtn'); 11329 const popover=document.getElementById('dbMenuPopover'); 11330 if(!menuBtn||!popover) return; 11331 const items=Array.prototype.slice.call(sel.querySelectorAll('option[value^="ext:"]')) 11332 /* Rondogidsen is een tab geworden; de winkellink met dezelfde naam hoort 11333 niet ook nog in dit menu. Hij blijft wel in de keuzelijst staan, zodat een 11334 bestaande verwijzing naar ext:rondoguides blijft werken. */ 11335 .filter(function(opt){ return opt.value!=='ext:rondoguides'; }); 11336 if(!items.length){ menuBtn.style.display='none'; return; } 11337 popover.innerHTML=items.map(function(opt){ 11338 /* Het taalpad erop. _grSetDbTab doet dat voor zijn eigen ext:-p
11338ad al, maar 11339 dit menu bouwt de links zelf op en sloeg het over â vandaar hier ook. */ 11340 const href=window._grTaalUrl(opt.dataset.href||'#'); 11341 /* Alleen uitloggen blijft in hetzelfde venster â daarna is het dashboard 11342 toch niet meer wat het was. Al het andere, bestellingen en abonnementen 11343 incluis, opent ernaast zodat je je plek in de lijst niet kwijtraakt. */ 11344 const zelfdeVenster=/logout/i.test(href); 11345 return '<a href="'+href+'"'+(zelfdeVenster?'':' target="_blank" rel="noopener"')+'>'+opt.textContent+'</a>'; 11346 }).join(''); 11347 menuBtn.addEventListener('click', function(e){ 11348 e.stopPropagation(); 11349 const open=popover.classList.toggle('open'); 11350 menuBtn.setAttribute('aria-expanded', open ? 'true' : 'false'); 11351 }); 11352 document.addEventListener('click', function(e){ 11353 if(popover.contains(e.target)||menuBtn.contains(e.target)) return; 11354 popover.classList.remove('open'); 11355 menuBtn.setAttribute('aria-expanded','false'); 11356 }); 11357})(); 11358 11359/* ââ Hash en tab ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 11360 Elke tab heeft een adres, zodat je een weergave kunt delen en na het 11361 herladen terugkomt waar je was. De hash is bewust korter en leesbaarder dan 11362 de interne namen: #gepland leest prettiger dan #mine, #palmares dan 11363 #voltooid-palmares. 11364 11365 Zonder hash opent Rondogidsen. Staat er wél een hash, dan wint die â ook op 11366 een gedeelde link uit een oud bericht. */ 11367const _tabBijHash={ 11368 'rondoguides': 'rondoguides', 11369 'gidsen': 'rondoguides', 11370 'bucketlist': 'bucketlist', 11371 'gepland': 'mine', 11372 'mine': 'mine', 11373 'palmares': 'voltooid-palmares', 11374 'voltooid-palmares': 'voltooid-palmares', 11375 'all': 'all', 11376 'alle': 'all', 11377 'archief': 'archief' 11378}; 11379const _hashBijTab={ 11380 'rondoguides': '#rondoguides', 11381 'bucketlist': '#bucketlist', 11382 'mine': '#gepland', 11383 'voltooid-palmares': '#palmares', 11384 'all': '#all', 11385 'archief': '#archief' 11386}; 11387window._grTabUitHash=function(){ 11388 const sleutel=(location.hash||'').replace('#','').toLowerCase(); 11389 const tab=_tabBijHash[sleutel]; 11390 if(!tab) return null; 11391 /* Alle ritten is er alleen voor een admin. Komt iemand anders met #all 11392 binnen, dan valt hij terug op de standaardtab in plaats van op een lege 11393 of half werkende weergave. */ 11394 if(tab==='all'&&!isAdmin) return null; 11395 return tab; 11396}; 11397window._grSetDbTab=function(tab){ 11398 window.GR_DASHBOARD_TAB = tab; 11399 if(sel.value!==tab) sel.value = tab; 11400 if(window._grMarkeerTab) window._grMarkeerTab(tab); 11401 /* Adres bijwerken zonder geschiedenisstap: anders zou de terugknop je door 11402 alle tabs slepen die je onderweg hebt aangeraakt in plaats van terug naar 11403 de vorige pagina. */ 11404 const _nieuweHash=_hashBijTab[tab]; 11405 if(_nieuweHash&&location.hash!==_nieuweHash){ 11406 try { history.replaceState(null,'',location.pathname+location.search+_nieuweHash); } 11407 catch(e) { /* adresbalk is bijzaak */ } 11408 } 11409 const toolbar=document.getElementById('dbToolbar'); 11410 if(toolbar) toolbar.style.display = (tab==='all') ? '' : 'none'; 11411 /* Expliciet 'block' en niet '': de markup zet er zelf display:none op, en een 11412 lege waarde wist alleen die inline-regel. Dan hangt het ervan af wat de 11413 stylesheet zegt, en juist daar is de verbergregel net weggehaald. Met een 11414 echte waarde is er niets om over te twijfelen. */ 11415 const searchRow=document.getElementById('dbBucketlistSearchRow'); 11416 if(searchRow) searchRow.style.display = (tab==='bucketlist'||tab==='mine'||tab==='rondoguides') ? 'block' : 'none'; 11417 const lrEl=document.getElementById('listRides'); 11418 if(lrEl) lrEl.style.display = (tab==='voltooid-palmares') ? 'none' : ''; 11419 const _ps=document.getElementById('palmaresTabSection'); 11420 if(_ps) _ps.style.display=(tab==='voltooid-palmares')?'':'none'; 11421 /* Pas tonen als de ritten binnen zijn. "+ Zet op bucketlist" opent een lijst 11422 die uit allRides komt; klik je terwijl die nog leeg is, dan krijg je een 11423 lege modal. */ 11424 var _dataKlaar = !!window.GR_RITTEN_GELADEN; 11425 ['dbAddBtn1','dbAddBtn2'].forEach(function(id,i){ 11426 var el=document.getElementById(id); 11427 if(el) el.style.display=(_dataKlaar && ['bucketlist','mine'][i]===tab)?'block':'none'; 11428 }); 11429 var b3=document.getElementById('dbAddBtn3');if(b3)b3.style.display='none'; 11430 if(tab==='all'){ 11431 window.GR_DASHBOARD_MODE = false;
11432 activeView = 'all'; 11433 }else{ 11434 window.GR_DASHBOARD_MODE = true; 11435 } 11436 if(typeof render==='function') render(); 11437}; 11438/* Openen op de tab uit de hash; staat er niets, dan Rondogidsen. */ 11439window._grSetDbTab(window._grTabUitHash()||'rondoguides'); 11440sel.addEventListener('change', function(){ 11441 window._grSetDbTab(this.value); 11442}); 11443/* Verandert de hash later alsnog â iemand plakt een link in de adresbalk, of 11444 drukt op terug â dan gaat de tab mee. */ 11445window.addEventListener('hashchange', function(){ 11446 const _t=window._grTabUitHash(); 11447 if(_t&&_t!==window.GR_DASHBOARD_TAB) window._grSetDbTab(_t); 11448}); 11449const dbSF=document.getElementById('dbSearchFilter'); 11450const dbSClear=document.getElementById('dbBtnClearSearch'); 11451if(dbSF){ 11452 dbSF.addEventListener('input', function(){ 11453 if(dbSClear) dbSClear.classList.toggle('hidden', !this.value); 11454 if(typeof render==='function') render(); 11455 }); 11456} 11457window.dbClearSearch=function(){ 11458 if(dbSF){ dbSF.value = ''; dbSF.dispatchEvent(new Event('input')); } 11459}; 11460(function(){ 11461 const params=new URLSearchParams(window.location.search); 11462 const actId=params.get('activity'); 11463 if(!actId||!dbSF) return; 11464 dbSF.value = actId.substring(0, 8); 11465 if(dbSClear) dbSClear.classList.remove('hidden'); 11466 if(typeof render==='function') render(); 11467 setTimeout(function(){ 11468 const card=document.querySelector('[data-ride-id^="' + actId.substring(0, 8) + '"]') || 11469 document.querySelector('[data-ride-id="' + actId + '"]'); 11470 if(card){ 11471 card.scrollIntoView({ behavior: 'smooth', block: 'center' }); 11472 const det=card.querySelector('.ride-details'); 11473 if(det&&!det.classList.contains('open')){ 11474 det.classList.add('open'); 11475 det.style.maxHeight = '5000px'; 11476 } 11477 } 11478 }, 400); 11479})(); 11480}; 11481</script>
11481 11482 11483 11484
11485<script> 11486function createCard(ride, isOwner, myParticipation, isArchiveMode){ 11487const div=document.createElement('div'); 11488const isCancelled=(ride.status===STATUS_CANCELLED); 11489div.className = 'ride-card' + (isCancelled ? ' cancelled-card' : '') + (ride.status===STATUS_BUCKETLIST ? ' is-bucketlist' : ''); 11490div.setAttribute('data-ride-id', ride.id); 11491const isGlobalAdmin=ADMIN_EMAILS.includes(clean(userEmail)); 11492const details=getRouteDetails(ride); 11493const userHasAccess=hasAccess(ride, details); 11494const userHasGuideAccess=userHasAccess||isOwner; 11495const shopUrl=((details.shop||details.shopLink||'')).replace(/'/g, "\\'"); 11496let headerClickAction=`window.toggleAccordion(this)`; 11497if(!userHasGuideAccess&&userEmail) headerClickAction = `window.showUpgradeModal('${shopUrl}')`; 11498/* Op de tab Rondogidsen valt er niets uit te klappen: daar hoort één knop en 11499 verder niets. De kop krijgt dus ook geen klikactie meer, anders klap je een 11500 leeg paneel open. _isGidsKaart wordt verderop gezet, dus dit gebeurt daar. */ 11501/* Leeg beginnen. Hier stond een pil met een liggend streepje; die verscheen 11502 overal waar geen van de takken hieronder aansloeg. Wat er in dat geval wél 11503 komt, staat onderaan het datumblok bij elkaar. */ 11504let dateHtml=''; 11505const typeClass=(ride.type||"").toLowerCase().replace(/[^a-z]/g, ''); 11506let cssClass="event"; 11507if(typeClass.includes('road')&&typeClass.includes('gravel')) cssClass = "eventroadgravel"; 11508else if(typeClass.includes('road')) cssClass = "eventroad"; 11509else if(typeClass.includes('gravel')) cssClass = "eventgravel"; 11510const cancelledClass=isCancelled ? 'cancelled' : ''; 11511function formatDatePill(dateVal, timeVal){ 11512const d=new Date(dateVal); 11513const day=d.getDate(); 11514const mon=MONTHS[d.getMonth()]; 11515const yr=d.getFullYear().toString().slice(2); 11516let s=_isEn ? `${mon} ${day}, '${yr}` : `${String(day).padStart(2,'0')} ${mon} '${yr}`; 11517if(timeVal){ 11518const t=new Date(timeVal); 11519const h=t.getHours().toString().padStart(2,'0'); 11520const m=t.getMinutes().toString().padStart(2,'0'); 11521s+=` ${h}:${m}`; 11522} 11523return s; 11524} 11525const sameDay=(d1, d2)=>{ const a=new Date(d1), b = new Date(d2); return a.getFullYear()===b.getFullYear()&&a.getMonth()===b.getMonth()&&a.getDate()===b.getDate(); }; 11526if(ride.datum){ 11527dateHtml = `<h4 class="date-pill ${cssClass} ${cancelledClass}">${formatDatePill(ride.datum)}</h4>`; 11528if(ride.datumfinish&&!sameDay(ride.datum, ride.datumfinish)) dateHtml+=`<h4 class="date-pill ${cssClass} ${cancelledClass} date-pill-finish">${formatDatePill(ride.datumfinish)}</h4>`; 11529} else if(/^ntb:/i.test(ride.dagen||'')){ 11530/* Vrije toelichting uit de ntb-stand: letterlijk tonen, niet als daglijst. */ 11531const _ntbLabel=String(ride.dagen).slice(4).trim(); 11532dateHtml = `<h4 class="date-pill ${cssClass} ${cancelledClass}">${_ntbLabel || (L['gr-planner-day-ntb']||'Datum / tijd: ntb.')}</h4>`; 11533} else if(ride.dagen){ 11534const dagList=(ride.dagen||'').toLowerCase().trim(); 11535/* 'geen' betekent: geen daglijst. Hier stond eerst een ???-pil. Nu valt dit 11536 door naar de fietspil hieronder. */ 11537if(dagList!=='geen'){ 11538const label=(()=>{ const parts=dagList.split(',').map(s=>s.trim().substring(0,2)); return parts.length > 3 ? parts.slice(0,3).join(', ')+'...' : parts.join(', '); })(); 11539dateHtml = `<h4 class="date-pill ${cssClass} ${cancelledClass}">${label}</h4>`; 11540} 11541} 11542/* Geen datum, geen daglijst, geen ntb-toelichting: dan een pil met alleen een 11543 fietsje. Zelfde kleurklasse als de gewone datumpillen, dus gravel krijgt de 11544 gravelkleur en road de roadkleur. */ 11545if(!dateHtml) dateHtml = `<h4 class="date-pill ${cssClass} ${cancelledClass}" aria-label="${L['gr-planner-no-date']||'Geen datum'}">${SVG_BIKE}</h4>`; 11546if(isCancelled) dateHtml+=`<div class="cancelled-label">${L['gr-planner-cancelled']||"Geannuleerd"}</div>`; 11547let eventPill=""; 11548if(ride.eventNaam&&ride.eventNaam.trim()!==""&&ride.status!==STATUS_BUCKETLIST) eventPill = `<h3 class="event-name-pill">${ride.eventNaam}</h3>`; 11549const routeName=`<h3 class="ride-route-name">${details.naam||ride.rondo||(L['gr-planner-ride-default']||"Rit")}</h3>`; 11550const statsHtml=`<span class="ride-route-stats">` + getMultiRouteStatsHTML(ride) + `</span>`;
11551const isTicketRide=!!(ride.tickets===true||String(ride.tickets).toUpperCase()==='TRUE'); 11552const isBucketlistRide=(ride.status===STATUS_BUCKETLIST); 11553const _earlyIsLink=v=>typeof v==='string'&&v.length > 1&&v.toLowerCase()!=='true'&&v.toLowerCase()!=='false'; 11554const _earlyGuideUrlRaw = 11555 _earlyIsLink(details.guide) ? details.guide : 11556 _earlyIsLink(details.guideLink) ? details.guideLink : 11557 _earlyIsLink(details.rondogids) ? details.rondogids : 11558 _earlyIsLink(details.Rondogids) ? details.Rondogids : 11559 _earlyIsLink(ride.guideLink) ? ride.guideLink : ''; 11560/* Hier het taalpad erop, niet bij elke knop apart: alles hieronder â Bekijk 11561 Rondo, Bestel, Meedoen, de gids, #booking â leidt zich van deze drie af. */ 11562const _earlyRawShop = window._grTaalUrl(_earlyIsLink(details.shop) ? details.shop : 11563 (_earlyIsLink(details.shopLink) ? details.shopLink : 11564 (_earlyIsLink(ride.shopLink) ? ride.shopLink : ''))); 11565const _earlyShopUrl = _earlyRawShop ? (isTicketRide ? _earlyRawShop + '-event' : _earlyRawShop) : ''; 11566const _earlyRsvpTags = ride.rsvpTag ? ride.rsvpTag.split(',').map(t=>clean(t)).filter(Boolean) : []; 11567const _earlyUserHasTicket = isTicketRide&&_earlyRsvpTags.length > 0&&_earlyRsvpTags.some(tag=>userTags.some(ut=>clean(ut)===tag)); 11568const _earlyAreaTag = getAreaTagForRide(ride.rondo); 11569const _earlyUserHasAreaTag=!!(_earlyAreaTag&&userTags.some(t=>clean(t)===_earlyAreaTag)); 11570const _earlyUserHasRsvpTag=(_earlyRsvpTags.length > 0&&_earlyRsvpTags.some(tag=>userTags.some(ut=>clean(ut)===tag)))||_earlyUserHasAreaTag; 11571const _earlyBookingUrl = _earlyShopUrl ? _earlyShopUrl + '#booking' : ''; 11572const _earlyHasRondoneur = userTags.some(t=>clean(t)==='rondoneur'); 11573const _earlyHasRsvpTagOnly=_earlyRsvpTags.length > 0&&_earlyRsvpTags.some(tag=>userTags.some(ut=>clean(ut)===tag)); 11574/* Rondogids â bij een event telt alleen je eventtag. Niet je Rondoneur- of 11575 gebiedstag, en ook de adminvlag niet: de gids van een event hoort achter het 11576 ticket te blijven. Zelfde regel als in het kaartpaneel. Bij een gewone Rondo 11577 verandert er niets. */ 11578const _earlyShowBook = isTicketRide 11579 ? _earlyHasRsvpTagOnly 11580 : (isGlobalAdmin||_earlyHasRondoneur||_earlyUserHasAreaTag); 11581const _earlyGuideUrlFinal=_earlyGuideUrlRaw ? window._grTaalUrl(isTicketRide ? _earlyGuideUrlRaw + '-event' : _earlyGuideUrlRaw) : ''; 11582const _earlyGuideUrl=_earlyGuideUrlFinal||(_earlyShowBook&&_earlyShopUrl ? _earlyShopUrl : ''); 11583// (oude losse actie-iconen + share-popover vervangen door het hamburger actie-menu hieronder) 11584const _showPlanBtn=isBucketlistRide&&(_earlyHasRondoneur||_earlyUserHasAreaTag||isGlobalAdmin); 11585// ââ Acties als popover-menu achter een hamburger-icoon ââââââââââââââââââââââ 11586const _mi=[]; // menu-items 11587if(!isArchiveMode&&!isCancelled&&(isOwner||isGlobalAdmin)){ 11588_mi.push(`<div class="action-option" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}');window.editRide('${ride.id}')">${SVG_EDIT} ${L['gr-planner-edit']||'Bewerk'}</div>`); 11589} 11590if(!isArchiveMode&&!isCancelled&&_showPlanBtn){ 11591_mi.push(`<div class="action-option" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}');window.openPlanRondoModal('${(ride.rondo||'').replace(/'/g,"\\'")}','${(_earlyAreaTag||'').replace(/'/g,"\\'")}')">${SVG_CALENDAR} ${L['gr-planner-plan-rondo-tooltip']||'Plan deze Rondo'}</div>`); 11592} 11593if(!isArchiveMode&&!isCancelled){ 11594if(_earlyShowBook&&_earlyGuideUrl){ 11595_mi.push(`<a class="action-option" href="${_earlyGuideUrl}" target="_blank" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}')">${SVG_BOOK} ${L['gr-planner-view-guide']||'Bekijk Rondogids'}</a>`); 11596} else if(!_earlyShowBook&&_earlyBookingUrl){ 11597/* Bij een event eerst de keuze voorleggen: tickets voor het event, of het 11598 Rondopakket om zelf een datum te prikken. Het pakket gebruikt de link 11599 zonder -event, want dat is de gewone Rondo-pagina. */ 11600if(isTicketRide&&_earlyRawShop){ 11601_mi.push(`<div class="action-option" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}');window.showTicketModal('${_earlyBookingUrl}','${_earlyShopUrl}','${_earlyRawShop}#booking')">${SVG_SHOP} ${L['gr-planner-order-rondo']||'Bestel deze Rondo'}</div>`); 11602} else { 11603_mi.push(`<a class="action-option" href="${_earlyBookingUrl}" target="_blank" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}')">${SVG_SHOP} ${L['gr-planner-order-rondo']||'Bestel deze Rondo'}</a>`); 11604} 11605} 11606} 11607/* Bekijk Rondo â altijd, met of zonder eventtag. Wijst naar de gewone 11608 Rondopagina, dus _earlyRawShop zonder het achtervoegsel -event: dat laatste is 11609 de eventpagina en die zit al achter Meedoen en Bestel. */ 11610if(_earlyRawShop){ 11611_mi.push(`<a class="action-option" href="${_earlyRawShop}" target="_blank" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}')">${SVG_BOOK} ${L['gr-atlas-view-rondo']||'Bekijk Rondo'}</a>`); 11612} 11613/* Meedoen aan dit event â alleen bij een event waarvoor je nog geen ticket hebt. 11614 Zonder #booking: de eventpagina zelf, niet meteen het formulier. 11615 Zelfde controle als de RSVP-popover (_earlyUserHasTicket vergelijkt de 11616 rsvpTag van de rit met je klanttags), maar hier als menu-optie, zodat het 11617 ook werkt waar de RSVP-knop niet bereikbaar is â bijvoorbeeld in de 11618 Plan-deze-Rondo-modal. */ 11619if(!isArchiveMode&&!isCancelled&&isTicketRide&&!_earlyUserHasTicket){ 11620_mi.push(`<div class="action-option" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}');window.showTicketModal('${_earlyShopUrl}','${_earlyShopUrl}')">${SVG_SHOP} ${L['gr-planner-book-tickets']||'Meedoen aan dit event'}</div>`); 11621} 11622/* Rondo voltooid â op élke kaart, in alle vier de tabbladen: bucketlist, 11623 gepland, alle ritten en archief. Juist in het archief is het zinvol: daar 11624 staan de ritten die geweest zijn en die je alsnog in je Palmares wilt zetten. 11625 Daarom géén !isArchiveMode-voorwaarde, anders dan bij de opties hierboven. 11626 Wel uitgelogd verbergen, en op het openbare dashboard van iemand anders: 11627 daar valt er voor jou niets te registreren. */ 11628if(userEmail&&!window.GR_PUBLIC_VIEW){ 11629_mi.push(`<div class="action-option" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}');window.grOpenRondoVoltooid('${(ride.rondo||'').replace(/'/g,"\\'")}')">${SVG_VOLCHECK} ${L['gr-atlas-rondo-completed']||'Rondo voltooid'}</div>`); 11630} 11631/* Delen via⦠â alleen op het tabblad "Jouw geplande ritten". Een bucketlistitem 11632 of een rit in het archief heeft geen zinvolle deel-link, en op het openbare 11633 dashboard van iemand anders hoort de knop er ook niet te staan. 11634 GR_DASHBOARD_TAB wordt gezet door _grSetDbTab; buiten het dashboard â in de 11635 kaart, in de Plan-deze-Rondo-modal â bestaat hij niet en blijft de knop dus 11636 weg. 11637 11638 "Kopieer link" stond hier ook en is helemaal vervallen: het deelvenster van 11639 de browser biedt kopiëren zelf al aan, en valt dat weg dan zet 11640 window.shareActivity de link alsnog op het klembord. Twee menu-opties voor 11641 dezelfde handeling dus. window.copyActivityLink blijft bestaan voor het geval 11642 je hem elders nog aanroept. */ 11643const _opGeplandTab = (window.GR_DASHBOARD_TAB === 'mine') && !window.GR_PUBLIC_VIEW; 11644if(_opGeplandTab){ 11645_mi.push(`<div class="action-option" id="share-btn-${ride.id}" onclick="event.stopPropagation();window.closeActionMenu('${ride.id}');window.shareActivity('${ride.id}')">${SVG_SHARE} ${L['gr-planner-share-via']||'Vrienden uitnodigen...'}</div>`); 11646} 11647_mi.push(`<div class="action-option" onclick="event.stopPropagation();window.actionToggleDetails('${ride.id}',this)">${SVG_INFO} ${L['gr-planner-view-details']||'Details bekijken'}</div>`); 11648const actionsHtml = `
11649<div class="actions"> 11650<div class="action-menu-wrapper"> 11651<button type="button" class="btn-icon-svg btn-action-menu" data-gr-action-menu="${ride.id}" title="${L['gr-planner-actions']||'Acties'}">${SVG_MENU}</button> 11652<div id="action-popover-${ride.id}" class="action-popover" style="display:none;" onclick="event.stopPropagation()">${_mi.join('')}</div> 11653</div> 11654</div>`; 11655let rsvpActionsHtml=''; 11656const curStatus=isOwner 11657? (myParticipation ? myParticipation.status : STATUS_GO) 11658: (myParticipation ? myParticipation.status : null); 11659if(!isGlobalAdmin&&(isArchiveMode||isCancelled)){ 11660if(isCancelled) rsvpActionsHtml = ''; 11661else rsvpActionsHtml = `<div style="opacity:0.6; font-size:0.9em; font-weight:bold; color:#888;">${L['gr-planner-completed']||'Afgerond'}</div>`; 11662} else if(!isGlobalAdmin&&!userHasAccess&&!isBucketlistRide&&!isTicketRide){ 11663let rsvpClickAction=userEmail ? `window.showUpgradeModal('${shopUrl}')` : `window.toggleAccordion(this.closest('.ride-card').querySelector('.ride-header'))`; 11664rsvpActionsHtml = `<div class="rsvp-actions"><button class="btn-rsvp-trigger" onclick="event.stopPropagation(); ${rsvpClickAction}">${L['gr-planner-you']||'Jij?'}</button></div>`; 11665}else{ 11666let _userHasTicket=_earlyUserHasTicket, _ticketShopUrl = _earlyShopUrl, _ticketBookUrl = _earlyBookingUrl; 11667const _now=new Date(); _now.setHours(0,0,0,0); 11668const _rideDay=ride.datum ? new Date(new Date(ride.datum).toDateString()) : null; 11669const showVoltooid=isBucketlistRide||!_rideDay||_rideDay<=_now; 11670const _isPast=_rideDay!==null&&_rideDay < _now; 11671const _isDashboard=!!window.GR_DASHBOARD_MODE; 11672let btnClass='', btnLabel = L['gr-planner-you']||'Jij?'; 11673if(curStatus===STATUS_VOLTOOID){ btnClass = 'active-blue'; btnLabel = 'ââ'; } 11674/* Ticket in huis: vinkje op actiekleur. */ 11675else if(isTicketRide&&_userHasTicket){ btnClass = 'active-orange'; btnLabel = 'â'; } 11676else if(isBucketlistRide&&!isOwner&&_earlyUserHasAreaTag){ btnClass = 'active-green'; btnLabel = SVG_HEART_FILLED; } 11677/* Bewaard op de bucketlist â bij een gewone Rondo én bij een event zonder 11678 ticket â is een hartje, geen vinkje: je doet nog niet mee, je hebt hem 11679 alleen opgeslagen. Een vinkje blijft voor echte deelname aan een rit. */ 11680else if(curStatus===STATUS_GO){ btnClass = 'active-green'; btnLabel = (isBucketlistRide||isTicketRide) ? SVG_HEART_FILLED : 'â'; } 11681else if(curStatus===STATUS_MAYBE){ btnClass = 'active-blue'; btnLabel = '?'; } 11682let _pi=[]; 11683if(isOwner) _pi.push(`<div class="rsvp-option info-only" style="font-style:italic">${L['gr-planner-you-are-organizer']||'Jij bent organisator'}</div>`); 11684if(curStatus===STATUS_VOLTOOID){ 11685_pi.push(`<div class="rsvp-option active-item blue"><span class="ri">ââ </span>${L['gr-planner-rsvp-voltooid']||'Rondo Voltooid'}</div><div class="rsvp-divider"></div>`); 11686} else if(isTicketRide&&_userHasTicket){ 11687_pi.push(`<div class="rsvp-option active-item orange"><span class="ri">â</span>${_grLbl('gr-planner-you-have-tickets','Je hebt Tickets')}</div><div class="rsvp-divider"></div>`); 11688} else if(!isBucketlistRide&&!isTicketRide&&curStatus===STATUS_GO){ 11689const _partLabel=(_isDashboard&&_isPast) ? (L['gr-planner-event-voltooid']||'Event voltooid') : (L['gr-planner-participating']||'Ik doe mee'); 11690_pi.push(`<div class="rsvp-option active-item green"><span class="ri">â</span>${_partLabel}</div><div class="rsvp-divider"></div>`); 11691} else if((isBucketlistRide||isTicketRide)&&curStatus===STATUS_GO&&isOwner){ 11692_pi.push(`<div class="rsvp-option active-item green"><span class="ri">â</span>${L['gr-planner-participating']||'Ik doe mee'}</div><div class="rsvp-divider"></div>`); 11693} else if(isBucketlistRide&&!isOwner&&_earlyUserHasAreaTag){ 11694_pi.push(`<div class="rsvp-option active-item green"><span class="ri">â</span>${L['gr-bucketlist-areatag-status']||'Rondo besteld'}</div><div class="rsvp-divider"></div>`); 11695} else if((isBucketlistRide||isTicketRide)&&curStatus===STATUS_GO&&!isOwner){ 11696_pi.push(`<div class="rsvp-option active-item green"><span class="ri">${SVG_HEART_FILLED}</span>${L['gr-bucketlist-on-list']||'Bewaard op bucketlist'}</div><div class="rsvp-divider"></div>`); 11697}
11697 else if(!isBucketlistRide&&!isTicketRide&&curStatus===STATUS_MAYBE){ 11698_pi.push(`<div class="rsvp-option active-item blue"><span class="ri">?</span>${L['gr-planner-rsvp-maybe-active']||'Ik doe misschien mee'}</div><div class="rsvp-divider"></div>`); 11699} 11700if(showVoltooid&&curStatus!==STATUS_VOLTOOID){ 11701_pi.push(`<div class="rsvp-option text-blue" onclick="event.stopPropagation(); window.rsvp('${ride.id}', '${STATUS_VOLTOOID}', this)"><span class="ri">ââ </span>${L['gr-planner-rsvp-voltooid']||'Rondo Voltooid'}</div>`); 11702} 11703if(!isBucketlistRide){ 11704if(isTicketRide){ 11705if(isGlobalAdmin&&isOwner){ 11706if(curStatus!==STATUS_GO&&curStatus!==STATUS_VOLTOOID){ 11707_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.rsvp('${ride.id}', '${STATUS_GO}', this)"><span class="ri">â</span>${L['gr-planner-ticket-join']||'Meedoen'}</div>`); 11708} 11709if(curStatus!==STATUS_MAYBE&&curStatus!==STATUS_VOLTOOID){ 11710_pi.push(`<div class="rsvp-option text-blue" onclick="event.stopPropagation(); window.rsvp('${ride.id}', '${STATUS_MAYBE}', this)"><span class="ri">?</span>${L['gr-planner-rsvp-maybe']||'Misschien'}</div>`); 11711} 11712if(curStatus===STATUS_GO||curStatus===STATUS_MAYBE){ 11713_pi.push(`<div class="rsvp-option danger" onclick="event.stopPropagation(); window.rsvp('${ride.id}', 'DELETE', this)"><span class="ri">â</span>${L['gr-planner-rsvp-no']||'Ik doe niet mee'}</div>`); 11714} 11715} else if(!_userHasTicket&&curStatus!==STATUS_VOLTOOID){ 11716_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.showTicketModal('${_ticketBookUrl}', '${_ticketShopUrl}')"><span class="ri">â</span>${L['gr-planner-ticket-join']||'Meedoen'}</div>`); 11717} 11718}else{ 11719if(curStatus!==STATUS_GO&&curStatus!==STATUS_VOLTOOID){ 11720_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.rsvp('${ride.id}', '${STATUS_GO}', this)"><span class="ri">â</span>${L['gr-planner-ticket-join']||'Meedoen'}</div>`); 11721} 11722} 11723} 11724if((isBucketlistRide||isTicketRide)&&curStatus!==STATUS_GO&&!(isGlobalAdmin&&isOwner&&isTicketRide)&&!(_earlyUserHasAreaTag&&isBucketlistRide)){ 11725_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.rsvp('${ride.id}', '${STATUS_GO}', this)"><span class="ri">â¡</span>${L['gr-bucketlist-btn-save']||'Bewaar op bucketlist'}</div>`); 11726} 11727if(!isBucketlistRide&&!isTicketRide&&curStatus!==STATUS_MAYBE&&curStatus!==STATUS_VOLTOOID&&!(_isDashboard&&_isPast)){ 11728_pi.push(`<div class="rsvp-option text-blue" onclick="event.stopPropagation(); window.rsvp('${ride.id}', '${STATUS_MAYBE}', this)"><span class="ri">?</span>${L['gr-planner-rsvp-maybe']||'Misschien'}</div>`); 11729} 11730/* Verwijderen mag altijd als de Rondo op je bucketlist staat â ook met een 11731 gebiedstag; die zei alleen iets over toegang, niet over je eigen lijst. */ 11732/* Ook bij een event: staat hij op je bucketlist, dan moet je hem er ook weer 11733 af kunnen halen. */ 11734if((isBucketlistRide||isTicketRide)&&curStatus===STATUS_GO&&!_earlyUserHasTicket){ 11735_pi.push(`<div class="rsvp-option danger" onclick="event.stopPropagation(); window.rsvp('${ride.id}', 'DELETE', this)"><span class="ri">â</span>${L['gr-bucketlist-btn-remove']||'Verwijder van bucketlist'}</div>`); 11736} 11737if(!isBucketlistRide&&!isTicketRide&&(curStatus===STATUS_GO||curStatus===STATUS_MAYBE)){ 11738const _noLabel=_isDashboard?L['gr-planner-verwijder']||'Verwijder':L['gr-planner-rsvp-no']||'Ik doe niet mee'; 11739_pi.push(`<div class="rsvp-option danger" onclick="event.stopPropagation();window.rsvp('${ride.id}','DELETE',this)"><span class="ri">â</span>${_noLabel}</div>`); 11740} 11741rsvpActionsHtml = ` 11742<div class="rsvp-actions"> 11743<button class="btn-rsvp-trigger ${btnClass}" onclick="event.stopPropagation(); window.toggleRSVP('${ride.id}', this)">${btnLabel}</button> 11744<div id="rsvp-popover-${ride.id}" class="rsvp-popover">${_pi.join('')}</div> 11745</div>`; 11746} 11747const hostAv=ride.hostAvatar 11748? `<img src="${ride.hostAvatar}" class="host-avatar-small">` 11749: `<div class="host-avatar-small" style="background:#ddd;display:inline-flex;align-items:center;justify-content:center;font-size:10px;font-weight:bold;color:#555;">${getInitials(ride.hostName)}</div>`; 11750const hostPill=`<div class="detail-pill">${hostAv}<span class="value">${ride.hostName||(L['gr-planner-guest']||'Gast')}</span></div>`;
11751let locLine=""; 11752if(ride.startlocatie){ 11753const mapUrl=`https://maps.google.com/?q=${encodeURIComponent(ride.startlocatie)}`; 11754const navLink=`<a href="${mapUrl}" target="_blank" class="inline-nav-link">${L['gr-planner-navigate-start']||'Navigeer naar Start'}</a>`; 11755locLine = `<div class="ride-detail-line"><strong>${L['gr-planner-start-location']||'Startlocatie'}:</strong> <a href="${mapUrl}" target="_blank" style="color:inherit;text-decoration:underline;">${ride.startlocatie}</a> ${navLink}</div>`; 11756} 11757let datePillStr=""; 11758if(ride.datum){ 11759datePillStr = formatDatePill(ride.datum, ride.tijd); 11760if(ride.datumfinish){ 11761if(sameDay(ride.datum, ride.datumfinish)){ 11762if(ride.tijdfinish){ const tf=new Date(ride.tijdfinish); datePillStr+=` - ${tf.getHours().toString().padStart(2,'0')}:${tf.getMinutes().toString().padStart(2,'0')}`; } 11763}else{ 11764datePillStr+=` - ${formatDatePill(ride.datumfinish, ride.tijdfinish)}`; 11765} 11766} 11767} 11768let durStr=""; 11769if(details.afstand&&ride.tempo){ 11770let s=DEFAULT_PACE; 11771if(String(ride.tempo).includes('<')) s=24; else if(String(ride.tempo).includes('>')) s=34; else if(String(ride.tempo).includes('-')) s=29; 11772const d=parseFloat(String(details.afstand).replace(',','.')); 11773if(d){ const h=Math.floor(d/s); const m=Math.round((d/s - h)*60); durStr = `± ${h}u ${m.toString().padStart(2,'0')}m`; } 11774} 11775/* Geen organisator-pill bij events en bucketlist-items. */ 11776const _geenHostPill=isBucketlistRide||isTicketRide||!!String(ride.eventNaam||'').trim(); 11777/* Stand "Ntb.": de toelichting staat in dagen achter het voorvoegsel ntb:. 11778 Dat voorvoegsel is opslag, geen tekst voor in de pil. */ 11779const _dagenRuw=String(ride.dagen||''); 11780const _dagenLabel=L['gr-planner-day-ntb']||'Datum / tijd: ntb.'; 11781const _dagenPil=/^ntb:/i.test(_dagenRuw) ? (_dagenRuw.slice(4).trim()||_dagenLabel) 11782 : (_dagenRuw.toLowerCase().trim()==='geen' ? _dagenLabel : _dagenRuw); 11783/* Alleen Mannen of Vrouwen krijgen een pil; "Iedereen" zegt niets extra. */ 11784const _toonVoorWie=/^(mannen|vrouwen)$/i.test(String(ride.voorWie||'').trim()); 11785const pillsHtml=[ 11786_geenHostPill ? '' : hostPill, 11787_toonVoorWie ? `<div class="detail-pill"><span class="value">${ride.voorWie}</span></div>` : '', 11788ride.dagen ? `<div class="detail-pill"><span class="value">${_dagenPil}</span></div>` : '', 11789datePillStr ? `<div class="detail-pill"><span class="value">${datePillStr}</span></div>` : '', 11790ride.tempo ? `<div class="detail-pill"><span class="value">${ride.tempo}</span></div>` : '', 11791durStr ? `<div class="detail-pill"><span class="value">${durStr}</span></div>` : '' 11792].filter(Boolean).join(''); 11793const extraRaw = (_isEn&&ride.extraEn) ? ride.extraEn : (ride.extra||""); 11794const extraHtml = extraRaw.replace(/\n/g, '<br>'); 11795const partsClick=userHasGuideAccess ? `onclick="event.stopPropagation(); window.toggleParticipants('${ride.id}', this)"` : ""; 11796const _rideRsvpTags=ride.rsvpTag ? ride.rsvpTag.split(',').map(t=>clean(t)).filter(Boolean) : []; 11797const _hasRsvpTagForRide=_rideRsvpTags.some(tag=>userTags.some(ut=>clean(ut)===tag)); 11798const _rideAreaTag=getAreaTagForRide(ride.rondo); 11799const _hasAreaTagForRide=!!(_rideAreaTag&&userTags.some(t=>clean(t)===_rideAreaTag)); 11800const _hasRondoneurTag=userTags.some(t=>clean(t)==='rondoneur'); 11801const userHasGuideLink=isGlobalAdmin || 11802 (isTicketRide ? _hasRsvpTagForRide : (_hasRondoneurTag||_hasAreaTagForRide)); 11803let detailsPanel=''; 11804if(userHasGuideAccess){ 11805// De gids-/bestel-link werd hier opgebouwd voor .guide-link-wrap; die actie 11806// zit nu in het hamburger-menu (zie _earlyGuideUrl / _earlyBookingUrl). 11807/* Opmerkingen horen bij een rit waar je naartoe kunt: een dag, een tijd, iets 11808 om over af te spreken. Bij een bucketlist-Rondo, een rit met alleen 11809 voorkeursdagen of eentje op 'ntb' is er nog niets om onder te reageren â daar 11810 werd het veld een prikbord zonder aanleiding. Vandaar de eis van een echte 11811 datum. */ 11812const _heeftDatum = !!(ride.datum && String(ride.datum).trim()); 11813let commentInputHtml=""; 11814if(userEmail&&!isCancelled&&_heeftDatum){ 11815const myAvatarImg=localDisplayAvatar ? `<img src="${localDisplayAvatar}" class="current-user-avatar-small">` : `<div class="current-user-placeholder-small">${getInitials(localDisplayName)}</div>`; 11816commentInputHtml = ` 11817<div class="comment-input-group"> 11818${myAvatarImg} 11819<textarea id="input-comment-${ride.id}" class="comment-textarea" rows="1" placeholder="${L['gr-planner-placeholder-comment']||'Plaats reactie...'}" onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();window.postComment('${ride.id}',this);}this.style.height='auto';this.style.height=this.scrollHeight+'px';"></textarea> 11820<button class="btn-send-comment" onclick="window.postComment('${ride.id}',this)"> 11821<span class="desktop-text">${L['gr-planner-send']||'Verstuur'}</span> 11822<span class="mobile-icon">â¤</span> 11823</button> 11824</div>`; 11825} 11826// Gids-, plan- en deel-links zaten hier in een .guide-link-wrap; die acties
11827// staan nu in het hamburger-menu in de kaartkop. 11828detailsPanel = ` 11829<div class="ride-details"> 11830<div class="detail-pills-container">${pillsHtml}</div> 11831${locLine} 11832${(details.mapImg||details.mapImage) ? `<div class="route-map-wrap"><img src="${details.mapImg||details.mapImage}" class="route-map-img" alt="kaart" loading="lazy"></div>` : ''} 11833${extraRaw ? `<h4>${L['gr-planner-label-info']||'Informatie'}</h4><div class="detail-extra">${extraHtml}</div>` : ''} 11834${(!isCancelled&&userEmail&&_heeftDatum) ? `<div class="comments-section"> 11835<h4>${L['gr-planner-comments']||'Opmerkingen'}</h4> 11836<div class="comment-list" id="comments-${ride.id}"></div> 11837${commentInputHtml} 11838</div>` : ''} 11839</div>`; 11840}else{ 11841const shopUrl=window._grTaalUrl((details.shop||details.shopLink) ? (isTicketRide ? (details.shop||details.shopLink) + '-event' : (details.shop||details.shopLink)) : "https://granrondo.cc/collections/all"); 11842detailsPanel = ` 11843<div class="ride-details"> 11844<div class="restricted-box"> 11845<p>${L['gr-planner-no-access-info']||'Geen toegang tot de info.'}</p> 11846<div class="restricted-actions"> 11847<a href="${shopUrl}" target="_blank" class="btn-primary">${L['gr-planner-order-rondo']||'Bestel Rondo'}</a> 11848<a href="${window._grTaalUrl('https://granrondo.cc/join')}" target="_blank" class="btn-secondary"> 11849${L['gr-planner-unlock-all']||'Unlock Alles'} 11850<span style="display:block;font-size:1em;font-weight:400;margin-top:2px;">${L['gr-planner-join-rondoneur']||'Join als Rondoneur'}</span> 11851</a> 11852</div> 11853</div> 11854</div>`; 11855} 11856/* Op de tab Rondogidsen gaat het maar om één ding: de gids openen. Alles wat in 11857 de kaartkop om aandacht vraagt â de rsvp-knop, het actiemenu en het rijtje 11858 deelnemers â maakt daar plaats voor die ene knop. Buiten die tab verandert er 11859 niets: _isGidsKaart is dan false en de kop wordt opgebouwd zoals altijd. 11860 11861 De uitklap met route, kaartje en opmerkingen blijft wél gewoon werken: dat is 11862 inhoud, geen menu. */ 11863const _isGidsKaart=(window.GR_DASHBOARD_TAB||'')==='rondoguides'; 11864let _gidsActieHtml=''; 11865if(_isGidsKaart&&typeof window._grGidsVoorRit==='function'){ 11866const _gids=window._grGidsVoorRit(ride); 11867if(_gids&&_gids.url){ 11868_gidsActieHtml=`<a class="gr-gids-actie" href="${_gids.url}" target="_blank" rel="noopener" onclick="event.stopPropagation()">${L['gr-db-show-guide']||'Open Gids'}</a>`; 11869} 11870} 11871if(_isGidsKaart) { 11872div.classList.add('is-gidskaart'); 11873detailsPanel = ''; 11874headerClickAction = ''; 11875}
11876const _deelnemersHtml=_isGidsKaart ? '' : ` 11877<div class="participants-preview" ${partsClick}> 11878<div class="participants-avatars" id="avatarsRow-${ride.id}"></div> 11879<div id="participants-popover-${ride.id}" class="participants-popover" onclick="event.stopPropagation()"> 11880<div class="participants-popover-header">${L['gr-planner-participants']||'Deelnemers'}</div> 11881<div class="participants-popover-list" id="participants-list-${ride.id}"></div> 11882</div> 11883</div>`; 11884div.innerHTML = ` 11885<div class="ride-header" onclick="${headerClickAction}"> 11886<div class="header-date">${dateHtml}</div> 11887<div class="header-info">${routeName}${eventPill}${statsHtml}</div> 11888<div class="mobile-parts-rsvp-container"> 11889${_deelnemersHtml} 11890${_gidsActieHtml || (rsvpActionsHtml + actionsHtml)} 11891</div> 11892</div> 11893${detailsPanel}`; 11894if(userHasAccess&&userEmail&&!isCancelled) setTimeout(()=>renderCommentsForCard(ride, isOwner), 0); 11895return div; 11896} 11897 11898/* Opent het formulier Nieuwe activiteit met dit gebied al gekozen. 11899 Drie wegen, in volgorde van betrouwbaarheid: 11900 1. grPalOpenActivityForm â de echte route. Doet de profielcheck, initialiseert 11901 het formulier en vult het gebied in. Staat in palmares-script, dat overal 11902 in de footer zit, dus dit is vrijwel altijd de tak die het doet. 11903 2. _grAtlasOpenActivity â alleen aanwezig waar de kaart staat (homepage). 11904 3. De modal met de hand openen. Zonder gebied-preselectie, maar beter dan 11905 een knop die niets doet. 11906 Bewust hier en niet in de kaart: die staat niet op het dashboard, en juist 11907 daar zit dit menu. */ 11908window.grOpenRondoVoltooid = function (gebied) { 11909 if (typeof window.grPalOpenActivityForm === 'function') { 11910 if (window.grPalOpenActivityForm(gebied)) return; 11911 } 11912 if (typeof window._grAtlasOpenActivity === 'function') { 11913 window._grAtlasOpenActivity(gebied); return; 11914 } 11915 var m = document.getElementById('ritModal'); 11916 if (!m) { console.warn('[GR] Rondo voltooid: ritModal ontbreekt op deze pagina.'); return; } 11917 window._pendingVoltooidRide = null; 11918 window._pendingVoltooidId = null; 11919 m.style.display = 'flex'; 11920 document.body.classList.add('modal-open'); 11921}; 11922</script>
11922 11923 11924 11925
11926<script> 11927window._grFormDirty = false; 11928window._grCloseRideModal = function() { 11929const _confirmMsg = (typeof L !== 'undefined' && L['gr-planner-confirm-close-unsaved']) || 'Niet opgeslagen. Sluiten?'; 11930if(window._grFormDirty && !confirm(_confirmMsg)) return; 11931const _m = document.getElementById('rideModal'); if(_m) _m.style.display = "none"; 11932document.body.classList.remove('modal-open'); 11933window._grFormDirty = false; 11934}; 11935window.toggleShare = function(id) { 11936gQSA('.share-popover').forEach(p => { if (p.id !== `share-popover-${id}`) p.classList.remove('show'); }); 11937const el = gEI(`share-popover-${id}`); 11938if(el) el.classList.toggle('show'); 11939}; 11940// Hamburger actie-menu op de ride-card 11941// Inline display i.p.v. alleen een klasse: kan niet door thema-CSS overruled worden. 11942window.toggleActionMenu = function(id, force) { 11943gQSA('.action-popover').forEach(p => { 11944 if (p.id !== `action-popover-${id}`) { p.style.display = 'none'; p.classList.remove('show'); } 11945}); 11946const el = gEI(`action-popover-${id}`); 11947if(!el) return; 11948const open = (typeof force === 'boolean') ? force : el.style.display !== 'block'; 11949el.style.display = open ? 'block' : 'none'; 11950el.classList.toggle('show', open); 11951}; 11952window.closeActionMenu = function(id) { window.toggleActionMenu(id, false); }; 11953window.closeAllActionMenus = function() { 11954gQSA('.action-popover').forEach(p => { p.style.display = 'none'; p.classList.remove('show'); }); 11955}; 11956// Gedelegeerd: openen via de hamburger, sluiten daarbuiten. 11957// CAPTURE-fase: .ride-header heeft een inline onclick die de accordeon opent. 11958// In de bubble-fase is die al gedraaid voor we bij document zijn, dus vangen 11959// we de klik hier af vóórdat hij de kaart bereikt. 11960document.addEventListener('click', function(e) { 11961const t = e.target; 11962if (!t || !t.closest) return; 11963const btn = t.closest('[data-gr-action-menu]'); 11964if (btn) { 11965 e.preventDefault(); e.stopPropagation(); 11966 window.toggleActionMenu(btn.getAttribute('data-gr-action-menu')); 11967 return; 11968} 11969if (t.closest('.action-menu-wrapper')) return; // klik binnen het menu zelf 11970window.closeAllActionMenus(); 11971}, true); 11972// Details openen vanuit het actie-menu (sluit menu, toggelt accordeon) 11973window.actionToggleDetails = function(id, el) { 11974window.closeActionMenu(id); 11975const card = el && el.closest ? el.closest('.ride-card') : null; 11976const header = card ? card.querySelector('.ride-header') : null; 11977if(header) window.toggleAccordion(header); 11978}; 11979window.copyActivityLink = function(id) { 11980const shortId = id.substring(0, 8); 11981const _ep=location.pathname.startsWith('/en')?'/en':''; 11982const url = window.GR_DASHBOARD_MODE 11983 ? (window.location.origin + _ep + '/pages/dashboard?activity=' + shortId) 11984 : (window.location.origin + window.location.pathname + '?activity=' + shortId); 11985/* De losse optie "Kopieer link" bestaat niet meer; op een browser zonder 11986 navigator.share valt shareActivity hierop terug. Dan hoort de bevestiging op 11987 "Delen viaâ¦" te verschijnen, anders lijkt die knop niets te doen. */ 11988const copyEl = gEI(`share-copy-${id}`) || gEI(`share-btn-${id}`); 11989const doFeedback = () => { 11990if (copyEl) { const orig = copyEl.innerHTML; copyEl.innerHTML = (L['gr-planner-copied']||'â Gekopieerd!'); copyEl.classList.add('copied'); setTimeout(() => { copyEl.innerHTML = orig; copyEl.classList.remove('copied'); }, 2000); } 11991}; 11992if (navigator.clipboard) { 11993navigator.clipboard.writeText(url).then(doFeedback).catch(() => { 11994const ta = document.createElement('textarea'); ta.value = url; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); doFeedback(); 11995}); 11996} else { 11997const ta = document.createElement('textarea'); ta.value = url; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); doFeedback(); 11998} 11999}; 12000window.shareActivity = function(id) { 12001const shortId = id.substring(0, 8); 12002const _ep=location.pathname.startsWith('/en')?'/en':''; 12003const url = window.GR_DASHBOARD_MODE 12004 ? (window.location.origin + _ep + '/pages/dashboard?activity=' + shortId) 12005 : (window.location.origin + window.location.pathname + '?activity=' + shortId); 12006const ride = allRides.find(r => r.id === id); 12007const title = ride ? (ride.eventNaam || (getRouteDetails(ride).naam || ride.rondo) || 'Gran Rondo') : 'Gran Rondo'; 12008if (navigator.share) { 12009navigator.share({ title: title, url: url }).catch(() => {}); 12010} else { 12011window.copyActivityLink(id); 12012} 12013}; 12014window.toggleAccordion = function(header) { 12015const details = header.nextElementSibling;
12016if(!details) return; 12017const isOpen = details.classList.contains('open'); 12018gQSA('.ride-details').forEach(d => { d.classList.remove('open'); d.style.maxHeight = null; }); 12019if(!isOpen) { details.classList.add('open'); details.style.maxHeight = "5000px"; } 12020}; 12021window.toggleRSVP = function(id, triggerEl) { 12022if(window.requireLogin()) return; 12023gQSA('.rsvp-popover').forEach(p => { 12024 if (p.id !== `rsvp-popover-${id}`) { 12025 p.classList.remove('show'); 12026 p.style.position = ''; p.style.top = ''; p.style.right = ''; 12027 p.style.left = ''; p.style.transform = ''; p.style.zIndex = ''; 12028 } 12029}); 12030const el = gEI(`rsvp-popover-${id}`); 12031if (!el) return; 12032const willShow = !el.classList.contains('show'); 12033el.classList.toggle('show'); 12034if (willShow && triggerEl) { 12035 // Gebruik fixed positionering vanuit modal of detailpanel 12036 const needsFixed = triggerEl.closest('#planRondoModal') || triggerEl.closest('.detail-rsvp-row'); 12037 if (needsFixed) { 12038 const rect = triggerEl.getBoundingClientRect(); 12039 el.style.position = 'fixed'; 12040 el.style.top = (rect.bottom + 5) + 'px'; 12041 el.style.right = (window.innerWidth - rect.right) + 'px'; 12042 el.style.left = 'auto'; 12043 el.style.transform = 'none'; 12044 el.style.zIndex = '3000'; 12045 } 12046} 12047if (!willShow) { 12048 el.style.position = ''; el.style.top = ''; el.style.right = ''; 12049 el.style.left = ''; el.style.transform = ''; el.style.zIndex = ''; 12050} 12051}; 12052// Identieke toggle voor RSVP-kopie in detailpanel (gebruikt rsvp-dp-popover-* ID) 12053window.toggleRSVPDP = function(id, triggerEl) { 12054if(window.requireLogin()) return; 12055gQSA('.rsvp-popover').forEach(p => { 12056 if (p.id !== `rsvp-dp-popover-${id}`) { 12057 p.classList.remove('show'); 12058 p.style.position = ''; p.style.top = ''; p.style.right = ''; 12059 p.style.left = ''; p.style.transform = ''; p.style.zIndex = ''; 12060 } 12061}); 12062const el = gEI(`rsvp-dp-popover-${id}`); 12063if (!el) return; 12064const willShow = !el.classList.contains('show'); 12065el.classList.toggle('show'); 12066if (willShow && triggerEl) { 12067 const rect = triggerEl.getBoundingClientRect(); 12068 el.style.position = 'fixed'; 12069 el.style.top = (rect.bottom + 5) + 'px'; 12070 el.style.right = (window.innerWidth - rect.right) + 'px'; 12071 el.style.left = 'auto'; 12072 el.style.transform = 'none'; 12073 el.style.zIndex = '3000'; 12074} 12075if (!willShow) { 12076 el.style.position = ''; el.style.top = ''; el.style.right = ''; 12077 el.style.left = ''; el.style.transform = ''; el.style.zIndex = ''; 12078} 12079}; 12080window.toggleParticipants = function(id, triggerEl) { 12081if(window.requireLogin()) return; 12082gQSA('.participants-popover').forEach(p => { if (p.id !== `participants-popover-${id}`) p.classList.remove('show'); }); 12083gQSA('.ride-card').forEach(c => c.classList.remove('popover-open')); 12084const card = triggerEl ? triggerEl.closest('.ride-card') : gQS(`.ride-card[data-ride-id="${id}"]`); 12085if(card) card.classList.add('popover-open'); 12086const el = gEI(`participants-popover-${id}`); if(el) el.classList.toggle('show'); 12087}; 12088window.editRide = function(id) { const ride = allRides.find(r => String(r.id) === String(id)); console.log('[GR editRide script2b] id:', id, '| ride:', ride ? 'JA id='+ride.id : 'NEE'); if(ride) window._grOpenRitModal(ride); }; 12089window.deleteRide = function(id) { window.grDeleteRidePopover(id); }; 12090window.archiveRide = function(id) { window.grDeleteRidePopover(id); }; 12091window.cancelRide = async function(id) { 12092 await sendPost({ action: 'cancel_ride', ritId: id, email: userEmail, statusCancelled: STATUS_CANCELLED }, 1500); 12093 window.grHerlaadPagina(); 12094}; 12095// ââ Undo-balk "Item verwijderd⦠Maak ongedaan" âââââââââââââââââââââââââââââ 12096(function() { 12097 const s = document.createElement('style'); 12098 s.textContent = 12099 '#gr-undo-bar{position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(100px);' + 12100 'background:#271D62;color:#fff;padding:13px 22px;border-radius:30px;' + 12101 'font-family:inherit;font-size:0.9em;font-weight:600;display:flex;align-items:center;' + 12102 'gap:16px;box-shadow:0 4px 20px rgba(0,0,0,.3);z-index:99999;' + 12103 'transition:transform .3s ease;white-space:nowrap;pointer-events:none;opacity:0;}' + 12104 '#gr-undo-bar.gr-undo-show{transform:translateX(-50%) translateY(0);pointer-events:auto;opacity:1;}' + 12105 '#gr-undo-btn{background:none;border:none;color:#ffcc00;font-weight:800;' + 12106 'cursor:pointer;font-size:inherit;padding:0;text-decoration:underline;letter-spacing:.02em;}'; 12107 document.head.appendChild(s); 12108 const bar = document.createElement('div'); 12109 bar.id = 'gr-undo-bar'; 12110 bar.innerHTML = '<span id="gr-undo-msg"></span><button id="gr-undo-btn" type="button">Maak ongedaan</button>'; 12111 document.body.appendChild(bar); 12112})();
12113let _undoTimer = null; 12114function showUndoBar(msg, onUndo) { 12115 const bar = gEI('gr-undo-bar'), msgEl = gEI('gr-undo-msg'), btn = gEI('gr-undo-btn'); 12116 if (!bar) return; 12117 if (msgEl) msgEl.textContent = msg; 12118 if (_undoTimer) clearTimeout(_undoTimer); 12119 btn.onclick = function() { hideUndoBar(); if (onUndo) onUndo(); }; 12120 bar.classList.add('gr-undo-show'); 12121 _undoTimer = setTimeout(hideUndoBar, 5000); 12122} 12123function hideUndoBar() { 12124 const bar = gEI('gr-undo-bar'); 12125 if (bar) bar.classList.remove('gr-undo-show'); 12126 if (_undoTimer) { clearTimeout(_undoTimer); _undoTimer = null; } 12127} 12128// ââ Rit verwijderen via popover/modal (undo-toast, geen bevestigingsmodal) ââ 12129window.grDeleteRidePopover = async function(id) { 12130 // Sluit rideModal als die open is 12131 var _rm = document.getElementById('rideModal'); 12132 if(_rm && _rm.style.display!=='none'){ _rm.style.display='none'; document.body.classList.remove('modal-open'); } 12133 var ride = allRides.find(function(r){ return r.id===id; }); 12134 var pCount = allParticipants.filter(function(p){ return p.ritId===id&&(p.status===STATUS_GO||p.status===STATUS_MAYBE); }).length; 12135 var isArc = pCount > 1; 12136 var savedRide = ride ? Object.assign({}, ride) : null; 12137 var savedParts = allParticipants.filter(function(p){ return p.ritId===id; }); 12138 // Optimistic remove 12139 allRides = allRides.filter(function(r){ return r.id!==id; }); 12140 allParticipants = allParticipants.filter(function(p){ return p.ritId!==id; }); 12141 var card = document.querySelector('.ride-card[data-ride-id="'+id+'"]'); 12142 if(card) card.remove(); 12143 var undone = false; 12144 showUndoBar(L['gr-planner-rit-verwijderd']||'Rit verwijderd', function(){ 12145 undone = true; 12146 if(savedRide) allRides.push(savedRide); 12147 savedParts.forEach(function(p){ allParticipants.push(p); }); 12148 render(); 12149 }); 12150 await new Promise(function(r){ setTimeout(r, 5200); }); 12151 if(undone) return; 12152 // Commit naar GAS (text/plain = geen CORS-preflight, body correct doorgestuurd) 12153 var pl = JSON.stringify(isArc 12154 ? {action:'cancel_ride',ritId:id,email:userEmail,statusCancelled:STATUS_CANCELLED} 12155 : {action:'delete_ride',ritId:id,email:userEmail}); 12156 try{ await fetch(RIDE_SCRIPT_URL,{method:'POST',headers:{'Content-Type':'text/plain;charset=UTF-8'},body:pl}); }catch(e){} 12157 // GAS heeft cache al geïnvalideerd voor deleteRow â korte buffer dan reload 12158 await new Promise(function(r){ setTimeout(r, 800); }); 12159 window.grHerlaadPagina(); 12160}; 12161// ââ Helper: trigger-knop en popover opnieuw opbouwen na RSVP-actie ââ 12162function _rsvpUpdateDOM(id, newStatus) { 12163const _ride = allRides.find(r => r.id === id); if (!_ride) return; 12164const _isTicket = !!(_ride.tickets === true || String(_ride.tickets).toUpperCase() === 'TRUE'); 12165const _isBL = (_ride.status === STATUS_BUCKETLIST); 12166let _hasTicket = false, _tShopUrl = '', _tBookUrl = ''; 12167if (_isTicket) { 12168const _rsvpTags = _ride.rsvpTag ? _ride.rsvpTag.split(',').map(t => clean(t)).filter(Boolean) : []; 12169_hasTicket = _rsvpTags.length > 0 && _rsvpTags.some(tag => userTags.some(ut => clean(ut) === tag)); 12170const _det = (typeof getRouteDetails === 'function') ? getRouteDetails(_ride) : {}; 12171_tShopUrl = (_det.shopLink ? _det.shopLink + '-event' : '').replace(/'/g, "\\'"); 12172_tBookUrl = _tShopUrl ? _tShopUrl + '#booking' : ''; 12173} 12174const _dnow = new Date(); _dnow.setHours(0,0,0,0); 12175const _rDay = _ride.datum ? new Date(new Date(_ride.datum).toDateString()) : null; 12176const _showV = _isBL || !_rDay || _rDay <= _dnow; 12177const _isPast2 = !!(_rDay && _rDay < _dnow); 12178const _isDashboard2 = !!window.GR_DASHBOARD_MODE; 12179const _isOwner2 = userEmail ? clean(_ride.email) === clean(userEmail) : false; 12180const _isGlobalAdmin2 = typeof ADMIN_EMAILS !== 'undefined' && ADMIN_EMAILS.includes(clean(userEmail || '')); 12181const _areaTagForRide2 = (typeof getAreaTagForRide === 'function') ? getAreaTagForRide(_ride.rondo) : null; 12182const _userHasAreaTag2 = !!(_areaTagForRide2 && typeof userTags !== 'undefined' && userTags.some(t => clean(t) === _areaTagForRide2)); 12183const _cs = newStatus; 12184// Trigger knop 12185const btn = gQS(`.ride-card[data-ride-id="${id}"] .btn-rsvp-trigger`); 12186if (btn) { 12187btn.className = 'btn-rsvp-trigger'; 12188if (_cs === STATUS_VOLTOOID) { btn.classList.add('active-blue'); btn.innerHTML = 'ââ '; }
12189/* Zelfde regels als in createCard (planner-script3): ticket = oranje vinkje, 12190 bewaard op bucketlist = hartje. Deze functie bouwt de knop en de popover na 12191 elke RSVP-actie opnieuw op, dus de twee moeten gelijk blijven. */ 12192else if (_isTicket && _hasTicket) { btn.classList.add('active-orange'); btn.innerHTML = 'â'; } 12193else if (_isBL && !_isOwner2 && _userHasAreaTag2) { btn.classList.add('active-green'); btn.innerHTML = SVG_HEART_FILLED; } 12194else if (_cs === STATUS_GO) { btn.classList.add('active-green'); btn.innerHTML = (_isBL || _isTicket) ? SVG_HEART_FILLED : 'â'; } 12195else if (_cs === STATUS_MAYBE) { btn.classList.add('active-blue'); btn.innerHTML = '?'; } 12196else { btn.innerHTML = L['gr-planner-you'] || 'Jij?'; } 12197} 12198// Popover opnieuw opbouwen 12199const popEl = gEI(`rsvp-popover-${id}`); if (!popEl) return; 12200let _pi = []; 12201if (_isOwner2) _pi.push(`<div class="rsvp-option info-only" style="font-style:italic">${L['gr-planner-you-are-organizer'] || 'Jij bent organisator'}</div>`); 12202if (_cs === STATUS_VOLTOOID) { 12203_pi.push(`<div class="rsvp-option active-item blue"><span class="ri">ââ </span>${L['gr-planner-rsvp-voltooid'] || 'Rondo Voltooid'}</div><div class="rsvp-divider"></div>`); 12204} else if (_isTicket && _hasTicket) { 12205_pi.push(`<div class="rsvp-option active-item orange"><span class="ri">â</span>${_grLbl('gr-planner-you-have-tickets','Je hebt Tickets')}</div><div class="rsvp-divider"></div>`); 12206} else if (!_isBL && !_isTicket && _cs === STATUS_GO) { 12207const _partLabel2 = (_isDashboard2 && _isPast2) ? (L['gr-planner-event-voltooid'] || 'Event voltooid') : (L['gr-planner-participating'] || 'Ik doe mee'); 12208_pi.push(`<div class="rsvp-option active-item green"><span class="ri">â</span>${_partLabel2}</div><div class="rsvp-divider"></div>`); 12209} else if ((_isBL || _isTicket) && _cs === STATUS_GO && _isOwner2) { 12210_pi.push(`<div class="rsvp-option active-item green"><span class="ri">â</span>${L['gr-planner-participating'] || 'Ik doe mee'}</div><div class="rsvp-divider"></div>`); 12211} else if (_isBL && !_isOwner2 && _userHasAreaTag2) { 12212// Areatag: altijd â tonen als actieve status (ook als _cs === null) 12213_pi.push(`<div class="rsvp-option active-item green"><span class="ri">â</span>${L['gr-bucketlist-areatag-status'] || 'Rondo besteld'}</div><div class="rsvp-divider"></div>`); 12214} else if ((_isBL || _isTicket) && _cs === STATUS_GO && !_isOwner2) { 12215_pi.push(`<div class="rsvp-option active-item green"><span class="ri">${SVG_HEART_FILLED}</span>${L['gr-bucketlist-on-list'] || 'Bewaard op bucketlist'}</div><div class="rsvp-divider"></div>`); 12216} else if (!_isBL && !_isTicket && _cs === STATUS_MAYBE) { 12217_pi.push(`<div class="rsvp-option active-item blue"><span class="ri">?</span>${L['gr-planner-rsvp-maybe-active'] || 'Ik doe misschien mee'}</div><div class="rsvp-divider"></div>`); 12218} 12219if (_showV && _cs !== STATUS_VOLTOOID) { 12220_pi.push(`<div class="rsvp-option text-blue" onclick="event.stopPropagation(); window.rsvp('${id}', '${STATUS_VOLTOOID}', this)"><span class="ri">ââ </span>${L['gr-planner-rsvp-voltooid'] || 'Rondo Voltooid'}</div>`); 12221} 12222if (!_isBL) { 12223if (_isTicket) { 12224if (_isGlobalAdmin2 && _isOwner2) { 12225// Admin+organisator van ticket event: directe RSVP, geen ticket modal 12226if (_cs !== STATUS_GO && _cs !== STATUS_VOLTOOID) { 12227_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.rsvp('${id}', '${STATUS_GO}', this)"><span class="ri">â</span>${L['gr-planner-ticket-join'] || 'Meedoen'}</div>`); 12228} 12229if (_cs !== STATUS_MAYBE && _cs !== STATUS_VOLTOOID) { 12230_pi.push(`<div class="rsvp-option text-blue" onclick="event.stopPropagation(); window.rsvp('${id}', '${STATUS_MAYBE}', this)"><span class="ri">?</span>${L['gr-planner-rsvp-maybe'] || 'Misschien'}</div>`); 12231} 12232if (_cs === STATUS_GO || _cs === STATUS_MAYBE) { 12233_pi.push(`<div class="rsvp-option danger" onclick="event.stopPropagation(); window.rsvp('${id}', 'DELETE', this)"><span class="ri">â</span>${L['gr-planner-rsvp-no'] || 'Ik doe niet mee'}</div>`); 12234} 12235} else if (!_hasTicket && _cs !== STATUS_VOLTOOID) { 12236_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.showTicketModal('${_tShopUrl}', '${_tShopUrl}')"><span class="ri">â</span>${L['gr-planner-ticket-join'] || 'Meedoen'}</div>`); 12237} 12238} else { 12239if (_cs !== STATUS_GO && _cs !== STATUS_VOLTOOID) { 12240_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.rsvp('${id}', '${STATUS_GO}', this)"><span class="ri">â</span>${L['gr-planner-ticket-join'] || 'Meedoen'}</div>`); 12241} 12242} 12243} 12244if ((_isBL || _isTicket) && _cs !== STATUS_GO && !(_isGlobalAdmin2 && _isOwner2 && _isTicket) && !(_userHasAreaTag2 && _isBL)) { 12245_pi.push(`<div class="rsvp-option text-green" onclick="event.stopPropagation(); window.rsvp('${id}', '${STATUS_GO}', this)"><span class="ri">â¡</span>${L['gr-bucketlist-btn-save'] || 'Bewaar op bucketlist'}</div>`); 12246} 12247if (!_isBL && !_isTicket && _cs !== STATUS_MAYBE && _cs !== STATUS_VOLTOOID && !(_isDashboard2 && _isPast2)) { 12248_pi.push(`<div class="rsvp-option text-blue" onclick="event.stopPropagation(); window.rsvp('${id}', '${STATUS_MAYBE}', this)"><span class="ri">?</span>${L['gr-planner-rsvp-maybe'] || 'Misschien'}</div>`); 12249} 12250/* Van de bucketlist halen mag zodra hij erop staat â ook bij een event. Met 12251 een ticket niet: dan doe je mee en is dit geen bucketlist-item meer. */ 12252if ((_isBL || _isTicket) && _cs === STATUS_GO && !_hasTicket) { 12253_pi.push(`<div class="rsvp-option danger" onclick="event.stopPropagation(); window.rsvp('${id}
12253', 'DELETE', this)"><span class="ri">â</span>${L['gr-bucketlist-btn-remove'] || 'Verwijder van bucketlist'}</div>`); 12254} 12255if (!_isBL && !_isTicket && (_cs === STATUS_GO || _cs === STATUS_MAYBE)) { 12256const _noLabel2 = (_isDashboard2 && _isPast2) ? (L['gr-planner-niet-meegedaan'] || 'Niet meegedaan') : (L['gr-planner-rsvp-no'] || 'Ik doe niet mee'); 12257_pi.push(`<div class="rsvp-option danger" onclick="event.stopPropagation(); window.rsvp('${id}', 'DELETE', this)"><span class="ri">â</span>${_noLabel2}</div>`); 12258} 12259popEl.innerHTML = _pi.join(''); 12260} 12261window.rsvp = async function(id, status, optionElement) { 12262window.toggleRSVP(id); 12263/* "Rondo Voltooid": geen tussenmodal meer. Direct opslaan â daarmee is de rit 12264 ook van je bucketlist af, want Voltooid is geen bucketlist-status â en 12265 meteen het formulier Nieuwe activiteit openen met het gebied voorgevuld. */ 12266if (status === STATUS_VOLTOOID) { 12267window._pendingVoltooidId = id; 12268window._pendingVoltooidRide = allRides.find(r => r.id === id) || null; 12269const _volRondo = (window._pendingVoltooidRide && window._pendingVoltooidRide.rondo) || ''; 12270window.confirmVoltooid().then(() => { 12271 if (typeof render === 'function') render(); 12272 if (typeof renderVoltooidSection === 'function') renderVoltooidSection(); 12273}); 12274/* Palmares-bridge doet de profielcheck en zet het gebied klaar; is die er niet, 12275 dan valt dit terug op de bestaande .open-rit-modal-btn-afhandeling. */ 12276if (typeof window.grPalOpenActivityForm === 'function' && window.grPalOpenActivityForm(_volRondo)) return; 12277const _volBtn = document.querySelector('.open-rit-modal-btn'); 12278if (_volBtn) { _volBtn.click(); if (typeof window._preFillPalmaresArea === 'function') window._preFillPalmaresArea(); } 12279else console.warn('[GR] Activiteitenformulier niet gevonden op deze pagina.'); 12280return; 12281} 12282// Verwijder (bucketlist-rit of dashboard-view) â kaart direct weg + undo-balk onderaan 12283const _rsvpDelRide = allRides.find(r => r.id === id); 12284// Organizer/admin op dashboard: verwijder de HELE rit (niet alleen RSVP) 12285if(status==='DELETE'&&window.GR_DASHBOARD_MODE&&_rsvpDelRide&&_rsvpDelRide.status!==STATUS_BUCKETLIST){ 12286const _isOrg=clean(_rsvpDelRide.email)===clean(userEmail||''); 12287const _isAdm=typeof ADMIN_EMAILS!=='undefined'&&ADMIN_EMAILS.includes(clean(userEmail||'')); 12288if(_isOrg||_isAdm){window.grDeleteRidePopover(id);return;} 12289} 12290if (status === 'DELETE' && _rsvpDelRide && (_rsvpDelRide.status === STATUS_BUCKETLIST || activeView === 'bucketlist' || activeView === 'planned' || window.GR_DASHBOARD_MODE)) { 12291 const card = gQS(`.ride-card[data-ride-id="${id}"]`); 12292 const savedP = allParticipants.find(p => p.ritId === id && clean(p.email) === clean(userEmail)); 12293 allParticipants = allParticipants.filter(p => !(p.ritId === id && clean(p.email) === clean(userEmail))); 12294 if (card) card.remove(); 12295 sendPost({ action: 'rsvp', ritId: id, email: userEmail, status: 'DELETE' }, 0); 12296 showUndoBar((L['gr-planner-item-deleted']||'Item verwijderd...'), function() { 12297 const restoreP = savedP || { ritId: id, email: userEmail, status: STATUS_GO, name: localDisplayName, avatar: localDisplayAvatar }; 12298 allParticipants.push(restoreP); 12299 sendPost({ action: 'rsvp', ritId: id, email: userEmail, status: STATUS_GO }, 0); 12300 render(); 12301 }); 12302 return; 12303} 12304_rsvpUpdateDOM(id, status === 'DELETE' ? null : status); 12305await sendPost({ action: 'rsvp', ritId: id, email: userEmail, status: status }, 0); 12306allParticipants = allParticipants.filter(p => !(p.ritId === id && clean(p.email) === clean(userEmail))); 12307if(status !== 'DELETE') allParticipants.push({ ritId: id, email: userEmail, status: status, name: localDisplayName, avatar: localDisplayAvatar }); 12308updateAvatarsForCard(id); updateParticipantsListForCard(id); 12309}; 12310// Wordt aangeroepen vanuit palmaresConfirmModal knoppen 12311window.confirmVoltooid = function() { 12312const id = window._pendingVoltooidId; if (!id) return Promise.resolve(); 12313window._pendingVoltooidId = null; 12314// Optimistic: local state first, server op runs in background 12315allParticipants = allParticipants.filter(p => !(p.ritId === id && clean(p.email) === clean(userEmail))); 12316allParticipants.push({ ritId: id, email: userEmail, status: STATUS_VOLTOOID, name: localDisplayName, avatar: localDisplayAvatar }); 12317_rsvpUpdateDOM(id, STATUS_VOLTOOID); 12318try { localStorage.removeItem(GR_CACHE_KEY); } catch(e) {} 12319updateAvatarsForCard(id); updateParticipantsListForCard(id); 12320sendPost({ action: 'rsvp', ritId: id, email: userEmail, status: STATUS_VOLTOOID }, 0);
12320 // fire & forget 12321return Promise.resolve(); 12322}; 12323// Pre-fill areaInput in ritModal zodra de select-opties geladen zijn 12324window._preFillPalmaresArea = function() { 12325const ride = window._pendingVoltooidRide; if (!ride || !ride.rondo) return; 12326const sel = document.getElementById('areaInput'); if (!sel) return; 12327const doSet = () => { sel.value = ride.rondo; sel.dispatchEvent(new Event('change')); }; 12328if (sel.options.length > 1) { doSet(); return; } 12329const obs = new MutationObserver(() => { if (sel.options.length > 1) { obs.disconnect(); doSet(); } }); 12330obs.observe(sel, { childList: true }); 12331}; 12332window.postComment = async function(id, triggerEl) { 12333if(window.requireLogin()) return; 12334// Gebruik de kaart van de trigger (voorkomt dat we de verkeerde textarea pakken bij dubbele IDs in planRondoModal) 12335const _card = triggerEl ? triggerEl.closest('.ride-card') : null; 12336const input = _card ? _card.querySelector(`#input-comment-${id}`) : gEI(`input-comment-${id}`); 12337const text = (input?.value || "").trim(); 12338if(!text) return; 12339if(text.length > 200) { alert(L['gr-planner-alert-comment-too-long'] || 'Reactie te lang'); return; } 12340input.value = ""; 12341const now = new Date(); const timestampISO = now.toISOString(); 12342const commentsDiv = _card ? _card.querySelector(`#comments-${id}`) : gEI(`comments-${id}`); 12343const div = document.createElement('div'); div.className = 'comment-item'; 12344const timeStr = `${now.getDate()}/${now.getMonth()+1} - ${now.getHours()}:${now.getMinutes().toString().padStart(2,'0')}`; 12345let avHtml = localDisplayAvatar ? `<img src="${localDisplayAvatar}" class="comment-avatar-img">` : `<div class="comment-avatar-placeholder">${getInitials(localDisplayName)}</div>`; 12346const ride = allRides.find(r => r.id === id); 12347let nameHtml = `<span class="comment-meta">${localDisplayName}</span>`; 12348if (ride && clean(ride.email) === clean(userEmail)) nameHtml += `<span class="organizer-label">(${L['gr-planner-organizer-label'] || 'organisator'})</span>`; 12349div.innerHTML = `${avHtml}<div class="comment-content">${nameHtml}<span class="comment-date">(${timeStr})</span><br><span class="comment-text">${text.replace(/\n/g,'<br>')}</span></div><button class="comment-delete-btn" title="${L['gr-planner-delete-message'] || 'Verwijder'}">${SVG_TRASH}</button>`; 12350const btn = div.querySelector('.comment-delete-btn'); 12351if(btn) btn.onclick = function() { window.deleteComment(id, timestampISO, div); }; 12352commentsDiv.appendChild(div); commentsDiv.scrollTop = commentsDiv.scrollHeight; 12353allComments.push({ ritId: id, email: userEmail, text: text, timestamp: timestampISO, name: localDisplayName, avatar: localDisplayAvatar }); 12354if (window._grCacheBijwerken) window._grCacheBijwerken(); 12355await sendPost({ action: 'post_comment', ritId: id, email: userEmail, bericht: text, timestamp: timestampISO }); 12356 12357/* Het Apps Script bewaart een eigen timestamp en negeert de meegestuurde â bij 12358 een meting zat er 1,17 seconde tussen. Verwijderen zoekt de rij op timestamp, 12359 dus zonder correctie vindt een delete vlak na het plaatsen niets: in beeld 12360 verdwijnt de opmerking wel, maar in de sheet blijft hij staan. 12361 Daarom hier de werkelijke waarde ophalen en de verwijderknop bijstellen. */ 12362try { 12363 const _vers = await fetchFreshData(); 12364 const _mijn = (_vers.berichten || []).filter(function (c) { 12365 return c.ritId === id && clean(c.email) === clean(userEmail) && (c.text || '') === text; 12366 }).sort(function (a, b) { return new Date(b.timestamp) - new Date(a.timestamp); }); 12367 const _srvTs = _mijn.length ? _mijn[0].timestamp : null; 12368 if (_srvTs && _srvTs !== timestampISO) { 12369 const _lokaal = allComments.find(function (c) { return c.ritId === id && c.timestamp === timestampISO; }); 12370 if (_lokaal) _lokaal.timestamp = _srvTs; 12371 if (btn) btn.onclick = function () { window.deleteComment(id, _srvTs, div); }; 12372 if (window._grCacheBijwerken) window._grCacheBijwerken(); 12373 } 12374} catch (e) { 12375 console.warn('[GR opmerking] server-timestamp niet opgehaald; direct verwijderen kan mislukken.', e); 12376} 12377}; 12378window.deleteComment = async function(ritId, ts, el) { 12379if(confirm(L['gr-planner-confirm-delete-message'] || 'Verwijderen?')) { 12380/* Naast de timestamp ook de tekst meesturen. Een net geplaatste opmerking heeft 12381 nog de ISO-tijd uit de browser; ná een herlading komt die uit de spreadsheet 12382 en kan de notatie afwijken. Op tekst kan het Apps Script dan alsnog de juiste 12383 rij vinden. Kent het script het veld niet, dan wordt het simpelweg genegeerd. */ 12384const _c = allComments.find(c => c.ritId === ritId && c.timestamp === ts); 12385el.remove(); allComments = allComments.filter(c => !(c.ritId === ritId && c.timestamp === ts)); 12386if (window._grCacheBijwerken) window._grCacheBijwerken(); 12387await sendPost({ 12388 action: 'delete_comment', ritId: ritId, email: userEmail, timestamp: ts, 12389 bericht: _c ? (_c.text || '') : '' 12390}); 12391} 12392}; 12393window.formatDoc = function(cmd, e) { if(e) e.preventDefault(); document.execCommand(cmd, false, null); }; 12394window.addLink = function(e) { 12395if(e) e.preventDefault(); 12396let url = prompt(L['gr-planner-prompt-url'] || 'URL:'); 12397if (url) { 12398if (!url.match(/^https?:\/\//i)) url = 'https://' + url; 12399document.execCommand('createLink', false, url); 12400const sel = window.getSelection(); 12401if(sel.anchorNode && sel.anchorNode.parentNode.tagName === 'A') sel.anchorNode.parentNode.target = "_blank"; 12402} 12403};
12404window.addLinkEn = function(e) { 12405if(e) e.preventDefault(); 12406const enDiv = gEI('inpExtraDivEn'); 12407if (enDiv) enDiv.focus(); 12408window.addLink(null); 12409}; 12410const _btnNewRide = gEI('btnNewRide'); 12411if(_btnNewRide) _btnNewRide.addEventListener('click', (e) => { if(window.requireLogin(e)) return; window._grOpenRitModal(null); }); 12412const _closeRideBtn = gEI('rideModal') && gEI('rideModal').querySelector('.close-ride-modal'); 12413if(_closeRideBtn) _closeRideBtn.addEventListener('click', window._grCloseRideModal); 12414const closeLoginBtn = gQS('.close-login-modal'); 12415if(closeLoginBtn) closeLoginBtn.addEventListener('click', () => { loginModal.style.display = "none"; document.body.classList.remove('modal-open'); }); 12416gQSA('.close-upgrade-modal').forEach(btn => btn.addEventListener('click', (e) => { e.stopPropagation(); const m = gEI('upgradeModal'); if(m) m.style.display = "none"; document.body.classList.remove('modal-open'); })); 12417const upgradeModalBackdrop = gEI('upgradeModal'); 12418if(upgradeModalBackdrop) upgradeModalBackdrop.addEventListener('click', (e) => { if(e.target === upgradeModalBackdrop) { upgradeModalBackdrop.style.display = "none"; document.body.classList.remove('modal-open'); } }); 12419/* dateMode-radios zitten in rideModal (nu in de footer) â herstelbaar houden. */ 12420let radios = Array.from(document.getElementsByName('dateMode')); 12421/* Drie standen: specifieke datum, voorkeursdagen, of ntb met vrije toelichting. */ 12422window._grToonDatumVak = function(modus) { 12423const vakken = { specific: 'inputSpecific', days: 'inputDays', ntb: 'inputNtb' }; 12424Object.keys(vakken).forEach(function(k) { 12425const el = gEI(vakken[k]);
12426if (el) el.classList.toggle('hidden', k !== modus); 12427}); 12428/* Vierde stand: bucketlist. Die heeft geen eigen datumvak â geen van de drie 12429 past op 'bucketlist', dus ze gaan alle drie weg, en dat is precies goed. 12430 Wel verdwijnen Eventnaam en Ticketverkoop: een Rondo op de bucketlist is 12431 geen event, dus die twee velden slaan nergens op. */ 12432var _isBucket = (modus === 'bucketlist'); 12433var _ev = gEI('groupEventName'); 12434if (_ev) _ev.classList.toggle('gr-bucket-verborgen', _isBucket); 12435var _tk = gEI('groupTickets'); 12436if (_tk) _tk.classList.toggle('gr-bucket-verborgen', _isBucket); 12437}; 12438/* Gedelegeerd op document: `radios` werd op laadmoment opgehaald, maar 12439 rideModal zit in gr-shared-modals (footer). Was die er nog niet, dan werden 12440 er nul listeners gebonden en deed het wisselen van datummodus niets. */ 12441document.addEventListener('change', function (e) { 12442const t = e.target; 12443if (!t || t.name !== 'dateMode' || !t.checked) return; 12444const d = gEI('inpDate'); 12445if (d && d.disabled) return; 12446window._grToonDatumVak(t.value); 12447}); 12448</script>
12448 12449 12450 12451
12452<script> 12453/* De rit-modal is verhuisd naar gr-shared-modals (footer). Stond dat snippet 12454 later dan planner-script1/4, dan zijn modal/form/inpRondo/inpType/radios daar 12455 als null vastgelegd en klapte deze functie op radios.find(...). Hier eerst 12456 opnieuw ophalen, zodat de volgorde in de footer niet meer uitmaakt. */ 12457function _grRefreshRideEls() { 12458 if (!modal) modal = gEI('rideModal'); 12459 if (!form) form = gEI('rideForm'); 12460 if (!inpRondo) inpRondo = gEI('inpRondo'); 12461 if (!inpType) inpType = gEI('inpType'); 12462 if (!radios || !radios.length) radios = Array.from(document.getElementsByName('dateMode')); 12463} 12464/* Terugval als planner-script4 nog niet geladen is. */ 12465function _grDatumVak(modus) { 12466if (window._grToonDatumVak) return window._grToonDatumVak(modus); 12467const vakken = { specific: 'inputSpecific', days: 'inputDays', ntb: 'inputNtb' }; 12468Object.keys(vakken).forEach(function (k) { 12469const el = gEI(vakken[k]); 12470if (el) el.classList.toggle('hidden', k !== modus); 12471}); 12472} 12473window._grOpenRitModal = function(ride) { 12474_grRefreshRideEls(); 12475if (!modal || !inpRondo || !radios.length) { 12476 console.warn('[GR] rit-modal onvolledig â staat gr-shared-modals.html in de footer?'); 12477 return; 12478} 12479console.log('[GR _grOpenRitModal] aangeroepen met ride:', ride ? 'id=' + ride.id : 'null'); 12480document.body.classList.add('modal-open'); 12481window._grFormDirty = false; 12482const isGlobalAdmin = ADMIN_EMAILS.includes(clean(userEmail)); 12483const evGrp = gEI('groupEventName'); 12484if(evGrp) evGrp.style.display = isGlobalAdmin ? 'block' : 'none'; 12485const infoEnGrp = gEI('groupInfoEn'); 12486if(infoEnGrp) infoEnGrp.classList.toggle('hidden', !isGlobalAdmin); 12487const edEn = gEI('inpExtraDivEn'); 12488if(edEn) edEn.innerHTML = (ride && ride.extraEn) ? ride.extraEn : ""; 12489const rsvpTagGrp = gEI('groupRsvpTag'); 12490if(rsvpTagGrp) { if(isGlobalAdmin) rsvpTagGrp.classList.remove('hidden'); else rsvpTagGrp.classList.add('hidden'); } 12491const _rsvpTagEl = gEI('inpRsvpTag'); if(_rsvpTagEl) _rsvpTagEl.value = ride ? (ride.rsvpTag || "") : ""; 12492/* De bucketlist-stand staat als vierde optie bij "Rit aanmaken" en is alleen 12493 voor admins. Alleen het tonen van de optie gebeurt hier; welke stand 12494 aanstaat wordt verderop bepaald, ná het datumblok â dat zet anders alsnog 12495 'specific' terug. */ 12496const bucketlistLbl = gEI('labelBucketlistMode'); 12497if(bucketlistLbl) { if(isGlobalAdmin) bucketlistLbl.classList.remove('hidden'); else bucketlistLbl.classList.add('hidden'); } 12498const _isBucketRide = !!(ride && ride.status === STATUS_BUCKETLIST); 12499const ticketsGrp = gEI('groupTickets'); 12500if(ticketsGrp) { if(isGlobalAdmin) ticketsGrp.classList.remove('hidden'); else ticketsGrp.classList.add('hidden'); } 12501/* publicRideGroup werd alleen in init() zichtbaar gemaakt, dus vóórdat de 12502 footer met deze modal bestond. Hier bij het openen doen, net als hierboven. */ 12503const publicGrp = gEI('publicRideGroup'); 12504if(publicGrp) { if(isGlobalAdmin) publicGrp.classList.remove('hidden'); else publicGrp.classList.add('hidden'); } 12505const inpTickets = gEI('inpTickets'); 12506if(inpTickets) inpTickets.checked = !!(ride && (ride.tickets === true || String(ride.tickets).toUpperCase() === 'TRUE')); 12507const isEdit = !!(ride && ride.id != null && ride.id !== ''); 12508const _rideModalEl = gEI('rideModal'); if(_rideModalEl) _rideModalEl._isEditMode = isEdit; 12509const _editRitIdEl = gEI('editRitId'); if(_editRitIdEl) _editRitIdEl.value = isEdit ? ride.id : ""; 12510const _intendedTitle = isEdit ? (L['gr-planner-edit-ride'] || 'Rit bewerken') : (L['gr-planner-modal-new-ride'] || 'Nieuwe rit'); 12511console.log('[GR _grOpenRitModal] isEdit:', isEdit, '| titel wordt:', _intendedTitle); 12512const _rideModalForTitle = gEI('rideModal'); 12513const _modalTitleEl = (_rideModalForTitle && _rideModalForTitle.querySelector('[id="modalTitle"]')) || gEI('modalTitle'); 12514console.log('[GR _grOpenRitModal] modalTitle element:', _modalTitleEl ? 'gevonden (huidig: "' + _modalTitleEl.innerText + '")' : 'NIET gevonden'); 12515if(_modalTitleEl) _modalTitleEl.innerText = _intendedTitle; 12516if(isEdit) { setTimeout(function() { var _rm2 = document.getElementById('rideModal'); var _t2 = (_rm2 && _rm2.querySelector('[id="modalTitle"]')) || document.getElementById('modalTitle'); console.log('[GR _grOpenRitModal 200ms] titel nu:', _t2 ? '"' + _t2.innerText + '"' : 'n/a', 'â forceer:', _intendedTitle); if(_t2) _t2.innerText = _intendedTitle; }, 200); } 12517const dupBtn = gEI('btnDuplicateRide'); 12518if(dupBtn) { 12519const canDup = isEdit && (clean(ride.email) === clean(userEmail) || isGlobalAdmin); 12520if(canDup) { 12521dupBtn.classList.remove('hidden'); 12522dupBtn.onclick = function() { 12523const copy = Object.assign({}, ride, { id: undefined, ritId: undefined }); 12524gEI('rideModal').style.display = 'none'; document.body.classList.remove('modal-open'); 12525window._grOpenRitModal(copy); 12526}; 12527} else { dupBtn.classList.add('hidden'); } 12528} 12529gEI('modalName').innerText = localDisplayName; 12530const avCont = gEI('modalAvatarContainer'); 12531avCont.innerHTML = localDisplayAvatar ? `<img src="${localDisplayAvatar}" class="avatar-img">` : `<div class="avatar-placeholder" style="width:32px;height:32px;">${getInitials(localDisplayName)}</div>`; 12532gEI('inpEventName').value = ride ? (ride.eventNaam||"") : ""; 12533let participantCount = 0; 12534if(ride) { participantCount = allParticipants.filter(p => p.ritId === ride.id && (p.status===STATUS_GO || p.status===STATUS_MAYBE)).length; } 12535if(ride && ride.rondo && !Array.from(gEI('inpRondo').options).some(o => o.value === ride.rondo)) { 12536const opt = document.createElement('option'); opt.value = ride.rondo; opt.text = ride.rondo; gEI('inpRondo').appendChild(opt); 12537}
12538gEI('inpRondo').value = (ride && ride.rondo) ? ride.rondo : ""; 12539updateTypeOptions(); 12540const delBtnContainer = gEI('deleteRideContainer'); 12541if (ride && ride.id) { 12542if(delBtnContainer) delBtnContainer.classList.remove('hidden'); 12543const btnDel = gEI('btnDeleteRideModal'); 12544if(btnDel) { 12545btnDel.innerText = L['gr-planner-btn-delete'] || 'Verwijderen'; 12546btnDel.dataset.delid = String(ride.id); 12547btnDel.dataset.delname = ride.rondo || ''; 12548btnDel.dataset.delcount = String(participantCount); 12549} 12550} else { if(delBtnContainer) delBtnContainer.classList.add('hidden'); } 12551const editor = gEI('inpExtraDiv'); 12552if (editor) editor._userEdited = false; 12553const editorEnEl = gEI('inpExtraDivEn'); 12554if (editorEnEl) editorEnEl._userEdited = false; 12555if(ride) { 12556gEI('inpStartlocatie').value = ride.startlocatie || ""; 12557if(ride.type) gEI('inpType').value = ride.type === 'Road, Gravel' ? 'Beide' : ride.type; 12558updateRouteInfo(); 12559gEI('inpPace').value = ride.tempo || ""; 12560gEI('inpTarget').value = ride.voorWie || "Iedereen"; 12561editor.innerHTML = ride.extra || ""; 12562if (editor) editor._userEdited = true; 12563const dfElEdit = gEI('inpDateFinish'); 12564const tfElEdit = gEI('inpTimeFinish'); 12565if(dfElEdit) dfElEdit.value = ride.datumfinish ? new Date(ride.datumfinish).toISOString().split('T')[0] : ""; 12566if(tfElEdit) tfElEdit.value = ride.tijdfinish ? new Date(ride.tijdfinish).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit',hour12:false}) : ""; 12567gEI('inpPublic').checked = !!ride.isPublic; 12568/* De ntb-toelichting wordt opgeslagen in hetzelfde veld als de voorkeursdagen, 12569 met het voorvoegsel "ntb:". Zo hoeft de spreadsheet geen extra kolom. */ 12570const _ntbTekst = /^ntb:/i.test(ride.dagen || '') ? String(ride.dagen).slice(4) : null; 12571if(_ntbTekst !== null) { 12572radios.find(r => r.value === 'ntb').checked = true; 12573_grDatumVak('ntb'); 12574const _nn = gEI('inpNtbNote'); if(_nn) _nn.value = _ntbTekst; 12575gQSA('input[name="dayOpt"]').forEach(cb => cb.checked = false); 12576} else if(ride.dagen) { 12577radios.find(r => r.value === 'days').checked = true; 12578_grDatumVak('days'); 12579const days = ride.dagen.toLowerCase().split(',').map(s=>s.trim()); 12580gQSA('input[name="dayOpt"]').forEach(cb => cb.checked = days.includes(cb.value)); 12581const _nn2 = gEI('inpNtbNote'); if(_nn2) _nn2.value = ""; 12582} else { 12583radios.find(r => r.value === 'specific').checked = true; 12584_grDatumVak('specific'); 12585const _nn3 = gEI('inpNtbNote'); if(_nn3) _nn3.value = ""; 12586if(ride.datum) gEI('inpDate').value = new Date(ride.datum).toISOString().split('T')[0]; 12587gEI('inpTime').value = ride.tijd ? new Date(ride.tijd).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit',hour12:false}) : ""; 12588gQSA('input[name="dayOpt"]').forEach(cb => cb.checked = false); 12589} 12590} else { 12591gEI('rideForm').reset(); editor.innerHTML = ""; 12592const dfElNew = gEI('inpDateFinish'); if(dfElNew) dfElNew.value = ""; 12593const tfElNew = gEI('inpTimeFinish'); if(tfElNew) tfElNew.value = ""; 12594radios.find(r => r.value === 'specific').checked = true; 12595_grDatumVak('specific'); 12596const _nnNew = gEI('inpNtbNote'); if(_nnNew) _nnNew.value = ""; 12597updateTypeOptions(); gQSA('input[name="dayOpt"]').forEach(cb => cb.checked = false); 12598updateRouteInfo(); gEI('inpPublic').checked = false; 12599gEI('inpStartlocatie').disabled = false; gEI('inpEventName').value = ""; 12600} 12601/* ââ Bucketlist-stand, ná het datumblok hierboven ââââââââââââââââââââââââ 12602 Dat blok kiest altijd een van de drie datumstanden en zette 'specific' terug 12603 over de bucketlist-stand heen. Bij het opslaan vroeg het formulier dan om een 12604 datum die een bucketlist-Rondo niet heeft: je kreeg een melding en er gebeurde 12605 verder niets â het leek te blijven hangen. Daarom staat dit hier, als laatste 12606 woord over welke stand aanstaat. */ 12607if(_isBucketRide && isGlobalAdmin) { 12608 var _bRadio = gQS('input[name="dateMode"][value="bucketlist"]'); 12609 if(_bRadio) { _bRadio.checked = true; if(window._grToonDatumVak) window._grToonDatumVak('bucketlist'); } 12610} else if(window._grToonDatumVak) { 12611 /* Geen bucketlist: Eventnaam en Ticketverkoop weer tevoorschijn als de modal 12612 hiervoor wél op bucketlist stond. */ 12613 var _huidigeStand = gQS('input[name="dateMode"]:checked'); 12614 window._grToonDatumVak(_huidigeStand ? _huidigeStand.value : 'specific'); 12615} 12616const chkRowM = gEI('dateChangedRow'); 12617const chkM = gEI('chkDateChanged'); 12618if(chkRowM) { chkRowM.style.display = 'none'; } // rij altijd verborgen bij openen 12619if(chkM) { chkM.checked = false; } // nooit pre-aangevinkt 12620gEI('rideModal').style.display = "block"; 12621setupAutocomplete(); 12622function setupRichEnter(el) { 12623if (!el || el._enterSetup) return; 12624el._enterSetup = true; 12625el.addEventListener('keydown', function(e) { 12626if (e.key === 'Enter') { 12627e.preventDefault(); 12628document.execCommand('insertHTML', false, '<br>'); 12629} 12630}
12630); 12631el.addEventListener('input', function() { el._userEdited = true; window._grFormDirty = true; }); 12632} 12633setupRichEnter(gEI('inpExtraDiv')); 12634setupRichEnter(gEI('inpExtraDivEn')); 12635const inputs = gEI('rideForm').querySelectorAll('input, select, textarea'); 12636inputs.forEach(i => { i.onchange = () => { window._grFormDirty = true; }; i.oninput = () => { window._grFormDirty = true; }; }); 12637const btnTr = gEI('btnTranslate'); 12638if(btnTr) { btnTr.onclick = async function() { 12639const src = gEI('inpExtraDiv'); const dst = gEI('inpExtraDivEn'); if(!src||!dst) return; 12640const html = src.innerHTML.trim(); if(!html) return; 12641btnTr.textContent = L['gr-planner-translating'] || 'Vertalenâ¦'; btnTr.disabled = true; 12642try { 12643const tags = []; 12644let text = html 12645 .replace(/<br\s*\/?>/gi, '\n') 12646 .replace(/<[^>]+>/g, m => { tags.push(m); return '{' + (tags.length - 1) + '}'; }); 12647const MAX_CHUNK = 490; 12648const lines = text.split('\n'); 12649const chunks = []; 12650let cur = ''; 12651for (const line of lines) { 12652const cand = cur ? cur + '\n' + line : line; 12653if (cand.length <= MAX_CHUNK) { cur = cand; } 12654else { 12655if (cur) chunks.push(cur); 12656if (line.length > MAX_CHUNK) { 12657const parts = line.match(/[^.!?]+[.!?]+\s*/g) || [line]; 12658let sc = ''; 12659for (const p of parts) { 12660if ((sc + p).length <= MAX_CHUNK) { sc += p; } 12661else { if (sc) chunks.push(sc.trim()); sc = p; } 12662} 12663cur = sc.trim(); 12664} else { cur = line; } 12665} 12666} 12667if (cur) chunks.push(cur); 12668const results = []; 12669for (const chunk of chunks) { 12670const r = await fetch(`https://api.mymemory.translated.net/get?q=${encodeURIComponent(chunk)}&langpair=nl|en`); 12671const j = await r.json(); 12672const t = j.responseData?.translatedText || chunk; 12673results.push(t.toUpperCase().includes('QUERY LENGTH') ? chunk : t); 12674} 12675let translated = results.join('\n') 12676 .replace(/\{(\d+)\}/g, (_, i) => tags[+i] || '') 12677 .replace(/\n/g, '<br>'); 12678dst.innerHTML = translated; 12679} catch(e) { dst.innerHTML = src.innerHTML; } 12680btnTr.textContent = L['gr-planner-btn-translate'] || 'Vertaal'; btnTr.disabled = false; 12681}; } 12682const NOTICE_HTML = `<strong><em><span data-gr-notice="date">${L['gr-planner-date-changed'] || 'Let op: Datum / tijd aangepast'}</span></em></strong>`; 12683const addNotice = () => { 12684const ed = gEI('inpExtraDiv'); 12685if(!ed.querySelector('[data-gr-notice="date"]')) { 12686if(ed.innerHTML.trim()) { ed.appendChild(document.createElement('br')); ed.appendChild(document.createElement('br')); } 12687const tmp = document.createElement('div'); tmp.innerHTML = NOTICE_HTML; 12688ed.appendChild(tmp.firstChild); 12689} 12690}; 12691const removeNotice = () => { 12692const ed = gEI('inpExtraDiv'); 12693const span = ed.querySelector('[data-gr-notice="date"]'); 12694if(!span) return; 12695let node = span; 12696while(node.parentNode !== ed) node = node.parentNode; 12697let prev = node.previousSibling; 12698while(prev && (prev.nodeName === 'BR' || (prev.nodeType === 3 && !prev.textContent.trim()))) { 12699const del = prev; prev = prev.previousSibling; ed.removeChild(del); 12700} 12701ed.removeChild(node); 12702while(ed.lastChild && (ed.lastChild.nodeName === 'BR' || (ed.lastChild.nodeType === 3 && !ed.lastChild.textContent.trim()))) { 12703ed.removeChild(ed.lastChild); 12704} 12705}; 12706if(chkM) { 12707chkM.onchange = function() { 12708window._grFormDirty = true; 12709if(chkM.checked) addNotice(); else removeNotice(); 12710}; 12711} 12712if(isEdit) { 12713const origD = gEI('inpDate').value; 12714const origT = gEI('inpTime').value; 12715const origDF = gEI('inpDateFinish') ? gEI('inpDateFinish').value : ""; 12716const origTF = gEI('inpTimeFinish') ? gEI('inpTimeFinish').value : ""; 12717const showChk = () => { 12718const changed = gEI('inpDate').value !== origD || gEI('inpTime').value !== origT || 12719(gEI('inpDateFinish') ? gEI('inpDateFinish').value : "") !== origDF || 12720(gEI('inpTimeFinish') ? gEI('inpTimeFinish').value : "") !== origTF; 12721if(chkRowM) { 12722const wasHidden = chkRowM.style.display === 'none'; 12723chkRowM.style.display = changed ? '' : 'none'; 12724if(changed && wasHidden && chkM && chkM.checked) addNotice(); 12725if(!changed) removeNotice(); 12726} 12727}; 12728['inpDate','inpTime','inpDateFinish','inpTimeFinish'].forEach(id => { 12729const el = gEI(id); if(el) { el.addEventListener('change', showChk); el.addEventListener('input', showChk); } 12730}); 12731} 12732} 12733/* #rideForm zit in gr-shared-modals (footer). Draaide dit bestand eerder, dan 12734 was gEI('rideForm') null en werd de submit-listener nooit gebonden: Opslaan 12735 deed dan niets. Daarom gedelegeerd op document â submit-events bubbelen, dus 12736 de volgorde van laden maakt niet meer uit. */ 12737document.addEventListener('submit', async (e) => { 12738if (!e.target || e.target.id !== 'rideForm') return; 12739e.preventDefault(); 12740const _dateMode = gQS('input[name="dateMode"]:checked').value; 12741const isNtb = _dateMode === 'ntb'; 12742const isDays = _dateMode === 'days'; 12743const isBucket = _dateMode === 'bucketlist'; 12744// Geen datum en geen tijd bij voorkeursdagen, bij ntb en op de bucketlist. 12745const _zonderDatum = isDays || isNtb || isBucket; 12746let daysStr = ""; 12747if(isBucket) { 12748 /* Een bucketlist-Rondo heeft geen datum en geen toelichting; hij staat er 12749 gewoon, tot iemand hem plant. */ 12750} else if(isNtb) { 12751const _nt = (gEI('inpNtbNote') ? gEI('inpNtbNote').value : "").trim(); 12752if(!_nt) { alert(L['gr-planner-alert-ntb-note'] || 'Vul een toelichting in.'); return; } 12753daysStr = 'ntb:' + _nt; 12754} else if(isDays) { 12755const checked = Array.from(gQSA('input[name="dayOpt"]:checked')).map(cb=>cb.value); 12756if(!gEI('inpDate').disabled && checked.length===0) { alert(L['gr-planner-alert-select-day'] || 'Kies min 1'); return; } 12757daysStr = checked.join(', '); 12758} else { 12759const d = gEI('inpDate').value; const t = gEI('inpTime').value; 12760if(!d || !t) { alert(L['gr-planner-alert-date-time-required'] || 'Datum verplicht'); return; } 12761const df = gEI('inpDateFinish') ? gEI('inpDateFinish').value : ""; 12762if(df && df < d) { alert(L['gr-planner-alert-finish-before-start'] || 'Einddatum
12762kan niet vóór begindatum liggen.'); return; } 12763} 12764const selectedArea = gEI('inpRondo').value; 12765const isGlobalAdmin = ADMIN_EMAILS.includes(clean(userEmail)); 12766const infoDiv = gEI('inpExtraDiv'); 12767const infoText = infoDiv.innerText || ""; 12768if(infoText.length > 1200) { alert(L['gr-planner-alert-info-too-long'] || 'Te lang (max 1200)'); return; } 12769if((infoText.match(/\n/g) || []).length > 20) { alert(L['gr-planner-alert-info-too-many-lines'] || 'Max 20 regels'); return; } 12770const infoEnDiv = gEI('inpExtraDivEn'); 12771const infoEnText = infoEnDiv ? (infoEnDiv.innerText || "") : ""; 12772if(infoEnText.length > 1200) { alert((L['gr-planner-alert-info-too-long'] || 'Information (English) too long (max 1200)').replace('max 1200 tekens', 'max 1200 chars')); return; } 12773function sanitizeRichText(html) { 12774const tmp = document.createElement('div'); tmp.innerHTML = html; 12775const allowed = ['b','strong','i','em','u','br']; 12776function walk(node) { 12777Array.from(node.childNodes).forEach(child => { 12778if (child.nodeType === Node.TEXT_NODE) return; 12779if (child.nodeType !== Node.ELEMENT_NODE) { node.removeChild(child); return; } 12780const tag = child.tagName.toLowerCase(); 12781if (allowed.includes(tag)) { walk(child); } 12782else if (tag === 'a') { 12783let href = child.getAttribute('href') || ''; 12784if (!href.match(/^https?:\/\//i)) href = 'https://' + href; 12785const newA = document.createElement('a'); newA.href = href; newA.target = '_blank'; 12786walk(child); while (child.firstChild) newA.appendChild(child.firstChild); 12787node.replaceChild(newA, child); 12788} else { 12789walk(child); 12790while (child.firstChild) node.insertBefore(child.firstChild, child); 12791node.removeChild(child); 12792} 12793}); 12794} 12795walk(tmp); return tmp.innerHTML; 12796} 12797let rawExtra = sanitizeRichText(infoDiv.innerHTML); 12798rawExtra = rawExtra.replace(/<a\s+(?:[^>]*?\s+)?href=(["'])(.*?)\1/gi, (match, quote, url) => { 12799if (!url.match(/^https?:\/\//i)) url = 'https://' + url; return `<a href="${url}" target="_blank"`; 12800}); 12801const btn = gEI('rideForm').querySelector('button[type="submit"]'); 12802/* Eerst het opschrift onthouden zoals het er nú staat. Bij het herstellen werd 12803 een labelsleutel gebruikt met 'Opslaan' als terugval; op de Engelse pagina 12804 kwam er dan Nederlands terug zodra het label ontbrak. Wat er stond, klopte 12805 altijd al. */ 12806const _opslaanLabel = btn.innerText; 12807btn.disabled = true; btn.innerText = L['gr-planner-saving'] || "Opslaan..."; 12808/* Gaat er hierna iets mis, dan hoort de knop weer bruikbaar te zijn. Zonder 12809 deze vanger bleef hij op "Opslaan..." staan en kon je niets meer: de 12810 gebruiker ziet een dood formulier en weet niet waarom. */ 12811function _grHerstelOpslaanKnop(reden) { 12812 btn.disabled = false; 12813 btn.innerText = _opslaanLabel || L['gr-planner-btn-save'] || 'Opslaan'; 12814 if (reden) console.error('[GR] opslaan mislukt:', reden); 12815} 12816 12817/* ââ Rit-id vooraf bepalen ââââââââââââââââââââââââââââââââââââââââââââ 12818 Bij een nieuwe rit is #editRitId leeg en maakt Apps Script het id zelf aan 12819 (Utilities.getUuid). sendPost gaat met mode:'no-cors' de deur uit, dus dat 12820 antwoord is niet te lezen â het id kwam hier nooit terug. De deel-link na 12821 het opslaan miste daardoor zijn ?activity=, en dan wijst hij nergens heen. 12822 12823 saveRide_ doet `var id = req.ritId || generateId_()` en zoekt alleen naar 12824 een bestaande rij als req.ritId is meegegeven. Een vers UUID vindt daar 12825 niets, dus de rit wordt gewoon nieuw aangemaakt â met ons id. Zelfde vorm 12826 als wat de server maakt, dus er verandert niets aan de sheet. */ 12827function _grNieuwRitId() { 12828 try { if (window.crypto && crypto.randomUUID) return crypto.randomUUID(); } catch (e) {} 12829 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 12830 var r = Math.random() * 16 | 0; 12831 return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); 12832 }); 12833} 12834const _grRitId = gEI('editRitId').value || _grNieuwRitId(); 12835const payload = { 12836action: 'save_ride', ritId: _grRitId, email: userEmail, 12837startlocatie: gEI('inpStartlocatie').value, 12838rondo: selectedArea, type: gEI('inpType').value === 'Beide' ? 'Road, Gravel' : gEI('inpType').value, 12839tempo: gEI('inpPace').value, voorWie: gEI('inpTarget').value, 12840extra: rawExtra, ...(isGlobalAdmin ? { extraEn: gEI('inpExtraDivEn') ? sanitizeRichText(gEI('inpExtraDivEn').innerHTML) : "" } : {}), 12841datum: _zonderDatum ? "" : gEI('inpDate').value, 12842tijd: _zonderDatum ? "" : gEI('inpTime').value, dagen: daysStr, 12843datumfinish: gEI('inpDateFinish') ? (gEI('inpDateFinish').value || "") : "", 12844tijdfinish: gEI('inpTimeFinish') ? (gEI('inpTimeFinish').value || "") : "", 12845isPublic: gEI('inpPublic').checked, 12846eventNaam: isBucket ? '' : gEI('inpEventName').value, 12847statusGo: STATUS_GO, 12848...(isGlobalAdmin ? { rsvpTag: gEI('inpRsvpTag').value } : {}), 12849/* Status altijd meesturen voor een admin, ook als hij leeg moet worden. 12850 Stuurde je het veld alleen mee wanneer bucketlist aanstond, dan viel de 12851 status bij het uitzetten weg uit de payload en hield de sheet de oude waarde 12852 â uitvinken werkte dus nooit. */ 12853...(isGlobalAdmin ? { status: isBucket ? STATUS_BUCKETLIST : '' } : {}), 12854...(isGlobalAdmin && gEI('inpTickets') ? { tickets: isBucket ? false : gEI('inpTickets').checked } : {}) 12855}; 12856/* ââ Opslaan: niet langer wachten dan nodig âââââââââââââââââââââââââââââââ 12857 Hier stond `await sendPost(payload, 3000)`, gevolgd door een herlaadbeurt van 12858 de hele pagina. Die drie seconden waren marge voor de server, maar overbodig: 12859 de fetch-belofte komt pas terug als Apps Script klaar is â doPost schrijft de 12860 rij en leegt de cache vóórdat hij antwoordt. Wat de gebruiker eraan overhield 12861 was een knop die na het opslaan nog seconden op "Opslaan..." bleef staan, plus 12862 de herlaadbeurt daarbovenop. 12863 12864 Bij het bewerken van een rit zónder datum en tijd â bucketlist, 'ntb' en 12865 voorkeursdagen â kan het helemaal zonder herlaadbeurt. Alles wat verandert 12866 staat in payload en is gewone tekst of een ja/nee, dus we zetten het hier in 12867 de rit, tekenen opnieuw en sluiten de modal. Direct klaar. 12868 12869 Een rit mét datum herlaadt nog wel. De server levert datum en tijd in een 12870 ander formaat terug (2026-02-15T00:00:00.000Z, en de tijd op een sheet-datum 12871 uit 1899) dan wat hier in het formulier staat. Dat half nabouwen levert 12872 NaN:NaN op in de datumpil â beter de echte waarde ophalen. */ 12873const _isBewerking = !!gEI('editRitId').value; 12874const _zonderDatumVelden = _zonderDatum && !payload.datumfinish && !payload.tijdfinish; 12875const _ritInLijst = (_isBewerking && typeof allRides !== 'undefined' && Array.isArray(allRides)) 12876 ? allRides.find(function (r) { return r && String(r.id) === String(_grRitId); }) 12877 : null; 12878 12879if (_ritInLijst && _zonderDatumVelden) { 12880 sendPost(payload, 0); // loopt door op de achtergrond 12881 /* email, hostName en hostAvatar blijven met rust: die horen bij de eigenaar 12882 van de rit. Een admin die andermans rit bewerkt zou ze anders op zijn eigen
12883 naam zetten â precies wat saveRide_ serverkant ook weigert te doen. */ 12884 Object.keys(payload).forEach(function (sleutel) { 12885 if (sleutel === 'action' || sleutel === 'ritId' || sleutel === 'email' || sleutel === 'statusGo') return; 12886 _ritInLijst[sleutel] = payload[sleutel]; 12887 }); 12888 window._grFormDirty = false; 12889 try { localStorage.removeItem('gr_rides_v1'); } catch (e) {} 12890 _grHerstelOpslaanKnop(); 12891 const _rideModalSluit = gEI('rideModal'); 12892 if (_rideModalSluit) _rideModalSluit.style.display = 'none'; 12893 document.body.classList.remove('modal-open'); 12894 if (typeof render === 'function') render(); 12895 return; 12896} 12897 12898try { 12899 await sendPost(payload, 0); 12900} catch (_e) { 12901 _grHerstelOpslaanKnop(_e); 12902 alert(L['gr-planner-alert-save-error'] || 'Opslaan mislukt. Probeer het nog een keer.'); 12903 return; 12904} 12905window._grFormDirty = false; 12906try { localStorage.removeItem('gr_rides_v1'); } catch(e) {} 12907if (window._grPlanRondoMode) { 12908 window._grPlanRondoMode = false; 12909 const _pArea = window._grPlanRondoArea || payload.rondo || ''; 12910 const _pId = window._grPlanRondoRideId || payload.ritId || ''; 12911 window._grPlanRondoArea = null; window._grPlanRondoRideId = null; 12912 const shortId = _pId ? _pId.substring(0, 8) : ''; 12913 /* Zelfde adres als window.shareActivity hierboven. Hier stond /pages/planner 12914 en die pagina bestaat niet meer â live gemeten: HTTP 404. De planner draait 12915 op /pages/dashboard. Buiten het dashboard blijft de huidige pagina staan, 12916 want daar leest hetzelfde script de ?activity= weer uit. */ 12917 const _ep=location.pathname.startsWith('/en')?'/en':''; 12918 const _shareBasis = window.GR_DASHBOARD_MODE 12919 ? (window.location.origin + _ep + '/pages/dashboard') 12920 : (window.location.origin + window.location.pathname); 12921 const shareUrl = _shareBasis + (shortId ? '?activity=' + shortId : ''); 12922 if (!shortId) console.warn('[GR planner] Geen rit-id voor de deel-link â de link wijst naar het dashboard zonder rit.'); 12923 function _grFmtDate(d) { 12924 if (!d) return ''; const dt = new Date(d + 'T00:00:00'); 12925 return dt.toLocaleDateString('nl-NL', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); 12926 } 12927 const _d1 = payload.datum ? _grFmtDate(payload.datum) : ''; 12928 const _t1 = payload.tijd || ''; 12929 const _d2 = payload.datumfinish ? _grFmtDate(payload.datumfinish) : ''; 12930 const _t2 = payload.tijdfinish || ''; 12931 const _dateStr = _d1 + (_t1 ? ' ' + _t1 : '') + (_d2 ? ' tot ' + _d2 : '') + (_t2 ? ' ' + _t2 : ''); 12932 let _confEl = document.getElementById('grPlanRondoConfirmModal'); 12933 if (!_confEl) { 12934 _confEl = document.createElement('div'); 12935 _confEl.id = 'grPlanRondoConfirmModal'; 12936 _confEl.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;'; 12937 _confEl.innerHTML = `<div style="background:#fff;border-radius:16px;padding:32px 24px;max-width:380px;width:90%;text-align:center;color:#271D62;font-family:inherit;"> 12938 <h3 id="grPRC_title" style="margin:0 0 12px;font-size:1.1em;line-height:1.4;"></h3> 12939 <p style="font-weight:700;margin:0 0 14px;font-size:0.95em;">Nodig je fietsvrienden en anderen uit:</p> 12940 <button id="grPRC_share" class="btn btn-primary" style="width:100%;margin-bottom:10px;">Delen via...</button> 12941 <button id="grPRC_copy" class="btn btn-secondary" style="width:100%;margin-bottom:16px;">Kopieer link</button> 12942 <button id="grPRC_close" style="display:block;width:100%;padding:8px;font-family:inherit;font-size:0.9em;text-transform:uppercase;letter-spacing:0.04em;color:#271D62;text-align:center;cursor:pointer;background:none;border:none;text-decoration:underline;opacity:0.7;">Sluiten</button> 12943 </div>`; 12944 document.body.appendChild(_confEl); 12945 } 12946 document.getElementById('grPRC_title').textContent = 'Gran Rondo ' + _pArea + ' is gepland' + (_dateStr ? ' op ' + _dateStr : ''); 12947 document.getElementById('grPRC_share').onclick = function() { 12948 const _sb = this; 12949 const _origShare = _sb.textContent; 12950 if (navigator.share) { 12951 navigator.share({ title: 'Gran Rondo ' + _pArea, text: 'Gran Rondo ' + _pArea + (_dateStr ? ' â ' + _dateStr : ''), url: shareUrl }) 12952 .then(function(){ _sb.textContent = 'â Gedeeld!'; setTimeout(function(){ _sb.textContent = _origShare; }, 2000); }) 12953 .catch(function(){}); 12954 } else { 12955 if (navigator.clipboard) { navigator.clipboard.writeText(shareUrl).then(function(){ _sb.textContent = 'â Link gekopieerd!'; setTimeout(function(){ _sb.textContent = _origShare; }, 2000); }).catch(function(){}); } 12956 } 12957 }; 12958 document.getElementById('grPRC_copy').onclick = function() { 12959 const _cb = this; const _origCopy = _cb.textContent; 12960 const ta = document.createElement('textarea'); ta.value = shareUrl; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); 12961 _cb.textContent = 'â Gekopieerd!'; setTimeout(function(){ _cb.textContent = _origCopy; }, 2000); 12962 }; 12963 document.getElementById('grPRC_close').onclick = function() { window.grHerlaadPagina('#gepland'); }; 12964 _confEl.style.display = 'flex'; 12965 return; 12966} 12967window.grHerlaadPagina(); 12968}); 12969window.clearSearch = function() { 12970const el = gEI('filterArea'); 12971if (el) { el.value = ''; el.dispatchEvent(new Event('input')); } 12972deepLinkRideId = null; 12973const url = new URL(window.location.href); 12974url.searchParams.delete('activity'); 12975window.history.replaceState({}, '', url.toString()); 12976render(); 12977}; 12978const filterAreaEl = gEI('filterArea'); 12979if (filterAreaEl) { 12980filterAreaEl.addEventListener('input', function() { 12981const btn = gEI('btnClearSearch'); 12982if (btn) btn.classList.toggle('hidden', !this.value); 12983render(); 12984}); 12985} 12986function setupAutocomplete() { 12987const input = gEI('inpStartlocatie'); 12988if (!input || !window.google || !window.google.maps || !window.google.maps.places) return; 12989if (input._autocomplete) return; 12990input._autocomplete = new google.maps.places.Autocomplete(input, { types: ['geocode', 'establishment'] }); 12991input.addEventListener('keydown', function(e) { if (e.key === 'Enter') e.preventDefault(); }); 12992} 12993window.initMaps = function() { setupAutocomplete(); }; 12994 12995// ââ Plan deze Rondo modal ââââââââââââââââââââââââââââââââââââââââââââââââââ 12996let _planRondoCurrentRondo = ''; 12997let _planRondoCurrentArea = ''; 12998window.openPlanRondoModal = function(rondoName, areaTag) { 12999 if (window.requireLogin()) return; 13000 _planRondoCurrentRondo = rondoName; 13001 _planRondoCurrentArea = areaTag; 13002 const modal = document.getElementById('planRondoModal'); 13003 if (!modal) return; 13004 // Filter: zelfde gebied, toekomstig, niet geannuleerd, niet bucketlist 13005 const now = new Date(); now.setHours(0, 0, 0, 0); 13006 const lMe = clean(userEmail); 13007 const areaRides = allRides.filter(r => { 13008 if (r.status === STATUS_CANCELLED || r.status === STATUS_BUCKETLIST || r.status === STATUS_VOLTOOID) return false;
13009 const rTag = getAreaTagForRide(r.rondo); 13010 if (!rTag || rTag !== areaTag) return false; 13011 if (r.datum) return new Date(r.datum) >= now; 13012 return !!(r.isPublic || r.rsvpTag || r.tickets === true || String(r.tickets).toUpperCase() === 'TRUE'); 13013 }); 13014 areaRides.sort((a, b) => { 13015 if (a.datum && b.datum) return new Date(a.datum) - new Date(b.datum); 13016 if (a.datum) return -1; if (b.datum) return 1; 13017 return (a.rondo || '').localeCompare(b.rondo || ''); 13018 }); 13019 // Subtitle aanpassen op aanwezigheid van ritten 13020 const subEl = document.getElementById('planRondoSubtitle'); 13021 if (subEl) { 13022 subEl.textContent = areaRides.length > 0 13023 ? (L['gr-planner-plan-rondo-sub-rides'] || 'Fiets mee met anderen of prik zelf een datum.') 13024 : (L['gr-planner-plan-rondo-sub-norides'] || 'Prik een datum voor je Rondo en nodig anderen uit om met je mee te gaan.'); 13025 } 13026 const listEl = document.getElementById('planRondoRidesList'); 13027 if (!listEl) { modal.style.display = 'block'; document.body.classList.add('modal-open'); return; } 13028 listEl.innerHTML = ''; 13029 if (areaRides.length > 0) { 13030 areaRides.forEach(ride => { 13031 const isOwner = userEmail ? clean(ride.email) === lMe : false; 13032 const myP = userEmail ? allParticipants.find(p => p.ritId === ride.id && clean(p.email) === lMe) : null; 13033 listEl.appendChild(createCard(ride, isOwner, myP, false)); 13034 }); 13035 setTimeout(() => { areaRides.forEach(r => { updateAvatarsForCard(r.id); updateParticipantsListForCard(r.id); }); }, 0); 13036 } 13037 modal.style.display = 'block'; 13038 document.body.classList.add('modal-open'); 13039}; 13040window.openPlanRondoNew = function() { 13041 const rondoName = _planRondoCurrentRondo; 13042 const modal = document.getElementById('planRondoModal'); 13043 if (modal) { modal.style.display = 'none'; document.body.classList.remove('modal-open'); } 13044 window._grPlanRondoMode = true; 13045 window._grPlanRondoArea = rondoName; 13046 window._grOpenRitModal(null); 13047 // Pre-fill rondo + modalTitel + UUID na kleine vertraging (modal opent async) 13048 setTimeout(function() { 13049 // Pre-genereer UUID zodat we de rit-link kunnen tonen na opslaan 13050 const _newId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 13051 const r = Math.random() * 16 | 0; return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); 13052 }); 13053 const _ritIdEl = document.getElementById('editRitId'); 13054 if (_ritIdEl && !_ritIdEl.value) { _ritIdEl.value = _newId; window._grPlanRondoRideId = _newId; } 13055 // Titel instellen op "Rondo plannen" 13056 const _t = document.getElementById('modalTitle'); 13057 if (_t) _t.innerText = (typeof L !== 'undefined' && L['gr-planner-plan-rondo-title']) || 'Rondo plannen'; 13058 // Rondo pre-selecteren 13059 const inp = document.getElementById('inpRondo'); 13060 if (inp && rondoName) { 13061 if (!Array.from(inp.options).some(o => o.value === rondoName)) { 13062 const opt = document.createElement('option'); opt.value = rondoName; opt.text = rondoName; inp.appendChild(opt); 13063 } 13064 inp.value = rondoName; 13065 if (typeof updateTypeOptions === 'function') updateTypeOptions(); 13066 } 13067 }, 80); 13068}; 13069 13070init(); 13071// Extend _grInitDashboardTabs: external nav links, btnLoadMore fix, searchRow always visible, palmares search sync 13072(function(){ 13073var _gOrig=window._grInitDashboardTabs; 13074if(!_gOrig) return; 13075window._grInitDashboardTabs=function(){ 13076 _gOrig.apply(this,arguments); 13077 var _ep=location.pathname.startsWith('/en')?'/en':''; 13078 var _oSt=window._grSetDbTab; 13079 window._grSetDbTab=function(t){ 13080 if(t&&t.startsWith('ext:')){ 13081 var _sel=document.getElementById('dbViewSelect'),_o=_sel&&_sel.querySelector('option[value="'+t+'"]'),_h=_o&&_o.dataset.href; 13082 if(_h) window.location.href=(/^\//.test(_h)?_ep:'')+_h; 13083 return; 13084 } 13085 var _bm=document.getElementById('btnLoadMore');if(_bm)_bm.remove(); 13086 _oSt(t); 13087 /* Hier stond: _sr.style.display='' â de zoekbalk werd bij élke tabwissel 13088 aangezet, meteen nadat _grSetDbTab net had bepaald op welke tabs hij 13089 hoort. Twee stukken code die om dezelfde eigenschap vochten; het 13090 verborgen houden met !important in de stylesheet was daar het lapmiddel
13091 voor. Nu is er één eigenaar: _grSetDbTab. */ 13092 var _b3=document.getElementById('dbAddBtn3');if(_b3)_b3.style.display=(t==='voltooid-palmares'&&!window.GR_PUBLIC_VIEW)?'block':'none'; 13093 if(t==='voltooid-palmares'&&typeof window._grPalSetSearch==='function'){var _df=document.getElementById('dbSearchFilter');if(_df)window._grPalSetSearch(_df.value);} 13094 }; 13095 var _dbsf=document.getElementById('dbSearchFilter'); 13096 if(_dbsf) _dbsf.addEventListener('input',function(){ 13097 if((window.GR_DASHBOARD_TAB||'')==='voltooid-palmares'){ 13098 if(typeof window._grPalSetSearch==='function') window._grPalSetSearch(this.value); 13099 } 13100 }); 13101}; 13102}()); 13103// Dashboard tab-balk setup (na init zodat DOM + globals beschikbaar zijn) 13104if (window.GR_DASHBOARD_MODE && typeof window._grInitDashboardTabs === 'function') { 13105window._grInitDashboardTabs(); 13106} 13107/* ââ Publiek profiel: force palmares tab ââ */ 13108if (window.GR_DASHBOARD_MODE && window.GR_PUBLIC_VIEW) { 13109 setTimeout(function(){ 13110 if(typeof window._grSetDbTab==='function') window._grSetDbTab('voltooid-palmares'); 13111 document.querySelectorAll('.circles-controls-bar').forEach(function(el){el.style.setProperty('display','none','important');}); 13112 }, 100); 13113} 13114</script>
13114 13115 13116 13117 13118 13119 13120 13121 13122 13123
13124<script> 13125(function() { 13126 var SCRIPT_URL = "https://script.google.com/macros/s/AKfycbykfmZGR3AVsTqRF0LNs3Kx1zzVauuYSe-GGb2JzR8AeHYCjB8BNOQbXJZ5ouxa946n/exec"; 13127 var ACT_SHEET_URL = "https://opensheet.elk.sh/1z4oQxDzP6xwMxKY61Lp9X7Ky3wpQ27XjV79oIrJOtWo/Activiteiten"; 13128 var myEmail = null;/* Het hele labelobject komt hier rechtstreeks uit het metaobject en niet via 13129 een assign-variabele. Een losse sleutel uit zo'n variabele halen gaat goed â 13130 dat doet dit thema overal â maar het hele object erdoorheen halen en dan 13131 pas | json toepassen is een ander verhaal, en als daar niets uitkomt staat 13132 er 'const L = || {};' en sneuvelt het hele scriptblok. */ 13133 var palLabels ={"gr-db-more-items":"Show more items...","gr-palmares-btn-details":"View details","gr-palmares-btn-edit":"Edit","gr-palmares-btn-save":"Save","gr-palmares-btn-saving":"Saving...","gr-palmares-delete-confirm":"Type '%s' to delete:","gr-palmares-edit-title":"Edit activity","gr-palmares-error-delete":"Delete failed.","gr-palmares-error-load":"Error while loading.","gr-palmares-error-loading":"Could not load data. Please refresh the page.","gr-palmares-error-save":"Saving failed.","gr-palmares-label-opmerking":"Comment","gr-palmares-load-more":"Show more activitiesâ¦","gr-palmares-loading":"Loading activities...","gr-palmares-no-activities":"No activities yet.","gr-palmares-public-title":"Rondos â ","gr-palmares-total-areas":"Areas","gr-palmares-total-hm":"Total elevation","gr-palmares-total-km":"Total distance","gr-palmares-total-rounds":"Rondos ridden","gr-palmares-total-time":"Total hours","gr-palmares-unique-rounds":"Unique Rondos","gr-palmares-user-not-found":"User not found.","gr-palmares-view-activity":"View activity","gr-planner-actions":"Actions","gr-planner-plan-rondo-tooltip":"Plan this Rondo","gr-palmares-hidden-tooltip":"Only visible to you","gr-palmares-hof-link":"View Hall of Fame","gr-palmares-view-activity-kudos":"View activity \/ Give kudos"}; 13134 13135 /* ââ Rechten: zelfde logica als bucketlist-Rondo's in de Rondo Planner ââ 13136 Plannen mag alleen met de Rondoneur-tag, de gebiedstag van die Rondo, 13137 of als admin. De planner-globals zijn `let`-declaraties, dus die staan 13138 NIET op window â daarom via typeof benaderen, met Liquid als terugval. */ 13139 var _palRawTags = null || []; 13140 var _palClean = function(s){ return String(s == null ? '' : s).trim().toLowerCase(); }; 13141 var _palUserTags = (Array.isArray(_palRawTags) ? _palRawTags : []).map(_palClean); 13142 function _palTags() { 13143 if (typeof userTags !== 'undefined' && Array.isArray(userTags) && userTags.length) { 13144 return userTags.map(_palClean); 13145 } 13146 return _palUserTags; 13147 } 13148 function _palAreaTags() { 13149 if (typeof areaTags !== 'undefined' && areaTags) return areaTags; 13150 return window.areaTags || {}; 13151 } 13152 function _palIsAdmin() { 13153 var me = _palClean(myEmail); 13154 if (typeof ADMIN_EMAILS !== 'undefined' && Array.isArray(ADMIN_EMAILS) && ADMIN_EMAILS.indexOf(me) !== -1) return true; 13155 var t = _palTags(); 13156 return t.indexOf('admin') !== -1 || t.indexOf('staff') !== -1; 13157 } 13158 /* Gebiedstag opzoeken â zelfde matching als getAreaTagForRide() in de planner */ 13159 function _palAreaTagFor(gebied) { 13160 var at = _palAreaTags(); 13161 if (!at || !gebied) return null; 13162 if (at[gebied]) return _palClean(at[gebied]); 13163 var lg = _palClean(gebied); 13164 var k = Object.keys(at).find(function(key){ return _palClean(key) === lg; }); 13165 return k ? _palClean(at[k]) : null; 13166 } 13167 /* Mag deze gebruiker deze Rondo plannen? */ 13168 function _palCanPlan(gebied) { 13169 if (_palIsAdmin()) return true; 13170 var t = _palTags(); 13171 if (t.indexOf('rondoneur') !== -1) return true; 13172 var area = _palAreaTagFor(gebied); 13173 return !!(area && t.indexOf(area) !== -1); 13174 } 13175 13176 /* Palmares haalt zijn eigen data op en tekent zodra die binnen is; de planner 13177 vult areaTags pas na ZIJN fetch. Komt palmares eerder, dan is areaTags nog 13178 leeg en zou iemand mét de gebiedstag de plan-optie niet zien. Daarom één 13179 keer opnieuw tekenen zodra areaTags gevuld is. Voor admins en Rondoneurs
13180 verandert de uitkomst toch niet, dus die slaan we over. */ 13181 var _palAreaTagsSynced = false, _palAreaTagsTries = 0; 13182 function _palWaitForAreaTags() { 13183 if (_palAreaTagsSynced) return; 13184 if (_palIsAdmin() || _palTags().indexOf('rondoneur') !== -1) { _palAreaTagsSynced = true; return; } 13185 var at = _palAreaTags(); 13186 if (at && Object.keys(at).length) { 13187 _palAreaTagsSynced = true; 13188 var list = document.getElementById('grPalList'); 13189 if (list && allEntries.length) { list.innerHTML = ''; shownCount = 0; renderBatch(); } 13190 return; 13191 } 13192 if (++_palAreaTagsTries <= 40) setTimeout(_palWaitForAreaTags, 250); // max ~10s 13193 }var addLabels ={"gr-planner-activity-link":"Link to activity","gr-planner-activity-link-sub":"Strava, Komoot or another platform.","gr-planner-add-completed-rondo":"+ Add activity","gr-planner-btn-loading":"Working...","gr-planner-busy-upper":"SUBMITTING...","gr-planner-check-profile":"Checking profile...","gr-planner-choose-rondo":"Choose a Rondo","gr-planner-choose-type":"Choose type","gr-planner-close-window":"Close","gr-planner-create-profile":"Create profile","gr-planner-date-time-finish":"Finish date \u0026 time","gr-planner-date-time-start":"Start date \u0026 time","gr-planner-duration-label":"Riding time","gr-planner-duration-sub":"Calculated automatically from the start and finish time.","gr-planner-error-check-data":"Could not verify your data. Please try again.","gr-planner-error-fetch-routes":"Could not load routes. Please reload the page.","gr-planner-error-try-again":"Something went wrong. Please try again.","gr-planner-include-ranking":"Visible to others?","gr-planner-include-ranking-sub":"Make your ride visible to others.","gr-planner-loading":"Loading...","gr-planner-loading-routes":"Loading routes...","gr-planner-login":"Log in","gr-planner-login-to-add":"Log in to add a Rondo.","gr-planner-no":"No","gr-planner-not-logged-in":"Not logged in","gr-planner-profile-missing":"No profile found","gr-planner-profile-missing-text":"Create a profile first to submit a Rondo.","gr-planner-rating-10":"10 â An absolutely perfect Rondo!","gr-planner-rating-label":"Rating (1â10)","gr-planner-remarks-label":"Comment","gr-planner-remarks-placeholder":"Optional comment about your ride...","gr-planner-ride-submitted":"Your ride has been submitted. It may take a moment to appear.","gr-planner-select":"Select","gr-planner-semi-gravel-info":"Choose Road for the paved route, Gravel for the unpaved variant.","gr-planner-submit-ride":"Add activity","gr-planner-submit-ride-sub":"Enter the details of your completed ride.","gr-planner-submit-upper":"SAVE","gr-planner-thanks":"Thank you!","gr-planner-which-rondo":"Which Rondo?","gr-planner-which-route":"Which route?","gr-planner-yes":"Yes","gr-profile-choose":"Choose..."}; 13194 var MONTH = ['JAN','FEB','MRT','APR','MEI','JUN','JUL','AUG','SEP','OKT','NOV','DEC']; 13195 var PAGE = 20; 13196 var _palListEl = document.getElementById('grPalList'); 13197 var MAX_ITEMS = _palListEl && _palListEl.getAttribute('data-max') ? parseInt(_palListEl.getAttribute('data-max')) : 0; 13198 if (MAX_ITEMS > 0) PAGE = MAX_ITEMS; 13199 var allEntries = [], shownCount = 0, rondeAfstand = {}, globalRouteMap = {}; 13200 var sortBy = 'datum', searchQ = ''; 13201 // Bridge for dashboard dbSearchFilter â palmares search 13202 window._grPalSetSearch = function(q) { 13203 searchQ = (q||'').trim().toLowerCase(); 13204 shownCount = 0; 13205 var list = document.getElementById('grPalList'); 13206 if(list) list.innerHTML = ''; 13207 if(typeof renderBatch === 'function') renderBatch(); 13208 }; 13209 var ICON = { 13210 eye: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12,17 4,7 20,7"/></svg>', 13211 edit: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>', 13212 globe:'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>', 13213 menu: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="15" y2="18"/></svg>', 13214 info: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>', 13215 calendar:'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>', 13216 lock: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>' 13217 }; 13218 /* Een activiteit met "Zichtbaar voor anderen? = Nee" (sheetkolom "Ranglijst") 13219 blijft op je eigen dashboard staan, maar verdwijnt uit alles wat anderen 13220 zien: hall of fame, ranglijsten, recente rondo's en het publieke profiel 13221 (?user=). Op je eigen palmares markeert een slotje achter de titel dat de 13222 rit verborgen is. */ 13223 function _palVerborgen(entry){ 13224 return String((entry && entry['Ranglijst']) || '').trim().toLowerCase() === 'nee'; 13225 } 13226 var STAR_FULL = 'https://cdn.shopify.com/s/files/1/0899/1277/0934/files/star-icon.png?v=1750252532'; 13227 var STAR_HALF = 'https://cdn.shopify.com/s/files/1/0899/1277/0934/files/star-icon-half.png?v=1750252532'; 13228 function esc(s){ return String(s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); } 13229 function parseDutchDate(s){ 13230 if(!s) return new Date('Invalid'); 13231 var d=String(s).trim().split(' ')[0], p=d.split(/[-\/]/); 13232 if(p.length===3){ var a=parseInt(p[0]),b=parseInt(p[1]),c=parseInt(p[2]); if(c>1000) return new Date(c,b-1,a); if(a>1000) return new Date(a,b-1,c); } 13233 return new Date(s); 13234 } 13235 function parseTimeToSeconds(t){ 13236 if(!t) return 0; var p=String(t).split(':').map(Number);
13236 return p.length===3 ? p[0]*3600+p[1]*60+p[2] : p[0]*60+(p[1]||0); 13237 } 13238 function formatHMS(sec){ 13239 var h=Math.floor(sec/3600),m=Math.floor((sec%3600)/60),s=Math.floor(sec%60); 13240 return [h,m,s].map(function(v){return String(v).padStart(2,'0');}).join(':'); 13241 } 13242 function getKm(g,t){ return (rondeAfstand[g]&&rondeAfstand[g][t]&&rondeAfstand[g][t].km)||0; } 13243 function getHm(g,t){ return (rondeAfstand[g]&&rondeAfstand[g][t]&&rondeAfstand[g][t].hm)||0; } 13244 function renderStars(rating){ 13245 var r=Math.min(Math.max(Number(rating)||0,0),10); if(r<=0) return ''; 13246 var full=Math.floor(r/2),half=r%2>=1?1:0,empty=Math.max(0,5-full-half),html=''; 13247 for(var i=0;i<full;i++) html+='<img src="'+STAR_FULL+'" alt="â " width="14">'; 13248 if(half) html+='<img src="'+STAR_HALF+'" alt="½" width="14">'; 13249 for(var j=0;j<empty;j++) html+='<img src="'+STAR_FULL+'" alt="â" width="14" style="opacity:.18;">'; 13250 return html; 13251 } 13252 function getMapEmbed(url){ 13253 if(!url) return ''; var m=url.match(/activity\/(\d+)/i); 13254 if(m && url.toLowerCase().indexOf('komoot')>-1){ 13255 return '<div class="route-map-wrap"><iframe src="https://www.komoot.com/activity/'+m[1]+'/embed" width="100%" height="250" frameborder="0" scrolling="no" loading="lazy" style="display:block;border:0;"></iframe></div>'; 13256 } 13257 return ''; 13258 } 13259 window.grPalToggleDetail = function(idx){ 13260 var el=document.getElementById('grPalDetail'+idx); if(!el) return; 13261 if(el.classList.contains('open')){ el.classList.remove('open'); el.style.maxHeight=''; el.style.opacity=''; } 13262 else { el.classList.add('open'); el.style.maxHeight='5000px'; el.style.opacity='1'; } 13263 }; 13264 /* Geen Content-Type-header meesturen. Met application/json wordt dit een 13265 "preflighted request": de browser stuurt eerst een OPTIONS, Apps Script 13266 antwoordt daar niet op, en de fetch faalt gegarandeerd met "Failed to 13267 fetch". Daarna viel dit terug op mode:'no-cors' â dat kwam wél aan, maar 13268 leverde een opaque antwoord op: we konden niet zien of het gelukt was, en 13269 elke aanroep kostte anderhalve seconde extra. 13270 13271 Zonder die header is het een "simple request": geen OPTIONS, gewoon een 13272 leesbare 200 met de JSON van het script erin. 13273 13274 Het antwoord gaat er los doorheen, buiten de fetch-keten om. Gooide de 13275 callback een fout, dan belandde die vroeger in de .catch hierboven en werd 13276 het hele verzoek stilletjes nóg een keer verstuurd â met een foutmelding 13277 die nergens meer opdook. */ 13278 function postToScript(data, onSuccess, onError){ 13279 fetch(SCRIPT_URL, { method: 'POST', body: JSON.stringify(data) }) 13280 .then(function(r){ return r.text().catch(function(){ return ''; }); }) 13281 .then(function(txt){ 13282 var uit = null; 13283 try { uit = JSON.parse(txt); } catch(e) {} 13284 /* Het script antwoordt met {success:false, error:"..."} als er iets 13285 misging. Dat hoort bij onError thuis, niet bij onSuccess. */ 13286 if (uit && uit.success === false) { 13287 console.warn('[GR Palmares] script meldt een fout:', uit.error || txt); 13288 setTimeout(function(){ if(onError) onError(new Error(uit.error || 'mislukt')); }, 0); 13289 return; 13290 } 13291 setTimeout(function(){ if(onSuccess) onSuccess(txt, uit); }, 0); 13292 }) 13293 .catch(function(err){ 13294 console.warn('[GR Palmares] verzoek mislukt:', err); 13295 setTimeout(function(){ if(onError) onError(err); }, 0); 13296 }); 13297 } 13298 /* De drie knoppen van de bevestiging. Gedelegeerd op document, want de modal 13299 wordt bij het laden naar <body> verplaatst en kan dus later pas bestaan. */ 13300 (function(){ 13301 function vak() { return document.getElementById('grEditDeleteBevestig'); } 13302 function knop() { return document.getElementById('grEditDeleteBtn'); } 13303 function toon(ja) { 13304 var v = vak(), k = knop(); 13305 if (v) v.style.display = ja ? 'block' : 'none'; 13306 if (k) k.style.display = ja ? 'none' : ''; 13307 } 13308 document.addEventListener('click', function (e) { 13309 var t = e.target; 13310 if (!t || !t.id) return; 13311 if (t.id === 'grEditDeleteBtn') { e.preventDefault(); toon(true); return; } 13312 if (t.id === 'grEditDeleteNee') { e.preventDefault(); toon(false); return; } 13313 if (t.id === 'grEditDeleteJa') { 13314 e.preventDefault(); 13315 toon(false); 13316 var idxEl = document.getElementById('grEditIdx'); 13317 if (idxEl && window.grPalDoDelete) window.grPalDoDelete(idxEl.value); 13318 } 13319 }); 13320 /* Opent de modal opnieuw, dan hoort de vraag weer dicht te staan. */ 13321 window._grPalResetVerwijder = function(){ toon(false); }; 13322 })(); 13323 13324 /* ââ Verwijderen ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 13325 Hier stond een prompt() waarin je de gebiedsnaam moest overtypen. Twee 13326 bezwaren. Een: dat is veel gevraagd voor één activiteit uit je eigen lijst. 13327 Twee, en dat is de echte: zet iemand ooit het vinkje "Dialoogvensters 13328 onderdrukken" aan â dat biedt de browser vanzelf aan na een paar van die 13329 vensters â dan geeft prompt() meteen null terug. De regel eronder stuurde 13330 je dan zonder een woord terug. De knop leek stuk. 13331 13332 De bevestiging staat nu in de modal zelf, als gewone markup. Die laat zich 13333 niet onderdrukken, en één keer "Ja, verwijderen" is genoeg. 13334 13335 grPalDoDelete verwijdert vanaf nu meteen; het vragen gebeurt in de knop 13336 hierboven. Wie deze functie elders aanroept krijgt dus geen tussenstap 13337 meer â dat is precies de bedoeling, want dan is er al bevestigd. */ 13338 window.grPalDoDelete = function(idx){ 13339 var entry = allEntries[idx]; if(!entry) return; 13340 var expected = entry['Gebied'].trim(); 13341 document.body.style.cursor = "wait"; 13342 var ds = parseDutchDate(entry['Datum Start']); 13343 var dateKey = !isNaN(ds.getTime()) ? ds.getFullYear() + '-' + ('0' + (ds.getMonth() + 1)).slice(-2) + '-' + ('0' + ds.getDate()).slice(-2) : ''; 13344 postToScript({ action:'delete_activity', email:myEmail, gebied:expected, dateKey: dateKey }, 13345 function(){ 13346 document.body.style.cursor = "default"; 13347 /* De modal eerst dicht. Struikelt het bijwerken van de lijst hieronder 13348 ergens over, dan blijft er in elk geval geen popup hangen boven een 13349 activiteit die niet meer bestaat. */ 13350 var m = document.getElementById('grPalEditModal'); 13351 if (m) { m.style.display = 'none'; } 13352 document.body.classList.remove('modal-open');
13353 try { 13354 allEntries.splice(idx, 1); 13355 var list = document.getElementById('grPalList'); 13356 if (list) { list.innerHTML = ''; shownCount = 0; renderStats(allEntries); renderBatch(); } 13357 } catch (e) { 13358 /* Opnieuw tekenen mislukt: de activiteit Ãs weg, dus laat de pagina de 13359 verse stand ophalen in plaats van een halve lijst tonen. */ 13360 console.warn('[GR Palmares] lijst bijwerken mislukt, pagina wordt ververst:', e); 13361 window.grHerlaadPagina('#palmares'); 13362 } 13363 }, 13364 function(err){ 13365 document.body.style.cursor = "default"; 13366 console.warn('[GR Palmares] verwijderen mislukt:', err); 13367 alert(palLabels['gr-palmares-error-delete']); 13368 }); 13369 }; 13370 /* ââ Edit modal helpers ââ */ 13371 function toInputDate(str) { 13372 if(!str) return ''; 13373 var d = parseDutchDate(str); 13374 if(isNaN(d.getTime())) return ''; 13375 return d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0'+d.getDate()).slice(-2); 13376 } 13377 function toInputTime(str) { 13378 if(!str) return ''; 13379 /* De sheet levert zowel "19-6-2026 17:15" als "2026-06-19T17:15:00". 13380 Op alleen een spatie splitsen miste de ISO-variant, waardoor het 13381 tijdveld leeg bleef. */ 13382 var m = String(str).match(/(\d{1,2}):(\d{2})/); 13383 if (!m) return ''; 13384 return ('0' + m[1]).slice(-2) + ':' + m[2]; 13385 } 13386 function grEditCalcDuur() { 13387 var ds = document.getElementById('grEditDateStart').value; 13388 var ts = document.getElementById('grEditTimeStart').value || '00:00'; 13389 var df = document.getElementById('grEditDateFinish').value; 13390 var tf = document.getElementById('grEditTimeFinish').value || '00:00'; 13391 if(!ds || !df) return; 13392 var s = new Date(ds + 'T' + ts), f = new Date(df + 'T' + tf); 13393 if(f > s) { document.getElementById('grEditDuur').value = formatHMS(Math.floor((f-s)/1000)); } 13394 } 13395 /* ââ Hamburger actie-menu ââ */ 13396 /* Inline display i.p.v. alleen een klasse, zodat thema-CSS het niet kan overrulen. */ 13397 window.grPalToggleMenu = function(idx){ 13398 var el=document.getElementById('grPalMenu'+idx); 13399 document.querySelectorAll('.gr-pal-action-popover').forEach(function(p){ 13400 if(p!==el){ p.style.display='none'; p.classList.remove('show'); } 13401 }); 13402 if(!el) return; 13403 var open = el.style.display !== 'block'; 13404 el.style.display = open ? 'block' : 'none'; 13405 el.classList.toggle('show', open); 13406 }; 13407 window.grPalCloseMenu = function(idx){ 13408 var el=document.getElementById('grPalMenu'+idx); 13409 if(el){ el.style.display='none'; el.classList.remove('show'); } 13410 }; 13411 document.addEventListener('click', function(e){ 13412 if(e.target.closest && e.target.closest('.gr-pal-menu-wrapper')) return; 13413 document.querySelectorAll('.gr-pal-action-popover').forEach(function(p){ 13414 p.style.display='none'; p.classList.remove('show'); 13415 }); 13416 }); 13417 13418 /* ââ Edit modal open ââ */ 13419 /* Sleutel waarmee de backend de rij terugvindt: e-mail + gebied + dateKey. */ 13420 function _palDateKey(raw){ 13421 var d = parseDutchDate(raw); 13422 if (isNaN(d.getTime())) return ''; 13423 return d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0'+d.getDate()).slice(-2); 13424 } 13425 window.grPalOpenEdit = function(idx){ 13426 var entry=allEntries[idx]; if(!entry) return; 13427 /* De verwijdervraag hoort dicht te staan als je de modal opent â anders 13428 kijk je meteen tegen "Weet je het zeker?" aan van de vorige keer. */ 13429 if (window._grPalResetVerwijder) window._grPalResetVerwijder(); 13430 var _idxEl = document.getElementById('grEditIdx'); 13431 _idxEl.value = idx; 13432 /* De index in allEntries verschuift zodra de lijst opnieuw wordt opgehaald 13433 of gesorteerd. Leg daarom bij het openen de échte sleutel vast, zodat 13434 opslaan niet van die index afhangt. */ 13435 _idxEl.dataset.gebied = (entry['Gebied']||'').trim(); 13436 _idxEl.dataset.datekey = _palDateKey(entry['Datum Start']); 13437 document.getElementById('grEditGebied').value =entry['Gebied']||''; 13438 var dsRaw = entry['Datum Start']||''; 13439 document.getElementById('grEditDateStart').value =toInputDate(dsRaw); 13440 document.getElementById('grEditTimeStart').value =toInputTime(dsRaw); 13441 var dfRaw = entry['Datum Finish']||entry['Datum Einde']||entry['Einddatum']||''; 13442 document.getElementById('grEditDateFinish').value=toInputDate(dfRaw); 13443 document.getElementById('grEditTimeFinish').value=toInputTime(dfRaw); 13444 document.getElementById('grEditDuur').value =entry['Tijd']||entry['Duur']||''; 13445 document.getElementById('grEditLink').value =entry['URL']||''; 13446 /* De select heeft alleen 1..10; "8,0" of 8.5 matchte geen enkele optie 13447 en liet het veld leeg. Afronden naar een heel getal. */ 13448 var _cij = String(entry['Cijfer'] == null ? '' : entry['Cijfer']).replace(',', '.').trim(); 13449 var _cijNum = parseFloat(_cij); 13450 document.getElementById('grEditRating').value = isNaN(_cijNum) ? '' : String(Math.round(_cijNum)); 13451 document.getElementById('grEditOpmerking').value =entry['Opmerking']||''; 13452 document.getElementById('grEditError').style.display='none'; 13453 var btn=document.getElementById('grEditSaveBtn'); btn.disabled=false; btn.textContent=palLabels['gr-palmares-btn-save']; 13454 document.getElementById('grPalEditModal').style.display='flex'; 13455 }; 13456 ['grEditDateStart','grEditTimeStart','grEditDateFinish','grEditTimeFinish'].forEach(function(id){ 13457 var el=document.getElementById(id); if(el) el.addEventListener('change', grEditCalcDuur); 13458 }); 13459 /* De modals staan in gr-shared-modals.html (footer). Ontbreken ze op deze 13460 pagina, dan mag dat het script niet slopen. */ 13461 /* Gedelegeerd op document: de modals komen uit gr-shared-modals.html en 13462 kunnen later in de footer staan dan dit script. Een vastgeklikte 13463 referentie was dan null en de sluitknop deed niets. */ 13464 function _palEditModalEl(){ return document.getElementById('grPalEditModal'); } 13465 function _palSluitEdit(){ var m=_palEditModalEl(); if(m){ m.style.display='none'; document.body.classList.remove('modal-open'); } } 13466 13467 /* Sluiten op drie manieren, zodat het niet van één mechanisme afhangt:
13468 1) rechtstreekse binding zodra de knop in de DOM staat (footer laadt later), 13469 2) gedelegeerd op document in de CAPTURE-fase â een stopPropagation 13470 onderweg kan het dan niet meer tegenhouden, 13471 3) Escape-toets. */ 13472 (function _palBindEditClose(){ 13473 var pogingen = 0; 13474 (function probeer(){ 13475 var btn = document.getElementById('grPalEditClose'); 13476 if (btn && !btn._palBound) { 13477 btn._palBound = true; 13478 btn.addEventListener('click', function(ev){ ev.preventDefault(); ev.stopPropagation(); _palSluitEdit(); }); 13479 return; 13480 } 13481 if (++pogingen < 60) setTimeout(probeer, 250); // max ~15s 13482 })(); 13483 })(); 13484 13485 document.addEventListener('click', function(e){ 13486 var t = e.target; 13487 if (t && t.closest && t.closest('#grPalEditClose')) { e.preventDefault(); e.stopPropagation(); _palSluitEdit(); return; } 13488 var m = _palEditModalEl(); 13489 if (m && t === m) _palSluitEdit(); 13490 }, true); 13491 13492 document.addEventListener('keydown', function(e){ 13493 if (e.key !== 'Escape') return; 13494 var m = _palEditModalEl(); 13495 if (m && m.style.display && m.style.display !== 'none') _palSluitEdit(); 13496 }); 13497 document.addEventListener('submit',function(e){ 13498 if(!e.target || e.target.id!=='grPalEditForm') return; 13499 e.preventDefault(); 13500 var btn=document.getElementById('grEditSaveBtn'); var errEl=document.getElementById('grEditError'); 13501 btn.disabled=true; btn.textContent=palLabels['gr-palmares-btn-saving']; errEl.style.display='none'; 13502 var _idxEl = document.getElementById('grEditIdx'); 13503 var idx=parseInt(_idxEl.value,10); var entry=allEntries[idx]||{}; 13504 /* Sleutel uit het openen; val alleen terug op de entry als die er niet is. */ 13505 var _gebiedKey = (_idxEl.dataset.gebied || (entry['Gebied']||'')).trim(); 13506 var _dateKeyOrg = (_idxEl.dataset.datekey || ''); 13507 var linkVal = document.getElementById('grEditLink').value.trim(); 13508 var cijferVal = document.getElementById('grEditRating').value; 13509 var opmerkingVal = document.getElementById('grEditOpmerking').value.trim(); 13510 var dateStartVal = document.getElementById('grEditDateStart').value; 13511 var timeStartVal = document.getElementById('grEditTimeStart').value; 13512 var dateFinishVal= document.getElementById('grEditDateFinish').value; 13513 var timeFinishVal= document.getElementById('grEditTimeFinish').value; 13514 var duurVal = document.getElementById('grEditDuur').value.trim(); 13515 var dateKey = _dateKeyOrg || _palDateKey(entry['Datum Start']); 13516 /* Zonder gebied of dateKey vindt de backend de rij niet en wordt er stil 13517 niets opgeslagen. Dan liever een zichtbare fout. */ 13518 if (!_gebiedKey || !dateKey) { 13519 btn.disabled=false; btn.textContent=palLabels['gr-palmares-btn-save']; 13520 errEl.textContent=(palLabels['gr-palmares-error-save']||'Opslaan mislukt.'); 13521 errEl.style.display='block'; 13522 console.warn('[GR Palmares] Opslaan geweigerd: gebied/dateKey ontbreekt.', {gebied:_gebiedKey, dateKey:dateKey}); 13523 return; 13524 } 13525 postToScript({ 13526 action:'update_activity', email:myEmail, gebied:_gebiedKey, dateKey: dateKey, 13527 link: linkVal, cijfer: cijferVal, opmerking: opmerkingVal, 13528 datumStart: dateStartVal, tijdStart: timeStartVal, 13529 datumFinish: dateFinishVal, tijdFinish: timeFinishVal, 13530 duur: duurVal 13531 }, function(){ 13532 entry['URL'] = linkVal; 13533 entry['Cijfer'] = cijferVal; 13534 entry['Opmerking'] = opmerkingVal; 13535 if(dateStartVal) entry['Datum Start'] = dateStartVal + (timeStartVal ? ' ' + timeStartVal : ''); 13536 if(dateFinishVal !== undefined) entry['Datum Finish'] = dateFinishVal + (timeFinishVal ? ' ' + timeFinishVal : ''); 13537 if(duurVal) entry['Tijd'] = duurVal; 13538 var _m = document.getElementById('grPalEditModal'); 13539 if(_m) _m.style.display='none'; 13540 document.body.classList.remove('modal-open');
13541 try { localStorage.removeItem('gr_rides_v1'); } catch(e) {} 13542 /* NIET doorverwijzen: de sheet loopt achter op de zojuist weggeschreven 13543 wijziging, dus na een herlaad kreeg je de oude tekst terug. De entry 13544 hierboven is al bijgewerkt â opnieuw tekenen toont hem meteen. */ 13545 var list = document.getElementById('grPalList'); 13546 if (list) { list.innerHTML=''; shownCount = 0; renderStats(allEntries); renderBatch(); } 13547 /* Zorg dat je op het palmares-tabblad staat/blijft. */ 13548 if (window.GR_DASHBOARD_MODE) { 13549 if (typeof window._grSetDbTab === 'function') window._grSetDbTab('voltooid-palmares'); 13550 else { 13551 var sel = document.getElementById('dbViewSelect'); 13552 if (sel && sel.value !== 'voltooid-palmares') { sel.value='voltooid-palmares'; sel.dispatchEvent(new Event('change')); } 13553 } 13554 } 13555 /* Detailpaneel van deze activiteit weer openklappen zodat de nieuwe 13556 opmerking direct zichtbaar is. */ 13557 setTimeout(function(){ 13558 /* Zoek op het object zelf, niet op gebied â bij meerdere ritten in 13559 hetzelfde gebied opende anders de verkeerde kaart. */ 13560 var i = allEntries.indexOf(entry); 13561 if (i === -1) return; 13562 var d = document.getElementById('grPalDetail'+i); 13563 if (d && !d.classList.contains('open') && typeof window.grPalToggleDetail === 'function') { 13564 window.grPalToggleDetail(i); 13565 d.scrollIntoView({ behavior: 'smooth', block: 'center' }); 13566 } 13567 }, 80); 13568 }, function(){ 13569 btn.disabled=false; btn.textContent=palLabels['gr-palmares-btn-save']; errEl.textContent=palLabels['gr-palmares-error-save']; errEl.style.display='block'; 13570 }); 13571 }); 13572 /* ââ Render ride item ââ */ 13573 function renderItem(entry, idx){ 13574 var gebied =(entry['Gebied']||'').trim(); var type =(entry['Type']||'Road').trim(); 13575 var datum =parseDutchDate(entry['Datum Start']); 13576 var km =getKm(gebied,type); var hm =getHm(gebied,type); 13577 /* Zelfde terugval als in de Hall of Fame en de statsbalk: staat de kolom 13578 Tijd leeg, dan komt de duur uit begin- en eindtijdstip. Zonder dat stond 13579 er bij de nieuwste ritten een tijd van niets, terwijl begin en eind er 13580 gewoon in staan. */ 13581 var tijdStr =(window.GR&&GR.duurVan) ? GR.duurVan(entry).tekst : (entry['Tijd']||'').trim(); 13582 var link =(entry['URL']||'').trim(); if(!link||link==='https://'||link==='#') link=''; 13583 var cijfer =parseFloat(entry['Cijfer']); var opmerking=(entry['Opmerking']||'').trim(); 13584 var dateStr=String(datum.getDate()).padStart(2,'0')+' '+MONTH[datum.getMonth()]+' \''+String(datum.getFullYear()).slice(2); 13585 var typeClass=type.toLowerCase()==='gravel'?'eventgravel':type.toLowerCase().indexOf('gravel')>-1?'eventroadgravel':'eventroad'; 13586 var starsHtml='<div></div>'; 13587 if(!isNaN(cijfer)&&cijfer>0){ starsHtml='<div class="gr-pal-stars">'+renderStars(cijfer)+'<span class="gr-pal-stars-num">'+cijfer.toFixed(1)+'</span></div>'; } 13588 var slotHtml = _palVerborgen(entry) 13589 ? ' <span class="gr-pal-lock" title="'+esc(palLabels['gr-palmares-hidden-tooltip']||'Alleen zichtbaar voor jou')+'">'+ICON.lock+'</span>' 13590 : ''; 13591 var richting = (rondeAfstand[gebied] && rondeAfstand[gebied][type] && rondeAfstand[gebied][type].richting) ? rondeAfstand[gebied][type].richting : 'â²'; 13592 var statsHtml = '<span class="ride-route-stats"><div class="route-stats-block"><p><em>' + esc(type) + '</em>'; 13593 if (richting) statsHtml += '<em><strong>' + esc(richting) + '</strong></em>'; 13594 if (km) statsHtml += '<em>' + String(km).replace('.', ',') + 'km</em>'; 13595 if (hm) statsHtml += '<em><strong>â</strong></em><em>' + hm + 'hm</em>'; 13596 statsHtml += '</p></div></span>'; 13597 /* Geen detail-pills-container in de palmareslijst: type, km, hm, tijd en 13598 beoordeling staan al in de kaartkop (statsHtml en de sterren). */ 13599 var dc=''; 13600 if(opmerking) { dc += '<h4>'+palLabels['gr-palmares-label-opmerking']+'</h4><div class="detail-extra">' + esc(opmerking).replace(/\n/g, '<br>') + '</div>'; } 13601 var mapImg = (rondeAfstand[gebied] && rondeAfstand[gebied][type]) ? rondeAfstand[gebied][type].mapImg : ''; 13602 if (mapImg) { dc += '<div class="route-map-wrap"><img src="'+esc(mapImg)+'" class="route-map-img" style="width:100%; border-radius:12px;" alt="kaart" loading="lazy"></div>'; } 13603 else { dc += getMapEmbed(link); } 13604 /* Onderaan de uitklap een verwijzing naar de activiteit zelf. Hij stond al 13605 in het hamburgermenu, maar wie de details openklapt is juist aan het 13606 kijken wat die rit was â dan is een link die je ziet handiger dan eentje 13607 die je moet opzoeken. 13608 13609 Alleen als er een adres is ingevuld: zonder link valt er niets te bekijken 13610 en niets te geven. */ 13611 if(link){ 13612 dc += '<a class="gr-pal-activiteit-link" href="'+esc(link)+'" target="_blank" rel="noopener" onclick="event.stopPropagation();">' 13613 + ICON.globe + ' ' + esc(palLabels['gr-palmares-view-activity-kudos'] || 'Bekijk activiteit / Geef Kudo\'s') 13614 + '</a>'; 13615 } 13616 // Acties in een popover-menu achter het hamburger-icoon 13617 var _mi=''; 13618 if(!window.GR_PUBLIC_VIEW){ 13619 _mi+='<div class="gr-pal-action-option" onclick="event.stopPropagation();grPalCloseMenu('+idx+');grPalOpenEdit('+idx+')">'+ICON.edit+' '+(palLabels['gr-palmares-btn-edit']||'Bewerken')+'</div>'; 13620 } 13621 if(link){ 13622 _mi+='<a class="gr-pal-action-option" href="'+esc(link)+'" target="_blank" rel="noopener" onclick="event.stopPropagation();grPalCloseMenu('+idx+')">'+ICON.globe+' '+palLabels['gr-palmares-view-activity']+'</a>'; 13623 } 13624 /* Plannen alleen met Rondoneur-tag, gebiedstag of als admin */ 13625 if(window.GR_DASHBOARD_MODE&&!window.GR_PUBLIC_VIEW&&_palCanPlan(gebied)){ 13626 /* Zelfde route als vanuit de atlas-kaart: openPlanRondoModal(gebied, areaTag). 13627 Dat pad werkt bewezen; _grPlanRondoFromDashboard opende een andere 13628 modal en bleef onzichtbaar. Terugval blijft behouden. */ 13629 _mi+='<div class="gr-pal-action-option gr-pal-plan-link" data-gebied="'+esc(gebied)+'"' 13630 +' onclick="event.stopPropagation();grPalCloseMenu('+idx+');window.grPalPlanRondo(this.dataset.gebied)">' 13631 +ICON.calendar+' '+(palLabels['gr-planner-plan-rondo-tooltip']||'Plan deze Rondo')+'</div>'; 13632 } 13633 _mi+='<div class="gr-pal-action-option" onclick="event.stopPropagation();grPalCloseMenu('+idx+');grPalToggleDetail('+idx+')">'+ICON.info+' '+(palLabels['gr-palmares-btn-details']||'Details bekijken')+'</div>'; 13634 13635 return '<div class="ride-card" onclick="grPalToggleDetail('+idx+')">'
13636 +'<div class="ride-header gr-pal-ride-header">' 13637 +'<div class="header-date"><h4 class="date-pill '+typeClass+'">'+dateStr+'</h4></div>' 13638 +'<div class="header-info"><h3 class="ride-route-name">GRAN RONDO '+esc(gebied.toUpperCase())+slotHtml+'</h3>'+statsHtml+'</div>' 13639 +'<div class="gr-pal-rating-cell">'+starsHtml+'</div>' 13640 +'<div class="actions" onclick="event.stopPropagation();">' 13641 +'<div class="gr-pal-menu-wrapper">' 13642 +'<button type="button" class="btn-icon-svg" title="'+(palLabels['gr-planner-actions']||'Acties')+'" onclick="event.stopPropagation();grPalToggleMenu('+idx+')">'+ICON.menu+'</button>' 13643 +'<div id="grPalMenu'+idx+'" class="gr-pal-action-popover" style="display:none;" onclick="event.stopPropagation();">'+_mi+'</div>' 13644 +'</div>' 13645 +'</div>' 13646 +'</div>' 13647 +'<div class="ride-details" id="grPalDetail'+idx+'" onclick="event.stopPropagation();">'+dc+'</div>' 13648 +'</div>'; 13649 } 13650 function renderStats(entries){ 13651 var uniekeSet=new Set(),gebieden=new Set(),totSec=0,totKm=0,totHm=0; 13652 entries.forEach(function(e){ 13653 var g=(e['Gebied']||'').trim(),t=(e['Type']||'Road').trim(); 13654 uniekeSet.add(g+'__'+t); gebieden.add(g); 13655 /* Zelfde terugval als in de Hall of Fame: is de kolom Tijd leeg, dan komt 13656 de duur uit begin- en eindtijdstip. Anders telde het totaal aantal uren 13657 in je palmares alleen de ritten waar iemand de duur zelf had ingevuld. */ 13658 totSec+=(window.GR&&GR.duurVan) ? GR.duurVan(e).sec : parseTimeToSeconds(e['Tijd']||''); 13659 totKm+=getKm(g,t); totHm+=getHm(g,t); 13660 }); 13661 var totUren=Math.floor(totSec/3600); 13662 var stats=[ 13663 {lbl:palLabels['gr-palmares-total-rounds'], val:entries.length}, 13664 {lbl:palLabels['gr-palmares-unique-rounds'], val:uniekeSet.size}, 13665 {lbl:palLabels['gr-palmares-total-areas'], val:gebieden.size}, 13666 {lbl:palLabels['gr-palmares-total-km'], val:totKm}, 13667 {lbl:palLabels['gr-palmares-total-hm'], val:totHm}, 13668 {lbl:palLabels['gr-palmares-total-time'], val:totUren} 13669 ]; 13670 var sg=document.getElementById('grPalStatsGrid'); 13671 if(sg){ var _sc=window._grSetDbTab?' onclick="if(window._grSetDbTab)window._grSetDbTab(\'voltooid-palmares\')" style="cursor:pointer;"':''; sg.innerHTML=stats.map(function(s){ return '<div class="gr-pal-stat"'+_sc+'><span class="gr-pal-stat-lbl">'+esc(s.lbl)+'</span><span class="gr-pal-stat-val">'+esc(String(s.val))+'</span></div>'; }).join(''); _palToonStats(sg); } 13672 } 13673 13674 /* De statsbalk verschijnt pas als de profielkaart klaar is, zodat de linker 13675 kolom niet in twee stappen opbouwt. We kijken naar de DOM zelf â zodra 13676 #grProfileWidget een .gr-rider-card bevat â in plaats van naar een signaal 13677 uit een ander bestand, want welk script de kaart vult verschilt per pagina. */ 13678 function _palToonStats(sg) { 13679 if (!sg) return; 13680 var toon = function () { sg.style.display = 'flex'; }; 13681 var w = document.getElementById('grProfileWidget'); 13682 if (!w) { toon(); return; } // geen profielkaart op deze pagina 13683 if (w.querySelector('.gr-rider-card')) { toon(); return; } 13684 var gedaan = false, obs = null, klok = null; 13685 var af = function () { 13686 if (gedaan) return; 13687 gedaan = true; 13688 if (obs) obs.disconnect(); 13689 if (klok) clearTimeout(klok); 13690 toon(); 13691 }; 13692 if (typeof MutationObserver === 'function') { 13693 obs = new MutationObserver(function () { 13694 if (w.querySelector('.gr-rider-card')) af(); 13695 }); 13696 obs.observe(w, { childList: true, subtree: true }); 13697 } 13698 // Noodrem: profielkaart komt er niet (fout, gast, of ander script) â 13699 // de stats mogen dan alsnog verschijnen. 13700 klok = setTimeout(function () { 13701 if (!gedaan) console.warn('[GR] profielkaart bleef uit â stats alsnog getoond'); 13702 af(); 13703 }, 12000); 13704 } 13705 13706 function getDisplayEntries(){ 13707 var q=(searchQ||'').toLowerCase().trim(); 13708 var result = q ? allEntries.filter(function(e){ 13709 return (e['Gebied']||'').toLowerCase().indexOf(q)>-1; 13710 }) : allEntries.slice(); 13711 if(sortBy==='gebied') result.sort(function(a,b){ return (a['Gebied']||'').localeCompare(b['Gebied']||'','nl'); }); 13712 else if(sortBy==='beoordeling') result.sort(function(a,b){ return (Number(b['Cijfer'])||0)-(Number(a['Cijfer'])||0); }); 13713 else if(sortBy==='afstand') result.sort(function(a,b){ return getKm(b['Gebied']||'',b['Type']||'Road')-getKm(a['Gebied']||'',a['Type']||'Road'); }); 13714 // 'datum': allEntries already sorted date desc â slice() preserves order 13715 return result; 13716 } 13717 function renderBatch(){ 13718 var list=document.getElementById('grPalList');
13718 var lm=document.getElementById('grPalLoadMore'); 13719 if(!list) return; 13720 var displayed=getDisplayEntries(); 13721 var batch=displayed.slice(shownCount,shownCount+PAGE); 13722 batch.forEach(function(entry){ list.insertAdjacentHTML('beforeend',renderItem(entry,allEntries.indexOf(entry))); }); 13723 shownCount+=batch.length; 13724 if(shownCount>=displayed.length){ lm.style.display='none'; } 13725 else { PAGE=20; lm.style.display='block'; lm.innerHTML='<a href="#" id="grPalMoreBtn">'+(palLabels['gr-db-more-items']||palLabels['gr-palmares-load-more']||'Toon meer items...')+'</a>'; document.getElementById('grPalMoreBtn').addEventListener('click',function(e){ e.preventDefault(); renderBatch(); }); } 13726 } 13727 /* ââ Data laden ââ */ 13728 function _grLoadPalmaresData() { 13729 Promise.all([ 13730 fetch(ACT_SHEET_URL, { cache: 'no-store' }).then(function(r){return r.json();}), 13731 fetch('https://opensheet.elk.sh/1_Bc2komUMc7pVNT8rQkO0_Djnh41O5wCOvBMozarCms/routes', { cache: 'no-store' }).then(function(r){return r.json();}) 13732 ]).then(function(results){ 13733 var activiteiten=results[0],routes=results[1]; globalRouteMap = {}; 13734 (Array.isArray(routes)?routes:[]).forEach(function(row){ 13735 if(String(row['Join']||'').toUpperCase()!=='TRUE') return; 13736 var mapImg = '', km = 0, hm = 0, richting = 'â²'; 13737 for(var key in row) { 13738 var kl = key.toLowerCase(); 13739 if(kl.indexOf('map image')>-1 || kl.indexOf('mapimage')>-1 || kl.indexOf('kaartafbeelding')>-1 || 13740 kl.indexOf('afbeelding')>-1|| kl.indexOf('image')>-1 || kl.indexOf('img')>-1 || 13741 kl.indexOf('foto')>-1 || kl.indexOf('afb')>-1 || kl.indexOf('picture')>-1 || 13742 kl.indexOf('kaartje')>-1 || kl.indexOf('routekaart')>-1 || kl.indexOf('routefoto')>-1) { 13743 if(row[key]) mapImg = row[key]; 13744 } 13745 if(kl === 'km' || kl.indexOf('afstand') > -1) km = parseFloat(row[key]) || km; 13746 if(kl === 'hm' || kl.indexOf('hoogte') > -1) hm = parseFloat(row[key]) || hm; 13747 if(kl.indexOf('richting') > -1 && row[key]) richting = row[key]; 13748 } 13749 var g=(row['Gebied']||'').trim(),t=(row['Type']||'').trim(); 13750 if(!g||!t) return; 13751 if(!rondeAfstand[g]) rondeAfstand[g]={}; 13752 rondeAfstand[g][t]={km:km,hm:hm,mapImg:mapImg,richting:richting}; 13753 if(!globalRouteMap[g]) globalRouteMap[g] = []; 13754 if(globalRouteMap[g].indexOf(t) === -1) globalRouteMap[g].push(t); 13755 if(t==='Road-Gravel'){ 13756 if(!rondeAfstand[g]['Road']) rondeAfstand[g]['Road'] ={km:km,hm:hm,mapImg:mapImg,richting:richting}; 13757 if(!rondeAfstand[g]['Gravel']) rondeAfstand[g]['Gravel']={km:km,hm:hm,mapImg:mapImg,richting:richting}; 13758 if(globalRouteMap[g].indexOf('Road') === -1) globalRouteMap[g].push('Road'); 13759 if(globalRouteMap[g].indexOf('Gravel') === -1) globalRouteMap[g].push('Gravel'); 13760 } 13761 }); 13762 var em=(myEmail||'').trim().toLowerCase(); 13763 allEntries=(Array.isArray(activiteiten)?activiteiten:[]) 13764 .filter(function(e){ return (e['Gebied']||'').trim()&&(e['E-mailadres']||'').trim().toLowerCase()===em; }) 13765 .filter(function(e){ return !window.GR_PUBLIC_VIEW || !_palVerborgen(e); }) 13766 .map(function(e){ return {e:e,d:parseDutchDate(e['Datum Start'])}; }) 13767 .filter(function(o){ return !isNaN(o.d.getTime()); }) 13768 .sort(function(a,b){ return b.d-a.d; }) 13769 .map(function(o){ return o.e; }); 13770 var list=document.getElementById('grPalList'); var loading=document.getElementById('grPalLoading'); 13771 if(loading) loading.style.display='none'; 13772 // Geen lijst op deze pagina (bijv. de atlas op een andere pagina): niet 13773 // tekenen, maar de data staat wel klaar voor het activiteitenformulier. 13774 if(!list) return; 13775 if(!allEntries.length){ list.innerHTML='<p style="text-align:center;font-style:italic;padding:0px;">'+(palLabels['gr-palmares-no-activities']||'Nog geen activiteiten.')+'</p>'; return; } 13776 renderStats(allEntries); list.innerHTML=''; renderBatch(); 13777 _palWaitForAreaTags(); 13778 if(MAX_ITEMS === 0){ 13779 var ctrl=document.getElementById('grPalControls'); 13780 if(ctrl) ctrl.style.display='flex'; 13781 var searchEl=document.getElementById('grPalSearch'); 13782 var sortEl=document.getElementById('grPalSort'); 13783 if(searchEl) searchEl.addEventListener('input',function(){ 13784 searchQ=this.value; shownCount=0; 13785 document.getElementById('grPalList').innerHTML=''; renderBatch(); 13786 }); 13787 if(sortEl) sortEl.addEventListener('change',function(){ 13788 sortBy=this.value; shownCount=0; 13789 document.getElementById('grPalList').innerHTML=''; renderBatch(); 13790 }); 13791 } 13792 }).catch(function(err){ 13793 console.error('Palmares fout:',err); 13794 var list=document.getElementById('grPalList'); 13795 if(list) list.innerHTML='<p style="text-align:center;color:#c00;padding:30px;">'+(palLabels['gr-palmares-error-loading']||'Kon gegevens niet laden.')+'</p>'; 13796 }); 13797 } /* end _grLoadPalmaresData */ 13798 /* Hier stond _palOpenTabFromHash: dat keek naar #palmares en bleef tot twaalf 13799 seconden lang proberen de tab om te zetten zodra _grSetDbTab bestond. 13800 13801 Dat is vervallen. Elke tab heeft nu een eigen hash en _grInitDashboardTabs 13802 leest die meteen bij het openen. Twee stukken code die allebei de actieve 13803 tab zetten is bovendien om moeilijkheden vragen: klikte je binnen die twaalf 13804 seconden een andere tab aan, dan sprong je alsnog terug naar Palmares. */ 13805 13806 /* ââ Publiek profiel via ?user=NNNNN ââ */ 13807 (function(){ 13808 var _pubId = new URLSearchParams(window.location.search).get('user'); 13809 if(!_pubId){ _grLoadPalmaresData(); return; } 13810 /* Wie ben ik zelf? Nu vastleggen, want myEmail wordt hieronder overschreven 13811 met het adres van degene wiens profiel je bekijkt. */ 13812 var _ikZelf = String(myEmail || '').toLowerCase().trim(); 13813 window.GR_PUBLIC_VIEW = true; 13814 /* inject persistent CSS to hide controls immediately. 13815 De uitleg boven de palmareslijst hoort daar ook bij: "Voeg hier je 13816 voltooide rondo activiteiten toe" slaat nergens op als je naar het 13817 profiel van iemand anders kijkt. */ 13818 var _ps=document.createElement('style'); 13819 _ps.textContent='.circles-controls-bar{display:none!important;} #dbAddBtn3,.db-add-btn,.open-rit-modal-btn{display:none!important;} #grPalUitleg{display:none!important;}'; 13820 document.head.appendChild(_ps); 13821 fetch('https://opensheet.elk.sh/1z4oQxDzP6xwMxKY61Lp9X7Ky3wpQ27XjV79oIrJOtWo/Profiel').then(function(r){return r.json();}).then(function(rows){ 13822 var row=(Array.isArray(rows)?rows:[]).find(function(r){return String(r['ID']||'').trim()===String(_pubId).trim();}); 13823 if(row){ 13824 /* Je eigen profiel via ?user= is je eigen dashboard, maar dan uitgekleed: 13825 geen tabs, geen bewerkknoppen, geen toevoegen. Daar heb je niets aan, 13826 dus we sturen je door naar het gewone dashboard. replace() en niet 13827 assign(): met assign kom je met de terugknop weer in deze uitgeklede 13828 weergave terecht. */ 13829 var _doelMail=(row['E-mailadres']||'').toLowerCase().trim(); 13830 if(_doelMail && _ikZelf && _doelMail === _ikZelf){ 13831 var _u=new URL(window.location.href); 13832 _u.searchParams.delete('user'); 13833 _u.hash='#palmares'; 13834 window.location.replace(_u.toString()); 13835 return; 13836 } 13837 myEmail=_doelMail; 13838 var pubName=(row['Wat is je naam?']||row['Naam']||'').trim(); 13839 var pubAvatar=(row['Avatar URL']||'').trim();
13840 window.GR_PUBLIC_VIEW={name:pubName,avatarUrl:pubAvatar,_email:myEmail}; 13841 var _h2=document.querySelector('#shopify-section-template--27823587426678__rich_text_eNdxFK h2'); 13842 if(_h2&&pubName) _h2.textContent=(palLabels['gr-palmares-public-title']||"Rondo's â ")+pubName; 13843 /* notify dashboard-css.html (dat eerder of later kan zijn geladen) */ 13844 if(typeof window._grApplyPubProfile==='function') window._grApplyPubProfile(myEmail); 13845 setTimeout(function(){ 13846 document.querySelectorAll('.circles-controls-bar').forEach(function(el){el.style.setProperty('display','none','important');}); 13847 if(typeof window._grSetDbTab==='function'){window._grSetDbTab('voltooid-palmares');} 13848 else{var sel=document.getElementById('dbViewSelect');if(sel){sel.value='voltooid-palmares';sel.dispatchEvent(new Event('change'));}} 13849 },300); 13850 } else { 13851 var lst=document.getElementById('grPalList'); 13852 if(lst) lst.innerHTML='<p style="text-align:center;padding:30px;color:#888;">'+(palLabels['gr-palmares-user-not-found']||'Gebruiker niet gevonden.')+'</p>'; 13853 } 13854 _grLoadPalmaresData(); 13855 }).catch(function(){ _grLoadPalmaresData(); }); 13856 })(); 13857 /* ââ Modals losmaken van de tab ââââââââââââââââââââââââââââââââââââââ 13858 In dashboard-html staan #ritModal en #grPalEditModal binnen 13859 #palmaresTabSection. Die krijgt display:none zodra een andere tab actief 13860 is, en een display:flex op een kind van een display:none ouder rendert 13861 niets â de popup bleef daardoor onzichtbaar buiten de Palmares-tab. 13862 Het zijn position:fixed overlays, dus ze horen sowieso in <body>. */ 13863 (function _palDetachModals(){ 13864 ['ritModal','grPalEditModal'].forEach(function(id){ 13865 var m=document.getElementById(id); 13866 if(m && m.parentNode && m.parentNode!==document.body){ 13867 document.body.appendChild(m); /* verplaatst incl. listeners */ 13868 } 13869 }); 13870 })(); 13871 13872 /* ââ Add Rondo modal init ââ */ 13873 /* De modals staan in gr-shared-modals.html (footer). Stond dat snippet later 13874 in de footer dan dit script, dan was een eenmalig opgehaalde referentie 13875 null en deed de knop niets. Daarom elke keer opnieuw opzoeken. */ 13876 function addModalEl(){ return document.getElementById('ritModal'); } 13877 var profileChecked=false, formInitialized=false; 13878 document.addEventListener('click',function(e){ 13879 if(!e.target.closest || !e.target.closest('.open-rit-modal-btn')) return; 13880 var m=addModalEl(); 13881 if(!m){ console.warn('[GR Palmares] #ritModal ontbreekt â staat gr-shared-modals.html in de footer?'); return; } 13882 m.style.display='flex'; document.body.classList.add('modal-open'); 13883 if(myEmail&&!profileChecked) verifyProfile(); 13884 }); 13885 var _closeRitBtn=document.getElementById('closeRitModalBtn'); 13886 if(_closeRitBtn) _closeRitBtn.addEventListener('click',function(){ var m=addModalEl(); if(m){ m.style.display='none'; document.body.classList.remove('modal-open'); } }); 13887 document.addEventListener('click',function(e){ var m=addModalEl(); if(m && e.target===m){ m.style.display='none'; document.body.classList.remove('modal-open'); } }); 13888 function verifyProfile(){ 13889 /* Elementen zitten in de modal uit gr-shared-modals.html; ontbreken ze, 13890 dan mag dat geen onafgevangen fout geven. */ 13891 var _el = function(id){ return document.getElementById(id); }; 13892 fetch('https://opensheet.elk.sh/1z4oQxDzP6xwMxKY61Lp9X7Ky3wpQ27XjV79oIrJOtWo/Profiel').then(function(r){return r.json();}) 13893 .then(function(data){ 13894 var found=data.find(function(row){ return (row['E-mailadres']||'').toLowerCase()===(myEmail||'').toLowerCase(); }); 13895 var loader=_el('profileCheckLoader'); if(loader) loader.style.display='none'; 13896 profileChecked=true; 13897 if(found&&(found['Wat is je naam?']||'').trim()){ 13898 var wrap=_el('formContainerWrapper'); if(wrap) wrap.style.display='block'; 13899 initAddForm(); 13900 } else { 13901 var miss=_el('profileMissingMsg'); if(miss) miss.style.display='block'; 13902 } 13903 }).catch(function(){ 13904 var loader=_el('profileCheckLoader'); 13905 if(loader) loader.innerHTML='<span style="color:red;">'+(palLabels['gr-palmares-error-load']||'Fout bij laden.')+'</span>'; 13906 }); 13907 } 13908 function initAddFormSafe(){ try { initAddForm(); } catch(e) { console.warn('[GR Palmares] formulier vullen mislukt:', e); } } 13909 function initAddForm(){ 13910 if(formInitialized) return; 13911 var sel=document.getElementById('areaInput'); if(!sel) return; 13912 sel.innerHTML='<option value="">'+addLabels['gr-planner-choose-rondo']+'</option>';
13913 Object.keys(globalRouteMap).sort().forEach(function(area){ var o=document.createElement('option'); o.value=o.textContent=area; sel.appendChild(o); }); 13914 formInitialized=true; 13915 } 13916 /* Plan deze Rondo â exact dezelfde aanroep als de atlas-kaart doet. */ 13917 window.grPalPlanRondo = function(gebied){ 13918 var areaTag = _palAreaTagFor(gebied) || ''; 13919 if (typeof window.openPlanRondoModal === 'function') { 13920 window.openPlanRondoModal(gebied, areaTag); 13921 return; 13922 } 13923 if (typeof window._grPlanRondoFromDashboard === 'function') { window._grPlanRondoFromDashboard(); return; } 13924 if (typeof window._grOpenRitModal === 'function') { window._grOpenRitModal(null); return; } 13925 console.warn('[GR Palmares] Geen planner beschikbaar op deze pagina.'); 13926 }; 13927 13928 /* ââ Bridges voor externe scripts (o.a. GR Atlas kaart) ââ */ 13929 /* Opent het "Activiteit toevoegen" formulier incl. profielcheck en gebied-preselect */ 13930 window.grPalOpenActivityForm=function(gebied){ 13931 var _am=addModalEl(); 13932 if(!_am){ console.warn('[GR Palmares] #ritModal ontbreekt'); return false; } 13933 window._pendingVoltooidRide=null; window._pendingVoltooidId=null; 13934 _am.style.display='flex'; document.body.classList.add('modal-open'); 13935 if(myEmail&&!profileChecked) verifyProfile(); 13936 else if(profileChecked&&!formInitialized) initAddForm(); 13937 if(!gebied) return true; 13938 var tries=0; 13939 (function pre(){ 13940 var sel=document.getElementById('areaInput'); 13941 if(sel&&sel.options.length>1){ 13942 for(var i=0;i<sel.options.length;i++){ 13943 if((sel.options[i].value||'').toLowerCase()===String(gebied).toLowerCase()){ 13944 sel.value=sel.options[i].value; 13945 sel.dispatchEvent(new Event('change',{bubbles:true})); 13946 return; 13947 } 13948 } 13949 return; 13950 } 13951 if(++tries<50) setTimeout(pre,100); 13952 })(); 13953 return true; 13954 }; 13955 /* Opent de bewerk-popup van een bestaande activiteit op gebied (+ evt. datum) */ 13956 /* allEntries is pas gevuld nadat de palmares-lijst zijn data heeft opgehaald. 13957 Wordt de bewerkknop van buitenaf aangeroepen (bijvoorbeeld vanuit de atlas) 13958 terwijl dat nog niet gebeurd is, dan halen we de activiteiten hier alsnog 13959 op. Zo werkt bewerken ongeacht welke dashboard-tab openstaat. */ 13960 function _palEnsureEntries(cb){ 13961 if(allEntries.length){ cb(true); return; } 13962 fetch(ACT_SHEET_URL, { cache: 'no-store' }).then(function(r){ return r.json(); }).then(function(rows){ 13963 var em=(myEmail||'').trim().toLowerCase(); 13964 allEntries=(Array.isArray(rows)?rows:[]) 13965 .filter(function(e){ return (e['Gebied']||'').trim()&&(e['E-mailadres']||'').trim().toLowerCase()===em; }) 13966 .filter(function(e){ return !window.GR_PUBLIC_VIEW || !_palVerborgen(e); }) 13967 .map(function(e){ return {e:e,d:parseDutchDate(e['Datum Start'])}; }) 13968 .filter(function(o){ return !isNaN(o.d.getTime()); }) 13969 .sort(function(a,b){ return b.d-a.d; }) 13970 .map(function(o){ return o.e; }); 13971 cb(allEntries.length>0); 13972 }).catch(function(err){ 13973 console.warn('[GR Palmares] Activiteiten laden mislukt:',err); 13974 cb(false); 13975 }); 13976 } 13977 13978 function _palFindIdx(gebied,datumStart){ 13979 var g=String(gebied||'').trim().toLowerCase(); 13980 var d=String(datumStart||'').trim(); 13981 var idx=-1; 13982 for(var i=0;i<allEntries.length;i++){ 13983 if((allEntries[i]['Gebied']||'').trim().toLowerCase()!==g) continue; 13984 if(!d){ idx=i; break; } 13985 if(String(allEntries[i]['Datum Start']||'').trim()===d){ idx=i; break; } 13986 if(idx===-1) idx=i; /* zelfde gebied, andere datum â bewaar als fallback */ 13987 } 13988 return idx; 13989 } 13990 13991 window.grPalOpenEditByGebied=function(gebied,datumStart){ 13992 /* Zonder de bewerk-popup in de DOM kunnen we niets; laat de aanroeper dan 13993 zelf een alternatief kiezen. */ 13994 if(!document.getElementById('grPalEditModal')) return false; 13995 13996 var idx=_palFindIdx(gebied,datumStart); 13997 if(idx!==-1){ window.grPalOpenEdit(idx); return true; } 13998 13999 /* Nog geen data ingeladen â alsnog ophalen en daarna openen */ 14000 _palEnsureEntries(function(ok){ 14001 if(!ok) { console.warn('[GR Palmares] Geen activiteiten gevonden voor',gebied); return; } 14002 var i=_palFindIdx(gebied,datumStart); 14003 if(i!==-1) window.grPalOpenEdit(i); 14004 else console.warn('[GR Palmares] Activiteit niet gevonden:',gebied,datumStart); 14005 }); 14006 return true; 14007 }; 14008 14009 var areaEl=document.getElementById('areaInput'),routeEl=document.getElementById('routeTypeInput'),routeSec=document.getElementById('routeSection'); 14010 if(areaEl) areaEl.addEventListener('change',function(){ 14011 var area=this.value; routeEl.innerHTML='<option value="">'+(addLabels['gr-planner-choose-type']||'Kies type')+'</option>'; 14012 if(area&&globalRouteMap[area]&&globalRouteMap[area].length){ 14013 routeSec.style.display='block';
14014 globalRouteMap[area].forEach(function(t){ var o=document.createElement('option'); o.value=o.textContent=t; routeEl.appendChild(o); }); 14015 if(globalRouteMap[area].length===1) routeEl.value=globalRouteMap[area][0]; 14016 } else { routeSec.style.display='none'; } 14017 }); 14018 var startEl=document.getElementById('dateStartInput'),finishEl=document.getElementById('dateFinishInput'),durEl=document.getElementById('durationInput'); 14019 /* De duur werd berekend uit alleen de twee datumvelden. Op één dag zijn die 14020 gelijk, dus f > s ging niet op en bleef de duur leeg â ook als je netjes 14021 9:30 en 16:35 had ingevuld. Die lege duur belandde in de kolom Tijd, en 14022 daardoor stonden records in de Hall of Fame op nul. 14023 Nu tellen de tijdvelden mee. Staat er geen tijd, dan geldt middernacht en 14024 verandert er niets aan het oude gedrag. */ 14025 var startTijdEl=document.getElementById('timeStartInput'), finishTijdEl=document.getElementById('timeFinishInput'); 14026 function _samen(datumEl, tijdEl){ 14027 if(!datumEl||!datumEl.value) return null; 14028 var t=(tijdEl&&tijdEl.value) ? tijdEl.value : '00:00'; 14029 var d=new Date(datumEl.value+'T'+t); 14030 return isNaN(d.getTime()) ? null : d; 14031 } 14032 function calcDur(){ 14033 if(!durEl) return; 14034 var s=_samen(startEl,startTijdEl), f=_samen(finishEl,finishTijdEl); 14035 if(s&&f&&f>s){ durEl.value=formatHMS(Math.floor((f-s)/1000)); } else { durEl.value=''; } 14036 } 14037 if(startEl) startEl.addEventListener('change',function(){ if(finishEl) finishEl.min=this.value; calcDur(); }); 14038 if(finishEl) finishEl.addEventListener('change',calcDur); 14039 if(startTijdEl) startTijdEl.addEventListener('change',calcDur); 14040 if(finishTijdEl) finishTijdEl.addEventListener('change',calcDur); 14041 var addForm=document.getElementById('activityForm'); 14042 if(addForm) addForm.addEventListener('submit',function(e){ 14043 e.preventDefault(); 14044 var btn=document.getElementById('submitBtn'); btn.disabled=true; btn.textContent=addLabels['gr-planner-btn-loading']; document.getElementById('addErrorMsg').style.display='none'; 14045 var rankEl=document.querySelector('input[name="ranking"]:checked'); 14046 var dStart = startEl ? startEl.value : ''; var tStart = document.getElementById('timeStartInput') ? document.getElementById('timeStartInput').value : ''; 14047 var dFinish = finishEl ? finishEl.value : ''; var tFinish = document.getElementById('timeFinishInput') ? document.getElementById('timeFinishInput').value : ''; 14048 // Tag bepalen: vanuit geplande rit â rsvpTag of areatag; handmatig â areatag van gebied 14049 var _actTag = ''; 14050 var _pendingRide = window._pendingVoltooidRide || null; 14051 if (_pendingRide) { 14052 _actTag = (_pendingRide.rsvpTag || '').trim().toLowerCase(); 14053 // areaTags is een let-globale in planner-script1 en staat dus niet op 14054 // window; _palAreaTagFor() pakt hem wel op (en matcht hoofdletterloos). 14055 if (!_actTag && _pendingRide.rondo) { 14056 _actTag = _palAreaTagFor(_pendingRide.rondo) || ''; 14057 } 14058 } else if (areaEl && areaEl.value) { 14059 _actTag = _palAreaTagFor(areaEl.value) || ''; 14060 } 14061 postToScript({ 14062 action:'submit_activity',email:myEmail, 14063 gebied:areaEl?areaEl.value:'',routeType:routeEl?routeEl.value:'', 14064 datumStart:dStart,tijdStart:tStart, datumFinish:dFinish, tijdFinish:tFinish, 14065 duur:durEl?durEl.value:'', link:document.getElementById('linkInput').value, 14066 opname:rankEl?rankEl.value:'Ja', cijfer:document.getElementById('ratingInput').value, 14067 opmerking:document.getElementById('remarksInput').value, 14068 tag: _actTag, 14069 /* Komt de rit uit Strava, dan gaat het activiteitsnummer mee. saveActivity_ 14070 schrijft dat in de kolom strava_id, zodat later te zien is wat 14071 geïmporteerd is en wat met de hand is ingevoerd. */ 14072 ...(window.GR_STRAVA_HUIDIG ? { stravaId: window.GR_STRAVA_HUIDIG.id, bron: 'strava-import' } : {}) 14073 }, function(){ 14074 /* Zit er nog een Strava-rit in de wachtrij, dan schuift die nu in het 14075 formulier in plaats van dat de pagina herlaadt. Herladen halverwege zou 14076 de rest van de selectie weggooien. */ 14077 if (window.GR_STRAVA_WACHTRIJ && window.GR_STRAVA_WACHTRIJ.length && 14078 typeof window._grStravaVolgende === 'function') { 14079 window._grStravaVolgende(); 14080 return; 14081 } 14082 window.GR_STRAVA_HUIDIG = null; 14083 /* Drie seconden wachten was marge voor de server, maar postToScript leest 14084 het antwoord van Apps Script echt uit: staan we hier, dan is het al 14085 opgeslagen. Wat overblijft is even de bevestiging kunnen lezen, en 14086 daar is 1,2 seconde genoeg voor. */ 14087 addForm.style.display='none'; document.getElementById('addSuccessMsg').style.display='block'; setTimeout(function(){ window.grHerlaadPagina('#palmares'); },1200); 14088 }, function(){ 14089 btn.disabled=false; btn.textContent=addLabels['gr-planner-submit-upper']; document.getElementById('addErrorMsg').style.display='block'; 14090 }); 14091 }); 14092})(); 14093</script>
14093 14094 14095 14096 14097 14098 14099<!-- Ook zichtbaar voor uitgelogde bezoekers --> 14100<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css" /> 14101<style> 14102 html.modal-open, body.modal-open { overflow: hidden !important; } 14103 /* Schermbreed, ook als het thema de sectie in een smalle container zet: 14104 100vw plus een negatieve marge die de container-inspringing opheft. 14105 100vw telt de scrollbar mee, vandaar overflow-x hidden op de wrap. */ 14106 #gr-atlas-wrap { 14107 width: 100vw; max-width: 100vw; margin-left: calc(50% - 50vw); 14108 margin-right: calc(50% - 50vw); padding: 0; overflow-x: hidden; 14109 font-family: 'ashemore', sans-serif; 14110 } 14111 14112 /* ââ Map + Panel naast elkaar (desktop) âââââââââââââââââââââââââ */ 14113 #gr-atlas-map-container { display: flex; align-items: stretch; } 14114 14115 #gr-atlas-map { 14116 flex: 1; height: 750px; position: relative; 14117 border-radius: 16px; overflow: hidden; 14118 border: none; 14119 /* isolation maakt van de kaart een eigen stapellaag. Zonder dit lekken de 14120 z-indexen die Leaflet binnenin gebruikt â besturing en attributie staan 14121 op 1000 â naar buiten en komen ze bovenop de sticky header, die maar op 14122 3 staat. Met isolatie tellen die 1000-en alleen nog onderling mee en 14123 zakt het geheel netjes onder het menu. 14124 14125 Bewust op #gr-atlas-map en niet op #gr-atlas-wrap: het zijpaneel en zijn 14126 achtergrond zijn siblings van de kaart en moeten juist wél over de rest 14127 van de pagina heen kunnen. Die vallen zo buiten de isolatie. */ 14128 isolation: isolate; 14129 } 14130 #gr-atlas-map.panel-open { 14131 border-radius: 16px 0 0 16px; 14132 } 14133 14134 /* Detailinfo bij een event; eigen klassen omdat .detail-pill uit planner-css 14135 komt en dat bestand niet op elke pagina met de kaart meelaadt. */ 14136 .gr-atlas-detail-pills { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 0; } 14137 .gr-atlas-detail-pill { 14138 display: inline-block; padding: 4px 10px; border-radius: 999px; 14139 background: var(--color-lighter, #EFF1FD); color: var(--color-dark, #271D62); 14140 font-size: 0.78em; font-weight: 600; line-height: 1.3; white-space: nowrap; 14141 } 14142 .gr-atlas-detail-loc { margin: 10px 0 0; font-size: 0.85em; color: var(--color-dark, #271D62); } 14143 .gr-atlas-detail-loc strong { font-weight: 800; } 14144 .gr-atlas-detail-loc a { color: inherit; text-decoration: underline; } 14145 /* Zelfde kopstijl als .ride-details h4 in planner-css. */ 14146 .gr-atlas-detail-kop { 14147 margin: 16px 0 4px; font-weight: 800; opacity: 0.9; 14148 font-size: 0.9em; color: var(--color-dark, #271D62); 14149 } 14150 .gr-atlas-detail-extra { 14151 margin: 0; font-size: 0.85em; line-height: 1.45; 14152 color: var(--color-dark, #271D62); 14153 } 14154 .gr-atlas-detail-extra a { color: var(--color-action, #E84B20); } 14155 14156 /* Tickets boeken â zelfde maat als de andere twee paneelknoppen. */ 14157 /* Was een <button>, is nu een <a> die rechtstreeks naar de eventpagina gaat. 14158 Vandaar de drie regels onderaan: een link krijgt anders een streep eronder 14159 en houdt zich niet aan de hoofdletters en letterafstand van de andere 14160 pillen in deze rij. */ 14161 .gr-atlas-btn-ticket { 14162 display: flex; align-items: center; justify-content: center; gap: 6px; 14163 width: 100%; padding: 7px; background: var(--color-action, #E84B20); 14164 color: #fff; border: none; border-radius: 999px; cursor: pointer; align-content: center; 14165 font-family: "rum raisin", sans-serif; font-size: 1.2rem !important; line-height: 1.5rem; 14166 text-align: center; box-sizing: border-box; transition: opacity .2s; 14167 text-decoration: none; text-transform: uppercase; letter-spacing: 0.1em; 14168 } 14169 .gr-atlas-btn-ticket:hover { opacity: .88; } 14170 14171 /* Event in het kaartpaneel â zelfde opbouw als een kaart in de planner: 14172 datumpills, titel, eventnaam in brandkleur, route stats. 14173 De kleurklassen (.eventroad enz.) staan in planner-css, maar die laadt niet 14174 op elke pagina; daarom hier herhaald met dezelfde CSS-variabelen. */ 14175 .gr-atlas-date-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 19px; } 14176 .gr-atlas-date-pill { 14177 display: inline-block; margin: 0; padding: 6px 12px; border-radius: 999px; 14178 font-size: 15px; font-weight: 700; line-height: 1.2; 14179 text-transform: uppercase; white-space: nowrap; 14180 color: var(--color-dark, #271D62); background: var(--color-lighter, #EFF1FD); 14181 } 14182 .gr-atlas-date-pill.eventgravel { background: var(--color-gravel, #E7D9C4); } 14183 .gr-atlas-date-pill.eventroadgravel { background: var(--color-brand-light, #FBD8CE); } 14184 .gr-atlas-date-pill.eventroad { background: var(--color-lighter, #EFF1FD); } 14185 .gr-atlas-event-pill { 14186 color: var(--color-brand, #E84B20); 14187 margin: 6px 0 10px; font-size: 1em; font-weight: 700; line-height: 1.25; 14188 } 14189 14190 /* ââ Filterknoppen linksboven ââ 14191 z-index boven de Leaflet-panes (400) maar onder de statuspil (1000). */ 14192 /* Gecentreerd boven de kaart, alle vier naast elkaar. Stond eerder linksboven 14193 met flex-wrap, waardoor de selectiebox op smalle kaarten naar een tweede 14194 regel sprong. nowrap houdt ze op één rij; de knoppen zijn klein genoeg dat 14195 dat ook op mobiel past. De zoomknoppen zitten rechtsonder, dus de vroegere 14196 max-width die daar ruimte voor hield is niet meer nodig. */ 14197 #gr-atlas-filters { 14198 position: absolute; top: 12px; left: 50%; transform: translateX(-50%); 14199 z-index: 900; 14200 display: flex; flex-wrap: nowrap; justify-content: center; align-items: center; 14201 gap: 6px; max-width: calc(100% - 24px); 14202 } 14203 .gr-atlas-filter-btn { 14204 /* Op desktop het oorspronkelijke formaat. Let op: deze 0.78em komt hier niet 14205 in beeld â het thema heeft `a.button, button { font-size: 1.8rem 14206 !important }` en die wint, dus de knop rendert op 18px. Op de live kaart 14207 gemeten. De regel blijft staan als terugval mocht die themaregel ooit 14208 verdwijnen; het verkleinen gebeurt in de mediaquery onderaan, en dáár is 14209 !important wél nodig. */ 14210 font-family: 'ashemore', sans-serif; font-size: 0.78em; font-weight: 700; 14211 padding: 7px 14px; border-radius: 999px; cursor: pointer; 14212 background: rgba(255,255,255,.95); color: var(--color-dark, #271D62); 14213 border: 1.5px solid rgba(39,29,98,.18); 14214 box-shadow: 0 2px 8px rgba(0,0,0,.13); 14215 transition: background .15s, color .15s, border-color .15s; 14216 line-height: 1.2; white-space: nowrap; 14217 } 14218 .gr-atlas-filter-btn:hover { border-color: var(--color-dark, #271D62); } 14219 .gr-atlas-filter-btn.aan { 14220 background: var(--color-dark, #271D62); color: #fff; 14221 border-color: var(--color-dark, #271D62); 14222 } 14223 /* Selectiebox Alle / Todo / Voltooid / Bucketlist â zelfde pil als de 14224 knoppen. appearance:none haalt de systeempijl weg; het chevron hieronder 14225 is een inline SVG, dus geen extra verzoek. */ 14226 .gr-atlas-filter-select { 14227 font-family: 'rum raisin', sans-serif; font-size: 2em; font-weight: 700; 14228 text-transform: uppercase; letter-spacing: .1em; 14229 /* rechts wat extra ruimte: letter-spacing zet ook achter de laatste letter 14230 een spatie, die anders tegen het pijltje aan komt te staan. */ 14231 padding: 7px 1.6em 7px 0.7em; border-radius: 999px; cursor: pointer; 14232 background-color: rgba(255,255,255,.95); color: var(--color-dark, #271D62); 14233 border: 1.5px solid rgba(39,29,98,.18); 14234 box-shadow: 0 2px 8px rgba(0,0,0,.13); 14235 transition: background-color .15s, color .15s, border-color .15s; 14236 line-height: 1.2; white-space: nowrap; height: auto; 14237 -webkit-appearance: none; -moz-appearance: none; appearance: none; 14238 background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23271D62' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); 14239 background-repeat: no-repeat; background-position: right 0.55em center; 14240 background-size: 0.5em 0.5em; 14241 } 14242 .gr-atlas-filter-select:hover { border-color: var(--color-dark, #271D62); } 14243 .gr-atlas-filter-select.aan { 14244 background-color: var(--color-dark, #271D62); color: #fff; 14245 border-color: var(--color-dark, #271D62); 14246 background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); 14247 } 14248 /* De lijst zelf valt buiten de pil terug op systeemkleuren. */ 14249 .gr-atlas-filter-select option { background: #fff; color: var(--color-dark, #271D62); } 14250 /* Melding als een filter niets oplevert; onder de knoppen, zelfde hoek. */ 14251 /* Onder de knoppen, dus ook gecentreerd. */ 14252 #gr-atlas-filter-leeg { 14253 position: absolute; top: 52px; left: 50%; transform: translateX(-50%); 14254 text-align: center; z-index: 900; 14255 background: rgba(255,255,255,.95); color: #666; 14256 font-size: 0.78em; padding: 7px 13px; border-radius: 10px; 14257 box-shadow: 0 2px 8px rgba(0,0,0,.13); pointer-events: none; 14258 max-width: calc(100% - 24px); 14259 } 14260 @media (max-width: 700px) { 14261 #gr-atlas-filters { top: 8px; gap: 4px; max-width: calc(100% - 16px); } 14262 /* Alleen op mobiel een kwart kleiner, zodat alle vier naast elkaar passen. 14263 Op desktop houden ze hun oorspronkelijke formaat. 14264 14265 Het !important is hier onvermijdelijk: het thema zet 14266 `a.button, button { font-size: 1.8rem !important }` en zonder deze 14267 tegenhanger blijft de knop op 18px staan terwijl de selectiebox â geen 14268 <button>, dus buiten die regel â wél meekrimpt. Precies dat scheve beeld 14269 leverde de vorige poging op. Zelfde waarde als de selectiebox hieronder, 14270 dus de vier blijven onderling gelijk. */
14271 .gr-atlas-filter-btn { font-size: 1.5em !important; padding: 4px 8px; } 14272 .gr-atlas-filter-select { font-size: 1.5em; padding: 4px 1.4em 4px 0.6em; } 14273 #gr-atlas-filter-leeg { top: 62px; } 14274 } 14275 14276 /* Midden in de kaart: daar kijk je tijdens het laden toch al naartoe. 14277 translate(-50%,-50%) centreert op beide assen. */ 14278 #gr-atlas-status { 14279 position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); 14280 background: rgba(255,255,255,.95); padding: 10px 18px; border-radius: 999px; 14281 font-size: 0.85em; color: #444; z-index: 1000; pointer-events: none; white-space: nowrap; 14282 display: flex; align-items: center; gap: 10px; 14283 box-shadow: 0 4px 18px rgba(0,0,0,.16); 14284 } 14285 /* Spinner in de statuspil. Wordt door het script aan- en uitgezet via de 14286 klasse .gr-atlas-bezig, zodat een foutmelding niet blijft draaien. */ 14287 #gr-atlas-status::before { 14288 content: ''; width: 15px; height: 15px; border-radius: 50%; 14289 border: 2px solid #d8d8e4; border-top-color: var(--color-dark, #271D62); 14290 animation: grAtlasSpin .7s linear infinite; 14291 flex-shrink: 0; display: none; 14292 } 14293 #gr-atlas-status.gr-atlas-bezig::before { display: block; } 14294 @keyframes grAtlasSpin { to { transform: rotate(360deg); } } 14295 @media (prefers-reduced-motion: reduce) { 14296 #gr-atlas-status::before { animation: none; } 14297 } 14298 14299 /* ââ Zijpaneel (desktop) ââââââââââââââââââââââââââââââââââââââââ */ 14300 #gr-atlas-panel { 14301 display: none; width: 360px; min-width: 320px; 14302 height: auto; max-height: 750px; overflow-y: auto; overflow-x: hidden; 14303 background: #fff; border: 2px solid #e5e5f0; border-left: none; 14304 border-radius: 0 16px 16px 0; padding: 18px 20px 28px; 14305 box-sizing: border-box; position: relative; 14306 font-family: 'ashemore', sans-serif; color: #271D62; 14307 } 14308 #gr-atlas-panel.open { display: block; } 14309 14310 /* ââ Mobiel ââââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 14311 @media (max-width: 768px) { 14312 #gr-atlas-map { 14313 height: 60vh !important; max-height: 60vh; 14314 border-radius: 16px !important; border: none !important; 14315 } 14316 #gr-atlas-map.panel-open { border-radius: 16px !important; } 14317 /* Panel = centred overlay op mobiel */ 14318 #gr-atlas-panel { 14319 position: fixed !important; inset: auto !important; 14320 top: 50% !important; left: 50% !important; 14321 transform: translate(-50%, -50%) !important; 14322 width: 95vw !important; height: auto !important; max-height: 92vh !important; 14323 /* Zonder eigen scroll groeit het paneel door en schuift de bovenkant 14324 buiten beeld, want translate(-50%,-50%) centreert het geheel. */ 14325 overflow-y: auto !important; -webkit-overflow-scrolling: touch; 14326 max-width: 95vw !important; min-width: unset !important; 14327 border-radius: 20px !important; border: none !important; 14328 box-shadow: 0 8px 40px rgba(0,0,0,.28); z-index: 2000; 14329 } 14330 #gr-atlas-backdrop { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 1999; } 14331 #gr-atlas-backdrop.open { display: block; } 14332 } 14333 14334 /* ââ Legenda âââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 14335 .gr-atlas-legend { display: flex; gap: 18px; flex-wrap: wrap; margin: 14px 0 0; font-size: 0.88em; } 14336 .gr-atlas-legend span { display: flex; align-items: center; gap: 6px; } 14337 .gr-atlas-dot { width: 16px; height: 16px; border-radius: 50%; display: inline-block; border: 2px solid rgba(0,0,0,.2); flex-shrink: 0; } 14338 14339 /* ââ Panel content âââââââââââââââââââââââââââââââââââââââââââââââ */ 14340 /* Hamburger actie-menu op de plek van het oude kruisje */ 14341 .gr-atlas-panel-menu { 14342 position: absolute; top: 20px; right: 14px; z-index: 3; 14343 display: flex; align-items: center; gap: 2px; 14344 } 14345 /* Kruisje rechts van de hamburger, op elk formaat. Zelfde knop en icoonmaat 14346 als de hamburger, dus ook dezelfde lijndikte. Sluiten staat niet meer in 14347 het menu, dus dit is de enige knop ervoor. */ 14348 .gr-atlas-panel-menu .btn-icon-svg { 14349 background: none; border: none; cursor: pointer; padding: 6px; 14350 display: flex; align-items: center; justify-content: center; 14351 opacity: 0.6; transition: opacity 0.2s; border-radius: 6px; 14352 } 14353 .gr-atlas-panel-menu .btn-icon-svg:hover { opacity: 1; } 14354 .gr-atlas-panel-menu .btn-icon-svg svg {
14355 width: 20px; height: 20px; stroke: var(--color-dark, #271D62); 14356 fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; 14357 } 14358 14359 /* Titel: Rum Raisin, uppercase, vet */ 14360 .gr-atlas-popup-title { 14361 display: block; font-weight: 700; font-size: 1.7rem; 14362 font-family: 'Rum Raisin', sans-serif; text-transform: uppercase; 14363 color: var(--color-dark, #271D62); margin: 0 0 4px; 14364 padding-right: 44px; line-height: 1.25; 14365 } 14366 14367 /* Stats: één regel, ROAD ...KM GRAVEL ...KM */ 14368 .gr-atlas-popup-meta { 14369 display: flex; flex-wrap: wrap; gap: 0 28px; 14370 font-family: 'Rum Raisin', sans-serif; 14371 font-weight: 400; font-size: 1.2rem; 14372 margin-top: 2px; margin-bottom: 12px; 14373 align-items: baseline; 14374 } 14375 .gr-atlas-stat-item { white-space: nowrap; } 14376 14377 /* Kaartje (zelfde als planner detailpanel) */ 14378 .route-map-wrap { border-radius: 12px; overflow: hidden; margin: 10px 0 14px; } 14379 .route-map-img { width: 100%; aspect-ratio: 3/2; object-fit: cover; display: block; } 14380 14381 /* Voltooid melding (fallback als geen mini-kaart) */ 14382 .gr-atlas-popup-voltooid { font-size: 1.2rem; margin: 0 0 12px; } 14383 14384 /* Icoontjes + voltooid-label onder mini-kaart */ 14385 .gr-atlas-panel-actions { 14386 display: flex; gap: 4px; justify-content: space-between; align-items: center; 14387 margin: -4px 0 10px; min-height: 36px; 14388 } 14389 .gr-atlas-action-left { display: flex; flex-direction: column; justify-content: center; gap: 3px; } 14390 .gr-atlas-panel-actions-icons { display: flex; gap: 4px; } 14391 .gr-atlas-voltooid-label { 14392 font-size: 1.2rem; font-weight: 700; 14393 color: var(--color-action, #2EDFC2); text-decoration: none; 14394 } 14395 .gr-atlas-voltooid-label:hover { text-decoration: underline; } 14396 /* Vinkje staat hier vóór de tekst i.p.v. erachter */ 14397 .gr-atlas-voltooid-label .gr-atlas-stat-check { margin-left: 0; margin-right: 2px; } 14398 a.gr-atlas-voltooid-label { cursor: pointer; } 14399 a.gr-atlas-voltooid-label::after { display: none !important; } 14400 .gr-atlas-panel-actions .btn-icon-svg { 14401 background: none; border: none; cursor: pointer; 14402 padding: 6px; display: flex; align-items: center; justify-content: center; 14403 opacity: 0.6; transition: opacity 0.2s; border-radius: 6px; 14404 } 14405 .gr-atlas-panel-actions .btn-icon-svg:hover { opacity: 1; } 14406 .gr-atlas-panel-actions .btn-icon-svg svg { 14407 width: 20px; height: 20px; stroke: var(--color-dark, #271D62); 14408 fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; 14409 } 14410 .gr-atlas-panel-actions .btn-icon-svg.disabled { opacity: 0.15; cursor: default; pointer-events: none; } 14411 .gr-atlas-panel-actions a::after { display: none !important; } 14412 14413 /* ââ Actie-menu (hamburger) â zelfde stijl als planner âââââââââââ */ 14414 /* ââ RSVP-knop bij een event, links van de hamburger ââ 14415 Dezelfde standen en kleuren als .btn-rsvp-trigger in planner-css, maar met 14416 eigen klassen: planner-css laadt niet op elke pagina waar de kaart staat. */ 14417 .gr-atlas-rsvp-wrap { position: relative; display: inline-flex; } 14418 /* Beide standen zitten in de popover; alleen de actuele is zichtbaar. */ 14419 .gr-atlas-rsvp-stand[hidden] { display: none !important; } 14420 .gr-atlas-rsvp-btn { 14421 border: 1px solid var(--color-dark, #271D62); border-radius: 999px; 14422 background: var(--color-dark, #271D62); color: #fff; cursor: pointer; 14423 font-family: 'ashemore', sans-serif; font-size: 14px; font-weight: 800; 14424 line-height: 1.2; padding: 3px 11px; transition: all .2s; 14425 } 14426 .gr-atlas-rsvp-btn.heeft-ticket { 14427 background: var(--color-action, #E84B20); border-color: var(--color-action, #E84B20); 14428 } 14429 .gr-atlas-rsvp-btn.op-bucketlist { 14430 background: var(--color-brand, #E84B20); border-color: var(--color-brand, #E84B20); 14431 } 14432 .gr-atlas-rsvp-popover { 14433 display: none; position: absolute; top: 100%; right: 0; width: 240px; 14434 background: #fff; border: 1px solid #eee; box-shadow: 0 4px 25px rgba(0,0,0,0.2); 14435 border-radius: 12px; z-index: 2005; overflow: hidden; text-align: left; 14436 } 14437 .gr-atlas-rsvp-option { 14438 padding: 11px 14px; cursor: pointer; font-weight: 700; font-size: 1.3rem; 14439 border-bottom: 1px solid #f5f5f5; color: #333; transition: background .15s; 14440 } 14441 .gr-atlas-rsvp-option:last-child { border-bottom: none; } 14442 .gr-atlas-rsvp-option:hover { background: #f5f5f5; } 14443 .gr-atlas-rsvp-option .ri { margin-right: 10px; display: inline-flex; vertical-align: -3px; } 14444 /* Monotone iconen in plaats van emoji: die kleuren zichzelf op iOS/Android. */ 14445 .gr-atlas-ri-svg { width: 15px; height: 15px; display: block; } 14446 .gr-atlas-rsvp-btn .gr-atlas-ri-svg { width: 15px; height: 15px; margin: 2px 0; } 14447 .gr-atlas-rsvp-option.groen-tekst { color: var(--color-brand, #E84B20); } 14448 .gr-atlas-rsvp-option.rood { color: var(--c-red, #E53935); } 14449 /* Actieve stand: niet klikbaar, gevulde achtergrond. */ 14450 .gr-atlas-rsvp-option.actief { cursor: default; pointer-events: none; color: #fff; } 14451 .gr-atlas-rsvp-option.actief.oranje { background: var(--color-action, #E84B20); } 14452 .gr-atlas-rsvp-option.actief.groen { background: var(--color-brand, #E84B20); } 14453 .gr-atlas-menu-wrapper { position: relative; } 14454 .gr-atlas-action-popover { 14455 display: none; position: absolute; top: 100%; right: 0; width: 220px; 14456 background: #fff; border: 1px solid #eee; box-shadow: 0 4px 25px rgba(0,0,0,0.2); 14457 border-radius: 12px; z-index: 2004; overflow: hidden; text-align: left; 14458 } 14459 .gr-atlas-action-popover.show { display: block; } 14460 .gr-atlas-action-option { 14461 padding: 10px 14px; cursor: pointer; font-weight: 600; font-size: 1.3rem; 14462 border-bottom: 1px solid #f5f5f5; display: flex; align-items: center; gap: 10px; 14463 color: #333; transition: background 0.15s; text-decoration: none; 14464 } 14465 .gr-atlas-action-option:last-child { border-bottom: none; } 14466 .gr-atlas-action-option:hover { background: #f5f5f5; } 14467 .gr-atlas-action-option svg { 14468 width: 18px; height: 18px; flex-shrink: 0; opacity: 0.75; 14469 stroke: var(--color-dark, #271D62); fill: none; 14470 stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; 14471 } 14472 .gr-atlas-action-option:hover svg { opacity: 1; } 14473 .gr-atlas-action-option::after { display: none !important; } 14474 /* Gevuld hartje zodra de Rondo op de bucketlist staat â zelfde kleur als de 14475 andere menu-iconen, alleen dichtgevuld in plaats van omlijnd */ 14476 .gr-atlas-action-option.on-list svg { fill: var(--color-dark, #271D62); stroke: var(--color-dark, #271D62); } 14477 .gr-atlas-action-option.busy { opacity: 0.5; pointer-events: none; } 14478 14479 /* Stat-vinkje */ 14480 .gr-atlas-stat-check { 14481 display: inline-flex; align-items: center; justify-content: center; 14482 width: 14px; height: 14px; border-radius: 50%; 14483 border: 1.5px solid #2EDFC2; color: #fff; background: #2EDFC2; 14484 font-size: 9px; font-weight: bold; 14485 margin-left: 4px; vertical-align: middle; flex-shrink: 0; 14486 padding-top: 3px; padding-right: 1px; 14487 } 14488 /* Voltooide ritten lijst */ 14489 /* Kop boven de voltooide ritten. Dezelfde grijze lijn en dezelfde afstanden 14490 als .gr-loc-blok verderop, zodat de scheidingen in het paneel er allemaal 14491 hetzelfde uitzien â een echte <hr> zou de themastijlen meekrijgen. */ 14492 .gr-atlas-voltooid-kop { 14493 border-top: 1px solid #e5e5f0; 14494 margin-top: 35px; 14495 padding-top: 35px; 14496 } 14497 /* Zelfde koptekst als .gr-loc-titel bij de locaties: Rum Raisin, 1.7rem, 14498 hoofdletters. Zo staan de twee kopjes in het paneel op gelijke voet. */ 14499 .gr-atlas-voltooid-kop h4 {
14500 margin: 0; font-weight: 700; font-size: 1.7rem; 14501 font-family: 'Rum Raisin', sans-serif; text-transform: uppercase; 14502 color: var(--color-dark, #271D62); line-height: 1.15; 14503 } 14504 /* De marge zit nu in de kop erboven. */ 14505 .gr-atlas-voltooid-list { display: flex; flex-direction: column; gap: 10px; margin: 14px 0 0; } 14506 .gr-atlas-voltooid-row { display: flex; align-items: center; gap: 4px; } 14507 .gr-atlas-voltooid-row .gr-atlas-voltooid-label { font-size: 1.5rem; line-height: 1.2; flex: 1; } 14508 .gr-atlas-edit-btn { background: none; border: none; cursor: pointer; padding: 2px 4px; opacity: 0.6; transition: opacity .2s; flex-shrink: 0; display: inline-flex; align-items: center; } 14509 .gr-atlas-edit-btn:hover { opacity: 1; } 14510 .gr-atlas-edit-btn::after { display: none !important; } 14511 .gr-atlas-edit-btn svg { width: 18px; height: 18px; stroke: var(--color-dark, #271D62); fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } 14512 .gr-atlas-not-ridden { margin: 12px 0 0; } 14513 .gr-atlas-not-ridden a { font-size: 1.5rem; font-weight: 700; color: var(--color-action, #2EDFC2); text-decoration: none; line-height: 1.2; } 14514 .gr-atlas-not-ridden a:hover { text-decoration: underline; } 14515 14516 /* Knoppen naast elkaar; ze wikkelen vanzelf als er geen ruimte is. */ 14517 /* Knoppen onder elkaar, elk over de volle breedte van het paneel. */ 14518 .gr-atlas-popup-btns { display: flex; flex-direction: column; gap: 8px; margin: 16px 0; } 14519 .gr-atlas-popup-btns > * { width: 100%; min-width: 0; } 14520 14521 /* â cirkel in actiebalk â zelfde stijl als andere icon-buttons */ 14522 .gr-atlas-vol-check-btn { background: none; border: none; cursor: pointer; padding: 6px; 14523 display: flex; align-items: center; justify-content: center; 14524 opacity: 0.6; transition: opacity 0.2s; border-radius: 6px; } 14525 .gr-atlas-vol-check-btn:hover { opacity: 1; } 14526 .gr-atlas-vol-check-btn svg { width: 20px; height: 20px; stroke: var(--color-dark, #271D62); 14527 fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } 14528 14529 /* Leaflet thema-override: zorg dat link-kleur niet overschreven wordt */ 14530 .leaflet-container a.gr-atlas-btn { color: #fff; } 14531 a.gr-atlas-btn[target="_blank"]::after { display: none !important; } 14532 14533 /* Bekijk Rondo */ 14534 .gr-atlas-btn-view { 14535 display: block; border: none; 14536 background-color: var(--color-dark, #271D62); 14537 border-radius: 999px; color: #fff; cursor: pointer; 14538 padding: 7px; align-content: center; 14539 font-family: "rum raisin", sans-serif !important; 14540 font-size: 1.2rem !important; line-height: 1.5rem; text-align: center !important; 14541 width: 100%; text-transform: uppercase; outline: none; 14542 letter-spacing: 0.1em; box-sizing: border-box; text-decoration: none; 14543 } 14544 .gr-atlas-btn-view:hover { opacity: 0.88; } 14545 14546 /* Zelfde pil, in de actiekleur. Voor de gidsknop bij een event: die staat daar 14547 alleen, zonder Bekijk Rondo eronder, en mag dan de knop zijn die opvalt. */ 14548 .gr-atlas-btn-view.gr-atlas-btn-actie { 14549 background-color: var(--color-action, #E84B20); 14550 } 14551 14552 /* Rondo voltooid â draait op .gr-atlas-btn-view mee, zodat pil, formaat, 14553 lettertype en spacing gegarandeerd gelijk zijn aan Bekijk Rondo. Deze 14554 modifier keert alleen de kleuren om. !important omdat thema-knopregels 14555 anders de rand en de ronding overschrijven â een <button> krijgt daar meer 14556 opmaak mee dan de <a> van Bekijk Rondo. */ 14557 .gr-atlas-btn-view.gr-atlas-btn-omgekeerd { 14558 background-color: #fff !important; 14559 color: var(--color-dark, #271D62) !important; 14560 border: 2px solid var(--color-dark, #271D62) !important; 14561 border-radius: 999px !important; 14562 } 14563 .gr-atlas-btn-view.gr-atlas-btn-omgekeerd:hover { 14564 background-color: var(--color-dark, #271D62) !important; 14565 color: #fff !important; 14566 opacity: 1; 14567 } 14568 14569 /* Bucketlist knop â zelfde pil als Bekijk Rondo, andere kleur. Flex zodat het 14570 hartje netjes vóór de tekst staat in plaats van een regelafbreking af te 14571 dwingen. (Deze basisregel was per ongeluk gesneuveld bij het opruimen van 14572 de oude "Je hebt Tickets"-knop.) */ 14573 .gr-atlas-btn-bucket { 14574 display: flex; align-items: center; justify-content: center; gap: 6px; 14575 border: none; background-color: #2EDFC2; 14576 border-radius: 999px; color: var(--color-dark, #271D62); cursor: pointer; 14577 padding: 7px; align-content: center; 14578 font-family: "rum raisin", sans-serif !important; 14579 font-size: 1.2rem !important; line-height: 1.5rem; text-align: center !important; 14580 width: 100%; text-transform: uppercase; outline: none; 14581 letter-spacing: 0.1em; box-sizing: border-box; text-decoration: none; 14582 transition: opacity .2s; 14583 } 14584 .gr-atlas-btn-bucket:hover { opacity: 0.88; } 14585 .gr-atlas-btn-bucket svg { width: 15px; height: 15px; flex-shrink: 0; } 14586 .gr-atlas-btn-bucket:disabled { opacity: 0.5;
14586 cursor: not-allowed; } 14587 .gr-atlas-btn-bucket.on-list { background: #1abfa4; } 14588</style> 14589 14590 14591
14592<script> 14593(function () { 14594 'use strict'; 14595 if (window.GRGpx) return; // al geladen 14596 14597 var MAX_PUNTEN = 400; // punten per route na uitdunnen 14598 var MAX_PARALLEL = 4; // gelijktijdige downloads 14599 var DB_NAAM = 'grAtlasGpx', STORE = 'routes', DB_VERSIE = 1; 14600 var TTL = 30 * 24 * 3600 * 1000; // 30 dagen 14601 14602 /* ââ Parsen ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 14603 Regex-scan over de ruwe tekst. Scheelt bij een GPX van 20.000 punten 14604 ruwweg een factor 10 ten opzichte van DOMParser + querySelectorAll, 14605 omdat er geen DOM-knopen worden gebouwd. lat en lon los uitlezen, want 14606 de volgorde van de attributen verschilt per exportprogramma. */ 14607 var TAG_RE = /<(?:trkpt|rtept)\b([^>]*)>/gi; 14608 var LAT_RE = /\blat\s*=\s*["']([-+0-9.eE]+)["']/; 14609 var LON_RE = /\blon\s*=\s*["']([-+0-9.eE]+)["']/; 14610 14611 function parse(tekst, maxPunten) { 14612 var punten = [], m, attrs, mLat, mLon, lat, lon; 14613 TAG_RE.lastIndex = 0; 14614 while ((m = TAG_RE.exec(tekst)) !== null) { 14615 attrs = m[1]; 14616 mLat = LAT_RE.exec(attrs); if (!mLat) continue; 14617 mLon = LON_RE.exec(attrs); if (!mLon) continue; 14618 lat = parseFloat(mLat[1]); lon = parseFloat(mLon[1]); 14619 if (lat === lat && lon === lon) punten.push([lat, lon]); // NaN-check 14620 } 14621 return dun(punten, maxPunten || MAX_PUNTEN); 14622 } 14623 14624 /* Elke n-de punt houden, maar begin- en eindpunt altijd meenemen zodat de 14625 lijn niet net voor de finish afbreekt. */ 14626 function dun(punten, max) { 14627 if (punten.length <= max) return punten; 14628 var stap = Math.ceil(punten.length / max), uit = []; 14629 for (var i = 0; i < punten.length; i += stap) uit.push(punten[i]); 14630 var laatste = punten[punten.length - 1]; 14631 var eind = uit[uit.length - 1]; 14632 if (!eind || eind[0] !== laatste[0] || eind[1] !== laatste[1]) uit.push(laatste); 14633 return uit; 14634 } 14635 14636 /* ââ IndexedDB-cache âââââââââââââââââââââââââââââââââââââââââââââââââââ 14637 Alles hier faalt stil: gaat de cache niet open (privémodus, quotum vol, 14638 oudere browser), dan halen we gewoon opnieuw op. */ 14639 var _dbBelofte = null; 14640 function db() { 14641 if (_dbBelofte) return _dbBelofte; 14642 _dbBelofte = new Promise(function (res, rej) { 14643 if (!window.indexedDB) return rej(new Error('geen indexedDB')); 14644 var v = indexedDB.open(DB_NAAM, DB_VERSIE); 14645 v.onupgradeneeded = function () { 14646 var d = v.result; 14647 if (!d.objectStoreNames.contains(STORE)) d.createObjectStore(STORE); 14648 }; 14649 v.onsuccess = function () { res(v.result); }; 14650 v.onerror = function () { rej(v.error); }; 14651 /* onblocked vuurt geen van beide af, en na een afgebroken verversing kan 14652 een open verzoek blijven staan. Zonder deze wekker lost db() nooit op 14653 en blijft alles wat erop wacht hangen. Zonder cache werkt de kaart 14654 gewoon, alleen wat trager. */ 14655 v.onblocked = function () { rej(new Error('indexedDB geblokkeerd')); }; 14656 setTimeout(function () { rej(new Error('indexedDB reageert niet')); }, 4000); 14657 }).catch(function (e) { console.info('[GR Atlas GPX] cache niet beschikbaar:', e && e.message); return null; }); 14658 return _dbBelofte; 14659 } 14660 14661 function cacheLees(url) { 14662 return db().then(function (d) { 14663 if (!d) return null; 14664 return new Promise(function (res) { 14665 var tx, v; 14666 try { tx = d.transaction(STORE, 'readonly'); v = tx.objectStore(STORE).get(url); } 14667 catch (e) { return res(null); } 14668 v.onsuccess = function () { 14669 var r = v.result; 14670 if (!r || !r.p || (Date.now() - r.t) > TTL) return res(null); 14671 res(r.p); 14672 }; 14673 v.onerror = function () { res(null); }; 14674 }); 14675 }).catch(function () { return null; }); 14676 } 14677 14678 function cacheSchrijf(url, punten) { 14679 db().then(function (d) { 14680 if (!d) return; 14681 try { 14682 var tx = d.transaction(STORE, 'readwrite'); 14683 tx.objectStore(STORE).put({ t: Date.now(), p: punten }, url); 14684 } catch (e) { /* quotum vol of store weg â niet erg */ } 14685 }).catch(function () {}); 14686 } 14687 14688 14689 /* ââ Gebundelde routes ââââââââââââââââââââââââââââââââââââââââââââââââ 14690 Eén JSON met alle routes, als theme-asset. Dat is de grote winst: in 14691 plaats van tientallen GPX-bestanden van megabytes haal je één bestand 14692 van enkele tientallen kB op, van de Shopify-CDN, gzip-gecomprimeerd. 14693 De losse GPX-route blijft bestaan voor gebieden die nog niet in de 14694 bundel zitten. */ 14695 var _bundel = null; // Promise<{gebied: [[lat,lng],...]}> 14696 14697 /* Neemt één URL of een lijst. De bundel kan in Content â Files staan 14698 (file_url) óf in de theme-assets (asset_url); we proberen ze op volgorde 14699 en pakken de eerste die antwoordt. */ 14700 function laadBundel(urls) { 14701 if (_bundel) return _bundel; 14702 var lijst = (urls == null) ? [] : (Array.isArray(urls) ? urls.slice() : [urls]); 14703 lijst = lijst.filter(function (u) { return u && String(u).indexOf('http') === 0 || (u && u.indexOf('/') === 0); }); 14704 if (!lijst.length) { _bundel = Promise.resolve({}); return _bundel; } 14705 14706 _bundel = (function probeer(i) { 14707 if (i >= lijst.length) return Promise.reject(new Error('geen van de URLs gaf een bundel')); 14708 return fetch(lijst[i]) 14709 .then(function (r) { 14710 if (!r.ok) throw new Error('HTTP ' + r.status); 14711 return r.json(); 14712 }) 14713 .catch(function (e) { 14714 console.info('[GR Atlas GPX] bundel niet op ' + lijst[i] + ' (' + (e && e.message) + ')'); 14715 return probeer(i + 1); 14716 }); 14717 })(0) 14718 .then(function (j) { 14719 var r = (j && j.routes) || {}; 14720 var n = Object.keys(r).length; 14721 var punten = 0; 14722 for (var k in r) punten += (r[k] || []).length; 14723 console.info('[GR Atlas GPX] bundel geladen:', n, 'routes /', punten, 'punten'); 14724 return r; 14725 }) 14726 .catch(function (e) { 14727 console.info('[GR Atlas GPX] geen routebundel (' + (e && e.message) + ') â per GPX ophalen'); 14728 return {}; 14729 }); 14730 return _bundel; 14731 } 14732 14733 /* ââ Wachtrij ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 14734 Maximaal MAX_PARALLEL downloads. Bij elke vrijgekomen plek pakken we de 14735 route die op dát moment het dichtst bij het midden van de kaart ligt, dus 14736 pannen tijdens het laden verandert de volgorde meteen. */ 14737 var wachtrij = [], bezig = 0; 14738 var _midden = null; // functie die {lat,lng} teruggeeft 14739 14740 function afstand(taak) { 14741 var bron = _midden || window._grAtlasMidden; 14742 if (!bron || !taak.lat) return 0; 14743 var c = bron(); 14744 if (!c) return 0; 14745 var dLat = taak.lat - c.lat, dLng = (taak.lng - c.lng) * 0.63; // ruwe cos(51°) 14746 return dLat * dLat + dLng * dLng; 14747 } 14748 14749 function volgende() { 14750 if (!wachtrij.length || bezig >= MAX_PARALLEL) return; 14751 var best = 0; 14752 for (var i = 1; i < wachtrij.length; i++) { 14753 if (afstand(wachtrij[i]) < afstand(wachtrij[best])) best = i; 14754 } 14755 var taak = wachtrij.splice(best, 1)[0]; 14756 bezig++; 14757 haalOp(taak.url) 14758 .then(taak.res, taak.rej) 14759 .then(function () { bezig--; volgende(); }); 14760 } 14761 14762 /* De eerste ronde één tick uitstellen. Anders vertrekken de vier routes die 14763 toevallig als eerste in de rij komen, nog voordat de rest is aangemeld â 14764 dan doet de sortering op afstand niets voor precies de downloads die je 14765 als eerste ziet. */ 14766 var _gepland = false;
14767 function pomp() { 14768 if (_gepland) return; 14769 _gepland = true; 14770 setTimeout(function () { 14771 _gepland = false; 14772 while (bezig < MAX_PARALLEL && wachtrij.length) volgende(); 14773 }, 0); 14774 } 14775 14776 /* ââ Harde deadline per route ââââââââââââââââââââââââââââââââââââââââ 14777 De wachtrij laat maximaal MAX_PARALLEL downloads tegelijk lopen en telt 14778 `bezig` pas omlaag als een belofte klaar is. Blijft er één hangen â een 14779 IndexedDB-transactie die nooit afrondt, een fetch zonder antwoord â dan 14780 blijft die plek voorgoed bezet. Met vier vastlopers staat de hele kaart 14781 stil en blijft hij oneindig laden; alleen een harde verversing hielp. 14782 14783 Deze wekker zorgt dat elke poging binnen DEADLINE_MS afloopt, hoe dan ook. 14784 Een route zonder punten valt gewoon weg: de kaart tekent de rest. */ 14785 var DEADLINE_MS = 20000; 14786 14787 function metDeadline(belofte, url) { 14788 var klaar = false; 14789 return new Promise(function (res) { 14790 var wekker = setTimeout(function () { 14791 if (klaar) return; 14792 klaar = true; 14793 console.warn('[GR Atlas GPX] route duurde te lang (' + DEADLINE_MS + 'ms), overgeslagen:', url); 14794 res([]); 14795 }, DEADLINE_MS); 14796 belofte.then(function (p) { 14797 if (klaar) return; 14798 klaar = true; clearTimeout(wekker); res(p); 14799 }, function (e) { 14800 if (klaar) return; 14801 klaar = true; clearTimeout(wekker); 14802 console.warn('[GR Atlas GPX] route mislukt:', url, e && e.message); 14803 res([]); 14804 }); 14805 }); 14806 } 14807 14808 function haalOp(url) { 14809 return metDeadline( 14810 cacheLees(url).then(function (uitCache) { 14811 if (uitCache && uitCache.length) return uitCache; 14812 return fetch(url) 14813 .then(function (r) { 14814 if (!r.ok) throw new Error('HTTP ' + r.status); 14815 return r.text(); 14816 }) 14817 .then(function (tekst) { 14818 var punten = parse(tekst, MAX_PUNTEN); 14819 if (punten.length) cacheSchrijf(url, punten); 14820 return punten; 14821 }); 14822 }), 14823 url 14824 ); 14825 } 14826 14827 /* ââ Publieke API ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 14828 laad(url, lat, lng) â Promise<[[lat,lng], ...]> 14829 lat/lng zijn optioneel en bepalen alleen de volgorde in de wachtrij. */ 14830 window.GRGpx = { 14831 laadBundel: laadBundel, 14832 /* De al opgehaalde bundel, zonder een nieuwe poging te starten. De atlas 14833 gebruikt het eerste punt van elke route als markerpositie, waardoor 14834 geocoderen (1 verzoek per seconde) grotendeels overbodig wordt. */ 14835 bundel: function () { return _bundel || Promise.resolve({}); }, 14836 /* gebied is optioneel; staat het in de bundel, dan gaat er geen enkel 14837 verzoek de deur uit. Is er geen bundel geladen, dan valt dit direct 14838 terug op de wachtrij â laadBundel(null) lost meteen op. */ 14839 laad: function (url, lat, lng, gebied) { 14840 var uitBundel = _bundel && gebied 14841 ? _bundel.then(function (b) { return b[gebied] || null; }) 14842 : Promise.resolve(null); 14843 return uitBundel.then(function (punten) { 14844 if (punten && punten.length) return punten; 14845 return new Promise(function (res, rej) { 14846 wachtrij.push({ url: url, lat: lat, lng: lng, res: res, rej: rej }); 14847 pomp(); 14848 }); 14849 }); 14850 }, 14851 // gr-atlas-script geeft hiermee het kaartmidden door voor de prioritering 14852 setMidden: function (fn) { _midden = fn; }, 14853 parse: parse, 14854 wisCache: function () { 14855 return db().then(function (d) { 14856 if (!d) return; 14857 try { d.transaction(STORE, 'readwrite').objectStore(STORE).clear(); } catch (e) {} 14858 }); 14859 }, 14860 _status: function () { return { wachtrij: wachtrij.length, bezig: bezig }; } 14861 }; 14862})(); 14863</script>
14863 14864 14865 14866 14867 14868 14869 14870 14871 14872 14873
14874<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
vendor: 1 bytes, line 14874
14874
14875<script> 14876(function () { 14877/* ââ Engelse teksten ââââââââââââââââââââââââââââââââââââââââââââââââââ 14878 Het planner-metaobject in Shopify is niet vertaald: op /en/ geeft het 14879 gewoon de Nederlandse tekst terug. Gemeten op de winkel â het 14880 palmares-metaobject Ãs vertaald, het planner-metaobject niet. 14881 14882 Daarom hier een Engelse tabel. Staat de bezoeker op een taalpad, dan wint 14883 deze; anders blijft alles zoals het was. Vertaal je het metaobject later 14884 alsnog, dan verandert er niets zichtbaars: dezelfde tekst, andere bron. 14885 14886 De Nederlandse teksten staan niet in deze tabel â die komen nog steeds uit 14887 het metaobject, met de terugval die achter elke regel hieronder staat. Zo 14888 blijft er één Nederlandse bron. */ 14889var _GR_EN = { 14890 "gr-atlas-add-bucketlist": "Add to Bucketlist", 14891 "gr-atlas-admin-download": "\u2b07 Download routes.json (admin)", 14892 "gr-atlas-book-tickets": "Join this event", 14893 "gr-atlas-completed-on": "Completed on", 14894 "gr-atlas-data-loading": "Loading rondos\u2026", 14895 "gr-atlas-edit-activity": "Edit", 14896 "gr-atlas-lib-error": "Could not load the map library.", 14897 "gr-atlas-lib-loading": "Loading map library\u2026", 14898 "gr-atlas-loading": "Loading\u2026", 14899 "gr-atlas-loc-rondobox": "Rondobox Store", 14900 "gr-atlas-loc-route": "Route to location", 14901 "gr-atlas-loc-rust": "Rest stop", 14902 "gr-atlas-loc-start": "Start/Rest", 14903 "gr-atlas-map-error": "Could not load the map.", 14904 "gr-atlas-map-loading": "Loading map\u2026", 14905 "gr-atlas-markers-placing": "Placing markers\u2026", 14906 "gr-atlas-my-activities": "Your activities", 14907 "gr-atlas-order-rondo": "Order Rondo", 14908 "gr-atlas-retry": "Try again", 14909 "gr-atlas-rondo-completed": "Rondo Completed", 14910 "gr-atlas-routes-loading": "Loading Rondos\u2026", 14911 "gr-atlas-saved-bucketlist": "Saved to Bucketlist", 14912 "gr-atlas-view-event": "View event", 14913 "gr-atlas-view-rondo": "View Rondo", 14914 "gr-bucketlist-btn-remove": "Remove from bucketlist", 14915 "gr-bucketlist-btn-save": "Save to bucketlist", 14916 "gr-bucketlist-on-list": "Saved to bucketlist", 14917 "gr-planner-actions": "Actions", 14918 "gr-planner-close": "Close", 14919 "gr-planner-item-deleted": "Item deleted\u2026", 14920 "gr-planner-label-info": "Information", 14921 "gr-planner-order-rondo": "Order this Rondo", 14922 "gr-planner-plan-rondo-tooltip": "Plan this Rondo", 14923 "gr-planner-start-location": "Start location", 14924 "gr-planner-ticket-join": "Join", 14925 "gr-planner-undo": "Undo", 14926 "gr-planner-view-guide": "View Rondo Guide", 14927 "gr-planner-you": "You?", 14928 "gr-planner-you-have-tickets": "You have tickets" 14929}; 14930var _grIsEn = (function () { 14931 var t = (location.pathname.split('/')[1] || ''); 14932 return /^[a-z]{2}$/.test(t) && t !== 'nl'; 14933})(); 14934/* Staat de Engelse metaobject-ingang er eenmaal, dan is dát de bron en doet 14935 de tabel hierboven niets meer. Anders zou dezelfde knop in de kaart anders 14936 heten dan in de modals, en zou een verbeterde vertaling in Shopify niet 14937 doorkomen. Zonder die ingang blijft de tabel de kaart in het Engels houden. */ 14938var _grMetaVertaald =false; 14939function _grLbl(sleutel, viaMetaobject) { 14940 if (_grMetaVertaald) return viaMetaobject; 14941 return (_grIsEn && _GR_EN[sleutel]) ? _GR_EN[sleutel] : viaMetaobject; 14942} 14943/* Ook gr-atlas-html gebruikt hem, voor de teksten in het paneel. Die kent de 14944 tabel niet zelf; zo staat de Engelse tekst op één plek. */ 14945window._grLbl = _grLbl; 14946 14947// ââ Bootstrap ââ draait op elke pagina; alleen opbouwen als de HTML er staat. 14948function _grAtlasInit(_mapContainer) { 14949 // LET OP: planner-script1 heeft een globale `const L` voor labels. Een kale 14950 // `L` wijst dus niet naar Leaflet â vandaar expliciet window.L. 14951 var L = window.L; 14952 14953 var SCRIPT_URL = "https://script.google.com/macros/s/AKfycbykfmZGR3AVsTqRF0LNs3Kx1zzVauuYSe-GGb2JzR8AeHYCjB8BNOQbXJZ5ouxa946n/exec"; 14954 var ROUTES_URL = "https://opensheet.elk.sh/1_Bc2komUMc7pVNT8rQkO0_Djnh41O5wCOvBMozarCms/routes"; 14955 var ACT_URL = "https://opensheet.elk.sh/1z4oQxDzP6xwMxKY61Lp9X7Ky3wpQ27XjV79oIrJOtWo/Activiteiten"; 14956 14957 var STATUS_BUCKETLIST = 'Bucketlist'; 14958 var STATUS_GO = 'Ik doe mee'; 14959 var STATUS_MAYBE = 'Misschien'; 14960 14961 var myEmail = null; 14962 var _isLoggedIn = !!myEmail; 14963 // Tags & rechten (zelfde logica als Rondo Planner) 14964 var _atlasRawTags = [] || []; 14965 var _atlasUserTags = (Array.isArray(_atlasRawTags) ? _atlasRawTags : []) 14966 .map(function(t){ return String(t || '').trim().toLowerCase(); }); 14967 var _atlasIsAdmin = false;
14968 var _atlasIsRondoneur = _atlasUserTags.indexOf('rondoneur') !== -1; 14969 var _areaTags = {}; // { rondo â areaTag } â gevuld in parsePlannerData 14970 14971 var GEO_CACHE = 'grAtlasGeo'; 14972 var GEO_TTL = 30 * 24 * 3600 * 1000; 14973 var statusEl = document.getElementById('gr-atlas-status'); 14974 /* bezig=false laat de spinner weg (foutmelding mag niet blijven draaien). */ 14975 function setStatus(msg, bezig) { 14976 if (!statusEl) return; 14977 statusEl.textContent = msg; 14978 statusEl.style.display = ''; 14979 statusEl.classList[bezig === false ? 'remove' : 'add']('gr-atlas-bezig'); 14980 } 14981 function hideStatus() { 14982 if (!statusEl) return; 14983 statusEl.style.display = 'none'; 14984 statusEl.classList.remove('gr-atlas-bezig'); 14985 } 14986 /* Pil pas weg als markers én routelijnen klaar zijn; noodrem na 30s. */ 14987 var _gpxVerwacht = 0, _gpxKlaar = 0, _markersKlaar = false, _statusAf = false; 14988 function gpxAangemeld() { _gpxVerwacht++; } 14989 function gpxAf() { _gpxKlaar++; statusBijwerken(); } 14990 function markersAf() { 14991 _markersKlaar = true; 14992 statusBijwerken(); 14993 /* Vanaf hier is de kaart bruikbaar: de stippen staan er en de routes die al 14994 binnen waren zijn getekend. Blijft er dan nog één route hangen, dan hoort 14995 dat geen dertig seconden "Laden Rondo'sâ¦" op te leveren â gemeten stond 14996 hij op (35/36) terwijl het echte werk na 57ms klaar was. 14997 14998 Drie tellen speling voor de rest, daarna gaat de pil weg. Wat nog 14999 onderweg is tekent zichzelf gewoon bij; daar hoeft niemand naar te 15000 kijken. De noodrem hieronder blijft voor het geval er écht niets komt. */ 15001 setTimeout(function () { 15002 if (_statusAf) return; 15003 if (_gpxKlaar < _gpxVerwacht) { 15004 console.info('[GR Atlas] kaart klaar; ' + (_gpxVerwacht - _gpxKlaar) 15005 + ' route(s) tekenen nog bij.'); 15006 } 15007 _statusAf = true; 15008 hideStatus(); 15009 }, 3000); 15010 } 15011 function statusBijwerken() { 15012 if (_statusAf || !_markersKlaar) return; 15013 if (_gpxKlaar < _gpxVerwacht) { 15014 setStatus(LBL_ROUTES_LOADING + ' (' + _gpxKlaar + '/' + _gpxVerwacht + ')'); 15015 return; 15016 } 15017 _statusAf = true; hideStatus(); 15018 } 15019 /* Noodrem. Verdween eerder stilletjes; dan stond er een halve kaart zonder 15020 enige aanwijzing dat er iets misging en wist alleen wie het wist dat een 15021 harde verversing hielp. Nu een knop die dat voor je doet. */ 15022 setTimeout(function () { 15023 if (_statusAf) return; 15024 _statusAf = true; 15025 console.warn('[GR Atlas] routes na 30s nog niet compleet (' + _gpxKlaar + '/' + _gpxVerwacht + ').'); 15026 if (!statusEl) return; 15027 statusEl.classList.remove('gr-atlas-bezig'); 15028 statusEl.style.display = ''; 15029 statusEl.style.pointerEvents = 'auto'; 15030 statusEl.innerHTML = ''; 15031 var knop = document.createElement('button'); 15032 knop.type = 'button'; 15033 knop.textContent = LBL_OPNIEUW; 15034 knop.style.cssText = 'background:var(--color-action,#E84B20);color:#fff;border:none;border-radius:999px;' 15035 + 'padding:8px 18px;font-family:inherit;font-size:1em;font-weight:700;cursor:pointer;'; 15036 knop.addEventListener('click', function () { 15037 if (window.grHerlaadPagina) window.grHerlaadPagina(); 15038 else location.reload(); 15039 }); 15040 statusEl.appendChild(knop); 15041 }, 30000); 15042 15043 // ââ Leaflet kaart ââ 15044 // Benelux; mobiel een halve stap verder uit (700px = breekpunt van de CSS). 15045 // zoomControl uit en zelf toevoegen: alleen zo kun je de positie kiezen. 15046 var _smal = !!(window.matchMedia && window.matchMedia('(max-width:700px)').matches); 15047 var map = L.map(_mapContainer, { zoomControl: false, zoomSnap: 0.5 }) 15048 .setView([51.35, 4.90], _smal ? 6.5 : 7.5); 15049 L.control.zoom({ position: 'bottomright' }).addTo(map); 15050 L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', { 15051 attribution: '© Esri | © <a href="https://openstreetmap.org">OpenStreetMap</a>', 15052 maxZoom: 19 15053 }).addTo(map); 15054 15055 // Verborgen container (tab/accordeon) meet 0x0 â invalidateSize zodra zichtbaar. 15056 function _fixSize() { try { map.invalidateSize(false); } catch (e) {} } 15057 setTimeout(_fixSize, 0); 15058 setTimeout(_fixSize, 300); 15059 window.addEventListener('resize', _fixSize); 15060 if (window.ResizeObserver) { 15061 try { new ResizeObserver(_fixSize).observe(_mapContainer); } catch (e) {} 15062 } 15063 if (window.IntersectionObserver) { 15064 try { 15065 new IntersectionObserver(function (entries) {
15066 entries.forEach(function (en) { if (en.isIntersecting) _fixSize(); }); 15067 }).observe(_mapContainer); 15068 } catch (e) {} 15069 } 15070 window._grAtlasFixSize = _fixSize; // handmatig aanroepbaar na tabwissel 15071 // Kaartmidden voor de wachtrij in gr-atlas-gpx; globaal i.v.m. laadvolgorde. 15072 window._grAtlasMidden = function () { 15073 try { return map.getCenter(); } catch (e) { return null; } 15074 }; 15075 15076 var COLOR = { ridden: '#ffffff', bucket: '#2EDFC2', none: '#271D62' }; 15077 var BORDER = { ridden: '#271D62', bucket: '#1abfa4', none: '#1a1440' }; 15078 15079 // ââ SVG overlay ââ 15080 var _NS = 'http://www.w3.org/2000/svg'; 15081 var _svg = document.createElementNS(_NS, 'svg'); 15082 _svg.setAttribute('style', 'position:absolute;top:0;left:0;overflow:visible;pointer-events:all;'); 15083 map.getPanes().overlayPane.appendChild(_svg); 15084 // Volgorde: casings â polys/hits â dots 15085 var _routesCasingGroup = document.createElementNS(_NS, 'g'); 15086 var _routesPolyGroup = document.createElementNS(_NS, 'g'); 15087 var _dotsGroup = document.createElementNS(_NS, 'g'); 15088 _svg.appendChild(_routesCasingGroup); 15089 _svg.appendChild(_routesPolyGroup); 15090 _svg.appendChild(_dotsGroup); 15091 var _dots = []; 15092 15093 function _reposition() { 15094 _dots.forEach(function(d) { 15095 try { 15096 var pt = map.latLngToLayerPoint(d.latlng); 15097 d.el.setAttribute('transform', 'translate(' + pt.x + ',' + pt.y + ')'); 15098 } catch(e) {} 15099 }); 15100 } 15101 map.on('moveend zoomend viewreset', function() { 15102 _reposition(); 15103 _gpxRoutes.forEach(_repositionGPX); 15104 }); 15105 15106 function _makeDotIcon(st) { 15107 // Geeft een SVG <text> element terug met ⥠of â, of null 15108 if (st === 'ridden') { 15109 var t = document.createElementNS(_NS, 'text'); 15110 t.setAttribute('text-anchor', 'middle'); t.setAttribute('dominant-baseline', 'central'); 15111 t.setAttribute('font-size', '15'); t.setAttribute('fill', '#271D62'); 15112 t.setAttribute('font-weight', 'bold'); t.setAttribute('style', 'pointer-events:none;'); 15113 t.textContent = 'â'; 15114 return t; 15115 } 15116 if (st === 'bucket') { 15117 var t = document.createElementNS(_NS, 'text'); 15118 t.setAttribute('text-anchor', 'middle'); t.setAttribute('dominant-baseline', 'central'); 15119 t.setAttribute('font-size', '17'); t.setAttribute('fill', '#ffffff'); 15120 t.setAttribute('style', 'pointer-events:none;'); 15121 t.textContent = 'â¥'; 15122 return t; 15123 } 15124 return null; 15125 } 15126 15127 function addDot(ll, color, border, gebied, st) { 15128 var latlng = [ll.lat, ll.lng]; 15129 var pt = map.latLngToLayerPoint(latlng); 15130 var g = document.createElementNS(_NS, 'g'); 15131 g.setAttribute('transform', 'translate(' + pt.x + ',' + pt.y + ')'); 15132 g.setAttribute('style', 'cursor:pointer;'); 15133 if (gebied) g.setAttribute('data-gr-gebied', gebied); 15134 var c = document.createElementNS(_NS, 'circle'); 15135 c.setAttribute('r', 11); c.setAttribute('fill', color); 15136 c.setAttribute('stroke', border); c.setAttribute('stroke-width', '2'); 15137 c.setAttribute('style', 'filter:drop-shadow(0 1px 3px rgba(0,0,0,.22));'); 15138 g.appendChild(c); 15139 var icon = _makeDotIcon(st); 15140 if (icon) g.appendChild(icon); 15141 _dotsGroup.appendChild(g); 15142 var entry = { el: g, latlng: latlng, gebied: gebied }; 15143 _dots.push(entry); 15144 return entry; 15145 } 15146 15147 var _gpxRoutes = []; // { el: polyline, latlngs: [[lat,lng],...] } 15148 15149 function _repositionGPX(g) { 15150 if (!g.latlngs.length) return; 15151 var pts = g.latlngs.map(function(ll) { 15152 var pt = map.latLngToLayerPoint(ll); return pt.x + ',' + pt.y; 15153 }).join(' '); 15154 g.el.setAttribute('points', pts); 15155 if (g.casing) g.casing.setAttribute('points', pts); 15156 if (g.hitArea) g.hitArea.setAttribute('points', pts); 15157 } 15158 15159 /* GPX loopt via gr-atlas-gpx.html: regex-parser, max 4 downloads tegelijk, 15160 dichtstbijzijnde route eerst, resultaat in IndexedDB. Ontbreekt dat 15161 bestand, dan pakt de terugval hieronder het op â trager, maar werkend. */ 15162 /* Eén JSON met alle routes. Kan in Content â Files staan (file_url) of in de 15163 theme-assets (asset_url); beide worden geprobeerd. Vindt hij niets, dan 15164 valt de module vanzelf terug op losse GPX-bestanden. */ 15165 var ROUTES_JSON = [ 15166 "https://cdn.shopify.com/s/files/1/0899/1277/0934/files/gr-atlas-routes.json", 15167 "//granrondo.cc/cdn/shop/files/gr-atlas-routes.json?v=7312393436741146553", 15168 "//granrondo.cc/cdn/shop/t/1/assets/gr-atlas-routes.json?v=9844" 15169 ]; 15170 if (window.GRGpx && window.GRGpx.laadBundel) window.GRGpx.laadBundel(ROUTES_JSON); 15171 15172 function _gpxLaad(url, lat, lng, gebied) {
15173 if (window.GRGpx && window.GRGpx.laad) return window.GRGpx.laad(url, lat, lng, gebied); 15174 return fetch(url).then(function(r) { return r.text(); }).then(parseGPX); 15175 } 15176 15177 var _PT_RE = /<(?:trkpt|rtept)\b([^>]*)>/gi; 15178 function parseGPX(xmlText) { 15179 if (window.GRGpx && window.GRGpx.parse) return window.GRGpx.parse(xmlText, 400); 15180 var alle = [], m, a, la, lo; 15181 _PT_RE.lastIndex = 0; 15182 while ((m = _PT_RE.exec(xmlText)) !== null) { 15183 a = m[1]; 15184 la = /\blat\s*=\s*"([-+0-9.eE]+)"/.exec(a); 15185 lo = /\blon\s*=\s*"([-+0-9.eE]+)"/.exec(a); 15186 if (la && lo) alle.push([parseFloat(la[1]), parseFloat(lo[1])]); 15187 } 15188 if (alle.length <= 400) return alle; 15189 var stap = Math.ceil(alle.length / 400), uit = []; 15190 for (var i = 0; i < alle.length; i += stap) uit.push(alle[i]); 15191 uit.push(alle[alle.length - 1]); 15192 return uit; 15193 } 15194 15195 var _gpxByGebied = {}; // { gebied â gpxEntry } 15196 var _activeGebied = null; 15197 15198 function _validHex(c) { return /^#[0-9A-Fa-f]{3,6}$/.test(c); } 15199 15200 function drawGPXRoute(latlngs, st, gebied, clickFn, color) { 15201 var stroke = (_validHex(color) ? color : '#271D62'); 15202 var casing = document.createElementNS(_NS, 'polyline'); 15203 casing.setAttribute('fill', 'none'); 15204 casing.setAttribute('stroke', '#ffffff'); 15205 casing.setAttribute('stroke-width', '7'); 15206 casing.setAttribute('stroke-opacity', '0'); 15207 casing.setAttribute('stroke-linecap', 'round'); 15208 casing.setAttribute('stroke-linejoin', 'round'); 15209 casing.setAttribute('style', 'pointer-events:none;'); 15210 _routesCasingGroup.appendChild(casing); 15211 15212 var poly = document.createElementNS(_NS, 'polyline'); 15213 poly.setAttribute('fill', 'none'); 15214 poly.setAttribute('stroke', stroke); 15215 poly.setAttribute('stroke-width', '2.5'); 15216 poly.setAttribute('stroke-opacity', '0.75'); 15217 poly.setAttribute('stroke-linecap', 'round'); 15218 poly.setAttribute('stroke-linejoin', 'round'); 15219 poly.setAttribute('style', 'pointer-events:none;'); 15220 _routesPolyGroup.appendChild(poly); 15221 15222 var hitArea = null; 15223 if (clickFn) { 15224 hitArea = document.createElementNS(_NS, 'polyline'); 15225 hitArea.setAttribute('fill', 'none'); 15226 hitArea.setAttribute('stroke', 'transparent'); 15227 hitArea.setAttribute('stroke-width', '8'); 15228 hitArea.setAttribute('style', 'cursor:pointer;pointer-events:stroke;'); 15229 hitArea.addEventListener('click', function(e) { e.stopPropagation(); clickFn(); }); 15230 _routesPolyGroup.appendChild(hitArea); 15231 } 15232 15233 if (gebied) { 15234 poly.setAttribute('data-gr-gebied', gebied); 15235 casing.setAttribute('data-gr-gebied', gebied); 15236 if (hitArea) hitArea.setAttribute('data-gr-gebied', gebied); 15237 } 15238 var entry = { el: poly, casing: casing, hitArea: hitArea, latlngs: latlngs, st: st, gebied: gebied, color: stroke }; 15239 _gpxRoutes.push(entry); 15240 if (gebied) _gpxByGebied[gebied] = entry; 15241 _repositionGPX(entry); 15242 return entry; 15243 } 15244 15245 function _applyGPXStyle(entry, active) { 15246 var stroke = entry.color || '#271D62'; 15247 if (active) { 15248 entry.el.setAttribute('stroke-width', '5'); 15249 entry.el.setAttribute('stroke-opacity', '1'); 15250 entry.el.setAttribute('stroke', stroke); 15251 entry.casing.setAttribute('stroke-opacity', '0.45'); 15252 entry.casing.setAttribute('stroke-width', '8'); 15253 } else { 15254 entry.el.setAttribute('stroke-width', '2.5'); 15255 entry.el.setAttribute('stroke', stroke); 15256 entry.el.setAttribute('stroke-opacity', _activeGebied ? '0.25' : '0.75'); 15257 entry.casing.setAttribute('stroke-opacity', '0'); 15258 } 15259 } 15260 15261 function _dimDots(activerGebied) { 15262 _dots.forEach(function(d) { 15263 var c = d.el.querySelector('circle'); 15264 if (!c) return; 15265 c.setAttribute('opacity', (activerGebied && d.gebied !== activerGebied) ? '0.25' : '1'); 15266 }); 15267 } 15268 15269 function highlightGPX(gebied) { 15270 _activeGebied = gebied; 15271 _gpxRoutes.forEach(function(e) { _applyGPXStyle(e, e.gebied === gebied); }); 15272 // Breng actieve route naar voren binnen de groepen 15273 var active = _gpxByGebied[gebied]; 15274 if (active) { 15275 _routesCasingGroup.appendChild(active.casing); 15276 _routesPolyGroup.appendChild(active.el); 15277 if (active.hitArea) _routesPolyGroup.appendChild(active.hitArea); 15278 } 15279 } 15280 15281 function resetGPX() { 15282 _activeGebied = null;
15283 _gpxRoutes.forEach(function(e) { _applyGPXStyle(e, false); }); 15284 } 15285 15286 var markers = {}; 15287 var _eventSet = new Set(); // gebieden met een ticket-event 15288 var _alleRoutes = {}; // alle rijen uit de routes-sheet, voor de admin-export 15289 var riddenSet = new Set(); 15290 var riddenMap = {}; // { gebied â [{url, datum}, ...] } 15291 var myBucketlist = new Set(); 15292 var _bucketRideMap = {}; // { rondo â ritId } 15293 var _routeDetails = {}; // { "Gebied|Type" â { naam, shopLink, km, hm, richting, mapImg } } 15294 15295 function getStatus(gebied) { 15296 if (riddenSet.has(gebied)) return 'ridden'; 15297 if (myBucketlist.has(gebied)) return 'bucket'; 15298 return 'none'; 15299 } 15300 15301 function refreshMarker(gebied) { 15302 var st = getStatus(gebied); 15303 var sel = '[data-gr-gebied="' + gebied.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"]'; 15304 var g = _svg.querySelector(sel); 15305 if (!g) return; 15306 var c = g.querySelector('circle'); 15307 if (c) { c.setAttribute('fill', COLOR[st]); c.setAttribute('stroke', BORDER[st]); } 15308 // Ververs icoon 15309 var old = g.querySelector('text'); if (old) g.removeChild(old); 15310 var icon = _makeDotIcon(st); if (icon) g.appendChild(icon); 15311 } 15312 15313 // ââ Zijpaneel ââ 15314 var _panel = document.getElementById('gr-atlas-panel'); 15315 var _backdrop = document.getElementById('gr-atlas-backdrop'); 15316 var _mapEl = document.getElementById('gr-atlas-map'); 15317 15318 /* De kleur van de routelijn van een gebied. gr-atlas-locaties gebruikt dit om 15319 de start- en rustbolletjes dezelfde kleur te geven als de lijn. */ 15320 window._grAtlasRouteKleur = function (gebied) { 15321 var e = gebied && _gpxByGebied[gebied]; 15322 return (e && e.color) || null; 15323 }; 15324 15325 function openPanel(htmlContent, gebied) { 15326 if (window.innerWidth <= 768) { 15327 document.documentElement.style.overflow = 'hidden'; 15328 document.body.style.overflow = 'hidden'; 15329 document.body.classList.add('modal-open'); 15330 } 15331 if (gebied) { 15332 highlightGPX(gebied); 15333 /* Start- en rustlocaties horen bij de route en verschijnen dus pas hier: 15334 als bolletje op de kaart in de kleur van de lijn, en als blok onder de 15335 route in ditzelfde paneel. Beide functies komen uit gr-atlas-locaties; 15336 staat dat snippet er niet, dan gebeurt er gewoon niets extra's. 15337 15338 Alleen bij een gebied. Klik je een bolletje aan, dan komt openPanel 15339 zónder gebied langs en laten we de zichtbare bolletjes met rust â 15340 anders verdween net dat bolletje waar je op klikte. */ 15341 try { 15342 if (typeof window._grAtlasLocBlokken === 'function') { 15343 var _locs = window._grAtlasLocBlokken(gebied); 15344 if (_locs) htmlContent += _locs; 15345 } 15346 if (typeof window._grAtlasLocToon === 'function') { 15347 window._grAtlasLocToon(gebied, window._grAtlasRouteKleur(gebied)); 15348 } 15349 } catch (e) { console.warn('[GR Atlas] locaties bij route mislukt:', e); } 15350 } 15351 _panel.innerHTML = ''; 15352 // Geen kruisje meer â sluiten gaat via het hamburger-menu, de kaart of de achtergrond 15353 var inner = document.createElement('div'); 15354 inner.innerHTML = htmlContent; 15355 _panel.appendChild(inner); 15356 _panel.classList.add('open'); 15357 _mapEl.classList.add('panel-open'); 15358 if (_backdrop) _backdrop.classList.add('open'); 15359 // Scroll naar boven 15360 _panel.scrollTop = 0; 15361 } 15362 function closePanel() { 15363 _panel.classList.remove('open'); 15364 _mapEl.classList.remove('panel-open'); 15365 if (_backdrop) _backdrop.classList.remove('open'); 15366 document.documentElement.style.overflow = ''; 15367 document.body.style.overflow = ''; 15368 document.body.classList.remove('modal-open'); 15369 resetGPX(); 15370 /* Geen route meer geselecteerd, dus de bijbehorende start- en 15371 rustbolletjes gaan ook weer weg. Rondobox blijft staan. */ 15372 try { if (typeof window._grAtlasLocVerberg === 'function') window._grAtlasLocVerberg(); } 15373 catch (e) {} 15374 } 15375 if (_backdrop) _backdrop.addEventListener('click', closePanel); 15376 // Sluit ook als ergens op de kaart geklikt wordt (niet op een dot) 15377 document.getElementById('gr-atlas-map').addEventListener('click', function(e) { 15378 if (e.target === _mapEl || e.target.tagName === 'canvas' || e.target === document.getElementById('gr-atlas-status')) closePanel(); 15379 }); 15380 15381 // ââ Geocoder ââ 15382 var geoCache = {}; 15383 try { var _gc = JSON.parse(sessionStorage.getItem(GEO_CACHE)); if (_gc && Date.now() - _gc.ts < GEO_TTL) geoCache = _gc.d; } catch(e) {} 15384 function saveGeoCache() { 15385 try { sessionStorage.setItem(GEO_CACHE, JSON.stringify({ ts: Date.now(), d: geoCache })); } catch(e) {} 15386 } 15387 function geocode(name) { 15388 if (geoCache[name]) return Promise.resolve(geoCache[name]); 15389 return fetch('https://nominatim.openstreetmap.org/search?q=' + encodeURIComponent(name) + '&format=json&limit=1&addressdetails=0') 15390 .then(function(r) { return r.json(); }) 15391 .then(function(data) { 15392 if (data && data[0]) { 15393 var ll = { lat: parseFloat(data[0].lat), lng: parseFloat(data[0].lon) }; 15394 geoCache[name] = ll; saveGeoCache(); return ll; 15395 } 15396 return null; 15397 }) 15398 .catch(function() { return null; }); 15399 } 15400 15401 // ââ Planner cache ââ 15402 var GR_CACHE_KEY = 'gr_rides_v1'; 15403 var GR_CACHE_TTL = 5 * 60 * 1000; 15404 15405 /* Liefst via gr-data: dat bewaakt dat er per paginaweergave hooguit één 15406 ?action=load onderweg is. Op de homepage vragen de kaart, de 15407 bucketlistknop en de voorinschrijving er alle drie om, en Apps Script doet
15408 ze ná elkaar â daar liep deze kaart tegen zijn eigen noodrem van dertig 15409 seconden aan. Staat gr-data niet in de footer, dan blijft de oude weg 15410 hieronder gewoon werken. */ 15411 function loadPlannerData() { 15412 if (window.GRData && window.GRData.load) { 15413 return window.GRData.load().catch(function () { 15414 return window.GRData.oud() || {}; // verouderde cache boven niets 15415 }); 15416 } 15417 try { 15418 var c = localStorage.getItem(GR_CACHE_KEY); 15419 if (c) { var p = JSON.parse(c); if (Date.now() - p.ts < GR_CACHE_TTL) return Promise.resolve(p.data); } 15420 } catch(e) {} 15421 return fetch(SCRIPT_URL + '?action=load&t=' + Date.now()) 15422 .then(function(r) { return r.json(); }) 15423 .then(function(d) { 15424 try { localStorage.setItem(GR_CACHE_KEY, JSON.stringify({ ts: Date.now(), data: d })); } catch(e) {} 15425 return d; 15426 }) 15427 .catch(function() { return {}; }); 15428 } 15429 15430 // ââ Parse planner data â zelfde logica als "Which Rondo's" popup â 15431 function parsePlannerData(data) { 15432 var allRitten = data.ritten || []; 15433 var deelnemers = data.deelnemers || []; 15434 _routeDetails = data.routeDetails || {}; 15435 _areaTags = data.areaTags || {}; 15436 15437 /* Events (tickets=true) staan niet op je bucketlist maar horen wel op de 15438 kaart â de filterknop Events toont ze. Zelfde ticket-check als de planner. */ 15439 function _isEvent(r) { return /^true$/i.test(String(r.tickets || '')); } 15440 /* Geweest is geweest. De regel staat in gr-atlas-html, zodat het paneel en 15441 deze filter niet uit elkaar kunnen lopen; ontbreekt dat bestand, dan valt 15442 het terug op het oude gedrag in plaats van de kaart leeg te laten. */ 15443 var _voorbij = window._grAtlasEventVoorbij || function () { return false; }; 15444 15445 var kandidaten = allRitten.filter(function(r) { 15446 return r.status === STATUS_BUCKETLIST || _isEvent(r); 15447 }); 15448 /* Welke gebieden hebben naast het event ook een gewone Rondo om zelf op 15449 avontuur te gaan? Die bepaalt wat er met een verlopen event gebeurt. */ 15450 var _heeftEigenRondo = {}; 15451 kandidaten.forEach(function(r) { 15452 if (r.rondo && r.status === STATUS_BUCKETLIST) _heeftEigenRondo[r.rondo] = true; 15453 }); 15454 /* Een event dat geweest is verdwijnt als het gebied zijn eigen Rondo al 15455 heeft: die staat er dan toch al, en twee markers op dezelfde plek leverde 15456 sowieso een dubbele stip op. Is het event de enige rit van dat gebied, dan 15457 blijft hij staan â maar dan als gewone Rondo, want _grAtlasEventBlok laat 15458 er bij een verlopen event alle eventopmaak af. Anders zou de Rondo van de 15459 kaart vallen op de dag ná het event. */ 15460 var blRitten = kandidaten.filter(function(r) { 15461 if (!_isEvent(r) || !_voorbij(r)) return true; 15462 return !_heeftEigenRondo[r.rondo]; 15463 }); 15464 blRitten.forEach(function(r) { 15465 if (r.rondo && _isEvent(r) && !_voorbij(r)) _eventSet.add(r.rondo); 15466 }); 15467 15468 blRitten.forEach(function(r) { 15469 if (r.rondo && !_bucketRideMap[r.rondo]) _bucketRideMap[r.rondo] = r.id; 15470 }); 15471 15472 var lowerMe = (myEmail || '').toLowerCase(); 15473 var myRitIds = new Set(
15474 deelnemers 15475 .filter(function(p) { 15476 return (p.email || '').toLowerCase() === lowerMe && 15477 (p.status === STATUS_GO || p.status === STATUS_MAYBE || p.status === STATUS_BUCKETLIST); 15478 }) 15479 .map(function(p) { return p.ritId; }) 15480 ); 15481 15482 blRitten.forEach(function(r) { 15483 if (r.rondo && myRitIds.has(r.id)) myBucketlist.add(r.rondo); 15484 }); 15485 15486 // Bron voor window.grAtlasTickets() â de diagnose staat in gr-atlas-html. 15487 window._grAtlasDiagBron = { ritten: blRitten, details: _routeDetails, tags: _atlasUserTags }; 15488 return blRitten; 15489 } 15490 15491 // ââ Login vragen ââ modal staat in gr-shared-modals.html (footer). 15492 function _grAtlasVraagLogin() { 15493 var m = document.getElementById('grBucketlistLoginModal'); 15494 if (m) { m.classList.add('open'); return; } 15495 console.warn('[GR Atlas] Login-popup ontbreekt â staat gr-shared-modals.html in de footer?'); 15496 window.location.href = LOGIN_URL; 15497 } 15498 15499 // Bucketlist-status staat op twee plekken: paneelknop én menu-optie. 15500 function _syncBucketUI(gebied, busy) { 15501 var on = myBucketlist.has(gebied); 15502 var b = document.querySelector('.gr-atlas-btn-bucket[data-gebied="' + gebied.replace(/"/g, '\\"') + '"]'); 15503 if (b) { 15504 b.disabled = !!busy; 15505 b.classList.toggle('on-list', on); 15506 b.innerHTML = on ? LBL_ON : LBL_ADD; 15507 } 15508 var m = document.querySelector('.gr-atlas-bl-option[data-gebied="' + gebied.replace(/"/g, '\\"') + '"]'); 15509 if (m) { 15510 m.classList.toggle('busy', !!busy); 15511 m.classList.toggle('on-list', on); 15512 m.innerHTML = (on ? _SVG_HEART : _SVG_HEART_EMPTY) + ' ' + (on ? LBL_SAVED_BUCKET : LBL_ADD_BUCKET); 15513 } 15514 } 15515 15516 function toggleBucketlist(gebied) { 15517 // Niet ingelogd â login-popup, net als op de Rondo-pagina's 15518 if (!myEmail) { _grAtlasVraagLogin(); return; } 15519 var isOn = myBucketlist.has(gebied); 15520 var ritId = _bucketRideMap[gebied]; 15521 if (!ritId) { console.warn('[GR Atlas] Geen rit voor', gebied); return; } 15522 var newStatus = isOn ? 'DELETE' : STATUS_GO; 15523 _syncBucketUI(gebied, true); 15524 fetch(SCRIPT_URL, { 15525 method: 'POST', mode: 'no-cors', headers: { 'Content-Type': 'application/json' }, 15526 body: JSON.stringify({ action: 'rsvp', ritId: ritId, email: myEmail, status: newStatus }) 15527 }) 15528 .then(function() { 15529 try { localStorage.removeItem(GR_CACHE_KEY); } catch(e) {} 15530 if (isOn) myBucketlist.delete(gebied); else myBucketlist.add(gebied); 15531 _syncBucketUI(gebied, false); 15532 refreshMarker(gebied); 15533 }) 15534 .catch(function() { _syncBucketUI(gebied, false); }); 15535 } 15536 15537 // ââ Labels & SVG-iconen ââ 15538 var _SVG_HEART = '<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" style="vertical-align:-2px;display:inline-block;pointer-events:none;"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.27 2 8.5 2 5.41 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.41 22 8.5c0 3.77-3.4 6.86-8.55 11.53L12 21.35z"/></svg>'; 15539 var _SVG_HEART_EMPTY = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align:-2px;display:inline-block;pointer-events:none;"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.27 2 8.5 2 5.41 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.41 22 8.5c0 3.77-3.4 6.86-8.55 11.53L12 21.35z"/></svg>'; 15540 var SVG_CALENDAR = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>'; 15541 var SVG_BOOK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path></svg>'; 15542 var SVG_SHOP = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path><line x1="3" y1="6" x2="21" y2="6"></line><path d="M16 10a4 4 0 0 1-8 0"></path></svg>'; 15543 var SVG_MENU = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="15" y2="18"></line></svg>'; 15544 var SVG_CLOSE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>'; 15545 var SVG_INFO = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>'; 15546 // Iconen â zelfde als palmares (18Ã18, stroke-based) 15547 var SVG_GLOBE = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>'; 15548 var SVG_EDIT = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>'; 15549 // Wireframe â-cirkel, zelfde lijnstijl als de andere icons
15550 // Liquid-teksten â bestaande keys eerst, nieuwe keys als fallback 15551 15552 var LBL_PLAN_RONDO = _grLbl('gr-planner-plan-rondo-tooltip', "Plan this Rondo"); 15553 var LBL_VIEW_GUIDE = _grLbl('gr-planner-view-guide', "View Rondo Guide"); 15554 var LBL_VIEW_ACTIVITY = "View activity"; 15555 var LBL_EDIT_ACTIVITY = _grLbl('gr-atlas-edit-activity', "Aanpassen"); 15556 var LBL_ADD_BUCKET = _grLbl('gr-atlas-add-bucketlist', "Zet op Bucketlist"); 15557 var LBL_SAVED_BUCKET = _grLbl('gr-atlas-saved-bucketlist', "Bewaard op Bucketlist"); 15558 var LBL_RONDO_VOL = _grLbl('gr-atlas-rondo-completed', "Rondo voltooid"); 15559 var LBL_VOLTOOID_OP = _grLbl('gr-atlas-completed-on', "Voltooid op"); 15560 var LBL_MIJN_ACT = _grLbl('gr-atlas-my-activities', "Jouw activiteiten"); 15561 var LBL_ORDER_RONDO = _grLbl('gr-planner-order-rondo', "Order this Rondo"); 15562 var LBL_ACTIONS = _grLbl('gr-planner-actions', "Acties"); 15563 var LBL_CLOSE = _grLbl('gr-planner-close', "Sluiten"); 15564 var LBL_VIEW_RONDO = _grLbl('gr-atlas-view-rondo', "Bekijk Rondo"); 15565 /* ââ Adressen in de taal van de bezoeker ââââââââââââââââââââââââââââââ 15566 Alles wat de kaart aanwijst â de Rondopagina, de gids, het event â staat 15567 in de sheet als https://granrondo.cc/products/⦠zonder taalvoorvoegsel. 15568 Op /en/ kwam je daardoor met één klik weer in het Nederlands terecht. 15569 15570 Deze functie zet het voorvoegsel van de huidige pagina ervoor. Buiten de 15571 hoofdtaal, wel te verstaan: op de Nederlandse site is er niets toe te 15572 voegen. Adressen naar een ander domein â Strava, Google Maps â blijven 15573 onaangeroerd; daar zegt ons taalvoorvoegsel niets. 15574
15575 Staat hier en niet in gr-atlas-html, omdat beide bestanden hem nodig 15576 hebben en dit het bestand is dat er zeker is als de kaart draait. */ 15577 window._grTaalUrl = function (url) { 15578 if (!url) return url; 15579 /* Een kale ankerlink hoort bij deze pagina en wordt geen volledig adres. */ 15580 if (String(url).charAt(0) === '#') return url; 15581 var taal = (location.pathname.split('/')[1] || ''); 15582 if (!/^[a-z]{2}$/.test(taal)) return url; 15583 try { 15584 var u = new URL(url, location.origin); 15585 if (u.host !== location.host) return url; 15586 if (u.pathname === '/' + taal || u.pathname.indexOf('/' + taal + '/') === 0) return url; 15587 u.pathname = '/' + taal + u.pathname; 15588 return u.toString(); 15589 } catch (e) { return url; } 15590 }; 15591 15592 /* Ook de inlogpagina: het pad stond hier vast op de Nederlandse versie, met 15593 locale=nl erachter. */ 15594 var LOGIN_TAAL = (function () { 15595 var t = (location.pathname.split('/')[1] || ''); 15596 return /^[a-z]{2}$/.test(t) ? t : 'nl'; 15597 })(); 15598 var LOGIN_URL = 'https://granrondo.cc/customer_authentication/login?return_to=' 15599 + encodeURIComponent((LOGIN_TAAL === 'nl' ? '' : '/' + LOGIN_TAAL) + '/pages/dashboard') 15600 + '&locale=' + LOGIN_TAAL; 15601 var LBL_MAP_LOADING = _grLbl('gr-atlas-map-loading', "Kaart ladenâ¦"); 15602 var LBL_LIB_LOADING = _grLbl('gr-atlas-lib-loading', "Kaartbibliotheek ladenâ¦"); 15603 var LBL_LIB_ERROR = _grLbl('gr-atlas-lib-error', "Kaartbibliotheek kon niet laden."); 15604 var LBL_DATA_LOADING = _grLbl('gr-atlas-data-loading', "Rondoâs ladenâ¦"); 15605 var LBL_MARKERS = _grLbl('gr-atlas-markers-placing', "Markers plaatsenâ¦"); 15606 var LBL_ROUTES_LOADING = _grLbl('gr-atlas-routes-loading', "Laden Rondo'sâ¦"); 15607 var LBL_MAP_ERROR = _grLbl('gr-atlas-map-error', "Kaart kon niet laden."); 15608 var LBL_ADMIN_DL = _grLbl('gr-atlas-admin-download', "⬠Download routes.json (admin)"); 15609 var LBL_LOADING = _grLbl('gr-atlas-loading', "Ladenâ¦"); 15610 var LBL_OPNIEUW = _grLbl('gr-atlas-retry', "Opnieuw proberen"); 15611 var LBL_ADD = _SVG_HEART_EMPTY + ' ' + LBL_ADD_BUCKET; 15612 var LBL_ON = _SVG_HEART + ' ' + LBL_SAVED_BUCKET; 15613 15614 // ââ routeDetails lookup ââ 15615 function _getRD(gebied, type) { 15616 var key = gebied + '|' + (type || ''); 15617 if (_routeDetails[key]) return _routeDetails[key]; 15618 var lKey = key.toLowerCase(); 15619 var ks = Object.keys(_routeDetails); 15620 var m = ks.find(function(k) { return k.toLowerCase() === lKey; }); 15621 if (m) return _routeDetails[m]; 15622 var lGeb = (gebied + '|').toLowerCase(); 15623 var pm = ks.find(function(k) { return k.toLowerCase().startsWith(lGeb); }); 15624 return pm ? _routeDetails[pm] : {}; 15625 } 15626 15627 // ââ Popup HTML ââ 15628 function buildPopupHTML(rit, routeRow, gebied) { 15629 var isBL = myBucketlist.has(gebied); 15630 var isRidden = riddenSet.has(gebied); 15631 var blTxt = isBL ? LBL_ON : LBL_ADD; 15632 var blCls = isBL ? 'on-list' : ''; 15633 var safeGebied = gebied.replace(/"/g, '"'); 15634 15635 // Naam + URLs via routeDetails 15636 var types = (rit.type || routeRow.Type || '').split(',').map(function(t) { return t.trim(); }).filter(Boolean); 15637 var rd0 = _getRD(gebied, types[0] || ''); 15638 var naam = rd0.naam || routeRow.Naam || routeRow.naam || rit.rondo || gebied; 15639 var shopUrl = rd0.shopLink || rd0.shop || ''; 15640 var guideUrl = rd0.guideUrl || rd0.guide || rd0.guideLink || shopUrl; 15641 // Event: eigen links (bij tickets de -event-variant) gaan vóór routeDetails; 15642 // die gaan mee als terugval, anders mist een event zonder eigen shopLink 15643 // de opties Meedoen aan dit event en Bestel deze Rondo. 15644 var _ev = (window._grAtlasEventBlok && window._grAtlasEventBlok(rit, _atlasUserTags, { 15645 shop: rd0.shopLink || rd0.shop || '', 15646 guide: rd0.guideUrl || rd0.guide || rd0.guideLink || '', 15647 opBucketlist: isBL, gebied: gebied 15648 })) || {}; 15649 if (_ev.shop) shopUrl = _ev.shop; 15650 if (_ev.gids) guideUrl = _ev.gids; 15651 // Terugval uit routeDetails krijgt hetzelfde -event achtervoegsel. 15652 function _evSuf(u) { 15653 return (_ev.suffix && u && u.slice(-_ev.suffix.length) !== _ev.suffix) ? u + _ev.suffix : u; 15654 } 15655 if (!_ev.shop) shopUrl = _evSuf(shopUrl); 15656 if (!_ev.gids) guideUrl = _evSuf(guideUrl); 15657 15658 // Welke types zijn al voltooid?
15659 var riddenEntries = riddenMap[gebied] || []; 15660 var riddenTypes = riddenEntries.map(function(e) { return (e.type || '').trim().toLowerCase(); }); 15661 15662 // Stats â ROAD 173km â GRAVEL 120km 15663 var statsHtml = ''; 15664 var typesUsed = types.length ? types : ['']; 15665 typesUsed.forEach(function(type) { 15666 var rd = type ? _getRD(gebied, type) : rd0; 15667 var km = rd.km || rd.afstand || routeRow.KM || ''; 15668 if (!type && !km) return; 15669 var label = (type || '').toUpperCase(); 15670 var kmStr = km ? ' ' + String(km).replace('.', ',') + 'km' : ''; 15671 var typeRidden = type && riddenTypes.indexOf(type.toLowerCase()) !== -1; 15672 var check = typeRidden ? '<span class="gr-atlas-stat-check" title="' + LBL_RONDO_VOL + '">â</span>' : ''; 15673 statsHtml += '<span class="gr-atlas-stat-item">' + label + kmStr + check + '</span>'; 15674 }); 15675 15676 // Datumnotatie 19-6-2026. new Date() leest de NL-volgorde niet, vandaar 15677 // eerst zelf matchen; anders kwam de ruwe tekst mét tijdstip terug. 15678 function _fmtDatum(raw) { 15679 if (!raw) return ''; 15680 var s = String(raw).trim(); 15681 var m = s.match(/^(\d{1,2})[-\/](\d{1,2})[-\/](\d{4})/); 15682 if (m) return parseInt(m[1], 10) + '-' + parseInt(m[2], 10) + '-' + m[3]; 15683 var d = new Date(s); 15684 if (!isNaN(d.getTime())) return d.getDate() + '-' + (d.getMonth() + 1) + '-' + d.getFullYear(); 15685 return s.split(/[ T]/)[0]; // laatste redmiddel: alles ná de datum weglaten 15686 } 15687 15688 // Kaartje 15689 var mapHtml = ''; 15690 var mapImg = rd0.mapImg || rd0.mapImage || rd0.kaart || ''; 15691 if (mapImg) { 15692 mapHtml = '<div class="route-map-wrap"><img src="' + mapImg + '" class="route-map-img" alt="kaart" loading="lazy"></div>'; 15693 } 15694 15695 // Rechtencheck â zelfde logica als de Rondo Planner 15696 var _areaTag = (_areaTags[gebied] || '').trim().toLowerCase(); 15697 var _hasArea = !!(_areaTag && _atlasUserTags.indexOf(_areaTag) !== -1); 15698 /* Rondogids â bij een ticket-event telt alleen je eventtag. Niet je 15699 Rondoneur- of gebiedstag, en ook de adminvlag niet: de gids van een event 15700 hoort achter het ticket te blijven, ook voor jezelf. Bij een gewone Rondo 15701 verandert er niets. */ 15702 var _magPlannen = _atlasIsAdmin || _atlasIsRondoneur || _hasArea; 15703 /* _ev.hadTicket zit in de tweede tak voor events die geweest zijn: die 15704 gelden hier verder als gewone Rondo, en zonder deze toevoeging zou je de 15705 gids kwijtraken op de dag ná het event waar je bij was. */ 15706 var _showBook = _ev.isTicket 15707 ? !!_ev.heeftTicket 15708 : (_atlasIsAdmin || _atlasIsRondoneur || _hasArea || !!_ev.hadTicket); 15709 var _guideHref = guideUrl || (_showBook && shopUrl ? shopUrl : ''); 15710 15711 /* Geen hamburger meer in het kaartpaneel. Alles staat nu of in de 15712 RSVP-popover rechtsboven, of als knop onder in het paneel. */ 15713 var _heeftGids = !!(_showBook && _guideHref); 15714 15715 var actionBar = '<div class="gr-atlas-panel-menu">' 15716 + (_ev.rsvp || '') 15717 + '<button type="button" class="btn-icon-svg gr-atlas-panel-close" title="' + LBL_CLOSE + '"' 15718 + ' onclick="event.stopPropagation();window._grAtlasClosePanel()">' + SVG_CLOSE + '</button>' 15719 + '</div>'; 15720 15721 /* Knoppenrij onderin. Rondogids en Meedoen sluiten elkaar uit: heb 15722 je toegang tot de gids, dan heb je het ticket al. */ 15723 /* Bij een event krijgt de gidsknop de actiekleur: dat is dan de enige knop 15724 die ergens heen gaat, en die hoort op te vallen. Bij een gewone Rondo 15725 blijft hij donker, want daar staat Bekijk Rondo er nog naast. */ 15726 var _gidsKlasse = 'gr-atlas-btn gr-atlas-btn-view' + (_ev.isTicket ? ' gr-atlas-btn-actie' : ''); 15727 var _knoppen = 15728 (_heeftGids 15729 ? '<a class="' + _gidsKlasse + '" href="' + window._grTaalUrl(_guideHref) + '" target="_blank" rel="noopener">' + LBL_VIEW_GUIDE + '</a>' 15730 : (_ev.ticketBtn || '')) 15731 /* Bekijk Rondo alleen bij een gewone Rondo. Bij een event wees hij naar 15732 dezelfde winkelpagina als de knop erboven â twee knoppen onder elkaar 15733 met hetzelfde doel, en juist bij een event is het de vraag welke van de 15734 twee je hebben moet. Nu is er één weg: de eventpagina, of de gids. */ 15735 + (shopUrl && !_ev.isTicket 15736 ? '<a class="gr-atlas-btn gr-atlas-btn-view" href="' + window._grTaalUrl(shopUrl) + '" target="_blank" rel="noopener">' + LBL_VIEW_RONDO + '</a>' 15737 : '') 15738 /* Rondo voltooid â opent het activiteitenformulier met dit gebied al 15739 ingevuld. Alleen voor ingelogde rijders; uitgelogd valt er niets te 15740 registreren. */ 15741 + (_isLoggedIn 15742 ? '<button type="button" class="gr-atlas-btn gr-atlas-btn-view gr-atlas-btn-omgekeerd"' 15743 + ' data-gebied="' + safeGebied + '"' 15744 + ' onclick="event.stopPropagation();window._grAtlasOpenActivity(this.dataset.gebied)">' 15745 + LBL_RONDO_VOL + '</button>' 15746 : ''); 15747 15748 // Voltooide ritten lijst (onder knoppen) 15749 var voltooidHtml = ''; 15750 if (isRidden && riddenEntries.length) { 15751 var vLines = riddenEntries.map(function(e) { 15752 var datumTxt = _fmtDatum(e.datum); 15753 var typeTxt = e.type ? ' (' + e.type + ')' : '';
15754 var lblTxt = LBL_VOLTOOID_OP + (datumTxt ? ' ' + datumTxt : '') + typeTxt; 15755 var safeDatum = String(e.datum || '').replace(/"/g, '"'); 15756 15757 // Label linkt naar de activiteit (Strava) wanneer er een URL is 15758 // Zelfde â-cirkel als achter de stats, vóór het label 15759 var lblInner = '<span class="gr-atlas-stat-check" title="' + LBL_RONDO_VOL + '">✓</span> ' + lblTxt; 15760 var lblHtml = e.url 15761 ? '<a href="' + e.url + '" target="_blank" rel="noopener" class="gr-atlas-voltooid-label" title="' + LBL_VIEW_ACTIVITY + '">' + lblInner + '</a>' 15762 : '<span class="gr-atlas-voltooid-label">' + lblInner + '</span>'; 15763 15764 // Globe â activiteit op Strava 15765 var stravaIcon = e.url 15766 ? '<a href="' + e.url + '" target="_blank" rel="noopener" class="gr-atlas-edit-btn" title="' + LBL_VIEW_ACTIVITY + '">' + SVG_GLOBE + '</a>' 15767 : ''; 15768 15769 // Potlood â palmares-bewerkpopup 15770 var editIcon = '<button class="gr-atlas-edit-btn" title="' + LBL_EDIT_ACTIVITY + '"' 15771 + ' data-gebied="' + safeGebied + '" data-datum="' + safeDatum + '"' 15772 + ' onclick="window._grAtlasEditActivity(this.dataset.gebied,this.dataset.datum)">' + SVG_EDIT + '</button>'; 15773 15774 return '<div class="gr-atlas-voltooid-row">' 15775 + lblHtml + stravaIcon + editIcon 15776 + '</div>'; 15777 }); 15778 /* Kop alleen als er ook echt iets onder staat; deze tak draait al binnen 15779 if (isRidden && riddenEntries.length), dus dat is hier gegeven. */ 15780 voltooidHtml = '<div class="gr-atlas-voltooid-kop"><h4>' + LBL_MIJN_ACT + '</h4></div>' 15781 + '<div class="gr-atlas-voltooid-list">' + vLines.join('') + '</div>'; 15782 } 15783 15784 return actionBar 15785 + (_ev.datums || '') 15786 + '<strong class="gr-atlas-popup-title">' + naam + '</strong>' 15787 + (_ev.naam || '') 15788 + (statsHtml ? '<div class="gr-atlas-popup-meta">' + statsHtml + '</div>' : '') 15789 + mapHtml 15790 + (_ev.details || '') 15791 + '<div class="gr-atlas-popup-btns">' + _knoppen + '</div>' 15792 + voltooidHtml; 15793 } 15794 15795 window._grAtlasToggleBL = function(gebied) { toggleBucketlist(gebied); }; 15796 // Haken voor gr-atlas-locaties.html (start-, Rondobox- en rustlocaties). 15797 window._grAtlasKaart = map; 15798 window._grAtlasOpenPanel = openPanel; 15799 15800 // ââ Hamburger actie-menu ââ 15801 // Inline display i.p.v. een CSS-klasse: kan niet door thema-CSS overruled worden. 15802 function _menuPop() { return document.getElementById('gr-atlas-action-popover'); } 15803 function _menuIsOpen(p) { return !!p && p.style.display === 'block'; } 15804 window._grAtlasToggleMenu = function(force) { 15805 var pop = _menuPop(); 15806 if (!pop) return; 15807 var open = (typeof force === 'boolean') ? force : !_menuIsOpen(pop); 15808 pop.style.display = open ? 'block' : 'none'; 15809 pop.classList.toggle('show', open); 15810 }; 15811 window._grAtlasCloseMenu = function() { window._grAtlasToggleMenu(false); }; 15812 window._grAtlasClosePanel = function() { window._grAtlasCloseMenu(); closePanel(); }; 15813 15814 // Eén gedelegeerde listener: opent bij een klik op de hamburger, sluit daarbuiten. 15815 document.addEventListener('click', function(e) { 15816 var t = e.target; 15817 if (!t || !t.closest) return; 15818 if (t.closest('[data-gr-menu-toggle]')) { 15819 e.preventDefault(); e.stopPropagation(); 15820 window._grAtlasToggleMenu(); 15821 return; 15822 } 15823 if (t.closest('.gr-atlas-menu-wrapper')) return; // klik binnen het menu zelf 15824 window._grAtlasCloseMenu(); 15825 }); 15826 15827 // ââ Activiteit-Voltooid formulier openen ââ 15828 // Gebruikt bij voorkeur de palmares-bridge (doet profielcheck + formulier-init). 15829 window._grAtlasOpenActivity = function(gebied) { 15830 // 1. Palmares-bridge â de echte functionaliteit 15831 if (typeof window.grPalOpenActivityForm === 'function') { 15832 if (window.grPalOpenActivityForm(gebied)) { closePanel(); return; } 15833 } 15834 // 2. Bestaande delegated handler (.open-rit-modal-btn) 15835 var modal = document.getElementById('ritModal'); 15836 if (!modal) { console.warn('[GR Atlas] ritModal niet op deze pagina â activiteitenformulier ontbreekt'); return; } 15837 window._pendingVoltooidRide = null; 15838 window._pendingVoltooidId = null; 15839 var trigger = document.createElement('span'); 15840 trigger.className = 'open-rit-modal-btn'; 15841 trigger.style.display = 'none'; 15842 document.body.appendChild(trigger); 15843 trigger.click(); 15844 if (trigger.parentNode) trigger.parentNode.removeChild(trigger); 15845 // 3. Laatste redmiddel: modal zelf openen 15846 if (getComputedStyle(modal).display === 'none') { 15847 modal.style.display = 'flex'; 15848 document.body.classList.add('modal-open'); 15849 } 15850 closePanel(); 15851 }; 15852 15853 // ââ Bewaarde activiteit bewerken ââ 15854 window._grAtlasEditActivity = function(gebied, datum) { 15855 // grPalOpenEditByGebied haalt de activiteiten zo nodig zelf op, dus dit 15856 // werkt ongeacht welke dashboard-tab openstaat. 15857 if (typeof window.grPalOpenEditByGebied === 'function') { 15858 if (window.grPalOpenEditByGebied(gebied, datum)) { closePanel(); return; } 15859 } 15860 console.warn('[GR Atlas] Bewerken niet mogelijk: palmares-bewerkpopup ontbreekt op deze pagina.', gebied, datum); 15861 }; 15862 15863 /* Routerijen voor de admin-export in gr-atlas-admin.html. */ 15864 window._grAtlasExportBron = function () { 15865 if (Object.keys(_alleRoutes).length) return _alleRoutes; 15866 var uit = {};
15867 Object.keys(markers).forEach(function (g) { uit[g] = markers[g].data || {}; }); 15868 return uit; 15869 }; 15870 15871 /* Wat gr-atlas-filters nodig heeft om te kunnen filteren: per gebied de 15872 routetypes (uit de sleutels "Gebied|Type" van routeDetails), of het 15873 voltooid is, en of er een ticket-event aan hangt. */ 15874 function publiceerMeta() { 15875 var meta = {}; 15876 Object.keys(markers).forEach(function(g) { 15877 var typen = []; 15878 Object.keys(_routeDetails).forEach(function(k) { 15879 var i = k.lastIndexOf('|'); 15880 if (i > 0 && k.slice(0, i) === g) { 15881 var t = k.slice(i + 1).trim().toLowerCase(); 15882 if (t && typen.indexOf(t) === -1) typen.push(t); 15883 } 15884 }); 15885 meta[g] = { typen: typen, voltooid: riddenSet.has(g), 15886 bucket: myBucketlist.has(g), event: _eventSet.has(g) }; 15887 }); 15888 window._grAtlasMeta = meta; 15889 try { document.dispatchEvent(new CustomEvent('gr:atlas-meta')); } catch (e) {} 15890 } 15891 15892 // ââ Hoofd-logica ââ elk verzoek krijgt een harde deadline. 15893 function _withTimeout(p, ms, fallback, naam) { 15894 /* De wekker moet uit zodra het antwoord binnen is. Zonder die regel bleef 15895 hij lopen ook als de race allang gewonnen was, en stond er dertig 15896 seconden later alsnog "duurde te lang" in de console â bij elk van de 15897 drie, terwijl de gegevens er in anderhalve seconde waren. Verwarrend bij 15898 het zoeken, en het houdt drie timers in leven op elke paginaweergave. */ 15899 var wekker; 15900 return Promise.race([ 15901 p, 15902 new Promise(function(resolve) { 15903 wekker = setTimeout(function() { 15904 console.warn('[GR Atlas] ' + naam + ' duurde te lang (' + ms + 'ms) â overgeslagen.'); 15905 resolve(fallback); 15906 }, ms); 15907 }) 15908 ]).then(function (r) { clearTimeout(wekker); return r; }, 15909 function (e) { clearTimeout(wekker); throw e; }); 15910 } 15911 15912 setStatus(LBL_DATA_LOADING); 15913 Promise.all([ 15914 _withTimeout(fetch(ROUTES_URL).then(function(r) { return r.json(); }).catch(function() { return []; }), 30000, [], 'routes-sheet'), 15915 _withTimeout(fetch(ACT_URL).then(function(r) { return r.json(); }).catch(function() { return []; }), 30000, [], 'activiteiten-sheet'), 15916 _withTimeout(loadPlannerData(), 30000, {}, 'planner-data') 15917 ]) 15918 .then(function(res) { 15919 var routes = res[0] || []; 15920 var acts = res[1] || []; 15921 var plannerData = res[2] || {}; 15922 15923 // Voltooide ritten via Activiteiten-sheet 15924 // Activiteit-URL zit in kolom 'URL' (zelfde als palmares renderItem) 15925 var lowerMe = (myEmail || '').toLowerCase();
15926 acts.forEach(function(a) { 15927 if ((a['E-mailadres'] || '').trim().toLowerCase() === lowerMe) { 15928 var g = (a['Gebied'] || '').trim(); 15929 if (g) { 15930 riddenSet.add(g); 15931 var url = (a['URL'] || '').trim(); 15932 if (url === 'https://' || url === '#') url = ''; 15933 if (!riddenMap[g]) riddenMap[g] = []; 15934 riddenMap[g].push({ 15935 url: url, 15936 datum: a['Datum Start'] || a['Datum'] || '', 15937 type: a['Type'] || a['Soort'] || '', 15938 ritId: a['Rit ID'] || a['RitId'] || a['ritId'] || a['Rit_ID'] || '' 15939 }); 15940 } 15941 } 15942 }); 15943 // Fallback: planner-ritten met STATUS_VOLTOOID 15944 var STATUS_VOLTOOID = 'Rondo Voltooid'; 15945 (plannerData.ritten || []).forEach(function(r) { 15946 if (r.status === STATUS_VOLTOOID && r.rondo) riddenSet.add(r.rondo); 15947 }); 15948 // Fallback 2: activiteitenTags + areaTags (zelfde check als planner voltooid-tab) 15949 var activiteitenTags = plannerData.activiteitenTags || []; 15950 var areaTags = plannerData.areaTags || {}; 15951 var userActTags = activiteitenTags 15952 .filter(function(a) { return (a.email || '').toLowerCase() === lowerMe; }) 15953 .map(function(a) { return (a.tag || '').toLowerCase(); }) 15954 .filter(Boolean); 15955 15956 // Bucketlist ritten 15957 var blRitten = parsePlannerData(plannerData); 15958 15959 // Markeer gebieden als voltooid via activiteitenTags (zelfde logica als planner voltooid-tab) 15960 blRitten.forEach(function(r) { 15961 if (!r.rondo) return; 15962 var aTag = (areaTags[r.rondo] || '').toLowerCase(); 15963 if (aTag && userActTags.indexOf(aTag) !== -1) riddenSet.add(r.rondo); 15964 }); 15965 console.log('[GR Atlas] Bucketlist ritten:', blRitten.length, '| User BL:', Array.from(myBucketlist)); 15966 15967 // Coördinaten lookup via routes-sheet 15968 var routeByGebied = {}; 15969 routes.forEach(function(row) { 15970 var g = (row['Gebied'] || '').trim(); 15971 if (g && !routeByGebied[g]) routeByGebied[g] = row; 15972 }); 15973 _alleRoutes = routeByGebied; // admin-export exporteert álle routes, niet alleen je bucketlist 15974 15975 var placed = 0, total = blRitten.length; 15976 if (total === 0) { hideStatus(); return; } 15977 setStatus(LBL_MARKERS + ' (0/' + total + ')'); 15978 var uncachedDelay = 0; 15979 15980 // Wachten op de routebundel: anders geocoderen we alsnog onnodig. 15981 var _bundelP = (window.GRGpx && window.GRGpx.bundel) ? window.GRGpx.bundel() : Promise.resolve({}); 15982 _bundelP.then(function(_bp) { plaatsMarkers(_bp || {}); }); 15983 15984 function plaatsMarkers(_bp) { 15985 blRitten.forEach(function(rit) { 15986 var gebied = rit.rondo || rit.id; 15987 var routeRow = routeByGebied[gebied] || {}; 15988 15989 function onMarkerPlaced(ll) { 15990 placed++; 15991 setStatus(LBL_MARKERS + ' (' + placed + '/' + total + ')'); 15992 if (placed >= total) { publiceerMeta(); markersAf(); } 15993 if (!ll) { console.warn('[GR Atlas] Geen coördinaten voor:', gebied); return; } 15994 markers[gebied] = { data: routeRow }; 15995 15996 // GPX route laden en tekenen 15997 var gpxUrl = routeRow['Routes_GPX'] || routeRow['GPX'] || routeRow['Gpx'] || routeRow['gpx'] 15998 || routeRow['GPX URL'] || routeRow['GPX Link'] || routeRow['Routes_gpx'] || ''; 15999 if (gpxUrl && gpxUrl.startsWith('http')) { 16000 (function(r, rw, g, url) { 16001 function teken(lls) { 16002 if (!lls || !lls.length) return; 16003 var clickFn = function() { openPanel(buildPopupHTML(r, rw, g), g); }; 16004 var routeColor = (rw['Routes_Kleur'] || rw['Kleur'] || '').trim(); 16005 drawGPXRoute(lls, getStatus(g), g, clickFn, routeColor); 16006 } 16007 gpxAangemeld(); 16008 _gpxLaad(url, ll && ll.lat, ll && ll.lng, g) 16009 .then(function(lls) { if (lls && lls.length) teken(lls); }) 16010 .catch(function(err) { console.warn('[GR Atlas GPX] fout', g, err); }) 16011 .then(gpxAf); 16012 })(rit, routeRow, gebied, gpxUrl); 16013 } 16014 } 16015 16016 var latOk = routeRow['Lat'] && !isNaN(parseFloat(routeRow['Lat'])); 16017 var lngOk = routeRow['Lng'] && !isNaN(parseFloat(routeRow['Lng'])); 16018 if (latOk && lngOk) { 16019 onMarkerPlaced({ lat: parseFloat(routeRow['Lat']), lng: parseFloat(routeRow['Lng']) }); 16020 } else if (geoCache[gebied]) { 16021 onMarkerPlaced(geoCache[gebied]); 16022 } else if (_bp[gebied] && _bp[gebied].length) { 16023 // Startpunt uit de bundel: preciezer dan Nominatim én meteen bruikbaar. 16024 var p0 = _bp[gebied][0]; 16025 onMarkerPlaced({ lat: p0[0], lng: p0[1] }); 16026 } else { 16027 // Laatste redmiddel; Nominatim staat 1 verzoek/seconde toe. 16028 uncachedDelay += 1200; 16029 (function(g, cb) { 16030 setTimeout(function() { geocode(g).then(cb); }, uncachedDelay); 16031 })(gebied, onMarkerPlaced); 16032 } 16033 }); 16034 if (uncachedDelay) { 16035 console.info('[GR Atlas] ' + Math.round(uncachedDelay/1200) + ' gebied(en) gegeocodeerd â voeg Lat/Lng of GPX toe om dat te vermijden.'); 16036 } 16037 } 16038 }) 16039 .catch(function(err) { 16040 console.error('[GR Atlas] Fout:', err); 16041 setStatus(LBL_MAP_ERROR, false); 16042 }); 16043} // ââ einde _grAtlasInit ââ 16044 16045// ââ Starten ââ 16046var _grAtlasStarted = false;
16047var _grLeafletLoading = false; 16048 16049function _grSetStatus(msg) { 16050 var s = document.getElementById('gr-atlas-status'); 16051 if (s) { s.style.display = ''; s.textContent = msg; } 16052} 16053 16054// Altijd via window.L testen: een kale `L` kan het labels-object van 16055// planner-script1 zijn (const L) in plaats van Leaflet. 16056function _grHasLeaflet() { return !!(window.L && window.L.map && window.L.tileLayer); } 16057 16058// Leaflet zelf inladen als het er nog niet is. Zo maakt de plek van dit 16059// script in de pagina (footer, header, snippet) niet meer uit. 16060var _grLeafletTries = 0; 16061function _grLoadLeaflet(done) { 16062 if (_grHasLeaflet()) { done(); return; } 16063 if (_grLeafletLoading) return; 16064 if (++_grLeafletTries > 2) { 16065 console.error('[GR Atlas] Leaflet blijft ontbreken na ' + _grLeafletTries + ' pogingen.'); 16066 _grSetStatus(LBL_LIB_ERROR); 16067 return; 16068 } 16069 _grLeafletLoading = true; 16070 _grSetStatus(LBL_LIB_LOADING); 16071 16072 if (!document.querySelector('link[href*="leaflet"]')) { 16073 var css = document.createElement('link'); 16074 css.rel = 'stylesheet'; 16075 css.href = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css'; 16076 document.head.appendChild(css); 16077 } 16078 // Altijd een verse tag: als we hier zijn is L niet gedefinieerd, dus een 16079 // eventuele bestaande tag heeft gefaald of is nog niet uitgevoerd. 16080 var js = document.createElement('script'); 16081 js.src = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js'; 16082 js.onload = function () { _grLeafletLoading = false; done(); }; 16083 js.onerror = function () { 16084 _grLeafletLoading = false; 16085 console.error('[GR Atlas] Leaflet kon niet geladen worden (CDN geblokkeerd?).'); 16086 _grSetStatus(LBL_LIB_ERROR); 16087 }; 16088 document.head.appendChild(js); 16089} 16090 16091function _grAtlasBoot() { 16092 if (_grAtlasStarted) return true; 16093 var el = document.getElementById('gr-atlas-map'); 16094 if (!el) return false; // atlas niet op deze pagina 16095 if (el._grAtlasReady) return true; // al opgebouwd 16096 16097 if (!_grHasLeaflet()) { // Leaflet ontbreekt â zelf ophalen 16098 _grLoadLeaflet(function () { _grAtlasBoot(); }); 16099 return true; // pollen mag stoppen 16100 } 16101 16102 _grAtlasStarted = true; 16103 el._grAtlasReady = true; 16104 try { 16105 _grAtlasInit(el); 16106 } catch (e) { 16107 console.error('[GR Atlas] Initialisatie mislukt:', e); 16108 _grSetStatus(LBL_MAP_ERROR); 16109 } 16110 return true; 16111} 16112 16113// Nu proberen; anders bij DOM-ready; anders kort pollen (HTML kan later 16114// ingeladen worden, bijvoorbeeld door een dashboard-tab). 16115if (!_grAtlasBoot()) { 16116 if (document.readyState === 'loading') { 16117 document.addEventListener('DOMContentLoaded', function () { _grAtlasBoot(); }); 16118 } 16119 var _tries = 0; 16120 var _poll = setInterval(function () { 16121 if (_grAtlasBoot() || ++_tries > 40) clearInterval(_poll); // max ~10s 16122 }, 250); 16123} 16124})(); 16125</script>
16125 16126 16127 16128 16129 16130 16131<style> 16132 /* ââ Bolletje op de kaart ââ */ 16133 .gr-loc-pin { 16134 display: flex; align-items: center; justify-content: center; 16135 width: 30px; height: 30px; border-radius: 50%; 16136 box-shadow: 0 1px 4px rgba(0,0,0,.35); cursor: pointer; 16137 box-sizing: border-box; border: 2px solid rgba(255,255,255,.9); 16138 transition: transform .15s; 16139 } 16140 .gr-loc-pin:hover { transform: scale(1.12); } 16141 .gr-loc-pin svg { width: 16px; height: 16px; display: block; } 16142 .gr-loc-pin.is-start { background: var(--color-brand, #E84B20); color: #fff; } 16143 .gr-loc-pin.is-rondobox { background: var(--color-action, #E9483F); color: #fff; } 16144 /* Rustlocaties: lichte achtergrond met een wit icoon, net als de andere twee. */ 16145 .gr-loc-pin.is-rust { 16146 background: var(--color-light, #D5D9F5); 16147 color: #fff; 16148 } 16149 /* Leaflet zet een eigen achtergrond op divIcons; die weg. 16150 Let op de selector: het marker-element krijgt in deze Leaflet-versie 16151 leaflet-marker-icon, niet leaflet-div-icon. Gemeten op de live kaart: 16152 class="leaflet-marker-icon gr-loc-icon leaflet-zoom-animated leaflet-interactive". 16153 Een regel op .leaflet-div-icon raakt dus niets. */ 16154 .leaflet-marker-icon.gr-loc-icon { background: none; border: none; } 16155 16156 /* ââ Start- en rustlocaties horen bij één route ââââââââââââââââââââââââââ 16157 Ze staan niet meer standaard op de kaart: pas als je een routelijn 16158 aanklikt verschijnen die van dát gebied, in de kleur van de lijn. 16159 Rondobox-locaties krijgen deze klasse niet en blijven dus altijd staan. 16160 16161 Verbergen gebeurt met een klasse en niet met style.display, omdat de 16162 filterknoppen in gr-atlas-html style.display al gebruiken. Twee partijen 16163 op dezelfde eigenschap gaan elkaar tegenwerken; zo blijven ze uit elkaar. 16164 Een inline display:none van het filter wint alsnog van deze regel, en dat 16165 is precies goed: weggefilterd blijft weggefilterd. */ 16166 .gr-loc-icon.gr-loc-bij-route { display: none; } 16167 .gr-loc-icon.gr-loc-bij-route.gr-loc-aan { display: block; } 16168 16169 /* ââ Rondobox bij de stand Voltooid ââââââââââââââââââââââââââââââââââââââ 16170 Rondobox-locaties staan er normaal altijd, want ze horen bij geen enkele 16171 route. Maar bij Voltooid kijk je naar wat jÃj gereden hebt, en een winkel 16172 hoort daar niet tussen. 16173 16174 Via een klasse op de kaart en niet per marker: de bolletjes komen na elkaar 16175 binnen, en eentje die ná het filteren wordt geplaatst zou anders alsnog 16176 verschijnen. Nu geldt de regel voor alles wat er is en nog komt. */ 16177 #gr-atlas-map.gr-filter-voltooid .gr-loc-icon.gr-loc-rondobox { display: none !important; } 16178 16179 /* Start en rust dragen hetzelfde koffie-icoon, dus met allebei de routekleur 16180 zijn ze niet meer uit elkaar te houden. Start wordt gevuld, rust omlijnd 16181 met dezelfde kleur. De kleur zelf zet het script per route inline. */ 16182 .gr-loc-pin.gr-loc-route-rust { 16183 background: var(--color-white) !important; 16184 border-width: 3px; 16185 } 16186 16187 /* ââ Locatieblok onder de route in het paneel ââââââââââââââââââââââââââ */ 16188 .gr-loc-blok { 16189 border-top: 1px solid #e5e5f0; 16190 margin-top: 35px; 16191 padding-top: 35px; 16192 } 16193 16194 /* ââ Locatie in het zijpaneel ââ */ 16195 /* Pillen staan onder de titel, dus de ruimte zit nu onder de pillen en niet 16196 meer erboven. */ 16197 .gr-loc-pills { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; } 16198 .gr-loc-pill { 16199 display: inline-block; margin: 0; padding: 6px 12px; border-radius: 999px; 16200 font-family: 'ashemore', sans-serif; 16201 font-size: 15px; font-weight: 700; line-height: 1.2; 16202 text-transform: uppercase; white-space: nowrap; 16203 color: var(--color-dark, #271D62); background: var(--color-lighter, #EFF1FD); 16204 } 16205 .gr-loc-pill.is-start { background: var(--color-brand, #E84B20); color: #fff; } 16206 .gr-loc-pill.is-rondobox { background: var(--color-action, #E9483F); color: #fff; } 16207 .gr-loc-pill.is-rust { background: var(--color-light, #D5D9F5); } 16208 .gr-loc-titel { 16209 display: block; font-weight: 700; font-size: 1.7rem; 16210 font-family: 'Rum Raisin', sans-serif; text-transform: uppercase; 16211 color: var(--color-dark, #271D62); line-height: 1.15; margin: 0 0 8px; 16212 } 16213 .gr-loc-kaart { 16214 width: 100%; aspect-ratio: 4 / 3; border: 0; border-radius: 12px; 16215 overflow: hidden; display: block; background: #eef0f6; 16216 } 16217 .gr-loc-knoppen { display: flex; flex-direction: column; gap: 8px; margin: 16px 0; } 16218</style> 16219
16220<script> 16221(function () { 16222 'use strict'; 16223 16224 /* Google Maps Embed API-sleutel. Laat leeg voor de variant zonder sleutel; 16225 die werkt ook, maar zoekt op naam in plaats van een vaste plek te tonen. 16226 Zet in Google Cloud "Maps Embed API" aan en beperk de sleutel tot je eigen 16227 domein voor je hem hier neerzet. */ 16228 var MAPS_KEY = ""; 16229 16230 var ROUTES_URL = 'https://opensheet.elk.sh/1_Bc2komUMc7pVNT8rQkO0_Djnh41O5wCOvBMozarCms/routes'; 16231 var GEO_KEY = 'grAtlasLocGeo'; 16232 var GEO_TTL = 30 * 24 * 3600 * 1000; 16233 16234 window._grAtlasLocVersie = 'gr-atlas-locaties 2026-09-05a'; 16235 if (!window._grAtlasStil) console.log('[GR Atlas]', window._grAtlasLocVersie); 16236 16237 /* De Engelse tabel staat in deel 2 en is daar als window._grLbl gedeeld. 16238 Ontbreekt die â deel 2 gooide een fout, of dit bestand staat los â dan 16239 blijft de tekst uit het metaobject staan in plaats van te breken. */ 16240 function _grLbl(sleutel, viaMetaobject) { 16241 return window._grLbl ? window._grLbl(sleutel, viaMetaobject) : viaMetaobject; 16242 } 16243 16244 var LBL = { 16245 start: _grLbl('gr-atlas-loc-start', "Start\/Rust"), 16246 rust: _grLbl('gr-atlas-loc-rust', "Rustlocatie"), 16247 rondobox: _grLbl('gr-atlas-loc-rondobox', "Rondobox Store"), 16248 route: _grLbl('gr-atlas-loc-route', "Route naar Locatie"), 16249 sluit: "Sluiten" 16250 }; 16251 16252 var SVG_KOFFIE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"' 16253 + ' stroke-linecap="round" stroke-linejoin="round"><path d="M17 8h1a4 4 0 1 1 0 8h-1"/>' 16254 + '<path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4z"/><line x1="6" y1="1" x2="6" y2="4"/>' 16255 + '<line x1="10" y1="1" x2="10" y2="4"/><line x1="14" y1="1" x2="14" y2="4"/></svg>'; 16256 var SVG_KADO = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"' 16257 + ' stroke-linecap="round" stroke-linejoin="round"><polyline points="20 12 20 22 4 22 4 12"/>' 16258 + '<rect x="2" y="7" width="20" height="5"/><line x1="12" y1="22" x2="12" y2="7"/>' 16259 + '<path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/>' 16260 + '<path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>'; 16261 16262 function waar(v) { return String(v == null ? '' : v).trim().toUpperCase() === 'TRUE'; } 16263 function tekst(v) { return String(v == null ? '' : v).trim(); } 16264 function esc(s) { 16265 return String(s).replace(/&/g, '&').replace(/</g, '<') 16266 .replace(/>/g, '>').replace(/"/g, '"'); 16267 } 16268 16269 /* ââ Locatielijst uit de routes-rijen ââââââââââââââââââââââââââââââââââ 16270 Eén locatie per gebied+naam: dezelfde startlocatie staat vaak bij zowel de 16271 Road- als de Gravelrij. Rondobox wint van de gewone startlocatie wanneer 16272 beide vinkjes aanstaan. */ 16273 function bouwLijst(rijen) { 16274 var perSleutel = {}, volgorde = []; 16275 function pak(soort, gebied, naam, link, type) { 16276 var s = soort + '|' + gebied + '|' + naam.toLowerCase(); 16277 if (!perSleutel[s]) { 16278 perSleutel[s] = { sleutel: s, soort: soort, rondobox: false, gebied: gebied, 16279 naam: naam, link: '', typen: [] }; 16280 volgorde.push(s); 16281 } 16282 /* Eerste niet-lege link wint; de Road- en Gravelrij vullen 'm niet altijd allebei. */ 16283 if (link && !perSleutel[s].link) perSleutel[s].link = link; 16284 /* Eén gebied kan meerdere start- of rustlocaties hebben: een andere voor de 16285 Road- dan voor de Gravelronde. Ze krijgen elk een eigen bolletje (de 16286 sleutel bevat de naam). Het routetype wordt wel verzameld â handig bij 16287 het opsporen van dubbelingen â maar staat niet in het paneel. */ 16288 String(type || '').split(',').forEach(function (t) { 16289 t = t.trim(); 16290 if (t && perSleutel[s].typen.indexOf(t) === -1) perSleutel[s].typen.push(t); 16291 }); 16292 return perSleutel[s]; 16293 } 16294 (rijen || []).forEach(function (r) { 16295 var gebied = tekst(r['Gebied']); 16296 var type = tekst(r['Type']); 16297 var start = tekst(r['Startlocatie']); 16298 var isBox = waar(r['Startlocatie Rondobox']); 16299 if (start && (waar(r['Startlocatie op kaart']) || isBox)) { 16300 var loc = pak('start', gebied, start, tekst(r['Startlocatie Link']), type); 16301 /* Staat Rondobox op één van de rijen aan, dan wint het kado-icoon. */ 16302 if (isBox) { loc.rondobox = true; loc.soort = 'start'; } 16303 } 16304 var rust = tekst(r['Rust Locatie']); 16305 if (rust && waar(r['Rustlocatie op kaart'])) { 16306 pak('rust', gebied, rust, tekst(r['Rustlocatie Link']), type); 16307 } 16308 }); 16309 return volgorde.map(function (s) { return perSleutel[s]; }); 16310 } 16311 16312 /* ââ Paneelinhoud ââââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 16313 function embedUrl(loc) { 16314 var q = encodeURIComponent(loc.naam + (loc.gebied ? ', ' + loc.gebied.replace(/^[A-Z]{2}\s+/, '') : ''));
16315 return MAPS_KEY 16316 ? 'https://www.google.com/maps/embed/v1/place?key=' + encodeURIComponent(MAPS_KEY) + '&q=' + q 16317 : 'https://maps.google.com/maps?q=' + q + '&output=embed'; 16318 } 16319 function routeUrl(loc) { 16320 /* De korte maps.app.goo.gl-link is het nauwkeurigst; ontbreekt die, dan een 16321 zoekopdracht op naam. */ 16322 return loc.link || ('https://maps.google.com/?q=' + encodeURIComponent(loc.naam)); 16323 } 16324 16325 function paneelHtml(loc) { 16326 return '<div class="gr-atlas-panel-menu">' 16327 + '<button type="button" class="btn-icon-svg gr-atlas-panel-close" title="' + esc(LBL.sluit) + '"' 16328 + ' onclick="event.stopPropagation();window._grAtlasClosePanel()">' 16329 + '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"' 16330 + ' stroke-linecap="round" stroke-linejoin="round">' 16331 + '<line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>' 16332 + '</svg></button></div>' 16333 + locBlok(loc, ''); 16334 /* De knop "Route naar Locatie" stond hier. Weggehaald: de ingesloten 16335 Google-kaart hierboven heeft zelf al een routeknop, dus het was twee 16336 keer hetzelfde aanbieden. routeUrl() blijft staan â die is klein en 16337 maakt het terugzetten een kwestie van één regel. */ 16338 } 16339 16340 /* Eén locatie als blok. Zonder extraKlasse is dit precies wat het paneel 16341 altijd al toonde; met 'gr-loc-blok' krijgt het een grijze scheidingslijn 16342 erboven, voor wanneer het ónder een route in hetzelfde paneel hangt. */ 16343 function locBlok(loc, extraKlasse) { 16344 var pillen = '<h4 class="gr-loc-pill ' + (loc.soort === 'rust' ? 'is-rust' : 'is-start') + '">' 16345 + esc(loc.soort === 'rust' ? LBL.rust : LBL.start) + '</h4>'; 16346 if (loc.rondobox) { 16347 pillen += '<h4 class="gr-loc-pill is-rondobox">' + esc(LBL.rondobox) + '</h4>'; 16348 } 16349 /* Titel eerst, pillen eronder â zelfde volgorde als een routepaneel, waar 16350 de naam ook boven de eigenschappen staat. */ 16351 return '<div class="' + (extraKlasse || '') + '">' 16352 + '<strong class="gr-loc-titel">' + esc(loc.naam) + '</strong>' 16353 + '<div class="gr-loc-pills">' + pillen + '</div>' 16354 + '<iframe class="gr-loc-kaart" loading="lazy" allowfullscreen' 16355 + ' referrerpolicy="no-referrer-when-downgrade" src="' + esc(embedUrl(loc)) + '"></iframe>' 16356 + '</div>'; 16357 } 16358 16359 /* ââ Geocoderen voor rustlocaties ââââââââââââââââââââââââââââââââââââââ */ 16360 var _geo = {}; 16361 try { 16362 var _g = JSON.parse(sessionStorage.getItem(GEO_KEY) || 'null'); 16363 if (_g && Date.now() - _g.ts < GEO_TTL) _geo = _g.d || {}; 16364 } catch (e) {} 16365 function bewaarGeo() { 16366 try { sessionStorage.setItem(GEO_KEY, JSON.stringify({ ts: Date.now(), d: _geo })); } catch (e) {} 16367 } 16368 /* De namen staan als "Zaak - Plaats" in de sheet. Met een komma leest een 16369 geocoder het als plaatsaanduiding in plaats van als onderdeel van de naam. */ 16370 function zoekterm(loc) { 16371 var naam = String(loc && loc.naam || loc || '').replace(/\s+-\s+/g, ', '); 16372 var geb = (loc && loc.gebied ? String(loc.gebied).replace(/^[A-Z]{2}\s+/, '') : ''); 16373 return geb ? naam + ', ' + geb : naam; 16374 } 16375 16376 /* Google eerst: dat is dezelfde bron als de kaartjes en de links in de sheet, 16377 dus de speld komt op de plek die je in Google Maps ziet. Draait de Maps 16378 JS-API niet op deze pagina, dan valt dit terug op Nominatim. */ 16379 function googleGeocode(term) { 16380 var g = window.google && window.google.maps && window.google.maps.Geocoder; 16381 if (!g) return Promise.resolve(null); 16382 return new Promise(function (klaar) { 16383 /* De callback van Google komt soms niet terug â een geweigerde sleutel, 16384 een geblokkeerd verzoek. Zonder deze wekker blijft de hele wachtrij 16385 staan en lijkt de knop niets te doen. */ 16386 var af = false; 16387 var wekker = setTimeout(function () { 16388 if (af) return; 16389 af = true; 16390 console.warn('[GR Atlas] Google-geocoder gaf geen antwoord voor:', term); 16391 klaar(null); 16392 }, 4000); 16393 function gereed(v) { if (af) return; af = true; clearTimeout(wekker); klaar(v); }
16394 try { 16395 new window.google.maps.Geocoder().geocode({ address: term }, function (res, status) { 16396 if (status === 'OK' && res && res[0] && res[0].geometry) { 16397 var p = res[0].geometry.location; 16398 gereed([p.lat(), p.lng()]); 16399 } else { 16400 if (status !== 'ZERO_RESULTS') console.warn('[GR Atlas] Google-geocoder:', status, '·', term); 16401 gereed(null); 16402 } 16403 }); 16404 } catch (e) { gereed(null); } 16405 }); 16406 } 16407 16408 function nominatim(term) { 16409 return fetch('https://nominatim.openstreetmap.org/search?format=json&limit=1&q=' + encodeURIComponent(term)) 16410 .then(function (r) { return r.json(); }) 16411 .then(function (d) { return (d && d[0]) ? [parseFloat(d[0].lat), parseFloat(d[0].lon)] : null; }) 16412 .catch(function () { return null; }); 16413 } 16414 16415 /* loc mag ook een kale naam zijn; de adminknop geeft het hele object mee. */ 16416 function geocode(loc) { 16417 var sleutel, term; 16418 try { 16419 sleutel = String(loc && loc.naam || loc || ''); 16420 term = zoekterm(loc); 16421 } catch (e) { return Promise.resolve(null); } 16422 if (!term) return Promise.resolve(null); 16423 if (_geo[sleutel]) return Promise.resolve(_geo[sleutel]); 16424 return googleGeocode(term) 16425 .then(function (ll) { return ll || nominatim(term); }) 16426 .then(function (ll) { 16427 if (ll) { _geo[sleutel] = ll; bewaarGeo(); } 16428 return ll; 16429 }) 16430 /* Wat er ook misgaat: nooit afketsen, anders stopt de wachtrij die hierop 16431 wacht â in de kaart én in de adminknop. */ 16432 .catch(function (e) { console.warn('[GR Atlas] geocode mislukt:', term, e); return null; }); 16433 } 16434 16435 /* Zonder Google-geocoder geldt de limiet van Nominatim: één per seconde. */ 16436 function wachtTijd() { 16437 return (window.google && window.google.maps && window.google.maps.Geocoder) ? 120 : 1100; 16438 } 16439 16440 /* ââ Locatiebundel âââââââââââââââââââââââââââââââââââââââââââââââââââââ 16441 Eén JSON met de coördinaten van alle locaties, gemaakt met de adminknop in 16442 gr-atlas-admin.html. Staat een locatie erin, dan hoeft er niets geocodeerd 16443 te worden â dat scheelt een seconde per rustlocatie bij elke bezoeker. 16444 Ontbreekt het bestand of een sleutel, dan valt alles gewoon terug op 16445 geocoderen; een verouderde bundel maakt dus nooit iets stuk. */ 16446 var LOC_JSON = [ 16447 /* Vast adres vooraan: file_url en asset_url leveren niet op elke pagina een 16448 bruikbare URL, en dan viel alles terug op geocoderen. */ 16449 'https://cdn.shopify.com/s/files/1/0899/1277/0934/files/gr-atlas-locaties.json', 16450 "//granrondo.cc/cdn/shop/files/gr-atlas-locaties.json?v=11360630700561010468", 16451 "//granrondo.cc/cdn/shop/t/1/assets/gr-atlas-locaties.json?v=9844" 16452 ]; 16453 function laadBundel() { 16454 var lijst = LOC_JSON.filter(function (u) { return u && u.indexOf('http') === 0; }); 16455 return (function probeer(i) { 16456 if (i >= lijst.length) return Promise.resolve({}); 16457 return fetch(lijst[i]) 16458 .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); }) 16459 .then(function (j) { return (j && j.locaties) || {}; }) 16460 .catch(function () { return probeer(i + 1); }); 16461 })(0); 16462 } 16463 16464 /* ââ Markers plaatsen ââââââââââââââââââââââââââââââââââââââââââââââââââ 16465 Rondobox ligt altijd bovenop: hogere zIndexOffset dan de andere twee. */ 16466 var Z_GEWOON = 500, Z_RONDOBOX = 1200; 16467 var _markers = []; // { mk, echt, loc } 16468 16469 function plaats(kaart, laag, loc, latlng) { 16470 if (!latlng || isNaN(latlng[0]) || isNaN(latlng[1])) return; 16471 var klasse = loc.rondobox ? 'is-rondobox' : (loc.soort === 'rust' ? 'is-rust' : 'is-start'); 16472 var icoon = loc.rondobox ? SVG_KADO : SVG_KOFFIE; 16473 var mk = window.L.marker(latlng, { 16474 title: loc.naam, 16475 zIndexOffset: loc.rondobox ? Z_RONDOBOX : Z_GEWOON, 16476 icon: window.L.divIcon({ 16477 /* gr-loc-rondobox erbij zodat het filter ze als groep kan aanspreken: 16478 bij de stand Voltooid horen ze niet op de kaart. */ 16479 className: 'gr-loc-icon' + (loc.rondobox ? ' gr-loc-rondobox' : ''), 16480 html: '<div class="gr-loc-pin ' + klasse + '">' + icoon + '</div>', 16481 iconSize: [30, 30], iconAnchor: [15, 15] 16482 }) 16483 }); 16484 mk.on('click', function (e) { 16485 if (e && e.originalEvent) e.originalEvent.stopPropagation(); 16486 if (window._grAtlasOpenPanel) window._grAtlasOpenPanel(paneelHtml(loc)); 16487 }); 16488 mk.addTo(laag); 16489 /* Start- en rustbolletjes verdwijnen mee met de filterknoppen: het filter in 16490 gr-atlas-html werkt op alles met data-gr-gebied binnen #gr-atlas-map, en 16491 Leaflet hangt zijn markerlaag daar gewoon in. Rondobox-locaties krijgen dat 16492 attribuut nÃét en blijven dus altijd staan. */ 16493 if (!loc.rondobox && loc.gebied) { 16494 var el = mk.getElement && mk.getElement(); 16495 if (el) { 16496 el.setAttribute('data-gr-gebied', loc.gebied); 16497 /* Niet meer standaard op de kaart: pas zichtbaar als je de routelijn 16498 van dit gebied aanklikt. Rondobox-locaties komen hier niet langs en 16499 blijven dus altijd staan. */ 16500 el.classList.add('gr-loc-bij-route'); 16501 } 16502 } 16503 _markers.push({ mk: mk, echt: window.L.latLng(latlng[0], latlng[1]), loc: loc }); 16504 try { herschik(kaart); } catch (e) { console.warn('[GR Atlas] herschikken mislukt:', e); } 16505 } 16506
16507 /* Het filter in gr-atlas-html draait over de elementen die er op dát moment 16508 zijn. Markers komen na het geocoderen één voor één binnen, dus na elke 16509 toevoeging opnieuw laten lopen â anders staat een nieuw bolletje er nog 16510 terwijl er een filter aanstaat. */ 16511 function filterOpnieuw() { 16512 if (window._grAtlasFilters && window._grAtlasFilters.opnieuw) { 16513 try { window._grAtlasFilters.opnieuw(); } catch (e) {} 16514 } 16515 } 16516 16517 /* ââ Overlappende bolletjes uit elkaar âââââââââââââââââââââââââââââââââ 16518 Twee zaken in hetzelfde dorp vallen op elkaar. Vanaf provincieniveau 16519 schuiven we ze een paar pixels uit elkaar rond hun gezamenlijke midden. 16520 De échte coördinaat blijft bewaard, dus het paneel en de Route-knop wijzen 16521 nog steeds naar de goede plek. Onder dat zoomniveau heeft spreiden geen 16522 zin: dan liggen hele provincies op elkaar. */ 16523 var ZOOM_SPREIDEN = 8; // ongeveer provincieniveau 16524 var DREMPEL = 34; // px; bolletje is 30 breed 16525 var _bezig = false; 16526 16527 /* Eén keer rekenen als er twintig markers achter elkaar binnenkomen. 16528 requestAnimationFrame moet mét window als ontvanger worden aangeroepen â 16529 losgetrokken uit window gooit hij in strict mode "Illegal invocation". */ 16530 function straks(fn) { 16531 if (window.requestAnimationFrame) window.requestAnimationFrame(fn); 16532 else setTimeout(fn, 16); 16533 } 16534 function herschik(kaart) { 16535 if (_bezig || !kaart || !_markers.length) return; 16536 _bezig = true; 16537 straks(function () { 16538 _bezig = false; 16539 try { verdeel(kaart); } 16540 catch (e) { console.warn('[GR Atlas] herschikken mislukt:', e); } 16541 }); 16542 } 16543 16544 function verdeel(kaart) { 16545 /* Altijd eerst terug naar de echte plek, anders stapelen de verschuivingen. */ 16546 _markers.forEach(function (m) { m.mk.setLatLng(m.echt); }); 16547 if (kaart.getZoom() < ZOOM_SPREIDEN) return; 16548 16549 var pt = _markers.map(function (m) { return kaart.latLngToLayerPoint(m.echt); }); 16550 var gedaan = []; 16551 for (var i = 0; i < _markers.length; i++) { 16552 if (gedaan[i]) continue; 16553 var groep = [i]; 16554 gedaan[i] = true; 16555 for (var j = i + 1; j < _markers.length; j++) { 16556 if (!gedaan[j] && pt[i].distanceTo(pt[j]) < DREMPEL) { groep.push(j); gedaan[j] = true; } 16557 } 16558 if (groep.length < 2) continue; 16559 16560 /* Rondobox eerst in de rij, zodat die op de bovenste plek terechtkomt. */ 16561 groep.sort(function (a, b) { 16562 return (_markers[b].loc.rondobox ? 1 : 0) - (_markers[a].loc.rondobox ? 1 : 0); 16563 }); 16564 var mx = 0, my = 0; 16565 groep.forEach(function (k) { mx += pt[k].x; my += pt[k].y; }); 16566 mx /= groep.length; my /= groep.length; 16567 16568 var straal = DREMPEL * 0.6; 16569 groep.forEach(function (k, n) { 16570 /* De eerste uit de rij komt bovenaan te staan, de rest met de klok mee. 16571 Omdat Rondobox vooraan is gesorteerd, staat die dus altijd boven de 16572 andere locatie â én er bovenop dankzij de hogere zIndexOffset. */ 16573 var hoek = (-Math.PI / 2) + (2 * Math.PI * n) / groep.length; 16574 var p = window.L.point(mx + Math.cos(hoek) * straal, my + Math.sin(hoek) * straal); 16575 _markers[k].mk.setLatLng(kaart.layerPointToLatLng(p)); 16576 }); 16577 } 16578 } 16579 16580 function start() { 16581 var kaart = window._grAtlasKaart; 16582 if (!kaart || !window.L) return; 16583 var laag = window.L.layerGroup().addTo(kaart); 16584 window._grAtlasLocatieLaag = laag; 16585 kaart.on('zoomend', function () { herschik(kaart); }); 16586 16587 /* Eerst de routes: we wachten op de routebundel gr-atlas-routes.json, dus op 16588 de routes zelf. Wachten op het signaal 'gr:atlas-meta' (alle gebieden op 16589 de kaart) leek logischer, maar dat komt pas ná de planner-data uit Apps 16590 Script en die kan bij een ingelogde bezoeker seconden duren â de locaties 16591 stonden dan voor niets te wachten. Noodrem na 5 seconden, want zonder 16592 routes hoort dit ook gewoon te werken. */ 16593 var tStart = Date.now(), tRoutes = 0; 16594 function wachtOpRoutes() { 16595 var af = false; 16596 return new Promise(function (klaar) { 16597 function gereed(reden) { 16598 if (af) return; 16599 af = true; tRoutes = Date.now() - tStart; 16600 if (reden) console.info('[GR Atlas] routebundel duurt lang â locaties gaan alvast van start.'); 16601 klaar(); 16602 } 16603 var p = (window.GRGpx && window.GRGpx.bundel) ? window.GRGpx.bundel() : null; 16604 if (p && p.then) p.then(function () { gereed(0); }, function () { gereed(0); }); 16605 else gereed(0); 16606 setTimeout(function () { gereed(1); }, 5000); 16607 }); 16608 } 16609 16610 wachtOpRoutes().then(function () { 16611 return Promise.all([ 16612 fetch(ROUTES_URL).then(function (r) { return r.json(); }).catch(function () { return []; }), 16613 laadBundel() 16614 ]); 16615 }).catch(function (e) { 16616 console.warn('[GR Atlas] locatiedata ophalen mislukt:', e); 16617 return [[], {}]; 16618 }).then(function (paar) { 16619 var lijst = bouwLijst(paar[0]); 16620 var locs = paar[1] || {}; 16621 var uitJson = 0, teGeo = []; 16622 lijst.forEach(function (loc) { 16623 var vast = locs[loc.sleutel]; 16624 if (vast && vast.length === 2) { 16625 plaats(kaart, laag, loc, vast); // coördinaat uit de locatiebundel 16626 uitJson++; 16627 } else { 16628 teGeo.push(loc); 16629 } 16630 }); 16631 var nRust = lijst.filter(function (l) { return l.soort === 'rust'; }).length; 16632 console.info('[GR Atlas] locaties:', lijst.length, 16633 '(start/Rondobox', lijst.length - nRust, '· rust', nRust + ')', 16634 '· uit locatiebundel:', uitJson, 16635 '· te geocoderen:', teGeo.length, 16636 '· routes klaar na', tRoutes + 'ms', 16637 '· alles geplaatst na', (Date.now() - tStart) + 'ms'); 16638 if (!nRust) console.info('[GR Atlas] geen rustlocaties â staat "Rustlocatie op kaart" ergens op TRUE?'); 16639 filterOpnieuw(); 16640 /* Nominatim staat één verzoek per seconde toe, dus netjes op een rij. */ 16641 (function volgende(i) { 16642 if (i >= teGeo.length) return; 16643 var loc = teGeo[i]; 16644 var uitCache = !!_geo[loc.naam]; 16645 geocode(loc).then(function (ll) { 16646 if (ll) plaats(kaart, laag, loc, ll); 16647 else console.warn('[GR Atlas] geen coördinaat voor:', loc.naam); 16648 filterOpnieuw(); 16649 setTimeout(function () { volgende(i + 1); }, uitCache ? 0 : wachtTijd()); 16650 }); 16651 })(0); 16652 }); 16653 } 16654
16655 /* Haken voor de adminknop in gr-atlas-admin.html: die bouwt met dezelfde 16656 lijst en dezelfde geocoder de locatiebundel op. */ 16657 window._grAtlasLocaties = { 16658 lijst: function () { 16659 return fetch(ROUTES_URL).then(function (r) { return r.json(); }) 16660 .then(bouwLijst).catch(function () { return []; }); 16661 }, 16662 geocode: geocode, 16663 wachtTijd: wachtTijd 16664 }; 16665 16666 /* ââ Koppeling met de routelijnen ââââââââââââââââââââââââââââââââââââââââ 16667 gr-atlas-script roept deze drie aan bij het openen en sluiten van het 16668 zijpaneel. Ze staan hier omdat de locatiedata hier woont; het script hoeft 16669 alleen het gebied en de lijnkleur door te geven. 16670 16671 Alle drie zijn ze veilig als er niets te doen valt: onbekend gebied levert 16672 een lege string of een lege ronde op, zonder fout. */ 16673 16674 /* De locaties van één gebied, elk als blok met een grijze scheidingslijn 16675 erboven. Rondobox-locaties horen hier ook bij en staan altijd bovenaan: 16676 dat is het adres waar je je Rondobox ophaalt, en dat wil je als eerste 16677 zien wanneer een gebied meerdere locaties heeft. 16678 16679 Op de kaart blijven ze wél apart: _grAtlasLocToon laat rondobox met rust, 16680 want die bolletjes staan er altijd al en horen niet mee te kleuren met de 16681 routelijn. Alleen in dit paneel lopen ze mee. */ 16682 window._grAtlasLocBlokken = function (gebied) { 16683 if (!gebied) return ''; 16684 return _markers 16685 .filter(function (m) { return m.loc.gebied === gebied; }) 16686 .sort(function (a, b) { return (b.loc.rondobox ? 1 : 0) - (a.loc.rondobox ? 1 : 0); }) 16687 .map(function (m) { return locBlok(m.loc, 'gr-loc-blok'); }) 16688 .join(''); 16689 }; 16690 16691 /* Toon de bolletjes van dit gebied in de kleur van de routelijn. Start wordt 16692 gevuld, rust omlijnd â anders zijn ze niet uit elkaar te houden, want ze 16693 dragen hetzelfde koffie-icoon. */ 16694 window._grAtlasLocToon = function (gebied, kleur) { 16695 window._grAtlasLocVerberg(); 16696 if (!gebied) return 0; 16697 var n = 0; 16698 _markers.forEach(function (m) { 16699 if (m.loc.rondobox || m.loc.gebied !== gebied) return; 16700 var el = m.mk.getElement && m.mk.getElement(); 16701 if (!el) return; 16702 el.classList.add('gr-loc-aan'); 16703 var pin = el.querySelector('.gr-loc-pin'); 16704 if (pin && kleur) { 16705 var isRust = m.loc.soort === 'rust'; 16706 pin.classList.toggle('gr-loc-route-rust', isRust); 16707 pin.style.borderColor = kleur; 16708 pin.style.background = isRust ? '' : kleur; 16709 pin.style.color = isRust ? kleur : '#fff'; 16710 } 16711 n++; 16712 }); 16713 return n; 16714 }; 16715 16716 /* Alles weer weg en de kleuren terug naar de klassen uit de stylesheet. */ 16717 window._grAtlasLocVerberg = function () { 16718 _markers.forEach(function (m) { 16719 if (m.loc.rondobox) return; 16720 var el = m.mk.getElement && m.mk.getElement(); 16721 if (!el) return; 16722 el.classList.remove('gr-loc-aan'); 16723 var pin = el.querySelector('.gr-loc-pin'); 16724 if (pin) { 16725 pin.classList.remove('gr-loc-route-rust'); 16726 pin.style.borderColor = ''; 16727 pin.style.background = ''; 16728 pin.style.color = ''; 16729 } 16730 }); 16731 }; 16732 16733 /* gr-atlas-script bouwt de kaart pas als de markup er staat; even wachten. 16734 Alles hierbinnen staat in een try/catch: dit snippet draait in de footer, 16735 naast de kaart zelf, en mag bij een fout nooit de rest meeslepen. */ 16736 var pogingen = 0; 16737 var t = setInterval(function () { 16738 try { 16739 if (window._grAtlasKaart) { clearInterval(t); start(); return; } 16740 if (++pogingen > 100) { 16741 clearInterval(t); 16742 console.warn('[GR Atlas] geen kaart gevonden â locaties overgeslagen.'); 16743 } 16744 } catch (e) { 16745 clearInterval(t); 16746 console.error('[GR Atlas] locaties mislukt:', e); 16747 } 16748 }, 200); 16749})(); 16750</script>
16750 16751 16752 16753 16754<style> 16755 .gr-st-vak { margin: 0 0 14px; } 16756 .gr-st-knop { 16757 display: inline-flex; align-items: center; justify-content: center; gap: 8px; 16758 width: 100%; box-sizing: border-box; 16759 padding: 10px 16px; border: none; border-radius: 999px; cursor: pointer; 16760 background: #FC4C02; color: #fff; /* Strava-oranje */ 16761 font-family: 'rum raisin'; text-transform: uppercase; letter-spacing: .05em; 16762 /* !important omdat het thema `a.button, button` op 1.8rem zet, ook met 16763 !important. Zonder tegenwicht wint die regel. */ 16764 font-size: 1.6rem !important; line-height: 1.4; 16765 text-decoration: none; transition: opacity .2s; 16766 } 16767 .gr-st-knop:hover { opacity: .88; } 16768 .gr-st-knop:disabled { opacity: .5; cursor: not-allowed; } 16769 .gr-st-knop svg { width: 15px; height: 15px; flex: 0 0 auto; fill: currentColor; } 16770 16771 .gr-st-paneel { 16772 border: 1px solid var(--color-light, #E5E1D6); 16773 border-radius: 14px; padding: 10px; margin-top: 10px; 16774 } 16775 .gr-st-zoekrij { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; } 16776 .gr-st-zoek { 16777 flex: 1 1 auto; width: 100%; box-sizing: border-box; 16778 padding: 9px 14px; border: 1px solid var(--color-light, #E5E1D6); 16779 border-radius: 999px; font-size: .95em; background-image: none !important; 16780 } 16781 .gr-st-lijst { max-height: 260px; overflow-y: auto; margin: 0 0 8px; } 16782 .gr-st-rij { 16783 display: flex; gap: 10px; align-items: flex-start; 16784 padding: 8px 6px; border-bottom: 1px solid var(--color-lighter, #EFF1FD); 16785 cursor: pointer; 16786 } 16787 .gr-st-rij:last-child { border-bottom: none; } 16788 .gr-st-rij input { margin-top: 3px; flex: 0 0 auto; } 16789 .gr-st-rij-tekst { flex: 1 1 auto; min-width: 0; } 16790 /* Titel en gegevens allebei op een eigen regel: als block, anders plakt de 16791 datum tegen de naam aan zodra die kort is. */ 16792 .gr-st-titel { 16793 display: block; 16794 font-weight: 700; font-size: .95em; line-height: 1.3; 16795 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; 16796 } 16797 .gr-st-meta { display: block; font-size: .82em; color: #777; line-height: 1.4; margin-top: 2px; } 16798 .gr-st-gebied { color: var(--color-dark, #271D62); font-weight: 700; } 16799 /* Onder elkaar: eerst importeren, daaronder sluiten. */ 16800 .gr-st-voet { display: flex; flex-direction: column; gap: 6px; align-items: stretch; } 16801 .gr-st-voet .gr-st-knop { width: 100%; } 16802 .gr-st-tekstknop { 16803 background: none; border: none; padding: 6px 4px; cursor: pointer; 16804 color: var(--color-dark, #271D62); font-family: inherit; font-size: .88em !important; 16805 text-decoration: underline; 16806 } 16807 /* Teller en "Meer laden" naast elkaar, met lucht naar de knoppen eronder. */ 16808 .gr-st-meerrij { 16809 display: flex; align-items: center; justify-content: space-between; 16810 gap: 10px; margin: 2px 0 14px; 16811 } 16812 .gr-st-teller { font-size: .82em; color: #777; } 16813 #grStMeer { margin: 0; } 16814 .gr-st-melding, .gr-st-haalmelding { font-size: .88em; line-height: 1.5; } 16815 .gr-st-info { color: #777; padding: 8px 2px; font-size: .88em; } 16816 .gr-st-fout { color: #c00; padding: 8px 2px; font-size: .88em; } 16817 .gr-st-voortgang { 16818 background: var(--color-lighter, #EFF1FD); color: var(--color-dark, #271D62); 16819 border-radius: 12px; padding: 9px 14px; font-size: .9em; line-height: 1.4; 16820 display: flex; gap: 10px; align-items: center; justify-content: space-between; 16821 } 16822 .gr-st-voortgang-kop { font-weight: 700; } 16823 /* Het aangevinkte item nog een keer, zodat je ziet wat je zit na te lopen. */ 16824 .gr-st-huidig { 16825 border: 1px solid var(--color-light, #E5E1D6); border-radius: 12px; 16826 padding: 9px 12px; margin-top: 8px; 16827 } 16828 .gr-st-huidig .gr-st-titel { white-space: normal; } 16829 /* Een eigen klas om het formulier weg te houden, en niet style.display. 16830 gr-planner-script zet die eigenschap ook â bij het opslaan en bij het 16831 herstellen â en twee schrijvers op één eigenschap gaat hier altijd mis. 16832 Met een klas heeft ieder zijn eigen knop om aan te draaien. */ 16833 #activityForm.gr-st-verborgen { display: none !important; } 16834 /* Lader terwijl we nog niet weten of je gekoppeld bent. De modal gaat open, 16835 de vraag naar Apps Script duurt soms een tel of twee, en tot die tijd stond 16836 het formulier er al terwijl de knop er later bovenop sprong. Nu zie je eerst 16837 dit en verschijnt de rest in één keer. */ 16838 .gr-st-start { 16839 display: flex; flex-direction: column; align-items: center; gap: 12px; 16840 padding: 34px 20px; color: #999; font-size: .95em; font-style: italic; 16841 } 16842 .gr-st-start .gr-st-tol { width: 30px; height: 30px; border-width: 3px; } 16843 /* Verschijnt pas als het echt lang duurt; tot die tijd staat hij op none. */ 16844 .gr-st-traag { display: block; margin-top: 6px; font-size: .82em; color: #999; font-style: normal; } 16845 .gr-st-info .gr-st-tol { display: inline-block; vertical-align: -3px; margin-right: 6px; } 16846 16847 /* Lader tijdens het overnemen van één activiteit. */ 16848 .gr-st-lader { 16849 display: flex; align-items: center; gap: 10px; 16850 padding: 14px 4px; color: #777; font-size: .9em; 16851 } 16852 .gr-st-tol { 16853 width: 18px; height: 18px; flex: 0 0 auto; border-radius: 50%; 16854 border: 2px solid var(--color-lighter, #EFF1FD); border-top-color: #FC4C02; 16855 animation: grStTol .7s linear infinite; 16856 } 16857 @keyframes grStTol { to { transform: rotate(360deg); } } 16858 @media (prefers-reduced-motion: reduce) { .gr-st-tol { animation: none; } } 16859</style> 16860
16861<script> 16862(function () { 16863 'use strict'; 16864 16865 /* Eén plek waar het anker gezocht wordt. Staat de modal niet op deze pagina, 16866 dan doet dit snippet helemaal niets â geen knop, geen netwerkverkeer. */ 16867 function anker() { return document.querySelector('[data-gr-strava-haal]'); } 16868 function melder() { return document.querySelector('[data-gr-strava-melding]'); } 16869 16870 /* Hier stond een afslag op een ontbrekend anker. Dat leek zuinig, maar het 16871 anker zit in gr-modals en die modal wordt na het laden naar <body> 16872 verplaatst â bij die ene volgorde waarin dit snippet eerder aan de beurt is, 16873 zou de knop nooit meer terugkomen. Nu kijkt de lus hieronder gewoon of het 16874 anker er inmiddels is. */ 16875 16876 var SCRIPT_URL = 'https://script.google.com/macros/s/AKfycbykfmZGR3AVsTqRF0LNs3Kx1zzVauuYSe-GGb2JzR8AeHYCjB8BNOQbXJZ5ouxa946n/exec'; 16877 16878 var L = { 16879 koppel: "Koppel met Strava", 16880 haal: "Haal ritten uit Strava", 16881 zoek: "Zoek in je activiteitenâ¦", 16882 importeer: "Importeer selectie", 16883 meer: "Meer laden", 16884 sluit: "Sluiten", 16885 leeg: "Geen fietsactiviteiten gevonden.", 16886 geenTreffer:"Niets gevonden met deze zoekterm.", 16887 laden: "Activiteiten ladenâ¦", 16888 wachten: "Wachten op Stravaâ¦", 16889 fout: "Strava kon niet bereikt worden. Probeer het zo nog eens.", 16890 kiesEerst: "Vink eerst een activiteit aan.", 16891 popupWeg: "Je browser blokkeerde het Strava-venster. Sta pop-ups toe en probeer het opnieuw.", 16892 /* %n% en %t% en geen {n}/{t}: accolades binnen een Liquid-filterwaarde 16893 laten de parser denken dat de uitdrukking daar eindigt â precies de fout 16894 "was not properly terminated with regexp". */ 16895 voortgang: "Importeren Strava Activiteit â %n% van %t%", 16896 overslaan: "Deze overslaan", 16897 klaar: "Alles geïmporteerd.", 16898 opnieuw: "Opnieuw proberen", 16899 ververs: "Pagina verversen", 16900 overnemen: "Gegevens overnemen uit Stravaâ¦", 16901 aantal: "Aantal items: %n%", 16902 startLaden: "Laden formulierâ¦", 16903 traag: "De eerste keer duurt dit het langst â Strava wordt via onze server opgehaald.", 16904 gekoppeldAls: "Gekoppeld als %s%.", 16905 ontkoppelVraag: "Weet je het zeker? Je ritten blijven staan, maar nieuwe ophalen kan daarna niet meer.", 16906 ontkoppelBezig: "Ontkoppelenâ¦" 16907 }; 16908 16909 var SVG_STRAVA = '<svg viewBox="0 0 24 24" aria-hidden="true">' 16910 + '<path d="M13.8 2 7.3 14.8h3.8L13.8 9l2.7 5.8h3.8z"/>' 16911 + '<path d="M16.5 14.8 14.9 18l-1.6-3.2h-2.5L14.9 22l3.6-7.2z"/></svg>'; 16912 16913 /* ââ Kleine hulpjes âââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 16914 16915 function esc(t) { 16916 return String(t == null ? '' : t) 16917 .replace(/&/g, '&').replace(/</g, '<') 16918 .replace(/>/g, '>').replace(/"/g, '"'); 16919 } 16920 16921 function email() { 16922 var el = document.getElementById('customerEmail'); 16923 var m = el ? String(el.value || '').trim() : ''; 16924 if (m) return m; 16925 /* Terugval voor het geval het verborgen veld er niet is. myEmail is een 16926 globale uit planner-script1. */ 16927 return (typeof window.myEmail === 'string' ? window.myEmail : '').trim(); 16928 } 16929 16930 /* Apps Script laat zo nu en dan een verzoek vallen â een tijdje niets, of een 16931 antwoord dat geen JSON is. Dat is niet te voorkomen, wél op te vangen: bij 16932 een misser wachten we even en proberen het nog twee keer. Pas als ook dat 16933 niets oplevert komt de melding met de knop. In de praktijk haalt de tweede 16934 poging het bijna altijd. 16935 16936 Elke poging krijgt zijn eigen wachttijd mee. Zonder grens blijft een verzoek 16937 dat niet terugkomt eeuwig hangen, en zie je alleen "Activiteiten ladenâ¦". */ 16938 function haalEenmaal(url, wachtMs) { 16939 return new Promise(function (klaar, mis) { 16940 var af = false; 16941 var wekker = setTimeout(function () { af = true; mis(new Error('duurde te lang')); }, wachtMs); 16942 fetch(url, { cache: 'no-store' }) 16943 .then(function (r) { return r.json(); }) 16944 .then(function (j) { if (af) return; clearTimeout(wekker); klaar(j); }) 16945 .catch(function (e) { if (af) return; clearTimeout(wekker); mis(e); }); 16946 }); 16947 } 16948 16949 function haal(params) { 16950 var q = Object.keys(params).map(function (k) { 16951 return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]); 16952 }).join('&'); 16953 var url = SCRIPT_URL + '?' + q; 16954 var pogingen = 0; 16955 function probeer() { 16956 pogingen++; 16957 return haalEenmaal(url, 15000).catch(function (e) { 16958 if (pogingen >= 3) throw e; 16959 console.warn('[GR Strava] poging ' + pogingen + ' mislukt, opnieuw:', e); 16960 return new Promise(function (r) { setTimeout(r, pogingen * 800); }).then(probeer); 16961 }); 16962 } 16963 return probeer(); 16964 } 16965 16966 function hms(sec) { 16967 sec = Math.max(0, Math.round(Number(sec) || 0)); 16968 var u = Math.floor(sec / 3600), m = Math.floor((sec % 3600) / 60), s = sec % 60; 16969 function tw(n) { return (n < 10 ? '0' : '') + n; } 16970 return tw(u) + ':' + tw(m) + ':' + tw(s); 16971 } 16972 16973 function datumNL(iso) { 16974 var d = String(iso || '').slice(0, 10); 16975 if (!/^\d{4}-\d{2}-\d{2}$/.test(d)) return ''; 16976 var p = d.split('-'); 16977 return p[2].replace(/^0/, '') + '-' + p[1].replace(/^0/, '') + '-' + p[0]; 16978 } 16979 16980 function toon(html) { var a = anker(); if (a) { a.innerHTML = html; a.style.display = ''; } } 16981
16982 /* ââ Meelopende tijd bij het wachten ââââââââââââââââââââââââââââââââââ 16983 Een tolletje zegt alleen dát er iets gebeurt, niet hoe lang het nog duurt. 16984 Bij Apps Script scheelt dat: de eerste vraag na een tijdje stilte kost 16985 gemeten tien seconden, elke vraag daarna ongeveer één. Zonder teller lijkt 16986 die eerste keer op een vastloper. 16987 16988 Elke tekst die mag meetellen krijgt data-gr-st-teller met de basistekst 16989 erin; deze lus zet de seconden erachter. Eén lus voor alles, zodat er niet 16990 per lader een eigen tijdmeting ontstaat die blijft doorlopen. */ 16991 var _teller = null; 16992 16993 function startTeller() { 16994 stopTeller(); 16995 var t0 = Date.now(); 16996 function tik() { 16997 var s = Math.round((Date.now() - t0) / 1000); 16998 var els = document.querySelectorAll('[data-gr-st-teller]'); 16999 if (!els.length) return; // niets meer te tellen 17000 Array.prototype.forEach.call(els, function (el) { 17001 var basis = el.getAttribute('data-gr-st-teller') || ''; 17002 el.textContent = basis + (s >= 1 ? ' (' + s + 's)' : ''); 17003 }); 17004 /* Na een seconde of zes is het geen gewone wachttijd meer. Dan erbij 17005 vertellen waarom, in plaats van je te laten raden. */ 17006 if (s >= 6) { 17007 var uitleg = document.querySelectorAll('[data-gr-st-traag]'); 17008 Array.prototype.forEach.call(uitleg, function (el) { el.style.display = ''; }); 17009 } 17010 } 17011 tik(); 17012 _teller = setInterval(tik, 1000); 17013 } 17014 17015 function stopTeller() { if (_teller) { clearInterval(_teller); _teller = null; } } 17016 17017 /* De regel die pas verschijnt als het lang duurt. */ 17018 function traagRegel() { 17019 return '<span class="gr-st-traag" data-gr-st-traag style="display:none;">' 17020 + esc(L.traag) + '</span>'; 17021 } 17022 17023 /* Zolang je in de lijst zit staat het formulier in de weg: je bent nog aan het 17024 kiezen, niet aan het invullen. Het komt terug zodra de eerste rit binnen is. */ 17025 function toonFormulier(ja) { 17026 var f = document.getElementById('activityForm'); 17027 if (f) f.classList.toggle('gr-st-verborgen', !ja); 17028 } 17029 function meld(html, fout) { 17030 var m = melder(); 17031 if (!m) return; 17032 if (!html) { m.style.display = 'none'; m.innerHTML = ''; return; } 17033 m.className = fout ? 'gr-st-haalmelding gr-st-fout' : 'gr-st-haalmelding gr-st-info'; 17034 m.innerHTML = html; 17035 m.style.display = ''; 17036 } 17037 17038 /* ââ Stand 1 en 2: welke knop hoort er te staan? ââââââââââââââââââââââââ */ 17039 17040 var _status = null; // laatste antwoord van strava_status 17041 var _gecheckt = false; // status al een keer opgehaald? 17042 17043 /* Welke weergave staat er op dit moment in het anker: 'knop', 'lijst', 17044 'stap' of 'fout'. 17045 17046 Hier zat de sprong terug naar het formulier. Een statuscontrole die nog 17047 onderweg was kwam binnen nádat jij de lijst al open had, en eindigde in 17048 toonKnop() â dat vervangt de lijst door de knop en zet het formulier weer 17049 aan. Bij het koppelen tikt de statuscontrole elke twee tellen, dus daar 17050 gebeurde het het vaakst: lijst geladen, en een tel later stond je weer bij 17051 het begin. 17052 17053 Nu tekent een statuscontrole alleen nog als er ook echt een knop staat. 17054 Ben je verder in het verhaal, dan laat hij je met rust. */ 17055 var _stand = 'knop'; 17056 17057 function toonKnop() { 17058 if (!_status) return; 17059 clearTimeout(_laderWekker); 17060 stopTeller(); 17061 _stand = 'knop'; 17062 toonFormulier(true); 17063 if (_status.gekoppeld) { 17064 toon('<div class="gr-st-vak"><button type="button" class="gr-st-knop" id="grStHaal">' 17065 + SVG_STRAVA + '<span>' + esc(L.haal) + '</span></button></div>'); 17066 document.getElementById('grStHaal').addEventListener('click', function () { 17067 laadLijst(1, true); 17068 }); 17069 } else { 17070 toon('<div class="gr-st-vak"><button type="button" class="gr-st-knop" id="grStKoppel">' 17071 + SVG_STRAVA + '<span>' + esc(L.koppel) + '</span></button></div>'); 17072 document.getElementById('grStKoppel').addEventListener('click', koppel); 17073 } 17074 } 17075 17076 var _statusLoopt = null; // de vraag die nu onderweg is 17077 var _volgendePoging = 0; // na een misser even wachten 17078 17079 /* ââ De stand onthouden âââââââââââââââââââââââââââââââââââââââââââââââ
17080 Of je gekoppeld bent verandert bijna nooit, maar het navragen kost bij 17081 Apps Script soms een paar tellen. Daardoor keek je elke keer dat de modal 17082 openging opnieuw naar een lader. 17083 17084 Dus onthouden we het antwoord voor deze sessie. Tweede keer openen is 17085 meteen raak: de knop staat er, en ondertussen vragen we stilletjes na of 17086 het nog klopt. Wijkt dat af, dan tekenen we alsnog bij. 17087 17088 Bewust sessionStorage en niet localStorage: verandert er iets buiten deze 17089 sessie om â je ontkoppelt op een ander apparaat â dan begin je bij het 17090 volgende bezoek gewoon weer met een schone vraag. 17091 17092 De state gaat er niet in mee. Dat is een ondertekend kaartje voor één 17093 koppelpoging; een oude opdiepen levert alleen maar een geweigerde 17094 aanvraag op. koppel() haalt daarom een verse stand op als die ontbreekt. */ 17095 function bewaarSleutel() { return 'gr_strava_stand_' + (email() || '').toLowerCase(); } 17096 17097 function leesBewaard() { 17098 try { 17099 var ruw = sessionStorage.getItem(bewaarSleutel()); 17100 if (!ruw) return null; 17101 var o = JSON.parse(ruw); 17102 return (o && typeof o.gekoppeld === 'boolean') ? o : null; 17103 } catch (e) { return null; } 17104 } 17105 17106 function bewaar(st) { 17107 try { 17108 sessionStorage.setItem(bewaarSleutel(), JSON.stringify({ 17109 gekoppeld: !!st.gekoppeld, 17110 clientId: st.clientId || '', 17111 redirectUri: st.redirectUri || '', 17112 scope: st.scope || '', 17113 athleetNaam: st.athleetNaam || '', 17114 athleetId: st.athleetId || '' 17115 })); 17116 } catch (e) { /* vol of geblokkeerd: dan gewoon elke keer navragen */ } 17117 } 17118 17119 /* Wat je ziet zolang de stand nog onderweg is: één lader, geen formulier. 17120 Anders staat het formulier er al, springt de knop er een tel later boven en 17121 schuift alles op. */ 17122 var _laderWekker = null; 17123 17124 function toonStartLader() { 17125 _stand = 'knop'; // hierna hoort er een knop te komen 17126 toonFormulier(false); 17127 toon('<div class="gr-st-vak"><div class="gr-st-start">' 17128 + '<span class="gr-st-tol"></span>' 17129 + '<span data-gr-st-teller="' + esc(L.startLaden) + '">' + esc(L.startLaden) + '</span>' 17130 + traagRegel() + '</div></div>'); 17131 startTeller(); 17132 17133 /* De lader mag het formulier hooguit even tegenhouden. Bij een koude start 17134 van Apps Script duurt het antwoord tot tien seconden, en zo lang naar een 17135 tolletje kijken is erger dan de knop die er later bij komt. Na anderhalve 17136 tel dus: formulier eronder, en een regeltje op de plek waar de knop komt. 17137 Zo verspringt er ook niets â die plek is dan al gereserveerd. */ 17138 clearTimeout(_laderWekker); 17139 _laderWekker = setTimeout(function () { 17140 if (_stand !== 'knop' || _status) return; // antwoord was er al 17141 toonFormulier(true); 17142 toon('<div class="gr-st-vak"><div class="gr-st-lader">' 17143 + '<span class="gr-st-tol"></span>' 17144 + '<span data-gr-st-teller="' + esc(L.startLaden) + '">' + esc(L.startLaden) + '</span>' 17145 + traagRegel() + '</div></div>'); 17146 startTeller(); 17147 }, 1500); 17148 } 17149 17150 function checkStatus(opnieuw) { 17151 if (_gecheckt && !opnieuw) { if (_stand === 'knop') toonKnop(); return Promise.resolve(_status); } 17152 var m = email(); 17153 if (!m) return Promise.resolve(null); // uitgelogd: geen knop 17154 /* Loopt er al een vraag, dan die teruggeven in plaats van een tweede te 17155 sturen. De wachtlus tikt elke halve tel en het koppelvenster elke twee 17156 tellen; zonder deze regel stapelden die verzoeken op en kwam het antwoord 17157 van de eerste ná dat van de tweede binnen. */ 17158 if (_statusLoopt) return _statusLoopt; 17159 17160 _statusLoopt = haal({ action: 'strava_status', email: m }).then(function (j) { 17161 _status = j || {}; 17162 _gecheckt = true; 17163 bewaar(_status); 17164 /* Alleen tekenen als er een knop staat. Zit je in de lijst of midden in 17165 een import, dan zou dit je daaruit gooien. */ 17166 if (_stand === 'knop') toonKnop(); 17167 vulProfielVak(); 17168 return _status; 17169 }).catch(function (e) { 17170 console.warn('[GR Strava] status ophalen mislukt:', e); 17171 /* Anders blijft de lader staan en kom je nooit bij het formulier. Zonder
17172 stand weten we niets over Strava, dus dan maar geen knop â het 17173 formulier zelf werkt gewoon met de hand. */ 17174 if (_stand === 'knop') { toon(''); toonFormulier(true); } 17175 /* Even niet opnieuw beginnen. _gecheckt blijft false omdat we nog steeds 17176 niets weten, en de wachtlus tikt elke halve tel â zonder deze pauze 17177 zou hij blijven hameren op een server die net niet antwoordde. Over 17178 een halve minuut mag het weer. */ 17179 _volgendePoging = Date.now() + 30000; 17180 return null; 17181 }).then(function (r) { _statusLoopt = null; return r; }); 17182 17183 return _statusLoopt; 17184 } 17185 17186 /* ââ Koppelen âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 17187 17188 function koppel() { 17189 if (!_status || !_status.clientId) { meld(esc(L.fout), true); return; } 17190 /* De state hoort vers te zijn. Komt de stand uit het geheugen van deze 17191 sessie, dan zit hij er niet bij â eerst ophalen, dan pas het venster 17192 openen. Anders stuurt Strava je terug met "state klopt niet". */ 17193 if (!_status.state) { 17194 meld(esc(L.wachten)); 17195 checkStatus(true).then(function () { meld(''); if (_status && _status.state) koppel(); }); 17196 return; 17197 } 17198 var url = 'https://www.strava.com/oauth/authorize' 17199 + '?client_id=' + encodeURIComponent(_status.clientId) 17200 + '&redirect_uri=' + encodeURIComponent(_status.redirectUri || '') 17201 + '&response_type=code' 17202 + '&approval_prompt=auto' 17203 + '&scope=' + encodeURIComponent(_status.scope || 'read,activity:read_all') 17204 + '&state=' + encodeURIComponent(_status.state || ''); 17205 17206 var venster = window.open(url, 'gr-strava', 'width=620,height=760'); 17207 if (!venster) { meld(esc(L.popupWeg), true); return; } 17208 17209 meld(esc(L.wachten)); 17210 /* Het venster sluit zichzelf na toestemming (stravaTerug_ in strava.gs). 17211 Of dat gelukt is, weten we alleen door het opnieuw te vragen â vandaar 17212 deze klopjes. Na twee minuten houdt het op, zodat er niet eindeloos 17213 verkeer blijft lopen als iemand het venster laat staan. */ 17214 var pogingen = 0; 17215 var tik = setInterval(function () { 17216 pogingen++; 17217 if (pogingen > 60) { clearInterval(tik); meld(''); return; } 17218 checkStatus(true).then(function (s) { 17219 if (s && s.gekoppeld) { clearInterval(tik); meld(''); laadLijst(1, true); } 17220 else if (venster.closed && pogingen > 2) { clearInterval(tik); meld(''); } 17221 }); 17222 }, 2000); 17223 } 17224 17225 /* ââ Stand 3: de lijst ââââââââââââââââââââââââââââââââââââââââââââââââââ */ 17226 17227 var _items = []; // alles wat we tot nu toe hebben opgehaald 17228 var _pagina = 0; 17229 var _meer = false; 17230 var _gekozen = {}; // id â true 17231 17232 function laadLijst(pg, opnieuw) { 17233 if (opnieuw) { _items = []; _pagina = 0; _gekozen = {}; } 17234 meld(''); 17235 toonFormulier(false); 17236 /* Bij "meer laden" blijft de lijst staan en verandert alleen die ene knop in 17237 "Activiteiten ladenâ¦". Eerst werd het hele paneel vervangen: je selectie 17238 verdween uit beeld, de lijst sprong naar boven en je zag even niets. Bij 17239 een eerste keer is er nog niets om te laten staan, dus dan wél de 17240 laadstand. */ 17241 var eersteKeer = !_items.length; 17242 if (eersteKeer) toonPaneel(true); 17243 else zetMeerKnop(true); 17244 17245 haal({ action: 'strava_activities', email: email(), page: pg, per_page: 50 }) 17246 .then(function (j) { 17247 if (!j || j.fout) throw new Error(j && j.fout ? j.fout : 'leeg antwoord'); 17248 _pagina = j.pagina || pg; 17249 _meer = !!j.meer; 17250 /* Dubbele weren: bij "meer laden" kan een rit die net is toegevoegd de 17251 paginagrens verschuiven, en dan komt hij twee keer langs. */ 17252 var gezien = {}; 17253 _items.forEach(function (a) { gezien[a.id] = true; }); 17254 (j.items || []).forEach(function (a) { if (!gezien[a.id]) _items.push(a); }); 17255 /* Zoekterm en positie in de lijst bewaren, want toonPaneel tekent alles 17256 opnieuw. Zonder dit typte je een zoekterm en was die na "meer laden" 17257 weg. */ 17258 var zoekEl = document.getElementById('grStZoek'); 17259 var zoekTerm = zoekEl ? zoekEl.value : ''; 17260 var lijstEl = document.getElementById('grStLijst'); 17261 var scrol = lijstEl ? lijstEl.scrollTop : 0; 17262 toonPaneel(false); 17263 var nieuwZoek = document.getElementById('grStZoek'); 17264 if (nieuwZoek && zoekTerm) { nieuwZoek.value = zoekTerm; nieuwZoek.dispatchEvent(new Event('input')); } 17265 var nieuwLijst = document.getElementById('grStLijst'); 17266 if (nieuwLijst && scrol) nieuwLijst.scrollTop = scrol; 17267 }) 17268 .catch(function (e) { 17269 console.warn('[GR Strava] activiteiten ophalen mislukt:', e); 17270 if (eersteKeer) { 17271 toonFout(function () { laadLijst(1, true); }); 17272 } else { 17273 /* De lijst die je al had blijft staan; alleen de knop meldt dat het 17274 niet lukte en biedt een nieuwe poging aan. */ 17275 zetMeerKnop(false); 17276 meldFout(function () { laadLijst(_pagina + 1, false); }); 17277 } 17278 }); 17279 } 17280 17281 /* Alleen de knop "Meer laden" van stand wisselen, zonder de lijst aan te 17282 raken. */ 17283 function zetMeerKnop(bezig) { 17284 var k = document.getElementById('grStMeer'); 17285 if (!k) return;
17286 k.disabled = !!bezig; 17287 if (bezig) { 17288 /* De tekst laten we door de teller zetten, anders schrijven we er hier 17289 overheen en staan de seconden er maar één tel. */ 17290 k.setAttribute('data-gr-st-teller', L.laden); 17291 startTeller(); 17292 } else { 17293 k.removeAttribute('data-gr-st-teller'); 17294 k.textContent = L.meer; 17295 stopTeller(); 17296 } 17297 } 17298 17299 /* Het hele paneel vervangen door een foutmelding met twee uitwegen: het nog 17300 eens proberen, of de pagina verversen als ook dat niet helpt. */ 17301 function toonFout(nogEens) { 17302 _stand = 'fout'; 17303 toon('<div class="gr-st-vak"><div class="gr-st-paneel">' 17304 + '<p class="gr-st-fout">' + esc(L.fout) + '</p>' 17305 + '<div class="gr-st-voet">' 17306 + '<button type="button" class="gr-st-knop" id="grStOpnieuw"><span>' + esc(L.opnieuw) + '</span></button>' 17307 + '<button type="button" class="gr-st-tekstknop" id="grStVerst">' + esc(L.ververs) + '</button>' 17308 + '<button type="button" class="gr-st-tekstknop" id="grStSluit2">' + esc(L.sluit) + '</button>' 17309 + '</div></div></div>'); 17310 var o = document.getElementById('grStOpnieuw'); 17311 if (o) o.addEventListener('click', function () { nogEens(); }); 17312 var v = document.getElementById('grStVerst'); 17313 if (v) v.addEventListener('click', function () { location.reload(); }); 17314 var sl = document.getElementById('grStSluit2'); 17315 if (sl) sl.addEventListener('click', function () { toonKnop(); toonFormulier(true); meld(''); }); 17316 } 17317 17318 /* Zelfde uitwegen, maar als regel onder de lijst â die blijft dan staan. */ 17319 function meldFout(nogEens) { 17320 meld(esc(L.fout) 17321 + ' <a href="#" id="grStOpnieuw2" style="color:inherit;font-weight:700;">' + esc(L.opnieuw) + '</a>' 17322 + ' · <a href="#" id="grStVerst2" style="color:inherit;font-weight:700;">' + esc(L.ververs) + '</a>', true); 17323 var o = document.getElementById('grStOpnieuw2'); 17324 if (o) o.addEventListener('click', function (e) { e.preventDefault(); meld(''); nogEens(); }); 17325 var v = document.getElementById('grStVerst2'); 17326 if (v) v.addEventListener('click', function (e) { e.preventDefault(); location.reload(); }); 17327 } 17328 17329 function gefilterd() { 17330 var veld = document.getElementById('grStZoek'); 17331 var q = veld ? veld.value.trim().toLowerCase() : ''; 17332 if (!q) return _items; 17333 return _items.filter(function (a) { 17334 return (a.naam || '').toLowerCase().indexOf(q) !== -1 17335 || (a.gebied || '').toLowerCase().indexOf(q) !== -1 17336 || datumNL(a.start).indexOf(q) !== -1; 17337 }); 17338 } 17339 17340 /* De beschrijving van één activiteit: naam op de eerste regel, de gegevens 17341 eronder. Twee keer gebruikt â in de keuzelijst en straks bij de rit die je 17342 aan het importeren bent â zodat je hetzelfde blokje terugziet. */ 17343 function itemHtml(a) { 17344 var meta = [datumNL(a.start), a.km ? a.km + ' km' : '', a.hm ? a.hm + ' hm' : '', hms(a.duurSec)] 17345 .filter(Boolean).join(' · '); 17346 return '<span class="gr-st-rij-tekst">' 17347 + '<span class="gr-st-titel">' + esc(a.naam) + '</span>' 17348 + '<span class="gr-st-meta">' + esc(meta) 17349 + (a.gebied ? ' · <span class="gr-st-gebied">' + esc(a.gebied) + '</span>' : '') 17350 + '</span></span>'; 17351 } 17352 17353 function rijHtml(a) { 17354 return '<label class="gr-st-rij">' 17355 + '<input type="checkbox" class="gr-st-vink" value="' + esc(a.id) + '"' 17356 + (_gekozen[a.id] ? ' checked' : '') + '>' 17357 + itemHtml(a) + '</label>'; 17358 } 17359 17360 function aantalGekozen() { return Object.keys(_gekozen).length; } 17361 17362 function werkKnopBij() { 17363 var k = document.getElementById('grStImport'); 17364 if (!k) return; 17365 var n = aantalGekozen(); 17366 k.querySelector('span').textContent = L.importeer + (n ? ' (' + n + ')' : ''); 17367 k.disabled = n === 0; 17368 } 17369 17370 function toonPaneel(bezig) { 17371 _stand = 'lijst'; 17372 var lijst = bezig 17373 ? '<p class="gr-st-info"><span class="gr-st-tol"></span> ' 17374 + '<span data-gr-st-teller="' + esc(L.laden) + '">' + esc(L.laden) + '</span>' 17375 + traagRegel() + '</p>' 17376 : (function () { 17377 var rijen = gefilterd(); 17378 if (!_items.length) return '<p class="gr-st-info">' + esc(L.leeg) + '</p>'; 17379 if (!rijen.length) return '<p class="gr-st-info">' + esc(L.geenTreffer) + '</p>'; 17380 return rijen.map(rijHtml).join(''); 17381 })(); 17382 17383 toon('<div class="gr-st-vak"><div class="gr-st-paneel">' 17384 + '<div class="gr-st-zoekrij">' 17385 + '<input type="text" id="grStZoek" class="gr-st-zoek" placeholder="' + esc(L.zoek) + '" autocomplete="off">' 17386 + '</div>' 17387 + '<div class="gr-st-lijst" id="grStLijst">' + lijst + '</div>' 17388 /* Teller links, "Meer laden" rechts. De rij staat er ook als er niets 17389 meer te laden valt: dan wil je nog steeds zien hoeveel je hebt. */ 17390 + (bezig ? '' : '<div class="gr-st-meerrij">' 17391 + '<span class="gr-st-teller">' + esc(L.aantal.replace('%n%', _items.length)) + '</span>'
17392 + (_meer ? '<button type="button" class="gr-st-tekstknop" id="grStMeer">' + esc(L.meer) + '</button>' : '') 17393 + '</div>') 17394 + '<div class="gr-st-voet">' 17395 + '<button type="button" class="gr-st-knop" id="grStImport" disabled>' + SVG_STRAVA + '<span>' + esc(L.importeer) + '</span></button>' 17396 + '<button type="button" class="gr-st-tekstknop" id="grStSluit">' + esc(L.sluit) + '</button>' 17397 + '</div></div></div>'); 17398 17399 if (bezig) { startTeller(); return; } 17400 stopTeller(); 17401 17402 var zoek = document.getElementById('grStZoek'); 17403 if (zoek) { 17404 /* Alleen de lijst opnieuw tekenen, niet het hele paneel: anders raakt het 17405 zoekveld bij elke toetsaanslag de aandacht kwijt. */ 17406 zoek.addEventListener('input', function () { 17407 var vak = document.getElementById('grStLijst'); 17408 if (!vak) return; 17409 var rijen = gefilterd(); 17410 vak.innerHTML = rijen.length ? rijen.map(rijHtml).join('') 17411 : '<p class="gr-st-info">' + esc(L.geenTreffer) + '</p>'; 17412 }); 17413 } 17414 17415 var vakLijst = document.getElementById('grStLijst'); 17416 if (vakLijst) vakLijst.addEventListener('change', function (e) { 17417 var v = e.target; 17418 if (!v || !v.classList.contains('gr-st-vink')) return; 17419 if (v.checked) _gekozen[v.value] = true; else delete _gekozen[v.value]; 17420 werkKnopBij(); 17421 }); 17422 17423 var meerKnop = document.getElementById('grStMeer'); 17424 if (meerKnop) meerKnop.addEventListener('click', function () { laadLijst(_pagina + 1, false); }); 17425 17426 var sluit = document.getElementById('grStSluit'); 17427 if (sluit) sluit.addEventListener('click', function () { toonKnop(); toonFormulier(true); meld(''); }); 17428 17429 var imp = document.getElementById('grStImport'); 17430 if (imp) imp.addEventListener('click', start); 17431 17432 werkKnopBij(); 17433 } 17434 17435 /* ââ Importeren: één voor één door het formulier ââââââââââââââââââââââââ */ 17436 17437 function start() { 17438 var ids = Object.keys(_gekozen); 17439 if (!ids.length) { meld(esc(L.kiesEerst), true); return; } 17440 /* In de volgorde waarin ze in de lijst staan, dus nieuwste eerst. */ 17441 /* De hele items in de wachtrij en niet alleen hun nummers: bij de volgende 17442 stap tonen we het blokje opnieuw, en dan moeten naam, datum en afstand nog 17443 bij de hand zijn. */ 17444 window.GR_STRAVA_WACHTRIJ = _items.filter(function (a) { return _gekozen[a.id]; }); 17445 window.GR_STRAVA_TOTAAL = window.GR_STRAVA_WACHTRIJ.length; 17446 window._grStravaVolgende(); 17447 } 17448 17449 /* De kop boven het formulier tijdens het importeren: welke rit van hoeveel, 17450 het blokje dat je aanvinkte, en zolang de gegevens onderweg zijn een lader 17451 in plaats van het formulier. */ 17452 function tekenStap(item, nu, totaal, bezig) { 17453 _stand = 'stap'; 17454 if (!bezig) stopTeller(); 17455 toon('<div class="gr-st-vak"><div class="gr-st-voortgang">' 17456 + '<span class="gr-st-voortgang-kop">' 17457 + esc(L.voortgang.replace('%n%', nu).replace('%t%', totaal)) + '</span>' 17458 + '<button type="button" class="gr-st-tekstknop" id="grStSla">' + esc(L.overslaan) + '</button>' 17459 + '</div>' 17460 + (item && item.naam ? '<div class="gr-st-huidig">' + itemHtml(item) + '</div>' : '') 17461 + (bezig ? '<div class="gr-st-lader"><span class="gr-st-tol"></span>' 17462 + '<span data-gr-st-teller="' + esc(L.overnemen) + '">' + esc(L.overnemen) + '</span>' 17463 + traagRegel() + '</div>' : '') 17464 + '</div>'); 17465 if (bezig) startTeller(); 17466 var sla = document.getElementById('grStSla'); 17467 if (sla) sla.addEventListener('click', function () { 17468 if (!window._grStravaVolgende()) { toonKnop(); toonFormulier(true); meld(esc(L.klaar)); } 17469 }); 17470 } 17471 17472 /* Wordt ook door gr-planner-script aangeroepen, na het opslaan van een rit. */ 17473 window._grStravaVolgende = function () { 17474 var rij = window.GR_STRAVA_WACHTRIJ || []; 17475 if (!rij.length) { 17476 window.GR_STRAVA_HUIDIG = null; 17477 window.GR_STRAVA_TOTAAL = 0; 17478 toonFormulier(true); 17479 return false; 17480 } 17481 var item = rij.shift(); 17482 var id = item && item.id ? item.id : item; // ook een kaal nummer blijft werken 17483 var totaal = window.GR_STRAVA_TOTAAL || 1; 17484 var nu = totaal - rij.length; 17485 17486 herstelFormulier(); 17487 /* Formulier blijft nog even weg. Het ophalen van de omschrijving duurt soms 17488 een tel of twee, en in die tijd stonden de velden er leeg bij â of erger, 17489 nog gevuld met de vorige rit. Dan lijkt het alsof er niets gebeurt, of dat 17490 de verkeerde gegevens zijn overgenomen. Nu zie je een lader, en het 17491 formulier verschijnt pas als alles erin staat. */ 17492 toonFormulier(false); 17493 tekenStap(item, nu, totaal, true); 17494 17495 meld(''); 17496 haal({ action: 'strava_activity', email: email(), id: id }) 17497 .then(function (j) { 17498 var a = (j && j.item) || null; 17499 if (!a) throw new Error('geen item'); 17500 window.GR_STRAVA_HUIDIG = a; 17501 vulFormulier(a); 17502 tekenStap(item, nu, totaal, false); 17503 toonFormulier(true); 17504 }) 17505 .catch(function (e) { 17506 console.warn('[GR Strava] activiteit ophalen mislukt:', e); 17507 tekenStap(item, nu, totaal, false); 17508 meldFout(function () {
17509 /* Dezelfde rit nog eens: terug vooraan in de wachtrij zetten en 17510 opnieuw beginnen, zodat de telling blijft kloppen. */ 17511 (window.GR_STRAVA_WACHTRIJ || []).unshift(item); 17512 window._grStravaVolgende(); 17513 }); 17514 }); 17515 return true; 17516 }; 17517 17518 /* Na een opgeslagen rit heeft gr-planner-script het formulier verborgen en de 17519 gelukt-melding getoond. Voor de volgende rit moet dat weer terug. */ 17520 function herstelFormulier() { 17521 var f = document.getElementById('activityForm'); 17522 var ok = document.getElementById('addSuccessMsg'); 17523 var fout = document.getElementById('addErrorMsg'); 17524 if (f) f.style.display = ''; 17525 if (ok) ok.style.display = 'none'; 17526 if (fout) fout.style.display = 'none'; 17527 var btn = document.getElementById('submitBtn'); 17528 if (btn) btn.disabled = false; 17529 } 17530 17531 function zetKeuze(select, waarde) { 17532 if (!select || !waarde) return false; 17533 var doel = String(waarde).trim().toLowerCase(); 17534 var opt = Array.prototype.slice.call(select.options).find(function (o) { 17535 return String(o.value).trim().toLowerCase() === doel; 17536 }); 17537 if (!opt) return false; 17538 select.value = opt.value; 17539 return true; 17540 } 17541 17542 function vulFormulier(a) { 17543 var gebiedEl = document.getElementById('areaInput'); 17544 if (zetKeuze(gebiedEl, a.gebied)) { 17545 /* change afvuren, want dáár vult de planner het routetype mee. Pas 17546 daarna heeft de tweede select opties om uit te kiezen. */ 17547 gebiedEl.dispatchEvent(new Event('change')); 17548 zetKeuze(document.getElementById('routeTypeInput'), a.routeType); 17549 } 17550 17551 var start = String(a.start || ''); 17552 var dStart = document.getElementById('dateStartInput'); 17553 var tStart = document.getElementById('timeStartInput'); 17554 /* Bewust géén change afvuren op de datum: die luisteraar rekent de duur 17555 opnieuw uit aan de hand van de einddatum, en die laten we leeg. De duur 17556 die Strava meet is nauwkeuriger dan begin tot eind. */ 17557 if (dStart) dStart.value = start.slice(0, 10); 17558 if (tStart) tStart.value = start.slice(11, 16); 17559 17560 var duur = document.getElementById('durationInput'); 17561 if (duur) duur.value = hms(a.duurSec || a.totaalSec); 17562 17563 var link = document.getElementById('linkInput'); 17564 if (link) link.value = a.link || ''; 17565 17566 var opm = document.getElementById('remarksInput'); 17567 if (opm) opm.value = a.opmerking || ''; 17568 17569 /* Het cijfer blijft leeg: dat is een oordeel en geen meting. Het veld is 17570 verplicht, dus het formulier vraagt er vanzelf om. */ 17571 17572 var wrap = document.getElementById('formContainerWrapper'); 17573 if (wrap) wrap.style.display = ''; 17574 var f = document.getElementById('activityForm'); 17575 if (f && f.scrollIntoView) f.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); 17576 } 17577 17578 /* ââ Ontkoppelen, vanuit Profiel bewerken âââââââââââââââââââââââââââââââ */ 17579 17580 /* Het vak staat in gr-modals en begint verborgen. Alleen wie gekoppeld is 17581 krijgt het te zien: voor de rest valt er niets te ontkoppelen. */ 17582 function vulProfielVak() { 17583 var vak = document.getElementById('grPmStravaVak'); 17584 if (!vak) return; 17585 if (!_status || !_status.gekoppeld) { vak.style.display = 'none'; return; } 17586 vak.style.display = ''; 17587 var naam = document.getElementById('grPmStravaNaam'); 17588 if (naam) { 17589 var wie = _status.athleetNaam || _status.athleetId || ''; 17590 naam.textContent = wie ? L.gekoppeldAls.replace('%s%', wie) : ''; 17591 } 17592 } 17593 17594 var _ontkoppelAan = false; 17595 function bindOntkoppel() { 17596 var knop = document.getElementById('grPmStravaOntkoppel'); 17597 if (!knop || _ontkoppelAan) return; 17598 _ontkoppelAan = true; 17599 knop.addEventListener('click', function () { 17600 if (!window.confirm(L.ontkoppelVraag)) return; 17601 knop.disabled = true; 17602 var oud = knop.textContent; 17603 knop.textContent = L.ontkoppelBezig; 17604 /* mode no-cors: het antwoord is toch niet te lezen, en meer dan "het is 17605 verstuurd" hebben we hier niet nodig. Daarna vragen we de stand gewoon 17606 opnieuw op â dát is het echte bewijs. */ 17607 fetch(SCRIPT_URL, { 17608 method: 'POST', mode: 'no-cors', 17609 headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, 17610 body: JSON.stringify({ action: 'strava_disconnect', email: email() }) 17611 }).catch(function () {}) 17612 .then(function () { return new Promise(function (r) { setTimeout(r, 1200); }); }) 17613 .then(function () { return checkStatus(true); }) 17614 .then(function () { 17615 knop.disabled = false;
17616 knop.textContent = oud; 17617 vulProfielVak(); 17618 if (_status && !_status.gekoppeld) { 17619 /* Zat je midden in een lijst of import, dan slaat die nergens meer 17620 op zonder koppeling. */ 17621 window.GR_STRAVA_WACHTRIJ = []; 17622 window.GR_STRAVA_HUIDIG = null; 17623 toonKnop(); 17624 } 17625 }); 17626 }); 17627 } 17628 17629 /* ââ Aanzetten zodra de modal opengaat ââââââââââââââââââââââââââââââââââ */ 17630 17631 /* De knop pas ophalen als de modal in beeld komt: op een pagina waar niemand 17632 hem opent hoeft er geen verzoek naar Apps Script te gaan. */ 17633 function kijk() { 17634 /* Het profielmodaal heeft zijn eigen aanleiding: staat het Strava-vak in de 17635 pagina en is het profiel open, dan willen we de stand ook weten. */ 17636 var pm = document.getElementById('grPmStravaVak'); 17637 if (pm) { 17638 bindOntkoppel(); 17639 /* #grProfileModal is de overlay van gr-modals; er is ook een oudere 17640 #profileModal in omloop, dus allebei meenemen. closest() pakt vanzelf 17641 degene die er is. */ 17642 var pmOpen = pm.closest('#grProfileModal') || pm.closest('#profileModal'); 17643 if (pmOpen && pmOpen.getClientRects().length) { 17644 if (!_gecheckt && email()) checkStatus(false); else vulProfielVak(); 17645 } 17646 } 17647 17648 var m = document.getElementById('ritModal'); 17649 if (!m || !anker()) return; 17650 /* Op getClientRects en niet op style.display: de modal gaat op meerdere 17651 plekken open â de ene zet display op flex, de andere loopt via 17652 grPalOpenActivityForm. Wat ze gemeen hebben is dat hij daarna te zien is, 17653 en dat is precies wat dit meet. Werkt ook bij position:fixed, waar 17654 offsetParent altijd null blijft. */ 17655 if (m.getClientRects().length === 0) return; 17656 if (!_gecheckt && Date.now() >= _volgendePoging) { 17657 /* Weten we het van een eerdere keer deze sessie, dan meteen de knop en 17658 geen lader. Ondertussen vragen we stil na of het nog klopt; wijkt het 17659 antwoord af, dan tekent checkStatus alsnog bij. 17660 17661 Alleen als we niets weten komt de lader in beeld, en dan vóórdat de 17662 vraag de deur uit gaat â anders zie je toch nog een tel het formulier 17663 zonder knop. */ 17664 var bewaard = leesBewaard(); 17665 if (bewaard && !_status) { 17666 _status = bewaard; 17667 toonKnop(); 17668 } else if (!_statusLoopt) { 17669 toonStartLader(); 17670 } 17671 checkStatus(true); 17672 } 17673 } 17674 17675 /* Alvast navragen, zonder iets te tekenen. Apps Script start koud op: de 17676 eerste vraag na een tijdje stilte kostte bij de meting 10,7 seconden, elke 17677 vraag daarna ongeveer één. Doen we dat pas als de modal opengaat, dan staat 17678 die wachttijd vol in beeld. 17679 17680 Even geduld voor we beginnen, zodat dit niet in de weg loopt bij het laden 17681 van de ritten zelf. En alleen op een pagina waar de modal ook echt staat. */ 17682 function warmDraaien() { 17683 if (_gecheckt || _statusLoopt || !anker() || !email()) return; 17684 checkStatus(true); 17685 } 17686 17687 if (document.readyState === 'loading') { 17688 document.addEventListener('DOMContentLoaded', function () { 17689 setTimeout(warmDraaien, 2500); 17690 setInterval(kijk, 500); 17691 }); 17692 } else { 17693 setTimeout(warmDraaien, 2500); 17694 setInterval(kijk, 500); 17695 } 17696})(); 17697</script>
17697 17698 17699 17700 </div> 17701</div> 17702 17703 17704</section><section id="shopify-section-sections--24695135142262__custom_liquid_W9xJgX" class="shopify-section shopify-section-group-footer-group section"><style data-shopify>.section-sections--24695135142262__custom_liquid_W9xJgX-padding { 17705 padding-top: calc(0px * 0.75); 17706 padding-bottom: calc(0px * 0.75); 17707 } 17708 17709 @media screen and (min-width: 750px) { 17710 .section-sections--24695135142262__custom_liquid_W9xJgX-padding { 17711 padding-top: 0px; 17712 padding-bottom: 0px; 17713 } 17714 }</style><div class="color-scheme-4 gradient"> 17715 <div class="section-sections--24695135142262__custom_liquid_W9xJgX-padding"> 17716 <div class="footer__content-top page-width"><div class="footer__blocks-wrapper grid grid--1-col scroll-trigger animate--slide-in" data-cascade="" style="--animation-order: 0;"><div class="footer-block grid__item scroll-trigger animate--slide-in" data-cascade="" style="--animation-order: 1;"><div class="footer-block__details-content footer-block-image center"></div></div> 17717 17718<div class="footer-block grid__item scroll-trigger animate--slide-in" data-cascade="" style="--animation-order: 2;"><div class="footer-block__details-content footer-block-image center"> 17719 17720<div class="footer-block__image-wrapper" style="max-width: min(100%, 100px);"><img src="https://cdn.shopify.com/s/files/1/0899/1277/0934/files/mr_granrondo.png?v=1767305175&width=500" alt="" loading="lazy" width="591" height="591"></div> 17721 17722</div></div><div class="footer-block grid__item footer-block--menu scroll-trigger animate--slide-in" data-cascade="" style="--animation-order: 0;"><ul class="footer-block__details-content list-unstyled"><li> 17723 <a href="#" 17724 class="link link--text list-menu__item list-menu__item--link js-mail" 17725 data-user="mr" 17726 data-domain="ridearound" 17727 data-tld="cc" 17728 data-subject="Vraag over ridearound.cc" 17729 data-body="Hi Michel,"> 17730 [email protected] 17731</a> 17732
17733<script> 17734(function () { 17735 const enc = encodeURIComponent; 17736 17737 document.querySelectorAll('.js-mail').forEach(function(a){ 17738 const u = a.dataset.user || ''; 17739 const d = a.dataset.domain || ''; 17740 const t = a.dataset.tld || ''; 17741 17742 a.addEventListener('click', function(e){ 17743 e.preventDefault(); 17744 const addr = u + '\u0040' + d + '.' + t; // "@" als unicode 17745 const subject = a.dataset.subject ? enc(a.dataset.subject) : ''; 17746 const body = a.dataset.body ? enc(a.dataset.body) : ''; 17747 const qs = (subject || body) ? `?subject=${subject}&body=${body}` : ''; 17748 window.location.href = `mailto:${addr}${qs}`; 17749 }); 17750 }); 17751})(); 17752</script>
17752<br><br> 17753<center> 17754<style> 17755.icon-insta { 17756 display: inline-block; 17757 width: 40px; 17758 height: 40px; 17759 background: transparent; 17760 border-radius: 50%; 17761 /* Geen mask meer, maar fill-rule="evenodd" gecombineerd in één pad (zoals Strava) */ 17762 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 19.2 19.2'%3E%3Cpath fill='%232EDFC2' fill-rule='evenodd' d='M9.6,0A9.6,9.6,0,1,1,9.59,0ZM13.498 6.651a1.656 1.656 0 0 0-.95-.949 2.766 2.766 0 0 0-.928-.172c-.527-.024-.685-.03-2.02-.03s-1.493.006-2.02.03a2.766 2.766 0 0 0-.929.172 1.656 1.656 0 0 0-.949.95 2.766 2.766 0 0 0-.172.928c-.024.527-.03.685-.03 2.02s.006 1.493.03 2.02a2.766 2.766 0 0 0 .172.929 1.656 1.656 0 0 0 .95.949 2.766 2.766 0 0 0 .928.172c.527.024.685.029 2.02.029s1.493-.005 2.02-.03a2.766 2.766 0 0 0 .929-.171 1.656 1.656 0 0 0 .949-.95 2.766 2.766 0 0 0 .172-.928c.024-.527.029-.685.029-2.02s-.005-1.493-.03-2.02a2.766 2.766 0 0 0-.171-.929z M9.6 12.168A2.568 2.568 0 1 1 12.168 9.6 2.568 2.568 0 0 1 9.6 12.168z m2.669-4.637a.6.6 0 1 1 .6-.6.6.6 0 0 1-.6.6z M11.267 9.6A1.667 1.667 0 1 1 9.6 7.933 1.667 1.667 0 0 1 11.267 9.6z'/%3E%3C/svg%3E"); 17763 background-repeat: no-repeat; 17764 background-position: center; 17765 background-size: contain; 17766} 17767 17768.icon-komoot { 17769 display: inline-block; 17770 width: 40px; 17771 height: 40px; 17772 background: transparent; 17773 border-radius: 50%; 17774 /* Masker vervangen door berekend samengevoegd pad */ 17775 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%232EDFC2' fill-rule='evenodd' d='M12,0A12,12,0,1,1,11.9,0Z M10.9 13.4145 l1.1 -1.715 l1.1 1.715 l2.981 2.981 A5.973 5.973 0 0 1 12 18 c-1.5215 0 -2.9675 -0.57 -4.081 -1.6045 z M6 12 C6 8.6925 8.6925 6 12 6 c3.31 0 6 2.6925 6 6 c0 1.3315 -0.4275 2.5875 -1.2345 3.642 l-3.009 -3.009 c0.075 -0.206 0.113 -0.4195 0.113 -0.635 A1.8715 1.8715 0 0 0 12 10.1285 a1.8715 1.8715 0 0 0 -1.8695 1.8695 c0 0.2155 0.0375 0.429 0.113 0.635 l-3.009 3.009 A5.9325 5.9325 0 0 1 6 12 Z'/%3E%3C/svg%3E"); 17776 background-repeat: no-repeat; 17777 background-position: center; 17778 background-size: 100% 100%; 17779} 17780 17781.icon-strava { 17782 display: inline-block; 17783 width: 40px; 17784 height: 40px; 17785 background: transparent; 17786 border-radius: 50%; 17787 /* Correcte url-encoding zonder regeleindes die iOS in de war maken */ 17788 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='%232EDFC2' fill-rule='evenodd' d='M10 0A10 10 0 1 0 10 20A10 10 0 1 0 10 0Z M9.075 4.168L5.626 10.820L7.658 10.820L9.074 8.175L10.481 10.820L12.498 10.820Z M12.497 10.820L11.497 12.829L10.481 10.820L8.941 10.820L11.497 15.832L14.036 10.820Z'/%3E%3C/svg%3E"); 17789 background-repeat: no-repeat; 17790 background-position: center; 17791 background-size: 100% 100%; 17792} 17793 17794/* FIX VOOR TAP/KLIKBAARHEID OP IOS */ 17795nav.icons a { 17796 position: relative; 17797 display: inline-block; 17798 z-index: 50; 17799 border-bottom: none !important; 17800} 17801nav.icons span { 17802 pointer-events: none; /* Voorkomt dat de klik op de lege span valt */ 17803} 17804</style> 17805<nav class="icons"> 17806<a href="https://www.instagram.com/granrondo.cc" target="_blank" class="link link--text"> <span class="icon-insta"></span></a> 17807<a href="https://www.strava.com/clubs/granrondo" target="_blank" class="link link--text"> <span class="icon-strava"></span></a> 17808<a href="https://www.komoot.com/nl-nl/user/618621809685" target="_blank" class="link link--text"> <span class="icon-komoot"></span></a> 17809</nav> 17810</center> 17811 </li></ul></div> 17812 </div> 17813 </div> 17814</div> 17815 17816 17817<style> #shopify-section-sections--24695135142262__custom_liquid_W9xJgX .footer__c
17817ontent-top {padding-bottom: 0rem; margin: auto;} #shopify-section-sections--24695135142262__custom_liquid_W9xJgX .grid {display: block; text-align: center;} #shopify-section-sections--24695135142262__custom_liquid_W9xJgX .footer-block__details-content {display: inline-flex; align-items: flex-end;} #shopify-section-sections--24695135142262__custom_liquid_W9xJgX .footer-block:nth-child(2) img {border-radius: 50%;} #shopify-section-sections--24695135142262__custom_liquid_W9xJgX .footer-block:nth-child(3) a {color: #11efd6; font-size: 1.5rem; line-height: 1.7rem; text-decoration: none; padding: 0; border-bottom: dotted 3px;} @media screen and (max-width: 989px) {#shopify-section-sections--24695135142262__custom_liquid_W9xJgX .footer-block__details-content, #shopify-section-sections--24695135142262__custom_liquid_W9xJgX div {margin: 0; }} </style></section><section id="shopify-section-sections--24695135142262__custom_liquid_yzrWwX" class="shopify-section shopify-section-group-footer-group section"><style data-shopify>.section-sections--24695135142262__custom_liquid_yzrWwX-padding { 17818 padding-top: calc(60px * 0.75); 17819 padding-bottom: calc(48px * 0.75); 17820 } 17821 17822 @media screen and (min-width: 750px) { 17823 .section-sections--24695135142262__custom_liquid_yzrWwX-padding { 17824 padding-top: 60px; 17825 padding-bottom: 48px; 17826 } 17827 }</style><div class="color-scheme-4 gradient"> 17828 <div class="section-sections--24695135142262__custom_liquid_yzrWwX-padding"> 17829 <div class="footer__content-top page-width"><div class="footer__blocks-wrapper grid grid--1-col grid--2-col grid--4-col-tablet scroll-trigger animate--slide-in" data-cascade="" style="--animation-order: 0;"><div class="footer-block grid__item footer-block--menu scroll-trigger animate--slide-in" data-cascade="" style="--animation-order: 1;"><ul class="footer-block__details-content list-unstyled"><li> 17830 <a href="https://granrondo.cc/pages/samen-voor-kika" target="_blank" class="link link--text list-menu__item list-menu__item--link"> 17831 Partners 17832 </a> 17833 </li><li> 17834 <a href="https://granrondo.cc/voorwaarden" target="_blank" class="link link--text list-menu__item list-menu__item--link"> 17835 Terms and Conditions 17836 </a> 17837 </li><li> 17838 <a href="https://granrondo.cc/privacy" target="_blank" class="link link--text list-menu__item list-menu__item--link"> 17839 Privacy 17840 </a> 17841 </li></ul></div></div><div class="footer-block--newsletter scroll-trigger animate--slide-in scroll-trigger--offscreen" data-cascade=""></div> 17842 </div> 17843 </div> 17844</div> 17845 17846 17847<style> #shopify-section-sections--24695135142262__custom_liquid_yzrWwX .footer-block {text-align: center;} #shopify-section-sections--24695135142262__custom_liquid_yzrWwX .list-menu__item--link {display: inline-block; margin-top: 1rem;} #shopify-section-sections--24695135142262__custom_liquid_yzrWwX .footer-block a {color: #d0d5fc; font-size: 1.2rem; line-height: 1.7rem; text-decoration: none; padding: 0; border-bottom: dotted 3px;} #shopify-section-sections--24695135142262__custom_liquid_yzrWwX .footer-block__details-content {margin-bottom: 0rem;} #shopify-section-sections--24695135142262__custom_liquid_yzrWwX .footer__content-top {padding-bottom: 1rem;} </style></section> 17848<!-- END sections: footer-group --> 17849 17850 <ul hidden> 17851 <li id="a11y-refresh-page-message">Choosing a selection results in a full page refresh.</li> 17852 <li id="a11y-new-window-message">Opens in a new window.</li> 17853 </ul> 17854 17855
17855<script> 17856 window.shopUrl = 'https://granrondo.cc'; 17857 window.routes = { 17858 cart_add_url: '/en-en/cart/add', 17859 cart_change_url: '/en-en/cart/change', 17860 cart_update_url: '/en-en/cart/update', 17861 cart_url: '/en-en/cart', 17862 predictive_search_url: '/en-en/search/suggest', 17863 }; 17864 17865 window.cartStrings = { 17866 error: `There was an error while updating your cart. Please try again.`, 17867 quantityError: `You can only add [quantity] of this item to your cart.`, 17868 }; 17869 17870 window.variantStrings = { 17871 addToCart: `Add to cart`, 17872 soldOut: `Sold out`, 17873 unavailable: `Unavailable`, 17874 unavailable_with_option: `[value] - Unavailable`, 17875 }; 17876 17877 window.quickOrderListStrings = { 17878 itemsAdded: `[quantity] items added`, 17879 itemAdded: `[quantity] item added`, 17880 itemsRemoved: `[quantity] items removed`, 17881 itemRemoved: `[quantity] item removed`, 17882 viewCart: `View cart`, 17883 each: `[money]/ea`, 17884 min_error: `This item has a minimum of [min]`, 17885 max_error: `This item has a maximum of [max]`, 17886 step_error: `You can only add this item in increments of [step]`, 17887 }; 17888 17889 window.accessibilityStrings = { 17890 imageAvailable: `Image [index] is now available in gallery view`, 17891 shareSuccess: `Link copied to clipboard`, 17892 pauseSlideshow: `Pause slideshow`, 17893 playSlideshow: `Play slideshow`, 17894 recipientFormExpanded: `Gift card recipient form expanded`, 17895 recipientFormCollapsed: `Gift card recipient form collapsed`, 17896 countrySelectorSearchCount: `[count] countries/regions found`, 17897 }; 17898 </script>
17898 17899 17900 17901
17902<script> 17903 /* Leeg buiten een productpagina; dan tekent het script alleen de kaarten. */ 17904 window.RA_PRODUCT_ROUND_ID = null; 17905</script>
17905 17906 17907<style> 17908 /* display hoort hier en niet in een inline style op het element: het script 17909 zette eerder style.display om het blok te verbergen, en wiste daarmee ook 17910 de inline-flex die card-product.liquid meegaf. Het blok viel dan terug op 17911 block en de drie spans â die zelf flex zijn â kwamen links onder elkaar. 17912 17913 Verbergen gaat nu via :empty. Zolang er geen beoordeling is blijft het 17914 element letterlijk leeg, dus die selector klopt vanzelf, zowel vóór het 17915 laden als bij nul beoordelingen. Geen enkele regel raakt style.display nog 17916 aan. Als inline-flex-element wordt het blok door de text-align: center van 17917 de kaart vanzelf gecentreerd. */ 17918 .ra-prod-rating { display: inline-flex; align-items: center; gap: 6px; line-height: 1; vertical-align: middle; } 17919 .ra-prod-rating:empty { display: none; } 17920 .ra-prod-rating img { width: var(--ra-ster, 16px); height: var(--ra-ster, 16px); vertical-align: middle; display: inline-block; } 17921 .ra-prod-rating .ra-stars { display: flex; align-items: center; } 17922 .ra-prod-rating .ra-score { font-weight: 600; display: flex; align-items: center; } 17923 .ra-prod-rating .ra-muted { opacity: .7; display: flex; align-items: center; } 17924 /* Onder de bannertitel wat groter, zoals het oude losse script deed. */ 17925 #product-round-rating { --ra-ster: 18px; margin: 12px 0 0; text-align: center; } 17926</style> 17927
17928<script> 17929(function(){ 17930 'use strict'; 17931 17932 /* Twee keer renderen â bijvoorbeeld zowel in de footer als in het 17933 productsjabloon â hoort geen tweede set fetches op te leveren. */ 17934 if (window._grRatingActief) return; 17935 window._grRatingActief = true; 17936 17937 var STAR_FULL = "https://cdn.shopify.com/s/files/1/0899/1277/0934/files/star-icon.png?v=1750252532"; 17938 var STAR_HALF = "https://cdn.shopify.com/s/files/1/0899/1277/0934/files/star-icon-half.png?v=1750252532"; 17939 17940 var ACT_URL = "https://opensheet.elk.sh/1z4oQxDzP6xwMxKY61Lp9X7Ky3wpQ27XjV79oIrJOtWo/Activiteiten"; 17941 var ROUTES_URL = "https://opensheet.elk.sh/1_Bc2komUMc7pVNT8rQkO0_Djnh41O5wCOvBMozarCms/routes"; 17942 17943 var VELD_GEBIED = "Gebied"; 17944 var VELD_CIJFER = "Cijfer"; 17945 var VELD_NAAM = "Naam"; 17946 17947 /* ââ Getallen uit de sheet âââââââââââââââââââââââââââââââââââââââââââ 17948 Nederlands formaat: punt als duizendtal, komma als decimaal. */ 17949 function parseNLFloat(v){ 17950 if (v == null) return NaN; 17951 var n = parseFloat(String(v).trim().replace(/\.(?=\d{3}(\D|$))/g, "").replace(",", ".")); 17952 return isNaN(n) ? NaN : n; 17953 } 17954 17955 function sterren(gem10){ 17956 var vijf = Math.round((Number(gem10) / 2) * 2) / 2; 17957 var heel = Math.floor(vijf); 17958 var half = vijf - heel === 0.5 ? 1 : 0; 17959 var leeg = 5 - heel - half; 17960 var img = function (src, o) { return '<img src="' + src + '" alt="â "' + (o ? ' style="opacity:' + o + '"' : '') + '>'; }; 17961 var uit = ''; 17962 for (var i = 0; i < heel; i++) uit += img(STAR_FULL); 17963 if (half) uit += '<img src="' + STAR_HALF + '" alt="â">'; 17964 for (var j = 0; j < leeg; j++) uit += img(STAR_FULL, '.2'); 17965 return uit; 17966 } 17967 17968 /* ââ Rondematcher ââââââââââââââââââââââââââââââââââââââââââââââââââââ 17969 Het roundid van het product tegen het gebied van een activiteit. De 17970 routes-sheet vertaalt een routenaam naar zijn gebied. */ 17971 function bouwMatcher(routes){ 17972 var naam2gebied = {}; 17973 (routes || []).forEach(function (r) { 17974 var naam = ((r && r[VELD_NAAM]) || '').trim(); 17975 var gebied = ((r && r[VELD_GEBIED]) || '').trim(); 17976 if (naam && gebied) naam2gebied[naam] = gebied; 17977 }); 17978 return function (actGebied, roundId) { 17979 actGebied = (actGebied || '').trim(); 17980 roundId = (roundId || '').trim(); 17981 if (!actGebied || !roundId) return false; 17982 if (actGebied === roundId) return true; 17983 if (roundId.length > 3 && actGebied.slice(-roundId.length) === roundId) return true; 17984 var roundGebied = naam2gebied[roundId]; 17985 if (roundGebied) { 17986 if (roundGebied === actGebied) return true; 17987 if (roundId.length > 3 && roundGebied.slice(-roundId.length) === roundId) return true; 17988 } 17989 return false; 17990 }; 17991 } 17992 17993 /* ââ Data ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 17994 Eén keer ophalen per paginabezoek; elk blok leest uit dezelfde cache. */ 17995 var _acts = [], _matcher = null, _dataP = null, _perSleutel = {}; 17996 17997 function haalData(){ 17998 if (_dataP) return _dataP; 17999 _dataP = Promise.all([ 18000 fetch(ACT_URL).then(function (r) { return r.json(); }).catch(function () { return []; }), 18001 fetch(ROUTES_URL).then(function (r) { return r.json(); }).catch(function () { return []; }) 18002 ]).then(function (paar) { 18003 _acts = paar[0] || []; 18004 _matcher = bouwMatcher(paar[1] || []); 18005 }); 18006 return _dataP; 18007 } 18008 18009 function gemiddelde(sleutel){ 18010 var k = (sleutel || '').trim(); 18011 if (!k) return { gem: 0, aantal: 0 }; 18012 if (_perSleutel[k]) return _perSleutel[k]; 18013 var cijfers = [];
18014 _acts.forEach(function (rij) { 18015 var cij = parseNLFloat(rij && rij[VELD_CIJFER]); 18016 if (!isNaN(cij) && _matcher && _matcher(rij && rij[VELD_GEBIED], k)) cijfers.push(cij); 18017 }); 18018 var aantal = cijfers.length; 18019 var res = { 18020 gem: aantal ? cijfers.reduce(function (a, b) { return a + b; }, 0) / aantal : 0, 18021 aantal: aantal 18022 }; 18023 _perSleutel[k] = res; 18024 return res; 18025 } 18026 18027 /* ââ Tekenen âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 18028 Nul beoordelingen betekent: niets. Geen sterren, geen cijfer, geen 18029 haakjes. Het element blijft leeg en valt weg uit de opmaak, zodat er ook 18030 geen gat overblijft waar de sterren stonden. */ 18031 function teken(el, res){ 18032 /* Geen beoordeling: leeg laten. De CSS-regel .ra-prod-rating:empty haalt 18033 het blok dan uit de opmaak, dus er blijft geen gat over. */ 18034 if (!res.aantal) { el.innerHTML = ''; return; } 18035 var getoond = res.aantal <= 1 ? 1 : res.aantal * 3; 18036 el.innerHTML = 18037 '<span class="ra-stars">' + sterren(res.gem) + '</span>' 18038 + '<span class="ra-score">' + res.gem.toFixed(1) + '</span>' 18039 + '<span class="ra-muted">(' + getoond + ')</span>'; 18040 } 18041 18042 function koppel(el){ 18043 if (el.dataset.raGedaan === '1') return; 18044 el.dataset.raGedaan = '1'; 18045 var sleutel = (el.dataset.roundid || '').trim() || (el.dataset.title || '').trim(); 18046 if (!sleutel) return; 18047 /* Nog niets tekenen: zonder beoordeling hoort er niets te staan, en een 18048 voorlopig cijfer dat daarna verdwijnt is erger dan even niets. Het blok 18049 is leeg en dus onzichtbaar tot de sheets binnen zijn. */ 18050 haalData().then(function () { teken(el, gemiddelde(sleutel)); }); 18051 } 18052 18053 function alleKaarten(){ 18054 Array.prototype.forEach.call(document.querySelectorAll('.ra-prod-rating'), koppel); 18055 } 18056 18057 /* ââ Blok onder de bannertitel op een productpagina âââââââââââââââââ */ 18058 var KOP_SELECTORS = [ 18059 'h1.banner__heading', 'h2.banner__heading', 18060 '.banner__content h1.banner__heading', '.banner__content h2.banner__heading', 18061 'section.image-banner h1.banner__heading', 'section.image-banner h2.banner__heading', 18062 'h1.inline-richtext.h1', 'h2.inline-richtext.h1' 18063 ]; 18064 function zoekKop(){ 18065 for (var i = 0; i < KOP_SELECTORS.length; i++) { 18066 var el = document.querySelector(KOP_SELECTORS[i]); 18067 if (el) return el; 18068 } 18069 return null; 18070 } 18071 function wachtOpKop(tijd){ 18072 return new Promise(function (klaar) { 18073 var nu = zoekKop(); 18074 if (nu) return klaar(nu); 18075 var obs = new MutationObserver(function () { 18076 var el = zoekKop(); 18077 if (el) { obs.disconnect(); klaar(el); } 18078 }); 18079 obs.observe(document.documentElement, { childList: true, subtree: true }); 18080 setTimeout(function () { obs.disconnect(); klaar(zoekKop()); }, tijd || 8000); 18081 }); 18082 } 18083 18084 function bannerBlok(){ 18085 var roundId = String(window.RA_PRODUCT_ROUND_ID || '').trim(); 18086 if (!roundId) return; // geen productpagina, of geen roundid 18087 if (document.getElementById('product-round-rating')) return; 18088 wachtOpKop().then(function (kop) { 18089 if (!kop) { console.warn('[GR rating] bannertitel niet gevonden â geen beoordeling onder de kop.'); return; } 18090 if (document.getElementById('product-round-rating')) return; 18091 var houder = document.createElement('div'); 18092 houder.id = 'product-round-rating'; 18093 var blok = document.createElement('div'); 18094 blok.className = 'ra-prod-rating'; 18095 blok.dataset.roundid = roundId; 18096 houder.appendChild(blok); 18097 kop.insertAdjacentElement('afterend', houder); 18098 koppel(blok); 18099 }); 18100 } 18101 18102 function start(){ 18103 alleKaarten(); 18104 bannerBlok(); 18105 /* Kaarten kunnen later binnenkomen: quick-add-modals, oneindig scrollen, 18106 gefilterde collecties die hun grid vervangen. */ 18107 try { 18108 new MutationObserver(function (muts) { 18109 for (var i = 0; i < muts.length; i++) { 18110 for (var j = 0; j < muts[i].addedNodes.length; j++) { 18111 var n = muts[i].addedNodes[j]; 18112 if (n.nodeType !== 1) continue; 18113 if (n.classList && n.classList.contains('ra-prod-rating')) koppel(n); 18114 else if (n.querySelector && n.querySelector('.ra-prod-rating')) alleKaarten(); 18115 } 18116 } 18117 }).observe(document.documentElement, { childList: true, subtree: true }); 18118 } catch (e) {} 18119 } 18120 18121 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); 18122 else start(); 18123})(); 18124</script>
18124 18125 18126 <style> </style> 18127<div id="shopify-block-ANXJ6b0lIbDZWeTNET__10148494829067693542" class="shopify-block shopify-app-block"><!-- XO-InsertCode Body --> 18128
18128<script> 18129/** 18130 * Script to disable all <a> links whose href contains "-reservering" 18131 * Improves reliability by preventing default click, disabling pointer-events, and setting aria-disabled. 18132 * 18133 * Voeg dit script toe onderaan je theme.js of cart.liquid (net voor </body>) 18134 */ 18135(function() { 18136 'use strict'; 18137 18138 /** 18139 * Disables matching links: removes href, prevents click, and applies styling and accessibility attributes. 18140 */ 18141 function disableReserveringLinks() { 18142 var links = document.querySelectorAll('a[href*="-reservering"]'); 18143 links.forEach(function(link) { 18144 // Skip if already processed 18145 if (link.dataset.reserveringDisabled) return; 18146 // Mark as processed to avoid duplicates 18147 link.dataset.reserveringDisabled = 'true'; 18148 18149 // Remove navigation 18150 link.removeAttribute('href'); 18151 // Prevent default click behavior 18152 link.addEventListener('click', function(event) { 18153 event.preventDefault(); 18154 }); 18155 // Accessibility: indicate disabled state 18156 link.setAttribute('aria-disabled', 'true'); 18157 18158 // Disable pointer events and change cursor 18159 link.style.pointerEvents = 'none'; 18160 link.style.cursor = 'default'; 18161 18162 // Optional styling class for disabled links 18163 link.classList.add('disabled-link'); 18164 }); 18165 } 18166 18167 // Execute when DOM is fully loaded 18168 document.addEventListener('DOMContentLoaded', disableReserveringLinks); 18169 18170 // Observe for dynamic content changes (e.g., AJAX updates) 18171 var observer = new MutationObserver(disableReserveringLinks); 18172 observer.observe(document.body, { childList: true, subtree: true }); 18173})(); 18174</script>
18174 18175 18176 18177 18178<!-- End: XO-InsertCode Body --> 18179 18180 18181</div><div id="shopify-block-AZFd6aGFnS21FS1hVa__13768625480086291342" class="shopify-block shopify-app-block">
18181<script> 18182 window['ShopifyForms'] = { 18183 ...window['ShopifyForms'], 18184 currentPageType: "collection" 18185 }; 18186</script>
18186 18187 18188 18189</div><div id="shopify-block-AR3JjZDY4emxKYnFYS__3720565183479497137" class="shopify-block shopify-app-block">
18189<script> 18190 window.GPOConfigs = window.GPOConfigs || {}; 18191 window.GPOConfigs.appEmbed = true; 18192 window.GPOConfigs.appUrl = 'https://option.globo.io'; 18193 window.GPOConfigs.cdnUrl = '';window.GPOConfigs.assetUrl = 'https://cdn.shopify.com/extensions/01a0f5c2-a34a-7217-a998-4319ae5864cf/globo-product-options-469/assets/'; 18194 window.GPOConfigs.embedAssetUrl = 'https://cdn.shopify.com/extensions/01a0f5c2-a34a-7217-a998-4319ae5864cf/globo-product-options-469/assets/'; 18195 window.GPOConfigs.fileUrl = 'https://granrondo.cc/cdn/shop/files/'; 18196 window.GPOConfigs.shopifyRoot = Shopify?.routes?.root ?? Shopify?.routes?.root_url ?? '/'; 18197 window.GPOConfigs.curCountryCode = "US"; 18198 window.GPOConfigs.optionIds = "";window.GPOConfigs.productOptionSetMap = {"all":"1175761","15634631983478":"1180312","15102157521270":"1180312","15411441074550":"1225000","15345225564534":"1225000","15492746477942":"1537259","15719000113526":"1561268","15775162171766":"1561268"};window.GPOConfigs.options = window.GPOConfigs.options || []; 18199 window.GPOConfigs.page = { type: "collection" };window.GPOConfigs.themeInfo = {"theme_store_id":887,"theme_name":"Dawn","theme_version":"15.2.0"};window.GPOConfigs.theme = {"product":{"form":["section div.gGL0tOtrxz>gp-product product-form form","[data-gpo-product-form]",".gpo-form-wrapper form",".product-form form","form[action*=\"/cart/add\"]:not([hidden]):not([class*=\"installment\"]):not([id*=\"installment\"]):not([class*=\"instalment\"]):not([id*=\"instalment\"])"],"sticky":{"variantActivator":"[data-gpo-sticky-variant-activator]","atcButton":".sticky-atc button,gp-sticky gp-button .gp-button-atc,[id*=js-fixed-btn-template] product-form .product-form__submit"},"imageContainer":"[data-gpo-product-image-container],product-form gp-product-images,.ecom-product-single__media--image.is-active,.product.product--stacked .product__media-list,.pf-media-slider,.product.grid div:not(.ymq_linshi_dom)>media-gallery slider-component,.product__media-wrapper .ymq_product_img_big","imageButton":".thumbnail-list .thumbnail-list__item button.thumbnail,.ecom-product-single__media--thumbnail,.ec_splide__arrow,.pf-slide-list-media,.pf-slider-next,.pf-slider-prev,.product__media-wrapper .ymq_swiper-button-prev,.product__media-wrapper .ymq_swiper-button-next,.product__media-wrapper .ymq_swiper-pagination-bullet,.product__media-wrapper .ymq_product_img_small","image":"[data-gpo-product-image],.product .product__media-list li.is-active img,.product .product__media-list li.is-active .product-media-container.media-type-video deferred-media img,product-form gp-product-images img,.ecom-product-single__media--image.is-active img,.pf-media-slider .is-current img,.product__media-wrapper .ymq_swiper-slide-active img.ymq_zoom_img","unitPrice":"[data-gpo-product-unit-price],product-form gp-product-price .gp-price,gp-product-price.gpo-product-unit-price [type=regular],[data-pf-type*=ProductPrice] [data-product-type=price],.product__info-container [id*=\"price-template\"] .price:not(.price--on-sale) .price__regular .price-item--regular,.product__info-container [id*=\"price-template\"] .price .price__sale .price-item--last,.product_main_info [id*=\"price-template\"] .price:not(.price--on-sale) .price__regular .price-item--regular,.product_main_info [id*=\"price-template\"] .price .price__sale .price-item--last,.gf_product-prices>.gf_product-price.money,gp-product-price>.money,.product--main [id*=ProductPrice],.ecom-product-single__price--sale,.product-form__buttons button .total_price_custom,.gpo-product-price .money,.ecom-product-single__price .money,.bt-product-info .bt-price-main","compareAtPrice":"[data-gpo-product-compare-at-price],gp-product-price.gpo-product-compare-price [type=compare],[data-pf-type*=ProductPrice] [data-product-type=compare_at_price],.product__info-container [id*=\"price-template\"] .price.price--on-sale .price__sale .price-item--regular,.product_main_info [id*=\"price-template\"] .price.price--on-sale .price__sale .price-item--regular,.gf_product-prices>.gf_product-compare-price.money,.product--main [id*=ComparePrice]","variantWrapper":"[id*=\"MainProduct-\"] variant-selects,[id*=\"MainProduct-\"] variant-radios","variantSelector":"[data-gpo-product-variant-selector],gp-product .product-form form [name=id],.product__info-container .product-form form [name=id],.product__info-wrapper product-form form [name=id],product-info product-form [name=id],configurator-form [name=id],.product--main select.product-single__variants,.gpo-form-wrapper form [name=id],[data-pf-type*=ProductVariantSwatches] [name=id],.ecom-product-single__variant-picker [name=id],.ecom-product-form [name=id]","variantActivator":"variant-selects .product-form__input select,variant-radios .product-form__input input,.product--main .select--item select,gp-product-variants input","quantity":"[name=qty],[name=quantity],[name=product_quantity]","addToCartButton":"[data-gpo-product-atc],[data-pf-type*=ProductATC],.gp-button-atc.gpo-gp-atc,gp-button button.gp-button-atc,.lh-buy-now,button.product-buy-buttons--primary,button[id*=AddToCart],button[id*=addToCart],a[id*=AddToCart],a[id*=addToCart],.AddtoCart,.btn-addtocart,.product__add-to-cart-button,button.product-submit,input.product-submit,.product-form--atc-button,.product-form__cart-submit,.product-form__add-button,.product-form--add-to-cart,.product-buy-buttons--cta,.btn--add-to-cart,.button-cart,button.add-to-cart-btn,.add-to-cart-button,.add_to_cart:not(#customily-cart-btn-preview),.button--addToCart,[data-
18199product-add],input.add-to-cart,.smi-button-add-to-cart,button.add-to-cart:not(.ymp_mainBtn),.product-details .add-to-cart-ui button:not(.qty-minus):not(.qty-plus),.gp-button-atc[aria-label=\"Add To Cart\"],.qview-btn-addtocart,[name=add]:not([type=normal]):not([egw-atc-override]),[type=submit]:not([name=subscribe]):not([name=checkout]):not([class*=search]):not(#query-btn):not(.spr-button):not(.active):not(.gpo-exclude):not(.cowlendar-add-to-cart):not([style=\"display:none;\"])","paymentButton":"[data-shopify=\"payment-button\"],[data-product-buy-now],[data-fast-checkout],#button-cart-buy,.shopify-payment-button__button--unbranded","addToCart":{"excludedAttrs":[{"key":"@click","value":"addToCart($event)"}]}},"collection":{"wrapper":".collection,.featured-collection,.pcx-tab-featured,.product-slide-wrapper,.subscription-variety .subscription-variety__options-wrapper","item":".collection .grid__item,.featured-collection .grid__item,.pcx-tab-featured .swiper-slide,.product-slide-wrapper .slick-track .slick-slide,.subscription-variety .product-card-wrapper","productLink":".pcx-tab-featured .swiper-slide a[id*=CardLink],#product-grid .card--media>.card__content>.card__information .card__heading>a,.product-slide-wrapper .slick-track .slick-slide a,.collection .card--media>.card__content>.card__information>.card__heading>a,.product-card-wrapper .card>.card__content .card__heading a","quickViewActivator":"modal-opener button","quickViewProductForm":"quick-add-modal[open] product-form form"},"cart":{"form":["[data-gpo-cart-form]","cart-items form#cart","div[id*=__cart-items] .cart__items","#cart-items","form[action*=\"/cart\"]:not([action*=\"/cart/add\"]):not([hidden])"],"page":[{"lineItem":{"key":"cart-items form .cart-item","image":".cart-item__image","details":".cart-item__details","quantity":{"wrapper":"quantity-input","input":"quantity-input input","decrease":"button[name=minus]","increase":"button[name=plus]"},"removeButton":"cart-remove-button a"}},{"lineItem":{"key":".cart__page .cart__item","image":".cart-item__image","details":".cart__item-details","quantity":{"wrapper":".js-qty__wrapper","input":".js-qty input","decrease":".js-qty__adjust--minus","increase":".js-qty__adjust--plus"},"removeButton":".cart__remove a"}},{"lineItem":{"key":".tableCart tbody tr","details":".cart__content--information","quantity":{"wrapper":".cart__qty","input":".cart__qty input","decrease":"[data-gpo-cart-item-qty-decrease]","increase":"[data-gpo-cart-item-qty-increase]"},"removeButton":".cart__remove a"}},{"lineItem":{"key":"form[action*=\"/cart\"] .cart_item","details":".product-name","quantity":{"wrapper":".quantity","input":".quantity input","decrease":"button.minus","increase":"button.plus"},"removeButton":"a.remove"}},{"lineItem":{"key":"#cart-items .cart-item","details":"#cart-items .cart-item>div>div:nth-child(1)>div:nth-child(2)","quantity":{"wrapper":"#cart-items .cart-item>div>div:nth-child(3)","input":"[x-text*=getQuantity]","decrease":"[\\@click*=minus]","increase":"[\\@click*=plus]"},"removeButton":"[\\@click*=removeItem]"}}]},"theme_store_id":887,"theme_name":"Dawn"};window.GPOConfigs.options[1175761] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"paragraph-3","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-3","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p>How does this work?</p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"Aan","conditionalField":true},{"id":"paragraph-4","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p>How does this work?</p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-4","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","allowed_value":"default","label_on_cart":"Recipient","advanced_addon":"default","text_transform":"none","conditionalField":true,"helptext_position":"below_label"},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen en routes</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>","type":"paragraph","hidden":true,"text_en":"<h3>Rondoneur benefit: <br>Access to all Rondoguides and routes</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>","text_nl":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen en routes</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>","columnWidth":100,"label_on_cart":"buttons-1","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":true},"manual":{"ids":[15091411386742,15032193941878,15100462104950,15100512043382,15102764876150,15102765891958,151027670
1819971606,15102768808310,15102770315638,15103264981366,15103246369142,15103253250422,15103260361078,15103274123638,15032193974646,15103290048886,15103283069302],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":0,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1180312] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"buttons-3","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"oos":"show","type":"buttons","label":"Datum","style":"horizontal","helptext":"Max. 75 deelnemers. Ontvangst om 8.30u bij De Carolinahoeve, De Steeg.","label_en":"Date","label_nl":"Datum","required":true,"columnWidth":100,"helptext_en":"Max. 75 participants. Welcome at 8:30 AM at De Carolinahoeve, De Steeg","helptext_nl":"Max. 75 deelnemers. Ontvangst om 8.30u bij De Carolinahoeve, De Steeg.","scroll_type":"default","default_value":[""],"initial_state":"expand","label_on_cart":"Date","option_values":[{"id":1,"value":"Zondag 13 sep 2026","helptext":"","value_nl":"Zondag 13 sep 2026","variant_id":56775515898230,"variant_price":"0.00","product_handle":"gran-rondo-veluwe-reservering"}],"advanced_addon":"default","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","type":"paragraph","text_en":"<h3>Other person's details</h3>\n<p>Important: Please enter only the details of the other person you are registering below.</p>","text_nl":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","columnWidth":100,"label_on_cart":"heading-1","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Jouw gegevens</h3>","type":"paragraph","text_en":"<h3>Your personal details</h3>","text_nl":"<h3>Jouw gegevens</h3>","columnWidth":100,"label_on_cart":"paragraph-2","conditionalField":true},{"id":"text-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Name","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"null"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"E-mail","conditionalField":true},{"id":"phone-2","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Noodnummer contactpersoon","prefix":"icon","helptext":"Nummer van contactpersoon in noodgeval.","label_en":"Emergency contact number","label_nl":"Noodnummer contactpersoon","required":true,"columnWidth":100,"helptext_en":"Emergency contact phone number","helptext_nl":"Nummer van contactpersoon in noodgeval.","placeholder":"+31612345678","label_on_cart":"Contact number","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true,"helptext_position":"tooltip"},{"id":"datetime-1","clo":{"match":"any","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"Minors under 18 may only participate with parental/guardian consent and must be accompanied by an adult.","helptext_nl":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-6","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"text-4","conditionalField":true},{"id":"paragraph-8","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-8","conditionalField":true},{"id":"paragraph-7","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"},{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo <span style=\"text-decoration: underline;\">voor jezelf</span> bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo <span style=\"text-decoration: underline;\">voor jezelf</span> bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-7","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","pp_font":"default","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"pp_opacity":100,"columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"Recipient","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true,"helptext_position":"below_label"},{"id":"buttons-4","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"oos":"show","type":"buttons","label":"Wegroute of gravelroute?","style":"horizontal","helptext":"Keuze aanpassen is altijd mogelijk. Graag doorgeven aan [email protected]","label_en":"Road route or gravel route?","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"It is always possible to switch. Please inform [email protected]","helptext_nl":"Keuze aanpassen is altijd mogelijk. Graag doorgeven aan [email protected]","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","pp_clipWidth":50,"pp_clipXAxis":50,"pp_clipYAxis":50,"slider_style":"style1","swatch_style":"default","initial_state":"exp
18199and","label_on_cart":"Route","option_values":[{"id":0,"max":"","min":"","name":1783589769987,"unit":"","label":"","value":"Weg","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Road","value_nl":"Weg","addon_type":"manual_product","asset_name":"","color_type":"one-color","placeholder":""},{"id":1,"name":1783589884484,"value":"Gravel","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Gravel","addon_type":"manual_product","asset_name":"","color_type":"one-color"}],"pp_clipHeight":50,"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below"},{"id":"select-2","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"select","label":"Ben je NTFU-lid?","prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","label_en":"Are you an NTFU member?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-2 at checkout to receive a â¬2 discount. If no code is used, we will donate â¬2 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU","option_values":[{"id":0,"value":"Nee ik ben geen NTFU-lid.","helptext":"","value_en":"No. I am not an NTFU member.","value_nl":"Nee ik ben geen NTFU-lid."},{"id":1,"value":"Ja ik ben NTFU-lid en doneer 2 euro","helptext":"","value_en":"Yes. I am an NTFU member and I will donate â¬2.","value_nl":"Ja ik ben NTFU-lid en doneer 2 euro"},{"id":2,"value":"Ja ik ben NTFU-lid en wil 2 euro korting","helptext":"","value_en":"Yes. I am an NTFU member and I would like a â¬2 discount.","value_nl":"Ja ik ben NTFU-lid en wil 2 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"text-3","clo":{"match":"any","whens":[{"value":"Ja ik ben NTFU-lid en doneer 2 euro","where":"EQUALS","select":"select-2"},{"value":"Ja ik ben NTFU-lid en wil 2 euro korting","where":"EQUALS","select":"select-2"}],"display":"show"},"type":"text","label":"NTFU lidnummer","prefix":"icon","pp_font":"default","label_en":"NTFU member ID","label_nl":"NTFU lidnummer","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_opacity":100,"columnWidth":100,"pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"NTFU ID","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15634631983478,15102157521270],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":0,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1225000] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"doorlopend","where":"CONTAINS","select":"shopify_variant","value_en":"Continuous","value_nl":"doorlopend"}],"display":"show"},"text":"<p><em>Voor de betaling van een doorlopend lidmaatschap heb je een bankpas met debit-functie nodig. Ofwel een creditcard of bankpas na 2024/2025.</em><br><br></p>","type":"paragraph","text_en":"<p><em>Voor de betaling van een doorlopend lidmaatschap heb je een bankpas met debit-functie nodig. Ofwel een creditcard of bankpas na 2024/2025.</em></p>","text_nl":"<p><em>Voor de betaling van een doorlopend lidmaatschap heb je een bankpas met debit-functie nodig. Ofwel een creditcard of bankpas na 2024/2025.</em><br><br></p>","columnWidth":100,"label_on_cart":"Lidmaatschap","conditionalField":true},{"id":"dropdown-1","clo":{"match":"all","whens":[{"value":"Supporter","where":"CONTAINS","select":"shopify_variant","value_nl":"Supporter"}],"display":"show"},"oos":"show","type":"dropdown","label":"Kies een bedrag","prefix":"icon","label_en":"Choose an amount","label_nl":"Kies een bedrag","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"placeholder":"-- Selecteer --","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"swatch_style":"default","label_on_cart":"Bedrag","option_values":[{"id":1,"name":1
18199758406065862,"value":"5","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"5","asset_name":"","color_type":"one-color","variant_id":56320467501430,"variant_price":"5.00","product_handle":"support-van-ridearound-cc"},{"id":2,"name":1758406236532,"value":"10","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"10","asset_name":"","color_type":"one-color","variant_id":56320467534198,"variant_price":"10.00","product_handle":"support-van-ridearound-cc"},{"id":3,"name":1758406240636,"value":"20","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"20","asset_name":"","color_type":"one-color","variant_id":56320467566966,"variant_price":"20.00","product_handle":"support-van-ridearound-cc"},{"id":0,"name":1758405982111,"value":"50","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"50","asset_name":"","color_type":"one-color","variant_id":56320467599734,"variant_price":"50.00","product_handle":"support-van-ridearound-cc"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true},{"id":"buttons-2","clo":{"match":"all","whens":[{"value":"Rondoneur","where":"CONTAINS","select":"shopify_variant","value_nl":"Rondoneur"}],"display":"show"},"oos":"show","type":"buttons","label":"<br>Rondoneurs Kit met welkomsvoordeel","style":"horizontal","helptext":"Pak je voordeel en rijd in stijl! <br>Als kersvers lid krijg je je <a href=rondoneur-cap target=\"_blank\">Rondoneur Cap</a> <br>en <a href=rondoneur-socks target=\"_blank\">Rondoneur Socks</a> met 40% korting. <br><br>Niet â¬30, maar slechts â¬18 per item. <br><br>","label_en":"<br>Rondoneurs Kit with welcome discount","label_nl":"<br>Rondoneurs Kit met welkomsvoordeel","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"Get your discount and ride in style! <br>As a brand new member, you get your <a href=\"rondoneur-cap\" target=\"_blank\">Rondoneur Cap</a> <br>and <a href=\"rondoneur-socks\" target=\"_blank\">Rondoneur Socks</a> with a 40% discount. <br><br>Not â¬30, but only â¬18 per item. <br><br>","helptext_nl":"Pak je voordeel en rijd in stijl! <br>Als kersvers lid krijg je je <a href=rondoneur-cap target=\"_blank\">Rondoneur Cap</a> <br>en <a href=rondoneur-socks target=\"_blank\">Rondoneur Socks</a> met 40% korting. <br><br>Niet â¬30, maar slechts â¬18 per item. <br><br>","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"expand","label_on_cart":"Rondoneurskit","option_values":[{"id":0,"name":1767197629713,"value":"Rondoneur Cap (one-size)","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Rondoneur Cap (one-size)","asset_name":"","color_type":"one-color","variant_id":56358706151798,"variant_price":"30.00","product_handle":"rondoneurs-welkomspakket"},{"id":1,"name":1767283399318,"value":"Rondoneur Socks (maat 36-42 / white-blue)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Rondoneur Socks (size 36-42)","value_nl":"Rondoneur Socks (maat 36-42 / white-blue)","asset_name":"","color_type":"one-color","variant_id":57511454245238,"variant_price":"30.00","product_handle":"rondoneur-socks"},{"id":2,"name":1767286624116,"value":"Rondoneur Socks (maat 43-48 / white-blue)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Rondoneur Socks (size 43-48)","value_nl":"Rondoneur Socks (maat 43-48 / white-blue)","asset_name":"","color_type":"one-color","variant_id":57511454310774,"variant_price":"30.00","product_handle":"rondoneur-socks"},{"id":3,"name":1773910108023,"value":"Rondoneur Socks (maat 36-42 / white-purple)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Rondoneur Socks (size 36-42 / white-purple)","value_nl":"Rondoneur Socks (maat 36-42 / white-purple)","asset_name":"","color_type":"one-color","variant_id":57511454212470,"variant_price":"30.00","product_handle":"rondoneur-socks"}
18199,{"id":4,"name":1773910109279,"value":"Rondoneur Socks (maat 43-48 / white-purple)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Rondoneur Socks (size 43-48 / white-purple)","value_nl":"Rondoneur Socks (maat 43-48 / white-purple)","asset_name":"","color_type":"one-color","variant_id":57511454278006,"variant_price":"30.00","product_handle":"rondoneur-socks"}],"advanced_addon":"default","allow_multiple":true,"number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below_label"},{"id":"buttons-3","clo":{"match":"all","whens":[{"value":"Rondoneur","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoneur","value_nl":"Rondoneur"}],"display":"show"},"max":"2","min":"1","oos":"show","type":"buttons","label":"Ik fiets mee op de... (meerder opties mogelijk)","style":"vertical","label_en":"I am cycling in the... (multiple options possible)","label_nl":"Ik fiets mee op de... (meerder opties mogelijk)","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"expand","label_on_cart":"Type","option_values":[{"id":1,"name":1768778269188,"value":"Weg","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Road","value_nl":"Weg","asset_name":"","color_type":"one-color"},{"id":0,"name":1768778217489,"value":"Gravel","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Gravel","asset_name":"","color_type":"one-color"}],"advanced_addon":"default","allow_multiple":true,"number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3"},{"id":"buttons-4","clo":{"match":"all","whens":[{"value":"Rondoneur","where":"CONTAINS","select":"shopify_variant","value_nl":"Rondoneur"}],"display":"show"},"oos":"show","type":"buttons","label":"Wat is je fietstempo?","style":"vertical","label_en":"What's you cycling pace?","label_nl":"Wat is je fietstempo?","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"expand","label_on_cart":"Tempo","option_values":[{"id":1,"name":1768778269188,"value":"< 25 km/u","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"< 25 km/h","value_nl":"< 25 km/u","asset_name":"","color_type":"one-color"},{"id":0,"name":1768778217489,"value":"25-30 km/u","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"25-30 km/h","value_nl":"25-30 km/u","asset_name":"","color_type":"one-color"},{"id":2,"name":1768778635413,"value":"30+ km/u","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"30+ km/h","value_nl":"30+ km/u","asset_name":"","color_type":"one-color"}],"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3"},{"id":"textarea-1","type":"textarea","label":"Berichtje voor Michel - MR.GranRondo (Optioneel)","prefix":"icon","pp_font":"default","helptext":"Wat is jouw motivatie in om GranRondo.cc te supporten? Laat een berichtje achter op support-pagina van GranRondo.cc.","label_en":"Message for Michel - MR.GranRondo (Optional)","label_nl":"Berichtje voor Michel - MR.GranRondo (Optioneel)","pp_color":"#000000","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"pp_height":25,"pp_opacity":100,"columnWidth":100,"helptext_en":"What is your motivation for supporting GranRondo.cc? Leave a message on the GranRondo.cc support page.","helptext_nl":"Wat is jouw motivatie in om GranRondo.cc te supporten? Laat een berichtje achter op support-pagina van GranRondo.cc.","placeholder":"Vul je motivatie in...","pp_fontSize":6,"pp_alignment":"center","pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"Motivation","advanced_addon":"default","placeholder_en":"Enter your motivation...","placeholder_nl":"Vul je motivatie in...","text_transform":"none","helptext_position":"below_label"}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15411441074550,15345225564534],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":0,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};
18199window.GPOConfigs.options[1295747] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"buttons-3","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"oos":"show","type":"buttons","label":"Datum","style":"horizontal","helptext":"Max. 40 deelnemers. Ontvangst om 8.30u bij De Proloog Amerongen","label_en":"Date","label_nl":"Datum","required":true,"columnWidth":100,"helptext_en":"Max. 40 participants. Welcome at 8:30 AM at De Proloog Amerongen","helptext_nl":"Max. 40 deelnemers. Ontvangst om 8.30u bij De Proloog Amerongen","scroll_type":"default","default_value":[""],"initial_state":"expand","label_on_cart":"Date","option_values":[{"id":1,"name":1764620482789,"value":"Zondag 1 feb 2026 - Road-Gravel","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Zondag 1 feb 2026 - Road-Gravel","asset_name":"","color_type":"one-color","variant_id":56775372046710,"variant_price":"0.00","product_handle":"de-echte-ronde-utrecht-reservering"}],"advanced_addon":"default","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-3","clo":{"match":"all","whens":[{"value":"Social","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3><strong>Meedoen aan de Social Rondo op zondag 1 februari?</strong></h3>\n<p><a href=\"https://granrondo.cc/utrecht\" target=\"_blank\" rel=\"noopener\">Bekijk het event</a></p>","type":"paragraph","hidden":true,"text_en":"<h3><strong>Joining the Social Rondo on Sunday, February 1th?</strong></h3>\n<p><a href=\"https://granrondo.cc/utrecht\" target=\"_blank\" rel=\"noopener\">Check out this event</a></p>","text_nl":"<h3><strong>Meedoen aan de Social Rondo op zondag 1 februari?</strong></h3>\n<p><a href=\"https://granrondo.cc/utrecht\" target=\"_blank\" rel=\"noopener\">Bekijk het event</a></p>","columnWidth":100,"label_on_cart":"Datum Zelf op Avontuur","conditionalField":true},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","type":"paragraph","text_en":"<h3><span style=\"font-size: 18.72px;\">Other person's details</span></h3>\n<p><span style=\"font-size: 18.72px;\">Important: Please enter only the details of the other person you are registering below.</span></p>","text_nl":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","columnWidth":100,"label_on_cart":"heading-1","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Jouw gegevens</h3>","type":"paragraph","text_en":"<h3>Your personal details</h3>","text_nl":"<h3>Jouw gegevens</h3>","columnWidth":100,"label_on_cart":"paragraph-2","conditionalField":true},{"id":"text-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Name","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"E-mail","conditionalField":true},{"id":"phone-1","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Mobiele Telefoonnummer","prefix":"icon","label_en":"Mobile phone number","label_nl":"Mobiele Telefoonnummer","required":true,"columnWidth":100,"placeholder":"+31612345678","label_on_cart":"Phone","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true},{"id":"phone-2","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Noodnummer contactpersoon","prefix":"icon","helptext":"Nummer van contactpersoon in noodgeval.","label_en":"Emergency contact number","label_nl":"Noodnummer contactpersoon","required":true,"columnWidth":100,"helptext_en":"Emergency contact phone number","helptext_nl":"Nummer van contactpersoon in noodgeval.","placeholder":"+31612345678","label_on_cart":"Contact number","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true,"helptext_position":"tooltip"},{"id":"datetime-1","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"Minors under 18 may only participate with parental/guardian consent and must be accompanied by an adult.","helptext_nl":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-6","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"text-4","conditionalField":true},{"id":"paragraph-7","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-7","conditionalField":true},{"id":"paragraph-8","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-8","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","allowed_value":"default","label_on_cart":" Recipient","advanced_addon":"default","text_transform":"none","conditionalField":true,"helptext_position":"below_label"},{"id":"select-2","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"select","label":"Ben je NTFU-lid?","prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","label_en":"Are you an NTFU member?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-2 at checkout to receive a â¬2 discount. If no code is used, we will donate â¬2 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU","option_values":[{"id":0,"value":"Nee ik ben geen NTFU-lid.","helptext":"","value_en":"No. I am not an NTFU member.","value_nl":"Nee ik ben geen NTFU-lid."},{"id":1,"value":"Ja ik ben NTFU-lid en doneer 2 euro","helptext":"","value_en":"Yes. I am an NTFU member and I will donate â¬2.","value_nl":"Ja ik ben NTFU-lid en doneer 2 euro"},{"id":2,"value":"Ja ik ben NTFU-lid en wil 2 euro korting","helptext":"","value_en":"Yes. I am an NTFU member and I would like a â¬2 discount.","value_nl":"Ja ik ben NTFU-lid en wil 2 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"text-3","clo":{"match":"any","whens":[{"value":"Ja ik ben NTFU-lid en doneer 2 euro","where":"EQUALS","select":"select-2"}
18199,{"value":"Ja ik ben NTFU-lid en wil 2 euro korting","where":"EQUALS","select":"select-2"}],"display":"show"},"type":"text","label":"NTFU lidnummer","prefix":"icon","pp_font":"default","label_en":"NTFU member ID","label_nl":"NTFU lidnummer","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_opacity":100,"columnWidth":100,"pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"NTFU ID","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true},{"id":"paragraph-4","clo":{"match":"all","whens":[{"value":"Social","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Social"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","type":"paragraph","hidden":true,"text_en":"<h3>Rondoneur benefit: <br>Access to all Rondoguides</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Check the <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondoguides</a> </p>","text_nl":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","columnWidth":100,"label_on_cart":"paragraph-4","conditionalField":true},{"id":"paragraph-5","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Deelname met korting voor Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Zorg dat je bent <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">ingelogd</a>.</p>\n<p>Je korting wordt automatisch verwerkt.</p>","type":"paragraph","hidden":true,"text_en":"<h3>Participation discount for Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Make sure you are <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">logged in</a>.<br>Your discount will be applied automatically.</p>","text_nl":"<h3>Deelname met korting voor Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Zorg dat je bent <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">ingelogd</a>.</p>\n<p>Je korting wordt automatisch verwerkt.</p>","columnWidth":100,"label_on_cart":"paragraph-5","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15103274123638,15634640142710],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":1,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1297460] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"paragraph-4","clo":{"match":"all","whens":[{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"text":"<p><span style=\"color: inherit; font-family: inherit;\">Zet je gratis en vrijblijvend op de voorinschrijflijst. Zodra de officiele inschrijving opent brengen we jou als eerste op de hoogte.</span></p>\n<article class=\"text-token-text-primary w-full focus:outline-none [--shadow-height:45px] has-data-writing-block:pointer-events-none has-data-writing-block:-mt-(--shadow-height) has-data-writing-block:pt-(--shadow-height) [&
18199:has([data-writing-block])>*]:pointer-events-auto scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]\" dir=\"auto\" tabindex=\"-1\" data-turn-id=\"request-692b6246-0450-8333-9580-c2ca55d19557-8\" data-testid=\"conversation-turn-6\" data-scroll-anchor=\"true\" data-turn=\"assistant\">\n<div class=\"text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)\">\n<div class=\"[--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn\" tabindex=\"-1\">\n<div class=\"z-0 flex min-h-[46px] justify-start\"> </div>\n</div>\n</div>\n</article>","type":"paragraph","hidden":true,"text_en":"<p>Join our pre-registration list for free and with no obligation. As soon as the official registration opens, you’ll be the first to know!</p>","text_nl":"<p><span style=\"color: inherit; font-family: inherit;\">Zet je gratis en vrijblijvend op de voorinschrijflijst. Zodra de officiele inschrijving opent brengen we jou als eerste op de hoogte.</span></p>\n<article class=\"text-token-text-primary w-full focus:outline-none [--shadow-height:45px] has-data-writing-block:pointer-events-none has-data-writing-block:-mt-(--shadow-height) has-data-writing-block:pt-(--shadow-height) [&:has([data-writing-block])>*]:pointer-events-auto scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]\" dir=\"auto\" tabindex=\"-1\" data-turn-id=\"request-692b6246-0450-8333-9580-c2ca55d19557-8\" data-testid=\"conversation-turn-6\" data-scroll-anchor=\"true\" data-turn=\"assistant\">\n<div class=\"text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)\">\n<div class=\"[--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn\" tabindex=\"-1\">\n<div class=\"z-0 flex min-h-[46px] justify-start\"> </div>\n</div>\n</div>\n</article>","columnWidth":100,"label_on_cart":"paragraph-4","conditionalField":true},{"id":"buttons-3","clo":{"match":"any","whens":[{"value":"Rondogids","where":"NOT_CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"}],"display":"show"},"oos":"show","type":"buttons","label":"Inschrijving","style":"horizontal","label_en":"Event","label_nl":"Inschrijving","required":true,"columnWidth":100,"scroll_type":"default","default_value":[""],"initial_state":"expand","label_on_cart":"Event","option_values":[{"id":0,"name":1764620350728,"value":"21 jun 2026 - Longest Day Challenge (Road)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"21 jun 2026 - Longest Day Challenge (Road)","value_nl":"21 jun 2026 - Longest Day Challenge (Road)","asset_name":"","color_type":"one-color"},{"id":1,"name":1764639206253,"value":"19-21 jun 2026 - Longest Weekend Challenge (Road)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"19-21 jun 2026 - Longest Weekend Challenge (Road)","value_nl":"19-21 jun 2026 - Longest Weekend Challenge (Road)","asset_name":"","color_type":"one-color"},{"id":2,"name":1764639207702,"value":"19-21 jun 2026 - Longest Weekend Challenge (Gravel)","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"19-21 jun 2026 - Longest Weekend Challenge (Gravel)","value_nl":"19-21 jun 2026 - Longest Weekend Challenge (Gravel)","asset_name":"","color_type":"one-color"}],"advanced_addon":"default","conditionalField":true},{"id":"paragraph-3","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_nl":"Rondogids"}],"display":"show"},"text":"<h3><strong>Meedoen aan de Longest Day(s) Challenge 19-21 juni?</strong></h3>\n<p><a href=\"https://granrondo.cc/nederland\" target=\"_blank\" rel=\"noopener\">Schrijf je hier in voor het event</a></p>","type":"paragraph","text_en":"<h3><strong>Joining the Longest Day(s) Challenge, June 19th–21st?</strong></h3>\n<p><a href=\"https://granrondo.cc/nederland\" target=\"_blank\" rel=\"noopener\">Subscribe for event this event here</a></p>","text_nl":"<h3><strong>Meedoen aan de Longest Day(s) Challenge 19-21 juni?</strong></h3>\n<p><a href=\"https://granrondo.cc/nederland\" target=\"_blank\" rel=\"noopener\">Schrijf je hier in voor het event</a></p>","columnWidth":100,"label_on_cart":"Datum Zelf op Avontuur","conditionalField":true},{"id":"buttons-6","clo":{"match":"all","whens":[{"value":"21 jun 2026 - Longest Day Challenge (Road)","where":"CONTAINS","select":"buttons-3"},{"value":"Rondogids","where":"NOT_CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"}],"display":"show"},"oos":"show","type":"buttons","label":"Startlocatie","style":"horizontal","helptext":"* Mogelijke start / finishlocaties.<br>Start op 21 juni is om 0:00 uur.","label_en":"Start location","label_nl":"Startlocatie","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"* Possible start / finish locations.<br>Start on June 21st at 12:00 AM.","helptext_nl":"* Mogelijke start / finishlocaties.<br>Start op 21 juni is om 0:00 uur.","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"exp
18199and","label_on_cart":"Start","option_values":[{"id":0,"name":1767031506983,"value":"Checkpoint Zuid = Body Dynamics / WSC de Betuwe - Tiel","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Checkpoint South = Body Dynamics / WSC de Betuwe - Tiel","value_nl":"Checkpoint Zuid = Body Dynamics / WSC de Betuwe - Tiel","asset_name":"","color_type":"one-color","variant_id":56971326521718,"variant_price":"0.00","product_handle":"gran-rondo-nl-locatie"}],"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below"},{"id":"buttons-8","clo":{"match":"all","whens":[{"value":"21 jun 2026 - Longest Day Challenge (Road)","where":"NOT_CONTAINS","select":"buttons-3"},{"value":"Rondogids","where":"NOT_CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"}],"display":"show"},"oos":"show","type":"buttons","label":"Startlocatie","style":"horizontal","hidden":true,"helptext":"* Mogelijke start / finishlocaties.<br>Start op 19 juni is om 17:00 uur.","label_en":"Start Location","label_nl":"Startlocatie","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"* Possible start / finish locations.<br>Start on June 19th is at 5:00 PM.","helptext_nl":"* Mogelijke start / finishlocaties.<br>Start op 19 juni is om 17:00 uur.","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"expand","label_on_cart":"Start location","option_values":[{"id":1,"name":1767032497084,"value":"Checkpoint West = JOOP - Schoorl","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Checkpoint West = JOOP - Schoorl","asset_name":"","color_type":"one-color","variant_id":56971326554486,"variant_price":"0.00","product_handle":"gran-rondo-nl-locatie"}],"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below"},{"id":"buttons-9","clo":{"match":"all","whens":[{"value":"21 jun 2026 - Longest Day Challenge (Road)","where":"NOT_CONTAINS","select":"buttons-3"},{"value":"Rondogids","where":"NOT_CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"}],"display":"show"},"oos":"show","type":"buttons","label":"Startlocatie","style":"horizontal","helptext":"* Mogelijke start / finishlocaties.<br>Start op 19 juni is om 17:00 uur.","label_en":"Start Location","label_nl":"Startlocatie","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"* Possible start / finish locations.<br>Start on June 19th is at 5:00 PM.","helptext_nl":"* Mogelijke start / finishlocaties.<br>Start op 19 juni is om 17:00 uur.","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"expand","label_on_cart":"buttons-9","option_values":[{"id":0,"name":1767031506983,"value":"Checkpoint Zuid = Body Dynamics / WSC de Betuwe - Tiel","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Checkpoint South = Body Dynamics / WSC de Betuwe - Tiel","value_nl":"Checkpoint Zuid = Body Dynamics / WSC de Betuwe - Tiel","asset_name":"","color_type":"one-color","variant_id":56971326521718,"variant_price":"0.00","product_handle":"gran-rondo-nl-locatie"},{"id":1,"name":1767032497084,"value":"Checkpoint West = JOOP - Schoorl","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Checkpoint West = JOOP - Schoorl","asset_name":"","color_type":"one-color","variant_id":56971326554486,"variant_price":"0.00","product_handle":"gran-rondo-nl-locatie"}],"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below"},{"id":"text-3","clo":{"match":"all","whens":[{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"type":"text","label":"Groepsnaam","prefix":"icon","pp_font":"default","helptext":"Fiets je samen als groep met anderen die zich hebben ingeschreven? Vul hier dan allemaal dezelfde groepsnaam in.","label_en":"Group name","label_nl":"Groepsnaam","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"pp_opacity":100,"columnWidth":100,"helptext_en":"Are you cycling together as a group with others who have registered? Then please all enter the same group name here.","helptext_nl":"Fiets je samen als groep met anderen die zich hebben ingeschreven? Vul hier dan allemaal dezelfde groepsnaam in.","pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"Group","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true,"helptext_position":"below_label"},{"id":"buttons-7","clo":{"match":"all","whens":[{"value":"Rondogids","where":"NOT_CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"}],"display":"show"},"oos":"show","type":"buttons","label":"Livetracker","style":"horizontal","hidden":true,"helptext":"Zodat je fans je kunnen volgen.","label_nl":"Livetracker","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"So your fans can follow you.","helptext_nl":"Zodat je fans je kunnen volgen.","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"exp
18199and","label_on_cart":"Livetracker","option_values":[{"id":0,"name":1769729420438,"value":"Livetracker â 25 euro","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Livetracker â 25 euro","asset_name":"","color_type":"one-color","variant_id":57174303965558,"variant_price":"0.00","product_handle":"livetracker"}],"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below_label"},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"Challenge","where":"CONTAINS","select":"shopify_variant"}],"display":"show"},"text":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","type":"paragraph","text_en":"<h3><strong>Other person's details</strong></h3>\n<p><span style=\"color: inherit; font-family: inherit;\">Important: Please enter only the details of the other person you are registering below.</span></p>\n<h3> </h3>","text_nl":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","columnWidth":100,"label_on_cart":"heading-1","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself"},{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"text":"<h3>Jouw gegevens</h3>","type":"paragraph","text_en":"<h3>Your personal details</h3>","text_nl":"<h3>Jouw gegevens</h3>","columnWidth":100,"label_on_cart":"paragraph-2","conditionalField":true},{"id":"text-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Name","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"E-mail","conditionalField":true},{"id":"phone-1","clo":{"match":"all","whens":[{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"type":"phone","label":"Mobiele Telefoonnummer","prefix":"icon","label_en":"Mobile phone number","label_nl":"Mobiele Telefoonnummer","required":true,"columnWidth":100,"placeholder":"+31612345678","label_on_cart":"Phone","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true},{"id":"phone-2","clo":{"match":"any","whens":[{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"type":"phone","label":"Noodnummer contactpersoon","prefix":"icon","helptext":"Nummer van contactpersoon in noodgeval.","label_en":"Emergency contact number","label_nl":"Noodnummer contactpersoon","required":true,"columnWidth":100,"helptext_en":"Emergency contact phone number","helptext_nl":"Nummer van contactpersoon in noodgeval.","placeholder":"+31612345678","label_on_cart":"Contact number","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true,"helptext_position":"tooltip"},{"id":"datetime-1","clo":{"match":"any","whens":[{"value":"Challenge","where":"CONTAINS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"Minors under 18 may only participate with parental/guardian consent and must be accompanied by an adult.","helptext_nl":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-6","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"text-5","conditionalField":true},{"id":"paragraph-7","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-7","conditionalField":true},{"id":"paragraph-8","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-8","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","allowed_value":"default","label_on_cart":"Recipient","advanced_addon":"default","text_transform":"none","conditionalField":true,"helptext_position":"below_label"},{"id":"select-2","clo":{"match":"all","whens":[{"value":"Challenge","where":"EQUALS","select":"shopify_variant","value_nl":"Challenge"}],"display":"show"},"type":"select","label":"Ben je NTFU-lid?","hidden":true,"prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-3 bij afrekenen en ontvang â¬3 korting. Geen code gebruikt? Dan doneren wij â¬3 aan KiKa namens jou.","label_en":"Are you an NTFU member?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-3 at checkout to receive a â¬3 discount. If no code is used, we will donate â¬3 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-3 bij afrekenen en ontvang â¬3 korting. Geen code gebruikt? Dan doneren wij â¬3 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU","option_values":[{"id":0,"value":"Nee ik ben geen NTFU-lid.","helptext":"","value_en":"No. I am not an NTFU member.","value_nl":"Nee ik ben geen NTFU-lid."},{"id":1,"value":"Ja ik ben NTFU-lid en doneer 3 euro","helptext":"","value_en":"Yes. I am an NTFU member and I will donate â¬3.","value_nl":"Ja ik ben NTFU-lid en doneer 3 euro"},{"id":2,"value":"Ja ik ben NTFU-lid en wil 3 euro korting","helptext":"","value_en":"Yes. I am an NTFU member and I would like a â¬2 discount.","value_nl":"Ja ik ben NTFU-lid en wil 3 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"text-4","clo":{"match":"any","whens":[{"value":"Ja ik ben NTFU-lid en doneer 3 euro","where":"EQUALS","select":"select-2"}
18199,{"value":"Ja ik ben NTFU-lid en wil 3 euro korting","where":"EQUALS","select":"select-2"}],"display":"show"},"type":"text","label":"NTFU lidnummer","hidden":true,"prefix":"icon","pp_font":"default","label_en":"NTFU member ID","label_nl":"NTFU lidnummer","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_opacity":100,"columnWidth":100,"pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"NTFU ID","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true},{"id":"paragraph-5","clo":{"match":"all","whens":[{"value":"Challenge","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Challenge"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","type":"paragraph","hidden":true,"text_en":"<h3>Rondoneur benefit: <br>Access to all Rondoguides</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Check the <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondoguides</a> </p>","text_nl":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","columnWidth":100,"label_on_cart":"paragraph-5","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15103264981366,15634574246262],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":1,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1297583] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"buttons-3","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"oos":"show","type":"buttons","label":"Datum","style":"horizontal","helptext":"Ontvangst om 9.15u bij Lowlander Amsterdam ","label_en":"Date","label_nl":"Datum","required":true,"columnWidth":100,"helptext_en":"Welcome at 9:15 AM at Lowlander Amsterdam","helptext_nl":"Ontvangst om 9.15u bij Lowlander Amsterdam ","scroll_type":"default","default_value":[""],"initial_state":"expand","label_on_cart":"Date","option_values":[{"id":0,"name":1764620350728,"value":"Zondag 22 mrt 2026 - Road","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Sunday 22 mar 2026 - Road","value_nl":"Zondag 22 mrt 2026 - Road","asset_name":"","color_type":"one-color","variant_id":56758187229558,"variant_price":"0.00","product_handle":"de-echte-ronde-amsterdam-reservering"},{"id":1,"name":1764658524127,"value":"Zondag 22 mrt 2026 - Road-Gravel","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Sunday 22 mar 2026 - Road-Gravel","value_nl":"Zondag 22 mrt 2026 - Road-Gravel","asset_name":"","color_type":"one-color","variant_id":56758187229558,"variant_price":"0.00","product_handle":"de-echte-ronde-amsterdam-reservering"}],"advanced_addon":"default","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-3","clo":{"match":"all","whens":[{"value":"Social","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3><strong>Meedoen aan de Social Rondo op zondag 22 maart?</strong></h3>\n<p><a href=\"https://granrondo.cc/amsterdam\" target=\"_blank\" rel=\"noopener\">Bekijk het event</a></p>","type":"paragraph","hidden":true,"text_en":"<h3><strong>Joining the Social Rondo on Sunday, March 22nd?</strong></h3>\n<p><a href=\"https://granrondo.cc/amsterdam\" target=\"_blank\" rel=\"noopener\">Check out this event</a></p>","text_nl":"<h3><strong>Meedoen aan de Social Rondo op zondag 22 maart?</strong></h3>\n<p><a href=\"https://granrondo.cc/amsterdam\" target=\"_blank\" rel=\"noopener\">Bekijk het event</a></p>","columnWidth":100,"label_on_cart":"Datum Zelf op Avontuur","conditionalField":true},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","type":"paragraph","text_en":"<h3><span style=\"font-size: 18.72px;\">Other person's details</span></h3>\n<p><span style=\"font-size: 18.72px;\">Important: Please enter only the details of the other person you are registering below.</span></p>","text_nl":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","columnWidth":100,"label_on_cart":"heading-1","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Jouw gegevens</h3>","type":"paragraph","text_en":"<h3>Your personal details</h3>","text_nl":"<h3>Jouw gegevens</h3>","columnWidth":100,"label_on_cart":"paragraph-2","conditionalField":true},{"id":"text-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Name","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"E-mail","conditionalField":true},{"id":"phone-1","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Mobiele Telefoonnummer","prefix":"icon","label_en":"Mobile phone number","label_nl":"Mobiele Telefoonnummer","required":true,"columnWidth":100,"placeholder":"+31612345678","label_on_cart":"Phone","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true},{"id":"phone-2","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Noodnummer contactpersoon","prefix":"icon","helptext":"Nummer van contactpersoon in noodgeval.","label_en":"Emergency contact number","label_nl":"Noodnummer contactpersoon","required":true,"columnWidth":100,"helptext_en":"Emergency contact phone number","helptext_nl":"Nummer van contactpersoon in noodgeval.","placeholder":"+31612345678","label_on_cart":"Contact number","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true,"helptext_position":"tooltip"},{"id":"datetime-1","clo":{"match":"any","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"Minors under 18 may only participate with parental/guardian consent and must be accompanied by an adult.","helptext_nl":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-6","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Iemand anders"},{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Rondogids"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"text-5","conditionalField":true},{"id":"paragraph-8","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Jezelf"},{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Rondogids"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-8","conditionalField":true},{"id":"paragraph-9","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Iemand anders"},{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Rondogids"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-9","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Iemand anders"},{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Rondogids"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","allowed_value":"default","label_on_cart":"Recipient","advanced_addon":"default","text_transform":"none","conditionalField":true,"helptext_position":"below_label"},{"id":"buttons-4","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"oos":"show","type":"buttons","label":"Maak je Rondopakket compleet met de <br><a href=\"https://granrondo.cc/products/de-echte-ronde-van-amsterdam-tacx-bidon-750ml\" target=\"_blank\">Tacx Amsterdam Bidon - Check hier</a>","style":"horizontal","label_en":"Complete your Rondo Package with the <br><a href=\"https://granrondo.cc/products/de-echte-ronde-van-amsterdam-tacx-bidon-750ml\" target=\"_blank\">Tacx Amsterdam Bottle - Check here</a>","label_nl":"Maak je Rondopakket compleet met de <br><a href=\"https://granrondo.cc/products/de-echte-ronde-van-amsterdam-tacx-bidon-750ml\" target=\"_blank\">Tacx Amsterdam Bidon - Check hier</a>","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","slider_style":"style1","swatch_style":"default","initial_state":"exp
18199and","label_on_cart":"Extra","option_values":[{"id":0,"name":1768769163607,"value":"Tacx Amsterdam Bidon 750ml â 10 euro","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Tacx Amsterdam Bottle 750ml â 10 euro","value_nl":"Tacx Amsterdam Bidon 750ml â 10 euro","asset_name":"","color_type":"one-color","variant_id":57096060174710,"variant_price":"10.00","product_handle":"de-echte-ronde-van-amsterdam-tacx-bidon-750ml"},{"id":1,"name":1773932762769,"value":"Geen Bidon","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"No Bottle","value_nl":"Geen Bidon","asset_name":"","color_type":"one-color"}],"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3"},{"id":"select-2","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"select","label":"Ben je NTFU-lid?","prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","label_en":"Are you an NTFU member?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-2 at checkout to receive a â¬2 discount. If no code is used, we will donate â¬2 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU","option_values":[{"id":0,"value":"Nee ik ben geen NTFU-lid.","helptext":"","value_en":"No. I am not an NTFU member.","value_nl":"Nee ik ben geen NTFU-lid."},{"id":1,"value":"Ja ik ben NTFU-lid en doneer 2 euro","helptext":"","value_en":"Yes. I am an NTFU member and I will donate â¬2.","value_nl":"Ja ik ben NTFU-lid en doneer 2 euro"},{"id":2,"value":"Ja ik ben NTFU-lid en wil 2 euro korting","helptext":"","value_en":"Yes. I am an NTFU member and I would like a â¬2 discount.","value_nl":"Ja ik ben NTFU-lid en wil 2 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"text-3","clo":{"match":"any","whens":[{"value":"Ja ik ben NTFU-lid en doneer 2 euro","where":"EQUALS","select":"select-2"},{"value":"Ja ik ben NTFU-lid en wil 2 euro korting","where":"EQUALS","select":"select-2"}],"display":"show"},"type":"text","label":"NTFU lidnummer","prefix":"icon","pp_font":"default","label_en":"NTFU member ID","label_nl":"NTFU lidnummer","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_opacity":100,"columnWidth":100,"pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"NTFU ID","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true},{"id":"paragraph-4","clo":{"match":"all","whens":[{"value":"Social","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Social"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","type":"paragraph","hidden":true,"text_en":"<h3>Rondoneur benefit: <br>Access to all Rondoguides</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Check the <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondoguides</a> </p>","text_nl":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","columnWidth":100,"label_on_cart":"paragraph-4","conditionalField":true},{"id":"paragraph-5","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Deelname met korting voor Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Zorg dat je bent <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">ingelogd</a>.</p>\n<p>Je korting wordt automatisch verwerkt.</p>","type":"paragraph","hidden":true,"text_en":"<h3>Participation discount for Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Make sure you are <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">logged in</a>.<br>Your discount will be applied automatically.</p>","text_nl":"<h3>Deelname met korting voor Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Zorg dat je bent <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">ingelogd</a>.</p>\n<p>Je korting wordt automatisch verwerkt.</p>","columnWidth":100,"label_on_cart":"paragraph-5","conditionalField":true},{"id":"paragraph-7","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Iemand anders"},{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Rondogids"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-7","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15634629394806,15091411386742],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":1,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1305864] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"buttons-3","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"oos":"show","type":"buttons","label":"Datum","style":"horizontal","helptext":"Max. 75 deelnemer
18199s. Ontvangst om 8.30u bij JOOP Schoorl","label_en":"Date","label_nl":"Datum","required":true,"columnWidth":100,"helptext_en":"Max. 75 participants. Welcome at 8:30 AM at JOOP Schoorl","helptext_nl":"Max. 75 deelnemers. Ontvangst om 8.30u bij JOOP Schoorl","scroll_type":"default","default_value":[""],"initial_state":"expand","label_on_cart":"Date","option_values":[{"id":0,"name":1765726028274,"value":"Zondag 12 apr 2026 - Road","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Sunday 12 apr 2026 - Road","value_nl":"Zondag 12 apr 2026 - Road","asset_name":"","color_type":"one-color","variant_id":56775383220598,"variant_price":"0.00","product_handle":"gran-rondo-noord-holland-reservering"}],"advanced_addon":"default","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-3","clo":{"match":"all","whens":[{"value":"Social","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3><strong>Meedoen aan de Social Rondo op zondag 12 april?</strong></h3>\n<p><a href=\"https://granrondo.cc/noord-holland\" target=\"_blank\" rel=\"noopener\">Bekijk het event</a></p>","type":"paragraph","hidden":true,"text_en":"<h3><strong>Joining the Social Rondo on Sunday, April 12th?</strong></h3>\n<p><a href=\"https://granrondo.cc/noord-holland\" target=\"_blank\" rel=\"noopener\">Check out this event</a></p>","text_nl":"<h3><strong>Meedoen aan de Social Rondo op zondag 12 april?</strong></h3>\n<p><a href=\"https://granrondo.cc/noord-holland\" target=\"_blank\" rel=\"noopener\">Bekijk het event</a></p>","columnWidth":100,"label_on_cart":"Datum Zelf op Avontuur","conditionalField":true},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","type":"paragraph","text_en":"<h3><span style=\"font-size: 18.72px;\">Other person's details</span></h3>\n<p><span style=\"font-size: 18.72px;\">Important: Please enter only the details of the other person you are registering below.</span></p>","text_nl":"<h3>Gegevens ander persoon</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","columnWidth":100,"label_on_cart":"heading-1","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Jouw gegevens</h3>","type":"paragraph","text_en":"<h3>Your personal details</h3>","text_nl":"<h3>Jouw gegevens</h3>","columnWidth":100,"label_on_cart":"paragraph-2","conditionalField":true},{"id":"text-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Name","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"E-mail","conditionalField":true},{"id":"phone-1","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Mobiele Telefoonnummer","prefix":"icon","label_en":"Mobile phone number","label_nl":"Mobiele Telefoonnummer","required":true,"columnWidth":100,"placeholder":"+31612345678","label_on_cart":"Phone","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true},{"id":"phone-2","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"phone","label":"Noodnummer contactpersoon","prefix":"icon","helptext":"Nummer van contactpersoon in noodgeval.","label_en":"Emergency contact number","label_nl":"Noodnummer contactpersoon","required":true,"columnWidth":100,"helptext_en":"Emergency contact phone number","helptext_nl":"Nummer van contactpersoon in noodgeval.","placeholder":"+31612345678","label_on_cart":"Contact number","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true,"helptext_position":"tooltip"},{"id":"datetime-1","clo":{"match":"any","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"Minors under 18 may only participate with parental/guardian consent and must be accompanied by an adult.","helptext_nl":"Jongeren onder 18 jaar mogen alleen deelnemen met toestemming van een ouder/voogd en onder begeleiding van een volwassene.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-6","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"text-4","conditionalField":true},{"id":"paragraph-7","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-7","conditionalField":true},{"id":"paragraph-8","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-8","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","allowed_value":"default","label_on_cart":"Recipient","advanced_addon":"default","text_transform":"none","conditionalField":true,"helptext_position":"below_label"},{"id":"select-2","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"type":"select","label":"Ben je NTFU-lid?","prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","label_en":"Are you an NTFU member?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-2 at checkout to receive a â¬2 discount. If no code is used, we will donate â¬2 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-2 bij afrekenen en ontvang â¬2 korting. Geen code gebruikt? Dan doneren wij â¬2 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU","option_values":[{"id":0,"value":"Nee ik ben geen NTFU-lid.","helptext":"","value_en":"No. I am not an NTFU member.","value_nl":"Nee ik ben geen NTFU-lid."},{"id":1,"value":"Ja ik ben NTFU-lid en doneer 2 euro","helptext":"","value_en":"Yes. I am an NTFU member and I will donate â¬2.","value_nl":"Ja ik ben NTFU-lid en doneer 2 euro"},{"id":2,"value":"Ja ik ben NTFU-lid en wil 2 euro korting","helptext":"","value_en":"Yes. I am an NTFU member and I would like a â¬2 discount.","value_nl":"Ja ik ben NTFU-lid en wil 2 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"text-3","clo":{"match":"any","whens":[{"value":"Ja ik ben NTFU-lid en doneer 2 euro","where":"EQUALS","select":"select-2"}
18199,{"value":"Ja ik ben NTFU-lid en wil 2 euro korting","where":"EQUALS","select":"select-2"}],"display":"show"},"type":"text","label":"NTFU lidnummer","prefix":"icon","pp_font":"default","label_en":"NTFU member ID","label_nl":"NTFU lidnummer","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_opacity":100,"columnWidth":100,"pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"NTFU ID","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true},{"id":"paragraph-4","clo":{"match":"all","whens":[{"value":"Social","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Social"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","type":"paragraph","hidden":true,"text_en":"<h3>Rondoneur benefit: <br>Access to all Rondoguides</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Check the <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondoguides</a> </p>","text_nl":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","columnWidth":100,"label_on_cart":"paragraph-4","conditionalField":true},{"id":"paragraph-5","clo":{"match":"all","whens":[{"value":"Social","where":"CONTAINS","select":"shopify_variant","value_nl":"Social"}],"display":"show"},"text":"<h3>Deelname met korting voor Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Zorg dat je bent <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">ingelogd</a>.</p>\n<p>Je korting wordt automatisch verwerkt.</p>","type":"paragraph","hidden":true,"text_en":"<h3>Participation discount for Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Make sure you are <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">logged in</a>.<br>Your discount will be applied automatically.</p>","text_nl":"<h3>Deelname met korting voor Rondoneurs</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Zorg dat je bent <a href=\"https://account.granrondo.cc/\" target=\"_blank\" rel=\"noopener\">ingelogd</a>.</p>\n<p>Je korting wordt automatisch verwerkt.</p>","columnWidth":100,"label_on_cart":"paragraph-5","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15634631328118,15103253250422],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":1,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1537259] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Section","style":"default","elements":[{"id":"select-1","type":"select","label":"Aankoop locatie","prefix":"icon","label_en":"Bought at...","label_nl":"Aankoop locatie","required":true,"columnWidth":100,"placeholder":"-- Please select --","label_on_cart":"Store Location","option_values":[{"id":0,"name":1
18199781561645027,"value":"Café Coureur Houffalize","color1":"#ffffff","color2":"#000000","helptext":"","value_nl":"Café Coureur Houffalize","addon_type":"manual_product","asset_name":"","color_type":"one-color"},{"id":1,"value":"Café Coureur Borgloon","helptext":"","value_nl":"Café Coureur Borgloon","addon_type":"manual_product"}],"advanced_addon":"default"}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15492746477942],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":0,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.options[1561268] = {"elements":[{"id":"group-1","clo":{"match":"all","whens":[{"value":"","where":"EQUALS","select":"null"}],"display":"show"},"icon":"","type":"group","label":"Group","style":"default","elements":[{"id":"paragraph-3","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_nl":"Rondogids"}],"display":"show"},"text":"<h3><strong>Meedoen aan Gravel Rondo Wallonie 400 Event in september 2027?</strong></h3>\n<p><a href=\"https://granrondo.cc/wallonie\" target=\"_blank\" rel=\"noopener\">Schrijf je hier in voor het event</a></p>","type":"paragraph","text_en":"<h3><strong>Joining the Gravel Rondo Wallonie 400 event, Sept 2027?</strong></h3>\n<p><a href=\"https://granrondo.cc/wallonie\" target=\"_blank\" rel=\"noopener\">Subscribe for event this event here</a></p>","text_nl":"<h3><strong>Meedoen aan Gravel Rondo Wallonie 400 Event in september 2027?</strong></h3>\n<p><a href=\"https://granrondo.cc/wallonie\" target=\"_blank\" rel=\"noopener\">Schrijf je hier in voor het event</a></p>","columnWidth":100,"label_on_cart":"Datum Zelf op Avontuur","conditionalField":true},{"id":"paragraph-1","clo":{"match":"all","whens":[{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Iemand anders"},{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_en":"Ticket","value_nl":"Ticket"}],"display":"show"},"text":"<h3>Wie wil je inschrijven?</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","type":"paragraph","text_en":"<h3><strong>Who do you want to register?</strong></h3>\n<p><span style=\"color: inherit; font-family: inherit;\">Important: Please enter only the details of the other person you are registering below.</span></p>\n<h3> </h3>","text_nl":"<h3>Wie wil je inschrijven?</h3>\n<p>Belangrijk: Vul hieronder uitsluitend de gegevens in van de andere persoon die je inschrijft.</p>","columnWidth":100,"label_on_cart":"heading-1","conditionalField":true},{"id":"paragraph-2","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_en":"Ticket","value_nl":"Ticket"}],"display":"show"},"text":"<h3>Gegevens Deelnemer</h3>","type":"paragraph","text_en":"<h3>Details Participant </h3>","text_nl":"<h3>Gegevens Deelnemer</h3>","columnWidth":100,"label_on_cart":"paragraph-2","conditionalField":true},{"id":"text-1","clo":{"match":"any","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Name","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-1","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"E-mail","conditionalField":true},{"id":"phone-1","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"phone","label":"Mobiele Telefoonnummer","prefix":"icon","label_en":"Mobile phone number","label_nl":"Mobiele Telefoonnummer","required":true,"columnWidth":100,"placeholder":"+31612345678","label_on_cart":"Phone","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true},{"id":"phone-2","clo":{"match":"any","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"phone","label":"Noodnummer contactpersoon","prefix":"icon","helptext":"Nummer van contactpersoon in noodgeval.","label_en":"Emergency contact number","label_nl":"Noodnummer contactpersoon","required":true,"columnWidth":100,"helptext_en":"Emergency contact phone number","helptext_nl":"Nummer van contactpersoon in noodgeval.","placeholder":"+31612345678","label_on_cart":"Contact number","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true,"helptext_position":"tooltip"},{"id":"datetime-1","clo":{"match":"any","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"De minimale leeftijd om te mogen deelnemen is 18 jaar.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"The minimum age to participate is 18 years.","helptext_nl":"De minimale leeftijd om te mogen deelnemen is 18 jaar.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate","placeholder_en":"-- Select birth date -- ","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"select-2","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"select","label":"NTFU-lid?","prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-3 bij afrekenen en ontvang â¬3 korting. Geen code gebruikt? Dan doneren wij â¬3 aan KiKa namens jou.","label_en":"NTFU member?","label_nl":"NTFU-lid?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-3 at checkout to receive a â¬3 discount. If no code is used, we will donate â¬3 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-3 bij afrekenen en ontvang â¬3 korting. Geen code gebruikt? Dan doneren wij â¬3 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU","option_values":[{"id":0,"value":"Nee geen NTFU-lid.","helptext":"","value_en":"No. not an NTFU member.","value_nl":"Nee geen NTFU-lid."},{"id":1,"value":"Ja NTFU-lid en doneert 3 euro","helptext":"","value_en":"Yes. NTFU member and will donate â¬3.","value_nl":"Ja NTFU-lid en doneert 3 euro"},{"id":2,"value":"Ja NTFU-lid en wil 3 euro korting","helptext":"","value_en":"Yes. NTFU member and would like a â¬3 discount.","value_nl":"Ja NTFU-lid en wil 3 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-8","clo":{"match":"all","whens":[{"value":"Duo","where":"CONTAINS","select":"shopify_variant","value_en":"Duo","value_nl":"Duo"},{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_en":"Ticket","value_nl":"Ticket"}],"display":"show"},"text":"<h3>Gegevens Deelnemer 2</h3>","type":"paragraph","text_en":"<h3 style=\"color: #000000; font-family: Times;\">
18199Details Participant 2</h3>","text_nl":"<h3>Gegevens Deelnemer 2</h3>","columnWidth":100,"label_on_cart":"paragraph-8","conditionalField":true},{"id":"text-5","clo":{"match":"all","whens":[{"value":"Duo","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else","value_nl":"Duo"},{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"text","label":"Naam","prefix":"icon","label_en":"Name","label_nl":"Naam","required":true,"columnWidth":100,"placeholder":"Voor- en achternaam","allowed_value":"default","label_on_cart":"Naam Duopartner","advanced_addon":"default","placeholder_en":"Full name","placeholder_nl":"Voor- en achternaam","text_transform":"none","conditionalField":true},{"id":"email-2","clo":{"match":"all","whens":[{"value":"Duo","where":"CONTAINS","select":"shopify_variant","value_en":"Duo","value_nl":"Duo"},{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"email","label":"E-mailadres","prefix":"icon","label_en":"E-mail address","label_nl":"E-mailadres","required":true,"columnWidth":100,"label_on_cart":"Email Duopartner","conditionalField":true},{"id":"phone-3","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"},{"value":"Duo","where":"CONTAINS","select":"shopify_variant"}],"display":"show"},"type":"phone","label":"Mobiele Telefoonnummer","prefix":"icon","label_en":"Mobile phone number","label_nl":"Mobiele Telefoonnummer","required":true,"columnWidth":100,"placeholder":"+31612345678","label_on_cart":"Phone Duopartner","placeholder_nl":"+31612345678","default_country":"us","conditionalField":true},{"id":"datetime-3","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"},{"value":"Duo","where":"CONTAINS","select":"shopify_variant","value_nl":"Duo"}],"display":"show"},"mode":"single","type":"datetime","label":"Geboortedatum","format":"date","prefix":"icon","helptext":"De minimale leeftijd om te mogen deelnemen is 18 jaar.","label_en":"Birthdate","label_nl":"Geboortedatum","required":true,"timezone":"7","columnWidth":100,"date-format":"d-m-Y","helptext_en":"The minimum age to participate is 18 years.","helptext_nl":"De minimale leeftijd om te mogen deelnemen is 18 jaar.","placeholder":"-- Selecteer geboortedatum -- ","label_on_cart":"Birthdate Duopartner","placeholder_en":"-- Select birth date -- ","placeholder_nl":"-- Selecteer geboortedatum -- ","conditionalField":true,"helptext_position":"below"},{"id":"select-5","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"},{"value":"Duo","where":"CONTAINS","select":"shopify_variant","value_nl":"Duo"}],"display":"show"},"type":"select","label":"NTFU-lid?","prefix":"icon","helptext":"NTFU-lid? Gebruik code NTFU-3 bij afrekenen en ontvang â¬3 korting. Geen code gebruikt? Dan doneren wij â¬3 aan KiKa namens jou.","label_en":"NTFU member?","label_nl":"NTFU-lid?","columnWidth":100,"helptext_en":"NTFU member? Use code NTFU-3 at checkout to receive a â¬3 discount. If no code is used, we will donate â¬3 to KiKa on your behalf.","helptext_nl":"NTFU-lid? Gebruik code NTFU-3 bij afrekenen en ontvang â¬3 korting. Geen code gebruikt? Dan doneren wij â¬3 aan KiKa namens jou.","placeholder":"-- Selecteer --","label_on_cart":"NTFU-2","option_values":[{"id":0,"value":"Nee geen NTFU-lid.","helptext":"","value_en":"No. not an NTFU member.","value_nl":"Nee geen NTFU-lid."},{"id":1,"value":"Ja NTFU-lid en doneert 3 euro","helptext":"","value_en":"Yes. NTFU member and will donate â¬3.","value_nl":"Ja NTFU-lid en doneert 3 euro"},{"id":2,"value":"Ja NTFU-lid en wil 3 euro korting","helptext":"","value_en":"Yes. NTFU member and would like a â¬3 discount.","value_nl":"Ja NTFU-lid en wil 3 euro korting"}],"advanced_addon":"default","placeholder_nl":"-- Selecteer --","conditionalField":true,"helptext_position":"below"},{"id":"paragraph-6","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>You will receive a voucher by email that you can give to the recipient. The voucher contains a unique start code link for access to the Rondogids with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Je ontvangt per email een voucher die aan de ontvanger kunt geven. Op de voucher staat een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"text-5","conditionalField":true},{"id":"paragraph-9","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>The Rondobox contains a unique start code link for the recipient to access the Rondo Guide with GPX.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Voor de ontvanger zit er in de Rondobox een unieke startcode-link voor toegang tot de Rondogids met GPX.</p>","columnWidth":100,"label_on_cart":"paragraph-9","conditionalField":true},{"id":"paragraph-10","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"},{"value":"ð","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"text":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","type":"paragraph","text_en":"<p><strong>How does this work?</strong></p>\n<p>If you order this Rondo for yourself, you will automatically get access to the Rondo guide using the email address in your account.</p>","text_nl":"<p><strong>Hoe werkt dit?</strong></p>\n<p>Als je deze Rondo voor jezelf bestelt, krijg je met je emailadres in je account automatisch toegang tot de Rondogids.</p>","columnWidth":100,"label_on_cart":"paragraph-10","conditionalField":true},{"id":"text-2","clo":{"match":"all","whens":[{"value":"Rondogids","where":"CONTAINS","select":"shopify_variant","value_en":"Rondoguide","value_nl":"Rondogids"},{"value":"Iemand anders","where":"CONTAINS","select":"shopify_variant","value_en":"Someone else"},{"value":"ð","where":"CONTAINS","select":"shopify_variant","value_nl":"ð"}],"display":"show"},"type":"text","label":"Verpakking gratis personaliseren?","prefix":"icon","helptext":"Naam aan wie je het geeft:","label_en":"Personalize your packaging for free?","label_nl":"Verpakking gratis personaliseren?","columnWidth":100,"helptext_en":"Recipient name(s)","helptext_nl":"Naam aan wie je het geeft:","allowed_value":"default","label_on_cart":"Recipient","advanced_addon":"default","text_transform":"none","conditionalField":true,"helptext_position":"below_label"},{"id":"text-4","clo":{"match":"any","whens":[{"value":"Ja ik ben NTFU-lid en doneer 3 euro","where":"EQUALS","select":"select-2"}
18199,{"value":"Ja ik ben NTFU-lid en wil 3 euro korting","where":"EQUALS","select":"select-2"}],"display":"show"},"type":"text","label":"NTFU lidnummer","hidden":true,"prefix":"icon","pp_font":"default","label_en":"NTFU member ID","label_nl":"NTFU lidnummer","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_opacity":100,"columnWidth":100,"pp_fontSize":6,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"NTFU ID","advanced_addon":"default","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true},{"id":"paragraph-5","clo":{"match":"all","whens":[{"value":"Challenge","where":"NOT_CONTAINS","select":"shopify_variant","value_nl":"Challenge"},{"value":"Jezelf","where":"CONTAINS","select":"shopify_variant","value_en":"Yourself","value_nl":"Jezelf"}],"display":"show"},"text":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","type":"paragraph","hidden":true,"text_en":"<h3>Rondoneur benefit: <br>Access to all Rondoguides</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Become a Rondoneur now</a></p>\n<p> </p>\n<p>Already a Rondoneur? Check the <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondoguides</a> </p>","text_nl":"<h3>Rondoneur-voordeel: <br>Toegang tot alle Rondogidsen</h3>\n<p><a href=\"https://granrondo.cc/support\" target=\"_blank\" rel=\"noopener\">Word nu lid als Rondoneur</a></p>\n<p> </p>\n<p>Ben je al Rondoneur? Kijk bij <a href=\"https://club.granrondo.cc/collections/rondoguides\" target=\"_blank\" rel=\"noopener\">Rondogidsen</a> </p>","columnWidth":100,"label_on_cart":"paragraph-5","conditionalField":true},{"id":"select-6","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"select","label":"Cafe Coureur Weekend Arrangement","prefix":"icon","label_en":"Cafe Coureur Weekend Arrangement","label_nl":"Cafe Coureur Weekend Arrangement","columnWidth":100,"placeholder":"-- Kies een optie --","default_value":["Samen met andere deelnemer(s) â standaard inbegrepen"],"label_on_cart":"Cafe Coureur Weekend Arrangement","option_values":[{"id":2,"max":"","min":"","name":"","unit":"","label":"","value":"3-Daags Rondo Weekend (2 nachten vr-zo) â 205 euro p.p.","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"3-Day Rondo Weekend (2 nights Fri-Sun) â 205 euros p.p.","value_nl":"3-Daags Rondo Weekend (2 nachten vr-zo) â 205 euro p.p.","addon_type":"manual_product","asset_name":"","color_type":"one-color","variant_id":58608497951094,"placeholder":"","variant_price":"205.00","product_handle":"cafe-coureur-weekend-arrangement"},{"id":3,"value":"4-Daags Rondo Weekend (3 nachten vr-ma) â 295 euro p.p.","helptext":"","value_en":"4-Day Rondo Weekend (3 nights Fri-Mon) â 295 euros p.p.","value_nl":"4-Daags Rondo Weekend (3 nachten vr-ma) â 295 euro p.p.","addon_type":"manual_product","variant_id":58608497983862,"variant_price":"295.00","product_handle":"cafe-coureur-weekend-arrangement"}],"advanced_addon":"default","placeholder_en":"-- Please select --","placeholder_nl":"-- Kies een optie --","conditionalField":true},{"id":"select-3","clo":{"match":"all","whens":[{"value":"1p","where":"CONTAINS","select":"shopify_variant","value_nl":"1p"},{"value":"3-","where":"CONTAINS","select":"shopify_variant","value_nl":"3-"},{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"select","label":"Kamer opties","prefix":"icon","helptext":"Standaard deel je een kamer met andere deelnemers (comfortabele eenpersoonsbedden). Bij inchecken kan je aangeven om bij bekenden/vrienden op de kamer te willen. Wil je meer privacy of een (niet-fietsende) supp
18199orter meenemen? Kies een upgrade hieronder.","label_en":"Room options","columnWidth":100,"helptext_en":"By default, you share a room with other participants (comfortable single beds). Upon check-in, you can indicate that you would like to share a room with acquaintances or friends. Do you want more privacy or to bring a (non-cycling) supporter? Choose an upgrade below.","helptext_nl":"Standaard deel je een kamer met andere deelnemers (comfortabele eenpersoonsbedden). Bij inchecken kan je aangeven om bij bekenden/vrienden op de kamer te willen. Wil je meer privacy of een (niet-fietsende) supporter meenemen? Kies een upgrade hieronder.","placeholder":"-- Kies een optie --","default_value":["Samen met andere deelnemer(s) â standaard inbegrepen"],"label_on_cart":"Room extras","option_values":[{"id":2,"max":"","min":"","name":"","unit":"","label":"","value":"Comfortabel eenpersoonsbed op gedeelde kamer â standaard inbegrepen","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Comfortable single bed on shared room â included","value_nl":"Comfortabel eenpersoonsbed op gedeelde kamer â standaard inbegrepen","addon_type":"manual_product","asset_name":"","color_type":"one-color","placeholder":""},{"id":0,"max":"","min":"","name":1782722528659,"unit":"","label":"","value":"Eigen tweepersoonskamer (slaap alleen) â 80 euro","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Private double room (sleep alone) â 80 euros","value_nl":"Eigen tweepersoonskamer (slaap alleen) â 80 euro","addon_type":"manual_product","asset_name":"","color_type":"one-color","variant_id":58176856949110,"placeholder":"","variant_price":"80.00","product_handle":"cafe-coureur-houffalize-upgrade"},{"id":1,"max":"","min":"","name":1782723225078,"unit":"","label":"","value":"Samen met supporter (incl. 3-Daags CC Arrangement) â 205 euro","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Together with a supporter (incl. 3-Day CC Package) â 205 euros","value_nl":"Samen met supporter (incl. 3-Daags CC Arrangement) â 205 euro","addon_type":"manual_product","asset_name":"","color_type":"one-color","variant_id":58176857014646,"placeholder":"","variant_price":"205.00","product_handle":"cafe-coureur-houffalize-upgrade"}],"advanced_addon":"default","placeholder_en":"-- Please select --","placeholder_nl":"-- Kies een optie --","conditionalField":true,"helptext_position":"below_label"},{"id":"select-4","clo":{"match":"all","whens":[{"value":"1p","where":"CONTAINS","select":"shopify_variant","value_nl":"1p"},{"value":"4-","where":"CONTAINS","select":"shopify_variant","value_en":"4-","value_nl":"4-"},{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"type":"select","label":"Kamer opties","prefix":"icon","helptext":"Standaard deel je een kamer met andere deelnemers (comfortabele eenpersoonsbedden). Bij inchecken kan je aangeven om bij bekenden/vrienden op de kamer te willen. Wil je meer privacy of een (niet-fietsende) supp
18199orter meenemen? Kies een upgrade hieronder.","label_en":"Room options","columnWidth":100,"helptext_en":"By default, you share a room with other participants (comfortable single beds). Upon check-in, you can indicate that you would like to share a room with acquaintances or friends. Do you want more privacy or to bring a (non-cycling) supporter? Choose an upgrade below.","helptext_nl":"Standaard deel je een kamer met andere deelnemers (comfortabele eenpersoonsbedden). Bij inchecken kan je aangeven om bij bekenden/vrienden op de kamer te willen. Wil je meer privacy of een (niet-fietsende) supporter meenemen? Kies een upgrade hieronder.","placeholder":"-- Kies een optie --","default_value":["Samen met andere deelnemer(s) â standaard inbegrepen"],"label_on_cart":"Room options","option_values":[{"id":2,"max":"","min":"","name":"","unit":"","label":"","value":"Comfortabel eenpersoonsbed op gedeelde kamer â standaard inbegrepen","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Comfortable single bed on shared room â included","value_nl":"Comfortabel eenpersoonsbed op gedeelde kamer â standaard inbegrepen","addon_type":"manual_product","asset_name":"","color_type":"one-color","placeholder":""},{"id":0,"max":"","min":"","name":1782722528659,"unit":"","label":"","value":"Eigen tweepersoonskamer (slaap alleen) â 120 euro","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Private double room (sleep alone) â 120 euros","value_nl":"Eigen tweepersoonskamer (slaap alleen) â 120 euro","addon_type":"manual_product","asset_name":"","color_type":"one-color","variant_id":58176856981878,"placeholder":"","variant_price":"120.00","product_handle":"cafe-coureur-houffalize-upgrade"},{"id":1,"max":"","min":"","name":1782723225078,"unit":"","label":"","value":"Samen met supporter (incl. 4-Daags CC Arrangement) â 295 euro","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Together with a supporter (incl. 4-Day CC Package) â 295 euros","value_nl":"Samen met supporter (incl. 4-Daags CC Arrangement) â 295 euro","addon_type":"manual_product","asset_name":"","color_type":"one-color","variant_id":58176857047414,"placeholder":"","variant_price":"295.00","product_handle":"cafe-coureur-houffalize-upgrade"}],"advanced_addon":"default","placeholder_en":"-- Please select --","placeholder_nl":"-- Kies een optie --","conditionalField":true,"helptext_position":"below_label"},{"id":"buttons-1","clo":{"match":"any","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_en":"Ticket","value_nl":"Ticket"},{"value":"Preregister","where":"CONTAINS","select":"shopify_variant","value_nl":"Preregister"}],"display":"show"},"oos":"show","type":"buttons","label":"Wegroute of gravelroute?","style":"vertical","helptext":"Keuze aanpassen is altijd mogelijk. Graag doorgeven aan [email protected]","label_en":"Road route or gravel route?","label_nl":"Wegroute of gravelroute?","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"It is always possible to switch. Please inform [email protected]","helptext_nl":"Keuze aanpassen is altijd mogelijk. Graag doorgeven aan [email protected]","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","show_arrows":"hide","pp_clipWidth":50,"pp_clipXAxis":50,"pp_clipYAxis":50,"slider_style":"style1","swatch_style":"default","initial_state":"expand","label_on_cart":"Route","option_values":[{"id":1,"max":"","min":"","name":1782745652511,"unit":"","label":"","value":"Weg","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Road","value_nl":"Weg","addon_type":"manual_product","asset_name":"","color_type":"one-color","placeholder":""},{"id":0,"max":"","min":"","name":1782732029371,"unit":"","label":"","value":"Gravel","color1":"#ffffff","color2":"#000000","default":"","helptext":"","value_en":"Gravel ","value_nl":"Gravel","addon_type":"manual_product","asset_name":"","color_type":"one-color","placeholder":""}],"pp_clipHeight":50,"advanced_addon":"default","number_of_rows":"1","show_indicators":"hide","conditionalField":true,"swatches_per_row":"3","helptext_position":"below"},{"id":"text-6","clo":{"match":"all","whens":[{"value":"Ticket","where":"EQUALS","select":"shopify_variant"}],"display":"show"},"type":"text","label":"Welke dag en tijd verwacht je te finishen?","hidden":true,"prefix":"icon","pp_font":"default","label_en":"Which day and time do you expect to finish?","label_nl":"Welke dag en tijd verwacht je te finishen?","pp_color":"#000000","pp_xAxis":50,"pp_yAxis":50,"pp_opacity":100,"columnWidth":100,"placeholder":"Bijvoorbeeld: Zondag om 13:00 uur","pp_fontSize":6,"pp_clipWidth":50,"pp_clipXAxis":50,"pp_clipYAxis":50,"pp_fontStyle":"normal","allowed_value":"default","label_on_cart":"Finishtime","pp_clipHeight":50,"advanced_addon":"default","placeholder_en":"For example: Sunday at 1 PM","placeholder_nl":"Bijvoorbeeld: Zondag om 13:00 uur","pp_effectWidth":"1","pp_shadowXAxis":1,"pp_shadowYAxis":1,"pp_strokeColor":"#EB1256","text_transform":"default","pp_customEffect":"noEffect","conditionalField":true},{"id":"checkbox-1","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"oos":"show","type":"checkbox","label":"Wil je een vrijwilliger aandragen?","style":"vertical","hidden":true,"helptext":"We nemen contact met je op om de details te bespreken. Komt het rond, dan krijgt de vrijwilliger een gratis Café Coureur Arrangement â en jij 50% van je ticketprijs terug.","label_en":"Bring a volunteer?","label_nl":"Wil je een vrijwilliger aandragen?","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"helptext_en":"We'll reach out to discu
18199ss the details. If it works out, your volunteer gets a complimentary Café Coureur Arrangement â and you get 50% of your ticket price back.","helptext_nl":"We nemen contact met je op om de details te bespreken. Komt het rond, dan krijgt de vrijwilliger een gratis Café Coureur Arrangement â en jij 50% van je ticketprijs terug.","pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","pp_clipWidth":50,"pp_clipXAxis":50,"pp_clipYAxis":50,"swatch_style":"default","initial_state":"expand","label_on_cart":"Vrijwilliger","option_values":[{"id":0,"name":1782722528659,"value":"Ja ik ken iemand die eventueel kan helpen","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Yes I know someone who would like to help out","value_nl":"Ja ik ken iemand die eventueel kan helpen","addon_type":"manual_product","asset_name":"","color_type":"one-color"}],"pp_clipHeight":50,"advanced_addon":"default","conditionalField":true,"helptext_position":"below"},{"id":"checkbox-2","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant","value_nl":"Ticket"}],"display":"show"},"oos":"show","type":"checkbox","label":"Akkoord met event regels (onder knop)","style":"vertical","hidden":true,"label_en":"Agree with event rules (below button)","label_nl":"Akkoord met event regels (onder knop)","pp_width":25,"pp_xAxis":50,"pp_yAxis":50,"required":true,"pp_height":25,"pp_imgMode":"cover","pp_opacity":100,"columnWidth":100,"pp_imgShape":{"value":{"src":"https://cdn.shopify.com/s/files/1/0241/9490/8215/files/shape-1.png","name":""},"options":[]},"scroll_type":"default","pp_clipWidth":50,"pp_clipXAxis":50,"pp_clipYAxis":50,"swatch_style":"default","initial_state":"expand","label_on_cart":"Agree event rules","option_values":[{"id":0,"name":1782765156557,"value":"Akkoord","color1":"#ffffff","color2":"#000000","helptext":"","value_en":"Yes I agree","value_nl":"Akkoord","addon_type":"manual_product","asset_name":"","color_type":"one-color"}],"pp_clipHeight":50,"advanced_addon":"default","conditionalField":true},{"id":"paragraph-7","clo":{"match":"all","whens":[{"value":"Ticket","where":"CONTAINS","select":"shopify_variant"}],"display":"show"},"text":"<h4>Nog meer personen boeken?</h4>\n<p><span style=\"color: inherit; font-family: inherit;\">Voeg iedereen afzonderlijk</span><span style=\"color: inherit; font-family: inherit;\"> toe aan startlijst. Staat iedereen op de startlijst, ga dan naar afrekenen.</span></p>","type":"paragraph","hidden":true,"text_en":"<h4>Booking for more people?</h4>\n<p><span style=\"color: inherit; font-family: inherit; font-size: 1em;\">Add everyone to the start list individually. Once everyone is on the start list, proceed to checkout.</span></p>","text_nl":"<h4>Nog meer personen boeken?</h4>\n<p><span style=\"color: inherit; font-family: inherit;\">Voeg iedereen afzonderlijk</span><span style=\"color: inherit; font-family: inherit;\"> toe aan startlijst. Staat iedereen op de startlijst, ga dan naar afrekenen.</span></p>","columnWidth":100,"label_on_cart":"Multiple","conditionalField":true}],"conditionalField":false}],"products":{"rule":{"all":{"enable":false},"manual":{"ids":[15719000113526,15775162171766],"enable":true},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"status":0,"customers":{"rule":{"all":{"enable":true},"manual":{"ids":[],"enable":false},"automate":{"enable":false,"operator":"and","conditions":[{"value":"","where":"EQUALS","select":"TAG"}]}}},"countries":{"type":"include","enable":false,"countries":[]},"settings":[],"published_scope":"web,pos"};window.GPOConfigs.shop = {"url":"khdz0c-aq.myshopify.com","version":2,"currency":"EUR","settings":{"general":{"widget":{"app_position":"before_atc","html_selector":".custom-modal-overlay variant-selects","alignment":"center","show_tooltip":false,"show_value_next_label":false,"fixed_height_and_scrollable":false,"fixed_height":"","swatch_image_format":"jpg","load_options_from_file":false,"load_options_from_s3":false,"index_options_by_product_id":false,"watermark":"\u003cspan style=\"font-size:12px;color:#868686\"\u003ePowered by \u003ca style=\"font-weight:bold;color:#2c6ecb;text-decoration:none;\" href=\"https:\/\/apps.shopify.com\/product-options-pro\" target=\"_blank\"\u003eGlobo Product Options\u003c\/a\u003e\u003c\/span\u003e","enable_remove_watermark":true,"remove_all_watermarks":true}
18199,"product_page":{"redirect_to_cart":true,"scroll_to_invalid":true,"file_preview":"link_or_image"},"cart_page":{"disable_quantity_and_remove":true,"edit_options":false,"preview_mode":"modal"},"custom_fonts":{"fonts":[]},"collection_page":{"show_on_quickview":true},"others_page":{"show_on_homepage":true,"show_on_page":true}},"design":{"theme":{"match_theme_style":false},"color":{"app_background":"#ffffff00","label_text":"#271D62","required_text":"#FFB600","helptext":"#7c7c9f","total_text":"#271D62","total_text_money":"#11EFD6","input_text":"#271D62","input_border":"#271D62","input_background":"#fff","switch_background":"#D0D5FD","switch_active_background":"#11EFD6","range_thumb":"#271D62","range_bg":"#D0D5FD","range_active_bg":"#271D62","select_text":"#271D62","select_border":"#271D62","select_background":"#fff","select_selected":"#D0D5FD","choicelist_text":"#271D62","choicelist_text_hover":"#271D62","choicelist_text_active":"#271D62","choicelist_hover":"#D0D5FD","choicelist_active":"#11EFD6","button_text":"#271D62","button_text_hover":"#271D62","button_text_active":"#fff","button_background":"#fff","button_background_hover":"#D0D5FD","button_background_active":"#271D62","swatch_border":"#271D62","swatch_border_hover":"#271D62","swatch_border_active":"#271D62","tab_title":"#7c7c9f","tab_title_active":"#271D62","tab_title_hover":"#D0D5FD","tab_content":"#271D62","tab_border":"#D0D5FD","group_label":"#271D62","group_icon":"#271D62","group_chevron":"#271D62"},"border":{"input":{"size":2,"radius":30},"dropdown":{"size":2,"radius":30},"swatch":{"size":2,"radius":30}},"typography":{"labeltext":{"customFont":true,"customFontFamily":"ashemore","customFontVariant":"600","fontFamily":"Assistant","fontVariant":"300","fontSize":17},"maintext":{"customFont":true,"customFontFamily":"ashemore","customFontVariant":"400","fontFamily":"Assistant","fontVariant":"300","fontSize":17},"helptext":{"customFont":true,"customFontFamily":"ashemore","customFontVariant":"400","fontFamily":"Assistant","fontVariant":"300","fontSize":17},"totaltext":{"customFont":true,"customFontFamily":"ashemore","customFontVariant":"400","fontFamily":"Assistant","fontVariant":"regular","fontSize":17}},"additional":{"custom_css":null}},"price":{"product_page":{"money_format":"money_format","label_addon":"","show_for_input":true,"show_for_option":true,"show_addon_message":false,"add_addon_to_product_price":false,"use_bundle":false}}},"translations":{"default":{"widget":{"choose_file":"Choose file","or_drop_file_to_upload":"or drop file to upload","file_uploading":"Uploading...","uploaded_msg":"Uploaded file:","uploaded_link":"Link","selection_will_add":"Selections will add {{addon}} to the price","enter_qty":"Enter quantity"},"addtocart":{"items_are_no_longer_available":"Some items are no longer available. Please try again later.","buynow_not_allowed":"This product cannot be purchased using this checkout method. Please add the item to cart, then proceed to checkout from the cart."},"validation":{"required":"This field is required","invalid":"Invalid","invalid_email":"Invalid email","invalid_phone":"Invalid phone number","invalid_number":"Invalid number","min_char":"Please enter more than or equal to {{min_character}} characters","char_limit":"Please enter less than or equal to {{character_limit}} characters","char_counter":"{{character_count}}\/{{character_limit}} characters","min_value":"Please enter a value greater than or equal to {{min_value}}","max_value":"Please enter a value less than or equal to {{max_value}}","min_selection":"Please select at least {{min_selection}} options","max_selection":"Please select at maximum {{max_selection}} options","exactly_selection":"Please select exactly {{exactly_selection}} options","file_not_allowed":"File not allowed"},"cart":{"edit_options":"Edit Options","cancel":"Cancel","save":"Save Changes"}}}}; 18200 window.GPOConfigs.money_format = window.GPOConfigs?.shop?.settings?.price?.product_page?.money_format === "money_with_currency_format" ? "${{amount}} USD" : "${{amount}}"; 18201 window.GPOConfigs.product = false; 18202 window.GPOConfigs.product.collections = false;
18203 window.GPOConfigs.customer = false; 18204 window.GPOConfigs.cart = {"note":null,"attributes":{},"original_total_price":0,"total_price":0,"total_discount":0,"total_weight":0.0,"item_count":0,"items":[],"requires_shipping":false,"currency":"USD","items_subtotal_price":0,"cart_level_discount_applications":[],"checkout_charge_amount":0}; 18205 window.GPOConfigs.cart_type = "page"; 18206 if (window.AVADA_SPEED_WHITELIST) { 18207 const gpo_w = /globo-product-option/i; 18208 window.AVADA_SPEED_WHITELIST = [].concat(window.AVADA_SPEED_WHITELIST, gpo_w); 18209 } 18210</script>
18210 18211 18212<style>.gpo-hidden,[class*=gpo-original],[data-gpo-is-enabled=true] [data-shopify=payment-button],[data-gpo-is-enabled=true][data-gpo-cart-hide-additional-payment-button=true] [data-shopify=dynamic-checkout-cart],a[class*=gpo-original],button[class*=gpo-original],input#AddToCart[class*=gpo-original],input#addToCart[class*=gpo-original],input[class*=gpo-original]{display:none!important}.gpo-hidden{opacity:0!important;visibility:hidden!important}#mini-cart form.cart a.gpo-clone-checkout-button,.cart-flyout a.gpo-clone-checkout-button{display:block!important}</style> 18213</div>
18213<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
18213 18214</body> 18215</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.